diff --git a/.gitignore b/.gitignore
index 5115c12d8..98ca98966 100644
--- a/.gitignore
+++ b/.gitignore
@@ -189,3 +189,4 @@ FakesAssemblies/
# Visual Studio 6 workspace options file
*.opt
+*.opendb
diff --git a/Artemis/Artemis.sln b/Artemis/Artemis.sln
index cf6e97100..201149a73 100644
--- a/Artemis/Artemis.sln
+++ b/Artemis/Artemis.sln
@@ -5,6 +5,8 @@ VisualStudioVersion = 14.0.24720.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Artemis", "Artemis\Artemis.csproj", "{ED9997A2-E54C-4E9F-9350-62BE672C3ABE}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LogiLed2Artemis", "LogiLed2Artemis\LogiLed2Artemis.vcxproj", "{D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
CD_ROM|Any CPU = CD_ROM|Any CPU
@@ -54,6 +56,34 @@ Global
{ED9997A2-E54C-4E9F-9350-62BE672C3ABE}.SingleImage|x64.Build.0 = Release|x64
{ED9997A2-E54C-4E9F-9350-62BE672C3ABE}.SingleImage|x86.ActiveCfg = Release|x86
{ED9997A2-E54C-4E9F-9350-62BE672C3ABE}.SingleImage|x86.Build.0 = Release|x86
+ {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.CD_ROM|Any CPU.ActiveCfg = Release|x64
+ {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.CD_ROM|Any CPU.Build.0 = Release|x64
+ {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.CD_ROM|x64.ActiveCfg = Release|x64
+ {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.CD_ROM|x64.Build.0 = Release|x64
+ {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.CD_ROM|x86.ActiveCfg = Release|Win32
+ {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.CD_ROM|x86.Build.0 = Release|Win32
+ {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.Debug|x64.ActiveCfg = Debug|x64
+ {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.Debug|x64.Build.0 = Debug|x64
+ {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.Debug|x86.ActiveCfg = Debug|Win32
+ {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.Debug|x86.Build.0 = Debug|Win32
+ {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.DVD-5|Any CPU.ActiveCfg = Release|x64
+ {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.DVD-5|Any CPU.Build.0 = Release|x64
+ {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.DVD-5|x64.ActiveCfg = Debug|x64
+ {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.DVD-5|x64.Build.0 = Debug|x64
+ {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.DVD-5|x86.ActiveCfg = Debug|Win32
+ {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.DVD-5|x86.Build.0 = Debug|Win32
+ {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.Release|Any CPU.ActiveCfg = Release|Win32
+ {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.Release|x64.ActiveCfg = Release|x64
+ {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.Release|x64.Build.0 = Release|x64
+ {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.Release|x86.ActiveCfg = Release|Win32
+ {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.Release|x86.Build.0 = Release|Win32
+ {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.SingleImage|Any CPU.ActiveCfg = Release|x64
+ {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.SingleImage|Any CPU.Build.0 = Release|x64
+ {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.SingleImage|x64.ActiveCfg = Release|x64
+ {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.SingleImage|x64.Build.0 = Release|x64
+ {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.SingleImage|x86.ActiveCfg = Release|Win32
+ {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.SingleImage|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/Artemis/Artemis/Artemis.csproj b/Artemis/Artemis/Artemis.csproj
index 1ea60910f..1f96f9a96 100644
--- a/Artemis/Artemis/Artemis.csproj
+++ b/Artemis/Artemis/Artemis.csproj
@@ -190,6 +190,10 @@
+
+ ..\packages\System.Linq.Dynamic.1.0.6\lib\net40\System.Linq.Dynamic.dll
+ True
+
@@ -249,6 +253,7 @@
Code
+
@@ -269,6 +274,12 @@
+
+
+
+
+
+
@@ -313,6 +324,7 @@
True
True
+
True
@@ -371,6 +383,7 @@
+
@@ -397,8 +410,11 @@
+
+
+
@@ -435,12 +451,21 @@
Witcher3View.xaml
+
+ LayerEditorView.xaml
+
+
+ LayerConditionView.xaml
+
OverlaysView.xaml
VolumeDisplayView.xaml
+
+ ProfileEditorView.xaml
+
ShellView.xaml
@@ -504,6 +529,7 @@
+
@@ -532,6 +558,10 @@
MSBuild:Compile
Designer
+
+ Designer
+ MSBuild:Compile
+
Designer
MSBuild:Compile
@@ -576,6 +606,14 @@
Designer
MSBuild:Compile
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
Designer
MSBuild:Compile
@@ -584,6 +622,10 @@
Designer
MSBuild:Compile
+
+ Designer
+ MSBuild:Compile
+
Designer
MSBuild:Compile
diff --git a/Artemis/Artemis/ArtemisBootstrapper.cs b/Artemis/Artemis/ArtemisBootstrapper.cs
index e0f82e4b6..dc80755b4 100644
--- a/Artemis/Artemis/ArtemisBootstrapper.cs
+++ b/Artemis/Artemis/ArtemisBootstrapper.cs
@@ -2,8 +2,6 @@
using System.Linq;
using System.Windows;
using System.Windows.Forms;
-using Artemis.Utilities;
-using Artemis.Utilities.LogitechDll;
using Artemis.ViewModels;
using Autofac;
using Caliburn.Micro;
diff --git a/Artemis/Artemis/DAL/ProfileProvider.cs b/Artemis/Artemis/DAL/ProfileProvider.cs
new file mode 100644
index 000000000..f696beeda
--- /dev/null
+++ b/Artemis/Artemis/DAL/ProfileProvider.cs
@@ -0,0 +1,83 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using Artemis.Models;
+using Artemis.Models.Profiles;
+using Newtonsoft.Json;
+
+namespace Artemis.DAL
+{
+ public static class ProfileProvider
+ {
+ private static readonly string ProfileFolder =
+ Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\Artemis\profiles";
+
+ ///
+ /// Get all profiles
+ ///
+ /// All profiles
+ public static List GetAll()
+ {
+ return ReadProfiles();
+ }
+
+ ///
+ /// Get all profiles matching the provided game
+ ///
+ /// The game to match
+ /// All profiles matching the provided game
+ public static List GetAll(GameModel game)
+ {
+ return GetAll().Where(g => g.GameName.Equals(game.Name)).ToList();
+ }
+
+ ///
+ /// Adds or update the given profile.
+ /// Updates occur when a profile with the same name and game exist.
+ ///
+ /// The profile to add or update
+ public static void AddOrUpdate(ProfileModel prof)
+ {
+ if (!(prof.GameName?.Length > 1) || !(prof.KeyboardName?.Length > 1) || !(prof.Name?.Length > 1))
+ throw new ArgumentException("Profile is invalid. Name, GameName and KeyboardName are required");
+
+ var path = ProfileFolder + $@"\{prof.KeyboardName}\{prof.GameName}";
+ if (!Directory.Exists(path))
+ Directory.CreateDirectory(path);
+
+ var serialized = JsonConvert.SerializeObject(prof, Formatting.Indented);
+ File.WriteAllText(path + $@"\{prof.Name}.json", serialized);
+ }
+
+ private static List ReadProfiles()
+ {
+ CheckProfiles();
+ var profiles = new List();
+
+ // Create the directory structure
+ var profileFiles = Directory.GetFiles(ProfileFolder, "*.json", SearchOption.AllDirectories);
+
+ // Parse the JSON files into objects and add them if they are valid
+ foreach (var file in profileFiles)
+ {
+ var prof = JsonConvert.DeserializeObject(File.ReadAllText(file));
+ if (prof.GameName?.Length > 1 && prof.KeyboardName?.Length > 1 && prof.Name?.Length > 1)
+ profiles.Add(prof);
+ }
+
+ return profiles;
+ }
+
+ private static void CheckProfiles()
+ {
+ // Create the directory structure
+ if (Directory.Exists(ProfileFolder))
+ return;
+
+ Directory.CreateDirectory(ProfileFolder);
+ Debug.WriteLine("Place presets");
+ }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/KeyboardProviders/Logitech/Orion.cs b/Artemis/Artemis/KeyboardProviders/Logitech/Orion.cs
index b4fb74df9..adfd56704 100644
--- a/Artemis/Artemis/KeyboardProviders/Logitech/Orion.cs
+++ b/Artemis/Artemis/KeyboardProviders/Logitech/Orion.cs
@@ -11,12 +11,14 @@ namespace Artemis.KeyboardProviders.Logitech
{
internal class Orion : KeyboardProvider
{
+ private string _versionString;
+
public Orion()
{
Name = "Logitech G910 RGB";
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" +
+ "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;
@@ -40,6 +42,12 @@ namespace Artemis.KeyboardProviders.Logitech
// Turn it into one long number...
var version = int.Parse($"{majorNum}{minorNum}{buildNum}");
+ 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 (detected {majorNum}.{minorNum}.{buildNum}).\n\n" +
+ "If the detected version differs from the version LGS is reporting, reinstall LGS or see the FAQ.\n\n" +
+ "If needed, you can select a different keyboard in Artemis under settings.";
+
return version >= 88115;
}
diff --git a/Artemis/Artemis/KeyboardProviders/Razer/BlackWidow.cs b/Artemis/Artemis/KeyboardProviders/Razer/BlackWidow.cs
index fb9881738..fc3f0d24e 100644
--- a/Artemis/Artemis/KeyboardProviders/Razer/BlackWidow.cs
+++ b/Artemis/Artemis/KeyboardProviders/Razer/BlackWidow.cs
@@ -13,8 +13,8 @@ namespace Artemis.KeyboardProviders.Razer
public BlackWidow()
{
Name = "Razer BlackWidow Chroma";
- CantEnableText = "Couldn't connect to your Razer BlackWidow Chroma.\n " +
- "Please check your cables and try updating Razer Synapse.\n\n " +
+ CantEnableText = "Couldn't connect to your Razer BlackWidow Chroma.\n" +
+ "Please check your cables and try updating Razer Synapse.\n\n" +
"If needed, you can select a different keyboard in Artemis under settings.";
}
diff --git a/Artemis/Artemis/Managers/MainManager.cs b/Artemis/Artemis/Managers/MainManager.cs
index f4f6a4859..0df082f1a 100644
--- a/Artemis/Artemis/Managers/MainManager.cs
+++ b/Artemis/Artemis/Managers/MainManager.cs
@@ -2,7 +2,6 @@
using System.Diagnostics;
using System.Linq;
using System.Threading;
-using System.Windows.Forms;
using Artemis.Events;
using Artemis.Models;
using Artemis.Services;
diff --git a/Artemis/Artemis/Models/Interfaces/GameDataModel.cs b/Artemis/Artemis/Models/Interfaces/GameDataModel.cs
new file mode 100644
index 000000000..3dd99c183
--- /dev/null
+++ b/Artemis/Artemis/Models/Interfaces/GameDataModel.cs
@@ -0,0 +1,6 @@
+namespace Artemis.Models.Interfaces
+{
+ public interface IGameDataModel
+ {
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Models/Profiles/LayerConditionModel.cs b/Artemis/Artemis/Models/Profiles/LayerConditionModel.cs
new file mode 100644
index 000000000..8a48cdbaa
--- /dev/null
+++ b/Artemis/Artemis/Models/Profiles/LayerConditionModel.cs
@@ -0,0 +1,21 @@
+using System.Collections.Generic;
+using System.Linq.Dynamic;
+using Artemis.Models.Interfaces;
+
+namespace Artemis.Models.Profiles
+{
+ public class LayerConditionModel
+ {
+ public string Field { get; set; }
+ public string Value { get; set; }
+ public string Operator { get; set; }
+
+ public bool ConditionMet(IGameDataModel subject)
+ {
+ // Put the subject in a list, allowing Dynamic Linq to be used.
+ var subjectList = new List {(T) subject};
+ var res = subjectList.Where($"{Field} {Operator} {Value}").Any();
+ return res;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Models/Profiles/LayerDynamicPropertiesModel.cs b/Artemis/Artemis/Models/Profiles/LayerDynamicPropertiesModel.cs
new file mode 100644
index 000000000..cb41291b0
--- /dev/null
+++ b/Artemis/Artemis/Models/Profiles/LayerDynamicPropertiesModel.cs
@@ -0,0 +1,86 @@
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq.Dynamic;
+using System.Reflection;
+using Artemis.Models.Interfaces;
+
+namespace Artemis.Models.Profiles
+{
+ public class LayerDynamicPropertiesModel
+ {
+ public string LayerProperty { get; set; }
+ public string GameProperty { get; set; }
+ public string RequiredOperator { get; set; }
+ public string RequiredValue { get; set; }
+ public LayerPopertyType LayerPopertyType { get; set; }
+
+ ///
+ /// Only used when LayerPropertyType is PercentageOf or PercentageOfProperty
+ ///
+ public string PercentageSource { get; set; }
+
+ ///
+ /// Only used when LayerPropertyType is Color
+ ///
+ public List LayerColors { get; set; }
+
+ internal void ApplyProperty(IGameDataModel dataModel, LayerPropertiesModel userProps,
+ LayerPropertiesModel props)
+ {
+ var dataList = new List {(T) dataModel};
+
+ // Attempt to set the property
+ var layerProp = props.GetType().GetProperty(LayerProperty);
+ var layerUserProp = userProps.GetType().GetProperty(LayerProperty);
+
+ if (LayerPopertyType == LayerPopertyType.PercentageOf)
+ SetPercentageOf(props, userProps, dataModel, int.Parse(PercentageSource));
+ if (LayerPopertyType == LayerPopertyType.PercentageOfProperty)
+ SetPercentageOfProperty(props, userProps, dataModel);
+ if (LayerPopertyType == LayerPopertyType.Color)
+ {
+ if (dataList.Where($"{GameProperty} {RequiredOperator} {RequiredValue}").Any())
+ SetColor(layerProp, dataModel);
+ }
+ }
+
+ private void SetPercentageOf(LayerPropertiesModel props, LayerPropertiesModel userProps,
+ IGameDataModel dataModel, int percentageSource)
+ {
+ // Property that will be set
+ var layerProp = props.GetType().GetProperty(LayerProperty);
+ // Property to use as a 100%
+ var userProp = userProps.GetType().GetProperty(LayerProperty);
+ // Value to use as a source
+ var source = dataModel.GetType().GetProperty(GameProperty)?.GetValue(dataModel, null);
+ if (layerProp == null || userProp == null || source == null)
+ return;
+
+ var percentage = double.Parse(source.ToString())/percentageSource;
+ layerProp.SetValue(props, (int) (percentage*(int) userProp.GetValue(userProps, null)));
+ }
+
+ private void SetPercentageOfProperty(LayerPropertiesModel props, LayerPropertiesModel userProps,
+ IGameDataModel dataModel)
+ {
+ var value = dataModel.GetType().GetProperty(PercentageSource)?.GetValue(dataModel, null);
+ if (value != null)
+ SetPercentageOf(props, userProps, dataModel, (int) value);
+ }
+
+ private void SetColor(PropertyInfo layerProp, IGameDataModel dataModel)
+ {
+ if (layerProp == null)
+ return;
+ if (layerProp.PropertyType == typeof (List))
+ layerProp.SetValue(dataModel, LayerColors, null);
+ }
+ }
+
+ public enum LayerPopertyType
+ {
+ PercentageOf,
+ PercentageOfProperty,
+ Color
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Models/Profiles/LayerModel.cs b/Artemis/Artemis/Models/Profiles/LayerModel.cs
new file mode 100644
index 000000000..1f254544b
--- /dev/null
+++ b/Artemis/Artemis/Models/Profiles/LayerModel.cs
@@ -0,0 +1,91 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Windows.Media;
+using Artemis.Models.Interfaces;
+using Artemis.Utilities;
+using Newtonsoft.Json;
+
+namespace Artemis.Models.Profiles
+{
+ public class LayerModel
+ {
+ [JsonIgnore] private readonly LayerDrawer _drawer;
+
+ public LayerModel(string name, LayerType layerType)
+ {
+ Name = name;
+ LayerType = layerType;
+ LayerUserProperties = new LayerPropertiesModel();
+ LayerCalculatedProperties = new LayerPropertiesModel();
+
+ Children = new List();
+ LayerConditions = new List();
+ LayerProperties = new List();
+
+ _drawer = new LayerDrawer(this);
+ }
+
+ public string Name { get; set; }
+ public LayerType LayerType { get; set; }
+ public LayerPropertiesModel LayerUserProperties { get; set; }
+
+ public List Children { get; set; }
+ public List LayerConditions { get; set; }
+ public List LayerProperties { get; set; }
+
+ [JsonIgnore]
+ public LayerPropertiesModel LayerCalculatedProperties { get; }
+
+ [JsonIgnore]
+ public ImageSource LayerImage => _drawer.GetPreviewImage();
+
+ public bool ConditionsMet(IGameDataModel dataModel)
+ {
+ return LayerConditions.All(cm => cm.ConditionMet(dataModel));
+ }
+
+ public void Draw(IGameDataModel dataModel, Graphics g)
+ {
+ if (!ConditionsMet(dataModel))
+ return;
+
+ Update(dataModel);
+ switch (LayerType)
+ {
+ case LayerType.Folder:
+ DrawChildren(dataModel, g);
+ break;
+ case LayerType.Rectangle:
+ _drawer.DrawRectangle(g);
+ break;
+ case LayerType.Ellipse:
+ _drawer.DrawEllipse(g);
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+
+ private void Update(IGameDataModel dataModel)
+ {
+ GeneralHelpers.CopyProperties(LayerCalculatedProperties, LayerUserProperties);
+ foreach (var dynamicProperty in LayerProperties)
+ dynamicProperty.ApplyProperty(dataModel, LayerUserProperties, LayerCalculatedProperties);
+ }
+
+ private void DrawChildren(IGameDataModel dataModel, Graphics g)
+ {
+ foreach (var layerModel in Children)
+ layerModel.Draw(dataModel, g);
+ }
+ }
+
+ public enum LayerType
+ {
+ Folder,
+ Rectangle,
+ Ellipse
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Models/Profiles/LayerPropertiesModel.cs b/Artemis/Artemis/Models/Profiles/LayerPropertiesModel.cs
new file mode 100644
index 000000000..20e02df5f
--- /dev/null
+++ b/Artemis/Artemis/Models/Profiles/LayerPropertiesModel.cs
@@ -0,0 +1,25 @@
+using System.Collections.Generic;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+
+namespace Artemis.Models.Profiles
+{
+ public class LayerPropertiesModel
+ {
+ public int X { get; set; }
+ public int Y { get; set; }
+ public int Width { get; set; }
+ public int Height { get; set; }
+ public int Opacity { get; set; }
+ public bool ContainedBrush { get; set; }
+ public LinearGradientMode GradientMode { get; set; }
+ public bool Rotate { get; set; }
+ public double RotateSpeed { get; set; }
+ public List Colors { get; set; }
+
+ public LayerPropertiesModel()
+ {
+ Colors = new List();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Models/Profiles/ProfileModel.cs b/Artemis/Artemis/Models/Profiles/ProfileModel.cs
new file mode 100644
index 000000000..86d4d409c
--- /dev/null
+++ b/Artemis/Artemis/Models/Profiles/ProfileModel.cs
@@ -0,0 +1,44 @@
+using System.Collections.Generic;
+
+namespace Artemis.Models.Profiles
+{
+ public class ProfileModel
+ {
+ public ProfileModel(string name, string keyboardName, string gameName)
+ {
+ Name = name;
+ KeyboardName = keyboardName;
+ GameName = gameName;
+ }
+
+ public string Name { get; set; }
+ public string KeyboardName { get; set; }
+ public string GameName { get; set; }
+
+ public List Layers { get; set; }
+
+ protected bool Equals(ProfileModel other)
+ {
+ return string.Equals(Name, other.Name) && string.Equals(KeyboardName, other.KeyboardName) && string.Equals(GameName, other.GameName);
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj)) return false;
+ if (ReferenceEquals(this, obj)) return true;
+ if (obj.GetType() != GetType()) return false;
+ return Equals((ProfileModel) obj);
+ }
+
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ var hashCode = Name?.GetHashCode() ?? 0;
+ hashCode = (hashCode*397) ^ (KeyboardName?.GetHashCode() ?? 0);
+ hashCode = (hashCode*397) ^ (GameName?.GetHashCode() ?? 0);
+ return hashCode;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/RocketLeague/RocketLeagueDataModel.cs b/Artemis/Artemis/Modules/Games/RocketLeague/RocketLeagueDataModel.cs
new file mode 100644
index 000000000..d85980ab8
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/RocketLeague/RocketLeagueDataModel.cs
@@ -0,0 +1,12 @@
+using System.Collections.Generic;
+using Artemis.Models.Interfaces;
+using Artemis.Utilities;
+
+namespace Artemis.Modules.Games.RocketLeague
+{
+ internal class RocketLeagueDataModel : IGameDataModel
+ {
+ public int Boost { get; set; }
+ public List Properties { get; }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionDataModel.cs b/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionDataModel.cs
index f2a6390d5..2ffc9d0e8 100644
--- a/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionDataModel.cs
+++ b/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionDataModel.cs
@@ -1,29 +1,31 @@
-using System.Collections.Generic;
+using System;
+using Artemis.Models.Interfaces;
namespace Artemis.Modules.Games.TheDivision
{
- public class TheDivisionDataModel
+ public class TheDivisionDataModel : IGameDataModel
{
- public List DivisionPlayers { get; set; }
- public GrenadeState GrenadeState { get; set; }
- public bool LowAmmo { get; set; }
- public bool LowHp { get; set; }
-
public TheDivisionDataModel()
{
- DivisionPlayers = new List();
+ TestyTest = new TestTest();
}
+
+ public PlayerState PartyMember1 { get; set; }
+ public PlayerState PartyMember2 { get; set; }
+ public PlayerState PartyMember3 { get; set; }
+
+ public bool LowAmmo { get; set; }
+ public bool LowHp { get; set; }
+ public GrenadeState GrenadeState { get; set; }
+
+ public TestTest TestyTest { get; set; }
}
- public class DivisionPlayer
+
+ public class TestTest
{
- public int Id { get; set; }
- public PlayerState PlayerState { get; set; }
-
- public DivisionPlayer(int id)
- {
- Id = id;
- }
+ public string TestS { get; set; }
+ public int TestI { get; set; }
}
public enum GrenadeState
diff --git a/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionModel.cs b/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionModel.cs
index 3c65d41c2..c231113d0 100644
--- a/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionModel.cs
+++ b/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionModel.cs
@@ -1,14 +1,12 @@
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
-using System.Linq;
using Artemis.Managers;
using Artemis.Models;
using Artemis.Modules.Effects.TypeWave;
using Artemis.Utilities;
using Artemis.Utilities.Keyboard;
using Artemis.Utilities.LogitechDll;
-using CUE.NET;
namespace Artemis.Modules.Games.TheDivision
{
@@ -95,8 +93,6 @@ namespace Artemis.Modules.Games.TheDivision
DllManager.PlaceDll();
_dataModel = new TheDivisionDataModel();
- for (var i = 1; i < 5; i++)
- _dataModel.DivisionPlayers.Add(new DivisionPlayer(i));
MainManager.PipeServer.PipeMessage += PipeServerOnPipeMessage;
Initialized = true;
@@ -118,7 +114,7 @@ namespace Artemis.Modules.Games.TheDivision
}
// Parses Division key data to game data
- private void InterpertrateDivisionKey(int[] parts)
+ private void InterpertrateDivisionKey(IReadOnlyList parts)
{
var keyCode = parts[1];
var rPer = parts[2];
@@ -129,16 +125,21 @@ namespace Artemis.Modules.Games.TheDivision
if (keyCode >= 59 && keyCode <= 62)
{
var playerId = keyCode - 58;
- var playerDataModel = _dataModel.DivisionPlayers.FirstOrDefault(p => p.Id == playerId);
- if (playerDataModel == null)
- return;
+ PlayerState newState;
if (gPer > 10)
- playerDataModel.PlayerState = PlayerState.Online;
+ newState = PlayerState.Online;
else if (rPer > 10)
- playerDataModel.PlayerState = PlayerState.Hit;
+ newState = PlayerState.Hit;
else
- playerDataModel.PlayerState = PlayerState.Offline;
+ newState = PlayerState.Offline;
+
+ if (playerId == 1)
+ _dataModel.PartyMember1 = newState;
+ else if (playerId == 2)
+ _dataModel.PartyMember2 = newState;
+ else if (playerId == 3)
+ _dataModel.PartyMember3 = newState;
}
// R blinks white when low on ammo
else if (keyCode == 19)
@@ -180,40 +181,28 @@ namespace Artemis.Modules.Games.TheDivision
_hpRect.Colors = _dataModel.LowHp
? new List {Color.Red, Color.Orange}
- : new List {Color.FromArgb(10, 255, 0), Color.FromArgb(80, 255, 45) };
+ : new List {Color.FromArgb(10, 255, 0), Color.FromArgb(80, 255, 45)};
- if (_dataModel.DivisionPlayers[1].PlayerState == PlayerState.Offline)
+ if (_dataModel.PartyMember1 == PlayerState.Offline)
_p2.Colors = new List {Color.Gray, Color.White};
- else if (_dataModel.DivisionPlayers[1].PlayerState == PlayerState.Online)
- _p2.Colors = new List { Color.FromArgb(10, 255, 0), Color.FromArgb(80, 255, 45) };
+ else if (_dataModel.PartyMember1 == PlayerState.Online)
+ _p2.Colors = new List {Color.FromArgb(10, 255, 0), Color.FromArgb(80, 255, 45)};
else
_p2.Colors = new List {Color.Red, Color.Orange};
- if (_dataModel.DivisionPlayers[2].PlayerState == PlayerState.Offline)
+ if (_dataModel.PartyMember2 == PlayerState.Offline)
_p3.Colors = new List {Color.Gray, Color.White};
- else if (_dataModel.DivisionPlayers[2].PlayerState == PlayerState.Online)
- _p3.Colors = new List { Color.FromArgb(10, 255, 0), Color.FromArgb(80, 255, 45) };
+ else if (_dataModel.PartyMember2 == PlayerState.Online)
+ _p3.Colors = new List {Color.FromArgb(10, 255, 0), Color.FromArgb(80, 255, 45)};
else
_p3.Colors = new List {Color.Red, Color.Orange};
- if (_dataModel.DivisionPlayers[3].PlayerState == PlayerState.Offline)
+ if (_dataModel.PartyMember3 == PlayerState.Offline)
_p4.Colors = new List {Color.Gray, Color.White};
- else if (_dataModel.DivisionPlayers[3].PlayerState == PlayerState.Online)
- _p4.Colors = new List { Color.FromArgb(10, 255, 0), Color.FromArgb(80, 255, 45) };
+ else if (_dataModel.PartyMember3 == PlayerState.Online)
+ _p4.Colors = new List {Color.FromArgb(10, 255, 0), Color.FromArgb(80, 255, 45)};
else
_p4.Colors = new List {Color.Red, Color.Orange};
-
- if (!_dataModel.LowAmmo)
- {
- foreach (var corsairLed in CueSDK.MouseSDK.Leds)
- corsairLed.Color = Color.Green;
- }
- else
- {
- foreach (var corsairLed in CueSDK.MouseSDK.Leds)
- corsairLed.Color = Color.Red;
- }
- CueSDK.MouseSDK.Update();
}
public override Bitmap GenerateBitmap()
diff --git a/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionView.xaml b/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionView.xaml
index 5bd90ab14..48b9924bf 100644
--- a/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionView.xaml
+++ b/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionView.xaml
@@ -7,48 +7,52 @@
xmlns:cal="http://www.caliburnproject.org"
mc:Ignorable="d"
d:DesignHeight="416.495" d:DesignWidth="553.608">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Note: For this game to work with Artemis, please open up your Division settings, navigate to 3rd Party and set LED keyboard support to Yes. (This only works if you have Artemis running before starting the game)
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Note: For this game to work with Artemis, please open up your Division settings, navigate to 3rd Party and set LED keyboard support to Yes. (This only works if you have Artemis running before starting the game)
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionViewModel.cs b/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionViewModel.cs
index e9478d8c6..2f2c5383e 100644
--- a/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionViewModel.cs
+++ b/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionViewModel.cs
@@ -1,4 +1,5 @@
using Artemis.Managers;
+using Artemis.ViewModels;
using Artemis.ViewModels.Abstract;
namespace Artemis.Modules.Games.TheDivision
@@ -15,8 +16,12 @@ namespace Artemis.Modules.Games.TheDivision
// Create effect model and add it to MainManager
GameModel = new TheDivisionModel(mainManager, (TheDivisionSettings) GameSettings);
MainManager.EffectManager.EffectModels.Add(GameModel);
+
+ ProfileEditor = new ProfileEditorViewModel(MainManager, GameModel);
}
+ public ProfileEditorViewModel ProfileEditor { get; set; }
+
public static string Name => "The Division";
}
}
\ No newline at end of file
diff --git a/Artemis/Artemis/Properties/Resources.Designer.cs b/Artemis/Artemis/Properties/Resources.Designer.cs
index 353d73f90..2cca27e55 100644
--- a/Artemis/Artemis/Properties/Resources.Designer.cs
+++ b/Artemis/Artemis/Properties/Resources.Designer.cs
@@ -61,14 +61,14 @@ namespace Artemis.Properties {
}
///
- /// Looks up a localized string similar to <?xml version="1.0" encoding="UTF-16"?>
- ///<!-- Used by Artemis to get the active Sign -->
- ///<UserConfig>
- /// <Group id="Artemis" displayName="Artemis">
- /// <VisibleVars>
- /// <Var id="ActiveSign" displayName="ActiveSign" displayType="SLIDER:0:1:1000000"/>
- /// </VisibleVars>
- /// </Group>
+ /// Looks up a localized string similar to <?xml version="1.0" encoding="UTF-16"?>
+ ///<!-- Used by Artemis to get the active Sign -->
+ ///<UserConfig>
+ /// <Group id="Artemis" displayName="Artemis">
+ /// <VisibleVars>
+ /// <Var id="ActiveSign" displayName="ActiveSign" displayType="SLIDER:0:1:1000000"/>
+ /// </VisibleVars>
+ /// </Group>
///</UserConfig>.
///
internal static string artemisXml {
@@ -88,23 +88,23 @@ namespace Artemis.Properties {
}
///
- /// Looks up a localized string similar to "Artemis"
- ///{
- /// "uri" "http://localhost:{{port}}/csgo_game_event"
- /// "timeout" "5.0"
- /// "buffer" "0.1"
- /// "throttle" "0.1"
- /// "heartbeat" "30.0"
- /// "data"
- /// {
- /// "provider" "1"
- /// "map" "1"
- /// "round" "1"
- /// "player_id" "1"
- /// "player_state" "1"
- /// "player_weapons" "1"
- /// "player_match_stats" "1"
- /// }
+ /// Looks up a localized string similar to "Artemis"
+ ///{
+ /// "uri" "http://localhost:{{port}}/csgo_game_event"
+ /// "timeout" "5.0"
+ /// "buffer" "0.1"
+ /// "throttle" "0.1"
+ /// "heartbeat" "30.0"
+ /// "data"
+ /// {
+ /// "provider" "1"
+ /// "map" "1"
+ /// "round" "1"
+ /// "player_id" "1"
+ /// "player_state" "1"
+ /// "player_weapons" "1"
+ /// "player_match_stats" "1"
+ /// }
///}.
///
internal static string csgoGamestateConfiguration {
@@ -116,7 +116,7 @@ namespace Artemis.Properties {
///
/// Looks up a localized string similar to "Artemis"
///{
- /// "uri" "http://localhost:4000/"
+ /// "uri" "http://localhost:{{port}}/"
/// "timeout" "5.0"
/// "buffer" "0.1"
/// "throttle" "0.1"
@@ -138,6 +138,16 @@ namespace Artemis.Properties {
}
}
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap folder {
+ get {
+ object obj = ResourceManager.GetObject("folder", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
///
/// Looks up a localized resource of type System.Byte[].
///
diff --git a/Artemis/Artemis/Properties/Resources.resx b/Artemis/Artemis/Properties/Resources.resx
index 5e03ad8fc..bf8569e4d 100644
--- a/Artemis/Artemis/Properties/Resources.resx
+++ b/Artemis/Artemis/Properties/Resources.resx
@@ -142,4 +142,7 @@
..\resources\witcher3\playerwitcher.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-16
+
+ ..\Resources\folder.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/LogitechLED.dll b/Artemis/Artemis/Resources/LogitechLED.dll
index 2d722626e..044b0e799 100644
Binary files a/Artemis/Artemis/Resources/LogitechLED.dll and b/Artemis/Artemis/Resources/LogitechLED.dll differ
diff --git a/Artemis/Artemis/Resources/folder.png b/Artemis/Artemis/Resources/folder.png
new file mode 100644
index 000000000..c818db4fa
Binary files /dev/null and b/Artemis/Artemis/Resources/folder.png differ
diff --git a/Artemis/Artemis/Services/MetroDialogService.cs b/Artemis/Artemis/Services/MetroDialogService.cs
index e8ef0b398..b63d5cad9 100644
--- a/Artemis/Artemis/Services/MetroDialogService.cs
+++ b/Artemis/Artemis/Services/MetroDialogService.cs
@@ -1,24 +1,24 @@
-//The MIT License(MIT)
-
-//Copyright(c) 2015 ihtfw
-
-//Permission is hereby granted, free of charge, to any person obtaining a copy
-//of this software and associated documentation files (the "Software"), to deal
-//in the Software without restriction, including without limitation the rights
-//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-//copies of the Software, and to permit persons to whom the Software is
-//furnished to do so, subject to the following conditions:
-
-//The above copyright notice and this permission notice shall be included in all
-//copies or substantial portions of the Software.
-
-//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-//SOFTWARE.
+// The MIT License(MIT)
+
+// Copyright(c) 2015 ihtfw
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
using System.Linq;
using System.Threading.Tasks;
diff --git a/Artemis/Artemis/Styles/Accents/CorsairYellow.xaml b/Artemis/Artemis/Styles/Accents/CorsairYellow.xaml
new file mode 100644
index 000000000..ceb3cd5d1
--- /dev/null
+++ b/Artemis/Artemis/Styles/Accents/CorsairYellow.xaml
@@ -0,0 +1,53 @@
+
+
+ #C0A200
+
+ #FFF0CF1E
+
+ #FFF0CF1E
+
+ #FFF0CF1E
+
+ #FFF0CF1E
+
+ #FFF0CF1E
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ White
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Artemis/Artemis/Utilities/GeneralHelpers.cs b/Artemis/Artemis/Utilities/GeneralHelpers.cs
index b83ed3751..fed6fa746 100644
--- a/Artemis/Artemis/Utilities/GeneralHelpers.cs
+++ b/Artemis/Artemis/Utilities/GeneralHelpers.cs
@@ -1,12 +1,14 @@
using System;
using System.Collections.Generic;
+using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Security.Principal;
-using System.Text;
-using System.Threading.Tasks;
using System.Windows;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using static System.String;
namespace Artemis.Utilities
{
@@ -37,12 +39,74 @@ namespace Artemis.Utilities
Environment.Exit(0);
}
- public static bool IsRunAsAdministrator()
- {
- var wi = WindowsIdentity.GetCurrent();
- var wp = new WindowsPrincipal(wi);
-
- return wp.IsInRole(WindowsBuiltInRole.Administrator);
+ public static bool IsRunAsAdministrator()
+ {
+ var wi = WindowsIdentity.GetCurrent();
+ var wp = new WindowsPrincipal(wi);
+
+ return wp.IsInRole(WindowsBuiltInRole.Administrator);
+ }
+
+ public static void CopyProperties(object dest, object src)
+ {
+ foreach (PropertyDescriptor item in TypeDescriptor.GetProperties(src))
+ {
+ item.SetValue(dest, item.GetValue(src));
+ }
+ }
+
+ public static List GenerateTypeMap(object o) => GenerateTypeMap(o.GetType().GetProperties());
+ public static List GenerateTypeMap() => GenerateTypeMap(typeof (T).GetProperties());
+
+ private static List GenerateTypeMap(IEnumerable getProperties,
+ string path = "")
+ {
+ var list = new List();
+ foreach (var propertyInfo in getProperties)
+ {
+ var friendlyName = Empty;
+ if (propertyInfo.PropertyType.Name == "Int32")
+ friendlyName = "(Number) ";
+ else if (propertyInfo.PropertyType.Name == "String")
+ friendlyName = "(Text) ";
+ if (propertyInfo.PropertyType.BaseType?.Name == "Enum")
+ friendlyName = "(Choice) ";
+
+ var parent = new PropertyCollection
+ {
+ Type = propertyInfo.PropertyType.Name,
+ DisplayType = friendlyName,
+ Display = $"{path.Replace(".", " → ")}{propertyInfo.Name}",
+ Path = $"{path}{propertyInfo.Name}"
+ };
+
+ if (propertyInfo.PropertyType.BaseType?.Name == "Enum")
+ {
+ parent.EnumValues = Enum.GetNames(propertyInfo.PropertyType);
+ parent.Type = "Enum";
+ }
+
+ if (friendlyName != Empty)
+ list.Add(parent);
+
+ list.AddRange(GenerateTypeMap(propertyInfo.PropertyType.GetProperties(), path + $"{propertyInfo.Name}."));
+ }
+ return list;
+ }
+
+ public struct PropertyCollection
+ {
+ public string Display { get; set; }
+ public string Path { get; set; }
+ public string Type { get; set; }
+
+ ///
+ /// Only used if Type is an enumerable
+ ///
+ public string[] EnumValues { get; set; }
+
+ public List Children { get; set; }
+ public string DisplayType { get; set; }
}
}
-}
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Utilities/LayerDrawer.cs b/Artemis/Artemis/Utilities/LayerDrawer.cs
new file mode 100644
index 000000000..e37ec462f
--- /dev/null
+++ b/Artemis/Artemis/Utilities/LayerDrawer.cs
@@ -0,0 +1,173 @@
+using System.Collections.Generic;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Drawing.Imaging;
+using System.IO;
+using System.Linq;
+using System.Windows.Media.Imaging;
+using Artemis.Models.Profiles;
+using Artemis.Properties;
+
+namespace Artemis.Utilities
+{
+ internal class LayerDrawer
+ {
+ private readonly LayerModel _layerModel;
+ private Rectangle _rectangle;
+ private double _rotationProgress;
+ private Rectangle _userRectangle;
+
+ public LayerDrawer(LayerModel layerModel)
+ {
+ _layerModel = layerModel;
+ _rotationProgress = 0;
+ }
+
+ public void Draw(Graphics graphics)
+ {
+ _rectangle = new Rectangle(
+ _layerModel.LayerCalculatedProperties.X,
+ _layerModel.LayerCalculatedProperties.Y,
+ _layerModel.LayerCalculatedProperties.Width,
+ _layerModel.LayerCalculatedProperties.Height);
+ _userRectangle = new Rectangle(
+ _layerModel.LayerUserProperties.X,
+ _layerModel.LayerUserProperties.Y,
+ _layerModel.LayerUserProperties.Width,
+ _layerModel.LayerUserProperties.Height);
+
+ if (_layerModel.LayerType == LayerType.Ellipse)
+ DrawEllipse(graphics);
+ else if (_layerModel.LayerType == LayerType.Ellipse)
+ DrawRectangle(graphics);
+
+ // Update the rotation progress
+ _rotationProgress = _rotationProgress + _layerModel.LayerCalculatedProperties.RotateSpeed;
+
+ if (_layerModel.LayerCalculatedProperties.ContainedBrush && _rotationProgress > _rectangle.Width)
+ _rotationProgress = _layerModel.LayerCalculatedProperties.RotateSpeed;
+ else if (!_layerModel.LayerCalculatedProperties.ContainedBrush && _rotationProgress > _userRectangle.Width)
+ _rotationProgress = _layerModel.LayerCalculatedProperties.RotateSpeed;
+ }
+
+ public BitmapImage GetPreviewImage()
+ {
+ _rectangle = new Rectangle(0, 0, 18, 18);
+ _userRectangle = new Rectangle(0, 0, 18, 18);
+ _layerModel.LayerCalculatedProperties.Opacity = 255;
+ var brush = CreateGradientBrush(_layerModel.LayerUserProperties.Colors);
+ var bitmap = new Bitmap(18, 18);
+
+ using (var g = Graphics.FromImage(bitmap))
+ {
+ g.SmoothingMode = SmoothingMode.AntiAlias;
+ if (_layerModel.LayerType == LayerType.Ellipse)
+ {
+ g.FillEllipse(brush, _rectangle);
+ g.DrawEllipse(new Pen(Color.Black, 1), 0, 0, 17, 17);
+ }
+ else if (_layerModel.LayerType == LayerType.Rectangle)
+ {
+ g.FillRectangle(brush, _rectangle);
+ g.DrawRectangle(new Pen(Color.Black, 1), 0, 0, 17, 17);
+ }
+ else
+ bitmap = Resources.folder;
+ }
+
+ using (var memory = new MemoryStream())
+ {
+ bitmap.Save(memory, ImageFormat.Png);
+ memory.Position = 0;
+
+ var bitmapImage = new BitmapImage();
+ bitmapImage.BeginInit();
+ bitmapImage.StreamSource = memory;
+ bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
+ bitmapImage.EndInit();
+
+ return bitmapImage;
+ }
+ }
+
+ public void DrawRectangle(Graphics graphics)
+ {
+ }
+
+ public void DrawEllipse(Graphics graphics)
+ {
+ }
+
+ private LinearGradientBrush CreateGradientBrush(List colors)
+ {
+ ColorBlend colorBlend;
+ var props = _layerModel.LayerCalculatedProperties;
+ // Create a ColorBlend
+ if (colors.Count == 0)
+ {
+ colorBlend = new ColorBlend
+ {
+ Colors = new[] {Color.Transparent, Color.Transparent},
+ Positions = new[] {0F, 1F}
+ };
+ }
+ else if (colors.Count == 1)
+ {
+ colorBlend = new ColorBlend
+ {
+ Colors = new[] {colors[0], colors[0]},
+ Positions = new[] {0F, 1F}
+ };
+ }
+ else
+ {
+ colorBlend = props.Rotate
+ ? new ColorBlend {Colors = CreateTilebleColors(colors).ToArray()}
+ : new ColorBlend {Colors = colors.ToArray()};
+ }
+
+ // If needed, apply opacity to the colors in the blend
+ if (props.Opacity < 255)
+ for (var i = 0; i < colorBlend.Colors.Length; i++)
+ colorBlend.Colors[i] = Color.FromArgb(props.Opacity, colorBlend.Colors[i]);
+
+ // Devide the colors over the colorblend
+ var devider = (float) colorBlend.Colors.Length - 1;
+ var positions = new List();
+ for (var i = 0; i < colorBlend.Colors.Length; i++)
+ positions.Add(i/devider);
+
+ // Apply the devided positions
+ colorBlend.Positions = positions.ToArray();
+
+ RectangleF rect;
+ if (props.Rotate)
+ rect = _layerModel.LayerCalculatedProperties.ContainedBrush
+ ? new Rectangle((int) _rotationProgress + _rectangle.X, _rectangle.Y, _rectangle.Width*2,
+ _rectangle.Height*2)
+ : new Rectangle((int) _rotationProgress + _userRectangle.X, _userRectangle.Y, _userRectangle.Width*2,
+ _userRectangle.Height*2);
+ else
+ rect = _layerModel.LayerCalculatedProperties.ContainedBrush
+ ? new Rectangle(_rectangle.X, _rectangle.Y, _rectangle.Width, _rectangle.Height)
+ : new Rectangle(_userRectangle.X, _userRectangle.Y, _userRectangle.Width, _userRectangle.Height);
+
+ return new LinearGradientBrush(rect, Color.Transparent, Color.Transparent,
+ _layerModel.LayerCalculatedProperties.GradientMode)
+ {
+ InterpolationColors = colorBlend
+ };
+ }
+
+ private List CreateTilebleColors(List sourceColors)
+ {
+ // Create a list using the original colors
+ var tilebleColors = new List(sourceColors);
+ // Add the original colors again
+ tilebleColors.AddRange(sourceColors);
+ // Add the first color, smoothing the transition
+ tilebleColors.Add(sourceColors.FirstOrDefault());
+ return tilebleColors;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/ViewModels/LayerEditor/LayerConditionViewModel.cs b/Artemis/Artemis/ViewModels/LayerEditor/LayerConditionViewModel.cs
new file mode 100644
index 000000000..6d7288c7b
--- /dev/null
+++ b/Artemis/Artemis/ViewModels/LayerEditor/LayerConditionViewModel.cs
@@ -0,0 +1,100 @@
+using System.Linq;
+using Artemis.Models.Profiles;
+using Artemis.Utilities;
+using Caliburn.Micro;
+
+namespace Artemis.ViewModels.LayerEditor
+{
+ public class LayerConditionViewModel : Screen
+ {
+ private readonly LayerEditorViewModel _conditionModel;
+ private GeneralHelpers.PropertyCollection _selectedDataModelProp;
+ private string _selectedOperator;
+ private bool _userValueIsVisible;
+
+ public LayerConditionViewModel(LayerEditorViewModel conditionModel, LayerConditionModel layerConditionModel,
+ BindableCollection dataModelProps)
+ {
+ _conditionModel = conditionModel;
+
+ LayerConditionModel = layerConditionModel;
+ DataModelProps = dataModelProps;
+ Operators = new BindableCollection();
+ }
+
+ public LayerConditionModel LayerConditionModel { get; set; }
+ public BindableCollection DataModelProps { get; set; }
+ public BindableCollection Operators { get; set; }
+
+ public GeneralHelpers.PropertyCollection SelectedDataModelProp
+ {
+ get { return _selectedDataModelProp; }
+ set
+ {
+ if (value.Equals(_selectedDataModelProp)) return;
+ _selectedDataModelProp = value;
+ OnSelectedItemChangedAction(_selectedDataModelProp);
+ NotifyOfPropertyChange(() => SelectedDataModelProp);
+ }
+ }
+
+ public string SelectedOperator
+ {
+ get { return _selectedOperator; }
+ set
+ {
+ if (value == _selectedOperator) return;
+ _selectedOperator = value;
+ NotifyOfPropertyChange(() => SelectedOperator);
+ }
+ }
+
+ public bool UserValueIsVisible
+ {
+ get { return _userValueIsVisible; }
+ set
+ {
+ if (value == _userValueIsVisible) return;
+ _userValueIsVisible = value;
+ NotifyOfPropertyChange(() => UserValueIsVisible);
+ }
+ }
+
+ public void OnSelectedItemChangedAction(GeneralHelpers.PropertyCollection prop)
+ {
+ Operators.Clear();
+ if (prop.EnumValues != null)
+ {
+ Operators.AddRange(prop.EnumValues);
+ UserValueIsVisible = false;
+ }
+ else
+ switch (prop.Type)
+ {
+ case "Int32":
+ Operators.AddRange(new[]
+ {
+ "Lower than", "Lower or equal to", "Higher than", "Higher or equal to", "Equal to",
+ "Not equal to"
+ });
+ UserValueIsVisible = true;
+ break;
+ case "Boolean":
+ Operators.AddRange(new[] {"False", "True"});
+ UserValueIsVisible = false;
+ break;
+ default:
+ Operators.AddRange(new[] {"Equal to", "Not equal to"});
+ UserValueIsVisible = true;
+ break;
+ }
+
+ SelectedOperator = Operators.First();
+ }
+
+ public void Delete()
+ {
+ _conditionModel.DeleteCondition(this, LayerConditionModel);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/ViewModels/LayerEditorViewModel.cs b/Artemis/Artemis/ViewModels/LayerEditorViewModel.cs
new file mode 100644
index 000000000..6532fa054
--- /dev/null
+++ b/Artemis/Artemis/ViewModels/LayerEditorViewModel.cs
@@ -0,0 +1,62 @@
+using System.Linq;
+using Artemis.Models.Profiles;
+using Artemis.Utilities;
+using Artemis.ViewModels.LayerEditor;
+using Caliburn.Micro;
+
+namespace Artemis.ViewModels
+{
+ public class LayerEditorViewModel : Screen
+ {
+ private LayerModel _layer;
+
+ public LayerEditorViewModel(LayerModel layer)
+ {
+ Layer = layer;
+ DataModelProps = new BindableCollection();
+ DataModelProps.AddRange(GeneralHelpers.GenerateTypeMap());
+
+ LayerConditionVms =
+ new BindableCollection>(
+ layer.LayerConditions.Select(c => new LayerConditionViewModel(this, c, DataModelProps)));
+
+ ProposedProperties = new LayerPropertiesModel();
+ GeneralHelpers.CopyProperties(ProposedProperties, Layer.LayerUserProperties);
+ }
+
+ public BindableCollection> LayerConditionVms { get; set; }
+
+ public LayerModel Layer
+ {
+ get { return _layer; }
+ set
+ {
+ if (Equals(value, _layer)) return;
+ _layer = value;
+ NotifyOfPropertyChange(() => Layer);
+ }
+ }
+
+ public BindableCollection DataModelProps { get; set; }
+
+ public LayerPropertiesModel ProposedProperties { get; set; }
+
+ public void AddCondition()
+ {
+ var condition = new LayerConditionModel();
+ Layer.LayerConditions.Add(condition);
+ LayerConditionVms.Add(new LayerConditionViewModel(this, condition, DataModelProps));
+ }
+
+ public void Apply()
+ {
+ GeneralHelpers.CopyProperties(Layer.LayerUserProperties, ProposedProperties);
+ }
+
+ public void DeleteCondition(LayerConditionViewModel layerConditionViewModel, LayerConditionModel layerConditionModel)
+ {
+ LayerConditionVms.Remove(layerConditionViewModel);
+ Layer.LayerConditions.Remove(layerConditionModel);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs b/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs
new file mode 100644
index 000000000..bd8b07218
--- /dev/null
+++ b/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs
@@ -0,0 +1,102 @@
+using System.Dynamic;
+using System.Linq;
+using System.Windows.Media;
+using Artemis.DAL;
+using Artemis.Managers;
+using Artemis.Models;
+using Artemis.Models.Profiles;
+using Caliburn.Micro;
+
+namespace Artemis.ViewModels
+{
+ public class ProfileEditorViewModel : Screen
+ {
+ private readonly GameModel _gameModel;
+ private readonly MainManager _mainManager;
+ private BindableCollection _profileModels;
+ private ProfileModel _selectedProfileModel;
+ private LayerEditorViewModel _editorVm;
+
+ public ProfileEditorViewModel(MainManager mainManager, GameModel gameModel)
+ {
+ _mainManager = mainManager;
+ _gameModel = gameModel;
+
+ ProfileModels = new BindableCollection();
+ LoadProfiles();
+ }
+
+ public BindableCollection ProfileModels
+ {
+ get { return _profileModels; }
+ set
+ {
+ if (Equals(value, _profileModels)) return;
+ _profileModels = value;
+ NotifyOfPropertyChange(() => ProfileModels);
+ }
+ }
+
+ public ProfileModel SelectedProfileModel
+ {
+ get { return _selectedProfileModel; }
+ set
+ {
+ if (Equals(value, _selectedProfileModel)) return;
+ _selectedProfileModel = value;
+ NotifyOfPropertyChange();
+ }
+ }
+
+ private void LoadProfiles()
+ {
+ ProfileModels.Clear();
+ ProfileModels.AddRange(ProfileProvider.GetAll(_gameModel));
+ SelectedProfileModel = ProfileModels.FirstOrDefault();
+ }
+
+ public async void AddProfile()
+ {
+ var name =
+ await
+ _mainManager.DialogService.ShowInputDialog("Add new profile",
+ "Please provide a profile name unique to this game and keyboard.");
+ if (name.Length < 1)
+ {
+ _mainManager.DialogService.ShowMessageBox("Invalid profile name", "Please provide a valid profile name");
+ return;
+ }
+
+ var profile = new ProfileModel(name, _mainManager.KeyboardManager.ActiveKeyboard.Name, _gameModel.Name);
+ if (ProfileProvider.GetAll().Contains(profile))
+ {
+ var overwrite =
+ await
+ _mainManager.DialogService.ShowQuestionMessageBox("Overwrite existing profile",
+ "A profile with this name already exists for this game. Would you like to overwrite it?");
+ if (!overwrite.Value)
+ return;
+ }
+
+ ProfileProvider.AddOrUpdate(profile);
+
+ LoadProfiles();
+ SelectedProfileModel = profile;
+ }
+
+ public void LayerEditor(LayerModel layer)
+ {
+ IWindowManager manager = new WindowManager();
+ _editorVm = new LayerEditorViewModel(layer);
+ dynamic settings = new ExpandoObject();
+
+ settings.Title = "Artemis | Edit " + layer.Name;
+ manager.ShowDialog(_editorVm, null, settings);
+ }
+
+ private ImageSource GenerateKeyboardImage()
+ {
+ return null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/ViewModels/SystemTrayViewModel.cs b/Artemis/Artemis/ViewModels/SystemTrayViewModel.cs
index 1b9bc164d..bda3ecf4f 100644
--- a/Artemis/Artemis/ViewModels/SystemTrayViewModel.cs
+++ b/Artemis/Artemis/ViewModels/SystemTrayViewModel.cs
@@ -1,54 +1,53 @@
-using System;
-using System.Windows;
-using Artemis.Events;
-using Artemis.Properties;
-using Artemis.Settings;
-using Artemis.Utilities;
-using Caliburn.Micro;
-
-namespace Artemis.ViewModels
-{
- public class SystemTrayViewModel : Screen, IHandle
- {
- private readonly ShellViewModel _shellViewModel;
-
- private readonly IWindowManager _windowManager;
- private string _activeIcon;
- private bool _checkedForUpdate;
- private bool _enabled;
- private string _toggleText;
-
- public SystemTrayViewModel(IWindowManager windowManager, ShellViewModel shellViewModel)
- {
- _windowManager = windowManager;
- _shellViewModel = shellViewModel;
- _shellViewModel.MainManager.Events.Subscribe(this);
- _shellViewModel.MainManager.EnableProgram();
- _checkedForUpdate = false;
- //ActiveIcon = "../logo.ico";
-
- if (General.Default.ShowOnStartup)
- ShowWindow();
- }
-
- public bool CanShowWindow => !_shellViewModel.IsActive;
-
- public bool CanHideWindow => _shellViewModel.IsActive;
-
- public bool Enabled
- {
- get { return _enabled; }
- set
- {
- if (value == _enabled) return;
- _enabled = value;
-
- ToggleText = _enabled ? "Disable Artemis" : "Enable Artemis";
- ActiveIcon = _enabled ? "../Resources/logo.ico" : "../Resources/logo-disabled.ico";
- NotifyOfPropertyChange(() => Enabled);
- }
- }
-
+using System;
+using System.Windows;
+using Artemis.Events;
+using Artemis.Properties;
+using Artemis.Settings;
+using Artemis.Utilities;
+using Caliburn.Micro;
+
+namespace Artemis.ViewModels
+{
+ public class SystemTrayViewModel : Screen, IHandle
+ {
+ private readonly ShellViewModel _shellViewModel;
+
+ private readonly IWindowManager _windowManager;
+ private string _activeIcon;
+ private bool _checkedForUpdate;
+ private bool _enabled;
+ private string _toggleText;
+
+ public SystemTrayViewModel(IWindowManager windowManager, ShellViewModel shellViewModel)
+ {
+ _windowManager = windowManager;
+ _shellViewModel = shellViewModel;
+ _shellViewModel.MainManager.Events.Subscribe(this);
+ _shellViewModel.MainManager.EnableProgram();
+ _checkedForUpdate = false;
+
+ if (General.Default.ShowOnStartup)
+ ShowWindow();
+ }
+
+ public bool CanShowWindow => !_shellViewModel.IsActive;
+
+ public bool CanHideWindow => _shellViewModel.IsActive;
+
+ public bool Enabled
+ {
+ get { return _enabled; }
+ set
+ {
+ if (value == _enabled) return;
+ _enabled = value;
+
+ ToggleText = _enabled ? "Disable Artemis" : "Enable Artemis";
+ ActiveIcon = _enabled ? "../Resources/logo.ico" : "../Resources/logo-disabled.ico";
+ NotifyOfPropertyChange(() => Enabled);
+ }
+ }
+
public string ActiveIcon
{
get { return _activeIcon; }
@@ -57,77 +56,77 @@ namespace Artemis.ViewModels
_activeIcon = value;
NotifyOfPropertyChange();
}
- }
-
- public string ToggleText
- {
- get { return _toggleText; }
- set
- {
- if (value == _toggleText) return;
- _toggleText = value;
- NotifyOfPropertyChange(() => ToggleText);
- }
- }
-
- public void Handle(ToggleEnabled message)
- {
- Enabled = message.Enabled;
- }
-
- public void ToggleEnabled()
- {
- if (Enabled)
- _shellViewModel.MainManager.DisableProgram();
- else
- _shellViewModel.MainManager.EnableProgram();
- }
-
- protected override void OnActivate()
- {
- base.OnActivate();
-
- NotifyOfPropertyChange(() => CanShowWindow);
- NotifyOfPropertyChange(() => CanHideWindow);
- }
-
- public void ShowWindow()
- {
- if (!CanShowWindow)
- return;
-
- // manually show the next window view-model
- _windowManager.ShowWindow(_shellViewModel);
-
- NotifyOfPropertyChange(() => CanShowWindow);
- NotifyOfPropertyChange(() => CanHideWindow);
-
- if (_checkedForUpdate)
- return;
-
- _checkedForUpdate = true;
- Updater.CheckForUpdate(_shellViewModel.MainManager.DialogService);
- }
-
-
- public void HideWindow()
- {
- if (!CanHideWindow)
- return;
-
- _shellViewModel.TryClose();
-
- NotifyOfPropertyChange(() => CanShowWindow);
- NotifyOfPropertyChange(() => CanHideWindow);
- }
-
- public void ExitApplication()
- {
- _shellViewModel.MainManager.Shutdown();
- Application.Current.Shutdown();
-
- // Sometimes you need to be rough.
- Environment.Exit(0);
- }
- }
+ }
+
+ public string ToggleText
+ {
+ get { return _toggleText; }
+ set
+ {
+ if (value == _toggleText) return;
+ _toggleText = value;
+ NotifyOfPropertyChange(() => ToggleText);
+ }
+ }
+
+ public void Handle(ToggleEnabled message)
+ {
+ Enabled = message.Enabled;
+ }
+
+ public void ToggleEnabled()
+ {
+ if (Enabled)
+ _shellViewModel.MainManager.DisableProgram();
+ else
+ _shellViewModel.MainManager.EnableProgram();
+ }
+
+ protected override void OnActivate()
+ {
+ base.OnActivate();
+
+ NotifyOfPropertyChange(() => CanShowWindow);
+ NotifyOfPropertyChange(() => CanHideWindow);
+ }
+
+ public void ShowWindow()
+ {
+ if (!CanShowWindow)
+ return;
+
+ // manually show the next window view-model
+ _windowManager.ShowWindow(_shellViewModel);
+
+ NotifyOfPropertyChange(() => CanShowWindow);
+ NotifyOfPropertyChange(() => CanHideWindow);
+
+ if (_checkedForUpdate)
+ return;
+
+ _checkedForUpdate = true;
+ Updater.CheckForUpdate(_shellViewModel.MainManager.DialogService);
+ }
+
+
+ public void HideWindow()
+ {
+ if (!CanHideWindow)
+ return;
+
+ _shellViewModel.TryClose();
+
+ NotifyOfPropertyChange(() => CanShowWindow);
+ NotifyOfPropertyChange(() => CanHideWindow);
+ }
+
+ public void ExitApplication()
+ {
+ _shellViewModel.MainManager.Shutdown();
+ Application.Current.Shutdown();
+
+ // Sometimes you need to be rough.
+ Environment.Exit(0);
+ }
+ }
}
\ No newline at end of file
diff --git a/Artemis/Artemis/Views/LayerEditor/LayerConditionView.xaml b/Artemis/Artemis/Views/LayerEditor/LayerConditionView.xaml
new file mode 100644
index 000000000..67c8f7ef0
--- /dev/null
+++ b/Artemis/Artemis/Views/LayerEditor/LayerConditionView.xaml
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Artemis/Artemis/Views/LayerEditor/LayerConditionView.xaml.cs b/Artemis/Artemis/Views/LayerEditor/LayerConditionView.xaml.cs
new file mode 100644
index 000000000..1dd225b05
--- /dev/null
+++ b/Artemis/Artemis/Views/LayerEditor/LayerConditionView.xaml.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace Artemis.Views.LayerEditor
+{
+ ///
+ /// Interaction logic for LayerConditionView.xaml
+ ///
+ public partial class LayerConditionView : UserControl
+ {
+ public LayerConditionView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Artemis/Artemis/Views/LayerEditorView.xaml b/Artemis/Artemis/Views/LayerEditorView.xaml
new file mode 100644
index 000000000..087e0200d
--- /dev/null
+++ b/Artemis/Artemis/Views/LayerEditorView.xaml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Artemis/Artemis/Views/LayerEditorView.xaml.cs b/Artemis/Artemis/Views/LayerEditorView.xaml.cs
new file mode 100644
index 000000000..ea8195886
--- /dev/null
+++ b/Artemis/Artemis/Views/LayerEditorView.xaml.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Shapes;
+using MahApps.Metro.Controls;
+
+namespace Artemis.Views
+{
+ ///
+ /// Interaction logic for LayerEditorView.xaml
+ ///
+ public partial class LayerEditorView : MetroWindow
+ {
+ public LayerEditorView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Artemis/Artemis/Views/ProfileEditorView.xaml b/Artemis/Artemis/Views/ProfileEditorView.xaml
new file mode 100644
index 000000000..813cb7f82
--- /dev/null
+++ b/Artemis/Artemis/Views/ProfileEditorView.xaml
@@ -0,0 +1,85 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Artemis/Artemis/Views/ProfileEditorView.xaml.cs b/Artemis/Artemis/Views/ProfileEditorView.xaml.cs
new file mode 100644
index 000000000..5cfcb4102
--- /dev/null
+++ b/Artemis/Artemis/Views/ProfileEditorView.xaml.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace Artemis.Views
+{
+ ///
+ /// Interaction logic for ProfileEditorView.xaml
+ ///
+ public partial class ProfileEditorView : UserControl
+ {
+ public ProfileEditorView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Artemis/Artemis/Views/ShellView.xaml b/Artemis/Artemis/Views/ShellView.xaml
index 29ff90142..3ee6e1392 100644
--- a/Artemis/Artemis/Views/ShellView.xaml
+++ b/Artemis/Artemis/Views/ShellView.xaml
@@ -8,7 +8,7 @@
xmlns:dialogs="clr-namespace:MahApps.Metro.Controls.Dialogs;assembly=MahApps.Metro"
dialogs:DialogParticipation.Register="{Binding RelativeSource={RelativeSource Self}, Path=DataContext}"
mc:Ignorable="d"
- Title="Artemis" Height="670" Width="690"
+ Title="Artemis" Height="800" Width="1200"
MinWidth="500" MinHeight="400"
GlowBrush="{DynamicResource AccentColorBrush}" Icon="../logo.ico">
diff --git a/Artemis/Artemis/packages.config b/Artemis/Artemis/packages.config
index 8cb94cea7..8a610c1e7 100644
--- a/Artemis/Artemis/packages.config
+++ b/Artemis/Artemis/packages.config
@@ -18,6 +18,7 @@
+
\ No newline at end of file
diff --git a/Artemis/LogiLed2Artemis/Logger.cpp b/Artemis/LogiLed2Artemis/Logger.cpp
new file mode 100644
index 000000000..d255c8713
--- /dev/null
+++ b/Artemis/LogiLed2Artemis/Logger.cpp
@@ -0,0 +1,104 @@
+// Original work by VRocker https://github.com/VRocker/LogiLed2Corsair
+// I'm mainly a C# developer, and these modification aren't a piece of art, but it suits our needs.
+
+// The MIT License (MIT)
+//
+// Copyright (c) 2015 VRocker
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "Logger.h"
+
+#include
+#include
+#include
+
+
+// Ok this looks butt-ugleh but its just to force the default log level to debug if we compile in debug
+#ifdef _DEBUG
+LogLevel CLogger::m_eLogLevel = LogLevel::Debug;
+#else
+LogLevel CLogger::m_eLogLevel = LogLevel::All;
+#endif
+FILE* CLogger::m_pFile = 0;
+
+void CLogger::InitLogging(const char* szFile)
+{
+ if (!m_pFile)
+ {
+ m_pFile = fopen(szFile, "a+");
+ if (!m_pFile)
+ {
+ // Hum, we couldn't open the file for writing
+ printf("ERROR: Unable to open log file %s.\n", szFile);
+ }
+ }
+}
+
+void CLogger::EndLogging(void)
+{
+ if (m_pFile)
+ {
+ fclose(m_pFile);
+ m_pFile = 0;
+ }
+}
+
+void CLogger::OutputLog_s(const char* sz, const LogLevel eLevel)
+{
+ // If the level of this log entry is less important than what we are told to log, just return
+ if (eLevel < m_eLogLevel)
+ return;
+
+ // If we don't have a file to write to, bail.
+ if (!m_pFile)
+ return;
+
+ char szOutput[512] = {0};
+
+ time_t rawtime;
+ struct tm* timeinfo;
+
+ time(&rawtime);
+ timeinfo = localtime(&rawtime);
+
+ // Timestamp the log entry
+ size_t uiLen = sprintf(szOutput, "<%.2d/%.2d/%.2d - %.2d:%.2d:%.2d> %s\n", timeinfo->tm_mday, timeinfo->tm_mon + 1, timeinfo->tm_year + 1900, timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec, sz);
+
+ // Write the text to the file
+ fwrite(szOutput, 1, uiLen, m_pFile);
+ // Flush the log file to the disk. May move this to a seperate function
+ fflush(m_pFile);
+
+ // Output the text to any console that may be attached
+ printf("%s", szOutput);
+}
+
+void CLogger::OutputLog(const char* sz, const LogLevel eLevel, ...)
+{
+ char szText[1024] = {0};
+ va_list marker;
+ va_start(marker, eLevel);
+ vsprintf(szText, sz, marker);
+ va_end(marker);
+
+ // Since this function is pretty much the same as the safer function, we'll just redirect it there
+ OutputLog_s(szText, eLevel);
+}
+
diff --git a/Artemis/LogiLed2Artemis/Logger.h b/Artemis/LogiLed2Artemis/Logger.h
new file mode 100644
index 000000000..41cab02d2
--- /dev/null
+++ b/Artemis/LogiLed2Artemis/Logger.h
@@ -0,0 +1,82 @@
+// Original work by VRocker https://github.com/VRocker/LogiLed2Corsair
+// I'm mainly a C# developer, and these modification aren't a piece of art, but it suits our needs.
+
+// The MIT License (MIT)
+//
+// Copyright (c) 2015 VRocker
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#pragma once
+#ifndef _LOGGER_H
+#define _LOGGER_H
+
+#include
+
+enum class LogLevel
+{
+ Debug,
+ All,
+ Critical,
+ Warning,
+ Information,
+ User,
+ Internal,
+ None,
+
+ // Just to force the compiler to treat the enum options as an int
+ FORCE_32BIT = 0x7fffffff
+};
+
+class CLogger
+{
+public:
+ static LogLevel GetLogLevel(void)
+ {
+ return m_eLogLevel;
+ }
+
+ static void SetLogLevel(const LogLevel e)
+ {
+#ifndef _DEBUG
+ if ( e == LogLevel::Debug ) return;
+#endif
+ m_eLogLevel = e;
+ }
+
+ static void InitLogging(const char* szFile);
+ // Always remember to end logging when you are finished otherwise you will have file handles floating around
+ static void EndLogging(void);
+
+ // Output the text to a log file.
+ static void OutputLog_s(const char* sz, const LogLevel eLevel);
+ static void OutputLog(const char* sz, const LogLevel eLevel, ...);
+
+ static FILE* GetFile()
+ {
+ return m_pFile;
+ }
+
+private:
+ static LogLevel m_eLogLevel;
+ static FILE* m_pFile;
+};
+
+#endif
+
diff --git a/Artemis/LogiLed2Artemis/LogiLed2Artemis.def b/Artemis/LogiLed2Artemis/LogiLed2Artemis.def
new file mode 100644
index 000000000..ef38be3f1
--- /dev/null
+++ b/Artemis/LogiLed2Artemis/LogiLed2Artemis.def
@@ -0,0 +1,49 @@
+// Original work by VRocker https://github.com/VRocker/LogiLed2Corsair
+// I'm mainly a C# developer, and these modification aren't a piece of art, but it suits our needs.
+
+// The MIT License (MIT)
+//
+// Copyright (c) 2015 VRocker
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+LIBRARY LogiLed2Artemis.dll
+
+EXPORTS
+
+ LogiLedInit
+ LogiLedGetSdkVersion
+ LogiLedSetTargetDevice
+ LogiLedSaveCurrentLighting
+ LogiLedSetLighting
+ LogiLedRestoreLighting
+ LogiLedFlashLighting
+ LogiLedPulseLighting
+ LogiLedStopEffects
+ LogiLedSetLightingFromBitmap
+ LogiLedSetLightingForKeyWithScanCode
+ LogiLedSetLightingForKeyWithHidCode
+ LogiLedSetLightingForKeyWithQuartzCode
+ LogiLedSetLightingForKeyWithKeyName
+ LogiLedSaveLightingForKey
+ LogiLedRestoreLightingForKey
+ LogiLedFlashSingleKey
+ LogiLedPulseSingleKey
+ LogiLedStopEffectsOnKey
+ LogiLedShutdown
diff --git a/Artemis/LogiLed2Artemis/LogiLed2Artemis.vcxproj b/Artemis/LogiLed2Artemis/LogiLed2Artemis.vcxproj
new file mode 100644
index 000000000..670478206
--- /dev/null
+++ b/Artemis/LogiLed2Artemis/LogiLed2Artemis.vcxproj
@@ -0,0 +1,168 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}
+ Win32Proj
+ LogiLed2Artemis
+ LogiLed2Artemis
+
+
+
+ DynamicLibrary
+ true
+ v140
+ Unicode
+
+
+ DynamicLibrary
+ true
+ v140
+ Unicode
+
+
+ DynamicLibrary
+ false
+ v140
+ true
+ Unicode
+
+
+ DynamicLibrary
+ false
+ v140
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+ true
+ $(LibraryPath)
+
+
+ false
+
+
+ false
+ $(ProjectName)
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_WINDOWS;_USRDLL;LOGILEDCORSAIR_EXPORTS;%(PreprocessorDefinitions)
+
+
+ Windows
+ true
+ LogiLed2Artemis.def
+ ../CUESDK/lib/i386/CUESDK_2013.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_WINDOWS;_USRDLL;LOGILEDCORSAIR_EXPORTS;%(PreprocessorDefinitions)
+ %(AdditionalIncludeDirectories)
+
+
+ Windows
+ true
+ LogiLed2Artemis.def
+ %(AdditionalDependencies)
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_WINDOWS;_USRDLL;LOGILEDCORSAIR_EXPORTS;%(PreprocessorDefinitions)
+
+
+ Windows
+ true
+ true
+ true
+ LogiLed2Artemis.def
+ ../CUESDK/lib/i386/CUESDK_2013.lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_WINDOWS;_USRDLL;LOGILEDCORSAIR_EXPORTS;%(PreprocessorDefinitions)
+
+
+ Windows
+ true
+ true
+ true
+ LogiLed2Artemis.def
+ %(AdditionalDependencies)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Artemis/LogiLed2Artemis/LogiLed2Artemis.vcxproj.filters b/Artemis/LogiLed2Artemis/LogiLed2Artemis.vcxproj.filters
new file mode 100644
index 000000000..34a553926
--- /dev/null
+++ b/Artemis/LogiLed2Artemis/LogiLed2Artemis.vcxproj.filters
@@ -0,0 +1,41 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+ Source Files
+
+
+
\ No newline at end of file
diff --git a/Artemis/LogiLed2Artemis/LogiLedDefs.h b/Artemis/LogiLed2Artemis/LogiLedDefs.h
new file mode 100644
index 000000000..e1d2a4f24
--- /dev/null
+++ b/Artemis/LogiLed2Artemis/LogiLedDefs.h
@@ -0,0 +1,135 @@
+#pragma once
+
+const int LOGITECH_LED_MOUSE = 0x0001;
+const int LOGITECH_LED_KEYBOARD = 0x0002;
+const int LOGITECH_LED_ALL = LOGITECH_LED_MOUSE | LOGITECH_LED_KEYBOARD;
+
+#define LOGI_LED_BITMAP_WIDTH 21
+#define LOGI_LED_BITMAP_HEIGHT 6
+#define LOGI_LED_BITMAP_BYTES_PER_KEY 4
+
+#define LOGI_LED_BITMAP_SIZE LOGI_LED_BITMAP_WIDTH*LOGI_LED_BITMAP_HEIGHT*LOGI_LED_BITMAP_BYTES_PER_KEY
+
+#define LOGI_LED_DURATION_INFINITE 0
+
+#define LOGI_DEVICETYPE_MONOCHROME_ORD 0
+#define LOGI_DEVICETYPE_RGB_ORD 1
+#define LOGI_DEVICETYPE_PERKEY_RGB_ORD 2
+
+#define LOGI_DEVICETYPE_MONOCHROME (1 << LOGI_DEVICETYPE_MONOCHROME_ORD)
+#define LOGI_DEVICETYPE_RGB (1 << LOGI_DEVICETYPE_RGB_ORD)
+#define LOGI_DEVICETYPE_PERKEY_RGB (1 << LOGI_DEVICETYPE_PERKEY_RGB_ORD)
+
+#define LOGI_DEVICETYPE_ALL (LOGI_DEVICETYPE_MONOCHROME | LOGI_DEVICETYPE_RGB | LOGI_DEVICETYPE_PERKEY_RGB)
+
+namespace LogiLed
+{
+ typedef enum
+ {
+ ESC = 0x01,
+ F1 = 0x3b,
+ F2 = 0x3c,
+ F3 = 0x3d,
+ F4 = 0x3e,
+ F5 = 0x3f,
+ F6 = 0x40,
+ F7 = 0x41,
+ F8 = 0x42,
+ F9 = 0x43,
+ F10 = 0x44,
+ F11 = 0x57,
+ F12 = 0x58,
+ PRINT_SCREEN = 0x137,
+ SCROLL_LOCK = 0x46,
+ PAUSE_BREAK = 0x145,
+ TILDE = 0x29,
+ ONE = 0x02,
+ TWO = 0x03,
+ THREE = 0x04,
+ FOUR = 0x05,
+ FIVE = 0x06,
+ SIX = 0x07,
+ SEVEN = 0x08,
+ EIGHT = 0x09,
+ NINE = 0x0A,
+ ZERO = 0x0B,
+ MINUS = 0x0C,
+ EQUALS = 0x0D,
+ BACKSPACE = 0x0E,
+ INSERT = 0x152,
+ HOME = 0x147,
+ PAGE_UP = 0x149,
+ NUM_LOCK = 0x45,
+ NUM_SLASH = 0x135,
+ NUM_ASTERISK = 0x37,
+ NUM_MINUS = 0x4A,
+ TAB = 0x0F,
+ Q = 0x10,
+ W = 0x11,
+ E = 0x12,
+ R = 0x13,
+ T = 0x14,
+ Y = 0x15,
+ U = 0x16,
+ I = 0x17,
+ O = 0x18,
+ P = 0x19,
+ OPEN_BRACKET = 0x1A,
+ CLOSE_BRACKET = 0x1B,
+ BACKSLASH = 0x2B,
+ KEYBOARD_DELETE = 0x153,
+ END = 0x14F,
+ PAGE_DOWN = 0x151,
+ NUM_SEVEN = 0x47,
+ NUM_EIGHT = 0x48,
+ NUM_NINE = 0x49,
+ NUM_PLUS = 0x4E,
+ CAPS_LOCK = 0x3A,
+ A = 0x1E,
+ S = 0x1F,
+ D = 0x20,
+ F = 0x21,
+ G = 0x22,
+ H = 0x23,
+ J = 0x24,
+ K = 0x25,
+ L = 0x26,
+ SEMICOLON = 0x27,
+ APOSTROPHE = 0x28,
+ ENTER = 0x1C,
+ NUM_FOUR = 0x4B,
+ NUM_FIVE = 0x4C,
+ NUM_SIX = 0x4D,
+ LEFT_SHIFT = 0x2A,
+ Z = 0x2C,
+ X = 0x2D,
+ C = 0x2E,
+ V = 0x2F,
+ B = 0x30,
+ N = 0x31,
+ M = 0x32,
+ COMMA = 0x33,
+ PERIOD = 0x34,
+ FORWARD_SLASH = 0x35,
+ RIGHT_SHIFT = 0x36,
+ ARROW_UP = 0x148,
+ NUM_ONE = 0x4F,
+ NUM_TWO = 0x50,
+ NUM_THREE = 0x51,
+ NUM_ENTER = 0x11C,
+ LEFT_CONTROL = 0x1D,
+ LEFT_WINDOWS = 0x15B,
+ LEFT_ALT = 0x38,
+ SPACE = 0x39,
+ RIGHT_ALT = 0x138,
+ RIGHT_WINDOWS = 0x15C,
+ APPLICATION_SELECT = 0x15D,
+ RIGHT_CONTROL = 0x11D,
+ ARROW_LEFT = 0x14B,
+ ARROW_DOWN = 0x150,
+ ARROW_RIGHT = 0x14D,
+ NUM_ZERO = 0x52,
+ NUM_PERIOD = 0x53,
+ } KeyName;
+}
+
diff --git a/Artemis/LogiLed2Artemis/main.cpp b/Artemis/LogiLed2Artemis/main.cpp
new file mode 100644
index 000000000..c224e7daf
--- /dev/null
+++ b/Artemis/LogiLed2Artemis/main.cpp
@@ -0,0 +1,254 @@
+// Original work by VRocker https://github.com/VRocker/LogiLed2Corsair
+// I'm mainly a C# developer, and these modification aren't a piece of art, but it suits our needs.
+
+// The MIT License (MIT)
+//
+// Copyright (c) 2015 VRocker
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "main.h"
+#include
+#include
+#include
+#include "LogiLedDefs.h"
+#define WIN32_LEAN_AND_MEAN
+#include
+#include "Logger.h"
+
+#include
+#include
+
+
+static bool g_hasInitialised = false;
+const char* game = "";
+
+void cleanup()
+{
+ CLogger::EndLogging();
+}
+
+BOOL WINAPI DllMain(HINSTANCE hInst, DWORD fdwReason, LPVOID)
+{
+ switch (fdwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ {
+ atexit(cleanup);
+
+ CLogger::InitLogging("Log.txt");
+ CLogger::SetLogLevel(LogLevel::None);
+
+ // Get the process that loaded the DLL
+ TCHAR divisionFind[] = _T("Division");
+ TCHAR gtaFind[] = _T("GTA");
+ TCHAR szPath[MAX_PATH];
+ GetModuleFileName(NULL, szPath, MAX_PATH);
+
+ if (_tcscmp(szPath, divisionFind) != 0)
+ game = "division";
+ else if (_tcscmp(szPath, gtaFind) != 0)
+ game = "gta";
+
+ CLogger::OutputLog("Attached to process.", LogLevel::Debug);
+ }
+ break;
+
+ case DLL_PROCESS_DETACH:
+ {
+ cleanup();
+
+ CLogger::OutputLog_s("Detached from process.", LogLevel::Debug);
+ }
+ break;
+ }
+
+ return true;
+}
+
+bool LogiLedInit()
+{
+ CLogger::OutputLog_s("Logitech LED init called.", LogLevel::Debug);
+ g_hasInitialised = true;
+ return true;
+}
+
+bool LogiLedGetSdkVersion(int* majorNum, int* minorNum, int* buildNum)
+{
+ CLogger::OutputLog("LogiLedGetSdkVersion called.", LogLevel::Debug);
+
+ // Mimic the SDK version
+ *majorNum = 8;
+ *minorNum = 81;
+ *buildNum = 15;
+
+ return true;
+}
+
+bool LogiLedSetTargetDevice(int targetDevice)
+{
+ CLogger::OutputLog("LogiLedSetTargetDevice called (%i)", LogLevel::Debug, targetDevice);
+
+ // Logitech SDK says this function returns false if LogiLedInit hasn't been called
+ return g_hasInitialised;
+}
+
+bool LogiLedSaveCurrentLighting()
+{
+ CLogger::OutputLog("LogiLedSaveCurrentLighting called (%i)", LogLevel::Debug);
+ return true;
+}
+
+void Transmit(const char* msg)
+{
+ //Pipe Init Data
+ HANDLE hPipe1;
+ char buf[100];
+ LPTSTR lpszPipename1 = TEXT("\\\\.\\pipe\\artemis");
+
+ hPipe1 = CreateFile(lpszPipename1, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
+ if (hPipe1 == NULL || hPipe1 == INVALID_HANDLE_VALUE)
+ {
+ CLogger::OutputLog("Could not open the pipe - (error %i)", LogLevel::Debug, GetLastError());
+ return;
+ }
+
+ DWORD cbWritten;
+ WriteFile(hPipe1, msg, strlen(msg), &cbWritten, NULL);
+ CLogger::OutputLog_s("Transmitted to pipe", LogLevel::Debug);
+}
+
+bool LogiLedSetLighting(int redPercentage, int greenPercentage, int bluePercentage)
+{
+ CLogger::OutputLog("LogiLedSetLighting called (%i %i %i)", LogLevel::Debug, redPercentage, greenPercentage, bluePercentage);
+
+ std::ostringstream os;
+ os << "0 0 " << redPercentage << " " << greenPercentage << " " << bluePercentage;
+ Transmit(os.str().c_str());
+
+ return true;
+}
+
+bool LogiLedRestoreLighting()
+{
+ CLogger::OutputLog("LogiLedRestoreLighting called", LogLevel::Debug);
+ return true;
+}
+
+bool LogiLedFlashLighting(int redPercentage, int greenPercentage, int bluePercentage, int milliSecondsDuration, int milliSecondsInterval)
+{
+ CLogger::OutputLog("LogiLedFlashLighting called (%i %i %i %i %i)", LogLevel::Debug, redPercentage, greenPercentage, bluePercentage, milliSecondsDuration, milliSecondsInterval);
+ return true;
+}
+
+bool LogiLedPulseLighting(int redPercentage, int greenPercentage, int bluePercentage, int milliSecondsDuration, int milliSecondsInterval)
+{
+ CLogger::OutputLog("LogiLedPulseLighting called (%i %i %i %i %i)", LogLevel::Debug, redPercentage, greenPercentage, bluePercentage, milliSecondsDuration, milliSecondsInterval);
+ return true;
+}
+
+bool LogiLedStopEffects()
+{
+ CLogger::OutputLog_s("LogiLedStopEffects called", LogLevel::Debug);
+ return true;
+}
+
+bool LogiLedSetLightingFromBitmap(unsigned char bitmap[])
+{
+ CLogger::OutputLog_s("LogiLedSetLightingFromBitmap called", LogLevel::Debug);
+ return true;
+}
+
+bool LogiLedSetLightingForKeyWithScanCode(int keyCode, int redPercentage, int greenPercentage, int bluePercentage)
+{
+ CLogger::OutputLog("LogiLedSetLightingForKeyWithScanCode called [Key: %i] (%i %i %i)", LogLevel::Debug, keyCode, redPercentage, greenPercentage, bluePercentage);
+ return true;
+}
+
+bool LogiLedSetLightingForKeyWithHidCode(int keyCode, int redPercentage, int greenPercentage, int bluePercentage)
+{
+ CLogger::OutputLog("LogiLedSetLightingForKeyWithHidCode called [Key: %i] (%i %i %i)", LogLevel::Debug, keyCode, redPercentage, greenPercentage, bluePercentage);
+ return true;
+}
+
+bool LogiLedSetLightingForKeyWithQuartzCode(int keyCode, int redPercentage, int greenPercentage, int bluePercentage)
+{
+ CLogger::OutputLog("LogiLedSetLightingForKeyWithQuartzCode called [Key: %i] (%i %i %i)", LogLevel::Debug, keyCode, redPercentage, greenPercentage, bluePercentage);
+ return true;
+}
+
+bool LogiLedSetLightingForKeyWithKeyName(LogiLed::KeyName keyName, int redPercentage, int greenPercentage, int bluePercentage)
+{
+ CLogger::OutputLog("LogiLedSetLightingForKeyWithKeyName called [Key: %i] (%i %i %i)", LogLevel::Debug, keyName, redPercentage, greenPercentage, bluePercentage);
+
+ // Only transmit interesting keys. This can most likely be done prettier, but I'm no C++ dev.
+ if (game == "division" &&
+ (keyName == LogiLed::F1 ||
+ keyName == LogiLed::F2 ||
+ keyName == LogiLed::F3 ||
+ keyName == LogiLed::F4 ||
+ keyName == LogiLed::R ||
+ keyName == LogiLed::G ||
+ keyName == LogiLed::V)
+ )
+ {
+ std::ostringstream os;
+ os << "1 " << keyName << " " << redPercentage << " " << greenPercentage << " " << bluePercentage;
+ std::string s = os.str();
+ Transmit(os.str().c_str());
+ }
+ return true;
+}
+
+bool LogiLedSaveLightingForKey(LogiLed::KeyName keyName)
+{
+ CLogger::OutputLog("LogiLedSaveLightingForKey called [Key: %i]", LogLevel::Debug, keyName);
+ return true;
+}
+
+bool LogiLedRestoreLightingForKey(LogiLed::KeyName keyName)
+{
+ CLogger::OutputLog("LogiLedRestoreLightingForKey called [Key: %i]", LogLevel::Debug, keyName);
+ return true;
+}
+
+bool LogiLedFlashSingleKey(LogiLed::KeyName keyName, int redPercentage, int greenPercentage, int bluePercentage, int msDuration, int msInterval)
+{
+ CLogger::OutputLog("LogiLedFlashSingleKey called [Key: %i] (%i %i %i %i %i)", LogLevel::Debug, keyName, redPercentage, greenPercentage, bluePercentage, msDuration, msInterval);
+ return true;
+}
+
+bool LogiLedPulseSingleKey(LogiLed::KeyName keyName, int startRedPercentage, int startGreenPercentage, int startBluePercentage, int finishRedPercentage, int finishGreenPercentage, int finishBluePercentage, int msDuration, bool isInfinite)
+{
+ CLogger::OutputLog("LogiLedPulseSingleKey called [Key: %i] (%i %i %i %i %i %i %i %i)", LogLevel::Debug, keyName, startRedPercentage, startGreenPercentage, startBluePercentage, finishRedPercentage, finishGreenPercentage, finishBluePercentage, msDuration, isInfinite);
+ return true;
+}
+
+bool LogiLedStopEffectsOnKey(LogiLed::KeyName keyName)
+{
+ CLogger::OutputLog("LogiLedStopEffectsOnKey called [Key: %i]", LogLevel::Debug, keyName);
+ return true;
+}
+
+void LogiLedShutdown()
+{
+ CLogger::OutputLog_s("LogiLedShutdown called.", LogLevel::Debug);
+ g_hasInitialised = false;
+}
+
diff --git a/Artemis/LogiLed2Artemis/main.h b/Artemis/LogiLed2Artemis/main.h
new file mode 100644
index 000000000..3f59c932d
--- /dev/null
+++ b/Artemis/LogiLed2Artemis/main.h
@@ -0,0 +1,2 @@
+#pragma once
+