diff --git a/Artemis/Artemis/Artemis.csproj b/Artemis/Artemis/Artemis.csproj
index ef47f3c4b..16aba318b 100644
--- a/Artemis/Artemis/Artemis.csproj
+++ b/Artemis/Artemis/Artemis.csproj
@@ -147,6 +147,10 @@
..\packages\Hardcodet.NotifyIcon.Wpf.1.0.5\lib\net451\Hardcodet.Wpf.TaskbarNotification.dll
True
+
+ ..\packages\ImageLibrary.2.0.5\lib\net45\Kaliko.ImageLibrary.dll
+ True
+
..\packages\log4net.2.0.5\lib\net45-full\log4net.dll
True
@@ -166,6 +170,18 @@
..\packages\Newtonsoft.Json.8.0.2\lib\net45\Newtonsoft.Json.dll
True
+
+ ..\packages\SharpDX.3.0.1\lib\net45\SharpDX.dll
+ True
+
+
+ ..\packages\SharpDX.Direct3D11.3.0.1\lib\net45\SharpDX.Direct3D11.dll
+ True
+
+
+ ..\packages\SharpDX.DXGI.3.0.1\lib\net45\SharpDX.DXGI.dll
+ True
+
@@ -248,6 +264,12 @@
+
+
+
+ AmbientLightningEffectView.xaml
+
+
AudioVisualization.settings
True
@@ -328,6 +350,7 @@
+
@@ -456,6 +479,10 @@
+
+ Designer
+ MSBuild:Compile
+
MSBuild:Compile
Designer
@@ -529,9 +556,6 @@
PreserveNewest
-
- PreserveNewest
-
diff --git a/Artemis/Artemis/KeyboardProviders/ProviderHelper.cs b/Artemis/Artemis/KeyboardProviders/ProviderHelper.cs
index 966f403d0..0e5483490 100644
--- a/Artemis/Artemis/KeyboardProviders/ProviderHelper.cs
+++ b/Artemis/Artemis/KeyboardProviders/ProviderHelper.cs
@@ -1,6 +1,7 @@
using System.Collections.Generic;
using Artemis.KeyboardProviders.Corsair;
using Artemis.KeyboardProviders.Logitech;
+using Artemis.KeyboardProviders.Razer;
namespace Artemis.KeyboardProviders
{
@@ -11,8 +12,8 @@ namespace Artemis.KeyboardProviders
return new List
{
new Orion(),
- new CorsairRGB()
- //new BlackWidow()
+ new CorsairRGB(),
+ new BlackWidow()
};
}
}
diff --git a/Artemis/Artemis/KeyboardProviders/Razer/BlackWidow.cs b/Artemis/Artemis/KeyboardProviders/Razer/BlackWidow.cs
index 59b3bbd6d..f0f409e11 100644
--- a/Artemis/Artemis/KeyboardProviders/Razer/BlackWidow.cs
+++ b/Artemis/Artemis/KeyboardProviders/Razer/BlackWidow.cs
@@ -3,6 +3,8 @@ using System.Drawing;
using Artemis.KeyboardProviders.Razer.Utilities;
using Corale.Colore.Core;
using Corale.Colore.Razer.Keyboard;
+using ColoreColor = Corale.Colore.Core.Color;
+using KeyboardCustom = Corale.Colore.Razer.Keyboard.Effects.Custom;
namespace Artemis.KeyboardProviders.Razer
{
@@ -22,19 +24,9 @@ namespace Artemis.KeyboardProviders.Razer
return false;
// Some people have Synapse installed, but not a Chroma keyboard, deal with this
- try
- {
- // Create a bitmap to send as a test
- var b = new Bitmap(22, 6);
- var razerArray = RazerUtilities.BitmapColorArray(b, 6, 22);
- Chroma.Instance.Keyboard.SetGrid(razerArray);
- Chroma.Instance.Keyboard.Clear();
- }
- catch (NullReferenceException)
- {
- return false;
- }
- return true;
+ var blackWidowFound = Chroma.Instance.Query(Corale.Colore.Razer.Devices.Blackwidow).Connected;
+ var blackWidowTeFound = Chroma.Instance.Query(Corale.Colore.Razer.Devices.BlackwidowTe).Connected;
+ return (blackWidowFound || blackWidowTeFound);
}
public override void Enable()
@@ -52,7 +44,8 @@ namespace Artemis.KeyboardProviders.Razer
public override void DrawBitmap(Bitmap bitmap)
{
var razerArray = RazerUtilities.BitmapColorArray(bitmap, Height, Width);
- Chroma.Instance.Keyboard.SetGrid(razerArray);
+
+ Chroma.Instance.Keyboard.SetCustom(razerArray);
}
}
}
\ No newline at end of file
diff --git a/Artemis/Artemis/KeyboardProviders/Razer/Utilities/RazerUtilities.cs b/Artemis/Artemis/KeyboardProviders/Razer/Utilities/RazerUtilities.cs
index b0fe17fda..cc33c32d5 100644
--- a/Artemis/Artemis/KeyboardProviders/Razer/Utilities/RazerUtilities.cs
+++ b/Artemis/Artemis/KeyboardProviders/Razer/Utilities/RazerUtilities.cs
@@ -1,25 +1,23 @@
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
-using Color = Corale.Colore.Core.Color;
+using Corale.Colore.Razer.Keyboard.Effects;
namespace Artemis.KeyboardProviders.Razer.Utilities
{
public static class RazerUtilities
{
- public static Color[][] BitmapColorArray(Bitmap b, int height, int width)
+ public static Custom BitmapColorArray(Bitmap b, int height, int width)
{
- var res = new Color[height][];
+ var keyboardGrid = Custom.Create();
if (b.Width > width || b.Height > height)
b = ResizeImage(b, width, height);
- for (var y = 0; y < b.Height - 1; y++)
- {
- res[y] = new Color[width];
- for (var x = 0; x < b.Width - 1; x++)
- res[y][x] = b.GetPixel(x, y);
- }
- return res;
+ for (var y = 0; y < b.Height; y++)
+ for (var x = 0; x < b.Width; x++)
+ keyboardGrid[y, x] = b.GetPixel(x, y);
+
+ return keyboardGrid;
}
///
diff --git a/Artemis/Artemis/Modules/Effects/AmbientLightning/AmbientLightningEffectModel.cs b/Artemis/Artemis/Modules/Effects/AmbientLightning/AmbientLightningEffectModel.cs
new file mode 100644
index 000000000..e1e6d35a1
--- /dev/null
+++ b/Artemis/Artemis/Modules/Effects/AmbientLightning/AmbientLightningEffectModel.cs
@@ -0,0 +1,135 @@
+using System.Collections.Generic;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.IO;
+using System.Linq;
+using System.Windows.Forms;
+using Artemis.Managers;
+using Artemis.Models;
+using Artemis.Utilities;
+using Artemis.Utilities.Keyboard;
+using Kaliko.ImageLibrary;
+using Kaliko.ImageLibrary.Filters;
+
+namespace Artemis.Modules.Effects.AmbientLightning
+{
+ internal class AmbientLightningEffectModel : EffectModel
+ {
+ private KeyboardRectangle _botRect;
+ private List _colors;
+ private List _rectangles;
+ private ScreenCapture _screenCapturer;
+ private KeyboardRectangle _topRect;
+
+ public AmbientLightningEffectModel(MainManager mainManager, AmbientLightningEffectSettings settings)
+ : base(mainManager)
+ {
+ Name = "Ambient Lightning";
+ Settings = settings;
+ Scale = 4;
+ Initialized = false;
+ }
+
+ public int Scale { get; set; }
+
+ public AmbientLightningEffectSettings Settings { get; set; }
+
+ public KeyboardRectangle KeyboardRectangle { get; set; }
+
+ public override void Dispose()
+ {
+ Initialized = false;
+ _screenCapturer = null;
+ }
+
+ public override void Enable()
+ {
+ Initialized = false;
+
+ _colors = new List();
+ _screenCapturer = new ScreenCapture();
+ _topRect = new KeyboardRectangle(MainManager.KeyboardManager.ActiveKeyboard, 0, 0, new List(),
+ LinearGradientMode.Horizontal) {Height = MainManager.KeyboardManager.ActiveKeyboard.Height*Scale/2};
+ _botRect = new KeyboardRectangle(MainManager.KeyboardManager.ActiveKeyboard, 0, 0, new List(),
+ LinearGradientMode.Horizontal);
+
+
+ Initialized = true;
+ }
+
+ public override void Update()
+ {
+ var capture = _screenCapturer.Capture();
+ _rectangles = new List();
+ // Analise the result
+ // Chop the screen into 2 rows and 3 columns
+ var resolution = Screen.PrimaryScreen.Bounds;
+ var blockWidth = resolution.Width/3;
+ var blockHeight = resolution.Height/2;
+ var colorIndex = 0;
+ for (var row = 0; row < 2; row++)
+ {
+ for (var column = 0; column < 3; column++)
+ {
+ var blockBase = new Point(blockWidth*column, blockHeight*row);
+ var samples = new List();
+ // For each block, take samples
+ for (var blockRow = 0; blockRow < 6; blockRow++)
+ {
+ for (var blockColumn = 0; blockColumn < 6; blockColumn++)
+ {
+ var x = blockWidth/6*blockColumn + blockWidth/6/4 + blockBase.X;
+ var y = blockHeight/6*blockRow + blockHeight/6/4 + blockBase.Y;
+ samples.Add(ScreenCapture.GetColor(capture, new Point(x, y)));
+ }
+ }
+
+ // Take the average of the samples
+ var averageR = samples.Sum(s => s.R)/samples.Count;
+ var averageG = samples.Sum(s => s.G)/samples.Count;
+ var averageB = samples.Sum(s => s.B)/samples.Count;
+
+ if (_colors.Count <= colorIndex)
+ _colors.Add(Color.FromArgb(255, averageR, averageG, averageB));
+ else
+ _colors[colorIndex] = Color.FromArgb(255, (averageR + _colors[colorIndex].R * 5) / 6, (averageG + _colors[colorIndex].G * 5) / 6, (averageB + _colors[colorIndex].B * 5) / 6);
+ colorIndex++;
+ }
+ }
+
+ // Put the resulting colors in 6 rectangles, their size differs per keyboard
+ var rectWidth = MainManager.KeyboardManager.ActiveKeyboard.Width/3*Scale;
+ var rectHeight = MainManager.KeyboardManager.ActiveKeyboard.Height/2*Scale;
+ for (var row = 0; row < 2; row++)
+ {
+ for (var column = 0; column < 3; column++)
+ {
+ var rectBase = new Point(rectWidth * column, rectHeight * row);
+ _rectangles.Add(new Rectangle(rectBase.X, rectBase.Y, rectWidth, rectHeight));
+ }
+ }
+ }
+
+ public override Bitmap GenerateBitmap()
+ {
+ var bitmap = MainManager.KeyboardManager.ActiveKeyboard.KeyboardBitmap(Scale);
+ using (var g = Graphics.FromImage(bitmap))
+ {
+ var i = 0;
+ foreach (var rectangle in _rectangles)
+ {
+ g.FillRectangle(new SolidBrush(_colors[i]), rectangle);
+ i++;
+ }
+ }
+
+ var test = new KalikoImage(bitmap);
+ test.ApplyFilter(new GaussianBlurFilter(8f));
+ var ms = new MemoryStream();
+ test.SaveBmp(ms);
+ ms.Position = 0;
+ return new Bitmap(ms);
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Effects/AmbientLightning/AmbientLightningEffectSettings.cs b/Artemis/Artemis/Modules/Effects/AmbientLightning/AmbientLightningEffectSettings.cs
new file mode 100644
index 000000000..70c673008
--- /dev/null
+++ b/Artemis/Artemis/Modules/Effects/AmbientLightning/AmbientLightningEffectSettings.cs
@@ -0,0 +1,37 @@
+using System.Drawing.Drawing2D;
+using Artemis.Models;
+
+namespace Artemis.Modules.Effects.AmbientLightning
+{
+ internal class AmbientLightningEffectSettings : EffectSettings
+ {
+ public AmbientLightningEffectSettings()
+ {
+ Load();
+ }
+
+ public int Width { get; set; }
+ public int Height { get; set; }
+ public bool Rotate { get; set; }
+ public int Scale { get; set; }
+ public LinearGradientMode Type { get; set; }
+
+ public sealed override void Load()
+ {
+ ToDefault();
+ }
+
+ public sealed override void Save()
+ {
+ }
+
+ public sealed override void ToDefault()
+ {
+ Width = 84;
+ Height = 24;
+ Scale = 4;
+ Type = LinearGradientMode.Horizontal;
+ Rotate = true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Effects/AmbientLightning/AmbientLightningEffectView.xaml b/Artemis/Artemis/Modules/Effects/AmbientLightning/AmbientLightningEffectView.xaml
new file mode 100644
index 000000000..55bdfba58
--- /dev/null
+++ b/Artemis/Artemis/Modules/Effects/AmbientLightning/AmbientLightningEffectView.xaml
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Artemis/Artemis/Modules/Effects/AmbientLightning/AmbientLightningEffectView.xaml.cs b/Artemis/Artemis/Modules/Effects/AmbientLightning/AmbientLightningEffectView.xaml.cs
new file mode 100644
index 000000000..266205ccb
--- /dev/null
+++ b/Artemis/Artemis/Modules/Effects/AmbientLightning/AmbientLightningEffectView.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.Modules.Effects.AmbientLightning
+{
+ ///
+ /// Interaction logic for AmbientLightningEffectView.xaml
+ ///
+ public partial class AmbientLightningEffectView : UserControl
+ {
+ public AmbientLightningEffectView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Artemis/Artemis/Modules/Effects/AmbientLightning/AmbientLightningEffectViewModel.cs b/Artemis/Artemis/Modules/Effects/AmbientLightning/AmbientLightningEffectViewModel.cs
new file mode 100644
index 000000000..eb65e08ee
--- /dev/null
+++ b/Artemis/Artemis/Modules/Effects/AmbientLightning/AmbientLightningEffectViewModel.cs
@@ -0,0 +1,32 @@
+using Artemis.Events;
+using Artemis.Managers;
+using Artemis.ViewModels.Abstract;
+using Caliburn.Micro;
+
+namespace Artemis.Modules.Effects.AmbientLightning
+{
+ internal class AmbientLightningEffectViewModel : EffectViewModel, IHandle
+ {
+ public AmbientLightningEffectViewModel(MainManager mainManager)
+ {
+ // Subscribe to main model
+ MainManager = mainManager;
+ MainManager.Events.Subscribe(this);
+
+ // Settings are loaded from file by class
+ EffectSettings = new AmbientLightningEffectSettings();
+
+ // Create effect model and add it to MainManager
+ EffectModel = new AmbientLightningEffectModel(mainManager, (AmbientLightningEffectSettings) EffectSettings);
+ MainManager.EffectManager.EffectModels.Add(EffectModel);
+ }
+
+
+ public static string Name => "Ambient Lightning";
+
+ public void Handle(ActiveEffectChanged message)
+ {
+ NotifyOfPropertyChange(() => EffectEnabled);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/RzChromaSDK64.dll b/Artemis/Artemis/RzChromaSDK64.dll
deleted file mode 100644
index 379eb567e..000000000
Binary files a/Artemis/Artemis/RzChromaSDK64.dll and /dev/null differ
diff --git a/Artemis/Artemis/Utilities/Keyboard/KeyboardRectangle.cs b/Artemis/Artemis/Utilities/Keyboard/KeyboardRectangle.cs
index 523eddd39..362e636b6 100644
--- a/Artemis/Artemis/Utilities/Keyboard/KeyboardRectangle.cs
+++ b/Artemis/Artemis/Utilities/Keyboard/KeyboardRectangle.cs
@@ -177,7 +177,6 @@ namespace Artemis.Utilities.Keyboard
// Apply the devided positions
colorBlend.Positions = positions.ToArray();
-
return colorBlend;
}
diff --git a/Artemis/Artemis/Utilities/ScreenCapture.cs b/Artemis/Artemis/Utilities/ScreenCapture.cs
new file mode 100644
index 000000000..81967b032
--- /dev/null
+++ b/Artemis/Artemis/Utilities/ScreenCapture.cs
@@ -0,0 +1,110 @@
+using System.Drawing;
+using System.IO;
+using SharpDX;
+using SharpDX.Direct3D;
+using SharpDX.Direct3D11;
+using SharpDX.DXGI;
+using Device = SharpDX.Direct3D11.Device;
+using MapFlags = SharpDX.DXGI.MapFlags;
+using Resource = SharpDX.DXGI.Resource;
+using ResultCode = SharpDX.DXGI.ResultCode;
+
+namespace Artemis.Utilities
+{
+ internal class ScreenCapture
+ {
+ private readonly Device _device;
+ private readonly OutputDuplication _duplicatedOutput;
+ private readonly Texture2D _screenTexture;
+ private readonly uint numAdapter = 0; // # of graphics card adapter
+ private readonly uint numOutput = 0; // # of output device (i.e. monitor)
+ private DataStream _dataStream;
+ private Resource _screenResource;
+ private Surface _screenSurface;
+
+ public ScreenCapture()
+ {
+ // Create device and factory
+ _device = new Device(DriverType.Hardware);
+ var factory = new Factory1();
+
+ // Creating CPU-accessible texture resource
+ var texdes = new Texture2DDescription
+ {
+ CpuAccessFlags = CpuAccessFlags.Read,
+ BindFlags = BindFlags.None,
+ Format = Format.B8G8R8A8_UNorm,
+ Height = factory.Adapters1[numAdapter].Outputs[numOutput].Description.DesktopBounds.Bottom,
+ Width = factory.Adapters1[numAdapter].Outputs[numOutput].Description.DesktopBounds.Right,
+ OptionFlags = ResourceOptionFlags.None,
+ MipLevels = 1,
+ ArraySize = 1,
+ SampleDescription =
+ {
+ Count = 1,
+ Quality = 0
+ },
+ Usage = ResourceUsage.Staging
+ };
+ _screenTexture = new Texture2D(_device, texdes);
+
+ // duplicate output stuff
+ var output = new Output1(factory.Adapters1[numAdapter].Outputs[numOutput].NativePointer);
+ _duplicatedOutput = output.DuplicateOutput(_device);
+ _screenResource = null;
+ _dataStream = null;
+ }
+
+ public DataStream Capture()
+ {
+ try
+ {
+ OutputDuplicateFrameInformation duplicateFrameInformation;
+ _duplicatedOutput.AcquireNextFrame(1000, out duplicateFrameInformation, out _screenResource);
+ }
+ catch (SharpDXException e)
+ {
+ if (e.ResultCode.Code == ResultCode.WaitTimeout.Result.Code)
+ return Capture();
+ throw;
+ }
+
+ // copy resource into memory that can be accessed by the CPU
+ _device.ImmediateContext.CopyResource(_screenResource.QueryInterface(),
+ _screenTexture);
+
+ // cast from texture to surface, so we can access its bytes
+ _screenSurface = _screenTexture.QueryInterface();
+
+ // map the resource to access it
+ _screenSurface.Map(MapFlags.Read, out _dataStream);
+
+ // seek within the stream and read one byte
+ _dataStream.Position = 4;
+ _dataStream.ReadByte();
+
+ // free resources
+ _dataStream.Close();
+ _screenSurface.Unmap();
+ _screenSurface.Dispose();
+ _screenResource.Dispose();
+ _duplicatedOutput.ReleaseFrame();
+
+ return _dataStream;
+ }
+
+ ///
+ /// Gets a specific pixel out of the data stream.
+ ///
+ ///
+ /// Given point on the screen.
+ ///
+ public static Color GetColor(DataStream surfaceDataStream, Point position)
+ {
+ var data = new byte[4];
+ surfaceDataStream.Seek(position.Y*1920*4 + position.X*4, SeekOrigin.Begin);
+ surfaceDataStream.Read(data, 0, 4);
+ return Color.FromArgb(255, data[2], data[1], data[0]);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/ViewModels/EffectsViewModel.cs b/Artemis/Artemis/ViewModels/EffectsViewModel.cs
index 1f2b5be68..4b95996de 100644
--- a/Artemis/Artemis/ViewModels/EffectsViewModel.cs
+++ b/Artemis/Artemis/ViewModels/EffectsViewModel.cs
@@ -1,4 +1,5 @@
using Artemis.Managers;
+using Artemis.Modules.Effects.AmbientLightning;
using Artemis.Modules.Effects.AudioVisualizer;
using Artemis.Modules.Effects.Debug;
using Artemis.Modules.Effects.TypeHole;
@@ -13,12 +14,14 @@ namespace Artemis.ViewModels
private readonly DebugEffectViewModel _debugVm;
private readonly TypeHoleViewModel _typeHoleVm;
private readonly TypeWaveViewModel _typeWaveVm;
+ 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"};
_debugVm = new DebugEffectViewModel(mainManager) {DisplayName = "Debug Effect"};
}
@@ -29,6 +32,7 @@ namespace Artemis.ViewModels
ActivateItem(_typeWaveVm);
//ActivateItem(_typeHoleVm);
ActivateItem(_audioVisualizerVm);
+ ActivateItem(_ambientLightningVm);
ActivateItem(_debugVm);
}
}
diff --git a/Artemis/Artemis/packages.config b/Artemis/Artemis/packages.config
index 38ab08916..0b67a3431 100644
--- a/Artemis/Artemis/packages.config
+++ b/Artemis/Artemis/packages.config
@@ -8,11 +8,15 @@
+
+
+
+
\ No newline at end of file