1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-12 21:38:38 +00:00

Merge pull request #73 from SpoinkyNL/development

Dota2
This commit is contained in:
Robert Beekman 2016-03-27 14:36:46 +02:00
commit 5e385d4e3d
63 changed files with 3216 additions and 395 deletions

View File

@ -3,6 +3,8 @@
<configuration>
<configSections>
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<section name="Artemis.Modules.Games.TheDivision.TheDivision" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<section name="Artemis.Modules.Games.Dota2.Dota2" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<section name="Artemis.Modules.Overlays.VolumeDisplay.VolumeDisplay" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<section name="Artemis.Modules.Games.RocketLeague.RocketLeague" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<section name="Artemis.Settings.Offsets" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
@ -22,6 +24,49 @@
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
<userSettings>
<Artemis.Modules.Games.TheDivision.TheDivision>
<setting name="Enabled" serializeAs="String">
<value>True</value>
</setting>
</Artemis.Modules.Games.TheDivision.TheDivision>
<Artemis.Modules.Games.Dota2.Dota2>
<setting name="Enabled" serializeAs="String">
<value>True</value>
</setting>
<setting name="GameDirectory" serializeAs="String">
<value />
</setting>
<setting name="CanCastAbility" serializeAs="String">
<value>True</value>
</setting>
<setting name="ShowHealth" serializeAs="String">
<value>True</value>
</setting>
<setting name="ShowDayCycle" serializeAs="String">
<value>True</value>
</setting>
<setting name="ShowMana" serializeAs="String">
<value>True</value>
</setting>
<setting name="ShowEvents" serializeAs="String">
<value>True</value>
</setting>
<setting name="MainColor" serializeAs="String">
<value>#FFFF0000</value>
</setting>
<setting name="ManaColor" serializeAs="String">
<value>#FF0000FF</value>
</setting>
<setting name="KeyboardLayout" serializeAs="String">
<value>Default</value>
</setting>
<setting name="AbilityReadyColor" serializeAs="String">
<value>#FF00FF00</value>
</setting>
<setting name="AbilityCooldownColor" serializeAs="String">
<value>#FF6A5ACD</value>
</setting>
</Artemis.Modules.Games.Dota2.Dota2>
<Artemis.Modules.Overlays.VolumeDisplay.VolumeDisplay>
<setting name="Enabled" serializeAs="String">
<value>True</value>
@ -243,6 +288,10 @@
<assemblyIdentity name="Autofac" publicKeyToken="17863af14b0044da" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="SharpDX" publicKeyToken="b4dcf0f35e5521f1" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.2.0" newVersion="3.0.2.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>

View File

@ -1,25 +1,25 @@
<Application x:Class="Artemis.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
<Application x:Class="Artemis.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:artemis="clr-namespace:Artemis"
DispatcherUnhandledException="Application_DispatcherUnhandledException"
ShutdownMode="OnExplicitShutdown">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary>
<artemis:ArtemisBootstrapper x:Key="ArtemisBootstrapper" />
</ResourceDictionary>
<!-- MahApps.Metro resource dictionaries. Make sure that all file names are Case Sensitive! -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Colors.xaml" />
<!-- Accent and AppTheme setting -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/Teal.xaml" />
<ResourceDictionary
Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseLight.xaml" />
<ResourceDictionary Source="/Resources/Icons.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
xmlns:artemis="clr-namespace:Artemis"
DispatcherUnhandledException="Application_DispatcherUnhandledException"
ShutdownMode="OnExplicitShutdown">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary>
<artemis:ArtemisBootstrapper x:Key="ArtemisBootstrapper" />
</ResourceDictionary>
<!-- MahApps.Metro resource dictionaries. Make sure that all file names are Case Sensitive! -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Colors.xaml" />
<!-- Accent and AppTheme setting -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/Teal.xaml" />
<ResourceDictionary
Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseLight.xaml" />
<ResourceDictionary Source="/Resources/Icons.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>

View File

@ -1,6 +1,7 @@
using System;
using System.Windows;
using System.Windows.Threading;
using Artemis.Utilities;
using WpfExceptionViewer;
namespace Artemis
@ -12,6 +13,9 @@ namespace Artemis
{
public App()
{
if (!GeneralHelpers.IsRunAsAdministrator())
GeneralHelpers.RunAsAdministrator();
InitializeComponent();
}

View File

@ -39,7 +39,7 @@
<ProductName>Artemis</ProductName>
<PublisherName>Artemis</PublisherName>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.2.0</ApplicationVersion>
<ApplicationVersion>1.0.3.0</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<CreateDesktopShortcut>true</CreateDesktopShortcut>
<PublishWizardCompleted>true</PublishWizardCompleted>
@ -118,6 +118,7 @@
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup />
<ItemGroup>
<Reference Include="Autofac, Version=4.0.0.0, Culture=neutral, PublicKeyToken=17863af14b0044da, processorArchitecture=MSIL">
<HintPath>..\packages\Autofac.4.0.0-rc1-177\lib\net45\Autofac.dll</HintPath>
@ -139,14 +140,18 @@
<HintPath>..\packages\Colore.4.0.0\lib\net35\Corale.Colore.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="CUE.NET, Version=1.0.2.1, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\CUE.NET.1.0.2.1\lib\net45\CUE.NET.dll</HintPath>
<Reference Include="CUE.NET, Version=1.0.2.2, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\CUE.NET.1.0.2.2\lib\net45\CUE.NET.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Hardcodet.Wpf.TaskbarNotification, Version=1.0.5.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Hardcodet.NotifyIcon.Wpf.1.0.5\lib\net451\Hardcodet.Wpf.TaskbarNotification.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Kaliko.ImageLibrary, Version=2.0.4.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ImageLibrary.2.0.5\lib\net45\Kaliko.ImageLibrary.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="log4net, Version=1.2.15.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
<HintPath>..\packages\log4net.2.0.5\lib\net45-full\log4net.dll</HintPath>
<Private>True</Private>
@ -166,6 +171,22 @@
<HintPath>..\packages\Newtonsoft.Json.8.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Screna, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Screna.0.1.3\lib\Screna.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="SharpDX, Version=3.0.2.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
<HintPath>..\packages\SharpDX.3.0.2\lib\net45\SharpDX.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="SharpDX.Direct3D11, Version=3.0.2.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
<HintPath>..\packages\SharpDX.Direct3D11.3.0.2\lib\net45\SharpDX.Direct3D11.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="SharpDX.DXGI, Version=3.0.2.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
<HintPath>..\packages\SharpDX.DXGI.3.0.2\lib\net45\SharpDX.DXGI.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
@ -248,12 +269,21 @@
<Compile Include="Models\EffectModel.cs" />
<Compile Include="Models\EffectSettings.cs" />
<Compile Include="Models\GameSettings.cs" />
<Compile Include="Modules\Effects\AmbientLightning\AmbientLightningEffectModel.cs" />
<Compile Include="Modules\Effects\AmbientLightning\AmbientLightningEffectSettings.cs" />
<Compile Include="Modules\Effects\AmbientLightning\AmbientLightningEffectView.xaml.cs">
<DependentUpon>AmbientLightningEffectView.xaml</DependentUpon>
</Compile>
<Compile Include="Modules\Effects\AmbientLightning\AmbientLightningEffectViewModel.cs" />
<Compile Include="Modules\Effects\AmbientLightning\ScreenCapture.cs" />
<Compile Include="Modules\Effects\AudioVisualizer\AudioVisualization.Designer.cs">
<DependentUpon>AudioVisualization.settings</DependentUpon>
<AutoGen>True</AutoGen>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<Compile Include="Modules\Effects\AudioVisualizer\AudioVisualizerModel.cs" />
<Compile Include="Modules\Effects\AudioVisualizer\Utilities\FftEventArgs.cs" />
<Compile Include="Modules\Effects\AudioVisualizer\Utilities\SampleAggregator.cs" />
<Compile Include="Modules\Effects\Debug\DebugEffectModel.cs" />
<Compile Include="Modules\Effects\TypeHole\TypeHoleModel.cs" />
<Compile Include="Modules\Effects\TypeWave\TypeWave.Designer.cs">
@ -270,12 +300,32 @@
</Compile>
<Compile Include="Modules\Games\CounterStrike\CounterStrikeModel.cs" />
<Compile Include="Modules\Games\CounterStrike\CounterStrikeSettings.cs" />
<Compile Include="Modules\Games\Dota2\Dota2.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
<DependentUpon>Dota2.settings</DependentUpon>
</Compile>
<Compile Include="Modules\Games\Dota2\Dota2DataModel.cs" />
<Compile Include="Modules\Games\Dota2\Dota2Model.cs" />
<Compile Include="Modules\Games\Dota2\Dota2Settings.cs" />
<Compile Include="Modules\Games\RocketLeague\RocketLeague.Designer.cs">
<DependentUpon>RocketLeague.settings</DependentUpon>
<AutoGen>True</AutoGen>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<Compile Include="Modules\Games\RocketLeague\RocketLeagueModel.cs" />
<Compile Include="Modules\Games\TheDivision\TheDivision.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
<DependentUpon>TheDivision.settings</DependentUpon>
</Compile>
<Compile Include="Modules\Games\TheDivision\TheDivisionDataModel.cs" />
<Compile Include="Modules\Games\TheDivision\TheDivisionModel.cs" />
<Compile Include="Modules\Games\TheDivision\TheDivisionSettings.cs" />
<Compile Include="Modules\Games\TheDivision\TheDivisionView.xaml.cs">
<DependentUpon>TheDivisionView.xaml</DependentUpon>
</Compile>
<Compile Include="Modules\Games\TheDivision\TheDivisionViewModel.cs" />
<Compile Include="Modules\Games\Witcher3\Witcher3Settings.cs" />
<Compile Include="Modules\Games\Witcher3\Witcher3.Designer.cs">
<AutoGen>True</AutoGen>
@ -315,13 +365,15 @@
<DesignTimeSharedInput>True</DesignTimeSharedInput>
<DependentUpon>Offsets.settings</DependentUpon>
</Compile>
<Compile Include="Utilities\Audio\FftEventArgs.cs" />
<Compile Include="Utilities\Audio\SampleAggregator.cs" />
<Compile Include="Utilities\ColorHelpers.cs" />
<Compile Include="Utilities\GameState\GameDataReceivedEventArgs.cs" />
<Compile Include="Utilities\GameState\GameStateWebServer.cs" />
<Compile Include="Utilities\GeneralHelpers.cs" />
<Compile Include="Utilities\ImageUtilities.cs" />
<Compile Include="Utilities\Keyboard\KeyboardHook.cs" />
<Compile Include="Utilities\LogitechDll\DllManager.cs" />
<Compile Include="Utilities\LogitechDll\NamedPipeServer.cs" />
<Compile Include="Utilities\LogitechDll\PipeServer.cs" />
<Compile Include="Utilities\Memory\GamePointer.cs" />
<Compile Include="Utilities\Memory\Memory.cs" />
<Compile Include="Utilities\Memory\MemoryHelpers.cs" />
@ -329,6 +381,7 @@
<Compile Include="Utilities\Keyboard\Key.cs" />
<Compile Include="Utilities\Keyboard\KeyboardRectangle.cs" />
<Compile Include="Utilities\ShellLink.cs" />
<Compile Include="Utilities\StickyValue.cs" />
<Compile Include="Utilities\Updater.cs" />
<Compile Include="ViewModels\Abstract\EffectViewModel.cs" />
<Compile Include="ViewModels\Abstract\GameViewModel.cs" />
@ -405,6 +458,7 @@
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<None Include="Modules\Effects\AudioVisualizer\AudioVisualization.settings">
<Generator>SettingsSingleFileGenerator</Generator>
@ -418,10 +472,18 @@
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>CounterStrike.Designer.cs</LastGenOutput>
</None>
<None Include="Modules\Games\Dota2\Dota2.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Dota2.Designer.cs</LastGenOutput>
</None>
<None Include="Modules\Games\RocketLeague\RocketLeague.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>RocketLeague.Designer.cs</LastGenOutput>
</None>
<None Include="Modules\Games\TheDivision\TheDivision.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>TheDivision.Designer.cs</LastGenOutput>
</None>
<None Include="Modules\Games\Witcher3\Witcher3.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Witcher3.Designer.cs</LastGenOutput>
@ -440,6 +502,8 @@
</Content>
<Resource Include="Resources\logo.ico" />
<Resource Include="Resources\logo-disabled.ico" />
<Resource Include="Resources\Dota2\dotaGamestateConfiguration.txt" />
<None Include="Resources\LogitechLED.dll" />
<Content Include="Resources\Witcher3\playerWitcher.txt" />
<Content Include="Resources\Witcher3\artemis.txt" />
<Resource Include="Resources\Entypo.ttf" />
@ -456,6 +520,14 @@
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<Page Include="Modules\Effects\AmbientLightning\AmbientLightningEffectView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Modules\Games\TheDivision\TheDivisionView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Resources\Icons.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
@ -529,10 +601,7 @@
<Content Include="LogitechLedEnginesWrapper.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="RzChromaSDK64.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Resources\CounterStrike\gamestateConfiguration.txt" />
<Content Include="Resources\CounterStrike\csgoGamestateConfiguration.txt" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.5.2">
@ -546,13 +615,14 @@
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\packages\CUE.NET.1.0.2.1\build\net45\CUE.NET.targets" Condition="Exists('..\packages\CUE.NET.1.0.2.1\build\net45\CUE.NET.targets')" />
<Import Project="..\packages\CUE.NET.1.0.2.2\build\net45\CUE.NET.targets" Condition="Exists('..\packages\CUE.NET.1.0.2.2\build\net45\CUE.NET.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\CUE.NET.1.0.2.1\build\net45\CUE.NET.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\CUE.NET.1.0.2.1\build\net45\CUE.NET.targets'))" />
<Error Condition="!Exists('..\packages\CUE.NET.1.0.2.2\build\net45\CUE.NET.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\CUE.NET.1.0.2.2\build\net45\CUE.NET.targets'))" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.

View File

@ -2,6 +2,8 @@
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;
@ -16,6 +18,7 @@ namespace Artemis
public ArtemisBootstrapper()
{
CheckDuplicateInstances();
Initialize();
}

View File

@ -3,8 +3,11 @@ using System.Drawing;
using System.Threading;
using Artemis.Utilities;
using CUE.NET;
using CUE.NET.Brushes;
using CUE.NET.Devices.Generic.Enums;
using CUE.NET.Devices.Headset;
using CUE.NET.Devices.Keyboard;
using CUE.NET.Devices.Mouse;
using CUE.NET.Exceptions;
namespace Artemis.KeyboardProviders.Corsair
@ -12,7 +15,6 @@ namespace Artemis.KeyboardProviders.Corsair
internal class CorsairRGB : KeyboardProvider
{
private CorsairKeyboard _keyboard;
public CorsairRGB()
{
Name = "Corsair RGB Keyboards";
@ -67,39 +69,44 @@ namespace Artemis.KeyboardProviders.Corsair
/*CUE is already initialized*/
}
_keyboard = CueSDK.KeyboardSDK;
switch (_keyboard.DeviceInfo.Model)
{
case "K95 RGB":
Height = 7;
Width = 24;
KeyboardRegions.Add(new KeyboardRegion("TopRow", new Point(1, 0), new Point(1, 20)));
Width = 25;
KeyboardRegions.Add(new KeyboardRegion("TopRow", new Point(0, 1), new Point(20, 1)));
KeyboardRegions.Add(new KeyboardRegion("NumPad", new Point(21, 2), new Point(25, 7)));
KeyboardRegions.Add(new KeyboardRegion("QWER", new Point(5, 3), new Point(8, 3)));
break;
case "K70 RGB":
Height = 7;
Width = 21;
KeyboardRegions.Add(new KeyboardRegion("TopRow", new Point(1, 0), new Point(1, 16)));
KeyboardRegions.Add(new KeyboardRegion("TopRow", new Point(0, 1), new Point(18, 1)));
KeyboardRegions.Add(new KeyboardRegion("NumPad", new Point(17, 2), new Point(21, 7)));
KeyboardRegions.Add(new KeyboardRegion("QWER", new Point(2, 3), new Point(5, 3)));
break;
case "K65 RGB":
Height = 7;
Width = 18;
KeyboardRegions.Add(new KeyboardRegion("TopRow", new Point(0, 1), new Point(18, 1)));
KeyboardRegions.Add(new KeyboardRegion("NumPad", new Point(17, 2), new Point(20, 7)));
KeyboardRegions.Add(new KeyboardRegion("QWER", new Point(2, 3), new Point(5, 3)));
break;
case "STRAFE RGB":
Height = 7;
KeyboardRegions.Add(new KeyboardRegion("TopRow", new Point(1, 0), new Point(1, 16)));
Height = 6;
KeyboardRegions.Add(new KeyboardRegion("TopRow", new Point(0, 1), new Point(18, 1)));
KeyboardRegions.Add(new KeyboardRegion("NumPad", new Point(18, 2), new Point(22, 7)));
KeyboardRegions.Add(new KeyboardRegion("QWER", new Point(1, 3), new Point(4, 3)));
Width = 22;
break;
}
// _keyboard.UpdateMode = UpdateMode.Manual;
_keyboard.Update(true);
}
public override void Disable()
{
CueSDK.Reinitialize();
}
/// <summary>
/// Properly resizes any size bitmap to the keyboard by creating a rectangle whose size is dependent on the bitmap
/// size.
@ -107,21 +114,21 @@ namespace Artemis.KeyboardProviders.Corsair
/// <param name="bitmap"></param>
public override void DrawBitmap(Bitmap bitmap)
{
using (
var resized = ImageUtilities.ResizeImage(bitmap,
(int) _keyboard.KeyboardRectangle.Width,
(int) _keyboard.KeyboardRectangle.Height)
)
var fixedBmp = new Bitmap(bitmap.Width, bitmap.Height);
using (var g = Graphics.FromImage(fixedBmp))
{
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;
}
g.Clear(Color.Black);
g.DrawImage(bitmap, 0,0);
}
_keyboard.Update(true);
var fixedImage = ImageUtilities.ResizeImage(fixedBmp, Width, Height);
var brush = new ImageBrush
{
Image = fixedImage
};
_keyboard.Brush = brush;
_keyboard.Update();
}
}
}

View File

@ -14,5 +14,7 @@ namespace Artemis.KeyboardProviders
public string RegionName { get; set; }
public Point TopLeft { get; set; }
public Point BottomRight { get; set; }
public Rectangle GetRectangle() => new Rectangle(TopLeft.X, TopLeft.Y, BottomRight.X - TopLeft.X, BottomRight.Y - TopLeft.Y);
}
}

View File

@ -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
{
@ -10,23 +14,28 @@ namespace Artemis.KeyboardProviders.Logitech
public Orion()
{
Name = "Logitech G910 RGB";
CantEnableText = "Couldn't connect to your Logitech G910.\n " +
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;
KeyboardRegions = new List<KeyboardRegion> {new KeyboardRegion("TopRow", new Point(0, 0), new Point(0, 16))};
KeyboardRegions = new List<KeyboardRegion>
{
new KeyboardRegion("TopRow", new Point(0, 0), new Point(18, 0)),
new KeyboardRegion("NumPad", new Point(17, 1), new Point(21, 6)),
new KeyboardRegion("QWER", new Point(2, 2), new Point(5, 2))
};
}
public override bool CanEnable()
{
//if (DllManager.RestoreDll())
// RestoreDll();
int majorNum = 0, minorNum = 0, buildNum = 0;
LogitechGSDK.LogiLedInit();
LogitechGSDK.LogiLedSetLightingForKeyWithKeyName(KeyboardNames.A, 100, 100, 100);
LogitechGSDK.LogiLedGetSdkVersion(ref majorNum, ref minorNum, ref buildNum);
LogitechGSDK.LogiLedRestoreLighting();
LogitechGSDK.LogiLedShutdown();
// Turn it into one long number...
@ -34,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

View File

@ -68,7 +68,7 @@ namespace Artemis.KeyboardProviders.Logitech.Utilities
int greenPercentage, int bluePercentage);
[DllImport("LogitechLedEnginesWrapper ", CallingConvention = CallingConvention.Cdecl)]
public static extern bool LogiLedSetLightingForKeyWithKeyName(KeyboardNames keyCode, int redPercentage,
public static extern bool LogiLedSetLightingForKeyWithKeyName(int keyCode, int redPercentage,
int greenPercentage, int bluePercentage);
[DllImport("LogitechLedEnginesWrapper ", CallingConvention = CallingConvention.Cdecl)]

View File

@ -7,7 +7,149 @@ namespace Artemis.KeyboardProviders.Logitech.Utilities
{
public static class OrionUtilities
{
public static byte[] BitmapToByteArray(Bitmap b)
public static KeyMapping[] Keymappings =
{
// First row
new KeyMapping(0, 0),
new KeyMapping(1, 1),
new KeyMapping(2, 1),
new KeyMapping(3, 2),
new KeyMapping(4, 3),
new KeyMapping(5, 4),
new KeyMapping(6, 5),
new KeyMapping(7, 6),
new KeyMapping(8, 7),
new KeyMapping(9, 8),
new KeyMapping(10, 9),
new KeyMapping(11, 9),
new KeyMapping(12, 10),
new KeyMapping(13, 11),
new KeyMapping(13, 12),
new KeyMapping(14, 13),
new KeyMapping(15, 14),
new KeyMapping(16, 15),
new KeyMapping(17, 16),
new KeyMapping(18, 17),
new KeyMapping(19, 18),
// Second row
new KeyMapping(21, 21),
new KeyMapping(22, 22),
new KeyMapping(23, 23),
new KeyMapping(24, 24),
new KeyMapping(25, 25),
new KeyMapping(26, 26),
new KeyMapping(27, 27),
new KeyMapping(28, 28),
new KeyMapping(29, 29),
new KeyMapping(30, 30),
new KeyMapping(31, 31),
new KeyMapping(32, 32),
new KeyMapping(33, 33),
new KeyMapping(34, 34),
new KeyMapping(35, 35),
new KeyMapping(36, 36),
new KeyMapping(37, 37),
new KeyMapping(38, 38),
new KeyMapping(39, 39),
new KeyMapping(40, 40),
new KeyMapping(41, 41),
// Third row
new KeyMapping(42, 42),
new KeyMapping(43, 43),
new KeyMapping(44, 44),
new KeyMapping(45, 45),
new KeyMapping(46, 46),
new KeyMapping(47, 46),
new KeyMapping(48, 47),
new KeyMapping(49, 48),
new KeyMapping(50, 49),
new KeyMapping(51, 50),
new KeyMapping(52, 51),
new KeyMapping(53, 52),
new KeyMapping(54, 53),
new KeyMapping(54, 54),
new KeyMapping(55, 55),
new KeyMapping(56, 56),
new KeyMapping(57, 57),
new KeyMapping(58, 58),
new KeyMapping(59, 59),
new KeyMapping(60, 60),
new KeyMapping(61, 61),
new KeyMapping(62, 62),
// Fourth row
new KeyMapping(63, 63),
new KeyMapping(64, 64),
new KeyMapping(65, 65),
new KeyMapping(66, 65),
new KeyMapping(67, 66),
new KeyMapping(68, 67),
new KeyMapping(69, 68),
new KeyMapping(70, 69),
new KeyMapping(71, 70),
new KeyMapping(72, 71),
new KeyMapping(73, 72),
new KeyMapping(74, 73),
new KeyMapping(75, 74),
new KeyMapping(76, 75),
new KeyMapping(76, 76),
new KeyMapping(78, 77),
new KeyMapping(79, 78),
new KeyMapping(79, 79),
new KeyMapping(80, 80),
new KeyMapping(81, 81),
new KeyMapping(82, 82),
// Fifth row
new KeyMapping(84, 84),
new KeyMapping(85, 85),
new KeyMapping(86, 86),
new KeyMapping(87, 87),
new KeyMapping(88, 88),
new KeyMapping(89, 89),
new KeyMapping(90, 90),
new KeyMapping(91, 91),
new KeyMapping(92, 92),
new KeyMapping(93, 93),
new KeyMapping(94, 94),
new KeyMapping(95, 95),
new KeyMapping(96, 96),
new KeyMapping(97, 97),
new KeyMapping(98, 98),
new KeyMapping(99, 99),
new KeyMapping(100, 100),
new KeyMapping(101, 101),
new KeyMapping(102, 102),
new KeyMapping(103, 103),
new KeyMapping(104, 104),
// Sixth row
new KeyMapping(105, 105),
new KeyMapping(106, 106),
new KeyMapping(107, 107),
new KeyMapping(108, 107),
new KeyMapping(109, 109),
new KeyMapping(110, 110),
new KeyMapping(111, 110),
new KeyMapping(112, 111),
new KeyMapping(113, 112),
new KeyMapping(114, 113),
new KeyMapping(115, 114),
new KeyMapping(116, 115),
new KeyMapping(115, 116), // ALTGR
new KeyMapping(116, 117),
new KeyMapping(117, 118),
new KeyMapping(118, 119),
new KeyMapping(119, 120),
new KeyMapping(120, 121),
new KeyMapping(121, 122),
new KeyMapping(122, 123),
new KeyMapping(124, 124),
};
public static byte[] BitmapToByteArray(Bitmap b, bool remap = true)
{
if (b.Width > 21 || b.Height > 6)
b = ResizeImage(b, 21, 6);
@ -22,7 +164,23 @@ namespace Artemis.KeyboardProviders.Logitech.Utilities
// Copy data from pointer to array
Marshal.Copy(iptr, pixels, 0, pixels.Length);
return pixels;
if (!remap)
return pixels;
var remapped = new byte[pixels.Length];
// Every key is 4 bytes
for (var i = 0; i <= pixels.Length /4; i++)
{
var firstSByte = Keymappings[i].Source * 4;
var firstTByte = Keymappings[i].Target * 4;
for (var j = 0; j < 4; j++)
remapped[firstTByte + j] = pixels[firstSByte + j];
}
return remapped;
}
/// <summary>
@ -56,5 +214,17 @@ namespace Artemis.KeyboardProviders.Logitech.Utilities
return destImage;
}
public struct KeyMapping
{
public KeyMapping(int source, int target)
{
Source = source;
Target = target;
}
public int Source { get; set; }
public int Target { get; set; }
}
}
}

View File

@ -1,6 +1,7 @@
using System.Collections.Generic;
using Artemis.KeyboardProviders.Corsair;
using Artemis.KeyboardProviders.Logitech;
using Artemis.KeyboardProviders.Razer;
namespace Artemis.KeyboardProviders
{
@ -10,9 +11,9 @@ namespace Artemis.KeyboardProviders
{
return new List<KeyboardProvider>
{
new CorsairRGB(),
new Orion(),
new CorsairRGB()
//new BlackWidow()
new BlackWidow()
};
}
}

View File

@ -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()
@ -42,6 +34,10 @@ namespace Artemis.KeyboardProviders.Razer
Chroma.Instance.Initialize();
Height = Constants.MaxRows;
Width = Constants.MaxColumns;
KeyboardRegions.Add(new KeyboardRegion("TopRow", new Point(0, 0), new Point(19, 0)));
KeyboardRegions.Add(new KeyboardRegion("NumPad", new Point(20, 1), new Point(23, 6)));
KeyboardRegions.Add(new KeyboardRegion("QWER", new Point(2, 2), new Point(5, 2)));
}
public override void Disable()
@ -52,7 +48,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);
}
}
}

View File

@ -1,57 +1,24 @@
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using Color = Corale.Colore.Core.Color;
using Artemis.Utilities;
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);
b = ImageUtilities.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);
/// <summary>
/// Resize the image to the specified width and height.
/// </summary>
/// <param name="image">The image to resize.</param>
/// <param name="width">The width to resize to.</param>
/// <param name="height">The height to resize to.</param>
/// <returns>The resized image.</returns>
public static Bitmap ResizeImage(Image image, int width, int height)
{
var destRect = new Rectangle(0, 0, width, height);
var destImage = new Bitmap(width, height);
destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
using (var graphics = Graphics.FromImage(destImage))
{
graphics.CompositingMode = CompositingMode.SourceCopy;
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
using (var wrapMode = new ImageAttributes())
{
wrapMode.SetWrapMode(WrapMode.TileFlipXY);
graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode);
}
}
return destImage;
return keyboardGrid;
}
}
}

View File

@ -2,11 +2,13 @@
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Windows.Forms;
using Artemis.Events;
using Artemis.Models;
using Artemis.Services;
using Artemis.Utilities.GameState;
using Artemis.Utilities.Keyboard;
using Artemis.Utilities.LogitechDll;
using Caliburn.Micro;
namespace Artemis.Managers
@ -47,8 +49,13 @@ namespace Artemis.Managers
// Create and start the web server
GameStateWebServer = new GameStateWebServer();
GameStateWebServer.Start();
// Start the named pipe
//PipeServer = new PipeServer();
//PipeServer.Start("artemis");
}
public PipeServer PipeServer { get; set; }
public BackgroundWorker UpdateWorker { get; set; }
public BackgroundWorker ProcessWorker { get; set; }
@ -65,6 +72,7 @@ namespace Artemis.Managers
public bool Suspended { get; set; }
public bool Running { get; private set; }
public event PauseCallbackHandler PauseCallback;
/// <summary>
@ -112,8 +120,15 @@ namespace Artemis.Managers
private void FinishStop(object sender, RunWorkerCompletedEventArgs e)
{
UpdateWorker.RunWorkerCompleted -= FinishStop;
KeyboardManager.ReleaseActiveKeyboard();
Running = false;
if (e.Error != null || !_restarting)
return;
Start();
_restarting = false;
}
public void Pause()
@ -137,7 +152,9 @@ namespace Artemis.Managers
{
Stop();
ProcessWorker.CancelAsync();
ProcessWorker.CancelAsync();
GameStateWebServer.Stop();
//NamedPipeServer.StopServer();
}
public void Restart()
@ -151,23 +168,9 @@ namespace Artemis.Managers
}
_restarting = true;
UpdateWorker.RunWorkerCompleted += FinishRestart;
Stop();
}
public void FinishRestart(object sender, RunWorkerCompletedEventArgs e)
{
UpdateWorker.RunWorkerCompleted -= FinishRestart;
if (e.Error != null)
return;
Start();
_restarting = false;
}
/// <summary>
/// Loads the last active effect and starts the program
/// </summary>
@ -278,12 +281,12 @@ namespace Artemis.Managers
// If the currently active effect is a no longer running game, get rid of it.
var activeGame = EffectManager.ActiveEffect as GameModel;
if (activeGame != null)
if (runningProcesses.All(p => p.ProcessName != activeGame.ProcessName))
if (!runningProcesses.Any(p => p.ProcessName == activeGame.ProcessName && p.HasExited == false))
EffectManager.DisableGame(activeGame);
// Look for running games, stopping on the first one that's found.
var newGame = EffectManager.EnabledGames
.FirstOrDefault(g => runningProcesses.Any(p => p.ProcessName == g.ProcessName));
.FirstOrDefault(g => runningProcesses.Any(p => p.ProcessName == g.ProcessName && p.HasExited == false));
// If it's not already enabled, do so.
if (newGame != null && EffectManager.ActiveEffect != newGame)

View File

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Artemis.Models
{
public class GamePointersCollectionModel
{
public string Game { get; set; }
public string GameVersion { get; set; }
public List<GamePointer> GameAddresses { get; set; }
}
public class GamePointer
{
public string Description { get; set; }
public IntPtr BasePointer { get; set; }
public int[] Offsets { get; set; }
public override string ToString()
{
return Offsets.Aggregate(BasePointer.ToString("X"),
(current, offset) => current + $"+{offset.ToString("X")}");
}
}
}

View File

@ -0,0 +1,139 @@
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<Color> _colors;
private List<Rectangle> _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.Dispose();
_screenCapturer = null;
}
public override void Enable()
{
Initialized = false;
_colors = new List<Color>();
_screenCapturer = new ScreenCapture();
_topRect = new KeyboardRectangle(MainManager.KeyboardManager.ActiveKeyboard, 0, 0, new List<Color>(),
LinearGradientMode.Horizontal) {Height = MainManager.KeyboardManager.ActiveKeyboard.Height*Scale/2};
_botRect = new KeyboardRectangle(MainManager.KeyboardManager.ActiveKeyboard, 0, 0, new List<Color>(),
LinearGradientMode.Horizontal);
Initialized = true;
}
public override void Update()
{
var capture = _screenCapturer.Capture();
if (capture == null)
return;
_rectangles = new List<Rectangle>();
// 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<Color>();
// 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(_screenCapturer.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);
}
}
}

View File

@ -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;
}
}
}

View File

@ -0,0 +1,55 @@
<UserControl x:Class="Artemis.Modules.Effects.AmbientLightning.AmbientLightningEffectView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Artemis.Modules.Effects.AmbientLightning"
xmlns:cal="http://www.caliburnproject.org"
xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
mc:Ignorable="d"
d:DesignHeight="475.392" d:DesignWidth="583.577">
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
<Grid Margin="15, 5, 15, 5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Margin="0,0,1,0">
<Label FontSize="20" MaxWidth="500" HorizontalAlignment="Left">
<Label.Content>
<AccessText TextWrapping="Wrap"
Text="Colors the keyboard according to what is on screen" />
</Label.Content>
</Label>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Label Content="Enable effect" Margin="0 3 0 0" HorizontalAlignment="Right" />
<ToggleButton x:Name="EffectEnabled" Margin="0 3 0 0" Width="25" Height="25"
Style="{DynamicResource MetroCircleToggleButtonStyle}"
cal:Message.Attach="[Event Click] = [Action ToggleEffect]"
ToolTip="Note: You can't enable an effect when Artemis is disabled"
ToolTipService.ShowOnDisabled="True" />
</StackPanel>
</StackPanel>
<!-- Buttons -->
<StackPanel Grid.Column="0" Grid.Row="8" Orientation="Horizontal" VerticalAlignment="Bottom">
<Button x:Name="ResetSettings" Content="Reset effect" VerticalAlignment="Top" Width="100"
Style="{DynamicResource SquareButtonStyle}" />
<Button x:Name="SaveSettings" Content="Save changes" VerticalAlignment="Top" Width="100"
Margin="10,0,0,0"
Style="{DynamicResource SquareButtonStyle}" />
</StackPanel>
</Grid>
</ScrollViewer>
</UserControl>

View File

@ -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
{
/// <summary>
/// Interaction logic for AmbientLightningEffectView.xaml
/// </summary>
public partial class AmbientLightningEffectView : UserControl
{
public AmbientLightningEffectView()
{
InitializeComponent();
}
}
}

View File

@ -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<ActiveEffectChanged>
{
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);
}
}
}

View File

@ -0,0 +1,125 @@
// Original code by Florian Schnell
// http://www.floschnell.de/computer-science/super-fast-screen-capture-with-windows-8.html
using System;
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.Modules.Effects.AmbientLightning
{
internal class ScreenCapture : IDisposable
{
private readonly Device _device;
private readonly Factory1 _factory;
private readonly Texture2D _screenTexture;
private DataStream _dataStream;
private OutputDuplication _duplicatedOutput;
private Resource _screenResource;
private Surface _screenSurface;
public ScreenCapture()
{
// Create device and factory
_device = new Device(DriverType.Hardware);
_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[0].Outputs[0].Description.DesktopBounds.Bottom,
Width = _factory.Adapters1[0].Outputs[0].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[0].Outputs[0].NativePointer);
_duplicatedOutput = output.DuplicateOutput(_device);
_screenResource = null;
_dataStream = null;
}
public void Dispose()
{
_duplicatedOutput.Dispose();
_screenResource.Dispose();
_dataStream.Dispose();
_factory.Dispose();
}
public DataStream Capture()
{
try
{
OutputDuplicateFrameInformation duplicateFrameInformation;
_duplicatedOutput.AcquireNextFrame(1000, out duplicateFrameInformation, out _screenResource);
}
catch (SharpDXException e)
{
if (e.ResultCode.Code == ResultCode.WaitTimeout.Result.Code ||
e.ResultCode.Code == ResultCode.AccessDenied.Result.Code ||
e.ResultCode.Code == ResultCode.AccessLost.Result.Code)
return null;
throw;
}
// copy resource into memory that can be accessed by the CPU
_device.ImmediateContext.CopyResource(_screenResource.QueryInterface<SharpDX.Direct3D11.Resource>(),
_screenTexture);
// cast from texture to surface, so we can access its bytes
_screenSurface = _screenTexture.QueryInterface<Surface>();
// 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;
}
/// <summary>
/// Gets a specific pixel out of the data stream.
/// </summary>
/// <param name="surfaceDataStream"></param>
/// <param name="position">Given point on the screen.</param>
/// <returns></returns>
public Color GetColor(DataStream surfaceDataStream, Point position)
{
var data = new byte[4];
surfaceDataStream.Seek(
position.Y*_factory.Adapters1[0].Outputs[0].Description.DesktopBounds.Right*4 + position.X*4,
SeekOrigin.Begin);
surfaceDataStream.Read(data, 0, 4);
return Color.FromArgb(255, data[2], data[1], data[0]);
}
}
}

View File

@ -5,8 +5,8 @@ using System.Drawing.Drawing2D;
using System.Linq;
using Artemis.Managers;
using Artemis.Models;
using Artemis.Modules.Effects.AudioVisualizer.Utilities;
using Artemis.Utilities;
using Artemis.Utilities.Audio;
using Artemis.Utilities.Keyboard;
using NAudio.CoreAudioApi;
using NAudio.Wave;
@ -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;

View File

@ -1,8 +1,8 @@
using System;
using System.Diagnostics;
using NAudio.Dsp;
namespace Artemis.Utilities.Audio
using System;
using System.Diagnostics;
using NAudio.Dsp;
namespace Artemis.Modules.Effects.AudioVisualizer.Utilities
{
public class FftEventArgs : EventArgs
{

View File

@ -1,7 +1,7 @@
using System;
using NAudio.Dsp;
namespace Artemis.Utilities.Audio
using System;
using NAudio.Dsp;
namespace Artemis.Modules.Effects.AudioVisualizer.Utilities
{ // The Complex and FFT are here!
public class SampleAggregator

View File

@ -44,7 +44,7 @@ namespace Artemis.Modules.Games.CounterStrike
return;
if (Directory.Exists(((CounterStrikeSettings) GameSettings).GameDirectory + "/csgo/cfg"))
{
var cfgFile = Resources.gamestateConfiguration.Replace("{{port}}",
var cfgFile = Resources.csgoGamestateConfiguration.Replace("{{port}}",
MainManager.GameStateWebServer.Port.ToString());
File.WriteAllText(
((CounterStrikeSettings) GameSettings).GameDirectory + "/csgo/cfg/gamestate_integration_artemis.cfg",

View File

@ -0,0 +1,170 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Artemis.Modules.Games.Dota2 {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")]
internal sealed partial class Dota2 : global::System.Configuration.ApplicationSettingsBase {
private static Dota2 defaultInstance = ((Dota2)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Dota2())));
public static Dota2 Default {
get {
return defaultInstance;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("True")]
public bool Enabled {
get {
return ((bool)(this["Enabled"]));
}
set {
this["Enabled"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("")]
public string GameDirectory {
get {
return ((string)(this["GameDirectory"]));
}
set {
this["GameDirectory"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("True")]
public bool CanCastAbility {
get {
return ((bool)(this["CanCastAbility"]));
}
set {
this["CanCastAbility"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("True")]
public bool ShowHealth {
get {
return ((bool)(this["ShowHealth"]));
}
set {
this["ShowHealth"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("True")]
public bool ShowDayCycle {
get {
return ((bool)(this["ShowDayCycle"]));
}
set {
this["ShowDayCycle"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("True")]
public bool ShowMana {
get {
return ((bool)(this["ShowMana"]));
}
set {
this["ShowMana"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("True")]
public bool ShowEvents {
get {
return ((bool)(this["ShowEvents"]));
}
set {
this["ShowEvents"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("#FFFF0000")]
public global::System.Windows.Media.Color MainColor {
get {
return ((global::System.Windows.Media.Color)(this["MainColor"]));
}
set {
this["MainColor"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("#FF0000FF")]
public global::System.Windows.Media.Color ManaColor {
get {
return ((global::System.Windows.Media.Color)(this["ManaColor"]));
}
set {
this["ManaColor"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("Default")]
public string KeyboardLayout {
get {
return ((string)(this["KeyboardLayout"]));
}
set {
this["KeyboardLayout"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("#FF00FF00")]
public global::System.Windows.Media.Color AbilityReadyColor {
get {
return ((global::System.Windows.Media.Color)(this["AbilityReadyColor"]));
}
set {
this["AbilityReadyColor"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("#FF6A5ACD")]
public global::System.Windows.Media.Color AbilityCooldownColor {
get {
return ((global::System.Windows.Media.Color)(this["AbilityCooldownColor"]));
}
set {
this["AbilityCooldownColor"] = value;
}
}
}
}

View File

@ -0,0 +1,42 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="Artemis.Modules.Games.Dota2" GeneratedClassName="Dota2">
<Profiles />
<Settings>
<Setting Name="Enabled" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
<Setting Name="GameDirectory" Type="System.String" Scope="User">
<Value Profile="(Default)" />
</Setting>
<Setting Name="CanCastAbility" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
<Setting Name="ShowHealth" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
<Setting Name="ShowDayCycle" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
<Setting Name="ShowMana" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
<Setting Name="ShowEvents" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
<Setting Name="MainColor" Type="System.Windows.Media.Color" Scope="User">
<Value Profile="(Default)">#FFFF0000</Value>
</Setting>
<Setting Name="ManaColor" Type="System.Windows.Media.Color" Scope="User">
<Value Profile="(Default)">#FF0000FF</Value>
</Setting>
<Setting Name="KeyboardLayout" Type="System.String" Scope="User">
<Value Profile="(Default)">Default</Value>
</Setting>
<Setting Name="AbilityReadyColor" Type="System.Windows.Media.Color" Scope="User">
<Value Profile="(Default)">#FF00FF00</Value>
</Setting>
<Setting Name="AbilityCooldownColor" Type="System.Windows.Media.Color" Scope="User">
<Value Profile="(Default)">#FF6A5ACD</Value>
</Setting>
</Settings>
</SettingsFile>

View File

@ -0,0 +1,228 @@
namespace Artemis.Modules.Games.Dota2
{
class Dota2DataModel
{
public class Rootobject
{
public Provider provider { get; set; }
public Map map { get; set; }
public Player player { get; set; }
public Hero hero { get; set; }
public Abilities abilities { get; set; }
public Items items { get; set; }
public Previously previously { get; set; }
}
public class Provider
{
public string name { get; set; }
public int appid { get; set; }
public int version { get; set; }
public int timestamp { get; set; }
}
public class Map
{
public string name { get; set; }
public long matchid { get; set; }
public int game_time { get; set; }
public int clock_time { get; set; }
public bool daytime { get; set; }
public bool nightstalker_night { get; set; }
public string game_state { get; set; }
public string win_team { get; set; }
public string customgamename { get; set; }
public int ward_purchase_cooldown { get; set; }
}
public class Player
{
public string steamid { get; set; }
public string name { get; set; }
public string activity { get; set; }
public int kills { get; set; }
public int deaths { get; set; }
public int assists { get; set; }
public int last_hits { get; set; }
public int denies { get; set; }
public int kill_streak { get; set; }
public string team_name { get; set; }
public int gold { get; set; }
public int gold_reliable { get; set; }
public int gold_unreliable { get; set; }
public int gpm { get; set; }
public int xpm { get; set; }
}
public class Hero
{
public int id { get; set; }
public string name { get; set; }
public int level { get; set; }
public bool alive { get; set; }
public int respawn_seconds { get; set; }
public int buyback_cost { get; set; }
public int buyback_cooldown { get; set; }
public int health { get; set; }
public int max_health { get; set; }
public int health_percent { get; set; }
public int mana { get; set; }
public int max_mana { get; set; }
public int mana_percent { get; set; }
public bool silenced { get; set; }
public bool stunned { get; set; }
public bool disarmed { get; set; }
public bool magicimmune { get; set; }
public bool hexed { get; set; }
public bool muted { get; set; }
public bool _break { get; set; }
public bool has_debuff { get; set; }
}
public class Abilities
{
public Ability0 ability0 { get; set; }
public Ability1 ability1 { get; set; }
public Ability2 ability2 { get; set; }
public Ability3 ability3 { get; set; }
public Attributes attributes { get; set; }
}
public class Ability0
{
public string name { get; set; }
public int level { get; set; }
public bool can_cast { get; set; }
public bool passive { get; set; }
public bool ability_active { get; set; }
public int cooldown { get; set; }
public bool ultimate { get; set; }
}
public class Ability1
{
public string name { get; set; }
public int level { get; set; }
public bool can_cast { get; set; }
public bool passive { get; set; }
public bool ability_active { get; set; }
public int cooldown { get; set; }
public bool ultimate { get; set; }
}
public class Ability2
{
public string name { get; set; }
public int level { get; set; }
public bool can_cast { get; set; }
public bool passive { get; set; }
public bool ability_active { get; set; }
public int cooldown { get; set; }
public bool ultimate { get; set; }
}
public class Ability3
{
public string name { get; set; }
public int level { get; set; }
public bool can_cast { get; set; }
public bool passive { get; set; }
public bool ability_active { get; set; }
public int cooldown { get; set; }
public bool ultimate { get; set; }
}
public class Attributes
{
public int level { get; set; }
}
public class Items
{
public Slot0 slot0 { get; set; }
public Slot1 slot1 { get; set; }
public Slot2 slot2 { get; set; }
public Slot3 slot3 { get; set; }
public Slot4 slot4 { get; set; }
public Slot5 slot5 { get; set; }
public Stash0 stash0 { get; set; }
public Stash1 stash1 { get; set; }
public Stash2 stash2 { get; set; }
public Stash3 stash3 { get; set; }
public Stash4 stash4 { get; set; }
public Stash5 stash5 { get; set; }
}
public class Slot0
{
public string name { get; set; }
}
public class Slot1
{
public string name { get; set; }
}
public class Slot2
{
public string name { get; set; }
}
public class Slot3
{
public string name { get; set; }
}
public class Slot4
{
public string name { get; set; }
}
public class Slot5
{
public string name { get; set; }
}
public class Stash0
{
public string name { get; set; }
}
public class Stash1
{
public string name { get; set; }
}
public class Stash2
{
public string name { get; set; }
}
public class Stash3
{
public string name { get; set; }
}
public class Stash4
{
public string name { get; set; }
}
public class Stash5
{
public string name { get; set; }
}
public class Previously
{
public Player1 player { get; set; }
}
public class Player1
{
public int gold { get; set; }
public int gold_unreliable { get; set; }
}
}
}

View File

@ -0,0 +1,335 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Windows.Forms.VisualStyles;
using System.Windows.Media;
using Artemis.KeyboardProviders;
using Artemis.Managers;
using Artemis.Models;
using Artemis.Utilities;
using Artemis.Utilities.GameState;
using Artemis.Utilities.Keyboard;
using Newtonsoft.Json;
using Color = System.Drawing.Color;
namespace Artemis.Modules.Games.Dota2
{
internal class Dota2Model : GameModel
{
private KeyboardRegion _keyPad;
private KeyboardRegion _abilityKeys;
private KeyboardRegion _topRow;
public Dota2Model(MainManager mainManager, Dota2Settings settings) : base(mainManager)
{
Settings = settings;
Name = "Dota2";
ProcessName = "dota2";
Enabled = Settings.Enabled;
Initialized = false;
Scale = 4;
}
public override void Dispose()
{
Initialized = false;
MainManager.GameStateWebServer.GameDataReceived -= HandleGameData;
}
public override void Enable()
{
Initialized = false;
_topRow = MainManager.KeyboardManager.ActiveKeyboard.KeyboardRegions.First(r => r.RegionName == "TopRow");
_keyPad = MainManager.KeyboardManager.ActiveKeyboard.KeyboardRegions.First(r => r.RegionName == "NumPad");
_abilityKeys = MainManager.KeyboardManager.ActiveKeyboard.KeyboardRegions.First(r => r.RegionName == "QWER");
HealthRectangle = new KeyboardRectangle(MainManager.KeyboardManager.ActiveKeyboard
, 0
, _topRow.BottomRight.Y*Scale
, new List<Color>()
, LinearGradientMode.Horizontal)
{Height = Scale, ContainedBrush = false};
ManaRectangle = new KeyboardRectangle(MainManager.KeyboardManager.ActiveKeyboard
, 0
, (_topRow.BottomRight.Y + 1)*Scale
, new List<Color>()
, LinearGradientMode.Horizontal)
{Height = Scale, ContainedBrush = false};
EventRectangle = new KeyboardRectangle(MainManager.KeyboardManager.ActiveKeyboard
, 0
, _topRow.TopLeft.X + 3
, new List<Color>()
, LinearGradientMode.Horizontal)
{
Height = MainManager.KeyboardManager.ActiveKeyboard.Height*Scale - Scale
,
Width = MainManager.KeyboardManager.ActiveKeyboard.Width*Scale - Scale - 12
};
DayCycleRectangle = new KeyboardRectangle(MainManager.KeyboardManager.ActiveKeyboard
, _keyPad.TopLeft.X*Scale
, _keyPad.TopLeft.Y* Scale
, new List<Color>()
, LinearGradientMode.Horizontal)
{
Height = _keyPad.GetRectangle().Height*Scale,
Width = _keyPad.GetRectangle().Width*Scale
};
SetAbilityKeys();
MainManager.GameStateWebServer.GameDataReceived += HandleGameData;
Initialized = true;
}
private void SetAbilityKeys()
{
#region Long Switch Statement for Keys
switch (Settings.KeyboardLayout)
{
case "0":
case "Default": //default
case "4": //Heroes of newearth
case "3": //League of Legends
for (int i = 0; i < AbilityKeysRectangles.Length; i++)
{
AbilityKeysRectangles[i] = new KeyboardRectangle(MainManager.KeyboardManager.ActiveKeyboard,
(_abilityKeys.TopLeft.X + i) * Scale - 2,
_abilityKeys.TopLeft.Y * Scale,
new List<Color>(),
LinearGradientMode.Horizontal)
{
Height = Scale,
Width = Scale
};
}
break;
case "2":
AbilityKeysRectangles[0] = new KeyboardRectangle(MainManager.KeyboardManager.ActiveKeyboard,
(_abilityKeys.TopLeft.X * Scale) - 2,
_abilityKeys.TopLeft.Y * Scale,
new List<Color>(),
LinearGradientMode.Horizontal)
{
Height = Scale,
Width = Scale
};
AbilityKeysRectangles[1] = new KeyboardRectangle(MainManager.KeyboardManager.ActiveKeyboard,
((_abilityKeys.TopLeft.X + 2) * Scale) - 2,
_abilityKeys.TopLeft.Y * Scale,
new List<Color>(),
LinearGradientMode.Horizontal)
{
Height = Scale,
Width = Scale
};
AbilityKeysRectangles[2] = new KeyboardRectangle(MainManager.KeyboardManager.ActiveKeyboard,
((_abilityKeys.TopLeft.X +3) * Scale) - 2,
_abilityKeys.TopLeft.Y * Scale,
new List<Color>(),
LinearGradientMode.Horizontal)
{
Height = Scale,
Width = Scale
};
AbilityKeysRectangles[3] = new KeyboardRectangle(MainManager.KeyboardManager.ActiveKeyboard,
((_abilityKeys.TopLeft.X +3)* Scale) - 2,
(_abilityKeys.TopLeft.Y +1)* Scale,
new List<Color>(),
LinearGradientMode.Horizontal)
{
Height = Scale,
Width = Scale
};
break;
case "1": //MMO
case "5": //Smite
for (int i = 0; i < AbilityKeysRectangles.Length; i++)
{
AbilityKeysRectangles[i] = new KeyboardRectangle(MainManager.KeyboardManager.ActiveKeyboard,
(_abilityKeys.TopLeft.X + i) * Scale - 3,
(_abilityKeys.TopLeft.Y-1) * Scale,
new List<Color>(),
LinearGradientMode.Horizontal)
{
Height = Scale,
Width = Scale
};
}
break;
}
#endregion
}
public override void Update()
{
if (D2Json?.map == null)
return;
UpdateMainColor();
if (Settings.ShowEvents)
UpdateEvents();
if (Settings.ShowDayCycle)
UpdateDay();
if (!D2Json.hero.alive)
return;
if (Settings.CanCastAbility)
UpdateAbilities();
if (Settings.ShowHealth)
UpdateHealth();
if (Settings.ShowMana)
UpdateMana();
}
private void UpdateMainColor()
{
var list = new List<Color> {ColorHelpers.ToDrawingColor(Settings.MainColor)};
EventRectangle.Colors = list;
DayCycleRectangle.Colors = list;
HealthRectangle.Colors = list;
ManaRectangle.Colors = list;
foreach (var key in AbilityKeysRectangles)
key.Colors = list;
}
private void UpdateEvents()
{
List<Color> list = null;
if (!D2Json.hero.alive)
list = new List<Color> { Color.LightGray };
else if (D2Json.hero.disarmed)
list = new List<Color> { Color.Yellow };
else if (D2Json.hero.hexed)
list = new List<Color> { Color.Yellow };
else if (D2Json.hero.silenced)
list = new List<Color> { Color.Yellow };
else if (D2Json.hero.stunned)
list = new List<Color> { Color.Yellow };
else if (D2Json.hero.magicimmune)
list = new List<Color> { Color.Lime };
if(list == null)
return;
EventRectangle.Colors = list;
DayCycleRectangle.Colors = list;
HealthRectangle.Colors = list;
ManaRectangle.Colors = list;
foreach (var item in AbilityKeysRectangles)
item.Colors = list;
}
private void UpdateDay()
{
if (D2Json?.map?.daytime == null)
return;
if (D2Json.map.nightstalker_night)
{
DayCycleRectangle.Colors = new List<Color> {Color.Blue};
return;
}
var timeLeft = 240 - D2Json.map.clock_time%240;
var timePercentage = 100.00/240*timeLeft;
DayCycleRectangle.Width = (int) (_keyPad.GetRectangle().Width*Scale/100.00*timePercentage);
DayCycleRectangle.Colors = D2Json.map.daytime
? new List<Color> {Color.Yellow}
: new List<Color> {Color.Blue};
}
private void UpdateMana()
{
if (D2Json?.hero == null || D2Json.hero.mana_percent == -1)
return;
var manaPercent = D2Json.hero.mana_percent;
ManaRectangle.Colors = new List<Color> {ColorHelpers.ToDrawingColor(Settings.ManaColor)};
ManaRectangle.Width = (int) Math.Floor(_topRow.GetRectangle().Width*Scale/100.00*manaPercent);
}
private void UpdateAbilities()
{
if (AbilityKeysRectangles == null)
return;
AbilityKeysRectangles[0].Colors = D2Json?.abilities?.ability0?.can_cast == true ? new List<Color>
{ ColorHelpers.ToDrawingColor(Settings.AbilityReadyColor) } : new List<Color> { ColorHelpers.ToDrawingColor(Settings.AbilityCooldownColor) };
AbilityKeysRectangles[1].Colors = D2Json?.abilities?.ability1?.can_cast == true ? new List<Color>
{ ColorHelpers.ToDrawingColor(Settings.AbilityReadyColor) } : new List<Color> { ColorHelpers.ToDrawingColor(Settings.AbilityCooldownColor) };
AbilityKeysRectangles[2].Colors = D2Json?.abilities?.ability2?.can_cast == true ? new List<Color>
{ ColorHelpers.ToDrawingColor(Settings.AbilityReadyColor) } : new List<Color> { ColorHelpers.ToDrawingColor(Settings.AbilityCooldownColor) };
AbilityKeysRectangles[3].Colors = D2Json?.abilities?.ability3?.can_cast == true ? new List<Color>
{ ColorHelpers.ToDrawingColor(Settings.AbilityReadyColor) } : new List<Color> { ColorHelpers.ToDrawingColor(Settings.AbilityCooldownColor) };
}
private void UpdateHealth()
{
if (D2Json?.hero == null || D2Json.hero.health_percent == -1)
return;
var healthPercent = D2Json.hero.health_percent;
if (healthPercent > 66)
HealthRectangle.Colors = new List<Color> {Color.Lime};
else if (healthPercent > 33)
HealthRectangle.Colors = new List<Color> {Color.Yellow};
else
HealthRectangle.Colors = new List<Color> {Color.Red};
HealthRectangle.Width = (int) Math.Floor(_topRow.GetRectangle().Width*Scale/100.00*healthPercent);
}
public override Bitmap GenerateBitmap()
{
var bitmap = MainManager.KeyboardManager.ActiveKeyboard.KeyboardBitmap(Scale);
using (var g = Graphics.FromImage(bitmap))
{
g.Clear(Color.Transparent);
EventRectangle.Draw(g);
HealthRectangle.Draw(g);
ManaRectangle.Draw(g);
foreach (var item in AbilityKeysRectangles)
{
item.Draw(g);
}
DayCycleRectangle.Draw(g);
}
return bitmap;
}
public void HandleGameData(object sender, GameDataReceivedEventArgs e)
{
var jsonString = e.Json.ToString();
// Ensure it's Dota 2 JSON
if (!jsonString.Contains("Dota 2"))
return;
// Parse the JSON
D2Json = JsonConvert.DeserializeObject<Dota2DataModel.Rootobject>(jsonString);
}
#region Variables
public Dota2Settings Settings { get; set; }
public Dota2DataModel.Rootobject D2Json { get; set; }
public int Scale { get; set; }
public KeyboardRectangle HealthRectangle { get; set; }
public KeyboardRectangle EventRectangle { get; set; }
public KeyboardRectangle DayCycleRectangle { get; set; }
public KeyboardRectangle ManaRectangle { get; set; }
public KeyboardRectangle[] AbilityKeysRectangles = new KeyboardRectangle[4];
#endregion
}
}

View File

@ -0,0 +1,88 @@
using System;
using System.Collections.Generic;
using System.Windows.Media;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Artemis.Models;
namespace Artemis.Modules.Games.Dota2
{
class Dota2Settings : GameSettings
{
public Dota2Settings()
{
Load();
}
#region Variables
public string GameDirectory { get; set; }
public bool CanCastAbility { get; set; }
public bool ShowHealth { get; set; }
public bool ShowDayCycle { get; set; }
public bool ShowMana { get; set; }
public bool ShowEvents { get; set; }
public Color MainColor { get; set; }
public Color ManaColor { get; set; }
public string KeyboardLayout { get; set; }
public Color AbilityCooldownColor { get; set; }
public Color AbilityReadyColor { get; set; }
#endregion
public override void Load()
{
KeyboardLayout = Dota2.Default.KeyboardLayout;
MainColor = Dota2.Default.MainColor;
ManaColor = Dota2.Default.ManaColor;
ShowHealth = Dota2.Default.ShowHealth;
CanCastAbility = Dota2.Default.CanCastAbility;
Enabled = Dota2.Default.Enabled;
GameDirectory = Dota2.Default.GameDirectory;
ShowDayCycle = Dota2.Default.ShowDayCycle;
ShowMana = Dota2.Default.ShowMana;
ShowEvents = Dota2.Default.ShowEvents;
AbilityReadyColor = Dota2.Default.AbilityReadyColor;
AbilityCooldownColor = Dota2.Default.AbilityCooldownColor;
}
public override void Save()
{
Dota2.Default.KeyboardLayout = KeyboardLayout;
Dota2.Default.MainColor = MainColor;
Dota2.Default.ManaColor = ManaColor;
Dota2.Default.ShowDayCycle = ShowDayCycle;
Dota2.Default.ShowHealth = ShowHealth;
Dota2.Default.CanCastAbility = CanCastAbility;
Dota2.Default.Enabled = Enabled;
Dota2.Default.GameDirectory = GameDirectory;
Dota2.Default.ShowMana = ShowMana;
Dota2.Default.ShowEvents = ShowEvents;
Dota2.Default.AbilityCooldownColor = AbilityCooldownColor;
Dota2.Default.AbilityReadyColor = AbilityReadyColor;
Dota2.Default.Save();
}
public override void ToDefault()
{
Enabled = true;
GameDirectory = string.Empty;
KeyboardLayout = "Default";
MainColor = Color.FromArgb(255,255,0,0);
ManaColor = Color.FromArgb(255,0,0,255);
AbilityCooldownColor = Color.FromArgb(255,106,90,205);
AbilityReadyColor = Color.FromArgb(255, 0, 255, 0);
ShowHealth = true;
CanCastAbility = true;
ShowDayCycle = true;
ShowMana = true;
ShowEvents = true;
}
}
}

View File

@ -1,13 +1,173 @@
<UserControl x:Class="Artemis.Modules.Games.Dota2.Dota2View"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
<Grid>
<TextBlock Text="Dota 2 support is still to be done." />
</Grid>
</ScrollViewer>
<UserControl x:Class="Artemis.Modules.Games.Dota2.Dota2View"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:cal="http://www.caliburnproject.org"
xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
mc:Ignorable="d" d:DesignWidth="635" Height="515.691">
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" Margin="0,0,0,-19">
<Grid Margin="15, 5, 15, 5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="80" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Margin="0,0,1,0">
<Label FontSize="20" HorizontalAlignment="Left">
<Label.Content>
<AccessText TextWrapping="Wrap"
Text="Shows game states and events from Dota 2." />
</Label.Content>
</Label>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Label Content="Enable effect" Margin="0 3 0 0" HorizontalAlignment="Right" />
<ToggleButton x:Name="EffectEnabled" Margin="0 3 0 0" Width="25" Height="25"
IsChecked="{Binding Path=GameSettings.Enabled, Mode=TwoWay}"
Style="{DynamicResource MetroCircleToggleButtonStyle}"
cal:Message.Attach="[Event Click] = [Action ToggleEffect]" />
</StackPanel>
</StackPanel>
<StackPanel Grid.Row="1"
Grid.Column="0"
Grid.ColumnSpan="2" Margin="0,0,1,0">
<Label FontSize="16" Content="Dota 2 Directory" FontFamily="Segoe UI Semibold" Foreground="#535353"
Width="130" HorizontalAlignment="Left" />
<Grid>
<TextBox x:Name="GameDirectory" Height="23" TextWrapping="Wrap" Margin="5,0,30,0"
Text="{Binding Path=GameSettings.GameDirectory, Mode=TwoWay}"
cal:Message.Attach="[Event LostFocus] = [Action PlaceConfigFile]" />
<Button x:Name="BrowseDirectory" Content="..." RenderTransformOrigin="-0.039,-0.944"
HorizontalAlignment="Right" Width="25"
Style="{DynamicResource SquareButtonStyle}" Height="25" />
</Grid>
</StackPanel>
<!-- Main Color -->
<TextBlock Grid.Row="2" Grid.Column="0" HorizontalAlignment="Left" Width="114" VerticalAlignment="Center"
Height="16" Margin="0,8">
Main keyboard color
</TextBlock>
<xctk:ColorPicker x:Name="MainColor"
SelectedColor="{Binding Path=GameSettings.MainColor, Mode=TwoWay}"
Grid.Row="2" Grid.Column="1" Width="110" HorizontalAlignment="Right"
VerticalAlignment="Center" Margin="0,5,-1,5" Height="22" />
<!-- Ability Ready Color -->
<TextBlock Grid.Row="3" Grid.Column="0" HorizontalAlignment="Left" Width="114" VerticalAlignment="Center"
Height="16" Margin="0,8">
Ability Ready Color
</TextBlock>
<xctk:ColorPicker x:Name="AbilityReadyColor"
SelectedColor="{Binding Path=GameSettings.AbilityReadyColor, Mode=TwoWay}"
Grid.Row="3" Grid.Column="1" Width="110" HorizontalAlignment="Right"
VerticalAlignment="Center" Margin="0,5,-1,5" Height="22" />
<!-- Ability on Cooldown Color -->
<TextBlock Grid.Row="4" Grid.Column="0" HorizontalAlignment="Left" Width="147" VerticalAlignment="Center"
Height="16" Margin="0,8">
Ability on Cooldown Color
</TextBlock>
<xctk:ColorPicker x:Name="AbilityCooldownColor"
SelectedColor="{Binding Path=GameSettings.AbilityCooldownColor, Mode=TwoWay}"
Grid.Row="4" Grid.Column="1" Width="110" HorizontalAlignment="Right"
VerticalAlignment="Center" Margin="0,5,-1,5" Height="22" />
<!-- Abilities Display -->
<TextBlock Grid.Row="5" Grid.Column="0" HorizontalAlignment="Left" Width="168" VerticalAlignment="Center"
Height="16" Margin="0,10,0,9">
Keyboard Template
</TextBlock>
<ComboBox Grid.Row="5" Grid.Column="1" x:Name="KeyboardLayouts" ItemsSource="{Binding Path=KeyboardLayouts}" SelectedIndex="{Binding Path=GameSettings.KeyboardLayout}" VerticalAlignment="Center"
HorizontalAlignment="Right"
Width="109" Margin="0,6,0,7" />
<!-- Items Display -->
<TextBlock Grid.Row="6" Grid.Column="0" HorizontalAlignment="Left" Width="168" VerticalAlignment="Center"
Height="16" Margin="0,10,0,9">
Castable Abilities
</TextBlock>
<controls:ToggleSwitch IsChecked="{Binding Path=GameSettings.CanCastAbility, Mode=TwoWay}"
Grid.Row="6" Grid.Column="1" HorizontalAlignment="Right" OnLabel="Yes" OffLabel="No"
Margin="0,0,-5,0" Width="114" />
<!-- Health Display -->
<TextBlock Grid.Row="7" Grid.Column="0" HorizontalAlignment="Left" Width="168" VerticalAlignment="Center"
Height="16" Margin="0,10,0,9">
Display health
</TextBlock>
<controls:ToggleSwitch IsChecked="{Binding Path=GameSettings.ShowHealth, Mode=TwoWay}"
Grid.Row="7" Grid.Column="1" HorizontalAlignment="Right" OnLabel="Yes" OffLabel="No"
Margin="0,0,-5,0" Width="114" />
<!-- Mana Display-->
<TextBlock Grid.Row="8" Grid.Column="0" HorizontalAlignment="Left" Width="168" VerticalAlignment="Center"
Height="16" Margin="0,10,0,9">
Display mana
</TextBlock>
<controls:ToggleSwitch IsChecked="{Binding Path=GameSettings.ShowMana, Mode=TwoWay}"
Grid.Row="8" Grid.Column="1" HorizontalAlignment="Right" OnLabel="Yes" OffLabel="No"
Margin="0,0,-5,0" Width="114" />
<!-- Mana Color -->
<TextBlock Grid.Row="9" Grid.Column="0" HorizontalAlignment="Left" Width="114" VerticalAlignment="Center"
Height="16" Margin="0,8">
Mana color
</TextBlock>
<xctk:ColorPicker x:Name="ManaColor"
SelectedColor="{Binding Path=GameSettings.ManaColor, Mode=TwoWay}"
Grid.Row="9" Grid.Column="1" Width="110" HorizontalAlignment="Right"
VerticalAlignment="Center" Margin="0,5,-1,5" Height="22" />
<!-- Daytime Display -->
<TextBlock Grid.Row="10" Grid.Column="0" HorizontalAlignment="Left" Width="168" VerticalAlignment="Center"
Height="16" Margin="0,10,0,9">
Display day/night
</TextBlock>
<controls:ToggleSwitch IsChecked="{Binding Path=GameSettings.ShowDayCycle, Mode=TwoWay}"
Grid.Row="10" Grid.Column="1" HorizontalAlignment="Right" OnLabel="Yes" OffLabel="No"
Margin="0,0,-5,0" Width="114" />
<!-- Dead Display -->
<TextBlock Grid.Row="11" Grid.Column="0" HorizontalAlignment="Left" Width="168" VerticalAlignment="Center"
Height="16" Margin="0,10,0,9">
Show events on the keyboard
</TextBlock>
<controls:ToggleSwitch IsChecked="{Binding Path=GameSettings.ShowEvents, Mode=TwoWay}"
Grid.Row="11" Grid.Column="1" HorizontalAlignment="Right" OnLabel="Yes" OffLabel="No"
Margin="0,0,-5,0" Width="114" />
<StackPanel Grid.Column="0" Grid.Row="12" Orientation="Horizontal" VerticalAlignment="Bottom">
<Button x:Name="ResetSettings" Content="Reset effect" VerticalAlignment="Top" Width="100"
Style="{DynamicResource SquareButtonStyle}" />
<Button x:Name="SaveSettings" Content="Save changes" VerticalAlignment="Top" Width="100"
Margin="10,0,0,0"
Style="{DynamicResource SquareButtonStyle}" />
</StackPanel>
</Grid>
</ScrollViewer>
</UserControl>

View File

@ -1,16 +1,84 @@
using Artemis.Managers;
using Artemis.ViewModels.Abstract;
namespace Artemis.Modules.Games.Dota2
{
public class Dota2ViewModel : GameViewModel
{
public Dota2ViewModel(MainManager mainManager)
{
MainManager = mainManager;
}
public static string Name => "Dota 2 (NYI)";
public string Content => "Dota 2 Content";
}
using System;
using System.IO;
using System.Windows.Forms;
using Artemis.Managers;
using Artemis.Models;
using Artemis.Properties;
using Artemis.ViewModels.Abstract;
using Caliburn.Micro;
namespace Artemis.Modules.Games.Dota2
{
public class Dota2ViewModel : GameViewModel
{
public Dota2ViewModel(MainManager mainManager)
{
MainManager = mainManager;
GameSettings = new Dota2Settings();
GameModel = new Dota2Model(mainManager, (Dota2Settings) GameSettings);
MainManager.EffectManager.EffectModels.Add(GameModel);
PlaceConfigFile();
}
public BindableCollection<string> KeyboardLayouts
{
get
{
return new BindableCollection<string>(new[] {"Default","MMO","WASD","League of Legends","Heros of Newearth","Smite"});
}
}
public static string Name => "Dota 2";
public string Content => "Dota 2 Content";
public void BrowseDirectory()
{
var dialog = new FolderBrowserDialog { SelectedPath = ((Dota2Settings)GameSettings).GameDirectory };
var result = dialog.ShowDialog();
if (result != DialogResult.OK)
return;
((Dota2Settings)GameSettings).GameDirectory = dialog.SelectedPath;
NotifyOfPropertyChange(() => GameSettings);
GameSettings.Save();
PlaceConfigFile();
}
public void PlaceConfigFile()
{
if (((Dota2Settings)GameSettings).GameDirectory == string.Empty)
return;
if (Directory.Exists(((Dota2Settings)GameSettings).GameDirectory + "/game/dota/cfg"))
{
var cfgFile = Resources.dotaGamestateConfiguration.Replace("{{port}}",
MainManager.GameStateWebServer.Port.ToString());
try
{
File.WriteAllText(
((Dota2Settings)GameSettings).GameDirectory + "/game/dota/cfg/gamestate_integration/gamestate_integration_artemis.cfg",
cfgFile);
}
catch (DirectoryNotFoundException)
{
Directory.CreateDirectory(((Dota2Settings) GameSettings).GameDirectory + "/game/dota/cfg/gamestate_integration/");
File.WriteAllText(
((Dota2Settings)GameSettings).GameDirectory + "/game/dota/cfg/gamestate_integration/gamestate_integration_artemis.cfg",
cfgFile);
}
return;
}
MainManager.DialogService.ShowErrorMessageBox("Please select a valid Dota 2 directory\n\n" +
@"By default Dota 2 is in \SteamApps\common\dota 2 beta");
((Dota2Settings)GameSettings).GameDirectory = string.Empty;
NotifyOfPropertyChange(() => GameSettings);
GameSettings.Save();
}
}
}

View File

@ -0,0 +1,38 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Artemis.Modules.Games.TheDivision {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")]
internal sealed partial class TheDivision : global::System.Configuration.ApplicationSettingsBase {
private static TheDivision defaultInstance = ((TheDivision)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new TheDivision())));
public static TheDivision Default {
get {
return defaultInstance;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("True")]
public bool Enabled {
get {
return ((bool)(this["Enabled"]));
}
set {
this["Enabled"] = value;
}
}
}
}

View File

@ -0,0 +1,9 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="Artemis.Modules.Games.TheDivision" GeneratedClassName="TheDivision">
<Profiles />
<Settings>
<Setting Name="Enabled" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
</Settings>
</SettingsFile>

View File

@ -0,0 +1,42 @@
using System.Collections.Generic;
namespace Artemis.Modules.Games.TheDivision
{
public class TheDivisionDataModel
{
public List<DivisionPlayer> DivisionPlayers { get; set; }
public GrenadeState GrenadeState { get; set; }
public bool LowAmmo { get; set; }
public bool LowHp { get; set; }
public TheDivisionDataModel()
{
DivisionPlayers = new List<DivisionPlayer>();
}
}
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
}
}

View File

@ -0,0 +1,257 @@
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
{
public class TheDivisionModel : GameModel
{
private Wave _ammoWave;
private TheDivisionDataModel _dataModel;
private KeyboardRectangle _hpRect;
private KeyboardRectangle _p2;
private KeyboardRectangle _p3;
private KeyboardRectangle _p4;
private StickyValue<bool> _stickyAmmo;
private StickyValue<bool> _stickyHp;
private int _trans;
public TheDivisionModel(MainManager mainManager, TheDivisionSettings settings) : base(mainManager)
{
Settings = settings;
Name = "TheDivision";
ProcessName = "TheDivision";
Scale = 4;
Enabled = Settings.Enabled;
Initialized = false;
}
public TheDivisionSettings Settings { get; set; }
public int Scale { get; set; }
public override void Dispose()
{
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<Color>(),
LinearGradientMode.Horizontal)
{
Height = 7*Scale,
Width = 21*Scale,
Rotate = true,
ContainedBrush = false
};
_p2 = new KeyboardRectangle(MainManager.KeyboardManager.ActiveKeyboard, 0*Scale, 1*Scale,
new List<Color>(),
LinearGradientMode.Horizontal)
{
Height = 2*Scale,
Width = 3*Scale,
Rotate = true,
ContainedBrush = false
};
_p3 = new KeyboardRectangle(MainManager.KeyboardManager.ActiveKeyboard, 0*Scale, 3*Scale,
new List<Color>(),
LinearGradientMode.Horizontal)
{
Height = 2*Scale,
Width = 3*Scale,
Rotate = true,
ContainedBrush = false
};
_p4 = new KeyboardRectangle(MainManager.KeyboardManager.ActiveKeyboard, 0*Scale, 5*Scale,
new List<Color>(),
LinearGradientMode.Horizontal)
{
Height = 2*Scale,
Width = 3*Scale,
Rotate = true,
ContainedBrush = false
};
_stickyAmmo = new StickyValue<bool>(200);
_stickyHp = new StickyValue<bool>(200);
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];
for (var i = 0; i < stringParts.Length; i++)
parts[i] = int.Parse(stringParts[i]);
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> {Color.Red, Color.Orange}
: new List<Color> {Color.FromArgb(10, 255, 0), Color.FromArgb(80, 255, 45) };
if (_dataModel.DivisionPlayers[1].PlayerState == PlayerState.Offline)
_p2.Colors = new List<Color> {Color.Gray, Color.White};
else if (_dataModel.DivisionPlayers[1].PlayerState == PlayerState.Online)
_p2.Colors = new List<Color> { Color.FromArgb(10, 255, 0), Color.FromArgb(80, 255, 45) };
else
_p2.Colors = new List<Color> {Color.Red, Color.Orange};
if (_dataModel.DivisionPlayers[2].PlayerState == PlayerState.Offline)
_p3.Colors = new List<Color> {Color.Gray, Color.White};
else if (_dataModel.DivisionPlayers[2].PlayerState == PlayerState.Online)
_p3.Colors = new List<Color> { Color.FromArgb(10, 255, 0), Color.FromArgb(80, 255, 45) };
else
_p3.Colors = new List<Color> {Color.Red, Color.Orange};
if (_dataModel.DivisionPlayers[3].PlayerState == PlayerState.Offline)
_p4.Colors = new List<Color> {Color.Gray, Color.White};
else if (_dataModel.DivisionPlayers[3].PlayerState == PlayerState.Online)
_p4.Colors = new List<Color> { Color.FromArgb(10, 255, 0), Color.FromArgb(80, 255, 45) };
else
_p4.Colors = new List<Color> {Color.Red, Color.Orange};
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()
{
var bitmap = MainManager.KeyboardManager.ActiveKeyboard.KeyboardBitmap(Scale);
using (var g = Graphics.FromImage(bitmap))
{
g.Clear(Color.Transparent);
_hpRect.Draw(g);
_p2.Draw(g);
_p3.Draw(g);
_p4.Draw(g);
// Very, very PH
if (_ammoWave.Size != 0)
{
var path = new GraphicsPath();
path.AddEllipse(_ammoWave.Point.X - _ammoWave.Size/2, _ammoWave.Point.Y - _ammoWave.Size/2,
_ammoWave.Size, _ammoWave.Size);
if (_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;
}
}
}

View File

@ -0,0 +1,29 @@
using Artemis.Models;
namespace Artemis.Modules.Games.TheDivision
{
public class TheDivisionSettings : GameSettings
{
public TheDivisionSettings()
{
Load();
}
public sealed override void Load()
{
Enabled = TheDivision.Default.Enabled;
}
public sealed override void Save()
{
TheDivision.Default.Enabled = Enabled;
TheDivision.Default.Save();
}
public sealed override void ToDefault()
{
Enabled = true;
}
}
}

View File

@ -0,0 +1,54 @@
<UserControl x:Class="Artemis.Modules.Games.TheDivision.TheDivisionView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Artemis.Modules.Games.TheDivision"
xmlns:cal="http://www.caliburnproject.org"
mc:Ignorable="d"
d:DesignHeight="416.495" d:DesignWidth="553.608">
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
<Grid Margin="15, 5, 15, 5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2">
<Label FontSize="20" HorizontalAlignment="Left">
<Label.Content>
<AccessText TextWrapping="Wrap"
Text="Shows lots of things, I should change this." />
</Label.Content>
</Label>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Label Content="Enable effect" Margin="0 3 0 0" HorizontalAlignment="Right" />
<ToggleButton x:Name="EffectEnabled" Margin="0 3 0 0" Width="25" Height="25"
IsChecked="{Binding Path=GameSettings.Enabled, Mode=TwoWay}"
Style="{DynamicResource MetroCircleToggleButtonStyle}"
cal:Message.Attach="[Event Click] = [Action ToggleEffect]" />
</StackPanel>
</StackPanel>
<TextBlock Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" VerticalAlignment="Center" Margin="0,8"
TextWrapping="Wrap" HorizontalAlignment="Left" FontFamily="Segoe UI Semibold"
Foreground="{DynamicResource HighlightBrush}" MaxWidth="510" TextAlignment="Justify">
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)
</TextBlock>
<!-- Buttons -->
<StackPanel Grid.Column="0" Grid.Row="4" Orientation="Horizontal" VerticalAlignment="Bottom">
<Button x:Name="ResetSettings" Content="Reset effect" VerticalAlignment="Top" Width="100"
Style="{DynamicResource SquareButtonStyle}" />
<Button x:Name="SaveSettings" Content="Save changes" VerticalAlignment="Top" Width="100"
Margin="10,0,0,0"
Style="{DynamicResource SquareButtonStyle}" />
</StackPanel>
</Grid>
</ScrollViewer>
</UserControl>

View File

@ -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.Games.TheDivision
{
/// <summary>
/// Interaction logic for TheDivisionView.xaml
/// </summary>
public partial class TheDivisionView : UserControl
{
public TheDivisionView()
{
InitializeComponent();
}
}
}

View File

@ -0,0 +1,22 @@
using Artemis.Managers;
using Artemis.ViewModels.Abstract;
namespace Artemis.Modules.Games.TheDivision
{
public class TheDivisionViewModel : GameViewModel
{
public TheDivisionViewModel(MainManager mainManager)
{
MainManager = mainManager;
// Settings are loaded from file by class
GameSettings = new TheDivisionSettings();
// Create effect model and add it to MainManager
GameModel = new TheDivisionModel(mainManager, (TheDivisionSettings) GameSettings);
MainManager.EffectManager.EffectModels.Add(GameModel);
}
public static string Name => "The Division";
}
}

View File

@ -32,8 +32,8 @@ namespace Artemis.Modules.Overlays.VolumeDisplay
{
var volumeRect = new KeyboardRectangle(MainManager.KeyboardManager.ActiveKeyboard, 0, 0, new List<Color>
{
ColorHelpers.ToDrawingColor(Settings.SecondaryColor),
ColorHelpers.ToDrawingColor(Settings.MainColor)
ColorHelpers.ToDrawingColor(Settings.MainColor),
ColorHelpers.ToDrawingColor(Settings.SecondaryColor)
},
LinearGradientMode.Horizontal)
{

View File

@ -55,13 +55,7 @@
<xctk:ColorPicker x:Name="SecondaryColor"
SelectedColor="{Binding Path=VolumeDisplaySettings.SecondaryColor, Mode=TwoWay}"
Grid.Row="2" Grid.Column="1" Width="110" HorizontalAlignment="Right"
VerticalAlignment="Center" Margin="0,5,-1,5" Height="22">
<xctk:ColorPicker.Template>
<ControlTemplate>
<Rectangle />
</ControlTemplate>
</xctk:ColorPicker.Template>
</xctk:ColorPicker>
VerticalAlignment="Center" Margin="0,5,-1,5" Height="22" />
<TextBlock Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" VerticalAlignment="Center" Margin="0,8"
TextWrapping="Wrap" HorizontalAlignment="Left" FontFamily="Segoe UI Semibold"

View File

@ -7,11 +7,11 @@ using System.Windows;
// associated with an assembly.
[assembly: AssemblyTitle("Artemis")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyDescription("Adds third-party support for RGB keyboards to games")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyCompany("Artemis developers")]
[assembly: AssemblyProduct("Artemis")]
[assembly: AssemblyCopyright("Copyright © 2015")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

View File

@ -61,14 +61,14 @@ namespace Artemis.Properties {
}
/// <summary>
/// Looks up a localized string similar to &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-16&quot;?&gt;
///&lt;!-- Used by Artemis to get the active Sign --&gt;
///&lt;UserConfig&gt;
/// &lt;Group id=&quot;Artemis&quot; displayName=&quot;Artemis&quot;&gt;
/// &lt;VisibleVars&gt;
/// &lt;Var id=&quot;ActiveSign&quot; displayName=&quot;ActiveSign&quot; displayType=&quot;SLIDER:0:1:1000000&quot;/&gt;
/// &lt;/VisibleVars&gt;
/// &lt;/Group&gt;
/// Looks up a localized string similar to &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-16&quot;?&gt;
///&lt;!-- Used by Artemis to get the active Sign --&gt;
///&lt;UserConfig&gt;
/// &lt;Group id=&quot;Artemis&quot; displayName=&quot;Artemis&quot;&gt;
/// &lt;VisibleVars&gt;
/// &lt;Var id=&quot;ActiveSign&quot; displayName=&quot;ActiveSign&quot; displayType=&quot;SLIDER:0:1:1000000&quot;/&gt;
/// &lt;/VisibleVars&gt;
/// &lt;/Group&gt;
///&lt;/UserConfig&gt;.
/// </summary>
internal static string artemisXml {
@ -88,28 +88,63 @@ namespace Artemis.Properties {
}
/// <summary>
/// Looks up a localized string similar to &quot;Artemis&quot;
///{
/// &quot;uri&quot; &quot;http://localhost:{{port}}/csgo_game_event&quot;
/// &quot;timeout&quot; &quot;5.0&quot;
/// &quot;buffer&quot; &quot;0.1&quot;
/// &quot;throttle&quot; &quot;0.1&quot;
/// &quot;heartbeat&quot; &quot;30.0&quot;
/// &quot;data&quot;
/// {
/// &quot;provider&quot; &quot;1&quot;
/// &quot;map&quot; &quot;1&quot;
/// &quot;round&quot; &quot;1&quot;
/// &quot;player_id&quot; &quot;1&quot;
/// &quot;player_state&quot; &quot;1&quot;
/// &quot;player_weapons&quot; &quot;1&quot;
/// &quot;player_match_stats&quot; &quot;1&quot;
/// }
/// Looks up a localized string similar to &quot;Artemis&quot;
///{
/// &quot;uri&quot; &quot;http://localhost:{{port}}/csgo_game_event&quot;
/// &quot;timeout&quot; &quot;5.0&quot;
/// &quot;buffer&quot; &quot;0.1&quot;
/// &quot;throttle&quot; &quot;0.1&quot;
/// &quot;heartbeat&quot; &quot;30.0&quot;
/// &quot;data&quot;
/// {
/// &quot;provider&quot; &quot;1&quot;
/// &quot;map&quot; &quot;1&quot;
/// &quot;round&quot; &quot;1&quot;
/// &quot;player_id&quot; &quot;1&quot;
/// &quot;player_state&quot; &quot;1&quot;
/// &quot;player_weapons&quot; &quot;1&quot;
/// &quot;player_match_stats&quot; &quot;1&quot;
/// }
///}.
/// </summary>
internal static string gamestateConfiguration {
internal static string csgoGamestateConfiguration {
get {
return ResourceManager.GetString("gamestateConfiguration", resourceCulture);
return ResourceManager.GetString("csgoGamestateConfiguration", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to &quot;Artemis&quot;
///{
/// &quot;uri&quot; &quot;http://localhost:4000/&quot;
/// &quot;timeout&quot; &quot;5.0&quot;
/// &quot;buffer&quot; &quot;0.1&quot;
/// &quot;throttle&quot; &quot;0.1&quot;
/// &quot;heartbeat&quot; &quot;30.0&quot;
/// &quot;data&quot;
/// {
/// &quot;provider&quot; &quot;1&quot;
/// &quot;map&quot; &quot;1&quot;
/// &quot;player&quot; &quot;1&quot;
/// &quot;hero&quot; &quot;1&quot;
/// &quot;abilities&quot; &quot;1&quot;
/// &quot;items&quot; &quot;1&quot;
/// }
///}.
/// </summary>
internal static string dotaGamestateConfiguration {
get {
return ResourceManager.GetString("dotaGamestateConfiguration", resourceCulture);
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] LogitechLED {
get {
object obj = ResourceManager.GetObject("LogitechLED", resourceCulture);
return ((byte[])(obj));
}
}

View File

@ -124,8 +124,14 @@
<data name="bow" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\bow.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="gamestateConfiguration" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\resources\counterstrike\gamestateconfiguration.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
<data name="csgoGamestateConfiguration" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\resources\counterstrike\csgoGamestateconfiguration.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
</data>
<data name="dotaGamestateConfiguration" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\resources\dota2\dotaGamestateconfiguration.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
</data>
<data name="LogitechLED" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\LogitechLED.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="logo" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\logo.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>

View File

@ -0,0 +1,17 @@
"Artemis"
{
"uri" "http://localhost:{{port}}/"
"timeout" "5.0"
"buffer" "0.1"
"throttle" "0.1"
"heartbeat" "30.0"
"data"
{
"provider" "1"
"map" "1"
"player" "1"
"hero" "1"
"abilities" "1"
"items" "1"
}
}

Binary file not shown.

Binary file not shown.

View File

@ -1,110 +1,110 @@
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using Artemis.Settings;
using Newtonsoft.Json;
namespace Artemis.Utilities.GameState
{
public class GameStateWebServer
{
public delegate void GameDataReceivedEventHandler(
object sender, GameDataReceivedEventArgs gameDataReceivedEventArgs);
private readonly HttpListener _listener = new HttpListener();
public GameStateWebServer()
{
Start();
}
public int Port { get; private set; }
public bool Running { get; private set; }
public event GameDataReceivedEventHandler GameDataReceived;
public void Start()
{
if (Running)
return;
try
{
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using Artemis.Settings;
using Newtonsoft.Json;
namespace Artemis.Utilities.GameState
{
public class GameStateWebServer
{
public delegate void GameDataReceivedEventHandler(
object sender, GameDataReceivedEventArgs gameDataReceivedEventArgs);
private readonly HttpListener _listener = new HttpListener();
public GameStateWebServer()
{
Start();
}
public int Port { get; private set; }
public bool Running { get; private set; }
public event GameDataReceivedEventHandler GameDataReceived;
public void Start()
{
if (Running)
return;
try
{
_listener.Prefixes.Clear();
Port = General.Default.GamestatePort;
_listener.Prefixes.Add($"http://localhost:{Port}/");
_listener.Start();
}
catch (Exception)
{
MessageBox.Show("Couldn't start the webserver. CS:GO effect won't work :c \n\nTry changing the port in Settings and restart Artemis.");
}
ThreadPool.QueueUserWorkItem(o =>
{
try
{
while (_listener.IsListening)
{
ThreadPool.QueueUserWorkItem(c =>
{
var ctx = c as HttpListenerContext;
if (ctx == null)
return;
try
{
var rstr = HandleRequest(ctx.Request);
var buf = Encoding.UTF8.GetBytes(rstr);
ctx.Response.ContentLength64 = buf.Length;
ctx.Response.OutputStream.Write(buf, 0, buf.Length);
}
catch
{
// ignored
}
finally
{
// always close the stream
ctx.Response.OutputStream.Close();
}
}, _listener.GetContext());
}
}
catch
{
// ignored
}
});
Running = true;
}
public void Stop()
{
_listener.Stop();
}
private string HandleRequest(HttpListenerRequest request)
{
object json;
using (var reader = new StreamReader(request.InputStream, request.ContentEncoding))
{
var result = reader.ReadToEnd();
json = JsonConvert.DeserializeObject<object>(result);
}
if (json != null)
OnGameDataReceived(new GameDataReceivedEventArgs(json));
return JsonConvert.SerializeObject(json);
}
protected virtual void OnGameDataReceived(GameDataReceivedEventArgs e)
{
GameDataReceived?.Invoke(this, e);
}
}
_listener.Start();
}
catch (Exception)
{
MessageBox.Show("Couldn't start the webserver. CS:GO/Dota2 effects won't work :c \n\nTry changing the port in Settings and restart Artemis.");
}
ThreadPool.QueueUserWorkItem(o =>
{
try
{
while (_listener.IsListening)
{
ThreadPool.QueueUserWorkItem(c =>
{
var ctx = c as HttpListenerContext;
if (ctx == null)
return;
try
{
var rstr = HandleRequest(ctx.Request);
var buf = Encoding.UTF8.GetBytes(rstr);
ctx.Response.ContentLength64 = buf.Length;
ctx.Response.OutputStream.Write(buf, 0, buf.Length);
}
catch
{
// ignored
}
finally
{
// always close the stream
ctx.Response.OutputStream.Close();
}
}, _listener.GetContext());
}
}
catch
{
// ignored
}
});
Running = true;
}
public void Stop()
{
_listener.Stop();
}
private string HandleRequest(HttpListenerRequest request)
{
object json;
using (var reader = new StreamReader(request.InputStream, request.ContentEncoding))
{
var result = reader.ReadToEnd();
json = JsonConvert.DeserializeObject<object>(result);
}
if (json != null)
OnGameDataReceived(new GameDataReceivedEventArgs(json));
return JsonConvert.SerializeObject(json);
}
protected virtual void OnGameDataReceived(GameDataReceivedEventArgs e)
{
GameDataReceived?.Invoke(this, e);
}
}
}

View File

@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Security.Principal;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
namespace Artemis.Utilities
{
public static class GeneralHelpers
{
public static void RunAsAdministrator()
{
var processInfo = new ProcessStartInfo(Assembly.GetExecutingAssembly().CodeBase)
{
UseShellExecute = true,
Verb = "runas"
};
// The following properties run the new process as administrator
// Start the new process
try
{
Process.Start(processInfo);
}
catch (Exception)
{
// The user did not allow the application to run as administrator
MessageBox.Show("Sorry, this application must be run as Administrator.");
}
// Shut down the current process
Environment.Exit(0);
}
public static bool IsRunAsAdministrator()
{
var wi = WindowsIdentity.GetCurrent();
var wp = new WindowsPrincipal(wi);
return wp.IsInRole(WindowsBuiltInRole.Administrator);
}
}
}

View File

@ -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,64 +73,5 @@ namespace Artemis.Utilities
//return the resulting bitmap
return result;
}
/// <summary>
/// Saves an image as a jpeg image, with the given quality
/// </summary>
/// <param name="path">Path to which the image would be saved.</param>
/// <param name="quality">
/// An integer from 0 to 100, with 100 being the
/// highest quality
/// </param>
/// <exception cref="ArgumentOutOfRangeException">
/// An invalid value was entered for image quality.
/// </exception>
public static void SaveJpeg(string path, Image image, int quality)
{
//ensure the quality is within the correct range
if ((quality < 0) || (quality > 100))
{
//create the error message
var error =
string.Format(
"Jpeg image quality must be between 0 and 100, with 100 being the highest quality. A value of {0} was specified.",
quality);
//throw a helpful exception
throw new ArgumentOutOfRangeException(error);
}
//create an encoder parameter for the image quality
var qualityParam = new EncoderParameter(Encoder.Quality, quality);
//get the jpeg codec
var jpegCodec = GetEncoderInfo("image/jpeg");
//create a collection of all parameters that we will pass to the encoder
var encoderParams = new EncoderParameters(1);
//set the quality parameter for the codec
encoderParams.Param[0] = qualityParam;
//save the image using the codec and the parameters
image.Save(path, jpegCodec, encoderParams);
}
/// <summary>
/// Returns the image codec with the given mime type
/// </summary>
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;
}
}
}

View File

@ -33,8 +33,8 @@ namespace Artemis.Utilities.Keyboard
_blinkWorker.DoWork += BlinkWorker_DoWork;
Scale = 4;
X = x*Scale;
Y = y*Scale;
X = x;
Y = y;
Width = keyboard.Width*Scale;
Height = keyboard.Height*Scale;
Visible = true;
@ -177,7 +177,6 @@ namespace Artemis.Utilities.Keyboard
// Apply the devided positions
colorBlend.Positions = positions.ToArray();
return colorBlend;
}

View File

@ -0,0 +1,80 @@
using System.IO;
using Artemis.Properties;
using Microsoft.Win32;
namespace Artemis.Utilities.LogitechDll
{
internal static class DllManager
{
private const string LogitechPath = @"C:\Program Files\Logitech Gaming Software\SDK\LED\x64\";
public static bool RestoreDll()
{
if (!File.Exists(LogitechPath + @"\LogitechLed.dll") || !File.Exists(LogitechPath + @"\artemis.txt"))
return false;
// Get rid of our own DLL
File.Delete(LogitechPath + @"\LogitechLed.dll");
// Restore the backup
if (File.Exists(LogitechPath + @"\LogitechLed.dll.bak"))
File.Copy(LogitechPath + @"\LogitechLed.dll.bak", LogitechPath + @"\LogitechLed.dll");
File.Delete(LogitechPath + @"\artemis.txt");
return true;
}
public static void PlaceDll()
{
if (DllPlaced())
return;
// Create directory structure, just in case
Directory.CreateDirectory(LogitechPath + @"");
// Backup the existing DLL
if (File.Exists(LogitechPath + @"\LogitechLed.dll"))
File.Move(LogitechPath + @"\LogitechLed.dll",
LogitechPath + @"\LogitechLed.dll.bak");
// Copy our own DLL in place
File.WriteAllBytes(LogitechPath + @"\LogitechLED.dll",
Resources.LogitechLED);
// A token to show the file is placed
File.Create(LogitechPath + @"\artemis.txt");
// If the user doesn't have a Logitech device, the CLSID will be missing
// and we should create it ourselves.
if (!RegistryKeyPlaced())
PlaceRegistryKey();
}
public static bool DllPlaced()
{
if (!Directory.Exists(LogitechPath + @""))
return false;
if (!RegistryKeyPlaced())
return false;
return File.Exists(LogitechPath + @"\artemis.txt");
}
private static bool RegistryKeyPlaced()
{
var key = Registry
.LocalMachine.OpenSubKey(
@"SOFTWARE\Classes\CLSID\{a6519e67-7632-4375-afdf-caa889744403}\ServerBinary");
return key != null;
}
private static void PlaceRegistryKey()
{
var key = Registry
.LocalMachine.OpenSubKey(
@"SOFTWARE\Classes\CLSID\{a6519e67-7632-4375-afdf-caa889744403}\ServerBinary", true);
key?.SetValue(null, LogitechPath + @"\LogitechLed.dll");
}
}
}

View File

@ -0,0 +1,189 @@
using System;
using System.IO;
using System.IO.Pipes;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using Microsoft.Win32.SafeHandles;
namespace Artemis.Utilities.LogitechDll
{
public class NamedPipeServer
{
public const uint DUPLEX = 0x00000003;
public const uint FILE_FLAG_OVERLAPPED = 0x40000000;
public const int BUFFER_SIZE = 100;
private SafeFileHandle clientHandle;
public Client clientse;
public int ClientType;
private Thread listenThread;
public string pipeName;
public NamedPipeServer(string PName, int Mode)
{
pipeName = PName;
ClientType = Mode; //0 Reading Pipe, 1 Writing Pipe
}
public event PipeDataReceivedEventHandler PipeDataReceived;
[DllImport("kernel32.dll", SetLastError = true)]
public static extern SafeFileHandle CreateNamedPipe(
string pipeName,
uint dwOpenMode,
uint dwPipeMode,
uint nMaxInstances,
uint nOutBufferSize,
uint nInBufferSize,
uint nDefaultTimeOut,
IntPtr lpSecurityAttributes);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern int ConnectNamedPipe(
SafeFileHandle hNamedPipe,
IntPtr lpOverlapped);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern int DisconnectNamedPipe(
SafeFileHandle hNamedPipe);
public void Start()
{
listenThread = new Thread(ListenForClients);
listenThread.Start();
}
private void ListenForClients()
{
while (true)
{
clientHandle = CreateNamedPipe(pipeName, DUPLEX | FILE_FLAG_OVERLAPPED, 0, 255, BUFFER_SIZE, BUFFER_SIZE,
0, IntPtr.Zero);
//could not create named pipe
if (clientHandle.IsInvalid)
return;
var success = ConnectNamedPipe(clientHandle, IntPtr.Zero);
//could not connect client
if (success == 0)
return;
clientse = new Client();
clientse.handle = clientHandle;
clientse.stream = new FileStream(clientse.handle, FileAccess.ReadWrite, BUFFER_SIZE, true);
if (ClientType == 0)
{
var readThread = new Thread(Read);
readThread.Start();
}
}
}
private void Read()
{
//Client client = (Client)clientObj;
//clientse.stream = new FileStream(clientse.handle, FileAccess.ReadWrite, BUFFER_SIZE, true);
byte[] buffer = null;
var encoder = new ASCIIEncoding();
while (true)
{
var bytesRead = 0;
try
{
buffer = new byte[BUFFER_SIZE];
bytesRead = clientse.stream.Read(buffer, 0, BUFFER_SIZE);
}
catch
{
//read error has occurred
break;
}
//client has disconnected
if (bytesRead == 0)
break;
//fire message received event
//if (this.MessageReceived != null)
// this.MessageReceived(clientse, encoder.GetString(buffer, 0, bytesRead));
var ReadLength = 0;
for (var i = 0; i < BUFFER_SIZE; i++)
{
if (buffer[i].ToString("x2") != "cc")
{
ReadLength++;
}
else
break;
}
if (ReadLength > 0)
{
var Rc = new byte[ReadLength];
Buffer.BlockCopy(buffer, 0, Rc, 0, ReadLength);
OnPipeDataReceived(new PipeDataReceivedEventArgs(encoder.GetString(Rc, 0, ReadLength)));
buffer.Initialize();
}
}
//clean up resources
clientse.stream.Close();
clientse.handle.Close();
}
public void SendMessage(string message, Client client)
{
var encoder = new ASCIIEncoding();
var messageBuffer = encoder.GetBytes(message);
if (client.stream.CanWrite)
{
client.stream.Write(messageBuffer, 0, messageBuffer.Length);
client.stream.Flush();
}
}
public void StopServer()
{
//clean up resources
DisconnectNamedPipe(clientHandle);
listenThread.Abort();
}
private void OnPipeDataReceived(PipeDataReceivedEventArgs e)
{
PipeDataReceived?.Invoke(this, e);
}
public class Client
{
public SafeFileHandle handle;
public FileStream stream;
}
}
public delegate void PipeDataReceivedEventHandler(
object sender, PipeDataReceivedEventArgs pipeDataReceivedEventArgs);
public class PipeDataReceivedEventArgs
{
public PipeDataReceivedEventArgs(string data)
{
Data = data;
}
public string Data { get; set; }
}
}

View File

@ -0,0 +1,132 @@
using System;
using System.Diagnostics;
using System.IO.Pipes;
using System.Security.AccessControl;
using System.Security.Principal;
using System.Text;
using System.Threading.Tasks;
namespace Artemis.Utilities.LogitechDll
{
// Delegate for passing received message back to caller
public delegate void DelegateMessage(string reply);
public class PipeServer
{
private string _pipeName;
public bool Running { get; set; }
public event DelegateMessage PipeMessage;
public void Start(string pipeName)
{
Running = true;
_pipeName = pipeName;
var task = new Task(PipeLoop);
task.Start();
}
public void Stop()
{
Running = false;
}
private void PipeLoop()
{
try
{
var security = new PipeSecurity();
var sid = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
security.AddAccessRule(new PipeAccessRule(sid, PipeAccessRights.FullControl,
AccessControlType.Allow));
while (Running)
{
var namedPipeServerStream = new NamedPipeServerStream(_pipeName, PipeDirection.In, 100,
PipeTransmissionMode.Byte, PipeOptions.None, 100, 100, security);
namedPipeServerStream.WaitForConnection();
var buffer = new byte[100];
namedPipeServerStream.Read(buffer, 0, 100);
namedPipeServerStream.Close();
var task = new Task(() => HandleMessage(buffer));
task.Start();
}
}
catch
{
// ignored
}
}
private void HandleMessage(byte[] buffer)
{
var request = Encoding.ASCII.GetString(buffer);
PipeMessage?.Invoke(request);
}
public void Listen(string pipeName)
{
try
{
var security = new PipeSecurity();
var sid = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
security.AddAccessRule(new PipeAccessRule(sid, PipeAccessRights.FullControl, AccessControlType.Allow));
// Set to class level var so we can re-use in the async callback method
_pipeName = pipeName;
// Create the new async pipe
var pipeServer = new NamedPipeServerStream(pipeName, PipeDirection.In, 100, PipeTransmissionMode.Byte,
PipeOptions.Asynchronous, 100, 100, security);
// Wait for a connection
pipeServer.BeginWaitForConnection(WaitForConnectionCallBack, pipeServer);
}
catch (Exception oEx)
{
Debug.WriteLine(oEx.Message);
}
}
private void WaitForConnectionCallBack(IAsyncResult iar)
{
try
{
// Get the pipe
var pipeServer = (NamedPipeServerStream) iar.AsyncState;
// End waiting for the connection
pipeServer.EndWaitForConnection(iar);
var buffer = new byte[255];
// Read the incoming message
pipeServer.Read(buffer, 0, 255);
// Convert byte buffer to string
var stringData = Encoding.UTF8.GetString(buffer, 0, buffer.Length);
Debug.WriteLine(stringData + Environment.NewLine);
// Pass message back to calling form
PipeMessage?.Invoke(stringData);
// Kill original sever and create new wait server
pipeServer.Close();
var security = new PipeSecurity();
var sid = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
security.AddAccessRule(new PipeAccessRule(sid, PipeAccessRights.FullControl, AccessControlType.Allow));
pipeServer = new NamedPipeServerStream(_pipeName, PipeDirection.In, 100, PipeTransmissionMode.Byte,
PipeOptions.Asynchronous, 100, 100, security);
// Recursively wait for the connection again and again....
pipeServer.BeginWaitForConnection(WaitForConnectionCallBack, pipeServer);
}
catch
{
// ignored
}
}
}
}

View File

@ -0,0 +1,64 @@
using System;
using System.ComponentModel;
using System.Threading;
namespace Artemis.Utilities
{
/// <summary>
/// A value that only changes it's not changed again within a set time
/// </summary>
internal class StickyValue<T> : 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;
}
}
}
}

View File

@ -14,7 +14,7 @@ namespace Artemis.Utilities
{
public static class Updater
{
public static int CurrentVersion = 102;
public static int CurrentVersion = 103;
public static async Task<Action> CheckForUpdate(MetroDialogService dialogService)
{

View File

@ -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);
}
}

View File

@ -2,6 +2,7 @@
using Artemis.Modules.Games.CounterStrike;
using Artemis.Modules.Games.Dota2;
using Artemis.Modules.Games.RocketLeague;
using Artemis.Modules.Games.TheDivision;
using Artemis.Modules.Games.Witcher3;
using Caliburn.Micro;
@ -13,13 +14,15 @@ namespace Artemis.ViewModels
private readonly Dota2ViewModel _dota2Vm;
private readonly RocketLeagueViewModel _rocketLeagueVm;
private readonly Witcher3ViewModel _witcher3Vm;
private readonly TheDivisionViewModel _divisionVm;
public GamesViewModel(MainManager mainManager)
{
_rocketLeagueVm = new RocketLeagueViewModel(mainManager) {DisplayName = "Rocket League"};
_counterStrikeVm = new CounterStrikeViewModel(mainManager) {DisplayName = "CS:GO"};
//_dota2Vm = new Dota2ViewModel(MainManager) {DisplayName = "Dota 2 (NYI)"};
_dota2Vm = new Dota2ViewModel(mainManager) {DisplayName = "Dota 2"};
_witcher3Vm = new Witcher3ViewModel(mainManager) {DisplayName = "The Witcher 3"};
// _divisionVm = new TheDivisionViewModel(mainManager) {DisplayName = "The Division"};
}
protected override void OnActivate()
@ -28,8 +31,9 @@ namespace Artemis.ViewModels
ActivateItem(_rocketLeagueVm);
ActivateItem(_counterStrikeVm);
//ActivateItem(_dota2Vm);
ActivateItem(_dota2Vm);
ActivateItem(_witcher3Vm);
// ActivateItem(_divisionVm);
}
}
}

View File

@ -98,7 +98,7 @@
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.ColumnSpan="2" x:Name="ActiveEffectName" />
<TextBlock Grid.Row="1" Grid.Column="0" Text="Artemis 1.0.2" VerticalAlignment="Center"
<TextBlock Grid.Row="1" Grid.Column="0" Text="Artemis 1.0.3" VerticalAlignment="Center"
HorizontalAlignment="Left" />
<Button Grid.Row="1" Grid.Column="1" Focusable="False"
Style="{StaticResource AccentedSquareButtonStyle}"

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 KiB

View File

@ -5,14 +5,19 @@
<package id="Caliburn.Micro.AutofacBootstrap" version="2.0.9-beta" targetFramework="net452" />
<package id="Caliburn.Micro.Core" version="2.0.2" targetFramework="net452" />
<package id="Colore" version="4.0.0" targetFramework="net452" />
<package id="CUE.NET" version="1.0.2.1" targetFramework="net452" />
<package id="CUE.NET" version="1.0.2.2" targetFramework="net452" />
<package id="Extended.Wpf.Toolkit" version="2.6" targetFramework="net452" />
<package id="Hardcodet.NotifyIcon.Wpf" version="1.0.5" targetFramework="net452" />
<package id="ImageLibrary" version="2.0.5" targetFramework="net452" />
<package id="log4net" version="2.0.5" targetFramework="net452" />
<package id="MahApps.Metro" version="1.2.4.0" targetFramework="net452" />
<package id="MahApps.Metro.Resources" version="0.4.0.0" targetFramework="net452" />
<package id="NAudio" version="1.7.3" targetFramework="net452" />
<package id="Newtonsoft.Json" version="8.0.2" targetFramework="net452" />
<package id="Screna" version="0.1.3" targetFramework="net452" />
<package id="SharpDX" version="3.0.2" targetFramework="net452" />
<package id="SharpDX.Direct3D11" version="3.0.2" targetFramework="net452" />
<package id="SharpDX.DXGI" version="3.0.2" targetFramework="net452" />
<package id="VirtualInput" version="1.0.1" targetFramework="net452" />
<package id="WpfExceptionViewer" version="1.0.0.0" targetFramework="net452" />
</packages>