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

Merge pull request #82 from SpoinkyNL/profiles_new

Profiles
This commit is contained in:
Robert Beekman 2016-04-25 18:14:59 +02:00
commit 38a2dc64e4
162 changed files with 12499 additions and 7982 deletions

2
.gitignore vendored
View File

@ -68,6 +68,7 @@ ipch/
*.opensdf
*.sdf
*.cachefile
*.VC.db
# Visual Studio profiler
*.psess
@ -189,3 +190,4 @@ FakesAssemblies/
# Visual Studio 6 workspace options file
*.opt
*.opendb

BIN
Artemis/Artemis.VC.db Normal file

Binary file not shown.

View File

@ -5,6 +5,8 @@ VisualStudioVersion = 14.0.24720.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Artemis", "Artemis\Artemis.csproj", "{ED9997A2-E54C-4E9F-9350-62BE672C3ABE}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LogiLed2Artemis", "LogiLed2Artemis\LogiLed2Artemis.vcxproj", "{D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
CD_ROM|Any CPU = CD_ROM|Any CPU
@ -54,6 +56,34 @@ Global
{ED9997A2-E54C-4E9F-9350-62BE672C3ABE}.SingleImage|x64.Build.0 = Release|x64
{ED9997A2-E54C-4E9F-9350-62BE672C3ABE}.SingleImage|x86.ActiveCfg = Release|x86
{ED9997A2-E54C-4E9F-9350-62BE672C3ABE}.SingleImage|x86.Build.0 = Release|x86
{D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.CD_ROM|Any CPU.ActiveCfg = Release|x64
{D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.CD_ROM|Any CPU.Build.0 = Release|x64
{D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.CD_ROM|x64.ActiveCfg = Release|x64
{D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.CD_ROM|x64.Build.0 = Release|x64
{D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.CD_ROM|x86.ActiveCfg = Release|Win32
{D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.CD_ROM|x86.Build.0 = Release|Win32
{D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.Debug|Any CPU.ActiveCfg = Debug|Win32
{D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.Debug|x64.ActiveCfg = Debug|x64
{D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.Debug|x64.Build.0 = Debug|x64
{D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.Debug|x86.ActiveCfg = Debug|Win32
{D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.Debug|x86.Build.0 = Debug|Win32
{D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.DVD-5|Any CPU.ActiveCfg = Release|x64
{D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.DVD-5|Any CPU.Build.0 = Release|x64
{D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.DVD-5|x64.ActiveCfg = Debug|x64
{D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.DVD-5|x64.Build.0 = Debug|x64
{D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.DVD-5|x86.ActiveCfg = Debug|Win32
{D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.DVD-5|x86.Build.0 = Debug|Win32
{D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.Release|Any CPU.ActiveCfg = Release|Win32
{D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.Release|x64.ActiveCfg = Release|x64
{D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.Release|x64.Build.0 = Release|x64
{D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.Release|x86.ActiveCfg = Release|Win32
{D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.Release|x86.Build.0 = Release|Win32
{D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.SingleImage|Any CPU.ActiveCfg = Release|x64
{D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.SingleImage|Any CPU.Build.0 = Release|x64
{D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.SingleImage|x64.ActiveCfg = Release|x64
{D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.SingleImage|x64.Build.0 = Release|x64
{D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.SingleImage|x86.ActiveCfg = Release|Win32
{D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}.SingleImage|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -17,8 +17,9 @@
<!-- 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" />
Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseDark.xaml" />
<ResourceDictionary Source="/Resources/Icons.xaml" />
<ResourceDictionary Source="Styles/ColorBox.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>

View File

@ -136,6 +136,10 @@
<HintPath>..\packages\Caliburn.Micro.2.0.2\lib\net45\Caliburn.Micro.Platform.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="ColorBox, Version=1.1.0.0, Culture=neutral, PublicKeyToken=f971124b2576acfc, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>lib\ColorBox.dll</HintPath>
</Reference>
<Reference Include="Corale.Colore, Version=4.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Colore.4.0.0\lib\net35\Corale.Colore.dll</HintPath>
<Private>True</Private>
@ -145,7 +149,7 @@
<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>
<HintPath>..\packages\Hardcodet.NotifyIcon.Wpf.1.0.8\lib\net451\Hardcodet.Wpf.TaskbarNotification.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Kaliko.ImageLibrary, Version=2.0.4.0, Culture=neutral, processorArchitecture=MSIL">
@ -168,11 +172,7 @@
<Private>True</Private>
</Reference>
<Reference Include="Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<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>
<HintPath>..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="SharpDX, Version=3.0.2.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
@ -188,8 +188,13 @@
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Linq.Dynamic, Version=1.0.5840.25917, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\System.Linq.Dynamic.1.0.6\lib\net40\System.Linq.Dynamic.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.Web" />
<Reference Include="System.Windows.Forms" />
@ -214,28 +219,28 @@
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="Xceed.Wpf.AvalonDock, Version=2.6.0.0, Culture=neutral, PublicKeyToken=3e4669d2f30244f4, processorArchitecture=MSIL">
<HintPath>..\packages\Extended.Wpf.Toolkit.2.6\lib\net40\Xceed.Wpf.AvalonDock.dll</HintPath>
<Reference Include="Xceed.Wpf.AvalonDock, Version=2.7.0.0, Culture=neutral, PublicKeyToken=3e4669d2f30244f4, processorArchitecture=MSIL">
<HintPath>..\packages\Extended.Wpf.Toolkit.2.7\lib\net40\Xceed.Wpf.AvalonDock.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Xceed.Wpf.AvalonDock.Themes.Aero, Version=2.6.0.0, Culture=neutral, PublicKeyToken=3e4669d2f30244f4, processorArchitecture=MSIL">
<HintPath>..\packages\Extended.Wpf.Toolkit.2.6\lib\net40\Xceed.Wpf.AvalonDock.Themes.Aero.dll</HintPath>
<Reference Include="Xceed.Wpf.AvalonDock.Themes.Aero, Version=2.7.0.0, Culture=neutral, PublicKeyToken=3e4669d2f30244f4, processorArchitecture=MSIL">
<HintPath>..\packages\Extended.Wpf.Toolkit.2.7\lib\net40\Xceed.Wpf.AvalonDock.Themes.Aero.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Xceed.Wpf.AvalonDock.Themes.Metro, Version=2.6.0.0, Culture=neutral, PublicKeyToken=3e4669d2f30244f4, processorArchitecture=MSIL">
<HintPath>..\packages\Extended.Wpf.Toolkit.2.6\lib\net40\Xceed.Wpf.AvalonDock.Themes.Metro.dll</HintPath>
<Reference Include="Xceed.Wpf.AvalonDock.Themes.Metro, Version=2.7.0.0, Culture=neutral, PublicKeyToken=3e4669d2f30244f4, processorArchitecture=MSIL">
<HintPath>..\packages\Extended.Wpf.Toolkit.2.7\lib\net40\Xceed.Wpf.AvalonDock.Themes.Metro.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Xceed.Wpf.AvalonDock.Themes.VS2010, Version=2.6.0.0, Culture=neutral, PublicKeyToken=3e4669d2f30244f4, processorArchitecture=MSIL">
<HintPath>..\packages\Extended.Wpf.Toolkit.2.6\lib\net40\Xceed.Wpf.AvalonDock.Themes.VS2010.dll</HintPath>
<Reference Include="Xceed.Wpf.AvalonDock.Themes.VS2010, Version=2.7.0.0, Culture=neutral, PublicKeyToken=3e4669d2f30244f4, processorArchitecture=MSIL">
<HintPath>..\packages\Extended.Wpf.Toolkit.2.7\lib\net40\Xceed.Wpf.AvalonDock.Themes.VS2010.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Xceed.Wpf.DataGrid, Version=2.6.0.0, Culture=neutral, PublicKeyToken=3e4669d2f30244f4, processorArchitecture=MSIL">
<HintPath>..\packages\Extended.Wpf.Toolkit.2.6\lib\net40\Xceed.Wpf.DataGrid.dll</HintPath>
<Reference Include="Xceed.Wpf.DataGrid, Version=2.7.0.0, Culture=neutral, PublicKeyToken=3e4669d2f30244f4, processorArchitecture=MSIL">
<HintPath>..\packages\Extended.Wpf.Toolkit.2.7\lib\net40\Xceed.Wpf.DataGrid.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Xceed.Wpf.Toolkit, Version=2.6.0.0, Culture=neutral, PublicKeyToken=3e4669d2f30244f4, processorArchitecture=MSIL">
<HintPath>..\packages\Extended.Wpf.Toolkit.2.6\lib\net40\Xceed.Wpf.Toolkit.dll</HintPath>
<Reference Include="Xceed.Wpf.Toolkit, Version=2.7.0.0, Culture=neutral, PublicKeyToken=3e4669d2f30244f4, processorArchitecture=MSIL">
<HintPath>..\packages\Extended.Wpf.Toolkit.2.7\lib\net40\Xceed.Wpf.Toolkit.dll</HintPath>
<Private>True</Private>
</Reference>
</ItemGroup>
@ -249,9 +254,12 @@
<SubType>Code</SubType>
</Compile>
<Compile Include="ArtemisBootstrapper.cs" />
<Compile Include="DAL\ProfileProvider.cs" />
<Compile Include="Events\ActiveKeyboardChanged.cs" />
<Compile Include="Events\ToggleEnabled.cs" />
<Compile Include="Events\ActiveEffectChanged.cs" />
<Compile Include="Events\ChangeBitmap.cs" />
<Compile Include="ItemBehaviours\BindableSelectedItemBehavior.cs" />
<Compile Include="KeyboardProviders\Corsair\CorsairRGB.cs" />
<Compile Include="KeyboardProviders\KeyboardProvider.cs" />
<Compile Include="KeyboardProviders\KeyboardRegion.cs" />
@ -269,6 +277,12 @@
<Compile Include="Models\EffectModel.cs" />
<Compile Include="Models\EffectSettings.cs" />
<Compile Include="Models\GameSettings.cs" />
<Compile Include="Models\Interfaces\GameDataModel.cs" />
<Compile Include="Models\Profiles\LayerConditionModel.cs" />
<Compile Include="Models\Profiles\LayerModel.cs" />
<Compile Include="Models\Profiles\LayerDynamicPropertiesModel.cs" />
<Compile Include="Models\Profiles\LayerPropertiesModel.cs" />
<Compile Include="Models\Profiles\ProfileModel.cs" />
<Compile Include="Modules\Effects\AmbientLightning\AmbientLightningEffectModel.cs" />
<Compile Include="Modules\Effects\AmbientLightning\AmbientLightningEffectSettings.cs" />
<Compile Include="Modules\Effects\AmbientLightning\AmbientLightningEffectView.xaml.cs">
@ -298,6 +312,7 @@
<AutoGen>True</AutoGen>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<Compile Include="Modules\Games\CounterStrike\CounterStrikeDataModel.cs" />
<Compile Include="Modules\Games\CounterStrike\CounterStrikeModel.cs" />
<Compile Include="Modules\Games\CounterStrike\CounterStrikeSettings.cs" />
<Compile Include="Modules\Games\Dota2\Dota2.Designer.cs">
@ -313,6 +328,7 @@
<AutoGen>True</AutoGen>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<Compile Include="Modules\Games\RocketLeague\RocketLeagueDataModel.cs" />
<Compile Include="Modules\Games\RocketLeague\RocketLeagueModel.cs" />
<Compile Include="Modules\Games\TheDivision\TheDivision.Designer.cs">
<AutoGen>True</AutoGen>
@ -366,11 +382,13 @@
<DependentUpon>Offsets.settings</DependentUpon>
</Compile>
<Compile Include="Utilities\ColorHelpers.cs" />
<Compile Include="Utilities\ExtensionMethods.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\LayerDrawer.cs" />
<Compile Include="Utilities\LogitechDll\DllManager.cs" />
<Compile Include="Utilities\LogitechDll\NamedPipeServer.cs" />
<Compile Include="Utilities\LogitechDll\PipeServer.cs" />
@ -380,9 +398,12 @@
<Compile Include="Utilities\Memory\Win32.cs" />
<Compile Include="Utilities\Keyboard\Key.cs" />
<Compile Include="Utilities\Keyboard\KeyboardRectangle.cs" />
<Compile Include="Utilities\ParentChild\ChildItemCollection.cs" />
<Compile Include="Utilities\ParentChild\IChildItem.cs" />
<Compile Include="Utilities\ShellLink.cs" />
<Compile Include="Utilities\StickyValue.cs" />
<Compile Include="Utilities\Updater.cs" />
<Compile Include="Utilities\ValueConverters.cs" />
<Compile Include="ViewModels\Abstract\EffectViewModel.cs" />
<Compile Include="ViewModels\Abstract\GameViewModel.cs" />
<Compile Include="ViewModels\EffectsViewModel.cs" />
@ -397,8 +418,12 @@
<Compile Include="Modules\Games\Dota2\Dota2ViewModel.cs" />
<Compile Include="Modules\Games\RocketLeague\RocketLeagueViewModel.cs" />
<Compile Include="Modules\Games\Witcher3\Witcher3ViewModel.cs" />
<Compile Include="ViewModels\LayerEditor\LayerConditionViewModel.cs" />
<Compile Include="ViewModels\LayerEditor\LayerDynamicPropertiesViewModel.cs" />
<Compile Include="ViewModels\LayerEditor\LayerEditorViewModel.cs" />
<Compile Include="ViewModels\OverlaysViewModel.cs" />
<Compile Include="Modules\Overlays\VolumeDisplay\VolumeDisplayViewModel.cs" />
<Compile Include="ViewModels\ProfileEditorViewModel.cs" />
<Compile Include="ViewModels\ShellViewModel.cs" />
<Compile Include="ViewModels\SystemTrayViewModel.cs" />
<Compile Include="ViewModels\WelcomeViewModel.cs" />
@ -435,12 +460,24 @@
<Compile Include="Modules\Games\Witcher3\Witcher3View.xaml.cs">
<DependentUpon>Witcher3View.xaml</DependentUpon>
</Compile>
<Compile Include="Views\LayerEditor\LayerConditionView.xaml.cs">
<DependentUpon>LayerConditionView.xaml</DependentUpon>
</Compile>
<Compile Include="Views\LayerEditor\LayerDynamicPropertiesView.xaml.cs">
<DependentUpon>LayerDynamicPropertiesView.xaml</DependentUpon>
</Compile>
<Compile Include="Views\LayerEditor\LayerEditorView.xaml.cs">
<DependentUpon>LayerEditorView.xaml</DependentUpon>
</Compile>
<Compile Include="Views\OverlaysView.xaml.cs">
<DependentUpon>OverlaysView.xaml</DependentUpon>
</Compile>
<Compile Include="Modules\Overlays\VolumeDisplay\VolumeDisplayView.xaml.cs">
<DependentUpon>VolumeDisplayView.xaml</DependentUpon>
</Compile>
<Compile Include="Views\ProfileEditorView.xaml.cs">
<DependentUpon>ProfileEditorView.xaml</DependentUpon>
</Compile>
<Compile Include="Views\ShellView.xaml.cs">
<DependentUpon>ShellView.xaml</DependentUpon>
</Compile>
@ -457,8 +494,8 @@
</Compile>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Include="Modules\Effects\AudioVisualizer\AudioVisualization.settings">
<Generator>SettingsSingleFileGenerator</Generator>
@ -495,18 +532,24 @@
<None Include="packages.config" />
<AppDesigner Include="Properties\" />
<Resource Include="Resources\bow.png" />
<Resource Include="Resources\WindowsIcons-license.txt" />
<Resource Include="Resources\Entypo-license.txt" />
<Content Include="logo.ico">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Resource Include="Resources\logo.ico" />
<Resource Include="Resources\logo-disabled.ico" />
<Resource Include="Resources\Dota2\dotaGamestateConfiguration.txt" />
<Resource Include="Resources\Entypo.ttf" />
<None Include="Resources\LogitechLED.dll" />
<None Include="Resources\folder.png" />
<Resource Include="Resources\Keyboards\k65.png" />
<Resource Include="Resources\Keyboards\k70.png" />
<Resource Include="Resources\Keyboards\k95.png" />
<Resource Include="Resources\Keyboards\strafe.png" />
<Resource Include="Resources\Keyboards\g910.png" />
<Resource Include="Resources\WindowsIcons-license.txt" />
<Resource Include="Resources\Entypo-license.txt" />
<Content Include="Resources\Witcher3\playerWitcher.txt" />
<Content Include="Resources\Witcher3\artemis.txt" />
<Resource Include="Resources\Entypo.ttf" />
<None Include="Settings\Offsets.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Offsets.Designer.cs</LastGenOutput>
@ -532,6 +575,14 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Styles\Accents\CorsairYellow.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Styles\ColorBox.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\EffectsView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
@ -576,6 +627,18 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\LayerEditor\LayerConditionView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\LayerEditor\LayerDynamicPropertiesView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\LayerEditor\LayerEditorView.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\OverlaysView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
@ -584,6 +647,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\ProfileEditorView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\ShellView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>

View File

@ -1,7 +1,7 @@
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Forms;
using Artemis.ViewModels;
using Autofac;
@ -19,6 +19,47 @@ namespace Artemis
CheckDuplicateInstances();
Initialize();
MessageBinder.SpecialValues.Add("$scaledmousex", (ctx) =>
{
var img = ctx.Source as Image;
var input = ctx.Source as IInputElement;
var e = ctx.EventArgs as System.Windows.Input.MouseEventArgs;
// If there is an image control, get the scaled position
if (img != null && e != null)
{
Point position = e.GetPosition(img);
return (int)(img.Source.Width * (position.X / img.ActualWidth));
}
// If there is another type of of IInputControl get the non-scaled position - or do some processing to get a scaled position, whatever needs to happen
if (e != null && input != null)
return e.GetPosition(input).X;
// Return 0 if no processing could be done
return 0;
});
MessageBinder.SpecialValues.Add("$scaledmousey", (ctx) =>
{
var img = ctx.Source as Image;
var input = ctx.Source as IInputElement;
var e = ctx.EventArgs as System.Windows.Input.MouseEventArgs;
// If there is an image control, get the scaled position
if (img != null && e != null)
{
Point position = e.GetPosition(img);
return (int)(img.Source.Width * (position.Y / img.ActualWidth));
}
// If there is another type of of IInputControl get the non-scaled position - or do some processing to get a scaled position, whatever needs to happen
if (e != null && input != null)
return e.GetPosition(input).Y;
// Return 0 if no processing could be done
return 0;
});
}
protected override void ConfigureContainer(ContainerBuilder builder)
@ -38,13 +79,14 @@ namespace Artemis
private void CheckDuplicateInstances()
{
if (Process.GetProcesses().Count(p => p.ProcessName.Contains(Assembly.GetExecutingAssembly()
.FullName.Split(',')[0]) && !p.Modules[0].FileName.Contains("vshost")) < 2)
var processes = Process.GetProcesses();
if (processes.Count(p => p.ProcessName == "Artemis") < 2)
return;
MessageBox.Show("An instance of Artemis is already running (check your system tray).",
"Artemis (╯°□°)╯︵ ┻━┻", MessageBoxButtons.OK, MessageBoxIcon.Warning);
Application.Current.Shutdown();
}
}
}

View File

@ -0,0 +1,91 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Xml.Serialization;
using Artemis.Models;
using Artemis.Models.Profiles;
namespace Artemis.DAL
{
public static class ProfileProvider
{
private static readonly string ProfileFolder =
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\Artemis\profiles";
/// <summary>
/// Get all profiles
/// </summary>
/// <returns>All profiles</returns>
public static List<ProfileModel> GetAll()
{
return ReadProfiles();
}
/// <summary>
/// Get all profiles matching the provided game
/// </summary>
/// <param name="game">The game to match</param>
/// <returns>All profiles matching the provided game</returns>
public static List<ProfileModel> GetAll(GameModel game)
{
return GetAll().Where(g => g.GameName.Equals(game.Name)).ToList();
}
/// <summary>
/// Adds or update the given profile.
/// Updates occur when a profile with the same name and game exist.
/// </summary>
/// <param name="prof">The profile to add or update</param>
public static void AddOrUpdate(ProfileModel prof)
{
if (!(prof.GameName?.Length > 1) || !(prof.KeyboardName?.Length > 1) || !(prof.Name?.Length > 1))
throw new ArgumentException("Profile is invalid. Name, GameName and KeyboardName are required");
var path = ProfileFolder + $@"\{prof.KeyboardName}\{prof.GameName}";
if (!Directory.Exists(path))
Directory.CreateDirectory(path);
var serializer = new XmlSerializer(typeof (ProfileModel));
using (var file = new StreamWriter(path + $@"\{prof.Name}.xml"))
{
serializer.Serialize(file, prof);
}
}
private static List<ProfileModel> ReadProfiles()
{
CheckProfiles();
var profiles = new List<ProfileModel>();
// Create the directory structure
var profilePaths = Directory.GetFiles(ProfileFolder, "*.xml", SearchOption.AllDirectories);
// Parse the JSON files into objects and add them if they are valid
// TODO: Invalid file handling
var deserializer = new XmlSerializer(typeof (ProfileModel));
foreach (var path in profilePaths)
{
using (var file = new StreamReader(path))
{
var prof = (ProfileModel) deserializer.Deserialize(file);
if (prof.GameName?.Length > 1 && prof.KeyboardName?.Length > 1 && prof.Name?.Length > 1)
profiles.Add(prof);
}
}
return profiles;
}
private static void CheckProfiles()
{
// Create the directory structure
if (Directory.Exists(ProfileFolder))
return;
Directory.CreateDirectory(ProfileFolder);
Debug.WriteLine("Place presets");
}
}
}

View File

@ -0,0 +1,12 @@
namespace Artemis.Events
{
public class ActiveKeyboardChanged
{
public ActiveKeyboardChanged(string activeKeyboard)
{
ActiveKeyboard = activeKeyboard;
}
public string ActiveKeyboard { get; set; }
}
}

View File

@ -0,0 +1,88 @@
using System.Collections;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interactivity;
namespace Artemis.ItemBehaviours
{
/// <summary>
/// Steve Greatrex - http://stackoverflow.com/a/5118406/5015269
/// </summary>
public class BindableSelectedItemBehavior : Behavior<TreeView>
{
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.SelectedItemChanged += OnTreeViewSelectedItemChanged;
}
protected override void OnDetaching()
{
base.OnDetaching();
if (AssociatedObject != null)
AssociatedObject.SelectedItemChanged -= OnTreeViewSelectedItemChanged;
}
private void OnTreeViewSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
SelectedItem = e.NewValue;
}
#region SelectedItem Property
public object SelectedItem
{
get { return GetValue(SelectedItemProperty); }
set { SetValue(SelectedItemProperty, value); }
}
public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register("SelectedItem",
typeof (object), typeof (BindableSelectedItemBehavior), new UIPropertyMetadata(null, OnSelectedItemChanged));
private static void OnSelectedItemChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
var item = ((BindableSelectedItemBehavior) sender).AssociatedObject
.ItemContainerGenerator.ContainerFromItem(e.NewValue) as TreeViewItem;
if (item != null)
item.SetValue(TreeViewItem.IsSelectedProperty, true);
else
ClearTreeViewSelection(((BindableSelectedItemBehavior) sender).AssociatedObject);
}
/// <summary>
/// Clears a TreeView's selected item recursively
/// Tom Wright - http://stackoverflow.com/a/1406116/5015269
/// </summary>
/// <param name="tv"></param>
public static void ClearTreeViewSelection(TreeView tv)
{
if (tv != null)
ClearTreeViewItemsControlSelection(tv.Items, tv.ItemContainerGenerator);
}
/// <summary>
/// Clears a TreeView's selected item recursively
/// Tom Wright - http://stackoverflow.com/a/1406116/5015269
/// </summary>
/// <param name="ic"></param>
/// <param name="icg"></param>
private static void ClearTreeViewItemsControlSelection(ICollection ic, ItemContainerGenerator icg)
{
if ((ic == null) || (icg == null))
return;
for (var i = 0; i < ic.Count; i++)
{
var tvi = icg.ContainerFromIndex(i) as TreeViewItem;
if (tvi == null)
continue;
ClearTreeViewItemsControlSelection(tvi.Items, tvi.ItemContainerGenerator);
tvi.IsSelected = false;
}
}
#endregion
}
}

View File

@ -1,20 +1,22 @@
using System.Collections.Generic;
using System.Drawing;
using System.Threading;
using System.Windows;
using Artemis.Properties;
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;
using Point = System.Drawing.Point;
namespace Artemis.KeyboardProviders.Corsair
{
internal class CorsairRGB : KeyboardProvider
{
private CorsairKeyboard _keyboard;
public CorsairRGB()
{
Name = "Corsair RGB Keyboards";
@ -74,6 +76,7 @@ namespace Artemis.KeyboardProviders.Corsair
case "K95 RGB":
Height = 7;
Width = 25;
PreviewSettings = new PreviewSettings(626, 175, new Thickness(0,-15,0,0), Resources.k95);
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)));
@ -81,6 +84,7 @@ namespace Artemis.KeyboardProviders.Corsair
case "K70 RGB":
Height = 7;
Width = 21;
PreviewSettings = new PreviewSettings(626, 175, new Thickness(0, -15, 0, 0), Resources.k70);
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)));
@ -88,16 +92,18 @@ namespace Artemis.KeyboardProviders.Corsair
case "K65 RGB":
Height = 7;
Width = 18;
PreviewSettings = new PreviewSettings(626, 175, new Thickness(0, -15, 0, 0), Resources.k65);
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 = 6;
Width = 22;
PreviewSettings = new PreviewSettings(626, 175, new Thickness(0, -15, 0, 0), Resources.strafe);
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;
}
}
@ -118,7 +124,7 @@ namespace Artemis.KeyboardProviders.Corsair
using (var g = Graphics.FromImage(fixedBmp))
{
g.Clear(Color.Black);
g.DrawImage(bitmap, 0,0);
g.DrawImage(bitmap, 0, 0);
}
var fixedImage = ImageUtilities.ResizeImage(fixedBmp, Width, Height);

View File

@ -1,5 +1,7 @@
using System.Collections.Generic;
using System.Drawing;
using System.Windows;
using Size = System.Windows.Size;
namespace Artemis.KeyboardProviders
{
@ -12,6 +14,8 @@ namespace Artemis.KeyboardProviders
public List<KeyboardRegion> KeyboardRegions { get; set; }
public PreviewSettings PreviewSettings { get; set; }
public abstract bool CanEnable();
public abstract void Enable();
public abstract void Disable();
@ -28,5 +32,23 @@ namespace Artemis.KeyboardProviders
/// </summary>
/// <returns></returns>
public Bitmap KeyboardBitmap(int scale) => new Bitmap(Width*scale, Height*scale);
public Rect KeyboardRectangle(int scale) => new Rect(new Size(Width*scale, Height*scale));
}
public struct PreviewSettings
{
public int Width { get; set; }
public int Height { get; set; }
public Thickness Margin { get; set; }
public Bitmap Image { get; set; }
public PreviewSettings(int width, int height, Thickness margin, Bitmap image)
{
Width = width;
Height = height;
Margin = margin;
Image = image;
}
}
}

View File

@ -3,6 +3,7 @@ using System.Drawing;
using System.Threading;
using System.Windows;
using Artemis.KeyboardProviders.Logitech.Utilities;
using Artemis.Properties;
using Artemis.Utilities;
using Artemis.Utilities.LogitechDll;
using Point = System.Drawing.Point;
@ -16,10 +17,11 @@ namespace Artemis.KeyboardProviders.Logitech
Name = "Logitech G910 RGB";
CantEnableText = "Couldn't connect to your Logitech G910.\n" +
"Please check your cables and updating the Logitech Gaming Software\n" +
"A minimum version of 8.81.15 is required).\n\n" +
"A minimum version of 8.81.15 is required.\n\n" +
"If needed, you can select a different keyboard in Artemis under settings.";
Height = 6;
Width = 21;
PreviewSettings = new PreviewSettings(626, 175, new Thickness(0, -15, 0, 0), Resources.g910);
KeyboardRegions = new List<KeyboardRegion>
{
new KeyboardRegion("TopRow", new Point(0, 0), new Point(18, 0)),
@ -40,6 +42,12 @@ namespace Artemis.KeyboardProviders.Logitech
// Turn it into one long number...
var version = int.Parse($"{majorNum}{minorNum}{buildNum}");
CantEnableText = "Couldn't connect to your Logitech G910.\n" +
"Please check your cables and updating the Logitech Gaming Software\n" +
$"A minimum version of 8.81.15 is required (detected {majorNum}.{minorNum}.{buildNum}).\n\n" +
"If the detected version differs from the version LGS is reporting, reinstall LGS or see the FAQ.\n\n" +
"If needed, you can select a different keyboard in Artemis under settings.";
return version >= 88115;
}

View File

@ -1,10 +1,8 @@
using System;
using System.Drawing;
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;
using Corale.Colore.Razer;
using Constants = Corale.Colore.Razer.Keyboard.Constants;
namespace Artemis.KeyboardProviders.Razer
{
@ -13,8 +11,8 @@ namespace Artemis.KeyboardProviders.Razer
public BlackWidow()
{
Name = "Razer BlackWidow Chroma";
CantEnableText = "Couldn't connect to your Razer BlackWidow Chroma.\n " +
"Please check your cables and try updating Razer Synapse.\n\n " +
CantEnableText = "Couldn't connect to your Razer BlackWidow Chroma.\n" +
"Please check your cables and try updating Razer Synapse.\n\n" +
"If needed, you can select a different keyboard in Artemis under settings.";
}
@ -24,9 +22,9 @@ namespace Artemis.KeyboardProviders.Razer
return false;
// Some people have Synapse installed, but not a Chroma keyboard, deal with this
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);
var blackWidowFound = Chroma.Instance.Query(Devices.Blackwidow).Connected;
var blackWidowTeFound = Chroma.Instance.Query(Devices.BlackwidowTe).Connected;
return blackWidowFound || blackWidowTeFound;
}
public override void Enable()

View File

@ -14,6 +14,7 @@ namespace Artemis.Managers
private readonly MainManager _mainManager;
private bool _clearing;
private EffectModel _pauseEffect;
private EffectModel _activeEffect;
public EffectManager(MainManager mainManager, IEventAggregator events)
{
@ -24,7 +25,16 @@ namespace Artemis.Managers
}
public List<EffectModel> EffectModels { get; set; }
public EffectModel ActiveEffect { get; private set; }
public EffectModel ActiveEffect
{
get { return _activeEffect; }
private set
{
_activeEffect = value;
_events.PublishOnUIThread(new ActiveEffectChanged(value?.Name));
}
}
public IEnumerable<OverlayModel> EnabledOverlays
{
@ -101,7 +111,7 @@ namespace Artemis.Managers
ActiveEffect.Enable();
// Let the ViewModels know
_events.PublishOnUIThread(new ActiveEffectChanged(ActiveEffect.Name));
//_events.PublishOnUIThread(new ActiveEffectChanged(ActiveEffect.Name));
_mainManager.Unpause();
_pauseEffect = null;
@ -143,7 +153,7 @@ namespace Artemis.Managers
General.Default.LastEffect = null;
General.Default.Save();
_events.PublishOnUIThread(new ActiveEffectChanged(""));
//_events.PublishOnUIThread(new ActiveEffectChanged(""));
_clearing = false;
_mainManager.Unpause();

View File

@ -1,23 +1,37 @@
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using Artemis.Events;
using Artemis.KeyboardProviders;
using Artemis.Settings;
using Caliburn.Micro;
namespace Artemis.Managers
{
public class KeyboardManager
{
private readonly IEventAggregator _events;
private readonly MainManager _mainManager;
private KeyboardProvider _activeKeyboard;
public KeyboardManager(MainManager mainManager)
public KeyboardManager(MainManager mainManager, IEventAggregator events)
{
_mainManager = mainManager;
_events = events;
KeyboardProviders = ProviderHelper.GetKeyboardProviders();
}
public List<KeyboardProvider> KeyboardProviders { get; set; }
public KeyboardProvider ActiveKeyboard { get; set; }
public KeyboardProvider ActiveKeyboard
{
get { return _activeKeyboard; }
set
{
_activeKeyboard = value;
// Let the ViewModels know
_events.PublishOnUIThread(new ActiveKeyboardChanged(value?.Name));
}
}
/// <summary>
/// Enables the last keyboard according to the settings file

View File

@ -2,7 +2,6 @@
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Windows.Forms;
using Artemis.Events;
using Artemis.Models;
using Artemis.Services;
@ -26,7 +25,7 @@ namespace Artemis.Managers
Events = events;
DialogService = dialogService;
KeyboardManager = new KeyboardManager(this);
KeyboardManager = new KeyboardManager(this, Events);
EffectManager = new EffectManager(this, Events);
KeyboardHook = new KeyboardHook();
@ -51,8 +50,8 @@ namespace Artemis.Managers
GameStateWebServer.Start();
// Start the named pipe
//PipeServer = new PipeServer();
//PipeServer.Start("artemis");
PipeServer = new PipeServer();
PipeServer.Start("artemis");
}
public PipeServer PipeServer { get; set; }

View File

@ -1,11 +1,15 @@
using Artemis.Managers;
using Artemis.Models.Interfaces;
using Artemis.Models.Profiles;
namespace Artemis.Models
{
public abstract class GameModel : EffectModel
{
public bool Enabled;
public string ProcessName;
public bool Enabled { get; set; }
public string ProcessName { get; set; }
public IGameDataModel GameDataModel { get; set; }
public ProfileModel Profile { get; set; }
protected GameModel(MainManager mainManager) : base(mainManager)
{

View File

@ -0,0 +1,6 @@
namespace Artemis.Models.Interfaces
{
public interface IGameDataModel
{
}
}

View File

@ -0,0 +1,32 @@
using System.Collections.Generic;
using System.Linq.Dynamic;
using Artemis.Models.Interfaces;
using Artemis.Utilities;
namespace Artemis.Models.Profiles
{
public class LayerConditionModel
{
public string Field { get; set; }
public string Value { get; set; }
public string Operator { get; set; }
public string Type { get; set; }
public bool ConditionMet<T>(IGameDataModel subject)
{
if (string.IsNullOrEmpty(Field) || string.IsNullOrEmpty(Value) || string.IsNullOrEmpty(Type))
return false;
var inspect = GeneralHelpers.GetPropertyValue(subject, Field);
if (inspect == null)
return false;
// Put the subject in a list, allowing Dynamic Linq to be used.
var subjectList = new List<T> {(T) subject};
var res = Type == "String"
? subjectList.Where($"{Field}.ToLower() {Operator} @0", Value.ToLower()).Any()
: subjectList.Where($"{Field} {Operator} {Value}").Any();
return res;
}
}
}

View File

@ -0,0 +1,67 @@
using System.ComponentModel;
using Artemis.Models.Interfaces;
using Artemis.Utilities;
using static System.Decimal;
namespace Artemis.Models.Profiles
{
public class LayerDynamicPropertiesModel
{
/// <summary>
/// Property this dynamic property applies on
/// </summary>
public string LayerProperty { get; set; }
/// <summary>
/// Property to base the percentage upon
/// </summary>
public string GameProperty { get; set; }
/// <summary>
/// Percentage source, the number that defines 100%
/// </summary>
public string PercentageSource { get; set; }
/// <summary>
/// Type of property
/// </summary>
public LayerPropertyType LayerPropertyType { get; set; }
internal void ApplyProperty<T>(IGameDataModel data, LayerPropertiesModel userProps, LayerPropertiesModel props)
{
if (LayerPropertyType == LayerPropertyType.PercentageOf)
Apply(props, userProps, data, int.Parse(PercentageSource));
if (LayerPropertyType == LayerPropertyType.PercentageOfProperty)
ApplyProp(props, userProps, data);
}
private void Apply(LayerPropertiesModel props, LayerPropertiesModel userProps, IGameDataModel data,
int percentageSource)
{
// Property to apply on
var layerProp = props.GetType().GetProperty(LayerProperty);
// User's settings
var userProp = userProps.GetType().GetProperty(LayerProperty);
// Property to base the percentage upon
var gameProperty = data.GetPropValue<int>(GameProperty);
if (layerProp == null || userProp == null)
return;
var percentage = ToDouble(gameProperty) / percentageSource;
layerProp.SetValue(props, (int) (percentage*(int) userProp.GetValue(userProps, null)));
}
private void ApplyProp(LayerPropertiesModel props, LayerPropertiesModel userProps, IGameDataModel data)
{
var value = data.GetPropValue<int>(PercentageSource);
Apply(props, userProps, data, value);
}
}
public enum LayerPropertyType
{
[Description("None")] None,
[Description("% of")] PercentageOf,
[Description("% of property")] PercentageOfProperty
}
}

View File

@ -0,0 +1,150 @@
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows.Media;
using System.Xml.Serialization;
using Artemis.Models.Interfaces;
using Artemis.Utilities;
using Artemis.Utilities.ParentChild;
namespace Artemis.Models.Profiles
{
public class LayerModel : IChildItem<LayerModel>, IChildItem<ProfileModel>
{
[XmlIgnore] private readonly LayerDrawer _drawer;
[XmlIgnore] private bool _mustDraw;
public LayerModel()
{
UserProps = new LayerPropertiesModel();
CalcProps = new LayerPropertiesModel();
Children = new ChildItemCollection<LayerModel, LayerModel>(this);
LayerConditions = new List<LayerConditionModel>();
LayerProperties = new List<LayerDynamicPropertiesModel>();
_mustDraw = true;
_drawer = new LayerDrawer(this, 4);
}
public string Name { get; set; }
public LayerType LayerType { get; set; }
public bool Enabled { get; set; }
public int Order { get; set; }
public LayerPropertiesModel UserProps { get; set; }
public ChildItemCollection<LayerModel, LayerModel> Children { get; }
public List<LayerConditionModel> LayerConditions { get; set; }
public List<LayerDynamicPropertiesModel> LayerProperties { get; set; }
[XmlIgnore]
public LayerPropertiesModel CalcProps { get; set; }
[XmlIgnore]
public ImageSource LayerImage => _drawer.GetThumbnail();
[XmlIgnore]
public LayerModel ParentLayer { get; internal set; }
[XmlIgnore]
public ProfileModel ParentProfile { get; internal set; }
public bool ConditionsMet<T>(IGameDataModel dataModel)
{
return Enabled && LayerConditions.All(cm => cm.ConditionMet<T>(dataModel));
}
public void DrawPreview(DrawingContext c)
{
GeneralHelpers.CopyProperties(CalcProps, UserProps);
if (LayerType == LayerType.Keyboard || LayerType == LayerType.Keyboard)
_drawer.Draw(c, _mustDraw);
else if (LayerType == LayerType.KeyboardGif)
_drawer.DrawGif(c);
_mustDraw = false;
}
public void Draw<T>(IGameDataModel dataModel, DrawingContext c)
{
if (!ConditionsMet<T>(dataModel))
return;
if (LayerType == LayerType.Folder)
foreach (var layerModel in Children.OrderByDescending(l => l.Order))
layerModel.Draw<T>(dataModel, c);
else if (LayerType == LayerType.Keyboard || LayerType == LayerType.Keyboard)
_drawer.Draw(c);
else if (LayerType == LayerType.KeyboardGif)
_drawer.DrawGif(c);
else if (LayerType == LayerType.Mouse)
_drawer.UpdateMouse();
else if (LayerType == LayerType.Headset)
_drawer.UpdateHeadset();
}
public void Update<T>(IGameDataModel dataModel)
{
if (LayerType == LayerType.Folder)
{
foreach (var layerModel in Children)
layerModel.Update<T>(dataModel);
return;
}
GeneralHelpers.CopyProperties(CalcProps, UserProps);
foreach (var dynamicProperty in LayerProperties)
dynamicProperty.ApplyProperty<T>(dataModel, UserProps, CalcProps);
}
public void Reorder(LayerModel selectedLayer, bool moveUp)
{
// Fix the sorting just in case
FixOrder();
int newOrder;
if (moveUp)
newOrder = selectedLayer.Order - 1;
else
newOrder = selectedLayer.Order + 1;
var target = Children.FirstOrDefault(l => l.Order == newOrder);
if (target == null)
return;
target.Order = selectedLayer.Order;
selectedLayer.Order = newOrder;
}
private void FixOrder()
{
Children.Sort(l => l.Order);
for (var i = 0; i < Children.Count; i++)
Children[i].Order = i;
}
#region IChildItem<Parent> Members
LayerModel IChildItem<LayerModel>.Parent
{
get { return ParentLayer; }
set { ParentLayer = value; }
}
ProfileModel IChildItem<ProfileModel>.Parent
{
get { return ParentProfile; }
set { ParentProfile = value; }
}
#endregion
}
public enum LayerType
{
[Description("Folder")] Folder,
[Description("Keyboard")] Keyboard,
[Description("Keyboard - GIF")] KeyboardGif,
[Description("Mouse")] Mouse,
[Description("Headset")] Headset
}
}

View File

@ -0,0 +1,41 @@
using System.ComponentModel;
using System.Windows;
using System.Windows.Media;
using System.Xml.Serialization;
namespace Artemis.Models.Profiles
{
[XmlInclude(typeof (SolidColorBrush))]
[XmlInclude(typeof (LinearGradientBrush))]
[XmlInclude(typeof (RadialGradientBrush))]
[XmlInclude(typeof (MatrixTransform))]
public class LayerPropertiesModel
{
public int X { get; set; }
public int Y { get; set; }
public int Width { get; set; }
public int Height { get; set; }
public double Opacity { get; set; }
public bool ContainedBrush { get; set; }
public LayerAnimation Animation { get; set; }
public double AnimationSpeed { get; set; }
public Brush Brush { get; set; }
public Rect GetRect(int scale = 4)
{
return new Rect(X*scale, Y*scale, Width*scale, Height*scale);
}
}
public enum LayerAnimation
{
[Description("None")] None,
[Description("Slide left")] SlideLeft,
[Description("Slide right")] SlideRight,
[Description("Slide up")] SlideUp,
[Description("Slide down")] SlideDown,
[Description("Grow")] Grow,
[Description("Pulse")] Pulse
}
}

View File

@ -0,0 +1,134 @@
using System.Drawing;
using System.Linq;
using System.Windows;
using System.Windows.Media;
using Artemis.Models.Interfaces;
using Artemis.Utilities;
using Artemis.Utilities.ParentChild;
using Color = System.Windows.Media.Color;
namespace Artemis.Models.Profiles
{
public class ProfileModel
{
public ProfileModel()
{
Layers = new ChildItemCollection<ProfileModel, LayerModel>(this);
DrawingVisual = new DrawingVisual();
}
public ChildItemCollection<ProfileModel, LayerModel> Layers { get; }
public string Name { get; set; }
public string KeyboardName { get; set; }
public string GameName { get; set; }
public DrawingVisual DrawingVisual { get; set; }
protected bool Equals(ProfileModel other)
{
return string.Equals(Name, other.Name) && string.Equals(KeyboardName, other.KeyboardName) &&
string.Equals(GameName, other.GameName);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != GetType()) return false;
return Equals((ProfileModel) obj);
}
public override int GetHashCode()
{
unchecked
{
var hashCode = Name?.GetHashCode() ?? 0;
hashCode = (hashCode*397) ^ (KeyboardName?.GetHashCode() ?? 0);
hashCode = (hashCode*397) ^ (GameName?.GetHashCode() ?? 0);
return hashCode;
}
}
/// <summary>
/// Adds a new layer with default settings to the profile
/// </summary>
/// <returns>The newly added layer</returns>
public LayerModel AddLayer()
{
var layer = new LayerModel
{
Name = "New layer",
Enabled = true,
Order = -1,
LayerType = LayerType.Keyboard,
UserProps = new LayerPropertiesModel
{
Brush = new SolidColorBrush(ColorHelpers.GetRandomRainbowMediaColor()),
Animation = LayerAnimation.None,
Height = 1,
Width = 1,
X = 0,
Y = 0,
Opacity = 1
}
};
Layers.Add(layer);
FixOrder();
return layer;
}
public void Reorder(LayerModel selectedLayer, bool moveUp)
{
// Fix the sorting just in case
FixOrder();
int newOrder;
if (moveUp)
newOrder = selectedLayer.Order - 1;
else
newOrder = selectedLayer.Order + 1;
var target = Layers.FirstOrDefault(l => l.Order == newOrder);
if (target == null)
return;
target.Order = selectedLayer.Order;
selectedLayer.Order = newOrder;
}
public void FixOrder()
{
Layers.Sort(l => l.Order);
for (var i = 0; i < Layers.Count; i++)
Layers[i].Order = i;
}
public Bitmap GenerateBitmap<T>(Rect keyboardRect, IGameDataModel gameDataModel)
{
Bitmap bitmap = null;
DrawingVisual.Dispatcher.Invoke(delegate
{
var visual = new DrawingVisual();
using (var c = visual.RenderOpen())
{
// Setup the DrawingVisual's size
c.PushClip(new RectangleGeometry(keyboardRect));
c.DrawRectangle(new SolidColorBrush(Color.FromArgb(0, 0, 0, 0)), null, keyboardRect);
// Draw the layers
foreach (var layerModel in Layers.OrderByDescending(l => l.Order))
layerModel.Draw<T>(gameDataModel, c);
// Remove the clip
c.Pop();
}
bitmap = ImageUtilities.DrawinVisualToBitmap(visual, keyboardRect);
});
return bitmap;
}
}
}

View File

@ -0,0 +1,124 @@
using Artemis.Models.Interfaces;
namespace Artemis.Modules.Games.CounterStrike
{
public class CounterStrikeDataModel : IGameDataModel
{
public Provider provider { get; set; }
public Map map { get; set; }
public Round round { get; set; }
public Player player { 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 string steamid { get; set; }
public int timestamp { get; set; }
}
public class TeamCt
{
public int score { get; set; }
}
public class TeamT
{
public int score { get; set; }
}
public class Map
{
public string mode { get; set; }
public string name { get; set; }
public string phase { get; set; }
public int round { get; set; }
public TeamCt team_ct { get; set; }
public TeamT team_t { get; set; }
}
public class Round
{
public string phase { get; set; }
}
public class State
{
public int health { get; set; }
public int armor { get; set; }
public bool helmet { get; set; }
public int flashed { get; set; }
public int smoked { get; set; }
public int burning { get; set; }
public int money { get; set; }
public int round_kills { get; set; }
public int round_killhs { get; set; }
}
public class Weapon0
{
public string name { get; set; }
public string paintkit { get; set; }
public string type { get; set; }
public string state { get; set; }
}
public class Weapon1
{
public string name { get; set; }
public string paintkit { get; set; }
public string type { get; set; }
public int ammo_clip { get; set; }
public int ammo_clip_max { get; set; }
public int ammo_reserve { get; set; }
public string state { get; set; }
}
public class Weapon2
{
public string name { get; set; }
public string paintkit { get; set; }
public string type { get; set; }
public string state { get; set; }
}
public class Weapons
{
public Weapon0 weapon_0 { get; set; }
public Weapon1 weapon_1 { get; set; }
public Weapon2 weapon_2 { get; set; }
}
public class MatchStats
{
public int kills { get; set; }
public int assists { get; set; }
public int deaths { get; set; }
public int mvps { get; set; }
public int score { get; set; }
}
public class Player
{
public string steamid { get; set; }
public string name { get; set; }
public string team { get; set; }
public string activity { get; set; }
public State state { get; set; }
public Weapons weapons { get; set; }
public MatchStats match_stats { get; set; }
}
public class Round2
{
public string phase { get; set; }
}
public class Previously
{
public Round2 round { get; set; }
}
}

View File

@ -1,23 +1,14 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using Artemis.KeyboardProviders;
using Artemis.Managers;
using Artemis.Models;
using Artemis.Utilities;
using Artemis.Utilities.GameState;
using Artemis.Utilities.Keyboard;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Artemis.Modules.Games.CounterStrike
{
public class CounterStrikeModel : GameModel
{
private KeyboardRegion _topRow;
public CounterStrikeModel(MainManager mainManager, CounterStrikeSettings settings) : base(mainManager)
{
Settings = settings;
@ -30,14 +21,6 @@ namespace Artemis.Modules.Games.CounterStrike
public CounterStrikeSettings Settings { get; set; }
public KeyboardRectangle EventRect { get; set; }
public KeyboardRectangle TeamRect { get; set; }
public KeyboardRectangle AmmoRect { get; set; }
public JObject CsJson { get; set; }
public bool DrawingSmoke { get; set; }
public bool DrawingFlash { get; set; }
public int Scale { get; set; }
public override void Dispose()
@ -50,23 +33,7 @@ namespace Artemis.Modules.Games.CounterStrike
{
Initialized = false;
// Some keyboards have a different baseline, Corsair F-keys start at row 1
_topRow = MainManager.KeyboardManager.ActiveKeyboard.KeyboardRegions.First(r => r.RegionName == "TopRow");
AmmoRect = new KeyboardRectangle(MainManager.KeyboardManager.ActiveKeyboard, 0, _topRow.TopLeft.X,
new List<Color>(),
LinearGradientMode.Horizontal) {Height = Scale, ContainedBrush = false};
TeamRect = new KeyboardRectangle(MainManager.KeyboardManager.ActiveKeyboard, 0, _topRow.TopLeft.X + 1,
new List<Color>(),
LinearGradientMode.Horizontal)
{
Height = MainManager.KeyboardManager.ActiveKeyboard.Height*Scale - Scale
};
EventRect = new KeyboardRectangle(MainManager.KeyboardManager.ActiveKeyboard, 0, _topRow.TopLeft.X + 1,
new List<Color>(),
LinearGradientMode.Horizontal)
{
Height = MainManager.KeyboardManager.ActiveKeyboard.Height*Scale - Scale
};
GameDataModel = new CounterStrikeDataModel();
MainManager.GameStateWebServer.GameDataReceived += HandleGameData;
Initialized = true;
@ -74,124 +41,20 @@ namespace Artemis.Modules.Games.CounterStrike
public override void Update()
{
if (CsJson == null)
if (Profile == null || GameDataModel == null)
return;
if (Settings.AmmoEnabled)
UpdateAmmo();
if (Settings.TeamColorEnabled)
UpdateTeam();
if (Settings.LowHpEnabled)
UpdateHealth();
if (Settings.FlashEnabled)
UpdateFlash();
if (Settings.SmokeEnabled)
UpdateSmoke();
}
private void UpdateHealth()
{
if (CsJson["player"]?["state"]?["health"] == null)
return;
var health = CsJson["player"]["state"]["health"].Value<int>();
if (health > 25 || health < 1)
return;
TeamRect.Colors = new List<Color> {Color.Red, Color.OrangeRed, Color.Red, Color.OrangeRed};
}
private void UpdateSmoke()
{
if (CsJson["player"]?["state"]?["smoked"] == null)
return;
var smoked = CsJson["player"]["state"]["smoked"].Value<int>();
if (smoked == 0 && !DrawingSmoke)
return;
EventRect.Colors = new List<Color> {Color.FromArgb(smoked, 255, 255, 255)};
DrawingSmoke = smoked != 0;
}
private void UpdateFlash()
{
if (CsJson["player"]?["state"]?["flashed"] == null)
return;
var flashed = CsJson["player"]["state"]["flashed"].Value<int>();
if (flashed == 0 && !DrawingFlash)
return;
EventRect.Colors = new List<Color> {Color.FromArgb(flashed, 255, 255, 255)};
DrawingFlash = flashed != 0;
}
private void UpdateTeam()
{
var currentTeam = CsJson["player"]?["team"];
if (currentTeam == null)
return;
var t1 = Color.FromArgb(255, 255, 129, 0);
var t2 = Color.FromArgb(255, 255, 170, 125);
var ct1 = Color.FromArgb(255, 203, 238, 255);
var ct2 = Color.FromArgb(255, 0, 173, 255);
TeamRect.Colors = currentTeam.Value<string>() == "T"
? new List<Color> {t1, t2, t1, t2}
: new List<Color> {ct1, ct2, ct1, ct2};
TeamRect.Rotate = true;
}
private void UpdateAmmo()
{
if (CsJson["player"]["weapons"] == null)
return;
var activeWeapon =
CsJson["player"]["weapons"].Children()
.Select(c => c.First)
.FirstOrDefault(w => w["state"]?.Value<string>() == "active");
// Update the ammo display
if (activeWeapon?["ammo_clip_max"] == null || activeWeapon["ammo_clip"] == null)
return;
var maxAmmo = activeWeapon["ammo_clip_max"].Value<int>();
var ammo = activeWeapon["ammo_clip"].Value<int>();
if (maxAmmo < 0)
return;
var ammoPercentage = (int) Math.Ceiling(100.00/maxAmmo)*ammo;
AmmoRect.Width = (int) Math.Floor(_topRow.BottomRight.Y/100.00*ammoPercentage)*Scale;
AmmoRect.Colors = new List<Color>
{
ColorHelpers.ToDrawingColor(Settings.AmmoMainColor),
ColorHelpers.ToDrawingColor(Settings.AmmoSecondaryColor)
};
// Low ammo indicator
if (ammoPercentage < 37)
AmmoRect.StartBlink(1000);
else
AmmoRect.StopBlink();
foreach (var layerModel in Profile.Layers)
layerModel.Update<CounterStrikeDataModel>(GameDataModel);
}
public override Bitmap GenerateBitmap()
{
var bitmap = MainManager.KeyboardManager.ActiveKeyboard.KeyboardBitmap(Scale);
if (Profile == null || GameDataModel == null)
return null;
using (var g = Graphics.FromImage(bitmap))
{
g.Clear(Color.Transparent);
AmmoRect.Draw(g);
TeamRect.Draw(g);
EventRect.Draw(g);
}
return bitmap;
var keyboardRect = MainManager.KeyboardManager.ActiveKeyboard.KeyboardRectangle(Scale);
return Profile.GenerateBitmap<CounterStrikeDataModel>(keyboardRect, GameDataModel);
}
public void HandleGameData(object sender, GameDataReceivedEventArgs e)
@ -203,7 +66,7 @@ namespace Artemis.Modules.Games.CounterStrike
return;
// Parse the JSON
CsJson = JsonConvert.DeserializeObject<JObject>(jsonString);
GameDataModel = JsonConvert.DeserializeObject<CounterStrikeDataModel>(jsonString);
}
}
}

View File

@ -19,11 +19,6 @@
<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="*" />
</Grid.RowDefinitions>
@ -58,73 +53,11 @@
</Grid>
</StackPanel>
<!-- Ammo display -->
<TextBlock Grid.Row="2" Grid.Column="0" HorizontalAlignment="Left" Width="130" VerticalAlignment="Center"
Height="16" Margin="0,10,0,9">
Display ammo on F-keys
</TextBlock>
<controls:ToggleSwitch IsChecked="{Binding Path=GameSettings.AmmoEnabled, Mode=TwoWay}"
Grid.Row="2" Grid.Column="1" HorizontalAlignment="Right" OnLabel="Yes" OffLabel="No"
Margin="0,0,-5,0" Width="114" />
<!-- Ammo main color -->
<TextBlock Grid.Row="3" Grid.Column="0" HorizontalAlignment="Left" Width="94" VerticalAlignment="Center"
Height="16" Margin="0,8">
Main ammo color
</TextBlock>
<xctk:ColorPicker x:Name="MainColor"
SelectedColor="{Binding Path=GameSettings.AmmoMainColor, Mode=TwoWay}"
Grid.Row="3" Grid.Column="1" Width="110" HorizontalAlignment="Right"
VerticalAlignment="Center" Margin="0,5,-1,5" Height="22" />
<!-- Ammo secondary color -->
<TextBlock Grid.Row="4" Grid.Column="0" HorizontalAlignment="Left" Width="122" VerticalAlignment="Center"
Height="16" Margin="0,8">
Secondary ammo color
</TextBlock>
<xctk:ColorPicker x:Name="SecondaryColor"
SelectedColor="{Binding Path=GameSettings.AmmoSecondaryColor, Mode=TwoWay}"
Grid.Row="4" Grid.Column="1" Width="110" HorizontalAlignment="Right"
VerticalAlignment="Center" Margin="0,5,-1,5" Height="22" />
<!-- Smoke effect -->
<TextBlock Grid.Row="5" Grid.Column="0" HorizontalAlignment="Left" Width="116" VerticalAlignment="Center"
Height="16" Margin="0,9,0,10">
Display smoked effect
</TextBlock>
<controls:ToggleSwitch IsChecked="{Binding Path=GameSettings.SmokeEnabled, Mode=TwoWay}"
Grid.Row="5" Grid.Column="1" HorizontalAlignment="Right" OnLabel="Yes" OffLabel="No"
Margin="0,0,-5,0" Width="114" />
<!-- Flash effect -->
<TextBlock Grid.Row="6" Grid.Column="0" HorizontalAlignment="Left" Width="113" VerticalAlignment="Center"
Height="16" Margin="0,10,0,9">
Display flashed effect
</TextBlock>
<controls:ToggleSwitch IsChecked="{Binding Path=GameSettings.FlashEnabled, Mode=TwoWay}"
Grid.Row="6" Grid.Column="1" HorizontalAlignment="Right" OnLabel="Yes" OffLabel="No"
Margin="0,0,-5,0" Width="114" />
<!-- Team color -->
<TextBlock Grid.Row="7" Grid.Column="0" HorizontalAlignment="Left" Width="181" VerticalAlignment="Center"
Height="16" Margin="0,9,0,10">
Color keyboard according to team
</TextBlock>
<controls:ToggleSwitch IsChecked="{Binding Path=GameSettings.TeamColorEnabled, Mode=TwoWay}"
Grid.Row="7" Grid.Column="1" HorizontalAlignment="Right" OnLabel="Yes" OffLabel="No"
Margin="0,0,-5,0" Width="114" />
<!-- Team color -->
<TextBlock Grid.Row="8" Grid.Column="0" HorizontalAlignment="Left" Width="160" VerticalAlignment="Center"
Height="16" Margin="0,10,0,9">
Color keyboard red on low HP
</TextBlock>
<controls:ToggleSwitch IsChecked="{Binding Path=GameSettings.LowHpEnabled, Mode=TwoWay}"
Grid.Row="8" Grid.Column="1" HorizontalAlignment="Right" OnLabel="Yes" OffLabel="No"
Margin="0,0,-5,0" Width="114" />
<!-- Profile editor -->
<ContentControl Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" x:Name="ProfileEditor" Margin="0,0,-30,0" />
<!-- Buttons -->
<StackPanel Grid.Column="0" Grid.Row="9" Orientation="Horizontal" VerticalAlignment="Bottom">
<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"

View File

@ -1,7 +1,9 @@
using System.IO;
using System.ComponentModel;
using System.IO;
using System.Windows.Forms;
using Artemis.Managers;
using Artemis.Properties;
using Artemis.ViewModels;
using Artemis.ViewModels.Abstract;
namespace Artemis.Modules.Games.CounterStrike
@ -19,8 +21,20 @@ namespace Artemis.Modules.Games.CounterStrike
GameModel = new CounterStrikeModel(mainManager, (CounterStrikeSettings) GameSettings);
MainManager.EffectManager.EffectModels.Add(GameModel);
PlaceConfigFile();
ProfileEditor = new ProfileEditorViewModel<CounterStrikeDataModel>(MainManager, GameModel);
ProfileEditor.PropertyChanged += ProfileUpdater;
GameModel.Profile = ProfileEditor.SelectedProfile;
}
private void ProfileUpdater(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "SelectedProfile")
GameModel.Profile = ProfileEditor.SelectedProfile;
}
public ProfileEditorViewModel<CounterStrikeDataModel> ProfileEditor { get; set; }
public static string Name => "CS:GO";
public string Content => "Counter-Strike: GO Content";

View File

@ -0,0 +1,9 @@
using Artemis.Models.Interfaces;
namespace Artemis.Modules.Games.RocketLeague
{
public class RocketLeagueDataModel : IGameDataModel
{
public int Boost { get; set; }
}
}

View File

@ -1,15 +1,10 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Artemis.Managers;
using Artemis.Models;
using Artemis.Settings;
using Artemis.Utilities;
using Artemis.Utilities.Keyboard;
using Artemis.Utilities.Memory;
using Newtonsoft.Json;
@ -17,13 +12,8 @@ namespace Artemis.Modules.Games.RocketLeague
{
public class RocketLeagueModel : GameModel
{
private int _boostAmount;
private bool _boostGrowing;
private KeyboardRectangle _boostRect;
private bool _contextualColor;
private Memory _memory;
private GamePointersCollection _pointer;
private int _previousBoost;
public RocketLeagueModel(MainManager mainManager, RocketLeagueSettings settings) : base(mainManager)
{
@ -49,105 +39,44 @@ namespace Artemis.Modules.Games.RocketLeague
{
Initialized = false;
_contextualColor = Settings.ContextualColor;
_boostRect = new KeyboardRectangle(MainManager.KeyboardManager.ActiveKeyboard, 0, 0, new List<Color>
{
ColorHelpers.ToDrawingColor(Settings.MainColor),
ColorHelpers.ToDrawingColor(Settings.SecondaryColor)
}, LinearGradientMode.Horizontal);
Updater.GetPointers();
_pointer = JsonConvert.DeserializeObject<GamePointersCollection>(Offsets.Default.RocketLeague);
var tempProcess = MemoryHelpers.GetProcessIfRunning(ProcessName);
_memory = new Memory(tempProcess);
GameDataModel = new RocketLeagueDataModel();
Initialized = true;
}
public override void Update()
{
if (_boostGrowing)
return;
if (_memory == null)
if (Profile == null || GameDataModel == null || _memory == null)
return;
var offsets = _pointer.GameAddresses.First(ga => ga.Description == "Boost").ToString();
var boostAddress = _memory.GetAddress("\"RocketLeague.exe\"" + offsets);
var boostFloat = _memory.ReadFloat(boostAddress)*100/3;
_previousBoost = _boostAmount;
_boostAmount = (int) Math.Ceiling(boostFloat);
((RocketLeagueDataModel) GameDataModel).Boost = (int) Math.Ceiling(boostFloat);
// Take care of any reading errors resulting in an OutOfMemory on draw
if (_boostAmount < 0)
_boostAmount = 0;
if (_boostAmount > 100)
_boostAmount = 100;
if (((RocketLeagueDataModel) GameDataModel).Boost < 0)
((RocketLeagueDataModel) GameDataModel).Boost = 0;
if (((RocketLeagueDataModel) GameDataModel).Boost > 100)
((RocketLeagueDataModel) GameDataModel).Boost = 100;
_boostRect.Width =
(int) Math.Ceiling(MainManager.KeyboardManager.ActiveKeyboard.Width*Scale/100.00*_boostAmount);
if (_contextualColor)
{
if (_boostAmount < 33)
_boostRect.Colors = new List<Color> {Color.Red};
else if (_boostAmount >= 33 && _boostAmount < 66)
_boostRect.Colors = new List<Color> {Color.Yellow};
else if (_boostAmount >= 66)
_boostRect.Colors = new List<Color> {Color.Lime};
}
Task.Run(() => GrowIfHigher());
}
private void GrowIfHigher()
{
if (_boostAmount <= _previousBoost || _boostGrowing)
return;
_boostGrowing = true;
const int amountOfSteps = 6;
var difference = _boostAmount - _previousBoost;
var differenceStep = difference/amountOfSteps;
var differenceStepRest = difference%amountOfSteps;
_boostAmount = _previousBoost;
_boostRect.Width =
(int) Math.Ceiling(MainManager.KeyboardManager.ActiveKeyboard.Width*Scale/100.00*_boostAmount);
for (var i = 0; i < amountOfSteps; i++)
{
if (differenceStepRest > 0)
{
differenceStepRest -= 1;
_boostAmount += 1;
_boostRect.Width =
(int) Math.Ceiling(MainManager.KeyboardManager.ActiveKeyboard.Width*Scale/100.00*_boostAmount);
}
_boostAmount += differenceStep;
_boostRect.Width =
(int) Math.Ceiling(MainManager.KeyboardManager.ActiveKeyboard.Width*Scale/100.00*_boostAmount);
Thread.Sleep(50);
}
_boostGrowing = false;
foreach (var layerModel in Profile.Layers)
layerModel.Update<RocketLeagueDataModel>(GameDataModel);
}
public override Bitmap GenerateBitmap()
{
var bitmap = MainManager.KeyboardManager.ActiveKeyboard.KeyboardBitmap(Scale);
if (_boostRect == null)
if (Profile == null || GameDataModel == null)
return null;
using (var g = Graphics.FromImage(bitmap))
{
g.Clear(Color.Transparent);
_boostRect.Draw(g);
}
return bitmap;
var keyboardRect = MainManager.KeyboardManager.ActiveKeyboard.KeyboardRectangle(Scale);
return Profile.GenerateBitmap<RocketLeagueDataModel>(keyboardRect, GameDataModel);
}
}
}

View File

@ -40,46 +40,8 @@
</StackPanel>
</StackPanel>
<!-- Main color -->
<TextBlock Grid.Row="1" Grid.Column="0" HorizontalAlignment="Left" VerticalAlignment="Center"
Height="16" Margin="0,8">
Main boost display color
</TextBlock>
<xctk:ColorPicker x:Name="MainColor"
SelectedColor="{Binding Path=GameSettings.MainColor, Mode=TwoWay}"
Grid.Row="1" Grid.Column="1" Width="110" HorizontalAlignment="Right"
VerticalAlignment="Center" Margin="0,5,-1,5" Height="22" />
<!-- Secondary color -->
<TextBlock Grid.Row="2" Grid.Column="0" HorizontalAlignment="Left" VerticalAlignment="Center"
Height="16" Margin="0,8">
Secondary boost display color
</TextBlock>
<xctk:ColorPicker x:Name="SecondaryColor"
SelectedColor="{Binding Path=GameSettings.SecondaryColor, Mode=TwoWay}"
Grid.Row="2" Grid.Column="1" Width="110" HorizontalAlignment="Right"
VerticalAlignment="Center" Margin="0,5,-1,5" Height="22" />
<!-- Secondary color -->
<TextBlock Grid.Row="3" Grid.Column="0" HorizontalAlignment="Left" VerticalAlignment="Center"
Height="16" Margin="0,8">
Color bar according to boost amount
</TextBlock>
<controls:ToggleSwitch IsChecked="{Binding Path=GameSettings.ContextualColor, Mode=TwoWay}"
Grid.Row="3" Grid.Column="1" HorizontalAlignment="Right" OnLabel="Yes" OffLabel="No"
Margin="0,0,-5,0" Width="114" />
<!-- Info text -->
<TextBlock Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="2" VerticalAlignment="Center" Margin="0,8"
TextWrapping="Wrap" HorizontalAlignment="Left" FontFamily="Segoe UI Semibold"
MaxWidth="510" TextAlignment="Justify">
Tip: To find a color combination you like, start an exhibition match, pickup 100 boost and play around with the colors.
They'll appear on your keyboard immediately! Once you're satisfied don't forget to click save changes.
</TextBlock>
<TextBlock x:Name="VersionText" Grid.Row="5" 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" />
<!-- Profile editor -->
<ContentControl Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" x:Name="ProfileEditor" Margin="0,0,-30,0" />
<!-- Buttons -->
<StackPanel Grid.Column="0" Grid.Row="9" Orientation="Horizontal" VerticalAlignment="Bottom">

View File

@ -1,7 +1,9 @@
using Artemis.Managers;
using System.ComponentModel;
using Artemis.Managers;
using Artemis.Settings;
using Artemis.Utilities;
using Artemis.Utilities.Memory;
using Artemis.ViewModels;
using Artemis.ViewModels.Abstract;
using Newtonsoft.Json;
@ -21,10 +23,15 @@ namespace Artemis.Modules.Games.RocketLeague
// Create effect model and add it to MainManager
GameModel = new RocketLeagueModel(mainManager, (RocketLeagueSettings) GameSettings);
MainManager.EffectManager.EffectModels.Add(GameModel);
SetVersionText();
ProfileEditor = new ProfileEditorViewModel<RocketLeagueDataModel>(MainManager, GameModel);
ProfileEditor.PropertyChanged += ProfileUpdater;
GameModel.Profile = ProfileEditor.SelectedProfile;
}
public ProfileEditorViewModel<RocketLeagueDataModel> ProfileEditor { get; set; }
public static string Name => "Rocket League";
public string VersionText
@ -40,6 +47,12 @@ namespace Artemis.Modules.Games.RocketLeague
public RocketLeagueModel RocketLeagueModel { get; set; }
private void ProfileUpdater(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "SelectedProfile")
GameModel.Profile = ProfileEditor.SelectedProfile;
}
private void SetVersionText()
{
if (!General.Default.EnablePointersUpdate)

View File

@ -1,29 +1,31 @@
using System.Collections.Generic;
using System;
using Artemis.Models.Interfaces;
namespace Artemis.Modules.Games.TheDivision
{
public class TheDivisionDataModel
public class TheDivisionDataModel : IGameDataModel
{
public List<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>();
TestyTest = new TestTest();
}
public PlayerState PartyMember1 { get; set; }
public PlayerState PartyMember2 { get; set; }
public PlayerState PartyMember3 { get; set; }
public bool LowAmmo { get; set; }
public bool LowHp { get; set; }
public GrenadeState GrenadeState { get; set; }
public TestTest TestyTest { get; set; }
}
public class DivisionPlayer
{
public int Id { get; set; }
public PlayerState PlayerState { get; set; }
public DivisionPlayer(int id)
{
Id = id;
}
public class TestTest
{
public string TestS { get; set; }
public int TestI { get; set; }
}
public enum GrenadeState

View File

@ -1,14 +1,12 @@
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using Artemis.Managers;
using Artemis.Models;
using Artemis.Modules.Effects.TypeWave;
using Artemis.Utilities;
using Artemis.Utilities.Keyboard;
using Artemis.Utilities.LogitechDll;
using CUE.NET;
namespace Artemis.Modules.Games.TheDivision
{
@ -95,8 +93,6 @@ namespace Artemis.Modules.Games.TheDivision
DllManager.PlaceDll();
_dataModel = new TheDivisionDataModel();
for (var i = 1; i < 5; i++)
_dataModel.DivisionPlayers.Add(new DivisionPlayer(i));
MainManager.PipeServer.PipeMessage += PipeServerOnPipeMessage;
Initialized = true;
@ -118,7 +114,7 @@ namespace Artemis.Modules.Games.TheDivision
}
// Parses Division key data to game data
private void InterpertrateDivisionKey(int[] parts)
private void InterpertrateDivisionKey(IReadOnlyList<int> parts)
{
var keyCode = parts[1];
var rPer = parts[2];
@ -129,16 +125,21 @@ namespace Artemis.Modules.Games.TheDivision
if (keyCode >= 59 && keyCode <= 62)
{
var playerId = keyCode - 58;
var playerDataModel = _dataModel.DivisionPlayers.FirstOrDefault(p => p.Id == playerId);
if (playerDataModel == null)
return;
PlayerState newState;
if (gPer > 10)
playerDataModel.PlayerState = PlayerState.Online;
newState = PlayerState.Online;
else if (rPer > 10)
playerDataModel.PlayerState = PlayerState.Hit;
newState = PlayerState.Hit;
else
playerDataModel.PlayerState = PlayerState.Offline;
newState = PlayerState.Offline;
if (playerId == 1)
_dataModel.PartyMember1 = newState;
else if (playerId == 2)
_dataModel.PartyMember2 = newState;
else if (playerId == 3)
_dataModel.PartyMember3 = newState;
}
// R blinks white when low on ammo
else if (keyCode == 19)
@ -180,40 +181,28 @@ namespace Artemis.Modules.Games.TheDivision
_hpRect.Colors = _dataModel.LowHp
? new List<Color> {Color.Red, Color.Orange}
: new List<Color> {Color.FromArgb(10, 255, 0), Color.FromArgb(80, 255, 45) };
: new List<Color> {Color.FromArgb(10, 255, 0), Color.FromArgb(80, 255, 45)};
if (_dataModel.DivisionPlayers[1].PlayerState == PlayerState.Offline)
if (_dataModel.PartyMember1 == PlayerState.Offline)
_p2.Colors = new List<Color> {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 if (_dataModel.PartyMember1 == PlayerState.Online)
_p2.Colors = new List<Color> {Color.FromArgb(10, 255, 0), Color.FromArgb(80, 255, 45)};
else
_p2.Colors = new List<Color> {Color.Red, Color.Orange};
if (_dataModel.DivisionPlayers[2].PlayerState == PlayerState.Offline)
if (_dataModel.PartyMember2 == 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 if (_dataModel.PartyMember2 == PlayerState.Online)
_p3.Colors = new List<Color> {Color.FromArgb(10, 255, 0), Color.FromArgb(80, 255, 45)};
else
_p3.Colors = new List<Color> {Color.Red, Color.Orange};
if (_dataModel.DivisionPlayers[3].PlayerState == PlayerState.Offline)
if (_dataModel.PartyMember3 == 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 if (_dataModel.PartyMember3 == PlayerState.Online)
_p4.Colors = new List<Color> {Color.FromArgb(10, 255, 0), Color.FromArgb(80, 255, 45)};
else
_p4.Colors = new List<Color> {Color.Red, Color.Orange};
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()

View File

@ -17,6 +17,7 @@
<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">
@ -41,6 +42,9 @@
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>
<!-- Profile editor -->
<ContentControl Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" x:Name="ProfileEditor" Margin="0,0,-30,0" />
<!-- Buttons -->
<StackPanel Grid.Column="0" Grid.Row="4" Orientation="Horizontal" VerticalAlignment="Bottom">
<Button x:Name="ResetSettings" Content="Reset effect" VerticalAlignment="Top" Width="100"

View File

@ -1,4 +1,5 @@
using Artemis.Managers;
using Artemis.ViewModels;
using Artemis.ViewModels.Abstract;
namespace Artemis.Modules.Games.TheDivision
@ -15,8 +16,12 @@ namespace Artemis.Modules.Games.TheDivision
// Create effect model and add it to MainManager
GameModel = new TheDivisionModel(mainManager, (TheDivisionSettings) GameSettings);
MainManager.EffectManager.EffectModels.Add(GameModel);
ProfileEditor = new ProfileEditorViewModel<TheDivisionDataModel>(MainManager, GameModel);
}
public ProfileEditorViewModel<TheDivisionDataModel> ProfileEditor { get; set; }
public static string Name => "The Division";
}
}

View File

@ -91,10 +91,7 @@ namespace Artemis.Properties {
/// 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;timeout&quot; &quot;0.1&quot;
/// &quot;data&quot;
/// {
/// &quot;provider&quot; &quot;1&quot;
@ -116,7 +113,7 @@ namespace Artemis.Properties {
/// <summary>
/// Looks up a localized string similar to &quot;Artemis&quot;
///{
/// &quot;uri&quot; &quot;http://localhost:4000/&quot;
/// &quot;uri&quot; &quot;http://localhost:{{port}}/&quot;
/// &quot;timeout&quot; &quot;5.0&quot;
/// &quot;buffer&quot; &quot;0.1&quot;
/// &quot;throttle&quot; &quot;0.1&quot;
@ -138,6 +135,56 @@ namespace Artemis.Properties {
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap folder {
get {
object obj = ResourceManager.GetObject("folder", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap g910 {
get {
object obj = ResourceManager.GetObject("g910", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap k65 {
get {
object obj = ResourceManager.GetObject("k65", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap k70 {
get {
object obj = ResourceManager.GetObject("k70", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap k95 {
get {
object obj = ResourceManager.GetObject("k95", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
@ -191,5 +238,15 @@ namespace Artemis.Properties {
return ResourceManager.GetString("playerWitcherWs", resourceCulture);
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap strafe {
get {
object obj = ResourceManager.GetObject("strafe", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
}
}

View File

@ -142,4 +142,22 @@
<data name="playerWitcherWs" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\resources\witcher3\playerwitcher.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-16</value>
</data>
<data name="folder" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\folder.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="k65" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\resources\keyboards\k65.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="k70" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\resources\keyboards\k70.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="k95" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\resources\keyboards\k95.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="strafe" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\resources\keyboards\strafe.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="g910" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Keyboards\g910.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>

View File

@ -1,10 +1,7 @@
"Artemis"
{
"uri" "http://localhost:{{port}}/csgo_game_event"
"timeout" "5.0"
"buffer" "0.1"
"throttle" "0.1"
"heartbeat" "30.0"
"timeout" "0.1"
"data"
{
"provider" "1"

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 292 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 284 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 308 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -1,24 +1,24 @@
//The MIT License(MIT)
// The MIT License(MIT)
//Copyright(c) 2015 ihtfw
// Copyright(c) 2015 ihtfw
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
using System.Linq;
using System.Threading.Tasks;

View File

@ -0,0 +1,53 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:options="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="options">
<Color x:Key="HighlightColor">#C0A200</Color>
<Color x:Key="AccentBaseColor">#FFF0CF1E</Color>
<!--80%-->
<Color x:Key="AccentColor">#FFF0CF1E</Color>
<!--60%-->
<Color x:Key="AccentColor2">#FFF0CF1E</Color>
<!--40%-->
<Color x:Key="AccentColor3">#FFF0CF1E</Color>
<!--20%-->
<Color x:Key="AccentColor4">#FFF0CF1E</Color>
<!-- re-set brushes too -->
<SolidColorBrush x:Key="HighlightBrush" Color="{StaticResource HighlightColor}" options:Freeze="True" />
<SolidColorBrush x:Key="AccentBaseColorBrush" Color="{StaticResource AccentBaseColor}" options:Freeze="True" />
<SolidColorBrush x:Key="AccentColorBrush" Color="{StaticResource AccentColor}" options:Freeze="True" />
<SolidColorBrush x:Key="AccentColorBrush2" Color="{StaticResource AccentColor2}" options:Freeze="True" />
<SolidColorBrush x:Key="AccentColorBrush3" Color="{StaticResource AccentColor3}" options:Freeze="True" />
<SolidColorBrush x:Key="AccentColorBrush4" Color="{StaticResource AccentColor4}" options:Freeze="True" />
<SolidColorBrush x:Key="WindowTitleColorBrush" Color="{StaticResource AccentColor}" options:Freeze="True" />
<LinearGradientBrush x:Key="ProgressBrush" EndPoint="0.001,0.5" StartPoint="1.002,0.5" options:Freeze="True">
<GradientStop Color="{StaticResource HighlightColor}" Offset="0" />
<GradientStop Color="{StaticResource AccentColor3}" Offset="1" />
</LinearGradientBrush>
<SolidColorBrush x:Key="CheckmarkFill" Color="{StaticResource AccentColor}" options:Freeze="True" />
<SolidColorBrush x:Key="RightArrowFill" Color="{StaticResource AccentColor}" options:Freeze="True" />
<Color x:Key="IdealForegroundColor">White</Color>
<SolidColorBrush x:Key="IdealForegroundColorBrush" Color="{StaticResource IdealForegroundColor}" options:Freeze="True" />
<SolidColorBrush x:Key="IdealForegroundDisabledBrush" Color="{StaticResource IdealForegroundColor}" Opacity="0.4" options:Freeze="True" />
<SolidColorBrush x:Key="AccentSelectedColorBrush" Color="{StaticResource IdealForegroundColor}" options:Freeze="True" />
<!-- DataGrid brushes -->
<SolidColorBrush x:Key="MetroDataGrid.HighlightBrush" Color="{StaticResource AccentColor}" options:Freeze="True" />
<SolidColorBrush x:Key="MetroDataGrid.HighlightTextBrush" Color="{StaticResource IdealForegroundColor}" options:Freeze="True" />
<SolidColorBrush x:Key="MetroDataGrid.MouseOverHighlightBrush" Color="{StaticResource AccentColor3}" options:Freeze="True" />
<SolidColorBrush x:Key="MetroDataGrid.FocusBorderBrush" Color="{StaticResource AccentColor}" options:Freeze="True" />
<SolidColorBrush x:Key="MetroDataGrid.InactiveSelectionHighlightBrush" Color="{StaticResource AccentColor2}" options:Freeze="True" />
<SolidColorBrush x:Key="MetroDataGrid.InactiveSelectionHighlightTextBrush" Color="{StaticResource IdealForegroundColor}" options:Freeze="True" />
<SolidColorBrush x:Key="MahApps.Metro.Brushes.ToggleSwitchButton.OnSwitchBrush.Win10" Color="{StaticResource AccentColor}" options:Freeze="True" />
<SolidColorBrush x:Key="MahApps.Metro.Brushes.ToggleSwitchButton.OnSwitchMouseOverBrush.Win10" Color="{StaticResource AccentColor2}" options:Freeze="True" />
<SolidColorBrush x:Key="MahApps.Metro.Brushes.ToggleSwitchButton.ThumbIndicatorCheckedBrush.Win10" Color="{StaticResource IdealForegroundColor}" options:Freeze="True" />
</ResourceDictionary>

View File

@ -0,0 +1,729 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:nc="http://schemas.ncore.com/wpf/xaml/colorbox"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!--
Please note:
The style refers to internal types of the ColorBox.dll. These types are not accessable outside of the Libary.
Therefore you have to embed this style into the dll or declare the internal types public in order to be able to apply this style.
The style definitions are forked and modified from the Generic.xaml
-->
<Geometry x:Key="SkewIcon">M456.021,227.816L545.590,227.816L456.021,362.171L366.452,362.171L456.021,227.816</Geometry>
<Geometry x:Key="TranslateIcon">M384,289.828L384,363L457.171,363M384,363L457.171,289.828M480,267L480,310.011L435.711,267L480,267</Geometry>
<Geometry x:Key="RotateIcon">F1 M 32.0034,13.0019L 35.0033,16.002L 35.0034,24.0019L 27.0033,24.002L 24.0034,21.0019L 29.5944,21.0014C 28.2209,19.4668 26.2249,18.501 24.0033,18.501C 19.8606,18.501 16.5022,21.8593 16.5022,26.002C 16.5022,28.0734 17.3418,29.9486 18.6992,31.3061L 16.2241,33.7812C 14.2332,31.7903 13.0018,29.0399 13.0018,26.0019C 13.0018,19.926 17.9274,15.0004 24.0033,15.0004C 27.1557,15.0004 29.9984,16.3263 32.0042,18.4508L 32.0034,13.0019 Z</Geometry>
<Geometry x:Key="ScaleIcon">F1 M 28,13L 36,13L 36,21L 33,24L 33,18.5L 24,27.5L 21.5,25L 30.5,16L 25,16L 28,13 Z M 13,18L 26,18L 23,21L 16,21L 16,33L 28,33L 28,26L 31,23L 31,36L 13,36L 13,18 Z</Geometry>
<Geometry x:Key="CenterIcon">M502.672,272.601C502.672,298.366 481.785,319.252 456.021,319.252 430.257,319.252 409.370,298.366 409.370,272.601 409.370,246.837 430.257,225.950 456.021,225.950 481.785,225.950 502.672,246.837 502.672,272.601zM502.672,272.601C502.672,298.366 481.785,319.252 456.021,319.252 430.257,319.252 409.370,298.366 409.370,272.601 409.370,246.837 430.257,225.950 456.021,225.950 481.785,225.950 502.672,246.837 502.672,272.601zM470.531,272.601C470.531,280.615 464.035,287.111 456.021,287.111 448.007,287.111 441.511,280.615 441.511,272.601 441.511,264.588 448.007,258.091 456.021,258.091 464.035,258.091 470.531,264.588 470.531,272.601z</Geometry>
<Geometry x:Key="FlipIcon">M384,267L384,363L480,363M384,363L459.026,286.973L438,267L479.000,267L479.000,307.000L459.026,286.973</Geometry>
<Style TargetType="Path" x:Key="IconStyle">
<Setter Property="Height" Value="16" />
<Setter Property="Width" Value="16" />
<Setter Property="Fill" Value="{DynamicResource GlyphBrush}" />
<Setter Property="Stretch" Value="Fill" />
</Style>
<Style TargetType="Slider" x:Key="OpacitySliderStyle" BasedOn="{StaticResource {x:Type Slider}}">
<Setter Property="Value"
Value="{Binding Brush.Opacity, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" />
<Setter Property="IsMoveToPointEnabled" Value="True" />
<Setter Property="Minimum" Value="0" />
<Setter Property="Maximum" Value="1" />
<Setter Property="Margin" Value="2,8,2,0"/>
</Style>
<BooleanToVisibilityConverter x:Key="BoolToVis" />
<VisualBrush x:Key="AlphaBrush" Stretch="None" TileMode="Tile" ViewportUnits="Absolute" Viewport="0,0,8,8">
<VisualBrush.Visual>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="4" />
<ColumnDefinition Width="4" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="4" />
<RowDefinition Height="4" />
</Grid.RowDefinitions>
<Rectangle Fill="#FFF" Grid.Row="0" Grid.Column="0" />
<Rectangle Fill="#AAA" Grid.Row="0" Grid.Column="1" />
<Rectangle Fill="#AAA" Grid.Row="1" Grid.Column="0" />
<Rectangle Fill="#FFF" Grid.Row="1" Grid.Column="1" />
</Grid>
</VisualBrush.Visual>
</VisualBrush>
<!-- Gradient Stop Thumb Style -->
<Style x:Key="SliderThumbStyle" TargetType="Thumb">
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="BorderBrush" Value="{StaticResource ControlBorderBrush}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Thumb">
<Grid>
<Path Data="M0,3 L5,3 L7,0 L9,3 L14,3 L14,16 L0,16 Z" Height="16" Width="14"
Fill="{DynamicResource BaseBorderBrush}" />
<Path Data="M1,4 L5,4 L7,1 L9,4 L13,4 L13,15 L1,15 Z" Height="16" Width="14"
Fill="{TemplateBinding Background}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Gradient Stop Slider Style -->
<Style x:Key="GradientStopSliderStyle" TargetType="Slider">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Slider">
<Track x:Name="PART_Track">
<Track.Thumb>
<Thumb Style="{StaticResource SliderThumbStyle}" Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}" />
</Track.Thumb>
</Track>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- ******* DoubleUpDown ******* -->
<Style x:Key="NumericUpDown" TargetType="{x:Type nc:UpDownBase}">
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Foreground" Value="{DynamicResource TextBrush}" />
<Setter Property="Background" Value="{DynamicResource DarkerBaseBrush}" />
<Setter Property="BorderBrush" Value="{DynamicResource BaseBorderBrush}" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Margin" Value="2" />
<Setter Property="Padding" Value="5,1" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="nc:UpDownBase">
<nc:Spinner IsTabStop="False" Background="{TemplateBinding Background}"
BorderThickness="{TemplateBinding BorderThickness}">
<TextBox x:Name="PART_TextBox" BorderThickness="{TemplateBinding BorderThickness}"
FocusVisualStyle="{x:Null}" Background="{TemplateBinding Background}"
ContextMenu="{TemplateBinding ContextMenu}" FontFamily="{TemplateBinding FontFamily}"
FontSize="{TemplateBinding FontSize}" FontStretch="{TemplateBinding FontStretch}"
FontStyle="{TemplateBinding FontStyle}" FontWeight="{TemplateBinding FontWeight}"
Foreground="{TemplateBinding Foreground}"
IsReadOnly="{Binding IsReadOnly, RelativeSource={RelativeSource TemplatedParent}}"
MinWidth="20" AcceptsReturn="False" Padding="{TemplateBinding Padding}"
TabIndex="{TemplateBinding TabIndex}" nc:TextBoxBehavior.SelectAllTextOnFocus="True" />
</nc:Spinner>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type nc:DoubleUpDown}" BasedOn="{StaticResource NumericUpDown}">
<Setter Property="Increment" Value=".1" />
<Setter Property="FormatString" Value="F1" />
</Style>
<!-- ******* Spinner ******* -->
<Style TargetType="{x:Type nc:Spinner}">
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Background" Value="{DynamicResource DarkerBaseBrush}" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Focusable" Value="False" />
<Setter Property="IsTabStop" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type nc:Spinner}">
<Border Background="{TemplateBinding Background}"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}">
<ContentPresenter />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- ******* ColorBox ******* -->
<Style TargetType="{x:Type nc:ColorBox}">
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Background" Value="{DynamicResource DarkerBaseBrush}" />
<Setter Property="BorderBrush" Value="{StaticResource ControlBorderBrush}" />
<Setter Property="VerticalAlignment" Value="Top" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type nc:ColorBox}">
<Border x:Name="PART_Root" Background="{TemplateBinding Background}" BorderBrush="{StaticResource ControlBorderBrush}">
<Border.InputBindings>
<KeyBinding Key="Delete" Command="{x:Static nc:ColorBox.RemoveGradientStop}" />
</Border.InputBindings>
<Grid>
<ToggleButton x:Name="PART_OpenPopup" BorderThickness="0" MinHeight="20" Padding="1"
Foreground="{TemplateBinding Foreground}"
Background="{TemplateBinding Brush}">
<ToggleButton.Style>
<Style TargetType="{x:Type ToggleButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<DockPanel Background="Transparent"
Margin="{TemplateBinding Padding}">
<Border MinWidth="20" Background="{StaticResource AlphaBrush}">
<Border Background="{TemplateBinding Background}" />
</Border>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ToggleButton.Style>
</ToggleButton>
<Popup IsOpen="{Binding ElementName=PART_OpenPopup,Path=IsChecked}" StaysOpen="False"
AllowsTransparency="True" Width="{Binding ActualWidth, ElementName=PART_Root}"
MinWidth="250" HorizontalOffset="-1" Placement="Top" PopupAnimation="Fade">
<Border Background="{StaticResource ControlBackgroundBrush}"
BorderBrush="{StaticResource AccentColorBrush}" BorderThickness="1"
Margin="10,0,10,10">
<Border.Effect>
<DropShadowEffect BlurRadius="10" ShadowDepth="0"
Color="{StaticResource AccentColor}" />
</Border.Effect>
<StackPanel Margin="10">
<StackPanel.Resources>
<Style x:Key="TBStyle" TargetType="TextBlock">
<Setter Property="Margin" Value="2" />
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
</StackPanel.Resources>
<!-- Available brush types -->
<ListBox x:Name="listAvailableBrushType" HorizontalContentAlignment="Center"
SelectedItem="{Binding BrushType, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
ItemsSource="{Binding AvailableBrushTypes, RelativeSource={RelativeSource TemplatedParent}}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Rows="1" Columns="4" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border x:Name="Border" Background="Transparent"
Padding="0,3">
<Path x:Name="Icon" Height="12" Width="20"
Stretch="Fill" Fill="#FF403C3C"
StrokeThickness="1" Stroke="{StaticResource ControlBorderBrush}"
Data="M371,190L557,190 557,293 371,293 371,190z" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Gray"
TargetName="Border" />
<Setter Property="Foreground" Value="White" />
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="Gray"
TargetName="Border" />
<Setter Property="Foreground" Value="White" />
</Trigger>
<DataTrigger Binding="{Binding}" Value="None">
<Setter Property="ToolTip" Value="No Brush" />
<Setter Property="StrokeThickness"
TargetName="Icon" Value="0" />
<Setter TargetName="Icon" Property="Data">
<Setter.Value>
<Geometry>M612,189L452.949,189L452.949,266.024L612,189 M612,196.999L452.949,273.999L612,273.999L612,196.999</Geometry>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding}" Value="Solid">
<Setter Property="ToolTip"
Value="Solid Color Brush" />
<Setter Property="Fill" TargetName="Icon"
Value="#FF403C3C" />
</DataTrigger>
<DataTrigger Binding="{Binding}" Value="Linear">
<Setter Property="ToolTip"
Value="Linear Gradient Brush" />
<Setter Property="Fill" TargetName="Icon">
<Setter.Value>
<LinearGradientBrush StartPoint="0,.5"
EndPoint="1,.5">
<GradientStop Color="#FF403C3C"
Offset="0" />
<GradientStop Color="White"
Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding}" Value="Radial">
<Setter Property="ToolTip"
Value="Radial Gradient Brush" />
<Setter Property="Fill" TargetName="Icon">
<Setter.Value>
<RadialGradientBrush>
<GradientStop Color="#FF403C3C"
Offset="1" />
<GradientStop Color="White" />
</RadialGradientBrush>
</Setter.Value>
</Setter>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
<!-- Color selector -->
<ScrollViewer Margin="0,5,0,0" HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Disabled">
<ScrollViewer.Style>
<Style TargetType="ScrollViewer">
<Style.Triggers>
<DataTrigger
Binding="{Binding ElementName=listAvailableBrushType, Path=SelectedValue}"
Value="None">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</ScrollViewer.Style>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="5" />
<ColumnDefinition Width="20" />
<ColumnDefinition Width="5" />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<!-- saturation / brightness selector -->
<Border BorderThickness="1"
BorderBrush="{StaticResource ControlBorderBrush}">
<Grid Grid.Column="0" ClipToBounds="true">
<nc:SaturationBrightnessSelector x:Name="SV" MinHeight="128"
Saturation="{Binding Path=Saturation,Mode=TwoWay,RelativeSource={RelativeSource TemplatedParent}}"
Brightness="{Binding Path=Brightness,Mode=TwoWay,RelativeSource={RelativeSource TemplatedParent}}"
Hue="{Binding ElementName=H,Path=Hue}" />
<Grid VerticalAlignment="Top" HorizontalAlignment="Left"
Margin="-6,-6,0,0" Width="12" Height="12">
<Ellipse Stroke="Black" />
<Ellipse Stroke="White" Margin="1" />
<Grid.RenderTransform>
<TranslateTransform
X="{Binding ElementName=SV,Path=SaturationOffset}"
Y="{Binding ElementName=SV,Path=BrightnessOffset}" />
</Grid.RenderTransform>
</Grid>
</Grid>
</Border>
<!-- hue selector -->
<nc:HueSelector x:Name="H" Grid.Column="2"
Hue="{Binding Path=Hue,Mode=TwoWay,RelativeSource={RelativeSource TemplatedParent}}" />
<Path Grid.Column="2" HorizontalAlignment="Left" Margin="0,-5,0,5"
Stroke="White" Fill="Black" Data="M 0 0 L 7 5 L 0 10Z">
<Path.RenderTransform>
<TranslateTransform Y="{Binding ElementName=H,Path=HueOffset}" />
</Path.RenderTransform>
</Path>
<Path Grid.Column="2" HorizontalAlignment="Right" Margin="0,-5,0,5"
Stroke="White" Fill="Black" Data="M 0 5 L 7 0 L 7 10 Z">
<Path.RenderTransform>
<TranslateTransform Y="{Binding ElementName=H,Path=HueOffset}" />
</Path.RenderTransform>
</Path>
<!-- alpha selector -->
<Rectangle Grid.Column="4" Fill="{StaticResource AlphaBrush}" />
<nc:AlphaSelector x:Name="A" Grid.Column="4"
Alpha="{Binding Path=Alpha,Mode=TwoWay,RelativeSource={RelativeSource TemplatedParent}}" />
<Path Grid.Column="4" HorizontalAlignment="Left" Margin="0,-5,0,5"
Stroke="White" Fill="Black" Data="M 0 0 L 7 5 L 0 10Z">
<Path.RenderTransform>
<TranslateTransform
Y="{Binding ElementName=A,Path=AlphaOffset}" />
</Path.RenderTransform>
</Path>
<Path Grid.Column="4" HorizontalAlignment="Right" Margin="0,-5,0,5"
Stroke="White" Fill="Black" Data="M 0 5 L 7 0 L 7 10 Z">
<Path.RenderTransform>
<TranslateTransform
Y="{Binding ElementName=A,Path=AlphaOffset}" />
</Path.RenderTransform>
</Path>
</Grid>
</ScrollViewer>
<!-- Current color viewer -->
<Grid Margin="0,5,0,0" Height="26">
<!-- Hide when brush type is None -->
<Grid.Style>
<Style TargetType="Grid">
<Style.Triggers>
<DataTrigger
Binding="{Binding ElementName=listAvailableBrushType, Path=SelectedValue}"
Value="None">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Style>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="5" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Border BorderThickness="1"
BorderBrush="{StaticResource ControlBorderBrush}">
<Rectangle>
<Rectangle.Fill>
<SolidColorBrush
Color="{Binding Color, RelativeSource={RelativeSource TemplatedParent}}" />
</Rectangle.Fill>
</Rectangle>
</Border>
<TextBox x:Name="PART_CurrentColor"
Text="{Binding Color, RelativeSource={RelativeSource TemplatedParent}}"
nc:TextBoxBehavior.SelectAllTextOnFocus="True" Grid.Column="2"
MinWidth="100" />
</Grid>
<!-- Gradient Stop editor -->
<Grid Margin="0,5,0,0" Focusable="False">
<Grid.Style>
<Style TargetType="Grid">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger
Binding="{Binding ElementName=listAvailableBrushType, Path=SelectedValue}"
Value="Linear">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
<DataTrigger
Binding="{Binding ElementName=listAvailableBrushType, Path=SelectedValue}"
Value="Radial">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Style>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Focusable="False">
<!-- Click to add gradient stop -->
<Border BorderThickness="1"
BorderBrush="{StaticResource ControlBorderBrush}"
Margin="-1, 0, 5, 0">
<nc:GradientStopAdder Height="20" Focusable="False"
IsTabStop="False" FocusVisualStyle="{x:Null}"
ColorBox="{Binding RelativeSource={RelativeSource TemplatedParent}}">
<nc:GradientStopAdder.Background>
<LinearGradientBrush
GradientStops="{Binding Brush.GradientStops, RelativeSource={RelativeSource TemplatedParent}}"
StartPoint="0, .5" EndPoint="1, .5" />
</nc:GradientStopAdder.Background>
<Button.Style>
<Style TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border BorderThickness="0"
Background="{TemplateBinding Background}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Button.Style>
</nc:GradientStopAdder>
</Border>
<!-- gradient stops -->
<ListBox x:Name="lbGradientStops"
ItemsSource="{Binding Path=Gradients, RelativeSource={RelativeSource TemplatedParent}}"
SelectedItem="{Binding SelectedGradient,RelativeSource={RelativeSource TemplatedParent}}"
Background="{x:Null}" Style="{x:Null}" BorderThickness="0"
FocusVisualStyle="{x:Null}" Focusable="False"
IsTabStop="False">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<nc:GradientStopSlider x:Name="PART_Slider"
BorderBrush="Black"
IsTabStop="False"
Style="{StaticResource GradientStopSliderStyle}"
Value="{Binding Offset}"
Minimum="0" Maximum="1"
ColorBox="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type nc:ColorBox}}}"
SelectedGradient="{Binding}"
Margin="0,0,0,2">
<nc:GradientStopSlider.Background>
<SolidColorBrush Color="{Binding Color}"/>
</nc:GradientStopSlider.Background>
</nc:GradientStopSlider>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver"
Value="True">
<Setter Property="BorderBrush"
TargetName="PART_Slider"
Value="Orange" />
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter Property="BorderBrush"
TargetName="PART_Slider"
Value="Blue" />
<Setter Property="Effect"
TargetName="PART_Slider">
<Setter.Value>
<DropShadowEffect
ShadowDepth="2"
BlurRadius="2"
Direction="270"
Color="{StaticResource AccentColor}" />
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsSelected"
Value="False">
<Setter Property="BorderBrush"
TargetName="PART_Slider"
Value="Blue" />
<Setter Property="Effect"
TargetName="PART_Slider">
<Setter.Value>
<DropShadowEffect
ShadowDepth="2"
BlurRadius="2"
Direction="270" />
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<Grid IsItemsHost="True" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
</StackPanel>
<!-- Reverse gradients button -->
<Button Grid.Column="1" ToolTip="Reverse gradient stops"
Command="{x:Static nc:ColorBox.ReverseGradientStop}"
x:Name="Delete" Width="50" Height="50"
Style="{DynamicResource MetroCircleButtonStyle}" VerticalAlignment="Top"
HorizontalAlignment="Right" Margin="0,-4,0,0">
<Button.Content>
<Rectangle Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}"
Width="20" Height="20">
<Rectangle.OpacityMask>
<VisualBrush
Visual="{StaticResource appbar_arrow_left_right}"
Stretch="Fill" />
</Rectangle.OpacityMask>
</Rectangle>
</Button.Content>
</Button>
</Grid>
<!-- Additional Properties -->
<StackPanel Margin="0,5,0,0">
<StackPanel.Style>
<Style TargetType="StackPanel">
<Style.Triggers>
<DataTrigger
Binding="{Binding ElementName=listAvailableBrushType, Path=SelectedValue}"
Value="None">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<ToggleButton x:Name="PART_AdditionalPropertyOpen"
BorderBrush="{TemplateBinding BorderBrush}"
ToolTip="Additional Properties" Height="20"
Content="Show more/less" />
<StackPanel Margin="0,5,0,0"
Visibility="{Binding ElementName=PART_AdditionalPropertyOpen, Path=IsChecked, Converter={StaticResource BoolToVis}}">
<!-- Solid brush -->
<DockPanel Margin="0,2">
<DockPanel.Style>
<Style TargetType="DockPanel">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger
Binding="{Binding ElementName=listAvailableBrushType, Path=SelectedValue}"
Value="Solid">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</DockPanel.Style>
<TextBlock Text="Opacity" VerticalAlignment="Center" />
<Slider Style="{StaticResource OpacitySliderStyle}"
Margin="10,0,0,0" />
</DockPanel>
<!-- Linear brush -->
<DockPanel>
<DockPanel.Style>
<Style TargetType="DockPanel">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger
Binding="{Binding ElementName=listAvailableBrushType, Path=SelectedValue}"
Value="Linear">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</DockPanel.Style>
<UniformGrid Rows="5" DockPanel.Dock="Left" Margin="0,0,5,0">
<TextBlock Text="Start Point" VerticalAlignment="Center" />
<TextBlock Text="End Point" VerticalAlignment="Center" />
<TextBlock Text="Mapping Mode" VerticalAlignment="Center" />
<TextBlock Text="Spread Method" VerticalAlignment="Center" />
<TextBlock Text="Opacity" VerticalAlignment="Center" />
</UniformGrid>
<UniformGrid Rows="5" DockPanel.Dock="Right">
<UniformGrid Rows="1">
<nc:DoubleUpDown
Value="{Binding StartX, RelativeSource={RelativeSource TemplatedParent}}" />
<nc:DoubleUpDown
Value="{Binding StartY, RelativeSource={RelativeSource TemplatedParent}}" />
</UniformGrid>
<UniformGrid Rows="1">
<nc:DoubleUpDown
Value="{Binding EndX, RelativeSource={RelativeSource TemplatedParent}}" />
<nc:DoubleUpDown
Value="{Binding EndY, RelativeSource={RelativeSource TemplatedParent}}" />
</UniformGrid>
<ComboBox Margin="2"
ItemsSource="{Binding MappingModeTypes, RelativeSource={RelativeSource TemplatedParent}}"
SelectedItem="{Binding MappingMode, RelativeSource={RelativeSource TemplatedParent}}" />
<ComboBox Margin="2"
ItemsSource="{Binding SpreadMethodTypes, RelativeSource={RelativeSource TemplatedParent}}"
SelectedItem="{Binding SpreadMethod, RelativeSource={RelativeSource TemplatedParent}}" />
<Slider Style="{StaticResource OpacitySliderStyle}" />
</UniformGrid>
</DockPanel>
<!-- Radial brush -->
<DockPanel>
<DockPanel.Style>
<Style TargetType="DockPanel">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger
Binding="{Binding ElementName=listAvailableBrushType, Path=SelectedValue}"
Value="Radial">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</DockPanel.Style>
<UniformGrid Rows="7" DockPanel.Dock="Left" Margin="0,0,5,0">
<TextBlock Text="Gradient Origin" VerticalAlignment="Center" />
<TextBlock Text="Center" VerticalAlignment="Center" />
<TextBlock Text="Radius X" VerticalAlignment="Center" />
<TextBlock Text="Radius Y" VerticalAlignment="Center" />
<TextBlock Text="Mapping Mode" VerticalAlignment="Center" />
<TextBlock Text="Spread Method" VerticalAlignment="Center" />
<TextBlock Text="Opacity" VerticalAlignment="Center" />
</UniformGrid>
<UniformGrid Rows="7" DockPanel.Dock="Right">
<UniformGrid Rows="1">
<nc:DoubleUpDown
Value="{Binding GradientOriginX, RelativeSource={RelativeSource TemplatedParent}}" />
<nc:DoubleUpDown
Value="{Binding GradientOriginY, RelativeSource={RelativeSource TemplatedParent}}" />
</UniformGrid>
<UniformGrid Rows="1">
<nc:DoubleUpDown
Value="{Binding CenterX, RelativeSource={RelativeSource TemplatedParent}}" />
<nc:DoubleUpDown
Value="{Binding CenterY, RelativeSource={RelativeSource TemplatedParent}}" />
</UniformGrid>
<nc:DoubleUpDown
Value="{Binding RadiusX, RelativeSource={RelativeSource TemplatedParent}}" />
<nc:DoubleUpDown
Value="{Binding RadiusY, RelativeSource={RelativeSource TemplatedParent}}" />
<ComboBox Margin="2"
ItemsSource="{Binding MappingModeTypes, RelativeSource={RelativeSource TemplatedParent}}"
SelectedItem="{Binding MappingMode, RelativeSource={RelativeSource TemplatedParent}}" />
<ComboBox Margin="2"
ItemsSource="{Binding SpreadMethodTypes, RelativeSource={RelativeSource TemplatedParent}}"
SelectedItem="{Binding SpreadMethod, RelativeSource={RelativeSource TemplatedParent}}" />
<Slider Style="{StaticResource OpacitySliderStyle}" />
</UniformGrid>
</DockPanel>
</StackPanel>
</StackPanel>
</StackPanel>
</Border>
</Popup>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

View File

@ -28,6 +28,23 @@ namespace Artemis.Utilities
return returnColor;
}
public static System.Windows.Media.Color GetRandomRainbowMediaColor()
{
var colors = new List<byte>();
var rand = new Random();
for (var i = 0; i < 3; i++)
colors.Add((byte) rand.Next(0, 256));
var highest = colors.Max();
var lowest = colors.Min();
colors[colors.FindIndex(c => c == highest)] = 255;
colors[colors.FindIndex(c => c == lowest)] = 0;
var returnColor = System.Windows.Media.Color.FromArgb(255, colors[0], colors[1], colors[2]);
return returnColor;
}
public static Color ShiftColor(Color c, int shiftAmount)
{
int newRed = c.R;

View File

@ -0,0 +1,74 @@
using System.Text.RegularExpressions;
namespace Artemis.Utilities
{
public static class ExtensionMethods
{
#region String
/// <summary>
/// Takes a string LikeThisOne and turns it into Like This One.
/// ZombieSheep - http://stackoverflow.com/a/5796793/5015269
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
public static string SplitCamelCase(this string str)
{
return Regex.Replace(Regex.Replace(str, @"(\P{Ll})(\P{Ll}\p{Ll})", "$1 $2"), @"(\p{Ll})(\P{Ll})", "$1 $2");
}
#endregion
#region Color
// TODO: Convert ColorHelpers to ExtensionMethods
#endregion
#region Reflection
/// <summary>
/// Gets a value by path
/// jheddings - http://stackoverflow.com/a/1954663/5015269
/// </summary>
/// <param name="obj"></param>
/// <param name="name">Path, such as "TimeOfDay.Minutes"</param>
/// <returns></returns>
public static object GetPropValue(this object obj, string name)
{
foreach (var part in name.Split('.'))
{
if (obj == null)
return null;
var type = obj.GetType();
var info = type.GetProperty(part);
if (info == null)
return null;
obj = info.GetValue(obj, null);
}
return obj;
}
/// <summary>
/// Gets a value by path
/// jheddings - http://stackoverflow.com/a/1954663/5015269
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj"></param>
/// <param name="name"></param>
/// <returns></returns>
public static T GetPropValue<T>(this object obj, string name)
{
var retVal = GetPropValue(obj, name);
if (retVal == null)
return default(T);
// throws InvalidCastException if types are incompatible
return (T) retVal;
}
#endregion
}
}

View File

@ -1,7 +1,6 @@
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using Artemis.Settings;
@ -9,12 +8,18 @@ using Newtonsoft.Json;
namespace Artemis.Utilities.GameState
{
/// <summary>
/// Listens for JSON calls, parses them and raises an event.
/// Includes some code from https://github.com/rakijah/CSGSI
/// </summary>
public class GameStateWebServer
{
public delegate void GameDataReceivedEventHandler(
object sender, GameDataReceivedEventArgs gameDataReceivedEventArgs);
private readonly HttpListener _listener = new HttpListener();
private readonly AutoResetEvent _waitForConnection = new AutoResetEvent(false);
private HttpListener _listener;
public GameStateWebServer()
{
@ -31,64 +36,69 @@ namespace Artemis.Utilities.GameState
if (Running)
return;
Port = General.Default.GamestatePort;
_listener = new HttpListener();
_listener.Prefixes.Add($"http://localhost:{Port}/");
var listenerThread = new Thread(ListenerRun);
try
{
_listener.Prefixes.Clear();
Port = General.Default.GamestatePort;
_listener.Prefixes.Add($"http://localhost:{Port}/");
_listener.Start();
}
catch (Exception)
catch (HttpListenerException)
{
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.");
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;
listenerThread.Start();
}
private void ListenerRun()
{
while (Running)
{
_listener.BeginGetContext(HandleRequest, _listener);
_waitForConnection.WaitOne();
_waitForConnection.Reset();
}
}
private void HandleRequest(IAsyncResult ar)
{
HttpListenerContext context = null;
try
{
context = _listener.EndGetContext(ar);
}
catch (ObjectDisposedException)
{
// Listener was Closed due to call of Stop();
}
catch (HttpListenerException)
{
// Listener was Closed due to call of Stop();
}
finally
{
_waitForConnection.Set();
}
if (context != null)
{
HandleRequest(context.Request);
context.Response.OutputStream.Close();
}
}
public void Stop()
{
_listener.Stop();
_listener.Close();
Running = false;
}
private string HandleRequest(HttpListenerRequest request)
private void HandleRequest(HttpListenerRequest request)
{
object json;
using (var reader = new StreamReader(request.InputStream, request.ContentEncoding))
@ -99,7 +109,6 @@ namespace Artemis.Utilities.GameState
if (json != null)
OnGameDataReceived(new GameDataReceivedEventArgs(json));
return JsonConvert.SerializeObject(json);
}
protected virtual void OnGameDataReceived(GameDataReceivedEventArgs e)

View File

@ -1,12 +1,15 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.IO;
using System.Reflection;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Security.Principal;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Xml.Serialization;
using static System.String;
namespace Artemis.Utilities
{
@ -44,5 +47,101 @@ namespace Artemis.Utilities
return wp.IsInRole(WindowsBuiltInRole.Administrator);
}
public static void CopyProperties(object dest, object src)
{
foreach (PropertyDescriptor item in TypeDescriptor.GetProperties(src))
{
item.SetValue(dest, item.GetValue(src));
}
}
/// <summary>
/// Perform a deep Copy of the object.
/// </summary>
/// <typeparam name="T">The type of object being copied.</typeparam>
/// <param name="source">The object instance to copy.</param>
/// <returns>The copied object.</returns>
public static T Clone<T>(T source)
{
// Don't serialize a null object, simply return the default for that object
if (ReferenceEquals(source, null))
return default(T);
var serializer = new XmlSerializer(typeof(T));
Stream stream = new MemoryStream();
using (stream)
{
serializer.Serialize(stream, source);
stream.Seek(0, SeekOrigin.Begin);
return (T)serializer.Deserialize(stream);
}
}
public static object GetPropertyValue(object o, string path)
{
var propertyNames = path.Split('.');
var value = o.GetType().GetProperty(propertyNames[0]).GetValue(o, null);
if (propertyNames.Length == 1 || value == null)
return value;
return GetPropertyValue(value, path.Replace(propertyNames[0] + ".", ""));
}
public static List<PropertyCollection> GenerateTypeMap(object o) => GenerateTypeMap(o.GetType().GetProperties());
public static List<PropertyCollection> GenerateTypeMap<T>() => GenerateTypeMap(typeof (T).GetProperties());
private static List<PropertyCollection> GenerateTypeMap(IEnumerable<PropertyInfo> getProperties,
string path = "")
{
var list = new List<PropertyCollection>();
foreach (var propertyInfo in getProperties)
{
var friendlyName = Empty;
if (propertyInfo.PropertyType.Name == "Int32")
friendlyName = "(Number)";
else if (propertyInfo.PropertyType.Name == "String")
friendlyName = "(Text)";
if (propertyInfo.PropertyType.BaseType?.Name == "Enum")
friendlyName = "(Choice)";
var parent = new PropertyCollection
{
Type = propertyInfo.PropertyType.Name,
DisplayType = friendlyName,
Display = $"{path.Replace(".", " ")}{propertyInfo.Name}",
Path = $"{path}{propertyInfo.Name}"
};
if (propertyInfo.PropertyType.BaseType?.Name == "Enum")
{
parent.EnumValues = Enum.GetNames(propertyInfo.PropertyType);
parent.Type = "Enum";
}
if (friendlyName != Empty)
list.Add(parent);
if (propertyInfo.PropertyType.Name != "String")
list.AddRange(GenerateTypeMap(propertyInfo.PropertyType.GetProperties(),
path + $"{propertyInfo.Name}."));
}
return list;
}
public struct PropertyCollection
{
public string Display { get; set; }
public string Path { get; set; }
public string Type { get; set; }
/// <summary>
/// Only used if Type is an enumerable
/// </summary>
public string[] EnumValues { get; set; }
public List<PropertyCollection> Children { get; set; }
public string DisplayType { get; set; }
}
}
}

View File

@ -1,54 +1,16 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using PixelFormat = System.Drawing.Imaging.PixelFormat;
namespace Artemis.Utilities
{
internal class ImageUtilities
{
private static Dictionary<string, ImageCodecInfo> encoders;
/// <summary>
/// A lock to prevent concurrency issues loading the encoders.
/// </summary>
private static readonly object encodersLock = new object();
/// <summary>
/// A quick lookup for getting image encoders
/// </summary>
public static Dictionary<string, ImageCodecInfo> Encoders
{
//get accessor that creates the dictionary on demand
get
{
//if the quick lookup isn't initialised, initialise it
if (encoders == null)
{
//protect against concurrency issues
lock (encodersLock)
{
//check again, we might not have been the first person to acquire the lock (see the double checked lock pattern)
if (encoders == null)
{
encoders = new Dictionary<string, ImageCodecInfo>();
//get all the codecs
foreach (var codec in ImageCodecInfo.GetImageEncoders())
{
//add each codec to the quick lookup
encoders.Add(codec.MimeType.ToLower(), codec);
}
}
}
}
//return the lookup
return encoders;
}
}
/// <summary>
/// Resize the image to the specified width and height.
/// </summary>
@ -73,5 +35,46 @@ namespace Artemis.Utilities
//return the resulting bitmap
return result;
}
public static Bitmap BitmapSourceToBitmap(BitmapSource srs)
{
var width = srs.PixelWidth;
var height = srs.PixelHeight;
var stride = width*((srs.Format.BitsPerPixel + 7)/8);
var ptr = IntPtr.Zero;
try
{
ptr = Marshal.AllocHGlobal(height*stride);
srs.CopyPixels(new Int32Rect(0, 0, width, height), ptr, height*stride, stride);
using (var btm = new Bitmap(width, height, stride, PixelFormat.Format1bppIndexed, ptr))
{
// Clone the bitmap so that we can dispose it and
// release the unmanaged memory at ptr
return new Bitmap(btm);
}
}
finally
{
if (ptr != IntPtr.Zero)
Marshal.FreeHGlobal(ptr);
}
}
public static Bitmap DrawinVisualToBitmap(DrawingVisual visual, Rect rect)
{
var bmp = new RenderTargetBitmap((int) rect.Width, (int) rect.Height, 96, 96, PixelFormats.Pbgra32);
bmp.Render(visual);
var encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bmp));
Bitmap bitmap;
using (var stream = new MemoryStream())
{
encoder.Save(stream);
bitmap = new Bitmap(stream);
}
return bitmap;
}
}
}

View File

@ -0,0 +1,168 @@
using System;
using System.Windows;
using System.Windows.Media;
using Artemis.Models.Profiles;
namespace Artemis.Utilities
{
internal class LayerDrawer
{
private readonly LayerModel _layerModel;
private double _animationProgress;
private Rect _firstRect;
private Rect _rectangle;
private Rect _secondRect;
public LayerDrawer(LayerModel layerModel, int scale)
{
Scale = scale;
_layerModel = layerModel;
_animationProgress = 0;
}
public int Scale { get; set; }
public void Draw(DrawingContext c, bool update = true)
{
if (_layerModel.CalcProps.Brush == null || !_layerModel.Enabled)
return;
if (!update)
_layerModel.CalcProps.Animation = LayerAnimation.None;
UpdateAnimation();
// Set up variables for this frame
_rectangle = new Rect(_layerModel.CalcProps.X*Scale,
_layerModel.CalcProps.Y*Scale, _layerModel.CalcProps.Width*Scale,
_layerModel.CalcProps.Height*Scale);
if (_layerModel.LayerType == LayerType.Keyboard)
_layerModel.CalcProps.Brush.Dispatcher.Invoke(() => DrawRectangle(c));
}
private void UpdateAnimation()
{
if (!_layerModel.Enabled)
return;
// Slide right animation
if (_layerModel.CalcProps.Animation == LayerAnimation.SlideRight)
{
_firstRect = new Rect(new Point(_rectangle.X + _animationProgress, _rectangle.Y),
new Size(_rectangle.Width, _rectangle.Height));
_secondRect = new Rect(new Point(_firstRect.X - _rectangle.Width, _rectangle.Y),
new Size(_rectangle.Width + 1, _rectangle.Height));
if (_animationProgress > _layerModel.CalcProps.Width*4)
_animationProgress = 0;
}
// Slide left animation
if (_layerModel.CalcProps.Animation == LayerAnimation.SlideLeft)
{
_firstRect = new Rect(new Point(_rectangle.X - _animationProgress, _rectangle.Y),
new Size(_rectangle.Width + 1, _rectangle.Height));
_secondRect = new Rect(new Point(_firstRect.X + _rectangle.Width, _rectangle.Y),
new Size(_rectangle.Width, _rectangle.Height));
if (_animationProgress > _layerModel.CalcProps.Width*4)
_animationProgress = 0;
}
// Slide down animation
if (_layerModel.CalcProps.Animation == LayerAnimation.SlideDown)
{
_firstRect = new Rect(new Point(_rectangle.X, _rectangle.Y + _animationProgress),
new Size(_rectangle.Width, _rectangle.Height));
_secondRect = new Rect(new Point(_firstRect.X, _firstRect.Y - _rectangle.Height),
new Size(_rectangle.Width, _rectangle.Height));
if (_animationProgress > _layerModel.CalcProps.Height*4)
_animationProgress = 0;
}
// Slide up animation
if (_layerModel.CalcProps.Animation == LayerAnimation.SlideUp)
{
_firstRect = new Rect(new Point(_rectangle.X, _rectangle.Y - _animationProgress),
new Size(_rectangle.Width, _rectangle.Height));
_secondRect = new Rect(new Point(_firstRect.X, _firstRect.Y + _rectangle.Height),
new Size(_rectangle.Width, _rectangle.Height));
if (_animationProgress > _layerModel.CalcProps.Height*4)
_animationProgress = 0;
}
// Pulse animation
if (_layerModel.CalcProps.Animation == LayerAnimation.Pulse)
{
var opac = (Math.Sin(_animationProgress*Math.PI) + 1)*(_layerModel.UserProps.Opacity/2);
_layerModel.CalcProps.Opacity = opac;
if (_animationProgress > 2)
_animationProgress = 0;
_animationProgress = _animationProgress + _layerModel.CalcProps.AnimationSpeed/2;
}
else
{
// Update the animation progress
_animationProgress = _animationProgress + _layerModel.CalcProps.AnimationSpeed;
}
}
public DrawingImage GetThumbnail()
{
if (_layerModel.UserProps.Brush == null)
return null;
var visual = new DrawingVisual();
using (var c = visual.RenderOpen())
c.DrawRectangle(_layerModel.UserProps.Brush, new Pen(new SolidColorBrush(Colors.White), 1),
new Rect(0, 0, 18, 18));
var image = new DrawingImage(visual.Drawing);
return image;
}
public void DrawRectangle(DrawingContext c)
{
var brush = _layerModel.CalcProps.Brush.CloneCurrentValue();
brush.Opacity = _layerModel.CalcProps.Opacity;
if (_layerModel.CalcProps.Animation == LayerAnimation.SlideDown ||
_layerModel.CalcProps.Animation == LayerAnimation.SlideLeft ||
_layerModel.CalcProps.Animation == LayerAnimation.SlideRight ||
_layerModel.CalcProps.Animation == LayerAnimation.SlideUp)
{
// TODO: if (_layerModel.CalcProps.ContainedBrush)
c.PushClip(new RectangleGeometry(_rectangle));
c.DrawRectangle(brush, null, _firstRect);
c.DrawRectangle(brush, null, _secondRect);
c.Pop();
}
else
{
c.DrawRectangle(brush, null, _rectangle);
}
}
public void DrawEllipse(DrawingContext c)
{
c.DrawEllipse(_layerModel.CalcProps.Brush, null,
new Point(_rectangle.Width/2, _rectangle.Height/2), _rectangle.Width, _rectangle.Height);
}
public void DrawGif(DrawingContext bmp)
{
}
public void UpdateMouse()
{
}
public void UpdateHeadset()
{
}
}
}

View File

@ -0,0 +1,138 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace Artemis.Utilities.ParentChild
{
/// <summary>
/// Collection of child items. This collection automatically set the
/// Parent property of the child items when they are added or removed
/// Thomas Levesque - http://www.thomaslevesque.com/2009/06/12/c-parentchild-relationship-and-xml-serialization/
/// </summary>
/// <typeparam name="P">Type of the parent object</typeparam>
/// <typeparam name="T">Type of the child items</typeparam>
public class ChildItemCollection<P, T> : IList<T>
where P : class
where T : IChildItem<P>
{
private IList<T> _collection;
private readonly P _parent;
public ChildItemCollection(P parent)
{
_parent = parent;
_collection = new List<T>();
}
public ChildItemCollection(P parent, IList<T> collection)
{
_parent = parent;
_collection = collection;
}
#region IEnumerable<T> Members
public IEnumerator<T> GetEnumerator()
{
return _collection.GetEnumerator();
}
#endregion
#region IEnumerable Members
IEnumerator IEnumerable.GetEnumerator()
{
return (_collection as IEnumerable).GetEnumerator();
}
#endregion
#region IList<T> Members
public int IndexOf(T item)
{
return _collection.IndexOf(item);
}
public void Insert(int index, T item)
{
if (item != null)
item.Parent = _parent;
_collection.Insert(index, item);
}
public void RemoveAt(int index)
{
var oldItem = _collection[index];
_collection.RemoveAt(index);
if (oldItem != null)
oldItem.Parent = null;
}
public T this[int index]
{
get { return _collection[index]; }
set
{
var oldItem = _collection[index];
if (value != null)
value.Parent = _parent;
_collection[index] = value;
if (oldItem != null)
oldItem.Parent = null;
}
}
#endregion
#region ICollection<T> Members
public void Add(T item)
{
if (item != null)
item.Parent = _parent;
_collection.Add(item);
}
public void Clear()
{
foreach (var item in _collection)
{
if (item != null)
item.Parent = null;
}
_collection.Clear();
}
public bool Contains(T item)
{
return _collection.Contains(item);
}
public void CopyTo(T[] array, int arrayIndex)
{
_collection.CopyTo(array, arrayIndex);
}
public int Count => _collection.Count;
public bool IsReadOnly => _collection.IsReadOnly;
public bool Remove(T item)
{
var b = _collection.Remove(item);
if (item != null)
item.Parent = null;
return b;
}
#endregion
public void Sort(Func<T, object> func)
{
_collection = _collection.OrderBy(func).ToList();
}
}
}

View File

@ -0,0 +1,12 @@
namespace Artemis.Utilities.ParentChild
{
/// <summary>
/// Defines the contract for an object that has a parent object
/// Thomas Levesque - http://www.thomaslevesque.com/2009/06/12/c-parentchild-relationship-and-xml-serialization/
/// </summary>
/// <typeparam name="P">Type of the parent object</typeparam>
public interface IChildItem<P> where P : class
{
P Parent { get; set; }
}
}

View File

@ -0,0 +1,66 @@
using System;
using System.Collections;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Windows.Data;
using Artemis.Models.Profiles;
using Artemis.Utilities.ParentChild;
namespace Artemis.Utilities
{
/// <summary>
/// Fredrik Hedblad - http://stackoverflow.com/a/3987099/5015269
/// </summary>
public class EnumDescriptionConverter : IValueConverter
{
object IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var myEnum = (Enum) value;
var description = GetEnumDescription(myEnum);
return description;
}
object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return string.Empty;
}
private string GetEnumDescription(Enum enumObj)
{
var fieldInfo = enumObj.GetType().GetField(enumObj.ToString());
var attribArray = fieldInfo.GetCustomAttributes(false);
if (attribArray.Length == 0)
{
return enumObj.ToString();
}
var attrib = attribArray[0] as DescriptionAttribute;
return attrib?.Description;
}
}
public class LayerOrderConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
IList collection;
if (value is ChildItemCollection<LayerModel, LayerModel>)
collection = ((ChildItemCollection<LayerModel, LayerModel>) value).ToList();
else
collection = (IList) value;
var view = new ListCollectionView(collection);
var sort = new SortDescription(parameter.ToString(), ListSortDirection.Ascending);
view.SortDescriptions.Add(sort);
return view;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
}
}

View File

@ -1,4 +1,5 @@
using Artemis.Managers;
using System.ComponentModel;
using Artemis.Managers;
using Artemis.Models;
using Caliburn.Micro;
@ -10,7 +11,7 @@ namespace Artemis.ViewModels.Abstract
public GameModel GameModel { get; set; }
public MainManager MainManager { get; set; }
public event OnLayersUpdatedCallback OnLayersUpdatedCallback;
public GameSettings GameSettings
{
get { return _gameSettings; }
@ -54,4 +55,6 @@ namespace Artemis.ViewModels.Abstract
SaveSettings();
}
}
public delegate void OnLayersUpdatedCallback(object sender);
}

View File

@ -11,7 +11,6 @@ namespace Artemis.ViewModels.Flyouts
public class FlyoutSettingsViewModel : FlyoutBaseViewModel, IHandle<ToggleEnabled>, IHandle<ActiveEffectChanged>
{
private string _activeEffectName;
private bool _enabled;
private GeneralSettings _generalSettings;
private string _selectedKeyboardProvider;
@ -91,7 +90,7 @@ namespace Artemis.ViewModels.Flyouts
public void Handle(ActiveEffectChanged message)
{
var effectDisplay = message.ActiveEffect.Length > 0 ? message.ActiveEffect : "none";
var effectDisplay = string.IsNullOrEmpty(message.ActiveEffect) ? message.ActiveEffect : "none";
ActiveEffectName = $"Active effect: {effectDisplay}";
}

View File

@ -22,7 +22,7 @@ namespace Artemis.ViewModels
_counterStrikeVm = new CounterStrikeViewModel(mainManager) {DisplayName = "CS:GO"};
_dota2Vm = new Dota2ViewModel(mainManager) {DisplayName = "Dota 2"};
_witcher3Vm = new Witcher3ViewModel(mainManager) {DisplayName = "The Witcher 3"};
// _divisionVm = new TheDivisionViewModel(mainManager) {DisplayName = "The Division"};
_divisionVm = new TheDivisionViewModel(mainManager) {DisplayName = "The Division"};
}
protected override void OnActivate()
@ -33,7 +33,7 @@ namespace Artemis.ViewModels
ActivateItem(_counterStrikeVm);
ActivateItem(_dota2Vm);
ActivateItem(_witcher3Vm);
// ActivateItem(_divisionVm);
ActivateItem(_divisionVm);
}
}
}

View File

@ -0,0 +1,201 @@
using System.ComponentModel;
using System.Linq;
using Artemis.Models.Profiles;
using Artemis.Utilities;
using Caliburn.Micro;
namespace Artemis.ViewModels.LayerEditor
{
public class LayerConditionViewModel<T> : Screen
{
private readonly NamedOperator[] _boolOperators =
{
new NamedOperator("True", "== True"),
new NamedOperator("False", "== False")
};
private readonly LayerEditorViewModel<T> _conditionModel;
private readonly NamedOperator[] _int32Operators =
{
new NamedOperator("Lower than", "<"),
new NamedOperator("Lower or equal to", "<="),
new NamedOperator("Higher than", ">"),
new NamedOperator("Higher or equal to", ">="),
new NamedOperator("Equal to", "=="),
new NamedOperator("Not equal to", "!=")
};
private readonly NamedOperator[] _operators =
{
new NamedOperator("Equal to", "=="),
new NamedOperator("Not equal to", "!=")
};
private bool _preselecting;
private GeneralHelpers.PropertyCollection _selectedDataModelProp;
private NamedOperator _selectedOperator;
private string _userValue;
private bool _userValueIsVisible;
public LayerConditionViewModel(LayerEditorViewModel<T> conditionModel, LayerConditionModel layerConditionModel,
BindableCollection<GeneralHelpers.PropertyCollection> dataModelProps)
{
_conditionModel = conditionModel;
_preselecting = false;
LayerConditionModel = layerConditionModel;
DataModelProps = dataModelProps;
Operators = new BindableCollection<NamedOperator>();
PropertyChanged += UpdateModel;
PropertyChanged += UpdateForm;
PreSelect();
}
public string UserValue
{
get { return _userValue; }
set
{
if (value == _userValue) return;
_userValue = value;
NotifyOfPropertyChange(() => UserValue);
}
}
public LayerConditionModel LayerConditionModel { get; set; }
public BindableCollection<GeneralHelpers.PropertyCollection> DataModelProps { get; set; }
public BindableCollection<NamedOperator> Operators { get; set; }
public GeneralHelpers.PropertyCollection SelectedDataModelProp
{
get { return _selectedDataModelProp; }
set
{
if (value.Equals(_selectedDataModelProp)) return;
_selectedDataModelProp = value;
NotifyOfPropertyChange(() => SelectedDataModelProp);
}
}
public bool UserValueIsVisible
{
get { return _userValueIsVisible; }
set
{
if (value == _userValueIsVisible) return;
_userValueIsVisible = value;
NotifyOfPropertyChange(() => UserValueIsVisible);
}
}
public NamedOperator SelectedOperator
{
get { return _selectedOperator; }
set
{
if (value.Equals(_selectedOperator)) return;
_selectedOperator = value;
NotifyOfPropertyChange(() => SelectedOperator);
}
}
/// <summary>
/// Handles updating the form to match the selected data model property
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void UpdateForm(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName != "SelectedDataModelProp")
return;
Operators.Clear();
if (SelectedDataModelProp.EnumValues != null)
{
Operators.AddRange(
SelectedDataModelProp.EnumValues.Select(val => new NamedOperator(val.SplitCamelCase(), "== " + val)));
UserValueIsVisible = false;
}
else
switch (SelectedDataModelProp.Type)
{
case "Int32":
Operators.AddRange(_int32Operators);
UserValueIsVisible = true;
break;
case "Boolean":
Operators.AddRange(_boolOperators);
UserValueIsVisible = false;
break;
default:
Operators.AddRange(_operators);
UserValueIsVisible = true;
break;
}
SelectedOperator = Operators.First();
}
/// <summary>
/// Handles saving user input to the model
/// TODO: Data validation?
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void UpdateModel(object sender, PropertyChangedEventArgs e)
{
// Don't mess with model during preselect
if (_preselecting)
return;
// Only care about these fields
if (e.PropertyName != "UserValue" &&
e.PropertyName != "SelectedOperator" &&
e.PropertyName != "SelectedDataModelProp")
return;
LayerConditionModel.Field = SelectedDataModelProp.Path;
LayerConditionModel.Operator = SelectedOperator.Value;
LayerConditionModel.Value = UserValue;
LayerConditionModel.Type = SelectedDataModelProp.Type;
}
/// <summary>
/// Setup the current UI elements to show the backing model
/// </summary>
private void PreSelect()
{
_preselecting = true;
SelectedDataModelProp = DataModelProps.FirstOrDefault(m => m.Path == LayerConditionModel.Field);
SelectedOperator = Operators.FirstOrDefault(o => o.Value == LayerConditionModel.Operator);
UserValue = LayerConditionModel.Value;
LayerConditionModel.Type = SelectedDataModelProp.Type;
_preselecting = false;
}
/// <summary>
/// Delete the current model from the parent
/// </summary>
public void Delete()
{
_conditionModel.DeleteCondition(this, LayerConditionModel);
}
public struct NamedOperator
{
public string Display { get; set; }
public string Value { get; set; }
public NamedOperator(string display, string value)
{
Display = display;
Value = value;
}
}
}
}

View File

@ -0,0 +1,159 @@
using System.ComponentModel;
using System.Linq;
using Artemis.Models.Profiles;
using Artemis.Utilities;
using Caliburn.Micro;
namespace Artemis.ViewModels.LayerEditor
{
public class LayerDynamicPropertiesViewModel : Screen
{
private readonly LayerModel _layer;
private readonly string _property;
private LayerDynamicPropertiesModel _layerDynamicPropertiesModelProposed;
private LayerPropertyType _layerPropertyType;
private string _name;
private GeneralHelpers.PropertyCollection _selectedSource;
private GeneralHelpers.PropertyCollection _selectedTarget;
private bool _sourcesIsVisible;
private bool _userSourceIsVisible;
public LayerDynamicPropertiesViewModel(string property,
BindableCollection<GeneralHelpers.PropertyCollection> dataModelProps, LayerModel layer)
{
_property = property;
_layer = layer;
// Look for the existing property model
LayerDynamicPropertiesModelProposed = new LayerDynamicPropertiesModel();
var original = _layer.LayerProperties.FirstOrDefault(lp => lp.LayerProperty == _property);
if (original == null)
{
LayerDynamicPropertiesModelProposed.LayerProperty = property;
LayerDynamicPropertiesModelProposed.LayerPropertyType = LayerPropertyType.None;
}
else
{
GeneralHelpers.CopyProperties(LayerDynamicPropertiesModelProposed, original);
}
Name = property + ":";
Targets = new BindableCollection<GeneralHelpers.PropertyCollection>();
Targets.AddRange(dataModelProps.Where(p => p.Type == "Int32"));
Sources = new BindableCollection<GeneralHelpers.PropertyCollection>();
Sources.AddRange(dataModelProps.Where(p => p.Type == "Int32"));
PropertyChanged += OnPropertyChanged;
SelectedTarget =
dataModelProps.FirstOrDefault(p => p.Path == LayerDynamicPropertiesModelProposed.GameProperty);
SelectedSource =
dataModelProps.FirstOrDefault(p => p.Path == LayerDynamicPropertiesModelProposed.PercentageSource);
LayerPropertyType = LayerDynamicPropertiesModelProposed.LayerPropertyType;
}
public LayerPropertyType LayerPropertyType
{
get { return _layerPropertyType; }
set
{
if (value == _layerPropertyType) return;
_layerPropertyType = value;
NotifyOfPropertyChange(() => LayerPropertyType);
}
}
public string Name
{
get { return _name; }
set
{
if (value == _name) return;
_name = value;
NotifyOfPropertyChange(() => Name);
}
}
public LayerDynamicPropertiesModel LayerDynamicPropertiesModelProposed
{
get { return _layerDynamicPropertiesModelProposed; }
set
{
if (Equals(value, _layerDynamicPropertiesModelProposed)) return;
_layerDynamicPropertiesModelProposed = value;
NotifyOfPropertyChange(() => LayerDynamicPropertiesModelProposed);
}
}
public BindableCollection<GeneralHelpers.PropertyCollection> Targets { get; set; }
public GeneralHelpers.PropertyCollection SelectedTarget
{
get { return _selectedTarget; }
set
{
if (value.Equals(_selectedTarget)) return;
_selectedTarget = value;
NotifyOfPropertyChange(() => SelectedTarget);
}
}
public BindableCollection<GeneralHelpers.PropertyCollection> Sources { get; set; }
public GeneralHelpers.PropertyCollection SelectedSource
{
get { return _selectedSource; }
set
{
if (value.Equals(_selectedSource)) return;
_selectedSource = value;
NotifyOfPropertyChange(() => SelectedSource);
}
}
public bool SourcesIsVisible
{
get { return _sourcesIsVisible; }
set
{
if (value == _sourcesIsVisible) return;
_sourcesIsVisible = value;
NotifyOfPropertyChange(() => SourcesIsVisible);
}
}
public bool UserSourceIsVisible
{
get { return _userSourceIsVisible; }
set
{
if (value == _userSourceIsVisible) return;
_userSourceIsVisible = value;
NotifyOfPropertyChange(() => UserSourceIsVisible);
}
}
private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "SelectedTarget")
LayerDynamicPropertiesModelProposed.GameProperty = SelectedTarget.Path;
if (e.PropertyName == "SelectedSource")
LayerDynamicPropertiesModelProposed.PercentageSource = SelectedSource.Path;
if (e.PropertyName == "LayerPropertyType")
{
LayerDynamicPropertiesModelProposed.LayerPropertyType = LayerPropertyType;
UserSourceIsVisible = LayerPropertyType == LayerPropertyType.PercentageOf;
SourcesIsVisible = LayerPropertyType == LayerPropertyType.PercentageOfProperty;
}
}
public void Apply()
{
var original = _layer.LayerProperties.FirstOrDefault(lp => lp.LayerProperty == _property);
if (original == null)
_layer.LayerProperties.Add(LayerDynamicPropertiesModelProposed);
else
GeneralHelpers.CopyProperties(original, LayerDynamicPropertiesModelProposed);
}
}
}

View File

@ -0,0 +1,168 @@
using System;
using System.ComponentModel;
using System.Linq;
using System.Threading;
using System.Windows.Media;
using Artemis.KeyboardProviders;
using Artemis.Models.Profiles;
using Artemis.Utilities;
using Caliburn.Micro;
namespace Artemis.ViewModels.LayerEditor
{
public class LayerEditorViewModel<T> : Screen
{
private readonly KeyboardProvider _activeKeyboard;
private readonly BackgroundWorker _previewWorker;
private readonly bool _wasEnabled;
private LayerModel _layer;
private LayerModel _proposedLayer;
private LayerPropertiesModel _proposedProperties;
public LayerEditorViewModel(KeyboardProvider activeKeyboard, LayerModel layer)
{
_activeKeyboard = activeKeyboard;
_wasEnabled = layer.Enabled;
Layer = layer;
ProposedLayer = new LayerModel();
GeneralHelpers.CopyProperties(ProposedLayer, Layer);
Layer.Enabled = false;
DataModelProps = new BindableCollection<GeneralHelpers.PropertyCollection>();
ProposedProperties = new LayerPropertiesModel();
DataModelProps.AddRange(GeneralHelpers.GenerateTypeMap<T>());
LayerConditionVms =
new BindableCollection<LayerConditionViewModel<T>>(
layer.LayerConditions.Select(c => new LayerConditionViewModel<T>(this, c, DataModelProps)));
HeightProperties = new LayerDynamicPropertiesViewModel("Height", DataModelProps, layer);
WidthProperties = new LayerDynamicPropertiesViewModel("Width", DataModelProps, layer);
OpacityProperties = new LayerDynamicPropertiesViewModel("Opacity", DataModelProps, layer);
_previewWorker = new BackgroundWorker {WorkerSupportsCancellation = true};
_previewWorker.DoWork += PreviewWorkerOnDoWork;
_previewWorker.RunWorkerAsync();
PropertyChanged += AnimationUiHandler;
PreSelect();
}
public LayerDynamicPropertiesViewModel OpacityProperties { get; set; }
public LayerDynamicPropertiesViewModel WidthProperties { get; set; }
public LayerDynamicPropertiesViewModel HeightProperties { get; set; }
public BindableCollection<GeneralHelpers.PropertyCollection> DataModelProps { get; set; }
public BindableCollection<string> LayerTypes => new BindableCollection<string>();
public BindableCollection<LayerConditionViewModel<T>> LayerConditionVms { get; set; }
public LayerModel Layer
{
get { return _layer; }
set
{
if (Equals(value, _layer)) return;
_layer = value;
NotifyOfPropertyChange(() => Layer);
}
}
public LayerModel ProposedLayer
{
get { return _proposedLayer; }
set
{
if (Equals(value, _proposedLayer)) return;
_proposedLayer = value;
NotifyOfPropertyChange(() => ProposedLayer);
}
}
public LayerPropertiesModel ProposedProperties
{
get { return _proposedProperties; }
set
{
if (Equals(value, _proposedProperties)) return;
_proposedProperties = value;
NotifyOfPropertyChange(() => ProposedProperties);
}
}
public ImageSource LayerImage
{
get
{
var keyboardRect = _activeKeyboard.KeyboardRectangle(4);
var visual = new DrawingVisual();
using (var drawingContext = visual.RenderOpen())
{
// Setup the DrawingVisual's size
drawingContext.PushClip(new RectangleGeometry(keyboardRect));
drawingContext.DrawRectangle(new SolidColorBrush(Color.FromArgb(0, 0, 0, 0)), null, keyboardRect);
// Draw the layer
_layer.DrawPreview(drawingContext);
// Remove the clip
drawingContext.Pop();
}
var image = new DrawingImage(visual.Drawing);
return image;
}
}
private void PreviewWorkerOnDoWork(object sender, DoWorkEventArgs doWorkEventArgs)
{
while (!_previewWorker.CancellationPending)
{
NotifyOfPropertyChange(() => LayerImage);
Thread.Sleep(1000/25);
}
}
public void PreSelect()
{
GeneralHelpers.CopyProperties(ProposedProperties, Layer.UserProps);
}
private void AnimationUiHandler(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName != "_proposedProperties")
return;
}
public void AddCondition()
{
var condition = new LayerConditionModel();
Layer.LayerConditions.Add(condition);
LayerConditionVms.Add(new LayerConditionViewModel<T>(this, condition, DataModelProps));
}
public void Apply()
{
GeneralHelpers.CopyProperties(Layer.UserProps, ProposedProperties);
HeightProperties.Apply();
WidthProperties.Apply();
OpacityProperties.Apply();
}
public void DeleteCondition(LayerConditionViewModel<T> layerConditionViewModel,
LayerConditionModel layerConditionModel)
{
LayerConditionVms.Remove(layerConditionViewModel);
Layer.LayerConditions.Remove(layerConditionModel);
}
public override void CanClose(Action<bool> callback)
{
_previewWorker.CancelAsync();
_layer.Enabled = _wasEnabled;
base.CanClose(callback);
}
}
}

View File

@ -0,0 +1,503 @@
using System;
using System.ComponentModel;
using System.Drawing.Imaging;
using System.Dynamic;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Xml.Serialization;
using Artemis.DAL;
using Artemis.Events;
using Artemis.KeyboardProviders;
using Artemis.Managers;
using Artemis.Models;
using Artemis.Models.Profiles;
using Artemis.Utilities;
using Artemis.ViewModels.LayerEditor;
using Caliburn.Micro;
using MahApps.Metro;
namespace Artemis.ViewModels
{
public class ProfileEditorViewModel<T> : Screen, IHandle<ActiveKeyboardChanged>
{
private readonly GameModel _gameModel;
private readonly MainManager _mainManager;
private DateTime _downTime;
private LayerModel _draggingLayer;
private Point? _draggingLayerOffset;
private LayerEditorViewModel<T> _editorVm;
private Cursor _keyboardPreviewCursor;
private BindableCollection<LayerModel> _layers;
private BindableCollection<ProfileModel> _profiles;
private bool _resizing;
private LayerModel _selectedLayer;
private ProfileModel _selectedProfile;
public ProfileEditorViewModel(MainManager mainManager, GameModel gameModel)
{
_mainManager = mainManager;
_gameModel = gameModel;
Profiles = new BindableCollection<ProfileModel>();
Layers = new BindableCollection<LayerModel>();
_mainManager.Events.Subscribe(this);
PropertyChanged += PropertyChangeHandler;
LoadProfiles();
}
public BindableCollection<ProfileModel> Profiles
{
get { return _profiles; }
set
{
if (Equals(value, _profiles)) return;
_profiles = value;
NotifyOfPropertyChange(() => Profiles);
}
}
public BindableCollection<LayerModel> Layers
{
get { return _layers; }
set
{
if (Equals(value, _layers)) return;
_layers = value;
NotifyOfPropertyChange(() => Layers);
}
}
public LayerModel SelectedLayer
{
get { return _selectedLayer; }
set
{
if (Equals(value, _selectedLayer)) return;
_selectedLayer = value;
NotifyOfPropertyChange(() => SelectedLayer);
NotifyOfPropertyChange(() => CanRemoveLayer);
}
}
public Cursor KeyboardPreviewCursor
{
get { return _keyboardPreviewCursor; }
set
{
if (Equals(value, _keyboardPreviewCursor)) return;
_keyboardPreviewCursor = value;
NotifyOfPropertyChange(() => KeyboardPreviewCursor);
}
}
public ProfileModel SelectedProfile
{
get { return _selectedProfile; }
set
{
if (Equals(value, _selectedProfile)) return;
_selectedProfile = value;
Layers.Clear();
Layers.AddRange(_selectedProfile?.Layers);
NotifyOfPropertyChange(() => SelectedProfile);
NotifyOfPropertyChange(() => CanAddLayer);
NotifyOfPropertyChange(() => CanRemoveLayer);
}
}
public ImageSource KeyboardPreview
{
get
{
if (_selectedProfile == null || ActiveKeyboard == null)
return null;
var keyboardRect = ActiveKeyboard.KeyboardRectangle(4);
var visual = new DrawingVisual();
using (var drawingContext = visual.RenderOpen())
{
// Setup the DrawingVisual's size
drawingContext.PushClip(new RectangleGeometry(keyboardRect));
drawingContext.DrawRectangle(new SolidColorBrush(Color.FromArgb(0, 0, 0, 0)), null, keyboardRect);
// Draw the layers
foreach (var layerModel in _selectedProfile.Layers.OrderByDescending(l => l.Order))
layerModel.DrawPreview(drawingContext);
// Get the selection color
var color = (Color) ThemeManager.DetectAppStyle(Application.Current).Item2.Resources["AccentColor"];
var pen = new Pen(new SolidColorBrush(color), 0.4);
// Draw the selection outline and resize indicator
if (SelectedLayer != null && SelectedLayer.Enabled)
{
var layerRect = SelectedLayer.UserProps.GetRect();
// Deflate the rect so that the border is drawn on the inside
layerRect.Inflate(-0.2, -0.2);
// Draw an outline around the selected layer
drawingContext.DrawRectangle(null, pen, layerRect);
// Draw a resize indicator in the bottom-right
drawingContext.DrawLine(pen,
new Point(layerRect.BottomRight.X - 1, layerRect.BottomRight.Y - 0.5),
new Point(layerRect.BottomRight.X - 1.2, layerRect.BottomRight.Y - 0.7));
drawingContext.DrawLine(pen,
new Point(layerRect.BottomRight.X - 0.5, layerRect.BottomRight.Y - 1),
new Point(layerRect.BottomRight.X - 0.7, layerRect.BottomRight.Y - 1.2));
drawingContext.DrawLine(pen,
new Point(layerRect.BottomRight.X - 0.5, layerRect.BottomRight.Y - 0.5),
new Point(layerRect.BottomRight.X - 0.7, layerRect.BottomRight.Y - 0.7));
}
// Remove the clip
drawingContext.Pop();
}
var image = new DrawingImage(visual.Drawing);
return image;
}
}
public ImageSource KeyboardImage
{
get
{
using (var memory = new MemoryStream())
{
if (ActiveKeyboard?.PreviewSettings.Image == null)
return null;
ActiveKeyboard.PreviewSettings.Image.Save(memory, ImageFormat.Png);
memory.Position = 0;
var bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.StreamSource = memory;
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.EndInit();
return bitmapImage;
}
}
}
public PreviewSettings? PreviewSettings => ActiveKeyboard?.PreviewSettings;
public bool CanAddLayer => _selectedProfile != null;
public bool CanRemoveLayer => _selectedProfile != null && _selectedLayer != null;
private KeyboardProvider ActiveKeyboard => _mainManager.KeyboardManager.ActiveKeyboard;
/// <summary>
/// Handles chaning the active keyboard, updating the preview image and profiles collection
/// </summary>
/// <param name="message"></param>
public void Handle(ActiveKeyboardChanged message)
{
NotifyOfPropertyChange(() => KeyboardImage);
NotifyOfPropertyChange(() => PreviewSettings);
LoadProfiles();
}
/// <summary>
/// Handles refreshing the layer preview
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void PropertyChangeHandler(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "KeyboardPreview")
return;
NotifyOfPropertyChange(() => KeyboardPreview);
if (SelectedProfile != null)
ProfileProvider.AddOrUpdate(SelectedProfile);
}
/// <summary>
/// Loads all profiles for the current game and keyboard
/// </summary>
private void LoadProfiles()
{
Profiles.Clear();
Profiles.AddRange(ProfileProvider.GetAll(_gameModel));
SelectedProfile = Profiles.FirstOrDefault();
}
/// <summary>
/// Adds a new profile to the current game and keyboard
/// </summary>
public async void AddProfile()
{
var name = await _mainManager.DialogService.ShowInputDialog("Add new profile",
"Please provide a profile name unique to this game and keyboard.");
if (name.Length < 1)
{
_mainManager.DialogService.ShowMessageBox("Invalid profile name", "Please provide a valid profile name");
return;
}
var profile = new ProfileModel
{
Name = name,
KeyboardName = ActiveKeyboard.Name,
GameName = _gameModel.Name
};
if (ProfileProvider.GetAll().Contains(profile))
{
var overwrite = await _mainManager.DialogService.ShowQuestionMessageBox("Overwrite existing profile",
"A profile with this name already exists for this game. Would you like to overwrite it?");
if (!overwrite.Value)
return;
}
ProfileProvider.AddOrUpdate(profile);
LoadProfiles();
SelectedProfile = profile;
}
public void ToggleEnabled(LayerModel layer)
{
NotifyOfPropertyChange(() => KeyboardPreview);
}
/// <summary>
/// Opens a new LayerEditorView for the given layer
/// </summary>
/// <param name="layer">The layer to open the view for</param>
public void LayerEditor(LayerModel layer)
{
IWindowManager manager = new WindowManager();
_editorVm = new LayerEditorViewModel<T>(ActiveKeyboard, layer);
dynamic settings = new ExpandoObject();
settings.Title = "Artemis | Edit " + layer.Name;
manager.ShowDialog(_editorVm, null, settings);
// Refresh the layer list and reselect the last layer
NotifyOfPropertyChange(() => Layers);
SelectedLayer = layer;
}
/// <summary>
/// Adds a new layer to the profile and selects it
/// </summary>
public void AddLayer()
{
if (_selectedProfile == null)
return;
var layer = SelectedProfile.AddLayer();
Layers.Add(layer);
SelectedLayer = layer;
}
/// <summary>
/// Removes the currently selected layer from the profile
/// </summary>
public void RemoveLayer()
{
if (_selectedProfile == null || _selectedLayer == null)
return;
SelectedProfile.Layers.Remove(_selectedLayer);
Layers.Remove(_selectedLayer);
SelectedProfile.FixOrder();
}
/// <summary>
/// Removes the given layer from the profile
/// </summary>
/// <param name="layer"></param>
public void RemoveLayerFromMenu(LayerModel layer)
{
SelectedProfile.Layers.Remove(layer);
Layers.Remove(layer);
SelectedProfile.FixOrder();
}
/// <summary>
/// Clones the given layer and adds it to the profile, on top of the original
/// </summary>
/// <param name="layer"></param>
public void CloneLayer(LayerModel layer)
{
var clone = GeneralHelpers.Clone(layer);
clone.Order = layer.Order - 1;
SelectedProfile.Layers.Add(clone);
Layers.Add(clone);
SelectedProfile.FixOrder();
}
/// <summary>
/// Moves the currently selected layer up in the profile's layer tree
/// </summary>
public void LayerUp()
{
if (SelectedLayer == null)
return;
var reorderLayer = SelectedLayer;
if (SelectedLayer.ParentLayer != null)
SelectedLayer.ParentLayer.Reorder(SelectedLayer, true);
else
SelectedLayer.ParentProfile.Reorder(SelectedLayer, true);
NotifyOfPropertyChange(() => Layers);
SelectedLayer = reorderLayer;
}
/// <summary>
/// Moves the currently selected layer down in the profile's layer tree
/// </summary>
public void LayerDown()
{
if (SelectedLayer == null)
return;
var reorderLayer = SelectedLayer;
if (SelectedLayer.ParentLayer != null)
SelectedLayer.ParentLayer.Reorder(SelectedLayer, false);
else
SelectedLayer.ParentProfile.Reorder(SelectedLayer, false);
NotifyOfPropertyChange(() => Layers);
SelectedLayer = reorderLayer;
}
/// <summary>
/// Handler for clicking
/// </summary>
/// <param name="e"></param>
public void MouseDownKeyboardPreview(MouseButtonEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
_downTime = DateTime.Now;
}
/// <summary>
/// Second handler for clicking, selects a the layer the user clicked on
/// if the used clicked on an empty spot, deselects the current layer
/// </summary>
/// <param name="e"></param>
public void MouseUpKeyboardPreview(MouseButtonEventArgs e)
{
var timeSinceDown = DateTime.Now - _downTime;
if (!(timeSinceDown.TotalMilliseconds < 500))
return;
var pos = e.GetPosition((Image) e.OriginalSource);
var x = pos.X/((double) ActiveKeyboard.PreviewSettings.Width/ActiveKeyboard.Width);
var y = pos.Y/((double) ActiveKeyboard.PreviewSettings.Height/ActiveKeyboard.Height);
var hoverLayer = SelectedProfile.Layers.OrderBy(l => l.Order).Where(l => l.Enabled)
.FirstOrDefault(l => l.UserProps.GetRect(1).Contains(x, y));
SelectedLayer = hoverLayer;
}
/// <summary>
/// Handler for resizing and moving the currently selected layer
/// </summary>
/// <param name="e"></param>
public void MouseMoveKeyboardPreview(MouseEventArgs e)
{
var pos = e.GetPosition((Image) e.OriginalSource);
var x = pos.X/((double) ActiveKeyboard.PreviewSettings.Width/ActiveKeyboard.Width);
var y = pos.Y/((double) ActiveKeyboard.PreviewSettings.Height/ActiveKeyboard.Height);
var hoverLayer = SelectedProfile.Layers.OrderBy(l => l.Order).Where(l => l.Enabled)
.FirstOrDefault(l => l.UserProps.GetRect(1).Contains(x, y));
HandleDragging(e, x, y, hoverLayer);
if (hoverLayer == null)
{
KeyboardPreviewCursor = Cursors.Arrow;
return;
}
// Turn the mouse pointer into a hand if hovering over an active layer
if (hoverLayer == SelectedLayer)
{
var rect = hoverLayer.UserProps.GetRect(1);
KeyboardPreviewCursor =
Math.Sqrt(Math.Pow(x - rect.BottomRight.X, 2) + Math.Pow(y - rect.BottomRight.Y, 2)) < 0.6
? Cursors.SizeNWSE
: Cursors.SizeAll;
}
else
KeyboardPreviewCursor = Cursors.Hand;
}
/// <summary>
/// Handles dragging the given layer
/// </summary>
/// <param name="e"></param>
/// <param name="x"></param>
/// <param name="y"></param>
/// <param name="hoverLayer"></param>
private void HandleDragging(MouseEventArgs e, double x, double y, LayerModel hoverLayer)
{
// Reset the dragging state on mouse release
if (e.LeftButton == MouseButtonState.Released ||
(_draggingLayer != null && _selectedLayer != _draggingLayer))
{
_draggingLayerOffset = null;
_draggingLayer = null;
return;
}
if (SelectedLayer == null)
return;
// Setup the dragging state on mouse press
if (_draggingLayerOffset == null && hoverLayer != null && e.LeftButton == MouseButtonState.Pressed)
{
var layerRect = hoverLayer.UserProps.GetRect(1);
_draggingLayerOffset = new Point(x - SelectedLayer.UserProps.X, y - SelectedLayer.UserProps.Y);
_draggingLayer = hoverLayer;
if (Math.Sqrt(Math.Pow(x - layerRect.BottomRight.X, 2) + Math.Pow(y - layerRect.BottomRight.Y, 2)) < 0.6)
_resizing = true;
else
_resizing = false;
}
if (_draggingLayerOffset == null || _draggingLayer == null || (_draggingLayer != SelectedLayer))
return;
// If no setup or reset was done, handle the actual dragging action
if (_resizing)
{
_draggingLayer.UserProps.Width = (int) Math.Round(x - _draggingLayer.UserProps.X);
_draggingLayer.UserProps.Height = (int) Math.Round(y - _draggingLayer.UserProps.Y);
if (_draggingLayer.UserProps.Width < 1)
_draggingLayer.UserProps.Width = 1;
if (_draggingLayer.UserProps.Height < 1)
_draggingLayer.UserProps.Height = 1;
}
else
{
_draggingLayer.UserProps.X = (int) Math.Round(x - _draggingLayerOffset.Value.X);
_draggingLayer.UserProps.Y = (int) Math.Round(y - _draggingLayerOffset.Value.Y);
}
NotifyOfPropertyChange(() => KeyboardPreview);
}
}
}

View File

@ -25,7 +25,6 @@ namespace Artemis.ViewModels
_shellViewModel.MainManager.Events.Subscribe(this);
_shellViewModel.MainManager.EnableProgram();
_checkedForUpdate = false;
//ActiveIcon = "../logo.ico";
if (General.Default.ShowOnStartup)
ShowWindow();

View File

@ -0,0 +1,70 @@
<UserControl x:Class="Artemis.Views.LayerEditor.LayerConditionView"
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.Views.LayerEditor"
xmlns:cal="http://www.caliburnproject.org"
xmlns:utilities="clr-namespace:Artemis.Utilities"
mc:Ignorable="d" d:DesignWidth="613.296" Height="46">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Resources/Icons.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid Margin="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="30" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!-- Left -->
<ComboBox x:Name="DataModelProps" Grid.Column="0" Width="210" MaxDropDownHeight="125"
HorizontalAlignment="Center" VerticalAlignment="Top">
<ComboBox.ItemTemplate>
<DataTemplate>
<Grid MinWidth="522">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Path=Display}" HorizontalAlignment="Left" />
<TextBlock Grid.Column="1" FontWeight="Bold" Text="{Binding Path=DisplayType}"
HorizontalAlignment="Right" />
</Grid>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<!-- Center -->
<TextBlock Grid.Column="1" Text="is" VerticalAlignment="Top" HorizontalAlignment="Center" Margin="0,3,0,0" />
<ComboBox x:Name="Operators" Grid.Column="2" Width="150" MaxDropDownHeight="125" HorizontalAlignment="Center"
VerticalAlignment="Top" DisplayMemberPath="Display" />
<!-- Right -->
<Grid Grid.Column="3" HorizontalAlignment="Left" Margin="10,0,0,0" Width="148">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="120" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" x:Name="UserValueIsVisible" HorizontalAlignment="Left" VerticalAlignment="Top">
<TextBox x:Name="UserValue" VerticalAlignment="Center" HorizontalAlignment="Left" Width="110" />
</StackPanel>
<Button Grid.Column="1" x:Name="Delete" Width="26" Height="26" Style="{DynamicResource SquareButtonStyle}"
VerticalAlignment="Top" HorizontalAlignment="Right">
<Button.Content>
<Rectangle Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}" Width="12" Height="12">
<Rectangle.OpacityMask>
<VisualBrush Visual="{StaticResource appbar_delete}" Stretch="Fill" />
</Rectangle.OpacityMask>
</Rectangle>
</Button.Content>
</Button>
</Grid>
</Grid>
</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.Views.LayerEditor
{
/// <summary>
/// Interaction logic for LayerConditionView.xaml
/// </summary>
public partial class LayerConditionView : UserControl
{
public LayerConditionView()
{
InitializeComponent();
}
}
}

View File

@ -0,0 +1,87 @@
<UserControl x:Class="Artemis.Views.LayerEditor.LayerDynamicPropertiesView"
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.Views.LayerEditor"
xmlns:utilities="clr-namespace:Artemis.Utilities"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:profileEnumerations="clr-namespace:Artemis.Models.Profiles"
xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
mc:Ignorable="d"
d:DesignHeight="40" d:DesignWidth="500">
<UserControl.Resources>
<utilities:EnumDescriptionConverter x:Key="HEnumDescriptionConverter" />
<ObjectDataProvider MethodName="GetValues"
ObjectType="{x:Type sys:Enum}"
x:Key="DynamicPropertyValues">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="profileEnumerations:LayerPropertyType" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</UserControl.Resources>
<Grid>
<!-- Height -->
<Grid.ColumnDefinitions>
<ColumnDefinition Width="65*" />
<ColumnDefinition Width="86*" />
<ColumnDefinition Width="65*" />
<ColumnDefinition Width="86*" />
</Grid.ColumnDefinitions>
<TextBlock x:Name="Name" Grid.Column="0" Margin="10" FontSize="13.333" VerticalAlignment="Center" Height="18" />
<!-- Target property -->
<ComboBox x:Name="Targets" Grid.Column="1" Margin="10,0" MaxDropDownHeight="125" VerticalAlignment="Center"
Height="22">
<ComboBox.ItemTemplate>
<DataTemplate>
<Grid MinWidth="435">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Path=Display}" HorizontalAlignment="Left" />
<TextBlock Grid.Column="1" FontWeight="Bold" Text="{Binding Path=DisplayType}"
HorizontalAlignment="Right" />
</Grid>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<!-- Dynamic type -->
<ComboBox SelectedItem="{Binding Path=LayerPropertyType}" Grid.Column="2"
ItemsSource="{Binding Source={StaticResource DynamicPropertyValues}}"
Margin="10,0" VerticalAlignment="Center" Height="22">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Converter={StaticResource HEnumDescriptionConverter}}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<!-- PercentageOfProperty -->
<StackPanel Grid.Column="3" x:Name="SourcesIsVisible" VerticalAlignment="Center">
<ComboBox x:Name="Sources" Margin="10,0" MaxDropDownHeight="125" Height="22">
<ComboBox.ItemTemplate>
<DataTemplate>
<Grid MinWidth="522">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Path=Display}" HorizontalAlignment="Left" />
<TextBlock Grid.Column="1" FontWeight="Bold" Text="{Binding Path=DisplayType}"
HorizontalAlignment="Right" />
</Grid>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</StackPanel>
<!-- PercentageOf -->
<StackPanel Grid.Column="3" x:Name="UserSourceIsVisible" VerticalAlignment="Center">
<controls:NumericUpDown Margin="10,0" Height="22" Value="{Binding Path=LayerDynamicPropertiesModelProposed.PercentageSource, Mode=TwoWay}" />
</StackPanel>
</Grid>
</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.Views.LayerEditor
{
/// <summary>
/// Interaction logic for LayerDynamicPropertiesView.xaml
/// </summary>
public partial class LayerDynamicPropertiesView : UserControl
{
public LayerDynamicPropertiesView()
{
InitializeComponent();
}
}
}

View File

@ -0,0 +1,141 @@
<controls:MetroWindow x:Class="Artemis.Views.LayerEditor.LayerEditorView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
xmlns:utilities="clr-namespace:Artemis.Utilities"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
Title="Artemis | Edit Layer" Height="750" Width="630"
xmlns:profileEnumerations="clr-namespace:Artemis.Models.Profiles"
xmlns:ncore="http://schemas.ncore.com/wpf/xaml/colorbox"
GlowBrush="{DynamicResource AccentColorBrush}" Icon="../../Resources/bow.png" ResizeMode="NoResize">
<controls:MetroWindow.Resources>
<utilities:EnumDescriptionConverter x:Key="HEnumDescriptionConverter" />
<ObjectDataProvider MethodName="GetValues"
ObjectType="{x:Type sys:Enum}"
x:Key="AnimationEnumValues">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="profileEnumerations:LayerAnimation" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<ObjectDataProvider MethodName="GetValues"
ObjectType="{x:Type sys:Enum}"
x:Key="DynamicPropertyValues">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="profileEnumerations:LayerPropertyType" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</controls:MetroWindow.Resources>
<Grid Margin="10,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="65*" />
<ColumnDefinition Width="86*" />
<ColumnDefinition Width="65*" />
<ColumnDefinition Width="86*" />
</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="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition />
</Grid.RowDefinitions>
<!-- Header -->
<Label Grid.Row="0" Grid.ColumnSpan="4" FontSize="20" Content="Basics" />
<!-- Layer name -->
<TextBlock Grid.Row="1" Grid.Column="0" Margin="10,12" FontSize="13.333" Text="Name:"
VerticalAlignment="Center" Height="18" />
<TextBox Grid.Row="1" Grid.Column="1" x:Name="Name" Margin="10" Text="{Binding Path=Layer.Name}" />
<!-- Layer type -->
<!-- Condition editor -->
<Label Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="4" FontSize="20" Content="Display if.." />
<Border Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="4" BorderThickness="1"
BorderBrush="{StaticResource GrayBrush7}" Margin="10,0" SnapsToDevicePixels="True">
<ListBox Height="138" x:Name="LayerConditionVms" ScrollViewer.VerticalScrollBarVisibility="Visible">
<ListBox.Template>
<ControlTemplate>
<ScrollViewer>
<ItemsPresenter />
</ScrollViewer>
</ControlTemplate>
</ListBox.Template>
</ListBox>
</Border>
<Button Grid.Row="4" Grid.Column="3" x:Name="AddCondition" Content="Add condition" VerticalAlignment="Center"
Style="{DynamicResource SquareButtonStyle}" Width="95" HorizontalAlignment="Right" Height="30"
Margin="0,10,10,10" ScrollViewer.VerticalScrollBarVisibility="Auto" />
<!-- Advanced -->
<Label Grid.Row="4" Grid.Column="0" FontSize="20" HorizontalAlignment="Left"
Content="Advanced" Width="97" VerticalAlignment="Bottom" />
<!-- Colors -->
<TextBlock Grid.Row="5" Grid.Column="0" Margin="10,13,10,0" FontSize="13.333" Text="Color(s):"
VerticalAlignment="Top" Height="18" />
<Border Grid.Row="5" Grid.Column="1" Margin="10" BorderBrush="{StaticResource ControlBorderBrush}"
BorderThickness="1" SnapsToDevicePixels="True" ToolTip="Click to edit">
<ncore:ColorBox Brush="{Binding Path=ProposedProperties.Brush, Mode=TwoWay}" Height="24" />
</Border>
<!-- ContainedBrush -->
<TextBlock Grid.Row="5" Grid.Column="2" Margin="10" FontSize="13.333" Text="Contained colors:"
VerticalAlignment="Center" Height="18" />
<controls:ToggleSwitch IsChecked="{Binding Path=ProposedProperties.ContainedBrush, Mode=TwoWay}" Grid.Row="5"
Grid.Column="3" OnLabel="Yes" OffLabel="No" Margin="10,1,5,1" VerticalAlignment="Center"
Height="36" />
<!-- Animation -->
<TextBlock Grid.Row="6" Grid.Column="0" Margin="10" FontSize="13.333" Text="Animation:"
VerticalAlignment="Center"
Height="18" />
<ComboBox Grid.Row="6" Grid.Column="1" ItemsSource="{Binding Source={StaticResource AnimationEnumValues}}"
Margin="10,10,10,0" SelectedItem="{Binding Path=ProposedProperties.Animation}"
VerticalAlignment="Top" Height="22">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Converter={StaticResource HEnumDescriptionConverter}}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<!-- Animation Speed -->
<TextBlock Grid.Row="6" Grid.Column="2" Margin="10" FontSize="13.333" Text="Animation speed:"
VerticalAlignment="Center" Height="18" />
<Slider x:Name="RotationSpeed" Grid.Row="6" Grid.Column="3" VerticalAlignment="Center"
TickPlacement="None" TickFrequency="0.05"
Value="{Binding Path=ProposedProperties.AnimationSpeed, Mode=TwoWay}" Minimum="0.05" Maximum="3"
SmallChange="1" IsSnapToTickEnabled="True" Margin="10,12,10,2" Height="24" />
<!-- Dynamic -->
<Label Grid.Row="7" Grid.Column="0" FontSize="20" HorizontalAlignment="Left"
Content="Dynamic" Width="97" VerticalAlignment="Bottom" />
<!-- Dynamic property views -->
<ContentControl Grid.Row="8" Grid.Column="0" Grid.ColumnSpan="4" x:Name="HeightProperties" />
<ContentControl Grid.Row="9" Grid.Column="0" Grid.ColumnSpan="4" x:Name="WidthProperties" />
<ContentControl Grid.Row="10" Grid.Column="0" Grid.ColumnSpan="4" x:Name="OpacityProperties" />
<Button Grid.Row="12" Grid.Column="0" x:Name="Apply" Content="Apply" VerticalAlignment="Bottom"
Style="{DynamicResource SquareButtonStyle}" Width="95" HorizontalAlignment="Left" Margin="10,0,0,20"
Height="30" />
<Button Grid.Row="12" Grid.Column="1" x:Name="PreSelect" Content="Reset" VerticalAlignment="Bottom"
Style="{DynamicResource SquareButtonStyle}" Width="95" HorizontalAlignment="Left" Margin="10,0,0,20"
Height="30" />
</Grid>
</controls:MetroWindow>

View File

@ -0,0 +1,15 @@
using MahApps.Metro.Controls;
namespace Artemis.Views.LayerEditor
{
/// <summary>
/// Interaction logic for LayerEditorView.xaml
/// </summary>
public partial class LayerEditorView : MetroWindow
{
public LayerEditorView()
{
InitializeComponent();
}
}
}

View File

@ -0,0 +1,134 @@
<UserControl x:Class="Artemis.Views.ProfileEditorView"
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:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:itemBehaviours="clr-namespace:Artemis.ItemBehaviours"
xmlns:utilities="clr-namespace:Artemis.Utilities"
mc:Ignorable="d"
d:DesignHeight="473" Width="1055">
<UserControl.Resources>
<utilities:LayerOrderConverter x:Key="LayerOrderConverter" />
</UserControl.Resources>
<Grid Width="Auto" Height="Auto">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!-- Preview -->
<Label Grid.Column="0" Grid.Row="0" FontSize="20" HorizontalAlignment="Left" Content="Preview" />
<Border Grid.Column="0" Grid.Row="1" Background="#FF232323" BorderBrush="{DynamicResource HighlightBrush}"
BorderThickness="3" Width="750" Height="400">
<Border>
<Border.Effect>
<!-- TODO: Pulse 10-20 -->
<DropShadowEffect ShadowDepth="0" Color="{DynamicResource HighlightColor}" Opacity="1"
BlurRadius="20" />
</Border.Effect>
<Grid>
<Image Grid.Column="0" Grid.Row="0" Source="{Binding Path=KeyboardImage}" Margin="50" />
<Image Grid.Column="0" Grid.Row="0" Source="{Binding Path=KeyboardPreview}" Opacity="0.8"
Width="{Binding Path=PreviewSettings.Width}"
Height="{Binding Path=PreviewSettings.Height}"
Margin="{Binding Path=PreviewSettings.Margin}"
Stretch="Fill" Cursor="{Binding Path=KeyboardPreviewCursor}"
cal:Message.Attach="[Event MouseMove] = [Action MouseMoveKeyboardPreview($eventArgs)];
[Event MouseDown] = [Action MouseDownKeyboardPreview($eventArgs)];
[Event MouseUp] = [Action MouseUpKeyboardPreview($eventArgs)]" />
</Grid>
</Border>
</Border>
<!-- Profile management -->
<StackPanel Grid.Column="0" Grid.Row="2" Orientation="Horizontal" Margin="0,5,0,0">
<Label Content="Active profile" />
<ComboBox Width="110" VerticalAlignment="Top" x:Name="Profiles" DisplayMemberPath="Name"
Margin="5,0,0,0" />
<Button x:Name="AddProfile" Content="Add profile" VerticalAlignment="Top"
Style="{DynamicResource SquareButtonStyle}" Width="95" HorizontalAlignment="Left" Margin="10,0,0,0" />
<Button x:Name="RemoveProfile" Content="Remove profile" VerticalAlignment="Top"
Style="{DynamicResource SquareButtonStyle}" Width="95" HorizontalAlignment="Right"
Margin="10,0,0,0" />
</StackPanel>
<!-- Layer list -->
<Label Grid.Column="1" Grid.Row="0" FontSize="20" HorizontalAlignment="Left" Content="Layers" Margin="10,0,0,0" />
<Border Grid.Column="1" Grid.Row="1" Background="#FF232323" BorderBrush="{DynamicResource HighlightBrush}"
BorderThickness="3" Margin="10,0,0,0" Height="400" Width="233">
<TreeView x:Name="ProfileTree" ItemsSource="{Binding Path=Layers, Converter={StaticResource LayerOrderConverter}, ConverterParameter=Order}">
<i:Interaction.Behaviors>
<itemBehaviours:BindableSelectedItemBehavior SelectedItem="{Binding SelectedLayer, Mode=TwoWay}" />
</i:Interaction.Behaviors>
<TreeView.Resources>
<ResourceDictionary
Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseDark.xaml" />
</TreeView.Resources>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children, Converter={StaticResource LayerOrderConverter}, ConverterParameter=Order}">
<StackPanel Orientation="Horizontal" Tag="{Binding DataContext, ElementName=ProfileTree}">
<StackPanel.ContextMenu>
<ContextMenu
cal:Action.TargetWithoutContext="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
<MenuItem Header="Rename" />
<MenuItem Header="Duplicate" cal:Message.Attach="CloneLayer($datacontext)"/>
<MenuItem Header="Delete" cal:Message.Attach="RemoveLayerFromMenu($datacontext)"/>
<MenuItem Header="Properties" cal:Message.Attach="LayerEditor($datacontext)" />
</ContextMenu>
</StackPanel.ContextMenu>
<CheckBox VerticalAlignment="Center" ToolTip="Layer enabled" IsChecked="{Binding Enabled}"
cal:Message.Attach="ToggleEnabled($datacontext)" />
<Image Height="18" Width="18" Source="{Binding LayerImage}" />
<TextBlock Margin="5,0,0,0" Text="{Binding Name}" VerticalAlignment="Center" />
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Border>
<Grid Grid.Column="1" Grid.Row="2" Margin="10,5,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Button Grid.Column="0" x:Name="AddLayer" Content="Add layer" VerticalAlignment="Top"
Style="{DynamicResource SquareButtonStyle}" Width="95" />
<Button Grid.Column="3" x:Name="RemoveLayer" Content="Remove layer" VerticalAlignment="Top"
Style="{DynamicResource SquareButtonStyle}" Width="95" />
</Grid>
<!-- Layer movement -->
<StackPanel Grid.Column="2" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="10,0,0,0">
<Button x:Name="LayerUp" Width="40" Height="40" Style="{DynamicResource MetroCircleButtonStyle}">
<Button.Content>
<Rectangle
Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}"
Width="16" Height="16">
<Rectangle.OpacityMask>
<VisualBrush Visual="{StaticResource appbar_arrow_up}" Stretch="Fill" />
</Rectangle.OpacityMask>
</Rectangle>
</Button.Content>
</Button>
<Button x:Name="LayerDown" Width="40" Height="40" Style="{DynamicResource MetroCircleButtonStyle}">
<Button.Content>
<Rectangle
Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}"
Width="16" Height="16">
<Rectangle.OpacityMask>
<VisualBrush Visual="{StaticResource appbar_arrow_down}" Stretch="Fill" />
</Rectangle.OpacityMask>
</Rectangle>
</Button.Content>
</Button>
</StackPanel>
</Grid>
</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.Views
{
/// <summary>
/// Interaction logic for ProfileEditorView.xaml
/// </summary>
public partial class ProfileEditorView : UserControl
{
public ProfileEditorView()
{
InitializeComponent();
}
}
}

View File

@ -8,8 +8,8 @@
xmlns:dialogs="clr-namespace:MahApps.Metro.Controls.Dialogs;assembly=MahApps.Metro"
dialogs:DialogParticipation.Register="{Binding RelativeSource={RelativeSource Self}, Path=DataContext}"
mc:Ignorable="d"
Title="Artemis" Height="670" Width="690"
MinWidth="500" MinHeight="400"
Title="Artemis" Height="800" Width="1210"
MinHeight="800" MinWidth="1210"
GlowBrush="{DynamicResource AccentColorBrush}" Icon="../logo.ico">
<!-- Bit of extra code to use a different icon than in the taskbar -->
<Controls:MetroWindow.IconTemplate>

Binary file not shown.

View File

@ -6,18 +6,18 @@
<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.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="Extended.Wpf.Toolkit" version="2.7" targetFramework="net452" />
<package id="Hardcodet.NotifyIcon.Wpf" version="1.0.8" 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="MahApps.Metro.Resources" version="0.5.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="Newtonsoft.Json" version="8.0.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="System.Linq.Dynamic" version="1.0.6" targetFramework="net452" />
<package id="VirtualInput" version="1.0.1" targetFramework="net452" />
<package id="WpfExceptionViewer" version="1.0.0.0" targetFramework="net452" />
</packages>

View File

@ -0,0 +1,104 @@
// Original work by VRocker https://github.com/VRocker/LogiLed2Corsair
// I'm mainly a C# developer, and these modification aren't a piece of art, but it suits our needs.
// The MIT License (MIT)
//
// Copyright (c) 2015 VRocker
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include "Logger.h"
#include <time.h>
#include <stdlib.h>
#include <stdarg.h>
// Ok this looks butt-ugleh but its just to force the default log level to debug if we compile in debug
#ifdef _DEBUG
LogLevel CLogger::m_eLogLevel = LogLevel::Debug;
#else
LogLevel CLogger::m_eLogLevel = LogLevel::All;
#endif
FILE* CLogger::m_pFile = 0;
void CLogger::InitLogging(const char* szFile)
{
if (!m_pFile)
{
m_pFile = fopen(szFile, "a+");
if (!m_pFile)
{
// Hum, we couldn't open the file for writing
printf("ERROR: Unable to open log file %s.\n", szFile);
}
}
}
void CLogger::EndLogging(void)
{
if (m_pFile)
{
fclose(m_pFile);
m_pFile = 0;
}
}
void CLogger::OutputLog_s(const char* sz, const LogLevel eLevel)
{
// If the level of this log entry is less important than what we are told to log, just return
if (eLevel < m_eLogLevel)
return;
// If we don't have a file to write to, bail.
if (!m_pFile)
return;
char szOutput[512] = {0};
time_t rawtime;
struct tm* timeinfo;
time(&rawtime);
timeinfo = localtime(&rawtime);
// Timestamp the log entry
size_t uiLen = sprintf(szOutput, "<%.2d/%.2d/%.2d - %.2d:%.2d:%.2d> %s\n", timeinfo->tm_mday, timeinfo->tm_mon + 1, timeinfo->tm_year + 1900, timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec, sz);
// Write the text to the file
fwrite(szOutput, 1, uiLen, m_pFile);
// Flush the log file to the disk. May move this to a seperate function
fflush(m_pFile);
// Output the text to any console that may be attached
printf("%s", szOutput);
}
void CLogger::OutputLog(const char* sz, const LogLevel eLevel, ...)
{
char szText[1024] = {0};
va_list marker;
va_start(marker, eLevel);
vsprintf(szText, sz, marker);
va_end(marker);
// Since this function is pretty much the same as the safer function, we'll just redirect it there
OutputLog_s(szText, eLevel);
}

View File

@ -0,0 +1,82 @@
// Original work by VRocker https://github.com/VRocker/LogiLed2Corsair
// I'm mainly a C# developer, and these modification aren't a piece of art, but it suits our needs.
// The MIT License (MIT)
//
// Copyright (c) 2015 VRocker
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#pragma once
#ifndef _LOGGER_H
#define _LOGGER_H
#include <stdio.h>
enum class LogLevel
{
Debug,
All,
Critical,
Warning,
Information,
User,
Internal,
None,
// Just to force the compiler to treat the enum options as an int
FORCE_32BIT = 0x7fffffff
};
class CLogger
{
public:
static LogLevel GetLogLevel(void)
{
return m_eLogLevel;
}
static void SetLogLevel(const LogLevel e)
{
#ifndef _DEBUG
if ( e == LogLevel::Debug ) return;
#endif
m_eLogLevel = e;
}
static void InitLogging(const char* szFile);
// Always remember to end logging when you are finished otherwise you will have file handles floating around
static void EndLogging(void);
// Output the text to a log file.
static void OutputLog_s(const char* sz, const LogLevel eLevel);
static void OutputLog(const char* sz, const LogLevel eLevel, ...);
static FILE* GetFile()
{
return m_pFile;
}
private:
static LogLevel m_eLogLevel;
static FILE* m_pFile;
};
#endif

View File

@ -0,0 +1,49 @@
// Original work by VRocker https://github.com/VRocker/LogiLed2Corsair
// I'm mainly a C# developer, and these modification aren't a piece of art, but it suits our needs.
// The MIT License (MIT)
//
// Copyright (c) 2015 VRocker
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
LIBRARY LogiLed2Artemis.dll
EXPORTS
LogiLedInit
LogiLedGetSdkVersion
LogiLedSetTargetDevice
LogiLedSaveCurrentLighting
LogiLedSetLighting
LogiLedRestoreLighting
LogiLedFlashLighting
LogiLedPulseLighting
LogiLedStopEffects
LogiLedSetLightingFromBitmap
LogiLedSetLightingForKeyWithScanCode
LogiLedSetLightingForKeyWithHidCode
LogiLedSetLightingForKeyWithQuartzCode
LogiLedSetLightingForKeyWithKeyName
LogiLedSaveLightingForKey
LogiLedRestoreLightingForKey
LogiLedFlashSingleKey
LogiLedPulseSingleKey
LogiLedStopEffectsOnKey
LogiLedShutdown

View File

@ -0,0 +1,168 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>LogiLed2Artemis</RootNamespace>
<ProjectName>LogiLed2Artemis</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<LibraryPath>$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<TargetName>$(ProjectName)</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;LOGILEDCORSAIR_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ModuleDefinitionFile>LogiLed2Artemis.def</ModuleDefinitionFile>
<AdditionalDependencies>../CUESDK/lib/i386/CUESDK_2013.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;LOGILEDCORSAIR_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ModuleDefinitionFile>LogiLed2Artemis.def</ModuleDefinitionFile>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;LOGILEDCORSAIR_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<ModuleDefinitionFile>LogiLed2Artemis.def</ModuleDefinitionFile>
<AdditionalDependencies>../CUESDK/lib/i386/CUESDK_2013.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;LOGILEDCORSAIR_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<ModuleDefinitionFile>LogiLed2Artemis.def</ModuleDefinitionFile>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="Logger.h" />
<ClInclude Include="LogiLedDefs.h" />
<ClInclude Include="main.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="Logger.cpp" />
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
<None Include="LogiLed2Artemis.def" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="main.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="LogiLedDefs.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Logger.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Logger.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="LogiLed2Artemis.def">
<Filter>Source Files</Filter>
</None>
</ItemGroup>
</Project>

View File

@ -0,0 +1,135 @@
#pragma once
const int LOGITECH_LED_MOUSE = 0x0001;
const int LOGITECH_LED_KEYBOARD = 0x0002;
const int LOGITECH_LED_ALL = LOGITECH_LED_MOUSE | LOGITECH_LED_KEYBOARD;
#define LOGI_LED_BITMAP_WIDTH 21
#define LOGI_LED_BITMAP_HEIGHT 6
#define LOGI_LED_BITMAP_BYTES_PER_KEY 4
#define LOGI_LED_BITMAP_SIZE LOGI_LED_BITMAP_WIDTH*LOGI_LED_BITMAP_HEIGHT*LOGI_LED_BITMAP_BYTES_PER_KEY
#define LOGI_LED_DURATION_INFINITE 0
#define LOGI_DEVICETYPE_MONOCHROME_ORD 0
#define LOGI_DEVICETYPE_RGB_ORD 1
#define LOGI_DEVICETYPE_PERKEY_RGB_ORD 2
#define LOGI_DEVICETYPE_MONOCHROME (1 << LOGI_DEVICETYPE_MONOCHROME_ORD)
#define LOGI_DEVICETYPE_RGB (1 << LOGI_DEVICETYPE_RGB_ORD)
#define LOGI_DEVICETYPE_PERKEY_RGB (1 << LOGI_DEVICETYPE_PERKEY_RGB_ORD)
#define LOGI_DEVICETYPE_ALL (LOGI_DEVICETYPE_MONOCHROME | LOGI_DEVICETYPE_RGB | LOGI_DEVICETYPE_PERKEY_RGB)
namespace LogiLed
{
typedef enum
{
ESC = 0x01,
F1 = 0x3b,
F2 = 0x3c,
F3 = 0x3d,
F4 = 0x3e,
F5 = 0x3f,
F6 = 0x40,
F7 = 0x41,
F8 = 0x42,
F9 = 0x43,
F10 = 0x44,
F11 = 0x57,
F12 = 0x58,
PRINT_SCREEN = 0x137,
SCROLL_LOCK = 0x46,
PAUSE_BREAK = 0x145,
TILDE = 0x29,
ONE = 0x02,
TWO = 0x03,
THREE = 0x04,
FOUR = 0x05,
FIVE = 0x06,
SIX = 0x07,
SEVEN = 0x08,
EIGHT = 0x09,
NINE = 0x0A,
ZERO = 0x0B,
MINUS = 0x0C,
EQUALS = 0x0D,
BACKSPACE = 0x0E,
INSERT = 0x152,
HOME = 0x147,
PAGE_UP = 0x149,
NUM_LOCK = 0x45,
NUM_SLASH = 0x135,
NUM_ASTERISK = 0x37,
NUM_MINUS = 0x4A,
TAB = 0x0F,
Q = 0x10,
W = 0x11,
E = 0x12,
R = 0x13,
T = 0x14,
Y = 0x15,
U = 0x16,
I = 0x17,
O = 0x18,
P = 0x19,
OPEN_BRACKET = 0x1A,
CLOSE_BRACKET = 0x1B,
BACKSLASH = 0x2B,
KEYBOARD_DELETE = 0x153,
END = 0x14F,
PAGE_DOWN = 0x151,
NUM_SEVEN = 0x47,
NUM_EIGHT = 0x48,
NUM_NINE = 0x49,
NUM_PLUS = 0x4E,
CAPS_LOCK = 0x3A,
A = 0x1E,
S = 0x1F,
D = 0x20,
F = 0x21,
G = 0x22,
H = 0x23,
J = 0x24,
K = 0x25,
L = 0x26,
SEMICOLON = 0x27,
APOSTROPHE = 0x28,
ENTER = 0x1C,
NUM_FOUR = 0x4B,
NUM_FIVE = 0x4C,
NUM_SIX = 0x4D,
LEFT_SHIFT = 0x2A,
Z = 0x2C,
X = 0x2D,
C = 0x2E,
V = 0x2F,
B = 0x30,
N = 0x31,
M = 0x32,
COMMA = 0x33,
PERIOD = 0x34,
FORWARD_SLASH = 0x35,
RIGHT_SHIFT = 0x36,
ARROW_UP = 0x148,
NUM_ONE = 0x4F,
NUM_TWO = 0x50,
NUM_THREE = 0x51,
NUM_ENTER = 0x11C,
LEFT_CONTROL = 0x1D,
LEFT_WINDOWS = 0x15B,
LEFT_ALT = 0x38,
SPACE = 0x39,
RIGHT_ALT = 0x138,
RIGHT_WINDOWS = 0x15C,
APPLICATION_SELECT = 0x15D,
RIGHT_CONTROL = 0x11D,
ARROW_LEFT = 0x14B,
ARROW_DOWN = 0x150,
ARROW_RIGHT = 0x14D,
NUM_ZERO = 0x52,
NUM_PERIOD = 0x53,
} KeyName;
}

View File

@ -0,0 +1,254 @@
// Original work by VRocker https://github.com/VRocker/LogiLed2Corsair
// I'm mainly a C# developer, and these modification aren't a piece of art, but it suits our needs.
// The MIT License (MIT)
//
// Copyright (c) 2015 VRocker
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include "main.h"
#include <stdio.h>
#include <tchar.h>
#include <thread>
#include "LogiLedDefs.h"
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include "Logger.h"
#include <complex>
#include <filesystem>
static bool g_hasInitialised = false;
const char* game = "";
void cleanup()
{
CLogger::EndLogging();
}
BOOL WINAPI DllMain(HINSTANCE hInst, DWORD fdwReason, LPVOID)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
{
atexit(cleanup);
CLogger::InitLogging("Log.txt");
CLogger::SetLogLevel(LogLevel::None);
// Get the process that loaded the DLL
TCHAR divisionFind[] = _T("Division");
TCHAR gtaFind[] = _T("GTA");
TCHAR szPath[MAX_PATH];
GetModuleFileName(NULL, szPath, MAX_PATH);
if (_tcscmp(szPath, divisionFind) != 0)
game = "division";
else if (_tcscmp(szPath, gtaFind) != 0)
game = "gta";
CLogger::OutputLog("Attached to process.", LogLevel::Debug);
}
break;
case DLL_PROCESS_DETACH:
{
cleanup();
CLogger::OutputLog_s("Detached from process.", LogLevel::Debug);
}
break;
}
return true;
}
bool LogiLedInit()
{
CLogger::OutputLog_s("Logitech LED init called.", LogLevel::Debug);
g_hasInitialised = true;
return true;
}
bool LogiLedGetSdkVersion(int* majorNum, int* minorNum, int* buildNum)
{
CLogger::OutputLog("LogiLedGetSdkVersion called.", LogLevel::Debug);
// Mimic the SDK version
*majorNum = 8;
*minorNum = 81;
*buildNum = 15;
return true;
}
bool LogiLedSetTargetDevice(int targetDevice)
{
CLogger::OutputLog("LogiLedSetTargetDevice called (%i)", LogLevel::Debug, targetDevice);
// Logitech SDK says this function returns false if LogiLedInit hasn't been called
return g_hasInitialised;
}
bool LogiLedSaveCurrentLighting()
{
CLogger::OutputLog("LogiLedSaveCurrentLighting called (%i)", LogLevel::Debug);
return true;
}
void Transmit(const char* msg)
{
//Pipe Init Data
HANDLE hPipe1;
char buf[100];
LPTSTR lpszPipename1 = TEXT("\\\\.\\pipe\\artemis");
hPipe1 = CreateFile(lpszPipename1, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
if (hPipe1 == NULL || hPipe1 == INVALID_HANDLE_VALUE)
{
CLogger::OutputLog("Could not open the pipe - (error %i)", LogLevel::Debug, GetLastError());
return;
}
DWORD cbWritten;
WriteFile(hPipe1, msg, strlen(msg), &cbWritten, NULL);
CLogger::OutputLog_s("Transmitted to pipe", LogLevel::Debug);
}
bool LogiLedSetLighting(int redPercentage, int greenPercentage, int bluePercentage)
{
CLogger::OutputLog("LogiLedSetLighting called (%i %i %i)", LogLevel::Debug, redPercentage, greenPercentage, bluePercentage);
std::ostringstream os;
os << "0 0 " << redPercentage << " " << greenPercentage << " " << bluePercentage;
Transmit(os.str().c_str());
return true;
}
bool LogiLedRestoreLighting()
{
CLogger::OutputLog("LogiLedRestoreLighting called", LogLevel::Debug);
return true;
}
bool LogiLedFlashLighting(int redPercentage, int greenPercentage, int bluePercentage, int milliSecondsDuration, int milliSecondsInterval)
{
CLogger::OutputLog("LogiLedFlashLighting called (%i %i %i %i %i)", LogLevel::Debug, redPercentage, greenPercentage, bluePercentage, milliSecondsDuration, milliSecondsInterval);
return true;
}
bool LogiLedPulseLighting(int redPercentage, int greenPercentage, int bluePercentage, int milliSecondsDuration, int milliSecondsInterval)
{
CLogger::OutputLog("LogiLedPulseLighting called (%i %i %i %i %i)", LogLevel::Debug, redPercentage, greenPercentage, bluePercentage, milliSecondsDuration, milliSecondsInterval);
return true;
}
bool LogiLedStopEffects()
{
CLogger::OutputLog_s("LogiLedStopEffects called", LogLevel::Debug);
return true;
}
bool LogiLedSetLightingFromBitmap(unsigned char bitmap[])
{
CLogger::OutputLog_s("LogiLedSetLightingFromBitmap called", LogLevel::Debug);
return true;
}
bool LogiLedSetLightingForKeyWithScanCode(int keyCode, int redPercentage, int greenPercentage, int bluePercentage)
{
CLogger::OutputLog("LogiLedSetLightingForKeyWithScanCode called [Key: %i] (%i %i %i)", LogLevel::Debug, keyCode, redPercentage, greenPercentage, bluePercentage);
return true;
}
bool LogiLedSetLightingForKeyWithHidCode(int keyCode, int redPercentage, int greenPercentage, int bluePercentage)
{
CLogger::OutputLog("LogiLedSetLightingForKeyWithHidCode called [Key: %i] (%i %i %i)", LogLevel::Debug, keyCode, redPercentage, greenPercentage, bluePercentage);
return true;
}
bool LogiLedSetLightingForKeyWithQuartzCode(int keyCode, int redPercentage, int greenPercentage, int bluePercentage)
{
CLogger::OutputLog("LogiLedSetLightingForKeyWithQuartzCode called [Key: %i] (%i %i %i)", LogLevel::Debug, keyCode, redPercentage, greenPercentage, bluePercentage);
return true;
}
bool LogiLedSetLightingForKeyWithKeyName(LogiLed::KeyName keyName, int redPercentage, int greenPercentage, int bluePercentage)
{
CLogger::OutputLog("LogiLedSetLightingForKeyWithKeyName called [Key: %i] (%i %i %i)", LogLevel::Debug, keyName, redPercentage, greenPercentage, bluePercentage);
// Only transmit interesting keys. This can most likely be done prettier, but I'm no C++ dev.
if (game == "division" &&
(keyName == LogiLed::F1 ||
keyName == LogiLed::F2 ||
keyName == LogiLed::F3 ||
keyName == LogiLed::F4 ||
keyName == LogiLed::R ||
keyName == LogiLed::G ||
keyName == LogiLed::V)
)
{
std::ostringstream os;
os << "1 " << keyName << " " << redPercentage << " " << greenPercentage << " " << bluePercentage;
std::string s = os.str();
Transmit(os.str().c_str());
}
return true;
}
bool LogiLedSaveLightingForKey(LogiLed::KeyName keyName)
{
CLogger::OutputLog("LogiLedSaveLightingForKey called [Key: %i]", LogLevel::Debug, keyName);
return true;
}
bool LogiLedRestoreLightingForKey(LogiLed::KeyName keyName)
{
CLogger::OutputLog("LogiLedRestoreLightingForKey called [Key: %i]", LogLevel::Debug, keyName);
return true;
}
bool LogiLedFlashSingleKey(LogiLed::KeyName keyName, int redPercentage, int greenPercentage, int bluePercentage, int msDuration, int msInterval)
{
CLogger::OutputLog("LogiLedFlashSingleKey called [Key: %i] (%i %i %i %i %i)", LogLevel::Debug, keyName, redPercentage, greenPercentage, bluePercentage, msDuration, msInterval);
return true;
}
bool LogiLedPulseSingleKey(LogiLed::KeyName keyName, int startRedPercentage, int startGreenPercentage, int startBluePercentage, int finishRedPercentage, int finishGreenPercentage, int finishBluePercentage, int msDuration, bool isInfinite)
{
CLogger::OutputLog("LogiLedPulseSingleKey called [Key: %i] (%i %i %i %i %i %i %i %i)", LogLevel::Debug, keyName, startRedPercentage, startGreenPercentage, startBluePercentage, finishRedPercentage, finishGreenPercentage, finishBluePercentage, msDuration, isInfinite);
return true;
}
bool LogiLedStopEffectsOnKey(LogiLed::KeyName keyName)
{
CLogger::OutputLog("LogiLedStopEffectsOnKey called [Key: %i]", LogLevel::Debug, keyName);
return true;
}
void LogiLedShutdown()
{
CLogger::OutputLog_s("LogiLedShutdown called.", LogLevel::Debug);
g_hasInitialised = false;
}

View File

@ -0,0 +1,2 @@
#pragma once

View File

@ -2,17 +2,17 @@
[
{
"Game":"RocketLeague",
"GameVersion":"1.16",
"GameVersion":"1.15",
"GameAddresses":[
{
"Description":"Boost",
"BasePointer":{
"value":22411984
"value":22555396
},
"Offsets":[
1632,
64,
1636,
180,
260,
800,
1800,
540
]