diff --git a/Artemis/Artemis/App.config b/Artemis/Artemis/App.config index 41ce7e0b7..c2fc93200 100644 --- a/Artemis/Artemis/App.config +++ b/Artemis/Artemis/App.config @@ -288,6 +288,10 @@ + + + + diff --git a/Artemis/Artemis/Artemis.csproj b/Artemis/Artemis/Artemis.csproj index c3848c7c9..39c557e86 100644 --- a/Artemis/Artemis/Artemis.csproj +++ b/Artemis/Artemis/Artemis.csproj @@ -171,16 +171,20 @@ ..\packages\Newtonsoft.Json.8.0.2\lib\net45\Newtonsoft.Json.dll True - - ..\packages\SharpDX.3.0.1\lib\net45\SharpDX.dll + + ..\packages\Screna.0.1.3\lib\Screna.dll True - - ..\packages\SharpDX.Direct3D11.3.0.1\lib\net45\SharpDX.Direct3D11.dll + + ..\packages\SharpDX.3.0.2\lib\net45\SharpDX.dll True - - ..\packages\SharpDX.DXGI.3.0.1\lib\net45\SharpDX.DXGI.dll + + ..\packages\SharpDX.Direct3D11.3.0.2\lib\net45\SharpDX.Direct3D11.dll + True + + + ..\packages\SharpDX.DXGI.3.0.2\lib\net45\SharpDX.DXGI.dll True @@ -315,6 +319,7 @@ True TheDivision.settings + @@ -376,6 +381,7 @@ + diff --git a/Artemis/Artemis/ArtemisBootstrapper.cs b/Artemis/Artemis/ArtemisBootstrapper.cs index 29dffcc6b..e0f82e4b6 100644 --- a/Artemis/Artemis/ArtemisBootstrapper.cs +++ b/Artemis/Artemis/ArtemisBootstrapper.cs @@ -18,8 +18,6 @@ namespace Artemis public ArtemisBootstrapper() { CheckDuplicateInstances(); - if (DllManager.RestoreDll()) - GeneralHelpers.RunAsAdministrator(); Initialize(); } diff --git a/Artemis/Artemis/KeyboardProviders/Corsair/CorsairRGB.cs b/Artemis/Artemis/KeyboardProviders/Corsair/CorsairRGB.cs index 075ae0ae1..75926f094 100644 --- a/Artemis/Artemis/KeyboardProviders/Corsair/CorsairRGB.cs +++ b/Artemis/Artemis/KeyboardProviders/Corsair/CorsairRGB.cs @@ -67,7 +67,6 @@ namespace Artemis.KeyboardProviders.Corsair /*CUE is already initialized*/ } _keyboard = CueSDK.KeyboardSDK; - switch (_keyboard.DeviceInfo.Model) { case "K95 RGB": @@ -100,7 +99,7 @@ namespace Artemis.KeyboardProviders.Corsair break; } - // _keyboard.UpdateMode = UpdateMode.Manual; + _keyboard.UpdateMode = UpdateMode.Manual; _keyboard.Update(true); } @@ -116,21 +115,24 @@ namespace Artemis.KeyboardProviders.Corsair /// public override void DrawBitmap(Bitmap bitmap) { - using ( - var resized = ImageUtilities.ResizeImage(bitmap, - (int) _keyboard.KeyboardRectangle.Width, - (int) _keyboard.KeyboardRectangle.Height) - ) + var res = ImageUtilities.ResizeImage(bitmap, (int) _keyboard.KeyboardRectangle.Width, + (int) _keyboard.KeyboardRectangle.Height); + + foreach (var item in _keyboard.Keys) { - foreach (var item in _keyboard.Keys) - { - var ledColor = resized.GetPixel((int) item.KeyRectangle.X, (int) item.KeyRectangle.Y); - if (ledColor == Color.FromArgb(0, 0, 0, 0)) - ledColor = Color.Black; - item.Led.Color = ledColor; - } + item.Led.Color = Color.Black; + + var ledColor = res.GetPixel((int) item.KeyRectangle.X, (int) item.KeyRectangle.Y); + if (ledColor.A == 0) + continue; + + // Since the brightness doesn't seem to be used, + // decrease the RGB value based on the brightness manually + item.Led.Color = Color.FromArgb(255, (int) (ledColor.R/255.00*ledColor.A), + (int) (ledColor.G/255.00*ledColor.A), (int) (ledColor.B/255.00*ledColor.A)); } + _keyboard.Update(true); } } -} +} \ No newline at end of file diff --git a/Artemis/Artemis/KeyboardProviders/Logitech/Orion.cs b/Artemis/Artemis/KeyboardProviders/Logitech/Orion.cs index a0ab5e50c..eaeae906e 100644 --- a/Artemis/Artemis/KeyboardProviders/Logitech/Orion.cs +++ b/Artemis/Artemis/KeyboardProviders/Logitech/Orion.cs @@ -1,7 +1,11 @@ using System.Collections.Generic; using System.Drawing; using System.Threading; +using System.Windows; using Artemis.KeyboardProviders.Logitech.Utilities; +using Artemis.Utilities; +using Artemis.Utilities.LogitechDll; +using Point = System.Drawing.Point; namespace Artemis.KeyboardProviders.Logitech { @@ -26,6 +30,8 @@ namespace Artemis.KeyboardProviders.Logitech public override bool CanEnable() { + if (DllManager.RestoreDll()) + RestoreDll(); int majorNum = 0, minorNum = 0, buildNum = 0; LogitechGSDK.LogiLedInit(); @@ -37,6 +43,18 @@ namespace Artemis.KeyboardProviders.Logitech return version >= 88115; } + private void RestoreDll() + { + MessageBox.Show( + "Artemis couldn't enable your Logitech keyboard, because the required files are not in place.\n\n" + + "This happens when you run The Division and shut down Artemis before shutting down The Division\n" + + "It can be fixed automatically by clicking OK, but to avoid this message in the future please\n" + + "shut down The Division before shutting down Artemis.\n\n" + + "Click OK to fix the issue and restart Artemis"); + + GeneralHelpers.RunAsAdministrator(); + } + public override void Enable() { // Initialize the SDK diff --git a/Artemis/Artemis/KeyboardProviders/ProviderHelper.cs b/Artemis/Artemis/KeyboardProviders/ProviderHelper.cs index 0e5483490..8e03f5aba 100644 --- a/Artemis/Artemis/KeyboardProviders/ProviderHelper.cs +++ b/Artemis/Artemis/KeyboardProviders/ProviderHelper.cs @@ -11,8 +11,8 @@ namespace Artemis.KeyboardProviders { return new List { - new Orion(), new CorsairRGB(), + new Orion(), new BlackWidow() }; } diff --git a/Artemis/Artemis/Modules/Effects/AudioVisualizer/AudioVisualizerModel.cs b/Artemis/Artemis/Modules/Effects/AudioVisualizer/AudioVisualizerModel.cs index 754cb4310..003645e62 100644 --- a/Artemis/Artemis/Modules/Effects/AudioVisualizer/AudioVisualizerModel.cs +++ b/Artemis/Artemis/Modules/Effects/AudioVisualizer/AudioVisualizerModel.cs @@ -93,6 +93,7 @@ namespace Artemis.Modules.Effects.AudioVisualizer public override void Update() { + // TODO: Use lock instead of a bool // Start filling the model _generating = true; diff --git a/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionDataModel.cs b/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionDataModel.cs new file mode 100644 index 000000000..f2a6390d5 --- /dev/null +++ b/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionDataModel.cs @@ -0,0 +1,42 @@ +using System.Collections.Generic; + +namespace Artemis.Modules.Games.TheDivision +{ + public class TheDivisionDataModel + { + 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(); + } + } + + public class DivisionPlayer + { + public int Id { get; set; } + public PlayerState PlayerState { get; set; } + + public DivisionPlayer(int id) + { + Id = id; + } + } + + public enum GrenadeState + { + HasGrenade, + HasNoGrenade, + GrenadeEquipped + } + + public enum PlayerState + { + Offline, + Online, + Hit + } +} \ No newline at end of file diff --git a/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionModel.cs b/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionModel.cs index 92dc1a9a6..b26817c30 100644 --- a/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionModel.cs +++ b/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionModel.cs @@ -1,15 +1,29 @@ -using System; -using System.Diagnostics; +using System.Collections.Generic; using System.Drawing; -using Artemis.KeyboardProviders.Logitech.Utilities; +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 { public class TheDivisionModel : GameModel { + private Wave _ammoWave; + private TheDivisionDataModel _dataModel; + private KeyboardRectangle _hpRect; + private KeyboardRectangle _p2; + private KeyboardRectangle _p3; + private KeyboardRectangle _p4; + private StickyValue _stickyAmmo; + private StickyValue _stickyHp; + private int _trans; + public TheDivisionModel(MainManager mainManager, TheDivisionSettings settings) : base(mainManager) { Settings = settings; @@ -28,18 +42,71 @@ namespace Artemis.Modules.Games.TheDivision { Initialized = false; DllManager.RestoreDll(); + + _stickyAmmo.Dispose(); + _stickyHp.Dispose(); } public override void Enable() { Initialized = false; + + _ammoWave = new Wave(new Point(30, 14), 0, Color.Transparent); + _hpRect = new KeyboardRectangle(MainManager.KeyboardManager.ActiveKeyboard, 3*Scale, 0*Scale, + new List(), + LinearGradientMode.Horizontal) + { + Height = 7*Scale, + Width = 21*Scale, + Rotate = true, + ContainedBrush = false + }; + + _p2 = new KeyboardRectangle(MainManager.KeyboardManager.ActiveKeyboard, 0*Scale, 1*Scale, + new List(), + LinearGradientMode.Horizontal) + { + Height = 2*Scale, + Width = 3*Scale, + Rotate = true, + ContainedBrush = false + }; + _p3 = new KeyboardRectangle(MainManager.KeyboardManager.ActiveKeyboard, 0*Scale, 3*Scale, + new List(), + LinearGradientMode.Horizontal) + { + Height = 2*Scale, + Width = 3*Scale, + Rotate = true, + ContainedBrush = false + }; + _p4 = new KeyboardRectangle(MainManager.KeyboardManager.ActiveKeyboard, 0*Scale, 6*Scale, + new List(), + LinearGradientMode.Horizontal) + { + Height = 2*Scale, + Width = 3*Scale, + Rotate = true, + ContainedBrush = false + }; + + _stickyAmmo = new StickyValue(200); + _stickyHp = new StickyValue(200); + DllManager.PlaceDll(); + _dataModel = new TheDivisionDataModel(); + for (var i = 1; i < 5; i++) + _dataModel.DivisionPlayers.Add(new DivisionPlayer(i)); + MainManager.PipeServer.PipeMessage += PipeServerOnPipeMessage; Initialized = true; } private void PipeServerOnPipeMessage(string reply) { + if (!Initialized) + return; + // Convert the given string to a list of ints var stringParts = reply.Split(' '); var parts = new int[stringParts.Length]; @@ -48,23 +115,105 @@ namespace Artemis.Modules.Games.TheDivision if (parts[0] == 1) InterpertrateDivisionKey(parts); - } // Parses Division key data to game data private void InterpertrateDivisionKey(int[] parts) { + var keyCode = parts[1]; + var rPer = parts[2]; + var gPer = parts[3]; + var bPer = parts[4]; + // F1 to F4 indicate the player and his party. Blinks red on damage taken - + if (keyCode >= 59 && keyCode <= 62) + { + var playerId = keyCode - 58; + var playerDataModel = _dataModel.DivisionPlayers.FirstOrDefault(p => p.Id == playerId); + if (playerDataModel == null) + return; + + if (gPer > 10) + playerDataModel.PlayerState = PlayerState.Online; + else if (rPer > 10) + playerDataModel.PlayerState = PlayerState.Hit; + else + playerDataModel.PlayerState = PlayerState.Offline; + } // R blinks white when low on ammo - + else if (keyCode == 19) + { + _stickyAmmo.Value = rPer == 100 && gPer > 1 && bPer > 1; + _dataModel.LowAmmo = _stickyAmmo.Value; + } // G turns white when holding a grenade, turns off when out of grenades - + else if (keyCode == 34) + { + if (rPer == 100 && gPer < 10 && bPer < 10) + _dataModel.GrenadeState = GrenadeState.HasGrenade; + else if (rPer == 100 && gPer > 10 && bPer > 10) + _dataModel.GrenadeState = GrenadeState.GrenadeEquipped; + else + _dataModel.GrenadeState = GrenadeState.HasNoGrenade; + } // V blinks on low HP + else if (keyCode == 47) + { + _stickyHp.Value = rPer == 100 && gPer > 1 && bPer > 1; + _dataModel.LowHp = _stickyHp.Value; + } } public override void Update() { + if (_dataModel.LowAmmo) + { + _ammoWave.Size++; + if (_ammoWave.Size > 30) + { + _ammoWave.Size = 0; + _trans = 255; + } + } + else + _ammoWave.Size = 0; + + _hpRect.Colors = _dataModel.LowHp + ? new List {Color.Red, Color.Orange} + : new List {Color.GreenYellow, Color.Green}; + + if (_dataModel.DivisionPlayers[1].PlayerState == PlayerState.Offline) + _p2.Colors = new List {Color.Gray, Color.White}; + else if (_dataModel.DivisionPlayers[1].PlayerState == PlayerState.Online) + _p2.Colors = new List {Color.GreenYellow, Color.Green}; + else + _p2.Colors = new List {Color.Red, Color.Orange}; + + if (_dataModel.DivisionPlayers[2].PlayerState == PlayerState.Offline) + _p3.Colors = new List {Color.Gray, Color.White}; + else if (_dataModel.DivisionPlayers[2].PlayerState == PlayerState.Online) + _p3.Colors = new List {Color.GreenYellow, Color.Green}; + else + _p3.Colors = new List {Color.Red, Color.Orange}; + + if (_dataModel.DivisionPlayers[3].PlayerState == PlayerState.Offline) + _p4.Colors = new List {Color.Gray, Color.White}; + else if (_dataModel.DivisionPlayers[3].PlayerState == PlayerState.Online) + _p4.Colors = new List {Color.GreenYellow, Color.Green}; + 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() @@ -73,6 +222,34 @@ namespace Artemis.Modules.Games.TheDivision 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 (_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; } diff --git a/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionView.xaml b/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionView.xaml index b176265a5..5bd90ab14 100644 --- a/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionView.xaml +++ b/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionView.xaml @@ -38,7 +38,7 @@ - Note: For this game to work with Artemis, please enable ... in The Division settings. + 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/Utilities/ImageUtilities.cs b/Artemis/Artemis/Utilities/ImageUtilities.cs index 64537a075..464bffc17 100644 --- a/Artemis/Artemis/Utilities/ImageUtilities.cs +++ b/Artemis/Artemis/Utilities/ImageUtilities.cs @@ -66,10 +66,6 @@ namespace Artemis.Utilities //use a graphics object to draw the resized image into the bitmap using (var graphics = Graphics.FromImage(result)) { - //set the resize quality modes to high quality - graphics.CompositingQuality = CompositingQuality.HighQuality; - graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; - graphics.SmoothingMode = SmoothingMode.HighQuality; //draw the image into the target bitmap graphics.DrawImage(image, 0, 0, result.Width, result.Height); } @@ -77,26 +73,5 @@ namespace Artemis.Utilities //return the resulting bitmap return result; } - - /// - /// Returns the image codec with the given mime type - /// - public static ImageCodecInfo GetEncoderInfo(string mimeType) - { - //do a case insensitive search for the mime type - var lookupKey = mimeType.ToLower(); - - //the codec to return, default to null - ImageCodecInfo foundCodec = null; - - //if we have the encoder, get it to return - if (Encoders.ContainsKey(lookupKey)) - { - //pull the codec from the lookup - foundCodec = Encoders[lookupKey]; - } - - return foundCodec; - } } } \ No newline at end of file diff --git a/Artemis/Artemis/Utilities/StickyValue.cs b/Artemis/Artemis/Utilities/StickyValue.cs new file mode 100644 index 000000000..a9ad4c1fd --- /dev/null +++ b/Artemis/Artemis/Utilities/StickyValue.cs @@ -0,0 +1,64 @@ +using System; +using System.ComponentModel; +using System.Threading; + +namespace Artemis.Utilities +{ + /// + /// A value that only changes it's not changed again within a set time + /// + internal class StickyValue : IDisposable + { + private readonly int _stickyTime; + private readonly BackgroundWorker _updateWorker; + private T _toStick; + private T _value; + private int _waitTime; + + public StickyValue(int stickyTime) + { + _stickyTime = stickyTime; + + _updateWorker = new BackgroundWorker {WorkerSupportsCancellation = true}; + _updateWorker.DoWork += UpdateWorkerOnDoWork; + _updateWorker.RunWorkerAsync(); + } + + public T Value + { + get { return _value; } + set + { + if (_toStick.Equals(value)) + return; + + _waitTime = _stickyTime; + _toStick = value; + } + } + + public void Dispose() + { + _updateWorker.CancelAsync(); + } + + private void UpdateWorkerOnDoWork(object sender, DoWorkEventArgs doWorkEventArgs) + { + while (!_updateWorker.CancellationPending) + { + if (_waitTime < _stickyTime) + { + Thread.Sleep(100); + continue; + } + + while (_waitTime > 0) + { + Thread.Sleep(50); + _waitTime -= 50; + } + _value = _toStick; + } + } + } +} \ No newline at end of file diff --git a/Artemis/Artemis/ViewModels/EffectsViewModel.cs b/Artemis/Artemis/ViewModels/EffectsViewModel.cs index 4b95996de..4a89893b5 100644 --- a/Artemis/Artemis/ViewModels/EffectsViewModel.cs +++ b/Artemis/Artemis/ViewModels/EffectsViewModel.cs @@ -14,14 +14,14 @@ namespace Artemis.ViewModels private readonly DebugEffectViewModel _debugVm; private readonly TypeHoleViewModel _typeHoleVm; private readonly TypeWaveViewModel _typeWaveVm; - private readonly AmbientLightningEffectViewModel _ambientLightningVm; + //private readonly AmbientLightningEffectViewModel _ambientLightningVm; public EffectsViewModel(MainManager mainManager) { _typeWaveVm = new TypeWaveViewModel(mainManager) {DisplayName = "Type Waves"}; //_typeHoleVm = new TypeHoleViewModel(MainManager) {DisplayName = "Type Holes (NYI)"}; _audioVisualizerVm = new AudioVisualizerViewModel(mainManager) {DisplayName = "Audio Visualization"}; - _ambientLightningVm = new AmbientLightningEffectViewModel(mainManager) {DisplayName = "Ambient Lightning"}; + //_ambientLightningVm = new AmbientLightningEffectViewModel(mainManager) {DisplayName = "Ambient Lightning"}; _debugVm = new DebugEffectViewModel(mainManager) {DisplayName = "Debug Effect"}; } @@ -32,7 +32,7 @@ namespace Artemis.ViewModels ActivateItem(_typeWaveVm); //ActivateItem(_typeHoleVm); ActivateItem(_audioVisualizerVm); - ActivateItem(_ambientLightningVm); + //ActivateItem(_ambientLightningVm); ActivateItem(_debugVm); } } diff --git a/Artemis/Artemis/packages.config b/Artemis/Artemis/packages.config index 0b67a3431..1871717eb 100644 --- a/Artemis/Artemis/packages.config +++ b/Artemis/Artemis/packages.config @@ -14,9 +14,10 @@ - - - + + + + \ No newline at end of file