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

Merge pull request #197 from SpoinkyNL/development

1.5.0.0
This commit is contained in:
Robert Beekman 2016-11-15 23:15:09 +01:00 committed by GitHub
commit 965cf4e56b
184 changed files with 6333 additions and 1708 deletions

View File

@ -7,10 +7,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Artemis", "Artemis\Artemis.
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Razer2Artemis", "Razer2Artemis\Razer2Artemis.vcxproj", "{39711909-C1D5-46CE-A9EA-2D561692EA47}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Razer2Artemis", "Razer2Artemis\Razer2Artemis.vcxproj", "{39711909-C1D5-46CE-A9EA-2D561692EA47}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnrealTournament2Artemis", "UnrealTournament2Artemis\UnrealTournament2Artemis.vcxproj", "{3541864F-1662-4BD6-8328-2C87AE61D152}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ColorBox", "ColorBox\ColorBox.csproj", "{40085232-ACED-4CBE-945B-90BA8153C151}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ColorBox", "ColorBox\ColorBox.csproj", "{40085232-ACED-4CBE-945B-90BA8153C151}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LogiLed2Artemis", "LogiLed2Artemis\LogiLed2Artemis.vcxproj", "{D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
CD_ROM|Any CPU = CD_ROM|Any CPU CD_ROM|Any CPU = CD_ROM|Any CPU
@ -88,34 +88,6 @@ Global
{39711909-C1D5-46CE-A9EA-2D561692EA47}.SingleImage|x64.Build.0 = Release|x64 {39711909-C1D5-46CE-A9EA-2D561692EA47}.SingleImage|x64.Build.0 = Release|x64
{39711909-C1D5-46CE-A9EA-2D561692EA47}.SingleImage|x86.ActiveCfg = Release|Win32 {39711909-C1D5-46CE-A9EA-2D561692EA47}.SingleImage|x86.ActiveCfg = Release|Win32
{39711909-C1D5-46CE-A9EA-2D561692EA47}.SingleImage|x86.Build.0 = Release|Win32 {39711909-C1D5-46CE-A9EA-2D561692EA47}.SingleImage|x86.Build.0 = Release|Win32
{3541864F-1662-4BD6-8328-2C87AE61D152}.CD_ROM|Any CPU.ActiveCfg = Release|x64
{3541864F-1662-4BD6-8328-2C87AE61D152}.CD_ROM|Any CPU.Build.0 = Release|x64
{3541864F-1662-4BD6-8328-2C87AE61D152}.CD_ROM|x64.ActiveCfg = Release|x64
{3541864F-1662-4BD6-8328-2C87AE61D152}.CD_ROM|x64.Build.0 = Release|x64
{3541864F-1662-4BD6-8328-2C87AE61D152}.CD_ROM|x86.ActiveCfg = Release|Win32
{3541864F-1662-4BD6-8328-2C87AE61D152}.CD_ROM|x86.Build.0 = Release|Win32
{3541864F-1662-4BD6-8328-2C87AE61D152}.Debug|Any CPU.ActiveCfg = Debug|Win32
{3541864F-1662-4BD6-8328-2C87AE61D152}.Debug|x64.ActiveCfg = Debug|x64
{3541864F-1662-4BD6-8328-2C87AE61D152}.Debug|x64.Build.0 = Debug|x64
{3541864F-1662-4BD6-8328-2C87AE61D152}.Debug|x86.ActiveCfg = Debug|Win32
{3541864F-1662-4BD6-8328-2C87AE61D152}.Debug|x86.Build.0 = Debug|Win32
{3541864F-1662-4BD6-8328-2C87AE61D152}.DVD-5|Any CPU.ActiveCfg = Release|x64
{3541864F-1662-4BD6-8328-2C87AE61D152}.DVD-5|Any CPU.Build.0 = Release|x64
{3541864F-1662-4BD6-8328-2C87AE61D152}.DVD-5|x64.ActiveCfg = Debug|x64
{3541864F-1662-4BD6-8328-2C87AE61D152}.DVD-5|x64.Build.0 = Debug|x64
{3541864F-1662-4BD6-8328-2C87AE61D152}.DVD-5|x86.ActiveCfg = Debug|Win32
{3541864F-1662-4BD6-8328-2C87AE61D152}.DVD-5|x86.Build.0 = Debug|Win32
{3541864F-1662-4BD6-8328-2C87AE61D152}.Release|Any CPU.ActiveCfg = Release|Win32
{3541864F-1662-4BD6-8328-2C87AE61D152}.Release|x64.ActiveCfg = Release|x64
{3541864F-1662-4BD6-8328-2C87AE61D152}.Release|x64.Build.0 = Release|x64
{3541864F-1662-4BD6-8328-2C87AE61D152}.Release|x86.ActiveCfg = Release|Win32
{3541864F-1662-4BD6-8328-2C87AE61D152}.Release|x86.Build.0 = Release|Win32
{3541864F-1662-4BD6-8328-2C87AE61D152}.SingleImage|Any CPU.ActiveCfg = Release|x64
{3541864F-1662-4BD6-8328-2C87AE61D152}.SingleImage|Any CPU.Build.0 = Release|x64
{3541864F-1662-4BD6-8328-2C87AE61D152}.SingleImage|x64.ActiveCfg = Release|x64
{3541864F-1662-4BD6-8328-2C87AE61D152}.SingleImage|x64.Build.0 = Release|x64
{3541864F-1662-4BD6-8328-2C87AE61D152}.SingleImage|x86.ActiveCfg = Release|Win32
{3541864F-1662-4BD6-8328-2C87AE61D152}.SingleImage|x86.Build.0 = Release|Win32
{40085232-ACED-4CBE-945B-90BA8153C151}.CD_ROM|Any CPU.ActiveCfg = Release|Any CPU {40085232-ACED-4CBE-945B-90BA8153C151}.CD_ROM|Any CPU.ActiveCfg = Release|Any CPU
{40085232-ACED-4CBE-945B-90BA8153C151}.CD_ROM|Any CPU.Build.0 = Release|Any CPU {40085232-ACED-4CBE-945B-90BA8153C151}.CD_ROM|Any CPU.Build.0 = Release|Any CPU
{40085232-ACED-4CBE-945B-90BA8153C151}.CD_ROM|x64.ActiveCfg = Release|Any CPU {40085232-ACED-4CBE-945B-90BA8153C151}.CD_ROM|x64.ActiveCfg = Release|Any CPU
@ -146,6 +118,34 @@ Global
{40085232-ACED-4CBE-945B-90BA8153C151}.SingleImage|x64.Build.0 = Release|Any CPU {40085232-ACED-4CBE-945B-90BA8153C151}.SingleImage|x64.Build.0 = Release|Any CPU
{40085232-ACED-4CBE-945B-90BA8153C151}.SingleImage|x86.ActiveCfg = Release|Any CPU {40085232-ACED-4CBE-945B-90BA8153C151}.SingleImage|x86.ActiveCfg = Release|Any CPU
{40085232-ACED-4CBE-945B-90BA8153C151}.SingleImage|x86.Build.0 = Release|Any CPU {40085232-ACED-4CBE-945B-90BA8153C151}.SingleImage|x86.Build.0 = Release|Any CPU
{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 EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@ -21,6 +21,7 @@
Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseDark.xaml" /> Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseDark.xaml" />
<ResourceDictionary Source="/Resources/Icons.xaml" /> <ResourceDictionary Source="/Resources/Icons.xaml" />
<ResourceDictionary Source="Styles/ColorBox.xaml" /> <ResourceDictionary Source="Styles/ColorBox.xaml" />
<ResourceDictionary Source="Styles/MarkdownStyles.xaml" />
</ResourceDictionary.MergedDictionaries> </ResourceDictionary.MergedDictionaries>
<converters:MilliSecondTimespanConverter x:Key="MilliSecondTimespanConverter" /> <converters:MilliSecondTimespanConverter x:Key="MilliSecondTimespanConverter" />
</ResourceDictionary> </ResourceDictionary>

View File

@ -167,8 +167,8 @@
<HintPath>..\packages\DynamicExpresso.Core.1.3.3.4\lib\net40\DynamicExpresso.Core.dll</HintPath> <HintPath>..\packages\DynamicExpresso.Core.1.3.3.4\lib\net40\DynamicExpresso.Core.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="GongSolutions.Wpf.DragDrop, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="GongSolutions.Wpf.DragDrop, Version=0.1.4.3, Culture=neutral, PublicKeyToken=d19974ea350ccea1, processorArchitecture=MSIL">
<HintPath>..\packages\gong-wpf-dragdrop.1.0.0\lib\net46\GongSolutions.Wpf.DragDrop.dll</HintPath> <HintPath>..\packages\gong-wpf-dragdrop.0.1.4.3\lib\net40\GongSolutions.Wpf.DragDrop.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="Hardcodet.Wpf.TaskbarNotification, Version=1.0.5.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="Hardcodet.Wpf.TaskbarNotification, Version=1.0.5.0, Culture=neutral, processorArchitecture=MSIL">
@ -206,6 +206,10 @@
<HintPath>..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.Rocks.dll</HintPath> <HintPath>..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.Rocks.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="MoonSharp.Interpreter, Version=2.0.0.0, Culture=neutral, PublicKeyToken=921e73ce94aa17f8, processorArchitecture=MSIL">
<HintPath>..\packages\MoonSharp.2.0.0.0\lib\net40-client\MoonSharp.Interpreter.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="NAudio, Version=1.7.3.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="NAudio, Version=1.7.3.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\NAudio.1.7.3\lib\net35\NAudio.dll</HintPath> <HintPath>..\packages\NAudio.1.7.3\lib\net35\NAudio.dll</HintPath>
<Private>True</Private> <Private>True</Private>
@ -222,10 +226,6 @@
<HintPath>..\packages\Ninject.Extensions.Conventions.3.2.0.0\lib\net45-full\Ninject.Extensions.Conventions.dll</HintPath> <HintPath>..\packages\Ninject.Extensions.Conventions.3.2.0.0\lib\net45-full\Ninject.Extensions.Conventions.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="Ninject.Extensions.Factory, Version=3.2.0.0, Culture=neutral, PublicKeyToken=c7192dc5380945e7, processorArchitecture=MSIL">
<HintPath>..\packages\Ninject.Extensions.Factory.3.2.1.0\lib\net45-full\Ninject.Extensions.Factory.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Ninject.Extensions.Logging, Version=3.2.0.0, Culture=neutral, PublicKeyToken=c7192dc5380945e7, processorArchitecture=MSIL"> <Reference Include="Ninject.Extensions.Logging, Version=3.2.0.0, Culture=neutral, PublicKeyToken=c7192dc5380945e7, processorArchitecture=MSIL">
<HintPath>..\packages\Ninject.Extensions.Logging.3.2.3.0\lib\net45-full\Ninject.Extensions.Logging.dll</HintPath> <HintPath>..\packages\Ninject.Extensions.Logging.3.2.3.0\lib\net45-full\Ninject.Extensions.Logging.dll</HintPath>
<Private>True</Private> <Private>True</Private>
@ -235,7 +235,7 @@
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL"> <Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<HintPath>..\packages\NLog.4.3.9\lib\net45\NLog.dll</HintPath> <HintPath>..\packages\NLog.4.3.10\lib\net45\NLog.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="NuGet.Squirrel, Version=3.0.0.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="NuGet.Squirrel, Version=3.0.0.0, Culture=neutral, processorArchitecture=MSIL">
@ -246,6 +246,14 @@
<HintPath>..\packages\Process.NET.1.0.5\lib\Process.NET.dll</HintPath> <HintPath>..\packages\Process.NET.1.0.5\lib\Process.NET.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="SharpDX, Version=3.1.1.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
<HintPath>..\packages\SharpDX.3.1.1\lib\net45\SharpDX.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="SharpDX.Direct3D9, Version=3.1.1.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
<HintPath>..\packages\SharpDX.Direct3D9.3.1.1\lib\net45\SharpDX.Direct3D9.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Splat, Version=1.6.2.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="Splat, Version=1.6.2.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Splat.1.6.2\lib\Net45\Splat.dll</HintPath> <HintPath>..\packages\Splat.1.6.2\lib\Net45\Splat.dll</HintPath>
<Private>True</Private> <Private>True</Private>
@ -303,8 +311,14 @@
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>
<Compile Include="ArtemisBootstrapper.cs" /> <Compile Include="ArtemisBootstrapper.cs" />
<Compile Include="Controls\Log\LoggingControl.xaml.cs">
<DependentUpon>LoggingControl.xaml</DependentUpon>
</Compile>
<Compile Include="Controls\Log\MemoryEventTarget.cs" />
<Compile Include="DAL\ProfileProvider.cs" /> <Compile Include="DAL\ProfileProvider.cs" />
<Compile Include="DAL\SettingsProvider.cs" /> <Compile Include="DAL\SettingsProvider.cs" />
<Compile Include="DeviceProviders\CoolerMaster\MasterkeysProL.cs" />
<Compile Include="DeviceProviders\CoolerMaster\Utilities\CmSdk.cs" />
<Compile Include="DeviceProviders\Corsair\CorsairMice.cs" /> <Compile Include="DeviceProviders\Corsair\CorsairMice.cs" />
<Compile Include="DeviceProviders\Corsair\CorsairHeadsets.cs" /> <Compile Include="DeviceProviders\Corsair\CorsairHeadsets.cs" />
<Compile Include="DeviceProviders\Corsair\CorsairMousemats.cs" /> <Compile Include="DeviceProviders\Corsair\CorsairMousemats.cs" />
@ -313,13 +327,14 @@
<Compile Include="DeviceProviders\Logitech\G810.cs" /> <Compile Include="DeviceProviders\Logitech\G810.cs" />
<Compile Include="DeviceProviders\Logitech\LogitechGeneric.cs" /> <Compile Include="DeviceProviders\Logitech\LogitechGeneric.cs" />
<Compile Include="DeviceProviders\Logitech\LogitechKeyboard.cs" /> <Compile Include="DeviceProviders\Logitech\LogitechKeyboard.cs" />
<Compile Include="Dialogs\MarkdownDialog.xaml.cs">
<DependentUpon>MarkdownDialog.xaml</DependentUpon>
</Compile>
<Compile Include="Events\EffectChangedEventArgs.cs" /> <Compile Include="Events\EffectChangedEventArgs.cs" />
<Compile Include="Events\EnabledChangedEventArgs.cs" /> <Compile Include="Events\EnabledChangedEventArgs.cs" />
<Compile Include="Events\KeyboardChangedEventArgs.cs" /> <Compile Include="Events\KeyboardChangedEventArgs.cs" />
<Compile Include="Events\RazerColorArrayChanged.cs" /> <Compile Include="Events\RazerColorArrayChanged.cs" />
<Compile Include="Events\RazerColorsChangedEventArgs.cs" /> <Compile Include="Events\RazerColorsChangedEventArgs.cs" />
<Compile Include="InjectionFactories\ILayerEditorVmFactory.cs" />
<Compile Include="InjectionFactories\IProfileEditorVmFactory.cs" />
<Compile Include="InjectionModules\DeviceModules.cs" /> <Compile Include="InjectionModules\DeviceModules.cs" />
<Compile Include="InjectionModules\EffectModules.cs" /> <Compile Include="InjectionModules\EffectModules.cs" />
<Compile Include="InjectionModules\ProfileModules.cs" /> <Compile Include="InjectionModules\ProfileModules.cs" />
@ -354,6 +369,13 @@
<DependentUpon>EurotruckSimulator2View.xaml</DependentUpon> <DependentUpon>EurotruckSimulator2View.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Modules\Games\EurotruckSimulator2\EurotruckSimulator2ViewModel.cs" /> <Compile Include="Modules\Games\EurotruckSimulator2\EurotruckSimulator2ViewModel.cs" />
<Compile Include="Modules\Games\GtaV\GtaVDataModel.cs" />
<Compile Include="Modules\Games\GtaV\GtaVModel.cs" />
<Compile Include="Modules\Games\GtaV\GtaVSettings.cs" />
<Compile Include="Modules\Games\GtaV\GtaVView.xaml.cs">
<DependentUpon>GtaVView.xaml</DependentUpon>
</Compile>
<Compile Include="Modules\Games\GtaV\GtaVViewModel.cs" />
<Compile Include="Modules\Games\UnrealTournament\UnrealTournamentDataModel.cs" /> <Compile Include="Modules\Games\UnrealTournament\UnrealTournamentDataModel.cs" />
<Compile Include="Modules\Games\UnrealTournament\UnrealTournamentModel.cs" /> <Compile Include="Modules\Games\UnrealTournament\UnrealTournamentModel.cs" />
<Compile Include="Modules\Games\UnrealTournament\UnrealTournamentSettings.cs" /> <Compile Include="Modules\Games\UnrealTournament\UnrealTournamentSettings.cs" />
@ -381,6 +403,28 @@
<Compile Include="Profiles\Layers\Animations\NoneAnimation.cs" /> <Compile Include="Profiles\Layers\Animations\NoneAnimation.cs" />
<Compile Include="Profiles\Layers\Models\EventPropertiesModel.cs" /> <Compile Include="Profiles\Layers\Models\EventPropertiesModel.cs" />
<Compile Include="Profiles\Layers\Models\KeyboardEventPropertiesModel.cs" /> <Compile Include="Profiles\Layers\Models\KeyboardEventPropertiesModel.cs" />
<Compile Include="Profiles\Layers\Types\AmbientLight\AmbienceCreator\AmbienceCreatorExtend.cs" />
<Compile Include="Profiles\Layers\Types\AmbientLight\AmbienceCreator\AmbienceCreatorMirror.cs" />
<Compile Include="Profiles\Layers\Types\AmbientLight\AmbienceCreator\AvgColor.cs" />
<Compile Include="Profiles\Layers\Types\AmbientLight\AmbienceCreator\IAmbienceCreator.cs" />
<Compile Include="Profiles\Layers\Types\AmbientLight\AmbientLightPropertiesModel.cs" />
<Compile Include="Profiles\Layers\Types\AmbientLight\AmbientLightPropertiesView.xaml.cs">
<DependentUpon>AmbientLightPropertiesView.xaml</DependentUpon>
</Compile>
<Compile Include="Profiles\Layers\Types\AmbientLight\AmbientLightPropertiesViewModel.cs" />
<Compile Include="Profiles\Layers\Types\AmbientLight\AmbientLightType.cs" />
<Compile Include="Profiles\Layers\Types\AmbientLight\Helper\CheckboxEnumFlagHelper.cs" />
<Compile Include="Profiles\Layers\Types\AmbientLight\Model\AmbienceCreatorType.cs" />
<Compile Include="Profiles\Layers\Types\AmbientLight\Model\BlackBarDetectionMode.cs" />
<Compile Include="Profiles\Layers\Types\AmbientLight\Model\Extensions\AvgColorExtension.cs" />
<Compile Include="Profiles\Layers\Types\AmbientLight\Model\Extensions\EnumExtension.cs" />
<Compile Include="Profiles\Layers\Types\AmbientLight\Model\Extensions\PixelDataExtension.cs" />
<Compile Include="Profiles\Layers\Types\AmbientLight\Model\FlipMode.cs" />
<Compile Include="Profiles\Layers\Types\AmbientLight\Model\ScreenCaptureMode.cs" />
<Compile Include="Profiles\Layers\Types\AmbientLight\Model\SmoothMode.cs" />
<Compile Include="Profiles\Layers\Types\AmbientLight\ScreenCapturing\DX9ScreenCapture.cs" />
<Compile Include="Profiles\Layers\Types\AmbientLight\ScreenCapturing\IScreenCapture.cs" />
<Compile Include="Profiles\Layers\Types\AmbientLight\ScreenCapturing\ScreenCaptureManager.cs" />
<Compile Include="Profiles\Layers\Types\Audio\AudioPropertiesModel.cs" /> <Compile Include="Profiles\Layers\Types\Audio\AudioPropertiesModel.cs" />
<Compile Include="Profiles\Layers\Types\Audio\AudioPropertiesView.xaml.cs"> <Compile Include="Profiles\Layers\Types\Audio\AudioPropertiesView.xaml.cs">
<DependentUpon>AudioPropertiesView.xaml</DependentUpon> <DependentUpon>AudioPropertiesView.xaml</DependentUpon>
@ -403,6 +447,22 @@
</Compile> </Compile>
<Compile Include="Profiles\Layers\Types\Mousemat\MousematPropertiesViewModel.cs" /> <Compile Include="Profiles\Layers\Types\Mousemat\MousematPropertiesViewModel.cs" />
<Compile Include="Profiles\Layers\Types\Mousemat\MousematType.cs" /> <Compile Include="Profiles\Layers\Types\Mousemat\MousematType.cs" />
<Compile Include="Profiles\LuaMouseWrapper.cs" />
<Compile Include="Profiles\Lua\Brushes\LuaBrush.cs" />
<Compile Include="Profiles\Lua\Brushes\LuaColor.cs" />
<Compile Include="Profiles\Lua\Brushes\LuaLinearGradientBrush.cs" />
<Compile Include="Profiles\Lua\Brushes\LuaRadialGradientBrush.cs" />
<Compile Include="Profiles\Lua\Events\LuaKeyPressEventArgs.cs" />
<Compile Include="Profiles\Lua\Events\LuaDeviceDrawingEventArgs.cs" />
<Compile Include="Profiles\Lua\Events\LuaDeviceUpdatingEventArgs.cs" />
<Compile Include="Profiles\Lua\Brushes\LuaBrushWrapper.cs" />
<Compile Include="Profiles\Lua\LuaDrawWrapper.cs" />
<Compile Include="Profiles\Lua\Events\LuaEventsWrapper.cs" />
<Compile Include="Profiles\Lua\LuaKeyboardWrapper.cs" />
<Compile Include="Profiles\Lua\LuaLayerWrapper.cs" />
<Compile Include="Profiles\Lua\LuaProfileWrapper.cs" />
<Compile Include="Profiles\Lua\Brushes\LuaSolidColorBrush.cs" />
<Compile Include="Profiles\Lua\LuaWrapper.cs" />
<Compile Include="Profiles\ProfileModel.cs" /> <Compile Include="Profiles\ProfileModel.cs" />
<Compile Include="Profiles\Layers\Models\SimplePropertiesModel.cs" /> <Compile Include="Profiles\Layers\Models\SimplePropertiesModel.cs" />
<Compile Include="Profiles\Layers\Types\Keyboard\KeyboardPropertiesModel.cs" /> <Compile Include="Profiles\Layers\Types\Keyboard\KeyboardPropertiesModel.cs" />
@ -489,6 +549,7 @@
</Compile> </Compile>
<Compile Include="Services\DialogService.cs" /> <Compile Include="Services\DialogService.cs" />
<Compile Include="Services\MetroDialogService.cs" /> <Compile Include="Services\MetroDialogService.cs" />
<Compile Include="Services\WindowService.cs" />
<Compile Include="Settings\EffectSettings.cs" /> <Compile Include="Settings\EffectSettings.cs" />
<Compile Include="Settings\GameSettings.cs" /> <Compile Include="Settings\GameSettings.cs" />
<Compile Include="Settings\GeneralSettings.cs" /> <Compile Include="Settings\GeneralSettings.cs" />
@ -511,6 +572,8 @@
<Compile Include="Utilities\Keyboard\KeyboardHook.cs" /> <Compile Include="Utilities\Keyboard\KeyboardHook.cs" />
<Compile Include="Utilities\Logging.cs" /> <Compile Include="Utilities\Logging.cs" />
<Compile Include="Utilities\DataReaders\PipeServer.cs" /> <Compile Include="Utilities\DataReaders\PipeServer.cs" />
<Compile Include="Utilities\Markdown\Markdown.cs" />
<Compile Include="Utilities\Markdown\TextToFlowDocumentConverter.cs" />
<Compile Include="Utilities\Memory\GamePointer.cs" /> <Compile Include="Utilities\Memory\GamePointer.cs" />
<Compile Include="Utilities\Keyboard\KeyboardRectangle.cs" /> <Compile Include="Utilities\Keyboard\KeyboardRectangle.cs" />
<Compile Include="Utilities\Memory\Memory.cs" /> <Compile Include="Utilities\Memory\Memory.cs" />
@ -548,7 +611,6 @@
<Compile Include="Modules\Overlays\VolumeDisplay\VolumeDisplayViewModel.cs" /> <Compile Include="Modules\Overlays\VolumeDisplay\VolumeDisplayViewModel.cs" />
<Compile Include="ViewModels\Profiles\ProfileEditorViewModel.cs" /> <Compile Include="ViewModels\Profiles\ProfileEditorViewModel.cs" />
<Compile Include="ViewModels\ShellViewModel.cs" /> <Compile Include="ViewModels\ShellViewModel.cs" />
<Compile Include="ViewModels\SystemTrayViewModel.cs" />
<Compile Include="ViewModels\WelcomeViewModel.cs" /> <Compile Include="ViewModels\WelcomeViewModel.cs" />
<Compile Include="Views\DebugView.xaml.cs"> <Compile Include="Views\DebugView.xaml.cs">
<DependentUpon>DebugView.xaml</DependentUpon> <DependentUpon>DebugView.xaml</DependentUpon>
@ -624,6 +686,9 @@
<Compile Include="Properties\AssemblyInfo.cs"> <Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>
<None Include="Resources\Keyboards\masterkeys-pro-l.png" />
<Resource Include="Resources\Kottke Silkscreen License.txt" />
<None Include="Resources\lua-placeholder.lua" />
<None Include="NLog.xsd"> <None Include="NLog.xsd">
<SubType>Designer</SubType> <SubType>Designer</SubType>
</None> </None>
@ -649,9 +714,13 @@
<SubType>Designer</SubType> <SubType>Designer</SubType>
</None> </None>
<AppDesigner Include="Properties\" /> <AppDesigner Include="Properties\" />
<Resource Include="Resources\slkscr.ttf" />
<Resource Include="Resources\bow.png" /> <Resource Include="Resources\bow.png" />
<Content Include="lib\CUE.NET.dll" /> <Content Include="lib\CUE.NET.dll" />
<Content Include="lib\Ets2SdkClient.dll" /> <Content Include="lib\Ets2SdkClient.dll" />
<Content Include="lib\SDKDLL.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="LogitechLedEnginesWrapper.dll"> <Content Include="LogitechLedEnginesWrapper.dll">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content> </Content>
@ -686,6 +755,14 @@
</None> </None>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Page Include="Controls\Log\LoggingControl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Dialogs\MarkdownDialog.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Modules\Effects\Bubbles\BubblesView.xaml"> <Page Include="Modules\Effects\Bubbles\BubblesView.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
@ -698,6 +775,10 @@
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Page> </Page>
<Page Include="Modules\Games\GtaV\GtaVView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Modules\Games\Overwatch\OverwatchView.xaml"> <Page Include="Modules\Games\Overwatch\OverwatchView.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
@ -714,6 +795,10 @@
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Page> </Page>
<Page Include="Profiles\Layers\Types\AmbientLight\AmbientLightPropertiesView.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Profiles\Layers\Types\Audio\AudioPropertiesView.xaml"> <Page Include="Profiles\Layers\Types\Audio\AudioPropertiesView.xaml">
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>
@ -746,6 +831,10 @@
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
</Page> </Page>
<Page Include="Styles\MarkdownStyles.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\DebugView.xaml"> <Page Include="Views\DebugView.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
@ -844,6 +933,7 @@
<None Include="Modules\Games\EurotruckSimulator2\Resources\Win32\ets2-telemetry-server.dll" /> <None Include="Modules\Games\EurotruckSimulator2\Resources\Win32\ets2-telemetry-server.dll" />
<None Include="Modules\Games\EurotruckSimulator2\Resources\Win64\ets2-telemetry-server.dll" /> <None Include="Modules\Games\EurotruckSimulator2\Resources\Win64\ets2-telemetry-server.dll" />
<None Include="Resources\audio.png" /> <None Include="Resources\audio.png" />
<None Include="Resources\ambilight.png" />
<Content Include="Resources\CounterStrike\csgoGamestateConfiguration.txt" /> <Content Include="Resources\CounterStrike\csgoGamestateConfiguration.txt" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -864,6 +954,9 @@
<Name>ColorBox</Name> <Name>ColorBox</Name>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup>
<Folder Include="Resources\Lua\" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\packages\CUE.NET.1.1.0.2\build\net45\CUE.NET.targets" Condition="Exists('..\packages\CUE.NET.1.1.0.2\build\net45\CUE.NET.targets')" /> <Import Project="..\packages\CUE.NET.1.1.0.2\build\net45\CUE.NET.targets" Condition="Exists('..\packages\CUE.NET.1.1.0.2\build\net45\CUE.NET.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">

View File

@ -10,6 +10,7 @@ using Artemis.Utilities;
using Artemis.Utilities.Converters; using Artemis.Utilities.Converters;
using Artemis.ViewModels; using Artemis.ViewModels;
using Caliburn.Micro; using Caliburn.Micro;
using MoonSharp.Interpreter;
using Newtonsoft.Json; using Newtonsoft.Json;
using Ninject; using Ninject;
@ -80,6 +81,7 @@ namespace Artemis
_kernel.Bind<IWindowManager>().To<WindowManager>().InSingletonScope(); _kernel.Bind<IWindowManager>().To<WindowManager>().InSingletonScope();
_kernel.Bind<IEventAggregator>().To<EventAggregator>().InSingletonScope(); _kernel.Bind<IEventAggregator>().To<EventAggregator>().InSingletonScope();
// Configure JSON.NET
var settings = new JsonSerializerSettings var settings = new JsonSerializerSettings
{ {
TypeNameHandling = TypeNameHandling.Auto, TypeNameHandling = TypeNameHandling.Auto,
@ -114,7 +116,7 @@ namespace Artemis
protected override void OnStartup(object sender, StartupEventArgs e) protected override void OnStartup(object sender, StartupEventArgs e)
{ {
DisplayRootViewFor<SystemTrayViewModel>(); DisplayRootViewFor<ShellViewModel>();
} }
} }
} }

View File

@ -0,0 +1,27 @@
<UserControl x:Class="Artemis.Controls.Log.LoggingControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid>
<!--<TextBox IsReadOnly="True" AcceptsReturn="True" Height="Auto" HorizontalAlignment="Stretch" Name="dgLog" VerticalAlignment="Stretch" Width="Auto"/>-->
<ListView ItemsSource="{Binding LogCollection}" Name="logView">
<ListView.View>
<GridView>
<GridView.Columns>
<!--<GridViewColumn DisplayMemberBinding="{Binding LoggerName}" Header="Logger"/>-->
<GridViewColumn DisplayMemberBinding="{Binding Level}" Header="Level" />
<GridViewColumn DisplayMemberBinding="{Binding TimeStamp, StringFormat=HH:mm:ss.ffffff}" Header="Time" />
<GridViewColumn DisplayMemberBinding="{Binding FormattedMessage}" Width="500" Header="Message" />
<GridViewColumn DisplayMemberBinding="{Binding Exception.Message}" Width="300" Header="Exception" />
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
<!--<ListBox Height="Auto" HorizontalAlignment="Stretch" Name="dgLog" VerticalAlignment="Stretch" Width="Auto" />-->
</Grid>
</UserControl>

View File

@ -0,0 +1,37 @@
using System.Collections.ObjectModel;
using System.Windows.Controls;
using Artemis.Utilities;
using NLog;
namespace Artemis.Controls.Log
{
/// <summary>
/// Interaction logic for LoggingControl.xaml
/// </summary>
public partial class LoggingControl : UserControl
{
public LoggingControl()
{
LogCollection = new ObservableCollection<LogEventInfo>();
InitializeComponent();
// init memory queue
Logging.ClearLoggingEvent();
Logging.MemoryEvent += EventReceived;
}
public static ObservableCollection<LogEventInfo> LogCollection { get; set; }
private async void EventReceived(LogEventInfo message)
{
await Dispatcher.InvokeAsync(() =>
{
if (LogCollection.Count >= 50)
LogCollection.RemoveAt(0);
LogCollection.Add(message);
});
}
}
}

View File

@ -0,0 +1,20 @@
using System;
using NLog;
using NLog.Targets;
namespace Artemis.Controls.Log
{
public class MemoryEventTarget : Target
{
public event Action<LogEventInfo> EventReceived;
/// <summary>
/// Notifies listeners about new event
/// </summary>
/// <param name="logEvent">The logging event.</param>
protected override void Write(LogEventInfo logEvent)
{
EventReceived?.Invoke(logEvent);
}
}
}

View File

@ -11,6 +11,7 @@ using Artemis.Profiles;
using Artemis.Profiles.Layers.Types.Keyboard; using Artemis.Profiles.Layers.Types.Keyboard;
using Artemis.Properties; using Artemis.Properties;
using Artemis.Utilities; using Artemis.Utilities;
using MoonSharp.Interpreter;
using Newtonsoft.Json; using Newtonsoft.Json;
using NLog; using NLog;
@ -23,40 +24,34 @@ namespace Artemis.DAL
private static readonly string ProfileFolder = private static readonly string ProfileFolder =
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\Artemis\profiles"; Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\Artemis\profiles";
private static readonly List<ProfileModel> Profiles = new List<ProfileModel>();
private static bool _installedDefaults; private static bool _installedDefaults;
/// <summary> static ProfileProvider()
/// Get all profiles
/// </summary>
/// <returns>All profiles</returns>
public static List<ProfileModel> GetAll()
{ {
lock (Profiles) // Configure MoonSharp
{ UserData.RegisterAssembly();
if (!Profiles.Any()) CheckProfiles();
ReadProfiles(); InstallDefaults();
// Return a new list, this'll make sure removing/updating the retrieved list doesn't
// affect the datastore
return Profiles.ToList();
}
} }
/// <summary> public static List<string> GetProfileNames(KeyboardProvider keyboard, EffectModel effect)
/// Get all profiles matching the provided game
/// </summary>
/// <param name="game">The game to match</param>
/// <param name="keyboard">The keyboard to match</param>
/// <returns>All profiles matching the provided game</returns>
public static List<ProfileModel> GetAll(EffectModel game, KeyboardProvider keyboard)
{ {
if (game == null) if (keyboard == null || effect == null)
throw new ArgumentNullException(nameof(game)); return null;
if (keyboard == null) return ReadProfiles(keyboard.Slug + "/" + effect.Name).Select(p => p.Name).ToList();
throw new ArgumentNullException(nameof(keyboard)); }
return GetAll().Where(g => g.GameName.Equals(game.Name) && g.KeyboardSlug.Equals(keyboard.Slug)).ToList(); public static ProfileModel GetProfile(KeyboardProvider keyboard, EffectModel effect, string name)
{
if (keyboard == null || effect == null)
return null;
return ReadProfiles(keyboard.Slug + "/" + effect.Name).FirstOrDefault(p => p.Name == name);
}
public static bool IsProfileUnique(ProfileModel profileModel)
{
var existing = ReadProfiles(profileModel.KeyboardSlug + "/" + profileModel.GameName);
return !existing.Contains(profileModel);
} }
/// <summary> /// <summary>
@ -69,12 +64,6 @@ namespace Artemis.DAL
if (prof == null) if (prof == null)
throw new ArgumentNullException(nameof(prof)); throw new ArgumentNullException(nameof(prof));
lock (Profiles)
{
if (!Profiles.Contains(prof))
Profiles.Add(prof);
}
lock (prof) lock (prof)
{ {
// Store the file // Store the file
@ -100,103 +89,34 @@ namespace Artemis.DAL
} }
File.WriteAllText(path + $@"\{prof.Name}.json", json); File.WriteAllText(path + $@"\{prof.Name}.json", json);
} Logger.Debug("Saved profile {0}/{1}/{2}", prof.KeyboardSlug, prof.GameName, prof.Name);
}
private static void ReadProfiles()
{
CheckProfiles();
InstallDefaults();
lock (Profiles)
{
Profiles.Clear();
// Create the directory structure
var profilePaths = Directory.GetFiles(ProfileFolder, "*.json", SearchOption.AllDirectories);
// Parse the JSON files into objects and add them if they are valid
foreach (var path in profilePaths)
{
try
{
var prof = LoadProfileIfValid(path);
if (prof == null)
continue;
// Only add unique profiles
if (Profiles.Any(p => p.GameName == prof.GameName && p.Name == prof.Name &&
p.KeyboardSlug == prof.KeyboardSlug))
{
Logger.Error("Didn't load duplicate profile: {0}", path);
}
else
{
Profiles.Add(prof);
}
}
catch (Exception e)
{
Logger.Error("Failed to load profile: {0} - {1}", path, e.InnerException.Message);
}
}
} }
} }
/// <summary> /// <summary>
/// Unpacks the default profiles into the profile directory /// Renames the profile on the model and filesystem
/// </summary> /// </summary>
private static void InstallDefaults() /// <param name="profile">The profile to rename</param>
/// <param name="name">The new name</param>
public static void RenameProfile(ProfileModel profile, string name)
{ {
// Only install the defaults once per session if (string.IsNullOrEmpty(name))
if (_installedDefaults)
return; return;
_installedDefaults = true;
// Load the ZIP from resources // Remove the old profile
var stream = Assembly.GetExecutingAssembly() DeleteProfile(profile);
.GetManifestResourceStream("Artemis.Resources.Keyboards.default-profiles.zip");
// Extract it over the old defaults in case one was updated // Update the profile, creating a new file
if (stream == null) profile.Name = name;
return; AddOrUpdate(profile);
var archive = new ZipArchive(stream);
archive.ExtractToDirectory(ProfileFolder, true);
var demoProfiles = Profiles.Where(d => d.Name == "Demo (duplicate to keep changes)");
InsertGif(demoProfiles, "GIF", Resources.demo_gif, "demo-gif");
} }
public static void InsertGif(IEnumerable<ProfileModel> profileModels, string layerName, Bitmap gifFile, public static void DeleteProfile(ProfileModel prof)
string fileName)
{ {
// Extract the GIF file // Remove the file
var gifDir = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\Artemis\gifs"; var path = ProfileFolder + $@"\{prof.KeyboardSlug}\{prof.GameName}\{prof.Name}.json";
Directory.CreateDirectory(gifDir); if (File.Exists(path))
var gifPath = gifDir + $"\\{fileName}.gif"; File.Delete(path);
gifFile.Save(gifPath);
foreach (var profile in profileModels)
{
var gifLayer = profile.GetLayers().FirstOrDefault(l => l.Name == layerName);
if (gifLayer == null)
continue;
((KeyboardPropertiesModel) gifLayer.Properties).GifFile = gifPath;
AddOrUpdate(profile);
}
}
/// <summary>
/// Makes sure the profile directory structure is in order and places default profiles
/// </summary>
private static void CheckProfiles()
{
// Create the directory structure
if (Directory.Exists(ProfileFolder))
return;
Directory.CreateDirectory(ProfileFolder);
} }
/// <summary> /// <summary>
@ -222,7 +142,7 @@ namespace Artemis.DAL
} }
/// <summary> /// <summary>
/// Exports the given profile to the provided path in XML /// Exports the given profile to the provided path in JSON
/// </summary> /// </summary>
/// <param name="prof">The profile to export</param> /// <param name="prof">The profile to export</param>
/// <param name="path">The path to save the profile to</param> /// <param name="path">The path to save the profile to</param>
@ -232,41 +152,102 @@ namespace Artemis.DAL
File.WriteAllText(path, json); File.WriteAllText(path, json);
} }
/// <summary> public static void InsertGif(string effectName, string profileName, string layerName, Bitmap gifFile, string fileName)
/// Renames the profile on the model and filesystem
/// </summary>
/// <param name="profile">The profile to rename</param>
/// <param name="name">The new name</param>
public static void RenameProfile(ProfileModel profile, string name)
{ {
if (string.IsNullOrEmpty(name)) var directories = new DirectoryInfo(ProfileFolder).GetDirectories();
return; var profiles = new List<ProfileModel>();
foreach (var directoryInfo in directories)
profiles.AddRange(ReadProfiles(directoryInfo.Name + "/effectName").Where(d => d.Name == profileName));
// Extract the GIF file
var gifDir = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\Artemis\gifs";
Directory.CreateDirectory(gifDir);
var gifPath = gifDir + $"\\{fileName}.gif";
gifFile.Save(gifPath);
// Remove the old profile foreach (var profile in profiles)
DeleteProfile(profile); {
var gifLayer = profile.GetLayers().FirstOrDefault(l => l.Name == layerName);
if (gifLayer == null)
continue;
// Update the profile, creating a new file ((KeyboardPropertiesModel) gifLayer.Properties).GifFile = gifPath;
profile.Name = name; AddOrUpdate(profile);
AddOrUpdate(profile); }
} }
public static void DeleteProfile(ProfileModel prof) private static List<ProfileModel> ReadProfiles(string subDirectory)
{ {
// Remove from datastore var profiles = new List<ProfileModel>();
lock (Profiles) var directory = ProfileFolder + "/" + subDirectory;
{ if (!Directory.Exists(directory))
// Get the profile from the datastore instead of just the provided value, to be certain it is removed return profiles;
var dsProfile = Profiles.FirstOrDefault(p => p.GameName == prof.GameName &&
p.Name == prof.Name &&
p.KeyboardSlug == prof.KeyboardSlug);
if (dsProfile != null)
Profiles.Remove(dsProfile);
}
// Remove the file // Create the directory structure
var path = ProfileFolder + $@"\{prof.KeyboardSlug}\{prof.GameName}\{prof.Name}.json"; var profilePaths = Directory.GetFiles(directory, "*.json", SearchOption.AllDirectories);
if (File.Exists(path))
File.Delete(path); // Parse the JSON files into objects and add them if they are valid
foreach (var path in profilePaths)
{
try
{
var prof = LoadProfileIfValid(path);
if (prof == null)
continue;
// Only add unique profiles
if (profiles.Any(p => p.GameName == prof.GameName && p.Name == prof.Name &&
p.KeyboardSlug == prof.KeyboardSlug))
{
Logger.Info("Didn't load duplicate profile: {0}", path);
}
else
{
profiles.Add(prof);
}
}
catch (Exception e)
{
Logger.Error("Failed to load profile: {0} - {1}", path, e);
}
}
return profiles;
}
/// <summary>
/// Unpacks the default profiles into the profile directory
/// </summary>
private static void InstallDefaults()
{
// Only install the defaults once per session
if (_installedDefaults)
return;
_installedDefaults = true;
// Load the ZIP from resources
var stream = Assembly.GetExecutingAssembly()
.GetManifestResourceStream("Artemis.Resources.Keyboards.default-profiles.zip");
// Extract it over the old defaults in case one was updated
if (stream == null)
return;
var archive = new ZipArchive(stream);
archive.ExtractToDirectory(ProfileFolder, true);
InsertGif("WindowsProfile", "Demo (duplicate to keep changes)", "GIF", Resources.demo_gif, "demo-gif");
}
/// <summary>
/// Makes sure the profile directory structure is in order and places default profiles
/// </summary>
private static void CheckProfiles()
{
// Create the directory structure
if (Directory.Exists(ProfileFolder))
return;
Directory.CreateDirectory(ProfileFolder);
} }
} }
} }

View File

@ -0,0 +1,91 @@
using System.Drawing;
using System.Linq;
using System.Threading;
using System.Windows;
using System.Windows.Forms;
using Artemis.DAL;
using Artemis.DeviceProviders.CoolerMaster.Utilities;
using Artemis.DeviceProviders.Logitech.Utilities;
using Artemis.Properties;
using Artemis.Settings;
using Artemis.Utilities;
namespace Artemis.DeviceProviders.CoolerMaster
{
public class MasterkeysProL : KeyboardProvider
{
private GeneralSettings _generalSettings;
public MasterkeysProL()
{
Name = "CM Masterkeys Pro L";
Slug = "cm-masterkeys-pro-l";
CantEnableText = "Couldn't connect to your CM Masterkeys Pro L.\n" +
"Please check your cables and try updating your CM software.\n\n" +
"If needed, you can select a different keyboard in Artemis under settings.";
Height = 6;
Width = 22;
PreviewSettings = new PreviewSettings(670, 189, new Thickness(-2, -5, 0, 0), Resources.masterkeys_pro_l);
_generalSettings = SettingsProvider.Load<GeneralSettings>();
}
public override void Disable()
{
CmSdk.EnableLedControl(false);
Thread.Sleep(500);
}
public override bool CanEnable()
{
CmSdk.SetControlDevice(DEVICE_INDEX.DEV_MKeys_L);
// Doesn't seem reliable but better than nothing I suppose
return CmSdk.IsDevicePlug();
}
public override void Enable()
{
CmSdk.SetControlDevice(DEVICE_INDEX.DEV_MKeys_L);
CmSdk.EnableLedControl(true);
}
public override void DrawBitmap(Bitmap bitmap)
{
// Resize the bitmap
using (var b = ImageUtilities.ResizeImage(bitmap, Width, Height))
{
// Create an empty matrix
var matrix = new COLOR_MATRIX {KeyColor = new KEY_COLOR[Height, Width]};
// Map the bytes to the matix
for (var x = 0; x < Width; x++)
{
for (var y = 0; y < Height; y++)
{
var c = b.GetPixel(x, y);
matrix.KeyColor[y, x] = new KEY_COLOR(c.R, c.G, c.B);
}
}
// Send the matrix to the keyboard
CmSdk.SetAllLedColor(matrix);
}
}
public override KeyMatch? GetKeyPosition(Keys keyCode)
{
switch (_generalSettings.Layout)
{
case "Qwerty":
return KeyMap.QwertyLayout.FirstOrDefault(k => k.KeyCode == keyCode);
case "Qwertz":
return KeyMap.QwertzLayout.FirstOrDefault(k => k.KeyCode == keyCode);
default:
return KeyMap.AzertyLayout.FirstOrDefault(k => k.KeyCode == keyCode);
}
}
}
}

View File

@ -0,0 +1,93 @@
using System.Runtime.InteropServices;
namespace Artemis.DeviceProviders.CoolerMaster.Utilities
{
public struct KEY_COLOR
{
public byte r;
public byte g;
public byte b;
public KEY_COLOR(byte colR, byte colG, byte colB)
{
r = colR;
g = colG;
b = colB;
}
}
public struct COLOR_MATRIX
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 132)] public KEY_COLOR[,] KeyColor;
}
//Enumeration of device list
public enum DEVICE_INDEX
{
DEV_MKeys_L = 0,
DEV_MKeys_S = 1,
DEV_MKeys_L_White = 2,
DEV_MKeys_M_White = 3,
DEV_MMouse_L = 4
}
//Enumeration of device layout
public enum LAYOUT_KEYBOARD
{
LAYOUT_UNINIT = 0,
LAYOUT_US = 1,
LAYOUT_EU = 2
}
public static class CmSdk
{
/// <summary>
/// Sets the control device which all following actions are targetted to
/// </summary>
/// <param name="devIndex"></param>
[DllImport("lib\\SDKDLL ", CallingConvention = CallingConvention.Cdecl)]
public static extern void SetControlDevice(DEVICE_INDEX devIndex);
/// <summary>
/// Obtain current device layout
/// </summary>
/// <returns></returns>
[DllImport("lib\\SDKDLL ", CallingConvention = CallingConvention.Cdecl)]
public static extern LAYOUT_KEYBOARD GetDeviceLayout();
/// <summary>
/// Verify if the currently conrolled device is plugged in
/// </summary>
/// <returns></returns>
[DllImport("lib\\SDKDLL ", CallingConvention = CallingConvention.Cdecl)]
public static extern bool IsDevicePlug();
/// <summary>
/// Enables led control on the currently controlled device
/// </summary>
/// <param name="bEnable"></param>
/// <returns></returns>
[DllImport("lib\\SDKDLL ", CallingConvention = CallingConvention.Cdecl)]
public static extern bool EnableLedControl(bool bEnable);
/// <summary>
/// Sets the LED of the currently controlled device
/// </summary>
/// <param name="iRow"></param>
/// <param name="iColumn"></param>
/// <param name="r"></param>
/// <param name="g"></param>
/// <param name="b"></param>
/// <returns></returns>
[DllImport("lib\\SDKDLL ", CallingConvention = CallingConvention.Cdecl)]
public static extern bool SetLedColor(int iRow, int iColumn, byte r, byte g, byte b);
/// <summary>
/// Sets all LEDS using the given color matrix
/// </summary>
/// <param name="colorMatrix"></param>
/// <returns></returns>
[DllImport("lib\\SDKDLL ", CallingConvention = CallingConvention.Cdecl)]
public static extern bool SetAllLedColor(COLOR_MATRIX colorMatrix);
}
}

View File

@ -11,6 +11,7 @@ using CUE.NET.Brushes;
using CUE.NET.Devices.Generic; using CUE.NET.Devices.Generic;
using CUE.NET.Devices.Generic.Enums; using CUE.NET.Devices.Generic.Enums;
using CUE.NET.Devices.Keyboard; using CUE.NET.Devices.Keyboard;
using CUE.NET.Helper;
using Ninject.Extensions.Logging; using Ninject.Extensions.Logging;
using Point = System.Drawing.Point; using Point = System.Drawing.Point;
@ -82,6 +83,7 @@ namespace Artemis.DeviceProviders.Corsair
} }
Logger.Debug("Corsair SDK reported device as: {0}", _keyboard.DeviceInfo.Model); Logger.Debug("Corsair SDK reported device as: {0}", _keyboard.DeviceInfo.Model);
_keyboard.Brush = _keyboardBrush ?? (_keyboardBrush = new ImageBrush()); _keyboard.Brush = _keyboardBrush ?? (_keyboardBrush = new ImageBrush());
} }
@ -103,19 +105,21 @@ namespace Artemis.DeviceProviders.Corsair
// For STRAFE, stretch the image on row 2. // For STRAFE, stretch the image on row 2.
if (_keyboard.DeviceInfo.Model == "STRAFE RGB") if (_keyboard.DeviceInfo.Model == "STRAFE RGB")
{ {
var strafeBitmap = new Bitmap(22, 8); using (var strafeBitmap = new Bitmap(22, 8))
using (var g = Graphics.FromImage(strafeBitmap))
{ {
g.DrawImage(image, new Point(0, 0)); using (var g = Graphics.FromImage(strafeBitmap))
g.DrawImage(image, new Rectangle(0, 3, 22, 7), new Rectangle(0, 2, 22, 7), GraphicsUnit.Pixel); {
} g.DrawImage(image, new Point(0, 0));
g.DrawImage(image, new Rectangle(0, 3, 22, 7), new Rectangle(0, 2, 22, 7), GraphicsUnit.Pixel);
}
image.Dispose(); image.Dispose();
image = strafeBitmap; image = strafeBitmap;
}
} }
_keyboardBrush.Image = image; _keyboardBrush.Image = image;
_keyboard.Update(true); _keyboard.Update();
image.Dispose(); image.Dispose();
} }
@ -136,11 +140,11 @@ namespace Artemis.DeviceProviders.Corsair
// ignored // ignored
} }
if (cueLed != null) if (cueLed == null)
return new KeyMatch(keyCode, (int) (cueLed.LedRectangle.X*widthMultiplier), return null;
(int) (cueLed.LedRectangle.Y*heightMultiplier));
return null; var center = cueLed.LedRectangle.GetCenter();
return new KeyMatch(keyCode, (int) (center.X*widthMultiplier),(int) (center.Y*heightMultiplier));
} }
} }
} }

View File

@ -39,7 +39,7 @@ namespace Artemis.DeviceProviders
/// <returns></returns> /// <returns></returns>
public Bitmap KeyboardBitmap(int scale) => new Bitmap(Width*scale, Height*scale); 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 Rect KeyboardRectangle(int scale = 4) => new Rect(new Size(Width*scale, Height*scale));
/// <summary> /// <summary>
/// Runs CanEnable asynchronously multiple times until successful, cancelled or max tries reached /// Runs CanEnable asynchronously multiple times until successful, cancelled or max tries reached

View File

@ -28,9 +28,15 @@ namespace Artemis.DeviceProviders.Logitech
public override KeyMatch? GetKeyPosition(Keys keyCode) public override KeyMatch? GetKeyPosition(Keys keyCode)
{ {
return _generalSettings.Layout == "Qwerty" switch (_generalSettings.Layout)
? KeyMap.QwertyLayout.FirstOrDefault(k => k.KeyCode == keyCode) {
: KeyMap.AzertyLayout.FirstOrDefault(k => k.KeyCode == keyCode); case "Qwerty":
return KeyMap.QwertyLayout.FirstOrDefault(k => k.KeyCode == keyCode);
case "Qwertz":
return KeyMap.QwertzLayout.FirstOrDefault(k => k.KeyCode == keyCode);
default:
return KeyMap.AzertyLayout.FirstOrDefault(k => k.KeyCode == keyCode);
}
} }
} }
} }

View File

@ -30,9 +30,19 @@ namespace Artemis.DeviceProviders.Logitech
public override KeyMatch? GetKeyPosition(Keys keyCode) public override KeyMatch? GetKeyPosition(Keys keyCode)
{ {
var value = _generalSettings.Layout == "Qwerty" KeyMatch value;
? KeyMap.QwertyLayout.FirstOrDefault(k => k.KeyCode == keyCode) switch (_generalSettings.Layout)
: KeyMap.AzertyLayout.FirstOrDefault(k => k.KeyCode == keyCode); {
case "Qwerty":
value = KeyMap.QwertyLayout.FirstOrDefault(k => k.KeyCode == keyCode);
break;
case "Qwertz":
value = KeyMap.QwertzLayout.FirstOrDefault(k => k.KeyCode == keyCode);
break;
default:
value = KeyMap.AzertyLayout.FirstOrDefault(k => k.KeyCode == keyCode);
break;
}
// Adjust the distance by 1 on both x and y for the G910 // Adjust the distance by 1 on both x and y for the G910
return new KeyMatch(value.KeyCode, value.X + 1, value.Y + 1); return new KeyMatch(value.KeyCode, value.X + 1, value.Y + 1);

View File

@ -13,12 +13,12 @@ namespace Artemis.DeviceProviders.Logitech
{ {
// Check to see if VC++ 2012 x64 is installed. // Check to see if VC++ 2012 x64 is installed.
if (Registry.LocalMachine.OpenSubKey( if (Registry.LocalMachine.OpenSubKey(
@"SOFTWARE\Classes\Installer\Dependencies\{ca67548a-5ebe-413a-b50c-4b9ceb6d66c6}") == null) @"SOFTWARE\Classes\Installer\Dependencies\{ca67548a-5ebe-413a-b50c-4b9ceb6d66c6}") == null)
{ {
CantEnableText = "Couldn't connect to your Logitech keyboard.\n" + CantEnableText = "Couldn't connect to your Logitech keyboard.\n" +
"The Visual C++ 2012 Redistributable could not be found, which is required.\n" + "The Visual C++ 2012 Redistributable v11.0.61030.0 could not be found, which is required.\n" +
"Please download it by going to the following URL:\n\n" + "Please download it by going to the following URL (link also in wiki):\n\n" +
"https://www.microsoft.com/download/confirmation.aspx?id=30679"; "https://download.microsoft.com/download/1/6/B/16B06F60-3B20-4FF2-B699-5E9B7962F9AE/VSU_4/vcredist_x64.exe";
return false; return false;
} }

View File

@ -8,6 +8,9 @@ namespace Artemis.DeviceProviders.Logitech.Utilities
static KeyMap() static KeyMap()
{ {
// There are several keyboard layouts // There are several keyboard layouts
#region Qwerty
QwertyLayout = new List<KeyMatch> QwertyLayout = new List<KeyMatch>
{ {
// Row 1 // Row 1
@ -129,6 +132,135 @@ namespace Artemis.DeviceProviders.Logitech.Utilities
new KeyMatch(Keys.Decimal, 19, 5) new KeyMatch(Keys.Decimal, 19, 5)
}; };
#endregion
#region Qwertz
QwertzLayout = new List<KeyMatch>
{
// Row 1
new KeyMatch(Keys.Escape, 0, 0),
new KeyMatch(Keys.F1, 2, 0),
new KeyMatch(Keys.F2, 3, 0),
new KeyMatch(Keys.F3, 4, 0),
new KeyMatch(Keys.F4, 5, 0),
new KeyMatch(Keys.F5, 6, 0),
new KeyMatch(Keys.F6, 7, 0),
new KeyMatch(Keys.F7, 8, 0),
new KeyMatch(Keys.F8, 9, 0),
new KeyMatch(Keys.F9, 11, 0),
new KeyMatch(Keys.F10, 12, 0), // returns 'None'
new KeyMatch(Keys.F11, 13, 0),
new KeyMatch(Keys.F12, 14, 0),
new KeyMatch(Keys.PrintScreen, 15, 0),
new KeyMatch(Keys.Scroll, 16, 0),
new KeyMatch(Keys.Pause, 17, 0),
// Row 2
new KeyMatch(Keys.Oem5, 0, 1),
new KeyMatch(Keys.D1, 1, 1),
new KeyMatch(Keys.D2, 2, 1),
new KeyMatch(Keys.D3, 3, 1),
new KeyMatch(Keys.D4, 4, 1),
new KeyMatch(Keys.D5, 5, 1),
new KeyMatch(Keys.D6, 6, 1),
new KeyMatch(Keys.D7, 7, 1),
new KeyMatch(Keys.D8, 8, 1),
new KeyMatch(Keys.D9, 9, 1),
new KeyMatch(Keys.D0, 10, 1),
new KeyMatch(Keys.OemOpenBrackets, 11, 1),
new KeyMatch(Keys.Oem6, 12, 1),
new KeyMatch(Keys.Back, 13, 1),
new KeyMatch(Keys.Insert, 14, 1),
new KeyMatch(Keys.Home, 15, 1),
new KeyMatch(Keys.PageUp, 16, 1),
new KeyMatch(Keys.NumLock, 17, 1),
new KeyMatch(Keys.Divide, 18, 1),
new KeyMatch(Keys.Multiply, 19, 1),
new KeyMatch(Keys.Subtract, 20, 1),
// Row 3
new KeyMatch(Keys.Tab, 0, 2),
new KeyMatch(Keys.Q, 1, 2),
new KeyMatch(Keys.W, 2, 2),
new KeyMatch(Keys.E, 3, 2),
new KeyMatch(Keys.R, 5, 2),
new KeyMatch(Keys.T, 6, 2),
new KeyMatch(Keys.Z, 7, 2),
new KeyMatch(Keys.U, 8, 2),
new KeyMatch(Keys.I, 9, 2),
new KeyMatch(Keys.O, 10, 2),
new KeyMatch(Keys.P, 11, 2),
new KeyMatch(Keys.Oem1, 12, 2),
new KeyMatch(Keys.Oemplus, 13, 2),
new KeyMatch(Keys.Delete, 14, 2),
new KeyMatch(Keys.End, 15, 2),
new KeyMatch(Keys.Next, 16, 2),
new KeyMatch(Keys.NumPad7, 17, 2),
new KeyMatch(Keys.NumPad8, 18, 2),
new KeyMatch(Keys.NumPad9, 19, 2),
new KeyMatch(Keys.Add, 20, 2),
// Row 4
new KeyMatch(Keys.Capital, 0, 3),
new KeyMatch(Keys.A, 1, 3),
new KeyMatch(Keys.S, 3, 3),
new KeyMatch(Keys.D, 4, 3),
new KeyMatch(Keys.F, 5, 3),
new KeyMatch(Keys.G, 6, 3),
new KeyMatch(Keys.H, 7, 3),
new KeyMatch(Keys.J, 8, 3),
new KeyMatch(Keys.K, 9, 3),
new KeyMatch(Keys.L, 10, 3),
new KeyMatch(Keys.Oemtilde, 11, 3),
new KeyMatch(Keys.Oem7, 12, 3),
new KeyMatch(Keys.OemQuestion, 13, 3),
new KeyMatch(Keys.Return, 14, 3),
new KeyMatch(Keys.NumPad4, 17, 3),
new KeyMatch(Keys.NumPad5, 18, 3),
new KeyMatch(Keys.NumPad6, 19, 3),
// Row 5
new KeyMatch(Keys.LShiftKey, 1, 4),
new KeyMatch(Keys.OemBackslash, 2, 4),
new KeyMatch(Keys.Y, 2, 4),
new KeyMatch(Keys.X, 3, 4),
new KeyMatch(Keys.C, 4, 4),
new KeyMatch(Keys.V, 5, 4),
new KeyMatch(Keys.B, 6, 4),
new KeyMatch(Keys.N, 7, 4),
new KeyMatch(Keys.M, 8, 4),
new KeyMatch(Keys.Oemcomma, 9, 4),
new KeyMatch(Keys.OemPeriod, 10, 4),
new KeyMatch(Keys.OemMinus, 11, 4),
new KeyMatch(Keys.RShiftKey, 13, 4),
new KeyMatch(Keys.Up, 15, 4),
new KeyMatch(Keys.NumPad1, 17, 4),
new KeyMatch(Keys.NumPad2, 18, 4),
new KeyMatch(Keys.NumPad3, 19, 4),
// Both returns return "Return" (Yes...)
// new OrionKey(System.Windows.Forms.Keys.Return, 20, 4),
// Row 6
new KeyMatch(Keys.LControlKey, 0, 5),
new KeyMatch(Keys.LWin, 1, 5),
new KeyMatch(Keys.Menu, 3, 5), // returns 'None'
new KeyMatch(Keys.Space, 6, 5),
new KeyMatch(Keys.RMenu, 11, 5),
new KeyMatch(Keys.RWin, 12, 5),
new KeyMatch(Keys.Apps, 13, 5),
new KeyMatch(Keys.RControlKey, 14, 5),
new KeyMatch(Keys.Left, 15, 5),
new KeyMatch(Keys.Down, 16, 5),
new KeyMatch(Keys.Right, 17, 5),
new KeyMatch(Keys.NumPad0, 18, 5),
new KeyMatch(Keys.Decimal, 19, 5)
};
#endregion
#region Azerty
AzertyLayout = new List<KeyMatch> AzertyLayout = new List<KeyMatch>
{ {
// Row 1 // Row 1
@ -249,9 +381,12 @@ namespace Artemis.DeviceProviders.Logitech.Utilities
new KeyMatch(Keys.NumPad0, 18, 5), new KeyMatch(Keys.NumPad0, 18, 5),
new KeyMatch(Keys.Decimal, 19, 5) new KeyMatch(Keys.Decimal, 19, 5)
}; };
#endregion
} }
public static List<KeyMatch> QwertyLayout { get; set; } public static List<KeyMatch> QwertyLayout { get; set; }
public static List<KeyMatch> QwertzLayout { get; set; }
public static List<KeyMatch> AzertyLayout { get; set; } public static List<KeyMatch> AzertyLayout { get; set; }
} }
} }

View File

@ -202,10 +202,16 @@ namespace Artemis.DeviceProviders.Logitech.Utilities
{ {
graphics.CompositingMode = CompositingMode.SourceCopy; graphics.CompositingMode = CompositingMode.SourceCopy;
graphics.CompositingQuality = CompositingQuality.HighQuality; graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.SmoothingMode = SmoothingMode.HighQuality; graphics.SmoothingMode = SmoothingMode.AntiAlias;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
// TODO: Make configurable
// Prevents light bleed
graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
// Soft/semi-transparent keys
//graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
using (var wrapMode = new ImageAttributes()) using (var wrapMode = new ImageAttributes())
{ {
wrapMode.SetWrapMode(WrapMode.TileFlipXY); wrapMode.SetWrapMode(WrapMode.TileFlipXY);

View File

@ -2,9 +2,11 @@
using System.Linq; using System.Linq;
using System.Windows; using System.Windows;
using System.Windows.Forms; using System.Windows.Forms;
using Artemis.DAL;
using Artemis.DeviceProviders.Logitech.Utilities; using Artemis.DeviceProviders.Logitech.Utilities;
using Artemis.DeviceProviders.Razer.Utilities; using Artemis.DeviceProviders.Razer.Utilities;
using Artemis.Properties; using Artemis.Properties;
using Artemis.Settings;
using Corale.Colore.Core; using Corale.Colore.Core;
using Corale.Colore.Razer; using Corale.Colore.Razer;
using Constants = Corale.Colore.Razer.Keyboard.Constants; using Constants = Corale.Colore.Razer.Keyboard.Constants;
@ -13,6 +15,8 @@ namespace Artemis.DeviceProviders.Razer
{ {
public class BlackWidow : KeyboardProvider public class BlackWidow : KeyboardProvider
{ {
private GeneralSettings _generalSettings;
public BlackWidow() public BlackWidow()
{ {
Name = "Razer BlackWidow Chroma"; Name = "Razer BlackWidow Chroma";
@ -24,6 +28,7 @@ namespace Artemis.DeviceProviders.Razer
Height = Constants.MaxRows; Height = Constants.MaxRows;
Width = Constants.MaxColumns; Width = Constants.MaxColumns;
PreviewSettings = new PreviewSettings(665, 175, new Thickness(0, -15, 0, 0), Resources.blackwidow); PreviewSettings = new PreviewSettings(665, 175, new Thickness(0, -15, 0, 0), Resources.blackwidow);
_generalSettings = SettingsProvider.Load<GeneralSettings>();
} }
public override bool CanEnable() public override bool CanEnable()
@ -56,7 +61,15 @@ namespace Artemis.DeviceProviders.Razer
public override KeyMatch? GetKeyPosition(Keys keyCode) public override KeyMatch? GetKeyPosition(Keys keyCode)
{ {
// TODO: Needs it's own keymap or a way to get it from the Chroma SDK // TODO: Needs it's own keymap or a way to get it from the Chroma SDK
return KeyMap.QwertyLayout.FirstOrDefault(k => k.KeyCode == keyCode); switch (_generalSettings.Layout)
{
case "Qwerty":
return KeyMap.QwertyLayout.FirstOrDefault(k => k.KeyCode == keyCode);
case "Qwertz":
return KeyMap.QwertzLayout.FirstOrDefault(k => k.KeyCode == keyCode);
default:
return KeyMap.AzertyLayout.FirstOrDefault(k => k.KeyCode == keyCode);
}
} }
} }
} }

View File

@ -10,19 +10,21 @@ namespace Artemis.DeviceProviders.Razer.Utilities
public static Custom BitmapColorArray(Bitmap b, int height, int width) public static Custom BitmapColorArray(Bitmap b, int height, int width)
{ {
var keyboardGrid = Custom.Create(); var keyboardGrid = Custom.Create();
if (b.Width > width || b.Height > height) // Resize the bitmap
b = ImageUtilities.ResizeImage(b, width, height); using (b = ImageUtilities.ResizeImage(b, width, height))
for (var y = 0; y < b.Height; y++)
{ {
// Map the bytes to the grid
for (var x = 0; x < b.Width; x++) for (var x = 0; x < b.Width; x++)
{ {
var pixel = b.GetPixel(x, y); for (var y = 0; y < b.Height; y++)
keyboardGrid[y, x] = new Color(pixel.R, pixel.G, pixel.B); {
var c = b.GetPixel(x, y);
keyboardGrid[y, x] = new Color(c.R, c.G, c.B);
}
} }
}
return keyboardGrid; return keyboardGrid;
}
} }
} }
} }

View File

@ -0,0 +1,53 @@
<dialogs:CustomDialog x:Class="Artemis.Dialogs.MarkdownDialog"
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:dialogs="clr-namespace:MahApps.Metro.Controls.Dialogs;assembly=MahApps.Metro"
xmlns:dialogs1="clr-namespace:Artemis.Dialogs"
xmlns:markdown="clr-namespace:Artemis.Utilities.Markdown"
xmlns:system="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<dialogs:CustomDialog.Resources>
<markdown:Markdown x:Key="Markdown"
DocumentStyle="{StaticResource DocumentStyle}"
Heading1Style="{StaticResource H1Style}"
Heading2Style="{StaticResource H2Style}"
Heading3Style="{StaticResource H3Style}"
Heading4Style="{StaticResource H4Style}"
LinkStyle="{StaticResource LinkStyle}"
ImageStyle="{StaticResource ImageStyle}"
SeparatorStyle="{StaticResource SeparatorStyle}"
AssetPathRoot="{x:Static system:Environment.CurrentDirectory}" />
<markdown:TextToFlowDocumentConverter x:Key="TextToFlowDocumentConverter"
Markdown="{StaticResource Markdown}" />
</dialogs:CustomDialog.Resources>
<Grid Margin="0 10 0 0">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<FlowDocumentScrollViewer
HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto"
Margin="-15 -15 0 0"
FontSize="{Binding DialogMessageFontSize, RelativeSource={RelativeSource AncestorType=dialogs:MessageDialog, Mode=FindAncestor}, UpdateSourceTrigger=PropertyChanged}"
Foreground="{Binding Foreground, RelativeSource={RelativeSource AncestorType=dialogs:MessageDialog, Mode=FindAncestor}, UpdateSourceTrigger=PropertyChanged}"
Document="{Binding Markdown, RelativeSource={RelativeSource AncestorType=dialogs1:MarkdownDialog, Mode=FindAncestor}, Converter={StaticResource TextToFlowDocumentConverter}, UpdateSourceTrigger=PropertyChanged}" IsSelectionEnabled="False" />
<StackPanel Grid.Row="1"
Height="85"
HorizontalAlignment="Right"
Orientation="Horizontal">
<Button x:Name="PART_AffirmativeButton"
Height="35"
MinWidth="80"
Margin="0 0 5 0"
Content="Alrighty, let's go!"
Style="{DynamicResource AccentedDialogSquareButton}" />
</StackPanel>
</Grid>
</dialogs:CustomDialog>

View File

@ -0,0 +1,28 @@
using System.Windows;
using System.Windows.Input;
namespace Artemis.Dialogs
{
/// <summary>
/// Interaction logic for MarkdownDialog.xaml
/// </summary>
public partial class MarkdownDialog
{
public static readonly DependencyProperty MarkdownProperty = DependencyProperty.Register("Markdown",
typeof(string), typeof(MarkdownDialog), new PropertyMetadata(default(string)));
public MarkdownDialog()
{
InitializeComponent();
CommandBindings.Add(new CommandBinding(NavigationCommands.GoToPage,
(sender, e) => System.Diagnostics.Process.Start((string) e.Parameter)));
}
public string Markdown
{
get { return (string) GetValue(MarkdownProperty); }
set { SetValue(MarkdownProperty, value); }
}
}
}

View File

@ -1,11 +0,0 @@
using Artemis.Models.Interfaces;
using Artemis.Profiles.Layers.Models;
using Artemis.ViewModels.Profiles;
namespace Artemis.InjectionFactories
{
public interface ILayerEditorVmFactory
{
LayerEditorViewModel CreateLayerEditorVm(IDataModel dataModel, LayerModel layer);
}
}

View File

@ -1,11 +0,0 @@
using Artemis.Managers;
using Artemis.Models;
using Artemis.ViewModels.Profiles;
namespace Artemis.InjectionFactories
{
public interface IProfileEditorVmFactory
{
ProfileEditorViewModel CreateProfileEditorVm(MainManager mainManager, EffectModel gameModel, string lastProfile);
}
}

View File

@ -1,11 +1,10 @@
using Artemis.InjectionFactories; using Artemis.Modules.Effects.ProfilePreview;
using Artemis.Modules.Effects.ProfilePreview;
using Artemis.Services; using Artemis.Services;
using Artemis.Utilities.DataReaders;
using Artemis.Utilities.GameState;
using Artemis.ViewModels; using Artemis.ViewModels;
using Artemis.ViewModels.Abstract; using Artemis.ViewModels.Abstract;
using Artemis.ViewModels.Profiles; using Artemis.ViewModels.Profiles;
using Caliburn.Micro;
using Ninject.Extensions.Factory;
using Ninject.Modules; using Ninject.Modules;
namespace Artemis.InjectionModules namespace Artemis.InjectionModules
@ -15,22 +14,26 @@ namespace Artemis.InjectionModules
public override void Load() public override void Load()
{ {
// ViewModels // ViewModels
Bind<IScreen>().To<ShellViewModel>().InSingletonScope(); Bind<ShellViewModel>().ToSelf().InSingletonScope();
Bind<IProfileEditorVmFactory>().ToFactory();
Bind<ILayerEditorVmFactory>().ToFactory();
Bind<ProfileViewModel>().ToSelf(); Bind<ProfileViewModel>().ToSelf();
Bind<ProfileEditorViewModel>().ToSelf();
Bind<DebugViewModel>().ToSelf().InSingletonScope(); Bind<DebugViewModel>().ToSelf().InSingletonScope();
Bind<BaseViewModel>().To<WelcomeViewModel>().InSingletonScope(); Bind<BaseViewModel>().To<WelcomeViewModel>();
Bind<BaseViewModel>().To<EffectsViewModel>().InSingletonScope(); Bind<BaseViewModel>().To<EffectsViewModel>();
Bind<BaseViewModel>().To<GamesViewModel>().InSingletonScope(); Bind<BaseViewModel>().To<GamesViewModel>();
Bind<BaseViewModel>().To<OverlaysViewModel>().InSingletonScope(); Bind<BaseViewModel>().To<OverlaysViewModel>();
// Models // Models
Bind<ProfilePreviewModel>().ToSelf().InSingletonScope(); Bind<ProfilePreviewModel>().ToSelf().InSingletonScope();
// Services // Services
Bind<MetroDialogService>().ToSelf().InSingletonScope(); Bind<MetroDialogService>().ToSelf().InSingletonScope();
Bind<WindowService>().ToSelf().InSingletonScope();
// Servers
Bind<GameStateWebServer>().ToSelf().InSingletonScope();
Bind<PipeServer>().ToSelf().InSingletonScope();
} }
} }
} }

View File

@ -1,4 +1,5 @@
using Artemis.DeviceProviders; using Artemis.DeviceProviders;
using Artemis.DeviceProviders.CoolerMaster;
using Artemis.DeviceProviders.Corsair; using Artemis.DeviceProviders.Corsair;
using Artemis.DeviceProviders.Logitech; using Artemis.DeviceProviders.Logitech;
using Artemis.DeviceProviders.Razer; using Artemis.DeviceProviders.Razer;
@ -15,6 +16,7 @@ namespace Artemis.InjectionModules
Bind<DeviceProvider>().To<G910>().InSingletonScope(); Bind<DeviceProvider>().To<G910>().InSingletonScope();
Bind<DeviceProvider>().To<G810>().InSingletonScope(); Bind<DeviceProvider>().To<G810>().InSingletonScope();
Bind<DeviceProvider>().To<BlackWidow>().InSingletonScope(); Bind<DeviceProvider>().To<BlackWidow>().InSingletonScope();
Bind<DeviceProvider>().To<MasterkeysProL>().InSingletonScope();
// Mice // Mice
Bind<DeviceProvider>().To<CorsairMice>().InSingletonScope(); Bind<DeviceProvider>().To<CorsairMice>().InSingletonScope();

View File

@ -16,26 +16,16 @@ namespace Artemis.InjectionModules
.SelectAllClasses() .SelectAllClasses()
.InheritedFrom<EffectModel>() .InheritedFrom<EffectModel>()
.BindBase() .BindBase()
.Configure(b => b.InSingletonScope()); .Configure((b, c) => b.InSingletonScope().Named(c.Name));
}); });
// View models
Kernel.Bind(x => Kernel.Bind(x =>
{ {
x.FromThisAssembly() x.FromThisAssembly()
.SelectAllClasses() .SelectAllClasses()
.InheritedFrom<EffectViewModel>() .InheritedFrom<EffectViewModel>()
.BindBase() .BindBase();
.Configure(b => b.InSingletonScope());
});
// Games
Kernel.Bind(x =>
{
x.FromThisAssembly()
.SelectAllClasses()
.InheritedFrom<GameModel>()
.BindBase()
.Configure(b => b.InSingletonScope());
}); });
Kernel.Bind(x => Kernel.Bind(x =>
@ -43,27 +33,14 @@ namespace Artemis.InjectionModules
x.FromThisAssembly() x.FromThisAssembly()
.SelectAllClasses() .SelectAllClasses()
.InheritedFrom<GameViewModel>() .InheritedFrom<GameViewModel>()
.BindBase() .BindBase();
.Configure(b => b.InSingletonScope());
}); });
// Overlays
Kernel.Bind(x =>
{
x.FromThisAssembly()
.SelectAllClasses()
.InheritedFrom<OverlayModel>()
.BindBase()
.Configure(b => b.InSingletonScope());
});
Kernel.Bind(x => Kernel.Bind(x =>
{ {
x.FromThisAssembly() x.FromThisAssembly()
.SelectAllClasses() .SelectAllClasses()
.InheritedFrom<OverlayViewModel>() .InheritedFrom<OverlayViewModel>()
.BindBase() .BindBase();
.Configure(b => b.InSingletonScope());
}); });
} }
} }

View File

@ -1,6 +1,7 @@
using Artemis.Profiles.Layers.Animations; using Artemis.Profiles.Layers.Animations;
using Artemis.Profiles.Layers.Conditions; using Artemis.Profiles.Layers.Conditions;
using Artemis.Profiles.Layers.Interfaces; using Artemis.Profiles.Layers.Interfaces;
using Artemis.Profiles.Layers.Types.AmbientLight;
using Artemis.Profiles.Layers.Types.Audio; using Artemis.Profiles.Layers.Types.Audio;
using Artemis.Profiles.Layers.Types.Folder; using Artemis.Profiles.Layers.Types.Folder;
using Artemis.Profiles.Layers.Types.Generic; using Artemis.Profiles.Layers.Types.Generic;
@ -41,10 +42,12 @@ namespace Artemis.InjectionModules
Bind<ILayerType>().To<GenericType>(); Bind<ILayerType>().To<GenericType>();
Bind<ILayerType>().To<KeyPressType>(); Bind<ILayerType>().To<KeyPressType>();
Bind<ILayerType>().To<AudioType>(); Bind<ILayerType>().To<AudioType>();
Bind<ILayerType>().To<AmbientLightType>();
// Bind some Layer Types to self as well in order to allow JSON.NET injection // Bind some Layer Types to self as well in order to allow JSON.NET injection
Bind<KeyPressType>().ToSelf(); Bind<KeyPressType>().ToSelf();
Bind<AudioType>().ToSelf(); Bind<AudioType>().ToSelf();
Bind<AmbientLightType>().ToSelf();
} }
} }
} }

View File

@ -73,7 +73,7 @@ namespace Artemis.Managers
public async void EnableKeyboard(KeyboardProvider keyboardProvider) public async void EnableKeyboard(KeyboardProvider keyboardProvider)
{ {
if (keyboardProvider == null) if (keyboardProvider == null)
throw new ArgumentNullException(nameof(keyboardProvider)); return;
if (ChangingKeyboard || (ActiveKeyboard?.Name == keyboardProvider.Name)) if (ChangingKeyboard || (ActiveKeyboard?.Name == keyboardProvider.Name))
return; return;

View File

@ -21,14 +21,24 @@ namespace Artemis.Managers
private EffectModel _waitEffect; private EffectModel _waitEffect;
private readonly GeneralSettings _generalSettings; private readonly GeneralSettings _generalSettings;
public EffectManager(ILogger logger, DeviceManager deviceManager) public EffectManager(ILogger logger, DeviceManager deviceManager, List<EffectModel> effectModels,
List<GameModel> gameModels, List<OverlayModel> overlayModels)
{ {
EffectModels = new List<EffectModel>();
_generalSettings = DAL.SettingsProvider.Load<GeneralSettings>(); _generalSettings = DAL.SettingsProvider.Load<GeneralSettings>();
_logger = logger; _logger = logger;
_deviceManager = deviceManager; _deviceManager = deviceManager;
var models = new List<EffectModel>();
// Add regular effects
models.AddRange(effectModels);
// Add overlays
models.AddRange(overlayModels);
// Add games, exclude WoW if needed
models.AddRange(_generalSettings.GamestatePort != 62575
? gameModels.Where(e => e.Name != "WoW")
: gameModels);
EffectModels = models;
_logger.Info("Intialized EffectManager"); _logger.Info("Intialized EffectManager");
} }

View File

@ -5,7 +5,6 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Timers; using System.Timers;
using Artemis.DeviceProviders; using Artemis.DeviceProviders;
using Caliburn.Micro;
using Ninject.Extensions.Logging; using Ninject.Extensions.Logging;
using Timer = System.Timers.Timer; using Timer = System.Timers.Timer;
@ -160,15 +159,27 @@ namespace Artemis.Managers
generic.UpdateDevice(frame.GenericBitmap); generic.UpdateDevice(frame.GenericBitmap);
foreach (var mousemat in mousemats) foreach (var mousemat in mousemats)
mousemat.UpdateDevice(frame.MousematBitmap); mousemat.UpdateDevice(frame.MousematBitmap);
OnRenderCompleted();
} }
} }
} }
public event EventHandler RenderCompleted;
protected virtual void OnRenderCompleted()
{
RenderCompleted?.Invoke(this, EventArgs.Empty);
}
} }
public class RenderFrame : IDisposable public class RenderFrame : IDisposable
{ {
public RenderFrame(KeyboardProvider keyboard) public RenderFrame(KeyboardProvider keyboard)
{ {
if (keyboard == null)
return;
KeyboardBitmap = keyboard.KeyboardBitmap(4); KeyboardBitmap = keyboard.KeyboardBitmap(4);
KeyboardBitmap.SetResolution(96, 96); KeyboardBitmap.SetResolution(96, 96);
@ -185,15 +196,25 @@ namespace Artemis.Managers
MousematBitmap.SetResolution(96, 96); MousematBitmap.SetResolution(96, 96);
using (var g = Graphics.FromImage(KeyboardBitmap)) using (var g = Graphics.FromImage(KeyboardBitmap))
{
g.Clear(Color.Black); g.Clear(Color.Black);
}
using (var g = Graphics.FromImage(MouseBitmap)) using (var g = Graphics.FromImage(MouseBitmap))
{
g.Clear(Color.Black); g.Clear(Color.Black);
}
using (var g = Graphics.FromImage(HeadsetBitmap)) using (var g = Graphics.FromImage(HeadsetBitmap))
{
g.Clear(Color.Black); g.Clear(Color.Black);
}
using (var g = Graphics.FromImage(GenericBitmap)) using (var g = Graphics.FromImage(GenericBitmap))
{
g.Clear(Color.Black); g.Clear(Color.Black);
}
using (var g = Graphics.FromImage(MousematBitmap)) using (var g = Graphics.FromImage(MousematBitmap))
{
g.Clear(Color.Black); g.Clear(Color.Black);
}
} }
public Bitmap KeyboardBitmap { get; set; } public Bitmap KeyboardBitmap { get; set; }
@ -204,10 +225,10 @@ namespace Artemis.Managers
public void Dispose() public void Dispose()
{ {
KeyboardBitmap.Dispose(); KeyboardBitmap?.Dispose();
MouseBitmap.Dispose(); MouseBitmap?.Dispose();
HeadsetBitmap.Dispose(); HeadsetBitmap?.Dispose();
GenericBitmap.Dispose(); GenericBitmap?.Dispose();
} }
} }
} }

View File

@ -23,7 +23,8 @@ namespace Artemis.Managers
private readonly Timer _processTimer; private readonly Timer _processTimer;
public MainManager(ILogger logger, LoopManager loopManager, DeviceManager deviceManager, public MainManager(ILogger logger, LoopManager loopManager, DeviceManager deviceManager,
EffectManager effectManager, ProfileManager profileManager, PipeServer pipeServer) EffectManager effectManager, ProfileManager profileManager, PipeServer pipeServer,
GameStateWebServer gameStateWebServer)
{ {
Logger = logger; Logger = logger;
LoopManager = loopManager; LoopManager = loopManager;
@ -40,7 +41,7 @@ namespace Artemis.Managers
Running = false; Running = false;
// Create and start the web server // Create and start the web server
GameStateWebServer = new GameStateWebServer(logger); GameStateWebServer = gameStateWebServer;
GameStateWebServer.Start(); GameStateWebServer.Start();
// Start the named pipe // Start the named pipe

View File

@ -51,34 +51,39 @@ namespace Artemis.Managers
ProfilePreviewModel == null) ProfilePreviewModel == null)
return; return;
var activePreview = GameViewModels.FirstOrDefault(vm => vm.IsActive); lock (GameViewModels)
if (activePreview == null)
{ {
// Should not be active if no selected profile is set var activePreview = GameViewModels.FirstOrDefault(vm => vm.IsActive);
if (_effectManager.ActiveEffect != ProfilePreviewModel)
return;
_logger.Debug("Loading last effect after profile preview"); if (activePreview == null)
var lastEffect = _effectManager.GetLastEffect();
if (lastEffect != null)
_effectManager.ChangeEffect(lastEffect);
else
_effectManager.ClearEffect();
}
else
{
if (_effectManager.ActiveEffect != ProfilePreviewModel && !(_effectManager.ActiveEffect is GameModel))
{ {
_logger.Debug("Activate profile preview"); // Should not be active if no selected profile is set
_effectManager.ChangeEffect(ProfilePreviewModel); if (_effectManager.ActiveEffect != ProfilePreviewModel)
return;
_logger.Debug("Loading last effect after profile preview");
var lastEffect = _effectManager.GetLastEffect();
if (lastEffect != null)
_effectManager.ChangeEffect(lastEffect);
else
_effectManager.ClearEffect();
} }
else
{
if (_effectManager.ActiveEffect != ProfilePreviewModel &&
!(_effectManager.ActiveEffect is GameModel))
{
_logger.Debug("Activate profile preview");
_effectManager.ChangeEffect(ProfilePreviewModel);
}
// LoopManager might be running, this method won't do any harm in that case. // LoopManager might be running, this method won't do any harm in that case.
_loopManager.StartAsync(); _loopManager.StartAsync();
ProfilePreviewModel.ProfileViewModel = activePreview.ProfileEditor.ProfileViewModel; ProfilePreviewModel.ProfileViewModel = activePreview.ProfileEditor.ProfileViewModel;
if (!ReferenceEquals(ProfilePreviewModel.Profile, activePreview.ProfileEditor.SelectedProfile)) if (!ReferenceEquals(ProfilePreviewModel.Profile, activePreview.ProfileEditor.SelectedProfile))
ProfilePreviewModel.Profile = activePreview.ProfileEditor.SelectedProfile; ProfilePreviewModel.Profile = activePreview.ProfileEditor.SelectedProfile;
}
} }
} }
} }

View File

@ -3,6 +3,8 @@ using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Linq; using System.Linq;
using System.Windows; using System.Windows;
using Artemis.DAL;
using Artemis.Events;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Models.Interfaces; using Artemis.Models.Interfaces;
using Artemis.Profiles; using Artemis.Profiles;
@ -10,6 +12,8 @@ using Artemis.Profiles.Layers.Interfaces;
using Artemis.Profiles.Layers.Models; using Artemis.Profiles.Layers.Models;
using Artemis.Settings; using Artemis.Settings;
using Newtonsoft.Json; using Newtonsoft.Json;
using Ninject;
using Ninject.Extensions.Logging;
namespace Artemis.Models namespace Artemis.Models
{ {
@ -19,26 +23,41 @@ namespace Artemis.Models
protected DateTime LastTrace; protected DateTime LastTrace;
protected EffectModel(MainManager mainManager, EffectSettings settings, IDataModel dataModel) protected EffectModel(DeviceManager deviceManager, EffectSettings settings, IDataModel dataModel)
{ {
MainManager = mainManager; DeviceManager = deviceManager;
Settings = settings; Settings = settings;
DataModel = dataModel; DataModel = dataModel;
MainManager.EffectManager.EffectModels.Add(this); // If set, load the last profile from settings
if (!string.IsNullOrEmpty(Settings?.LastProfile))
Profile = ProfileProvider.GetProfile(DeviceManager.ActiveKeyboard, this, Settings.LastProfile);
DeviceManager.OnKeyboardChangedEvent += DeviceManagerOnOnKeyboardChangedEvent;
}
private void DeviceManagerOnOnKeyboardChangedEvent(object sender, KeyboardChangedEventArgs args)
{
if (!string.IsNullOrEmpty(Settings?.LastProfile))
Profile = ProfileProvider.GetProfile(DeviceManager.ActiveKeyboard, this, Settings.LastProfile);
} }
public bool Initialized { get; set; } public bool Initialized { get; set; }
public MainManager MainManager { get; set; } public DeviceManager DeviceManager { get; set; }
public EffectSettings Settings { get; set; } public EffectSettings Settings { get; set; }
public string Name { get; set; } public string Name { get; set; }
public int KeyboardScale { get; set; } = 4; public int KeyboardScale { get; set; } = 4;
// Used by profile system // Used by profile system
public IDataModel DataModel { get; set; } public IDataModel DataModel { get; set; }
public ProfileModel Profile { get; set; } public ProfileModel Profile { get; set; }
public abstract void Dispose(); [Inject]
public ILogger Logger { get; set; }
public virtual void Dispose()
{
Profile?.Deactivate();
}
// Called on creation // Called on creation
public abstract void Enable(); public abstract void Enable();
@ -54,7 +73,7 @@ namespace Artemis.Models
/// <param name="keyboardOnly"></param> /// <param name="keyboardOnly"></param>
public virtual void Render(RenderFrame frame, bool keyboardOnly) public virtual void Render(RenderFrame frame, bool keyboardOnly)
{ {
if (Profile == null || DataModel == null || MainManager.DeviceManager.ActiveKeyboard == null) if ((Profile == null) || (DataModel == null) || (DeviceManager.ActiveKeyboard == null))
return; return;
lock (DataModel) lock (DataModel)
@ -62,49 +81,53 @@ namespace Artemis.Models
// Get all enabled layers who's conditions are met // Get all enabled layers who's conditions are met
var renderLayers = GetRenderLayers(keyboardOnly); var renderLayers = GetRenderLayers(keyboardOnly);
// If the profile has no active LUA wrapper, create one
if (!string.IsNullOrEmpty(Profile.LuaScript))
Profile.Activate(DeviceManager.ActiveKeyboard);
// Render the keyboard layer-by-layer // Render the keyboard layer-by-layer
var keyboardRect = MainManager.DeviceManager.ActiveKeyboard.KeyboardRectangle(KeyboardScale); var keyboardRect = DeviceManager.ActiveKeyboard.KeyboardRectangle(KeyboardScale);
using (var g = Graphics.FromImage(frame.KeyboardBitmap)) using (var g = Graphics.FromImage(frame.KeyboardBitmap))
{ {
Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Keyboard), Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Keyboard),
DataModel, keyboardRect, false, true); DataModel, keyboardRect, false, true, "keyboard");
} }
// Render mice layer-by-layer // Render mice layer-by-layer
var devRec = new Rect(0, 0, 40, 40); var devRec = new Rect(0, 0, 40, 40);
using (var g = Graphics.FromImage(frame.MouseBitmap)) using (var g = Graphics.FromImage(frame.MouseBitmap))
{ {
Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Mouse), DataModel, Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Mouse), DataModel,
devRec, false, true); devRec, false, true, "mouse");
} }
// Render headsets layer-by-layer // Render headsets layer-by-layer
using (var g = Graphics.FromImage(frame.HeadsetBitmap)) using (var g = Graphics.FromImage(frame.HeadsetBitmap))
{ {
Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Headset), Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Headset),
DataModel, devRec, false, true); DataModel, devRec, false, true, "headset");
} }
// Render generic devices layer-by-layer // Render generic devices layer-by-layer
using (var g = Graphics.FromImage(frame.GenericBitmap)) using (var g = Graphics.FromImage(frame.GenericBitmap))
{ {
Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Generic), Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Generic),
DataModel, devRec, false, true); DataModel, devRec, false, true, "generic");
} }
// Render mousemats layer-by-layer // Render mousemats layer-by-layer
using (var g = Graphics.FromImage(frame.MousematBitmap)) using (var g = Graphics.FromImage(frame.MousematBitmap))
{ {
Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Mousemat), Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Mousemat),
DataModel, devRec, false, true); DataModel, devRec, false, true, "mousemat");
} }
// Trace debugging // Trace debugging
if (DateTime.Now.AddSeconds(-2) <= LastTrace) if (DateTime.Now.AddSeconds(-2) <= LastTrace || Logger == null)
return; return;
LastTrace = DateTime.Now; LastTrace = DateTime.Now;
MainManager.Logger.Trace("Effect datamodel as JSON: \r\n{0}", var dmJson = JsonConvert.SerializeObject(DataModel, Formatting.Indented);
JsonConvert.SerializeObject(DataModel, Formatting.Indented)); Logger.Trace("Effect datamodel as JSON: \r\n{0}", dmJson);
MainManager.Logger.Trace("Effect {0} has to render {1} layers", Name, renderLayers.Count); Logger.Trace("Effect {0} has to render {1} layers", Name, renderLayers.Count);
foreach (var renderLayer in renderLayers) foreach (var renderLayer in renderLayers)
MainManager.Logger.Trace("- Layer name: {0}, layer type: {1}", renderLayer.Name, Logger.Trace("- Layer name: {0}, layer type: {1}", renderLayer.Name, renderLayer.LayerType);
renderLayer.LayerType);
} }
} }

View File

@ -6,7 +6,7 @@ namespace Artemis.Models
{ {
public abstract class GameModel : EffectModel public abstract class GameModel : EffectModel
{ {
protected GameModel(MainManager mainManager, GameSettings settings, IDataModel dataModel): base(mainManager, settings, dataModel) protected GameModel(DeviceManager deviceManager, GameSettings settings, IDataModel dataModel): base(deviceManager, settings, dataModel)
{ {
// Override settings to the GameSettings type // Override settings to the GameSettings type
Settings = settings; Settings = settings;

View File

@ -8,7 +8,7 @@ namespace Artemis.Models
private bool _enabled; private bool _enabled;
public string ProcessName; public string ProcessName;
protected OverlayModel(MainManager mainManager, OverlaySettings settings) : base(mainManager, settings, null) protected OverlayModel(DeviceManager deviceManager, OverlaySettings settings) : base(deviceManager, settings, null)
{ {
Settings = settings; Settings = settings;
Enabled = settings.Enabled; Enabled = settings.Enabled;

View File

@ -1,12 +1,14 @@
using Artemis.Managers; using Artemis.Managers;
using Artemis.Models;
using Artemis.Modules.Effects.ProfilePreview; using Artemis.Modules.Effects.ProfilePreview;
using Artemis.ViewModels.Abstract; using Artemis.ViewModels.Abstract;
using Ninject;
namespace Artemis.Modules.Effects.AudioVisualizer namespace Artemis.Modules.Effects.AudioVisualizer
{ {
public sealed class AudioVisualizerViewModel : EffectViewModel public sealed class AudioVisualizerViewModel : EffectViewModel
{ {
public AudioVisualizerViewModel(MainManager main, ProfilePreviewModel model) : base(main, model) public AudioVisualizerViewModel(MainManager main, [Named("ProfilePreviewModel")] EffectModel model) : base(main, model)
{ {
DisplayName = "Audio Visualization / Key waves"; DisplayName = "Audio Visualization / Key waves";
} }

View File

@ -15,7 +15,7 @@ namespace Artemis.Modules.Effects.Bubbles
{ {
#region Constructors #region Constructors
public BubblesModel(MainManager mainManager) : base(mainManager, SettingsProvider.Load<BubblesSettings>(), null) public BubblesModel(DeviceManager deviceManager) : base(deviceManager, SettingsProvider.Load<BubblesSettings>(), null)
{ {
Name = "Bubbles"; Name = "Bubbles";
Initialized = false; Initialized = false;
@ -40,8 +40,7 @@ namespace Artemis.Modules.Effects.Bubbles
{ {
KeyboardScale = Settings.Smoothness; KeyboardScale = Settings.Smoothness;
var rect = MainManager.DeviceManager.ActiveKeyboard.KeyboardRectangle(KeyboardScale); var rect = DeviceManager.ActiveKeyboard.KeyboardRectangle(KeyboardScale);
var scaleFactor = Settings.Smoothness/25.0; var scaleFactor = Settings.Smoothness/25.0;
for (var i = 0; i < Settings.BubbleCount; i++) for (var i = 0; i < Settings.BubbleCount; i++)
@ -74,7 +73,7 @@ namespace Artemis.Modules.Effects.Bubbles
public override void Update() public override void Update()
{ {
var keyboardRectangle = MainManager.DeviceManager.ActiveKeyboard.KeyboardRectangle(KeyboardScale); var keyboardRectangle = DeviceManager.ActiveKeyboard.KeyboardRectangle(KeyboardScale);
foreach (var bubble in _bubbles) foreach (var bubble in _bubbles)
{ {
if (Settings.IsShiftColors) if (Settings.IsShiftColors)

View File

@ -1,6 +1,8 @@
using System.Windows.Media; using System.Windows.Media;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Models;
using Artemis.ViewModels.Abstract; using Artemis.ViewModels.Abstract;
using Ninject;
namespace Artemis.Modules.Effects.Bubbles namespace Artemis.Modules.Effects.Bubbles
{ {
@ -9,11 +11,11 @@ namespace Artemis.Modules.Effects.Bubbles
private readonly BubblesModel _model; private readonly BubblesModel _model;
private SolidColorBrush _bubbleColor; private SolidColorBrush _bubbleColor;
public BubblesViewModel(MainManager main, BubblesModel model) : base(main, model) public BubblesViewModel(MainManager main, [Named("BubblesModel")] EffectModel model) : base(main, model)
{ {
_model = model; _model = (BubblesModel) model;
DisplayName = "Bubbles"; DisplayName = "Bubbles";
BubbleColor = new SolidColorBrush(model.Settings.BubbleColor); BubbleColor = new SolidColorBrush(_model.Settings.BubbleColor);
} }
/// <summary> /// <summary>

View File

@ -7,14 +7,17 @@ using Artemis.Models;
using Artemis.Models.Interfaces; using Artemis.Models.Interfaces;
using Artemis.Profiles.Layers.Interfaces; using Artemis.Profiles.Layers.Interfaces;
using Artemis.Profiles.Layers.Models; using Artemis.Profiles.Layers.Models;
using Artemis.Profiles.Lua;
using Artemis.ViewModels.Profiles; using Artemis.ViewModels.Profiles;
using Castle.Components.DictionaryAdapter; using Castle.Components.DictionaryAdapter;
using MoonSharp.Interpreter;
namespace Artemis.Modules.Effects.ProfilePreview namespace Artemis.Modules.Effects.ProfilePreview
{ {
public class ProfilePreviewModel : EffectModel public class ProfilePreviewModel : EffectModel
{ {
public ProfilePreviewModel(MainManager mainManager) : base(mainManager, null, new ProfilePreviewDataModel()) public ProfilePreviewModel(DeviceManager deviceManager)
: base(deviceManager, null, new ProfilePreviewDataModel())
{ {
Name = "Profile Preview"; Name = "Profile Preview";
} }
@ -24,6 +27,7 @@ namespace Artemis.Modules.Effects.ProfilePreview
public override void Dispose() public override void Dispose()
{ {
Initialized = false; Initialized = false;
base.Dispose();
} }
public override void Enable() public override void Enable()
@ -42,7 +46,7 @@ namespace Artemis.Modules.Effects.ProfilePreview
public override void Render(RenderFrame frame, bool keyboardOnly) public override void Render(RenderFrame frame, bool keyboardOnly)
{ {
if (Profile == null || DataModel == null || MainManager.DeviceManager.ActiveKeyboard == null) if ((Profile == null) || (DataModel == null) || (DeviceManager.ActiveKeyboard == null))
return; return;
lock (DataModel) lock (DataModel)
@ -50,46 +54,47 @@ namespace Artemis.Modules.Effects.ProfilePreview
// Get all enabled layers who's conditions are met // Get all enabled layers who's conditions are met
var renderLayers = GetRenderLayers(keyboardOnly); var renderLayers = GetRenderLayers(keyboardOnly);
// If the profile has no active LUA wrapper, create one
if (!Equals(LuaWrapper.ProfileModel, Profile))
Profile.Activate(DeviceManager.ActiveKeyboard);
// Render the keyboard layer-by-layer // Render the keyboard layer-by-layer
var keyboardRect = MainManager.DeviceManager.ActiveKeyboard.KeyboardRectangle(KeyboardScale); var keyboardRect = DeviceManager.ActiveKeyboard.KeyboardRectangle(KeyboardScale);
using (var g = Graphics.FromImage(frame.KeyboardBitmap)) using (var g = Graphics.FromImage(frame.KeyboardBitmap))
{ {
Profile.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Keyboard), Profile.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Keyboard),
DataModel, DataModel, keyboardRect, true, true, "keyboard");
keyboardRect, true, true);
} }
// Render mice layer-by-layer // Render mice layer-by-layer
var devRec = new Rect(0, 0, 40, 40); var devRec = new Rect(0, 0, 40, 40);
using (var g = Graphics.FromImage(frame.MouseBitmap)) using (var g = Graphics.FromImage(frame.MouseBitmap))
{ {
Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Mouse), DataModel, Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Mouse), DataModel,
devRec, true, true); devRec, true, true, "mouse");
} }
// Render headsets layer-by-layer // Render headsets layer-by-layer
using (var g = Graphics.FromImage(frame.HeadsetBitmap)) using (var g = Graphics.FromImage(frame.HeadsetBitmap))
{ {
Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Headset), Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Headset),
DataModel, DataModel, devRec, true, true, "headset");
devRec, true, true);
} }
// Render generic devices layer-by-layer // Render generic devices layer-by-layer
using (var g = Graphics.FromImage(frame.GenericBitmap)) using (var g = Graphics.FromImage(frame.GenericBitmap))
{ {
Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Generic), Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Generic),
DataModel, DataModel, devRec, true, true, "generic");
devRec, true, true);
} }
// Render mousemats layer-by-layer // Render mousemats layer-by-layer
using (var g = Graphics.FromImage(frame.MousematBitmap)) using (var g = Graphics.FromImage(frame.MousematBitmap))
{ {
Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Mousemat), Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Mousemat),
DataModel, DataModel, devRec, true, true, "mousemat");
devRec, true, true);
} }
} }
} }
} }
[MoonSharpUserData]
public class ProfilePreviewDataModel : IDataModel public class ProfilePreviewDataModel : IDataModel
{ {
} }

View File

@ -1,12 +1,15 @@
using Artemis.Models.Interfaces; using Artemis.Models.Interfaces;
using MoonSharp.Interpreter;
namespace Artemis.Modules.Effects.WindowsProfile namespace Artemis.Modules.Effects.WindowsProfile
{ {
[MoonSharpUserData]
public class WindowsProfileDataModel : IDataModel public class WindowsProfileDataModel : IDataModel
{ {
public WindowsProfileDataModel() public WindowsProfileDataModel()
{ {
Spotify = new Spotify(); Spotify = new Spotify();
GooglePlayMusic = new GooglePlayMusic();
Cpu = new CpuDataModel(); Cpu = new CpuDataModel();
Performance = new PerformanceDataModel(); Performance = new PerformanceDataModel();
CurrentTime = new CurrentTime(); CurrentTime = new CurrentTime();
@ -15,9 +18,11 @@ namespace Artemis.Modules.Effects.WindowsProfile
public CpuDataModel Cpu { get; set; } public CpuDataModel Cpu { get; set; }
public PerformanceDataModel Performance { get; set; } public PerformanceDataModel Performance { get; set; }
public Spotify Spotify { get; set; } public Spotify Spotify { get; set; }
public GooglePlayMusic GooglePlayMusic { get; set; }
public CurrentTime CurrentTime { get; set; } public CurrentTime CurrentTime { get; set; }
} }
[MoonSharpUserData]
public class CurrentTime public class CurrentTime
{ {
public int Hours24 { get; set; } public int Hours24 { get; set; }
@ -26,6 +31,7 @@ namespace Artemis.Modules.Effects.WindowsProfile
public int Seconds { get; set; } public int Seconds { get; set; }
} }
[MoonSharpUserData]
public class CpuDataModel public class CpuDataModel
{ {
public int TotalUsage { get; set; } public int TotalUsage { get; set; }
@ -39,11 +45,13 @@ namespace Artemis.Modules.Effects.WindowsProfile
public int Core8Usage { get; set; } public int Core8Usage { get; set; }
} }
[MoonSharpUserData]
public class PerformanceDataModel public class PerformanceDataModel
{ {
public int RAMUsage { get; set; } public int RAMUsage { get; set; }
} }
[MoonSharpUserData]
public class Spotify public class Spotify
{ {
public bool Running { get; set; } public bool Running { get; set; }
@ -57,4 +65,39 @@ namespace Artemis.Modules.Effects.WindowsProfile
public bool Playing { get; set; } public bool Playing { get; set; }
public int SongLength { get; set; } public int SongLength { get; set; }
} }
[MoonSharpUserData]
public class GooglePlayMusic
{
public bool playing { get; set; }
public Song song { get; set; }
public Rating rating { get; set; }
public Time time { get; set; }
public string shuffle { get; set; }
public string repeat { get; set; }
public int volume { get; set; }
}
[MoonSharpUserData]
public class Song
{
public string title { get; set; }
public string artist { get; set; }
public string album { get; set; }
public string albumArt { get; set; }
}
[MoonSharpUserData]
public class Rating
{
public bool liked { get; set; }
public bool disliked { get; set; }
}
public class Time
{
public int current { get; set; }
public int total { get; set; }
}
} }

View File

@ -1,36 +1,39 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Artemis.DAL; using Artemis.DAL;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Models; using Artemis.Models;
using Artemis.Profiles.Layers.Models; using Artemis.Profiles.Layers.Models;
using Ninject.Extensions.Logging; using Newtonsoft.Json;
using SpotifyAPI.Local; using SpotifyAPI.Local;
namespace Artemis.Modules.Effects.WindowsProfile namespace Artemis.Modules.Effects.WindowsProfile
{ {
public class WindowsProfileModel : EffectModel public class WindowsProfileModel : EffectModel
{ {
private readonly ILogger _logger;
private List<PerformanceCounter> _cores; private List<PerformanceCounter> _cores;
private int _cpuFrames; private int _cpuFrames;
private DateTime _lastMusicUpdate;
private PerformanceCounter _overallCpu; private PerformanceCounter _overallCpu;
private SpotifyLocalAPI _spotify; private SpotifyLocalAPI _spotify;
private bool _spotifySetupBusy; private bool _spotifySetupBusy;
public WindowsProfileModel(ILogger logger, MainManager mainManager) public WindowsProfileModel(DeviceManager deviceManager)
: base(mainManager, SettingsProvider.Load<WindowsProfileSettings>(), new WindowsProfileDataModel()) : base(deviceManager, SettingsProvider.Load<WindowsProfileSettings>(), new WindowsProfileDataModel())
{ {
_logger = logger; _lastMusicUpdate = DateTime.Now;
Name = "WindowsProfile"; Name = "WindowsProfile";
} }
public override void Dispose() public override void Dispose()
{ {
Initialized = false; Initialized = false;
base.Dispose();
} }
public override void Enable() public override void Enable()
@ -45,7 +48,7 @@ namespace Artemis.Modules.Effects.WindowsProfile
{ {
var dataModel = (WindowsProfileDataModel) DataModel; var dataModel = (WindowsProfileDataModel) DataModel;
UpdateCpu(dataModel); UpdateCpu(dataModel);
UpdateSpotify(dataModel); UpdateMusicPlayers(dataModel);
UpdateDay(dataModel); UpdateDay(dataModel);
} }
@ -79,7 +82,7 @@ namespace Artemis.Modules.Effects.WindowsProfile
} }
catch (InvalidOperationException) catch (InvalidOperationException)
{ {
_logger.Warn("Failed to setup CPU information, try running \"lodctr /R\" as administrator."); Logger?.Warn("Failed to setup CPU information, try running \"lodctr /R\" as administrator.");
} }
} }
@ -155,7 +158,7 @@ namespace Artemis.Modules.Effects.WindowsProfile
#endregion #endregion
#region Spotify #region Music
public void SetupSpotify() public void SetupSpotify()
{ {
@ -163,10 +166,7 @@ namespace Artemis.Modules.Effects.WindowsProfile
return; return;
_spotifySetupBusy = true; _spotifySetupBusy = true;
_spotify = new SpotifyLocalAPI {ListenForEvents = true}; _spotify = new SpotifyLocalAPI();
_spotify.OnPlayStateChange += UpdateSpotifyPlayState;
_spotify.OnTrackChange += UpdateSpotifyTrack;
_spotify.OnTrackTimeChange += UpdateSpotifyTrackTime;
// Connecting can sometimes use a little bit more conviction // Connecting can sometimes use a little bit more conviction
Task.Factory.StartNew(() => Task.Factory.StartNew(() =>
@ -184,33 +184,52 @@ namespace Artemis.Modules.Effects.WindowsProfile
}); });
} }
public void UpdateSpotify(WindowsProfileDataModel dataModel) public void UpdateMusicPlayers(WindowsProfileDataModel dataModel)
{ {
// This is quite resource hungry so only update it once every two seconds
if (DateTime.Now - _lastMusicUpdate < TimeSpan.FromSeconds(2))
return;
_lastMusicUpdate = DateTime.Now;
UpdateSpotify(dataModel);
UpdateGooglePlayMusic(dataModel);
}
private void UpdateSpotify(WindowsProfileDataModel dataModel)
{
// Spotify
if (!dataModel.Spotify.Running && SpotifyLocalAPI.IsSpotifyRunning()) if (!dataModel.Spotify.Running && SpotifyLocalAPI.IsSpotifyRunning())
SetupSpotify(); SetupSpotify();
var status = _spotify.GetStatus();
if (status == null)
return;
dataModel.Spotify.Playing = status.Playing;
dataModel.Spotify.Running = SpotifyLocalAPI.IsSpotifyRunning(); dataModel.Spotify.Running = SpotifyLocalAPI.IsSpotifyRunning();
}
private void UpdateSpotifyPlayState(object sender, PlayStateEventArgs e) if (status.Track != null)
{ {
((WindowsProfileDataModel) DataModel).Spotify.Playing = e.Playing; dataModel.Spotify.Artist = status.Track.ArtistResource?.Name;
} dataModel.Spotify.SongName = status.Track.TrackResource?.Name;
dataModel.Spotify.Album = status.Track.AlbumResource?.Name;
dataModel.Spotify.SongLength = status.Track.Length;
}
private void UpdateSpotifyTrack(object sender, TrackChangeEventArgs e)
{
var dataModel = (WindowsProfileDataModel) DataModel;
dataModel.Spotify.Artist = e.NewTrack.ArtistResource?.Name;
dataModel.Spotify.SongName = e.NewTrack.TrackResource?.Name;
dataModel.Spotify.Album = e.NewTrack.AlbumResource?.Name;
dataModel.Spotify.SongLength = e.NewTrack.Length;
}
private void UpdateSpotifyTrackTime(object sender, TrackTimeChangeEventArgs e)
{
var dataModel = (WindowsProfileDataModel) DataModel;
if (dataModel.Spotify.SongLength > 0) if (dataModel.Spotify.SongLength > 0)
dataModel.Spotify.SongPercentCompleted = (int) (e.TrackTime/dataModel.Spotify.SongLength*100.0); dataModel.Spotify.SongPercentCompleted =
(int) (status.PlayingPosition/dataModel.Spotify.SongLength*100.0);
}
private void UpdateGooglePlayMusic(WindowsProfileDataModel dataModel)
{
// Google Play Music
var appData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
var json = appData + @"\Google Play Music Desktop Player\json_store\playback.json";
if (!File.Exists(json))
return;
dataModel.GooglePlayMusic = JsonConvert.DeserializeObject<GooglePlayMusic>(File.ReadAllText(json));
} }
#endregion #endregion

View File

@ -1,48 +1,62 @@
using System.ComponentModel; using System.ComponentModel;
using Artemis.InjectionFactories;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Models;
using Artemis.Modules.Effects.ProfilePreview; using Artemis.Modules.Effects.ProfilePreview;
using Artemis.ViewModels.Abstract; using Artemis.ViewModels.Abstract;
using Artemis.ViewModels.Profiles; using Artemis.ViewModels.Profiles;
using Ninject;
using Ninject.Parameters;
namespace Artemis.Modules.Effects.WindowsProfile namespace Artemis.Modules.Effects.WindowsProfile
{ {
// TODO: This effect is a hybrid between a regular effect and a game, may want to clean this up // TODO: This effect is a hybrid between a regular effect and a game, may want to clean this up
public sealed class WindowsProfileViewModel : EffectViewModel public sealed class WindowsProfileViewModel : EffectViewModel
{ {
public WindowsProfileViewModel(MainManager main, IProfileEditorVmFactory pFactory, public WindowsProfileViewModel(MainManager main, IKernel kernel, ProfilePreviewModel profilePreviewModel,
ProfilePreviewModel profilePreviewModel, WindowsProfileModel model) : base(main, model) [Named("WindowsProfileModel")] EffectModel model) : base(main, model)
{ {
DisplayName = "Windows Profile"; DisplayName = "Windows Profile";
PFactory = pFactory;
ProfilePreviewModel = profilePreviewModel; ProfilePreviewModel = profilePreviewModel;
EffectSettings = ((WindowsProfileModel) EffectModel).Settings; EffectSettings = ((WindowsProfileModel) EffectModel).Settings;
ProfileEditor = PFactory.CreateProfileEditorVm(main, (WindowsProfileModel) EffectModel,
((WindowsProfileSettings) EffectSettings).LastProfile); IParameter[] args =
ProfilePreviewModel.Profile = ProfileEditor.SelectedProfile; {
new ConstructorArgument("mainManager", main),
new ConstructorArgument("gameModel", (WindowsProfileModel) EffectModel),
new ConstructorArgument("lastProfile", ((WindowsProfileSettings) EffectSettings).LastProfile)
};
ProfileEditor = kernel.Get<ProfileEditorViewModel>(args);
ProfileEditor.PropertyChanged += ProfileUpdater; ProfileEditor.PropertyChanged += ProfileUpdater;
MainManager.EffectManager.EffectModels.Add(EffectModel);
EffectModel.Profile = ProfileEditor.SelectedProfile;
ProfilePreviewModel.Profile = ProfileEditor.SelectedProfile;
} }
public ProfileEditorViewModel ProfileEditor { get; set; } public ProfileEditorViewModel ProfileEditor { get; set; }
public IProfileEditorVmFactory PFactory { get; set; }
public ProfilePreviewModel ProfilePreviewModel { get; set; } public ProfilePreviewModel ProfilePreviewModel { get; set; }
private void ProfileUpdater(object sender, PropertyChangedEventArgs e) private void ProfileUpdater(object sender, PropertyChangedEventArgs e)
{ {
if (e.PropertyName != "SelectedProfile" && IsActive) if ((e.PropertyName != "SelectedProfile") && IsActive)
return; return;
EffectModel.Profile = ProfileEditor.SelectedProfile; EffectModel.Profile = ProfileEditor.SelectedProfile;
ProfilePreviewModel.Profile = ProfileEditor.SelectedProfile; ProfilePreviewModel.Profile = ProfileEditor.SelectedProfile;
if (e.PropertyName != "SelectedProfile" || !ProfileEditor.ProfileViewModel.Activated || if ((e.PropertyName != "SelectedProfile") || !ProfileEditor.ProfileViewModel.Activated ||
ProfileEditor.ProfileViewModel.SelectedProfile == null) (ProfileEditor.ProfileViewModel.SelectedProfile == null))
return; return;
((WindowsProfileSettings) EffectSettings).LastProfile = ProfileEditor.ProfileViewModel.SelectedProfile.Name; ((WindowsProfileSettings) EffectSettings).LastProfile = ProfileEditor.ProfileViewModel.SelectedProfile.Name;
EffectSettings.Save(); EffectSettings.Save();
} }
public override void SaveSettings()
{
ProfileEditor.SaveSelectedProfile();
base.SaveSettings();
}
protected override void OnActivate() protected override void OnActivate()
{ {
base.OnActivate(); base.OnActivate();

View File

@ -1,8 +1,10 @@
using Artemis.Models.Interfaces; using Artemis.Models.Interfaces;
using MoonSharp.Interpreter;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace Artemis.Modules.Games.CounterStrike namespace Artemis.Modules.Games.CounterStrike
{ {
[MoonSharpUserData]
public class CounterStrikeDataModel : IDataModel public class CounterStrikeDataModel : IDataModel
{ {
public Provider provider { get; set; } public Provider provider { get; set; }
@ -12,6 +14,7 @@ namespace Artemis.Modules.Games.CounterStrike
public Previously previously { get; set; } public Previously previously { get; set; }
} }
[MoonSharpUserData]
public class Provider public class Provider
{ {
public string name { get; set; } public string name { get; set; }
@ -21,16 +24,19 @@ namespace Artemis.Modules.Games.CounterStrike
public int timestamp { get; set; } public int timestamp { get; set; }
} }
[MoonSharpUserData]
public class TeamCt public class TeamCt
{ {
public int score { get; set; } public int score { get; set; }
} }
[MoonSharpUserData]
public class TeamT public class TeamT
{ {
public int score { get; set; } public int score { get; set; }
} }
[MoonSharpUserData]
public class Map public class Map
{ {
public string mode { get; set; } public string mode { get; set; }
@ -41,11 +47,13 @@ namespace Artemis.Modules.Games.CounterStrike
public TeamT team_t { get; set; } public TeamT team_t { get; set; }
} }
[MoonSharpUserData]
public class Round public class Round
{ {
public string phase { get; set; } public string phase { get; set; }
} }
[MoonSharpUserData]
public class State public class State
{ {
[JsonIgnore] [JsonIgnore]
@ -63,7 +71,7 @@ namespace Artemis.Modules.Games.CounterStrike
public int round_killhs { get; set; } public int round_killhs { get; set; }
} }
[MoonSharpUserData]
public class Weapon public class Weapon
{ {
public string name { get; set; } public string name { get; set; }
@ -75,6 +83,7 @@ namespace Artemis.Modules.Games.CounterStrike
public string state { get; set; } public string state { get; set; }
} }
[MoonSharpUserData]
public class Weapons public class Weapons
{ {
public Weapon active_weapon { get; set; } public Weapon active_weapon { get; set; }
@ -83,6 +92,7 @@ namespace Artemis.Modules.Games.CounterStrike
public Weapon weapon_2 { get; set; } public Weapon weapon_2 { get; set; }
} }
[MoonSharpUserData]
public class MatchStats public class MatchStats
{ {
public int kills { get; set; } public int kills { get; set; }
@ -92,6 +102,7 @@ namespace Artemis.Modules.Games.CounterStrike
public int score { get; set; } public int score { get; set; }
} }
[MoonSharpUserData]
public class Player public class Player
{ {
public string steamid { get; set; } public string steamid { get; set; }
@ -103,11 +114,13 @@ namespace Artemis.Modules.Games.CounterStrike
public MatchStats match_stats { get; set; } public MatchStats match_stats { get; set; }
} }
[MoonSharpUserData]
public class Round2 public class Round2
{ {
public string phase { get; set; } public string phase { get; set; }
} }
[MoonSharpUserData]
public class Previously public class Previously
{ {
public Round2 round { get; set; } public Round2 round { get; set; }

View File

@ -1,47 +1,57 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using Artemis.DAL; using Artemis.DAL;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Models; using Artemis.Models;
using Artemis.Profiles.Layers.Models; using Artemis.Profiles.Layers.Models;
using Artemis.Properties;
using Artemis.Services;
using Artemis.Utilities;
using Artemis.Utilities.GameState; using Artemis.Utilities.GameState;
using Newtonsoft.Json; using Newtonsoft.Json;
using Ninject.Extensions.Logging;
namespace Artemis.Modules.Games.CounterStrike namespace Artemis.Modules.Games.CounterStrike
{ {
public class CounterStrikeModel : GameModel public class CounterStrikeModel : GameModel
{ {
private readonly MetroDialogService _dialogService;
private readonly GameStateWebServer _gameStateWebServer;
private DateTime _lastHeadshot; private DateTime _lastHeadshot;
private int _lastHeadshots; private int _lastHeadshots;
private DateTime _lastKill; private DateTime _lastKill;
private int _lastKills; private int _lastKills;
public CounterStrikeModel(MainManager mainManager) public CounterStrikeModel(DeviceManager deviceManager, GameStateWebServer gameStateWebServer,
: base(mainManager, SettingsProvider.Load<CounterStrikeSettings>(), new CounterStrikeDataModel()) MetroDialogService dialogService)
: base(deviceManager, SettingsProvider.Load<CounterStrikeSettings>(), new CounterStrikeDataModel())
{ {
_gameStateWebServer = gameStateWebServer;
_dialogService = dialogService;
Name = "CounterStrike"; Name = "CounterStrike";
ProcessName = "csgo"; ProcessName = "csgo";
Scale = 4; Scale = 4;
Enabled = Settings.Enabled; Enabled = Settings.Enabled;
Initialized = false; Initialized = false;
FindGameDir();
PlaceConfigFile();
} }
public ILogger Logger { get; set; }
public int Scale { get; set; } public int Scale { get; set; }
public override void Dispose() public override void Dispose()
{ {
Initialized = false; Initialized = false;
MainManager.GameStateWebServer.GameDataReceived -= HandleGameData; _gameStateWebServer.GameDataReceived -= HandleGameData;
base.Dispose();
} }
public override void Enable() public override void Enable()
{ {
Initialized = false; _gameStateWebServer.GameDataReceived += HandleGameData;
MainManager.GameStateWebServer.GameDataReceived += HandleGameData;
Initialized = true; Initialized = true;
} }
@ -89,6 +99,42 @@ namespace Artemis.Modules.Games.CounterStrike
DataModel = dm; DataModel = dm;
} }
public void FindGameDir()
{
var gameSettings = (CounterStrikeSettings) Settings;
// If already propertly set up, don't do anything
if ((gameSettings.GameDirectory != null) && File.Exists(gameSettings.GameDirectory + "csgo.exe") &&
File.Exists(gameSettings.GameDirectory + "/csgo/cfg/gamestate_integration_artemis.cfg"))
return;
var dir = GeneralHelpers.FindSteamGame(@"\Counter-Strike Global Offensive\csgo.exe");
gameSettings.GameDirectory = dir ?? string.Empty;
gameSettings.Save();
}
public void PlaceConfigFile()
{
var gameSettings = (CounterStrikeSettings) Settings;
if (gameSettings.GameDirectory == string.Empty)
return;
var path = gameSettings.GameDirectory;
if (Directory.Exists(path + "/csgo/cfg"))
{
var cfgFile = Resources.csgoGamestateConfiguration.Replace("{{port}}",
_gameStateWebServer.Port.ToString());
File.WriteAllText(path + "/csgo/cfg/gamestate_integration_artemis.cfg", cfgFile);
return;
}
_dialogService.ShowErrorMessageBox("Please select a valid CS:GO directory\n\n" +
@"By default CS:GO is in \SteamApps\common\Counter-Strike Global Offensive");
gameSettings.GameDirectory = string.Empty;
gameSettings.Save();
}
public void HandleGameData(object sender, GameDataReceivedEventArgs e) public void HandleGameData(object sender, GameDataReceivedEventArgs e)
{ {
var jsonString = e.Json.ToString(); var jsonString = e.Json.ToString();
@ -111,6 +157,7 @@ namespace Artemis.Modules.Games.CounterStrike
} }
} }
public override List<LayerModel> GetRenderLayers(bool keyboardOnly) public override List<LayerModel> GetRenderLayers(bool keyboardOnly)
{ {
return Profile.GetRenderLayers(DataModel, keyboardOnly); return Profile.GetRenderLayers(DataModel, keyboardOnly);

View File

@ -1,72 +1,22 @@
using System.IO; using Artemis.Managers;
using System.Windows.Forms; using Artemis.Models;
using Artemis.InjectionFactories;
using Artemis.Managers;
using Artemis.Properties;
using Artemis.Utilities;
using Artemis.ViewModels.Abstract; using Artemis.ViewModels.Abstract;
using Ninject;
namespace Artemis.Modules.Games.CounterStrike namespace Artemis.Modules.Games.CounterStrike
{ {
public sealed class CounterStrikeViewModel : GameViewModel public sealed class CounterStrikeViewModel : GameViewModel
{ {
public CounterStrikeViewModel(MainManager main, IProfileEditorVmFactory pFactory, CounterStrikeModel model) public CounterStrikeViewModel(MainManager main, IKernel kernel, [Named("CounterStrikeModel")] GameModel model)
: base(main, model, pFactory) : base(main, model, kernel)
{ {
DisplayName = "CS:GO"; DisplayName = "CS:GO";
FindGameDir();
PlaceConfigFile();
}
public void FindGameDir()
{
var gameSettings = (CounterStrikeSettings) GameSettings;
// If already propertly set up, don't do anything
if ((gameSettings.GameDirectory != null) && File.Exists(gameSettings.GameDirectory + "csgo.exe") &&
File.Exists(gameSettings.GameDirectory + "/csgo/cfg/gamestate_integration_artemis.cfg"))
return;
var dir = GeneralHelpers.FindSteamGame(@"\Counter-Strike Global Offensive\csgo.exe");
gameSettings.GameDirectory = dir ?? string.Empty;
gameSettings.Save();
} }
public void BrowseDirectory() public void BrowseDirectory()
{ {
var dialog = new FolderBrowserDialog {SelectedPath = ((CounterStrikeSettings) GameSettings).GameDirectory}; ((CounterStrikeModel) GameModel).PlaceConfigFile();
var result = dialog.ShowDialog();
if (result != DialogResult.OK)
return;
((CounterStrikeSettings) GameSettings).GameDirectory = Path.GetDirectoryName(dialog.SelectedPath);
NotifyOfPropertyChange(() => GameSettings); NotifyOfPropertyChange(() => GameSettings);
GameSettings.Save();
PlaceConfigFile();
}
public void PlaceConfigFile()
{
if (((CounterStrikeSettings) GameSettings).GameDirectory == string.Empty)
return;
var path = ((CounterStrikeSettings) GameSettings).GameDirectory;
if (Directory.Exists(path + "/csgo/cfg"))
{
var cfgFile = Resources.csgoGamestateConfiguration.Replace("{{port}}",
MainManager.GameStateWebServer.Port.ToString());
File.WriteAllText(path + "/csgo/cfg/gamestate_integration_artemis.cfg", cfgFile);
return;
}
DialogService.ShowErrorMessageBox("Please select a valid CS:GO directory\n\n" +
@"By default CS:GO is in \SteamApps\common\Counter-Strike Global Offensive");
((CounterStrikeSettings) GameSettings).GameDirectory = string.Empty;
NotifyOfPropertyChange(() => GameSettings);
GameSettings.Save();
} }
} }
} }

View File

@ -1,7 +1,9 @@
using Artemis.Models.Interfaces; using Artemis.Models.Interfaces;
using MoonSharp.Interpreter;
namespace Artemis.Modules.Games.Dota2 namespace Artemis.Modules.Games.Dota2
{ {
[MoonSharpUserData]
public class Dota2DataModel : IDataModel public class Dota2DataModel : IDataModel
{ {
public Provider provider { get; set; } public Provider provider { get; set; }
@ -13,6 +15,7 @@ namespace Artemis.Modules.Games.Dota2
public Previously previously { get; set; } public Previously previously { get; set; }
} }
[MoonSharpUserData]
public class Provider public class Provider
{ {
public string name { get; set; } public string name { get; set; }
@ -21,6 +24,7 @@ namespace Artemis.Modules.Games.Dota2
public int timestamp { get; set; } public int timestamp { get; set; }
} }
[MoonSharpUserData]
public class Map public class Map
{ {
public int dayCyclePercentage; public int dayCyclePercentage;
@ -36,6 +40,7 @@ namespace Artemis.Modules.Games.Dota2
public int ward_purchase_cooldown { get; set; } public int ward_purchase_cooldown { get; set; }
} }
[MoonSharpUserData]
public class Player public class Player
{ {
public string steamid { get; set; } public string steamid { get; set; }
@ -55,6 +60,7 @@ namespace Artemis.Modules.Games.Dota2
public int xpm { get; set; } public int xpm { get; set; }
} }
[MoonSharpUserData]
public class Hero public class Hero
{ {
public int id { get; set; } public int id { get; set; }
@ -80,6 +86,7 @@ namespace Artemis.Modules.Games.Dota2
public bool has_debuff { get; set; } public bool has_debuff { get; set; }
} }
[MoonSharpUserData]
public class Abilities public class Abilities
{ {
public Ability0 ability0 { get; set; } public Ability0 ability0 { get; set; }
@ -90,6 +97,7 @@ namespace Artemis.Modules.Games.Dota2
public Attributes attributes { get; set; } public Attributes attributes { get; set; }
} }
[MoonSharpUserData]
public class Ability0 public class Ability0
{ {
public string name { get; set; } public string name { get; set; }
@ -101,6 +109,7 @@ namespace Artemis.Modules.Games.Dota2
public bool ultimate { get; set; } public bool ultimate { get; set; }
} }
[MoonSharpUserData]
public class Ability1 public class Ability1
{ {
public string name { get; set; } public string name { get; set; }
@ -112,6 +121,7 @@ namespace Artemis.Modules.Games.Dota2
public bool ultimate { get; set; } public bool ultimate { get; set; }
} }
[MoonSharpUserData]
public class Ability2 public class Ability2
{ {
public string name { get; set; } public string name { get; set; }
@ -123,6 +133,7 @@ namespace Artemis.Modules.Games.Dota2
public bool ultimate { get; set; } public bool ultimate { get; set; }
} }
[MoonSharpUserData]
public class Ability3 public class Ability3
{ {
public string name { get; set; } public string name { get; set; }
@ -134,11 +145,13 @@ namespace Artemis.Modules.Games.Dota2
public bool ultimate { get; set; } public bool ultimate { get; set; }
} }
[MoonSharpUserData]
public class Attributes public class Attributes
{ {
public int level { get; set; } public int level { get; set; }
} }
[MoonSharpUserData]
public class Items public class Items
{ {
public Slot0 slot0 { get; set; } public Slot0 slot0 { get; set; }
@ -155,71 +168,85 @@ namespace Artemis.Modules.Games.Dota2
public Stash5 stash5 { get; set; } public Stash5 stash5 { get; set; }
} }
[MoonSharpUserData]
public class Slot0 public class Slot0
{ {
public string name { get; set; } public string name { get; set; }
} }
[MoonSharpUserData]
public class Slot1 public class Slot1
{ {
public string name { get; set; } public string name { get; set; }
} }
[MoonSharpUserData]
public class Slot2 public class Slot2
{ {
public string name { get; set; } public string name { get; set; }
} }
[MoonSharpUserData]
public class Slot3 public class Slot3
{ {
public string name { get; set; } public string name { get; set; }
} }
[MoonSharpUserData]
public class Slot4 public class Slot4
{ {
public string name { get; set; } public string name { get; set; }
} }
[MoonSharpUserData]
public class Slot5 public class Slot5
{ {
public string name { get; set; } public string name { get; set; }
} }
[MoonSharpUserData]
public class Stash0 public class Stash0
{ {
public string name { get; set; } public string name { get; set; }
} }
[MoonSharpUserData]
public class Stash1 public class Stash1
{ {
public string name { get; set; } public string name { get; set; }
} }
[MoonSharpUserData]
public class Stash2 public class Stash2
{ {
public string name { get; set; } public string name { get; set; }
} }
[MoonSharpUserData]
public class Stash3 public class Stash3
{ {
public string name { get; set; } public string name { get; set; }
} }
[MoonSharpUserData]
public class Stash4 public class Stash4
{ {
public string name { get; set; } public string name { get; set; }
} }
[MoonSharpUserData]
public class Stash5 public class Stash5
{ {
public string name { get; set; } public string name { get; set; }
} }
[MoonSharpUserData]
public class Previously public class Previously
{ {
public Player1 player { get; set; } public Player1 player { get; set; }
} }
[MoonSharpUserData]
public class Player1 public class Player1
{ {
public int gold { get; set; } public int gold { get; set; }

View File

@ -1,8 +1,12 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using Artemis.DAL; using Artemis.DAL;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Models; using Artemis.Models;
using Artemis.Profiles.Layers.Models; using Artemis.Profiles.Layers.Models;
using Artemis.Properties;
using Artemis.Services;
using Artemis.Utilities;
using Artemis.Utilities.GameState; using Artemis.Utilities.GameState;
using Newtonsoft.Json; using Newtonsoft.Json;
@ -10,14 +14,24 @@ namespace Artemis.Modules.Games.Dota2
{ {
public class Dota2Model : GameModel public class Dota2Model : GameModel
{ {
public Dota2Model(MainManager mainManager) private readonly MetroDialogService _dialogService;
: base(mainManager, SettingsProvider.Load<Dota2Settings>(), new Dota2DataModel()) private readonly GameStateWebServer _gameStateWebServer;
public Dota2Model(DeviceManager deviceManager, GameStateWebServer gameStateWebServer,
MetroDialogService dialogService)
: base(deviceManager, SettingsProvider.Load<Dota2Settings>(), new Dota2DataModel())
{ {
_gameStateWebServer = gameStateWebServer;
_dialogService = dialogService;
Name = "Dota2"; Name = "Dota2";
ProcessName = "dota2"; ProcessName = "dota2";
Enabled = Settings.Enabled; Enabled = Settings.Enabled;
Initialized = false; Initialized = false;
Scale = 4; Scale = 4;
FindGameDir();
PlaceConfigFile();
} }
public int Scale { get; set; } public int Scale { get; set; }
@ -25,14 +39,13 @@ namespace Artemis.Modules.Games.Dota2
public override void Dispose() public override void Dispose()
{ {
Initialized = false; Initialized = false;
MainManager.GameStateWebServer.GameDataReceived -= HandleGameData; _gameStateWebServer.GameDataReceived -= HandleGameData;
base.Dispose();
} }
public override void Enable() public override void Enable()
{ {
Initialized = false; _gameStateWebServer.GameDataReceived += HandleGameData;
MainManager.GameStateWebServer.GameDataReceived += HandleGameData;
Initialized = true; Initialized = true;
} }
@ -41,6 +54,55 @@ namespace Artemis.Modules.Games.Dota2
UpdateDay(); UpdateDay();
} }
public void FindGameDir()
{
var gameSettings = (Dota2Settings) Settings;
// If already propertly set up, don't do anything
if ((gameSettings.GameDirectory != null) && File.Exists(gameSettings.GameDirectory + "csgo.exe") &&
File.Exists(gameSettings.GameDirectory + "/csgo/cfg/gamestate_integration_artemis.cfg"))
return;
var dir = GeneralHelpers.FindSteamGame(@"\dota 2 beta\game\bin\win32\dota2.exe");
// Remove subdirectories where they stuck the executable
dir = dir?.Substring(0, dir.Length - 15);
gameSettings.GameDirectory = dir ?? string.Empty;
gameSettings.Save();
}
public void PlaceConfigFile()
{
var gameSettings = (Dota2Settings) Settings;
if (gameSettings.GameDirectory == string.Empty)
return;
if (Directory.Exists(gameSettings.GameDirectory + "/game/dota/cfg"))
{
var cfgFile = Resources.dotaGamestateConfiguration.Replace("{{port}}",
_gameStateWebServer.Port.ToString());
try
{
File.WriteAllText(
gameSettings.GameDirectory +
"/game/dota/cfg/gamestate_integration/gamestate_integration_artemis.cfg", cfgFile);
}
catch (DirectoryNotFoundException)
{
Directory.CreateDirectory(gameSettings.GameDirectory + "/game/dota/cfg/gamestate_integration/");
File.WriteAllText(
gameSettings.GameDirectory +
"/game/dota/cfg/gamestate_integration/gamestate_integration_artemis.cfg",
cfgFile);
}
return;
}
_dialogService.ShowErrorMessageBox("Please select a valid Dota 2 directory\n\n" +
@"By default Dota 2 is in \SteamApps\common\dota 2 beta");
gameSettings.GameDirectory = string.Empty;
gameSettings.Save();
}
private void UpdateDay() private void UpdateDay()
{ {
var dataModel = DataModel as Dota2DataModel; var dataModel = DataModel as Dota2DataModel;

View File

@ -1,88 +1,22 @@
using System.IO; using Artemis.Managers;
using System.Windows.Forms; using Artemis.Models;
using Artemis.InjectionFactories;
using Artemis.Managers;
using Artemis.Properties;
using Artemis.Utilities;
using Artemis.ViewModels.Abstract; using Artemis.ViewModels.Abstract;
using Ninject;
namespace Artemis.Modules.Games.Dota2 namespace Artemis.Modules.Games.Dota2
{ {
public sealed class Dota2ViewModel : GameViewModel public sealed class Dota2ViewModel : GameViewModel
{ {
public Dota2ViewModel(MainManager main, IProfileEditorVmFactory pFactory, Dota2Model model) public Dota2ViewModel(MainManager main, IKernel kernel, [Named("Dota2Model")] GameModel model)
: base(main, model, pFactory) : base(main, model, kernel)
{ {
DisplayName = "Dota 2"; DisplayName = "Dota 2";
FindGameDir();
PlaceConfigFile();
}
public void FindGameDir()
{
var gameSettings = (Dota2Settings) GameSettings;
// If already propertly set up, don't do anything
if ((gameSettings.GameDirectory != null) && File.Exists(gameSettings.GameDirectory + "csgo.exe") &&
File.Exists(gameSettings.GameDirectory + "/csgo/cfg/gamestate_integration_artemis.cfg"))
return;
var dir = GeneralHelpers.FindSteamGame(@"\dota 2 beta\game\bin\win32\dota2.exe");
// Remove subdirectories where they stuck the executable
dir = dir?.Substring(0, dir.Length - 15);
gameSettings.GameDirectory = dir ?? string.Empty;
gameSettings.Save();
}
public void BrowseDirectory()
{
var dialog = new FolderBrowserDialog {SelectedPath = ((Dota2Settings) GameSettings).GameDirectory};
var result = dialog.ShowDialog();
if (result != DialogResult.OK)
return;
((Dota2Settings) GameSettings).GameDirectory = dialog.SelectedPath;
NotifyOfPropertyChange(() => GameSettings);
GameSettings.Save();
PlaceConfigFile();
} }
public void PlaceConfigFile() public void PlaceConfigFile()
{ {
if (((Dota2Settings) GameSettings).GameDirectory == string.Empty) ((Dota2Model) GameModel).PlaceConfigFile();
return;
if (Directory.Exists(((Dota2Settings) GameSettings).GameDirectory + "/game/dota/cfg"))
{
var cfgFile = Resources.dotaGamestateConfiguration.Replace("{{port}}",
MainManager.GameStateWebServer.Port.ToString());
try
{
File.WriteAllText(
((Dota2Settings) GameSettings).GameDirectory +
"/game/dota/cfg/gamestate_integration/gamestate_integration_artemis.cfg",
cfgFile);
}
catch (DirectoryNotFoundException)
{
Directory.CreateDirectory(((Dota2Settings) GameSettings).GameDirectory +
"/game/dota/cfg/gamestate_integration/");
File.WriteAllText(
((Dota2Settings) GameSettings).GameDirectory +
"/game/dota/cfg/gamestate_integration/gamestate_integration_artemis.cfg",
cfgFile);
}
return;
}
DialogService.ShowErrorMessageBox("Please select a valid Dota 2 directory\n\n" +
@"By default Dota 2 is in \SteamApps\common\dota 2 beta");
((Dota2Settings) GameSettings).GameDirectory = string.Empty;
NotifyOfPropertyChange(() => GameSettings); NotifyOfPropertyChange(() => GameSettings);
GameSettings.Save();
} }
} }
} }

View File

@ -1,10 +1,22 @@
using Artemis.Models.Interfaces; using Artemis.Models.Interfaces;
using Artemis.Modules.Games.EurotruckSimulator2.Data; using Artemis.Modules.Games.EurotruckSimulator2.Data;
using MoonSharp.Interpreter;
namespace Artemis.Modules.Games.EurotruckSimulator2 namespace Artemis.Modules.Games.EurotruckSimulator2
{ {
[MoonSharpUserData]
public class EurotruckSimulator2DataModel : IDataModel public class EurotruckSimulator2DataModel : IDataModel
{ {
public EurotruckSimulator2DataModel()
{
// Register types for LUA
UserData.RegisterType<IEts2Game>();
UserData.RegisterType<IEts2Job>();
UserData.RegisterType<IEts2Navigation>();
UserData.RegisterType<IEts2Trailer>();
UserData.RegisterType<IEts2Truck>();
}
public IEts2Game Game { get; set; } public IEts2Game Game { get; set; }
public IEts2Job Job { get; set; } public IEts2Job Job { get; set; }
public IEts2Navigation Navigation { get; set; } public IEts2Navigation Navigation { get; set; }

View File

@ -1,32 +1,43 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.IO;
using Artemis.DAL; using Artemis.DAL;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Models; using Artemis.Models;
using Artemis.Modules.Games.EurotruckSimulator2.Data; using Artemis.Modules.Games.EurotruckSimulator2.Data;
using Artemis.Profiles.Layers.Models; using Artemis.Profiles.Layers.Models;
using Artemis.Properties;
using Artemis.Services;
using Artemis.Settings;
using Artemis.Utilities;
using Ninject.Extensions.Logging; using Ninject.Extensions.Logging;
namespace Artemis.Modules.Games.EurotruckSimulator2 namespace Artemis.Modules.Games.EurotruckSimulator2
{ {
public class EurotruckSimulator2Model : GameModel public class EurotruckSimulator2Model : GameModel
{ {
public EurotruckSimulator2Model(MainManager mainManager) private readonly MetroDialogService _dialogService;
: base(mainManager, SettingsProvider.Load<EurotruckSimulator2Settings>(), new EurotruckSimulator2DataModel()
) public EurotruckSimulator2Model(DeviceManager deviceManager, MetroDialogService dialogService)
: base(
deviceManager, SettingsProvider.Load<EurotruckSimulator2Settings>(), new EurotruckSimulator2DataModel())
{ {
_dialogService = dialogService;
Name = "EurotruckSimulator2"; Name = "EurotruckSimulator2";
ProcessName = "eurotrucks2"; ProcessName = "eurotrucks2";
Scale = 4; Scale = 4;
Enabled = Settings.Enabled; Enabled = Settings.Enabled;
Initialized = false; Initialized = false;
FindGameDir();
} }
public ILogger Logger { get; set; }
public int Scale { get; set; } public int Scale { get; set; }
public override void Dispose() public override void Dispose()
{ {
Initialized = false; Initialized = false;
base.Dispose();
} }
public override void Enable() public override void Enable()
@ -46,6 +57,66 @@ namespace Artemis.Modules.Games.EurotruckSimulator2
dataModel.Truck = telemetryData.Truck; dataModel.Truck = telemetryData.Truck;
} }
public void FindGameDir()
{
var gameSettings = (EurotruckSimulator2Settings) Settings;
// Demo is also supported but resides in a different directory, the full game can also be 64-bits
var dir = GeneralHelpers.FindSteamGame(@"\Euro Truck Simulator 2\bin\win_x64\eurotrucks2.exe") ??
GeneralHelpers.FindSteamGame(@"\Euro Truck Simulator 2\bin\win_x86\eurotrucks2.exe") ??
GeneralHelpers.FindSteamGame(@"\Euro Truck Simulator 2 Demo\bin\win_x86\eurotrucks2.exe");
if (string.IsNullOrEmpty(dir))
return;
gameSettings.GameDirectory = dir;
gameSettings.Save();
if (!File.Exists(dir + "/plugins/ets2-telemetry-server.dll"))
PlacePlugin();
}
public void PlacePlugin()
{
var gameSettings = (EurotruckSimulator2Settings) Settings;
if (gameSettings.GameDirectory == string.Empty)
return;
var path = gameSettings.GameDirectory;
// Ensure the selected directory exists
if (!Directory.Exists(path))
{
_dialogService.ShowErrorMessageBox($"Directory '{path}' not found.");
return;
}
// Ensure it's the ETS2 directory by looking for the executable
if (!File.Exists(path + "/eurotrucks2.exe"))
{
_dialogService.ShowErrorMessageBox("Please select a valid Eurotruck Simulator 2 directory\n\n" +
@"By default ETS2 is in \SteamApps\common\Euro Truck Simulator 2\bin\win_x64");
return;
}
// Create the plugins folder if it's not already there
Directory.CreateDirectory(path + "/plugins");
// Place either the 64-bits or 32-bits DLL
try
{
if (path.Contains("win_x64"))
File.WriteAllBytes(path + "/plugins/ets2-telemetry-server.dll", Resources.ets2_telemetry_server_x64);
else
File.WriteAllBytes(path + "/plugins/ets2-telemetry-server.dll", Resources.ets2_telemetry_server_x86);
Logger?.Debug("Installed ETS2 plugin in {0}", path);
}
catch (Exception e)
{
Logger?.Error(e, "Failed to install ETS2 plugin in {0}", path);
throw;
}
}
public override List<LayerModel> GetRenderLayers(bool keyboardOnly) public override List<LayerModel> GetRenderLayers(bool keyboardOnly)
{ {
return Profile.GetRenderLayers(DataModel, keyboardOnly); return Profile.GetRenderLayers(DataModel, keyboardOnly);

View File

@ -1,40 +1,18 @@
using System; using System.IO;
using System.IO;
using System.Windows.Forms; using System.Windows.Forms;
using Artemis.InjectionFactories;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Properties; using Artemis.Models;
using Artemis.Utilities;
using Artemis.ViewModels.Abstract; using Artemis.ViewModels.Abstract;
using Ninject;
namespace Artemis.Modules.Games.EurotruckSimulator2 namespace Artemis.Modules.Games.EurotruckSimulator2
{ {
public sealed class EurotruckSimulator2ViewModel : GameViewModel public sealed class EurotruckSimulator2ViewModel : GameViewModel
{ {
public EurotruckSimulator2ViewModel(MainManager main, IProfileEditorVmFactory pFactory, public EurotruckSimulator2ViewModel(MainManager main, IKernel kernel,
EurotruckSimulator2Model model) : base(main, model, pFactory) [Named("EurotruckSimulator2Model")] GameModel model) : base(main, model, kernel)
{ {
DisplayName = "ETS 2"; DisplayName = "ETS 2";
FindGameDir();
}
public void FindGameDir()
{
var gameSettings = (EurotruckSimulator2Settings) GameSettings;
// Demo is also supported but resides in a different directory, the full game can also be 64-bits
var dir = GeneralHelpers.FindSteamGame(@"\Euro Truck Simulator 2\bin\win_x64\eurotrucks2.exe") ??
GeneralHelpers.FindSteamGame(@"\Euro Truck Simulator 2\bin\win_x86\eurotrucks2.exe") ??
GeneralHelpers.FindSteamGame(@"\Euro Truck Simulator 2 Demo\bin\win_x86\eurotrucks2.exe");
if (string.IsNullOrEmpty(dir))
return;
gameSettings.GameDirectory = dir;
gameSettings.Save();
if (!File.Exists(dir + "/plugins/ets2-telemetry-server.dll"))
PlacePlugin();
} }
public void BrowseDirectory() public void BrowseDirectory()
@ -51,49 +29,7 @@ namespace Artemis.Modules.Games.EurotruckSimulator2
NotifyOfPropertyChange(() => GameSettings); NotifyOfPropertyChange(() => GameSettings);
GameSettings.Save(); GameSettings.Save();
PlacePlugin(); ((EurotruckSimulator2Model) GameModel).PlacePlugin();
}
public void PlacePlugin()
{
if (((EurotruckSimulator2Settings) GameSettings).GameDirectory == string.Empty)
return;
var path = ((EurotruckSimulator2Settings) GameSettings).GameDirectory;
// Ensure the selected directory exists
if (!Directory.Exists(path))
{
DialogService.ShowErrorMessageBox($"Directory '{path}' not found.");
return;
}
// Ensure it's the ETS2 directory by looking for the executable
if (!File.Exists(path + "/eurotrucks2.exe"))
{
DialogService.ShowErrorMessageBox("Please select a valid Eurotruck Simulator 2 directory\n\n" +
@"By default ETS2 is in \SteamApps\common\Euro Truck Simulator 2\bin\win_x64");
return;
}
// Create the plugins folder if it's not already there
Directory.CreateDirectory(path + "/plugins");
// Place either the 64-bits or 32-bits DLL
try
{
if (path.Contains("win_x64"))
File.WriteAllBytes(path + "/plugins/ets2-telemetry-server.dll", Resources.ets2_telemetry_server_x64);
else
File.WriteAllBytes(path + "/plugins/ets2-telemetry-server.dll", Resources.ets2_telemetry_server_x86);
MainManager.Logger.Debug("Installed ETS2 plugin in {0}", path);
}
catch (Exception e)
{
MainManager.Logger.Error(e, "Failed to install ETS2 plugin in {0}", path);
throw;
}
} }
} }
} }

View File

@ -0,0 +1,12 @@
using Artemis.Models.Interfaces;
using MoonSharp.Interpreter;
namespace Artemis.Modules.Games.GtaV
{
[MoonSharpUserData]
public class GtaVDataModel : IDataModel
{
public bool IsWanted { get; set; }
public string Color { get; set; }
}
}

View File

@ -0,0 +1,88 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Media;
using Artemis.DAL;
using Artemis.Managers;
using Artemis.Models;
using Artemis.Profiles.Layers.Models;
using Artemis.Utilities;
using Artemis.Utilities.DataReaders;
namespace Artemis.Modules.Games.GtaV
{
public class GtaVModel : GameModel
{
private readonly PipeServer _pipeServer;
public GtaVModel(DeviceManager deviceManager, PipeServer pipeServer)
: base(deviceManager, SettingsProvider.Load<GtaVSettings>(), new GtaVDataModel())
{
_pipeServer = pipeServer;
Name = "GTAV";
ProcessName = "GTA5";
Enabled = Settings.Enabled;
Initialized = false;
}
public override void Enable()
{
DllManager.PlaceLogitechDll();
_pipeServer.PipeMessage += PipeServerOnPipeMessage;
Initialized = true;
}
public override void Dispose()
{
Initialized = false;
// Delay restoring the DLL to allow GTA to release it
Task.Factory.StartNew(() =>
{
Thread.Sleep(5000);
DllManager.RestoreLogitechDll();
});
_pipeServer.PipeMessage -= PipeServerOnPipeMessage;
base.Dispose();
}
public override void Update()
{
// DataModel updating is done whenever a pipe message is received
}
public override List<LayerModel> GetRenderLayers(bool keyboardOnly)
{
return Profile.GetRenderLayers(DataModel, keyboardOnly);
}
private void PipeServerOnPipeMessage(string reply)
{
if (!Initialized)
return;
// Convert the given string to a list of ints
var stringParts = reply.Split(' ');
var parts = new string[stringParts.Length];
for (var i = 0; i < stringParts.Length; i++)
parts[i] = stringParts[i];
if (parts[0] == "0")
InterpertrateLighting(parts);
}
private void InterpertrateLighting(string[] parts)
{
var gameDataModel = (GtaVDataModel) DataModel;
var custom = parts[1];
gameDataModel.IsWanted = custom.StartsWith("ff");
var rPer = byte.Parse(parts[2]);
var gPer = byte.Parse(parts[3]);
var bPer = byte.Parse(parts[4]);
gameDataModel.Color = Color.FromArgb(255, rPer, gPer, bPer).ToHex();
}
}
}

View File

@ -0,0 +1,8 @@
using Artemis.Settings;
namespace Artemis.Modules.Games.GtaV
{
public class GtaVSettings : GameSettings
{
}
}

View File

@ -0,0 +1,54 @@
<UserControl x:Class="Artemis.Modules.Games.GtaV.GtaVView"
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"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
<Grid Margin="15, 5, 15, 5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Margin="0,0,1,0">
<Label FontSize="20" HorizontalAlignment="Left">
<Label.Content>
<AccessText TextWrapping="Wrap"
Text="By default fills up the keyboard and colors all devices according to the character you're playing/team you're in." />
</Label.Content>
</Label>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Label Content="Enable effect" Margin="0 3 0 0" HorizontalAlignment="Right" />
<ToggleButton x:Name="EffectEnabled" Margin="0 3 0 0" Width="25" Height="25"
IsChecked="{Binding Path=GameSettings.Enabled, Mode=TwoWay}"
Style="{DynamicResource MetroCircleToggleButtonStyle}"
cal:Message.Attach="[Event Click] = [Action ToggleEffect]" />
</StackPanel>
</StackPanel>
<!-- 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">
<Button x:Name="ResetSettings" Content="Reset effect" VerticalAlignment="Top" Width="100"
Style="{DynamicResource SquareButtonStyle}" />
<Button x:Name="SaveSettings" Content="Save changes" VerticalAlignment="Top" Width="100"
Margin="10,0,0,0"
Style="{DynamicResource SquareButtonStyle}" />
</StackPanel>
</Grid>
</ScrollViewer>
</UserControl>

View File

@ -0,0 +1,15 @@
using System.Windows.Controls;
namespace Artemis.Modules.Games.GtaV
{
/// <summary>
/// Interaction logic for GtaVView.xaml
/// </summary>
public partial class GtaVView : UserControl
{
public GtaVView()
{
InitializeComponent();
}
}
}

View File

@ -0,0 +1,16 @@
using Artemis.Managers;
using Artemis.Models;
using Artemis.ViewModels.Abstract;
using Ninject;
namespace Artemis.Modules.Games.GtaV
{
public sealed class GtaVViewModel : GameViewModel
{
public GtaVViewModel(MainManager mainManager, [Named("GtaVModel")] GameModel model, IKernel kernel)
: base(mainManager, model, kernel)
{
DisplayName = "GTA V";
}
}
}

View File

@ -1,7 +1,9 @@
using Artemis.Models.Interfaces; using Artemis.Models.Interfaces;
using MoonSharp.Interpreter;
namespace Artemis.Modules.Games.Overwatch namespace Artemis.Modules.Games.Overwatch
{ {
[MoonSharpUserData]
public class OverwatchDataModel : IDataModel public class OverwatchDataModel : IDataModel
{ {
public OverwatchStatus Status { get; set; } public OverwatchStatus Status { get; set; }

View File

@ -1,19 +1,23 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Windows.Media; using System.Windows.Media;
using Artemis.DAL; using Artemis.DAL;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Models; using Artemis.Models;
using Artemis.Models.Interfaces;
using Artemis.Profiles.Layers.Models; using Artemis.Profiles.Layers.Models;
using Artemis.Settings; using Artemis.Services;
using Artemis.Utilities; using Artemis.Utilities;
using Artemis.Utilities.DataReaders;
using Microsoft.Win32;
namespace Artemis.Modules.Games.Overwatch namespace Artemis.Modules.Games.Overwatch
{ {
public class OverwatchModel : GameModel public class OverwatchModel : GameModel
{ {
private readonly PipeServer _pipeServer;
private readonly MetroDialogService _dialogService;
private DateTime _characterChange; private DateTime _characterChange;
private string _lastMessage; private string _lastMessage;
// Using sticky values on these since they can cause flickering // Using sticky values on these since they can cause flickering
@ -23,9 +27,11 @@ namespace Artemis.Modules.Games.Overwatch
private DateTime _ultimateReady; private DateTime _ultimateReady;
private DateTime _ultimateUsed; private DateTime _ultimateUsed;
public OverwatchModel(MainManager mainManager) public OverwatchModel(DeviceManager deviceManager, PipeServer pipeServer, MetroDialogService dialogService)
: base(mainManager, SettingsProvider.Load<OverwatchSettings>(), new OverwatchDataModel()) : base(deviceManager, SettingsProvider.Load<OverwatchSettings>(), new OverwatchDataModel())
{ {
_pipeServer = pipeServer;
_dialogService = dialogService;
Name = "Overwatch"; Name = "Overwatch";
ProcessName = "Overwatch"; ProcessName = "Overwatch";
Scale = 4; Scale = 4;
@ -33,11 +39,7 @@ namespace Artemis.Modules.Games.Overwatch
Initialized = false; Initialized = false;
LoadOverwatchCharacters(); LoadOverwatchCharacters();
} FindOverwatch();
public OverwatchModel(MainManager mainManager, GameSettings settings, IDataModel dataModel)
: base(mainManager, settings, dataModel)
{
} }
public List<CharacterColor> OverwatchCharacters { get; set; } public List<CharacterColor> OverwatchCharacters { get; set; }
@ -77,7 +79,7 @@ namespace Artemis.Modules.Games.Overwatch
_stickyStatus = new StickyValue<OverwatchStatus>(300); _stickyStatus = new StickyValue<OverwatchStatus>(300);
_stickyUltimateReady = new StickyValue<bool>(350); _stickyUltimateReady = new StickyValue<bool>(350);
_stickyUltimateUsed = new StickyValue<bool>(350); _stickyUltimateUsed = new StickyValue<bool>(350);
MainManager.PipeServer.PipeMessage += PipeServerOnPipeMessage; _pipeServer.PipeMessage += PipeServerOnPipeMessage;
Initialized = true; Initialized = true;
} }
@ -86,11 +88,12 @@ namespace Artemis.Modules.Games.Overwatch
{ {
Initialized = false; Initialized = false;
_stickyStatus.Dispose(); _stickyStatus?.Dispose();
_stickyUltimateReady.Dispose(); _stickyUltimateReady?.Dispose();
_stickyUltimateUsed.Dispose(); _stickyUltimateUsed?.Dispose();
MainManager.PipeServer.PipeMessage -= PipeServerOnPipeMessage; _pipeServer.PipeMessage -= PipeServerOnPipeMessage;
base.Dispose();
} }
private void PipeServerOnPipeMessage(string message) private void PipeServerOnPipeMessage(string message)
@ -176,7 +179,7 @@ namespace Artemis.Modules.Games.Overwatch
} }
catch (FormatException e) catch (FormatException e)
{ {
MainManager.Logger.Trace(e, "Failed to parse to color array"); Logger?.Trace(e, "Failed to parse to color array");
return null; return null;
} }
} }
@ -270,6 +273,46 @@ namespace Artemis.Modules.Games.Overwatch
{ {
return Profile.GetRenderLayers(DataModel, keyboardOnly); return Profile.GetRenderLayers(DataModel, keyboardOnly);
} }
public void FindOverwatch()
{
var gameSettings = (OverwatchSettings) Settings;
// If already propertly set up, don't do anything
if ((gameSettings.GameDirectory != null) && File.Exists(gameSettings.GameDirectory + "Overwatch.exe") &&
File.Exists(gameSettings.GameDirectory + "RzChromaSDK64.dll"))
return;
var key = Registry.LocalMachine.OpenSubKey(
@"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Overwatch");
if (key == null)
return;
var path = key.GetValue("DisplayIcon").ToString();
if (!File.Exists(path))
return;
gameSettings.GameDirectory = path.Substring(0, path.Length - 14);
gameSettings.Save();
PlaceDll();
}
public void PlaceDll()
{
var settings = (OverwatchSettings) Settings;
var path = settings.GameDirectory;
if (!File.Exists(path + @"\Overwatch.exe"))
{
_dialogService.ShowErrorMessageBox("Please select a valid Overwatch directory\n\n" +
@"By default Overwatch is in C:\Program Files (x86)\Overwatch");
settings.GameDirectory = string.Empty;
settings.Save();
return;
}
DllManager.PlaceRazerDll(path);
}
} }
public struct CharacterColor public struct CharacterColor

View File

@ -1,43 +1,17 @@
using System.IO; using System.Windows.Forms;
using System.Windows.Forms;
using Artemis.InjectionFactories;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Utilities.DataReaders; using Artemis.Models;
using Artemis.ViewModels.Abstract; using Artemis.ViewModels.Abstract;
using Microsoft.Win32; using Ninject;
namespace Artemis.Modules.Games.Overwatch namespace Artemis.Modules.Games.Overwatch
{ {
public sealed class OverwatchViewModel : GameViewModel public sealed class OverwatchViewModel : GameViewModel
{ {
public OverwatchViewModel(MainManager main, IProfileEditorVmFactory pFactory, OverwatchModel model) public OverwatchViewModel(MainManager main, IKernel kernel, [Named("OverwatchModel")] GameModel model)
: base(main, model, pFactory) : base(main, model, kernel)
{ {
DisplayName = "Overwatch"; DisplayName = "Overwatch";
FindOverwatch();
}
public void FindOverwatch()
{
var gameSettings = (OverwatchSettings) GameSettings;
// If already propertly set up, don't do anything
if ((gameSettings.GameDirectory != null) && File.Exists(gameSettings.GameDirectory + "Overwatch.exe") &&
File.Exists(gameSettings.GameDirectory + "RzChromaSDK64.dll"))
return;
var key = Registry.LocalMachine.OpenSubKey(
@"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Overwatch");
if (key == null)
return;
var path = key.GetValue("DisplayIcon").ToString();
if (!File.Exists(path))
return;
gameSettings.GameDirectory = path.Substring(0, path.Length - 14);
gameSettings.Save();
PlaceDll();
} }
public void BrowseDirectory() public void BrowseDirectory()
@ -48,28 +22,9 @@ namespace Artemis.Modules.Games.Overwatch
return; return;
((OverwatchSettings) GameSettings).GameDirectory = dialog.SelectedPath; ((OverwatchSettings) GameSettings).GameDirectory = dialog.SelectedPath;
NotifyOfPropertyChange(() => GameSettings);
GameSettings.Save(); GameSettings.Save();
((OverwatchModel) GameModel).PlaceDll();
PlaceDll(); NotifyOfPropertyChange(() => GameSettings);
}
public void PlaceDll()
{
var path = ((OverwatchSettings) GameSettings).GameDirectory;
if (!File.Exists(path + @"\Overwatch.exe"))
{
DialogService.ShowErrorMessageBox("Please select a valid Overwatch directory\n\n" +
@"By default Overwatch is in C:\Program Files (x86)\Overwatch");
((OverwatchSettings) GameSettings).GameDirectory = string.Empty;
NotifyOfPropertyChange(() => GameSettings);
GameSettings.Save();
return;
}
DllManager.PlaceRazerDll(path);
} }
} }
} }

View File

@ -1,7 +1,9 @@
using Artemis.Models.Interfaces; using Artemis.Models.Interfaces;
using MoonSharp.Interpreter;
namespace Artemis.Modules.Games.RocketLeague namespace Artemis.Modules.Games.RocketLeague
{ {
[MoonSharpUserData]
public class RocketLeagueDataModel : IDataModel public class RocketLeagueDataModel : IDataModel
{ {
public int Boost { get; set; } public int Boost { get; set; }

View File

@ -17,8 +17,8 @@ namespace Artemis.Modules.Games.RocketLeague
private Memory _memory; private Memory _memory;
private GamePointersCollection _pointer; private GamePointersCollection _pointer;
public RocketLeagueModel(MainManager mainManager) public RocketLeagueModel(DeviceManager deviceManager)
: base(mainManager, SettingsProvider.Load<RocketLeagueSettings>(), new RocketLeagueDataModel()) : base(deviceManager, SettingsProvider.Load<RocketLeagueSettings>(), new RocketLeagueDataModel())
{ {
Name = "RocketLeague"; Name = "RocketLeague";
ProcessName = "RocketLeague"; ProcessName = "RocketLeague";
@ -50,6 +50,7 @@ namespace Artemis.Modules.Games.RocketLeague
{ {
Initialized = false; Initialized = false;
_memory = null; _memory = null;
base.Dispose();
} }
public override void Enable() public override void Enable()

View File

@ -1,9 +1,10 @@
using Artemis.DAL; using Artemis.DAL;
using Artemis.InjectionFactories;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Models;
using Artemis.Settings; using Artemis.Settings;
using Artemis.Utilities; using Artemis.Utilities;
using Artemis.ViewModels.Abstract; using Artemis.ViewModels.Abstract;
using Ninject;
namespace Artemis.Modules.Games.RocketLeague namespace Artemis.Modules.Games.RocketLeague
{ {
@ -11,8 +12,8 @@ namespace Artemis.Modules.Games.RocketLeague
{ {
private string _versionText; private string _versionText;
public RocketLeagueViewModel(MainManager main, IProfileEditorVmFactory pFactory, RocketLeagueModel model) public RocketLeagueViewModel(MainManager main, IKernel kernel, [Named("RocketLeagueModel")] GameModel model)
: base(main, model, pFactory) : base(main, model, kernel)
{ {
DisplayName = "Rocket League"; DisplayName = "Rocket League";
SetVersionText(); SetVersionText();

View File

@ -1,14 +1,11 @@
using Artemis.Models.Interfaces; using Artemis.Models.Interfaces;
using MoonSharp.Interpreter;
namespace Artemis.Modules.Games.TheDivision namespace Artemis.Modules.Games.TheDivision
{ {
[MoonSharpUserData]
public class TheDivisionDataModel : IDataModel public class TheDivisionDataModel : IDataModel
{ {
public TheDivisionDataModel()
{
TestyTest = new TestTest();
}
public PlayerState PartyMember1 { get; set; } public PlayerState PartyMember1 { get; set; }
public PlayerState PartyMember2 { get; set; } public PlayerState PartyMember2 { get; set; }
public PlayerState PartyMember3 { get; set; } public PlayerState PartyMember3 { get; set; }
@ -16,17 +13,8 @@ namespace Artemis.Modules.Games.TheDivision
public bool LowAmmo { get; set; } public bool LowAmmo { get; set; }
public bool LowHp { get; set; } public bool LowHp { get; set; }
public GrenadeState GrenadeState { get; set; } public GrenadeState GrenadeState { get; set; }
public TestTest TestyTest { get; set; }
} }
public class TestTest
{
public string TestS { get; set; }
public int TestI { get; set; }
}
public enum GrenadeState public enum GrenadeState
{ {
HasGrenade, HasGrenade,

View File

@ -12,12 +12,14 @@ namespace Artemis.Modules.Games.TheDivision
{ {
public class TheDivisionModel : GameModel public class TheDivisionModel : GameModel
{ {
private readonly PipeServer _pipeServer;
private StickyValue<bool> _stickyAmmo; private StickyValue<bool> _stickyAmmo;
private StickyValue<bool> _stickyHp; private StickyValue<bool> _stickyHp;
public TheDivisionModel(MainManager mainManager) public TheDivisionModel(DeviceManager deviceManager, PipeServer pipeServer)
: base(mainManager, SettingsProvider.Load<TheDivisionSettings>(), new TheDivisionDataModel()) : base(deviceManager, SettingsProvider.Load<TheDivisionSettings>(), new TheDivisionDataModel())
{ {
_pipeServer = pipeServer;
Name = "TheDivision"; Name = "TheDivision";
ProcessName = "TheDivision"; ProcessName = "TheDivision";
Scale = 4; Scale = 4;
@ -38,10 +40,11 @@ namespace Artemis.Modules.Games.TheDivision
DllManager.RestoreLogitechDll(); DllManager.RestoreLogitechDll();
}); });
_stickyAmmo.Dispose(); _stickyAmmo?.Dispose();
_stickyHp.Dispose(); _stickyHp?.Dispose();
MainManager.PipeServer.PipeMessage -= PipeServerOnPipeMessage; _pipeServer.PipeMessage -= PipeServerOnPipeMessage;
base.Dispose();
} }
public override void Enable() public override void Enable()
@ -53,7 +56,7 @@ namespace Artemis.Modules.Games.TheDivision
DllManager.PlaceLogitechDll(); DllManager.PlaceLogitechDll();
MainManager.PipeServer.PipeMessage += PipeServerOnPipeMessage; _pipeServer.PipeMessage += PipeServerOnPipeMessage;
Initialized = true; Initialized = true;
} }

View File

@ -1,13 +1,14 @@
using Artemis.InjectionFactories; using Ninject;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Models;
using Artemis.ViewModels.Abstract; using Artemis.ViewModels.Abstract;
namespace Artemis.Modules.Games.TheDivision namespace Artemis.Modules.Games.TheDivision
{ {
public sealed class TheDivisionViewModel : GameViewModel public sealed class TheDivisionViewModel : GameViewModel
{ {
public TheDivisionViewModel(MainManager main, IProfileEditorVmFactory pFactory, TheDivisionModel model) public TheDivisionViewModel(MainManager main, IKernel kernel, [Named("TheDivisionModel")] GameModel model)
: base(main, model, pFactory) : base(main, model, kernel)
{ {
DisplayName = "The Division"; DisplayName = "The Division";
} }

View File

@ -1,9 +1,11 @@
using System.ComponentModel; using System.ComponentModel;
using Artemis.Models.Interfaces; using Artemis.Models.Interfaces;
using MoonSharp.Interpreter;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace Artemis.Modules.Games.UnrealTournament namespace Artemis.Modules.Games.UnrealTournament
{ {
[MoonSharpUserData]
public class UnrealTournamentDataModel : IDataModel public class UnrealTournamentDataModel : IDataModel
{ {
public State State { get; set; } public State State { get; set; }
@ -19,6 +21,7 @@ namespace Artemis.Modules.Games.UnrealTournament
Dead Dead
} }
[MoonSharpUserData]
public class Player public class Player
{ {
public int Health { get; set; } public int Health { get; set; }
@ -41,6 +44,7 @@ namespace Artemis.Modules.Games.UnrealTournament
MonsterKill = 5 MonsterKill = 5
} }
[MoonSharpUserData]
public class PlayerState public class PlayerState
{ {
public string PlayerName { get; set; } public string PlayerName { get; set; }
@ -72,6 +76,7 @@ namespace Artemis.Modules.Games.UnrealTournament
public int No_Showdowns { get; set; } public int No_Showdowns { get; set; }
} }
[MoonSharpUserData]
public class Inventory public class Inventory
{ {
public bool HasJumpBoots { get; set; } public bool HasJumpBoots { get; set; }
@ -84,6 +89,7 @@ namespace Artemis.Modules.Games.UnrealTournament
public bool HasHelmet { get; set; } public bool HasHelmet { get; set; }
} }
[MoonSharpUserData]
public class Weapon public class Weapon
{ {
public string Name { get; set; } public string Name { get; set; }
@ -102,6 +108,7 @@ namespace Artemis.Modules.Games.UnrealTournament
ZoomingOut = 2 ZoomingOut = 2
} }
[MoonSharpUserData]
public class Environment public class Environment
{ {
public string GameMode { get; set; } public string GameMode { get; set; }

View File

@ -1,22 +1,35 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Timers; using System.Timers;
using Artemis.DAL; using Artemis.DAL;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Models; using Artemis.Models;
using Artemis.Profiles.Layers.Models; using Artemis.Profiles.Layers.Models;
using Artemis.Properties;
using Artemis.Services;
using Artemis.Settings;
using Artemis.Utilities;
using Artemis.Utilities.DataReaders;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Artemis.Modules.Games.UnrealTournament namespace Artemis.Modules.Games.UnrealTournament
{ {
public class UnrealTournamentModel : GameModel public class UnrealTournamentModel : GameModel
{ {
private readonly PipeServer _pipeServer;
private readonly MetroDialogService _dialogService;
private Timer _killTimer; private Timer _killTimer;
private int _lastScore; private int _lastScore;
public UnrealTournamentModel(MainManager mainManager) public UnrealTournamentModel(DeviceManager deviceManager, PipeServer pipeServer, MetroDialogService dialogService)
: base(mainManager, SettingsProvider.Load<UnrealTournamentSettings>(), new UnrealTournamentDataModel()) : base(deviceManager, SettingsProvider.Load<UnrealTournamentSettings>(), new UnrealTournamentDataModel())
{ {
_pipeServer = pipeServer;
_dialogService = dialogService;
Name = "UnrealTournament"; Name = "UnrealTournament";
ProcessName = "UE4-Win64-Shipping"; ProcessName = "UE4-Win64-Shipping";
Scale = 4; Scale = 4;
@ -25,6 +38,77 @@ namespace Artemis.Modules.Games.UnrealTournament
_killTimer = new Timer(3500); _killTimer = new Timer(3500);
_killTimer.Elapsed += KillTimerOnElapsed; _killTimer.Elapsed += KillTimerOnElapsed;
FindGame();
}
public void FindGame()
{
var gameSettings = (UnrealTournamentSettings)Settings;
// If already propertly set up, don't do anything
if ((gameSettings.GameDirectory != null) &&
File.Exists(gameSettings.GameDirectory + "UE4-Win64-Shipping.exe"))
return;
// Attempt to read the file
if (!File.Exists(@"C:\ProgramData\Epic\UnrealEngineLauncher\LauncherInstalled.dat"))
return;
var json =
JsonConvert.DeserializeObject<JObject>(
File.ReadAllText(@"C:\ProgramData\Epic\UnrealEngineLauncher\LauncherInstalled.dat"));
var utEntry =
json["InstallationList"].Children()
.FirstOrDefault(c => c["AppName"].Value<string>() == "UnrealTournamentDev");
if (utEntry == null)
return;
var utDir = utEntry["InstallLocation"].Value<string>();
// Use backslash in path for consistency
utDir = utDir.Replace('/', '\\');
if (!File.Exists(utDir + @"\UE4-Win64-Shipping.exe"))
return;
gameSettings.GameDirectory = utDir;
gameSettings.Save();
PlaceFiles();
}
public void PlaceFiles()
{
var gameSettings = (UnrealTournamentSettings)Settings;
var path = gameSettings.GameDirectory;
if (!File.Exists(path + @"\UE4-Win64-Shipping.exe"))
{
_dialogService.ShowErrorMessageBox("Please select a valid Unreal Tournament directory\n\n" +
@"By default Unreal Tournament is in C:\Program Files\Epic Games\UnrealTournament");
gameSettings.GameDirectory = string.Empty;
gameSettings.Save();
Logger?.Warn("Failed to install Unreal Tournament plugin in '{0}' (path not found)", path);
return;
}
// Load the ZIP from resources
using (var stream = new MemoryStream(Resources.ut_plugin))
{
var archive = new ZipArchive(stream);
try
{
Directory.CreateDirectory(path + @"\UnrealTournament\Plugins\Artemis");
archive.ExtractToDirectory(path + @"\UnrealTournament\Plugins\Artemis", true);
}
catch (Exception e)
{
Logger?.Error(e, "Failed to install Unreal Tournament plugin in '{0}'", path);
return;
}
}
Logger?.Info("Installed Unreal Tournament plugin in '{0}'", path);
} }
public int Scale { get; set; } public int Scale { get; set; }
@ -34,12 +118,13 @@ namespace Artemis.Modules.Games.UnrealTournament
Initialized = false; Initialized = false;
_killTimer.Stop(); _killTimer.Stop();
MainManager.PipeServer.PipeMessage -= PipeServerOnPipeMessage; _pipeServer.PipeMessage -= PipeServerOnPipeMessage;
base.Dispose();
} }
public override void Enable() public override void Enable()
{ {
MainManager.PipeServer.PipeMessage += PipeServerOnPipeMessage; _pipeServer.PipeMessage += PipeServerOnPipeMessage;
_killTimer.Start(); _killTimer.Start();
Initialized = true; Initialized = true;

View File

@ -1,65 +1,24 @@
using System; using System.Windows.Forms;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
using Artemis.DAL; using Artemis.DAL;
using Artemis.InjectionFactories;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Models;
using Artemis.Properties; using Artemis.Properties;
using Artemis.Utilities;
using Artemis.ViewModels.Abstract; using Artemis.ViewModels.Abstract;
using Newtonsoft.Json; using Ninject;
using Newtonsoft.Json.Linq;
namespace Artemis.Modules.Games.UnrealTournament namespace Artemis.Modules.Games.UnrealTournament
{ {
public sealed class UnrealTournamentViewModel : GameViewModel public sealed class UnrealTournamentViewModel : GameViewModel
{ {
public UnrealTournamentViewModel(MainManager main, IProfileEditorVmFactory pFactory, UnrealTournamentModel model) public UnrealTournamentViewModel(MainManager main, IKernel kernel,
: base(main, model, pFactory) [Named("UnrealTournamentModel")] GameModel model) : base(main, model, kernel)
{ {
DisplayName = "Unreal Tournament"; DisplayName = "Unreal Tournament";
MainManager.EffectManager.EffectModels.Add(GameModel);
FindGame();
InstallGif(); InstallGif();
} }
public UnrealTournamentModel UnrealTournamentModel { get; set; } public UnrealTournamentModel UnrealTournamentModel { get; set; }
public void FindGame()
{
var gameSettings = (UnrealTournamentSettings) GameSettings;
// If already propertly set up, don't do anything
if ((gameSettings.GameDirectory != null) &&
File.Exists(gameSettings.GameDirectory + "UE4-Win64-Shipping.exe"))
return;
// Attempt to read the file
if (!File.Exists(@"C:\ProgramData\Epic\UnrealEngineLauncher\LauncherInstalled.dat"))
return;
var json =
JsonConvert.DeserializeObject<JObject>(
File.ReadAllText(@"C:\ProgramData\Epic\UnrealEngineLauncher\LauncherInstalled.dat"));
var utEntry =
json["InstallationList"].Children()
.FirstOrDefault(c => c["AppName"].Value<string>() == "UnrealTournamentDev");
if (utEntry == null)
return;
var utDir = utEntry["InstallLocation"].Value<string>();
// Use backslash in path for consistency
utDir = utDir.Replace('/', '\\');
if (!File.Exists(utDir + @"\UE4-Win64-Shipping.exe"))
return;
gameSettings.GameDirectory = utDir;
gameSettings.Save();
PlaceFiles();
}
public void BrowseDirectory() public void BrowseDirectory()
{ {
@ -72,52 +31,19 @@ namespace Artemis.Modules.Games.UnrealTournament
return; return;
((UnrealTournamentSettings) GameSettings).GameDirectory = dialog.SelectedPath; ((UnrealTournamentSettings) GameSettings).GameDirectory = dialog.SelectedPath;
NotifyOfPropertyChange(() => GameSettings);
GameSettings.Save(); GameSettings.Save();
((UnrealTournamentModel) GameModel).PlaceFiles();
PlaceFiles(); NotifyOfPropertyChange(() => GameSettings);
}
public void PlaceFiles()
{
var path = ((UnrealTournamentSettings) GameSettings).GameDirectory;
if (!File.Exists(path + @"\UE4-Win64-Shipping.exe"))
{
DialogService.ShowErrorMessageBox("Please select a valid Unreal Tournament directory\n\n" +
@"By default Unreal Tournament is in C:\Program Files\Epic Games\UnrealTournament");
((UnrealTournamentSettings) GameSettings).GameDirectory = string.Empty;
NotifyOfPropertyChange(() => GameSettings);
GameSettings.Save();
MainManager.Logger.Warn("Failed to install Unreal Tournament plugin in '{0}' (path not found)", path);
return;
}
// Load the ZIP from resources
var stream = new MemoryStream(Resources.ut_plugin);
var archive = new ZipArchive(stream);
try
{
Directory.CreateDirectory(path + @"\UnrealTournament\Plugins\Artemis");
archive.ExtractToDirectory(path + @"\UnrealTournament\Plugins\Artemis", true);
}
catch (Exception e)
{
MainManager.Logger.Error(e, "Failed to install Unreal Tournament plugin in '{0}'", path);
return;
}
MainManager.Logger.Info("Installed Unreal Tournament plugin in '{0}'", path);
} }
// Installing GIF on editor open to make sure the proper profiles are loaded
private void InstallGif() private void InstallGif()
{ {
var gif = Resources.redeemer; var gif = Resources.redeemer;
ProfileProvider.InsertGif(ProfileProvider.GetAll() if (gif == null)
.Where(p => (p.GameName == "UnrealTournament") && (p.Name == "Default")), "Redeemer GIF", gif, return;
"redeemer");
ProfileProvider.InsertGif("UnrealTournament", "Default", "Redeemer GIF", gif, "redeemer");
} }
} }
} }

View File

@ -1,7 +1,9 @@
using Artemis.Models.Interfaces; using Artemis.Models.Interfaces;
using MoonSharp.Interpreter;
namespace Artemis.Modules.Games.Witcher3 namespace Artemis.Modules.Games.Witcher3
{ {
[MoonSharpUserData]
public class Witcher3DataModel : IDataModel public class Witcher3DataModel : IDataModel
{ {
public WitcherSign WitcherSign { get; set; } public WitcherSign WitcherSign { get; set; }

View File

@ -17,8 +17,8 @@ namespace Artemis.Modules.Games.Witcher3
private readonly Stopwatch _updateSw; private readonly Stopwatch _updateSw;
private string _witcherSettings; private string _witcherSettings;
public Witcher3Model(MainManager mainManager) public Witcher3Model(DeviceManager deviceManager)
: base(mainManager, SettingsProvider.Load<Witcher3Settings>(), new Witcher3DataModel()) : base(deviceManager, SettingsProvider.Load<Witcher3Settings>(), new Witcher3DataModel())
{ {
Name = "Witcher3"; Name = "Witcher3";
ProcessName = "witcher3"; ProcessName = "witcher3";
@ -38,6 +38,7 @@ namespace Artemis.Modules.Games.Witcher3
_witcherSettings = null; _witcherSettings = null;
_updateSw.Reset(); _updateSw.Reset();
base.Dispose();
} }
public override void Enable() public override void Enable()
@ -66,10 +67,11 @@ namespace Artemis.Modules.Games.Witcher3
if (_witcherSettings == null) if (_witcherSettings == null)
return; return;
var reader = new StreamReader( var reader =
File.Open(_witcherSettings, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)); new StreamReader(File.Open(_witcherSettings, FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
var configContent = reader.ReadToEnd(); var configContent = reader.ReadToEnd();
reader.Close(); reader.Close();
reader.Dispose();
var signRes = _configRegex.Match(configContent); var signRes = _configRegex.Match(configContent);
var parts = signRes.Value.Split('\n').Skip(1).Select(v => v.Replace("\r", "")).ToList(); var parts = signRes.Value.Split('\n').Skip(1).Select(v => v.Replace("\r", "")).ToList();

View File

@ -3,20 +3,20 @@ using System.Diagnostics;
using System.IO; using System.IO;
using System.IO.Compression; using System.IO.Compression;
using System.Linq; using System.Linq;
using System.Reflection;
using System.Windows.Forms; using System.Windows.Forms;
using Artemis.InjectionFactories;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Models;
using Artemis.Properties; using Artemis.Properties;
using Artemis.Utilities; using Artemis.Utilities;
using Artemis.ViewModels.Abstract; using Artemis.ViewModels.Abstract;
using Ninject;
namespace Artemis.Modules.Games.Witcher3 namespace Artemis.Modules.Games.Witcher3
{ {
public sealed class Witcher3ViewModel : GameViewModel public sealed class Witcher3ViewModel : GameViewModel
{ {
public Witcher3ViewModel(MainManager main, IProfileEditorVmFactory pFactory, Witcher3Model model) public Witcher3ViewModel(MainManager main, IKernel kernel, [Named("Witcher3Model")] GameModel model)
: base(main, model, pFactory) : base(main, model, kernel)
{ {
DisplayName = "The Witcher 3"; DisplayName = "The Witcher 3";
} }
@ -48,39 +48,43 @@ namespace Artemis.Modules.Games.Witcher3
} }
// Load the ZIP from resources // Load the ZIP from resources
var stream = new MemoryStream(Resources.witcher3_mod); using (var stream = new MemoryStream(Resources.witcher3_mod))
var archive = new ZipArchive(stream);
// Look for any conflicting mods
if (Directory.Exists(dialog.SelectedPath + @"\mods"))
{ {
var file = using (var archive = new ZipArchive(stream))
Directory.GetFiles(dialog.SelectedPath + @"\mods", "playerWitcher.ws", SearchOption.AllDirectories) {
.FirstOrDefault(); // Look for any conflicting mods
if (file != null) if (Directory.Exists(dialog.SelectedPath + @"\mods"))
if (!file.Contains("modArtemis"))
{ {
var viewHelp = await var file = Directory.GetFiles(dialog.SelectedPath + @"\mods", "playerWitcher.ws",
DialogService.ShowQuestionMessageBox("Conflicting mod found", SearchOption.AllDirectories)
"Oh no, you have a conflicting mod!\n\n" + .FirstOrDefault();
$"Conflicting file: {file.Remove(0, dialog.SelectedPath.Length)}\n\n" + if (file != null)
"Would you like to view instructions on how to manually install the mod?"); if (!file.Contains("modArtemis"))
if (!viewHelp.Value) {
return; var viewHelp = await
DialogService.ShowQuestionMessageBox("Conflicting mod found",
"Oh no, you have a conflicting mod!\n\n" +
$"Conflicting file: {file.Remove(0, dialog.SelectedPath.Length)}\n\n" +
"Would you like to view instructions on how to manually install the mod?");
if (!viewHelp.Value)
return;
// Put the mod in the documents folder instead // Put the mod in the documents folder instead
// Create the directory structure // Create the directory structure
var folder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\Artemis"; var folder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) +
@"\Artemis";
archive.ExtractToDirectory(folder + @"witcher3-mod", true); archive.ExtractToDirectory(folder + @"witcher3-mod", true);
System.Diagnostics.Process.Start(new ProcessStartInfo("https://github.com/SpoinkyNL/Artemis/wiki/The-Witcher-3")); System.Diagnostics.Process.Start(
return; new ProcessStartInfo("https://github.com/SpoinkyNL/Artemis/wiki/The-Witcher-3"));
return;
}
} }
archive.ExtractToDirectory(dialog.SelectedPath, true);
DialogService.ShowMessageBox("Success", "The mod was successfully installed!");
}
} }
archive.ExtractToDirectory(dialog.SelectedPath, true);
DialogService.ShowMessageBox("Success", "The mod was successfully installed!");
} }
} }
} }

View File

@ -8,7 +8,6 @@ using Artemis.Modules.Games.WoW.Data;
using Artemis.Profiles.Layers.Models; using Artemis.Profiles.Layers.Models;
using Artemis.Settings; using Artemis.Settings;
using Artemis.Utilities.Memory; using Artemis.Utilities.Memory;
using Newtonsoft.Json;
using Process.NET; using Process.NET;
using Process.NET.Memory; using Process.NET.Memory;
@ -19,21 +18,21 @@ namespace Artemis.Modules.Games.WoW
private readonly GamePointersCollection _pointer; private readonly GamePointersCollection _pointer;
private ProcessSharp _process; private ProcessSharp _process;
public WoWModel(MainManager mainManager) public WoWModel(DeviceManager deviceManager)
: base(mainManager, SettingsProvider.Load<WoWSettings>(), new WoWDataModel()) : base(deviceManager, SettingsProvider.Load<WoWSettings>(), new WoWDataModel())
{ {
Name = "WoW"; Name = "WoW";
ProcessName = "Wow-64"; ProcessName = "Wow-64";
Scale = 4; Scale = 4;
// Currently WoW is locked behind a hidden trigger (obviously not that hidden if you're reading this) // Currently WoW is locked behind a hidden trigger (obviously not that hidden since you're reading this)
// It is using memory reading and lets first try to contact Blizzard // It is using memory reading and lets first try to contact Blizzard
var settings = SettingsProvider.Load<GeneralSettings>(); var settings = SettingsProvider.Load<GeneralSettings>();
Enabled = settings.GamestatePort == 62575 && Settings.Enabled; Enabled = (settings.GamestatePort == 62575) && Settings.Enabled;
Initialized = false; Initialized = false;
_pointer = SettingsProvider.Load<OffsetSettings>().WorldOfWarcraft; _pointer = SettingsProvider.Load<OffsetSettings>().WorldOfWarcraft;
//_pointer = new GamePointersCollection //_pointer = new GamePointersCollection
//{ //{
// Game = "WorldOfWarcraft", // Game = "WorldOfWarcraft",
@ -71,8 +70,9 @@ namespace Artemis.Modules.Games.WoW
{ {
Initialized = false; Initialized = false;
_process.Dispose(); _process?.Dispose();
_process = null; _process = null;
base.Dispose();
} }
public override void Enable() public override void Enable()
@ -102,7 +102,7 @@ namespace Artemis.Modules.Games.WoW
_pointer.GameAddresses.First(a => a.Description == "TargetGuid").BasePointer, true); _pointer.GameAddresses.First(a => a.Description == "TargetGuid").BasePointer, true);
dataModel.Player = player; dataModel.Player = player;
if (dataModel.Player != null && dataModel.Player.Guid != Guid.Empty) if ((dataModel.Player != null) && (dataModel.Player.Guid != Guid.Empty))
{ {
dataModel.Player.UpdateDetails(nameCache); dataModel.Player.UpdateDetails(nameCache);
var target = player.GetTarget(objectManager); var target = player.GetTarget(objectManager);

View File

@ -1,13 +1,14 @@
using Artemis.InjectionFactories; using Artemis.Managers;
using Artemis.Managers; using Artemis.Models;
using Artemis.ViewModels.Abstract; using Artemis.ViewModels.Abstract;
using Ninject;
namespace Artemis.Modules.Games.WoW namespace Artemis.Modules.Games.WoW
{ {
public sealed class WoWViewModel : GameViewModel public sealed class WoWViewModel : GameViewModel
{ {
public WoWViewModel(MainManager main, IProfileEditorVmFactory pFactory, WoWModel model) public WoWViewModel(MainManager main, IKernel kernel, [Named("WoWModel")] GameModel model)
: base(main, model, pFactory) : base(main, model, kernel)
{ {
DisplayName = "WoW"; DisplayName = "WoW";
} }

View File

@ -13,12 +13,11 @@ namespace Artemis.Modules.Overlays.VolumeDisplay
{ {
public class VolumeDisplayModel : OverlayModel public class VolumeDisplayModel : OverlayModel
{ {
public VolumeDisplayModel(MainManager mainManager) public VolumeDisplayModel(DeviceManager deviceManager): base(deviceManager, SettingsProvider.Load<VolumeDisplaySettings>())
: base(mainManager, SettingsProvider.Load<VolumeDisplaySettings>())
{ {
Name = "VolumeDisplay"; Name = "VolumeDisplay";
Settings = (VolumeDisplaySettings) base.Settings; Settings = (VolumeDisplaySettings) base.Settings;
VolumeDisplay = new VolumeBar(MainManager.DeviceManager, Settings); VolumeDisplay = new VolumeBar(DeviceManager, Settings);
} }
public new VolumeDisplaySettings Settings { get; set; } public new VolumeDisplaySettings Settings { get; set; }
@ -79,7 +78,7 @@ namespace Artemis.Modules.Overlays.VolumeDisplay
public override void RenderOverlay(RenderFrame frame, bool keyboardOnly) public override void RenderOverlay(RenderFrame frame, bool keyboardOnly)
{ {
if ((MainManager.DeviceManager.ActiveKeyboard == null) || (VolumeDisplay == null) || (VolumeDisplay.Ttl < 1)) if ((DeviceManager.ActiveKeyboard == null) || (VolumeDisplay == null) || (VolumeDisplay.Ttl < 1))
return; return;
using (var g = Graphics.FromImage(frame.KeyboardBitmap)) using (var g = Graphics.FromImage(frame.KeyboardBitmap))

View File

@ -1,6 +1,8 @@
using System.Windows.Media; using System.Windows.Media;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Models;
using Artemis.ViewModels.Abstract; using Artemis.ViewModels.Abstract;
using Ninject;
namespace Artemis.Modules.Overlays.VolumeDisplay namespace Artemis.Modules.Overlays.VolumeDisplay
{ {
@ -10,13 +12,14 @@ namespace Artemis.Modules.Overlays.VolumeDisplay
private SolidColorBrush _mainColor; private SolidColorBrush _mainColor;
private SolidColorBrush _secondaryColor; private SolidColorBrush _secondaryColor;
public VolumeDisplayViewModel(MainManager mainManager, VolumeDisplayModel model) : base(mainManager, model) public VolumeDisplayViewModel(MainManager mainManager, [Named("VolumeDisplayModel")] OverlayModel model)
: base(mainManager, model)
{ {
_model = model; _model = (VolumeDisplayModel) model;
DisplayName = "Volume Display"; DisplayName = "Volume Display";
MainColor = new SolidColorBrush(model.Settings.MainColor); MainColor = new SolidColorBrush(_model.Settings.MainColor);
SecondaryColor = new SolidColorBrush(model.Settings.SecondaryColor); SecondaryColor = new SolidColorBrush(_model.Settings.SecondaryColor);
} }
public Brush MainColor public Brush MainColor

View File

@ -531,6 +531,7 @@
<xs:element name="useDefaultRowHighlightingRules" minOccurs="0" maxOccurs="1" type="xs:boolean" /> <xs:element name="useDefaultRowHighlightingRules" minOccurs="0" maxOccurs="1" type="xs:boolean" />
<xs:element name="highlight-row" minOccurs="0" maxOccurs="unbounded" type="NLog.Targets.ConsoleRowHighlightingRule" /> <xs:element name="highlight-row" minOccurs="0" maxOccurs="unbounded" type="NLog.Targets.ConsoleRowHighlightingRule" />
<xs:element name="highlight-word" minOccurs="0" maxOccurs="unbounded" type="NLog.Targets.ConsoleWordHighlightingRule" /> <xs:element name="highlight-word" minOccurs="0" maxOccurs="unbounded" type="NLog.Targets.ConsoleWordHighlightingRule" />
<xs:element name="detectConsoleAvailable" minOccurs="0" maxOccurs="1" type="xs:boolean" />
<xs:element name="encoding" minOccurs="0" maxOccurs="1" type="xs:string" /> <xs:element name="encoding" minOccurs="0" maxOccurs="1" type="xs:string" />
<xs:element name="errorStream" minOccurs="0" maxOccurs="1" type="xs:boolean" /> <xs:element name="errorStream" minOccurs="0" maxOccurs="1" type="xs:boolean" />
</xs:choice> </xs:choice>
@ -559,6 +560,11 @@
<xs:documentation>Indicates whether to use default row highlighting rules.</xs:documentation> <xs:documentation>Indicates whether to use default row highlighting rules.</xs:documentation>
</xs:annotation> </xs:annotation>
</xs:attribute> </xs:attribute>
<xs:attribute name="detectConsoleAvailable" type="xs:boolean">
<xs:annotation>
<xs:documentation>Indicates whether to auto-check if the console is available. - Disables console writing if Environment.UserInteractive = False (Windows Service) - Disables console writing if Console Standard Input is not available (Non-Console-App)</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="encoding" type="xs:string"> <xs:attribute name="encoding" type="xs:string">
<xs:annotation> <xs:annotation>
<xs:documentation>The encoding for writing messages to the .</xs:documentation> <xs:documentation>The encoding for writing messages to the .</xs:documentation>
@ -670,6 +676,7 @@
<xs:element name="header" minOccurs="0" maxOccurs="1" type="Layout" /> <xs:element name="header" minOccurs="0" maxOccurs="1" type="Layout" />
<xs:element name="footer" minOccurs="0" maxOccurs="1" type="Layout" /> <xs:element name="footer" minOccurs="0" maxOccurs="1" type="Layout" />
<xs:element name="error" minOccurs="0" maxOccurs="1" type="xs:boolean" /> <xs:element name="error" minOccurs="0" maxOccurs="1" type="xs:boolean" />
<xs:element name="detectConsoleAvailable" minOccurs="0" maxOccurs="1" type="xs:boolean" />
<xs:element name="encoding" minOccurs="0" maxOccurs="1" type="xs:string" /> <xs:element name="encoding" minOccurs="0" maxOccurs="1" type="xs:string" />
</xs:choice> </xs:choice>
<xs:attribute name="name" type="xs:string"> <xs:attribute name="name" type="xs:string">
@ -697,6 +704,11 @@
<xs:documentation>Indicates whether to send the log messages to the standard error instead of the standard output.</xs:documentation> <xs:documentation>Indicates whether to send the log messages to the standard error instead of the standard output.</xs:documentation>
</xs:annotation> </xs:annotation>
</xs:attribute> </xs:attribute>
<xs:attribute name="detectConsoleAvailable" type="xs:boolean">
<xs:annotation>
<xs:documentation>Indicates whether to auto-check if the console is available - Disables console writing if Environment.UserInteractive = False (Windows Service) - Disables console writing if Console Standard Input is not available (Non-Console-App)</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="encoding" type="xs:string"> <xs:attribute name="encoding" type="xs:string">
<xs:annotation> <xs:annotation>
<xs:documentation>The encoding for writing messages to the .</xs:documentation> <xs:documentation>The encoding for writing messages to the .</xs:documentation>

View File

@ -35,7 +35,7 @@ namespace Artemis.Profiles.Layers.Animations
const int scale = 4; const int scale = 4;
// Set up variables for this frame // Set up variables for this frame
var rect = props.Contain var rect = applied.Contain
? new Rect(applied.X*scale, applied.Y*scale, applied.Width*scale, applied.Height*scale) ? new Rect(applied.X*scale, applied.Y*scale, applied.Width*scale, applied.Height*scale)
: new Rect(props.X*scale, props.Y*scale, props.Width*scale, props.Height*scale); : new Rect(props.X*scale, props.Y*scale, props.Width*scale, props.Height*scale);

View File

@ -35,7 +35,7 @@ namespace Artemis.Profiles.Layers.Animations
const int scale = 4; const int scale = 4;
// Set up variables for this frame // Set up variables for this frame
var rect = props.Contain var rect = applied.Contain
? new Rect(applied.X*scale, applied.Y*scale, applied.Width*scale, applied.Height*scale) ? new Rect(applied.X*scale, applied.Y*scale, applied.Width*scale, applied.Height*scale)
: new Rect(props.X*scale, props.Y*scale, props.Width*scale, props.Height*scale); : new Rect(props.X*scale, props.Y*scale, props.Width*scale, props.Height*scale);

View File

@ -28,7 +28,7 @@ namespace Artemis.Profiles.Layers.Animations
const int scale = 4; const int scale = 4;
// Set up variables for this frame // Set up variables for this frame
var rect = props.Contain var rect = applied.Contain
? new Rect(applied.X*scale, applied.Y*scale, applied.Width*scale, applied.Height*scale) ? new Rect(applied.X*scale, applied.Y*scale, applied.Width*scale, applied.Height*scale)
: new Rect(props.X*scale, props.Y*scale, props.Width*scale, props.Height*scale); : new Rect(props.X*scale, props.Y*scale, props.Width*scale, props.Height*scale);

View File

@ -28,7 +28,7 @@ namespace Artemis.Profiles.Layers.Animations
const int scale = 4; const int scale = 4;
// Set up variables for this frame // Set up variables for this frame
var rect = props.Contain var rect = applied.Contain
? new Rect(applied.X*scale, applied.Y*scale, applied.Width*scale, applied.Height*scale) ? new Rect(applied.X*scale, applied.Y*scale, applied.Width*scale, applied.Height*scale)
: new Rect(props.X*scale, props.Y*scale, props.Width*scale, props.Height*scale); : new Rect(props.X*scale, props.Y*scale, props.Width*scale, props.Height*scale);

View File

@ -28,7 +28,7 @@ namespace Artemis.Profiles.Layers.Animations
const int scale = 4; const int scale = 4;
// Set up variables for this frame // Set up variables for this frame
var rect = props.Contain var rect = applied.Contain
? new Rect(applied.X*scale, applied.Y*scale, applied.Width*scale, applied.Height*scale) ? new Rect(applied.X*scale, applied.Y*scale, applied.Width*scale, applied.Height*scale)
: new Rect(props.X*scale, props.Y*scale, props.Width*scale, props.Height*scale); : new Rect(props.X*scale, props.Y*scale, props.Width*scale, props.Height*scale);

View File

@ -28,7 +28,7 @@ namespace Artemis.Profiles.Layers.Animations
const int scale = 4; const int scale = 4;
// Set up variables for this frame // Set up variables for this frame
var rect = props.Contain var rect = applied.Contain
? new Rect(applied.X*scale, applied.Y*scale, applied.Width*scale, applied.Height*scale) ? new Rect(applied.X*scale, applied.Y*scale, applied.Width*scale, applied.Height*scale)
: new Rect(props.X*scale, props.Y*scale, props.Width*scale, props.Height*scale); : new Rect(props.X*scale, props.Y*scale, props.Width*scale, props.Height*scale);

View File

@ -0,0 +1,79 @@
using System;
using Artemis.Profiles.Layers.Types.AmbientLight.Model;
using Artemis.Profiles.Layers.Types.AmbientLight.Model.Extensions;
namespace Artemis.Profiles.Layers.Types.AmbientLight.AmbienceCreator
{
public class AmbienceCreatorExtend : IAmbienceCreator
{
#region Methods
public byte[] GetAmbience(byte[] pixels, int sourceWidth, int sourceHeight,
int targetWidth, int targetHeight,
AmbientLightPropertiesModel settings)
{
AvgColor[] colors = new AvgColor[targetWidth];
for (int i = 0; i < colors.Length; i++)
colors[i] = new AvgColor();
int offsetLeft = settings.OffsetLeft + (settings.BlackBarDetectionMode.HasFlag(BlackBarDetectionMode.Left)
? pixels.DetectBlackBarLeft(sourceWidth, sourceHeight, settings.OffsetLeft, settings.OffsetRight, settings.OffsetTop, settings.OffsetBottom)
: 0);
int offsetRight = settings.OffsetRight + (settings.BlackBarDetectionMode.HasFlag(BlackBarDetectionMode.Right)
? pixels.DetectBlackBarRight(sourceWidth, sourceHeight, settings.OffsetLeft, settings.OffsetRight, settings.OffsetTop, settings.OffsetBottom)
: 0);
int offsetTop = settings.OffsetTop + (settings.BlackBarDetectionMode.HasFlag(BlackBarDetectionMode.Top)
? pixels.DetectBlackBarTop(sourceWidth, sourceHeight, settings.OffsetLeft, settings.OffsetRight, settings.OffsetTop, settings.OffsetBottom)
: 0);
int offsetBottom = settings.OffsetBottom + (settings.BlackBarDetectionMode.HasFlag(BlackBarDetectionMode.Bottom)
? pixels.DetectBlackBarBottom(sourceWidth, sourceHeight, settings.OffsetLeft, settings.OffsetRight, settings.OffsetTop, settings.OffsetBottom)
: 0);
int effectiveSourceWidth = sourceWidth - offsetLeft - offsetRight;
int effectiveSourceHeight = sourceHeight - offsetTop - offsetBottom;
int relevantSourceHeight = (int)Math.Round(effectiveSourceHeight * (settings.MirroredAmount / 100.0));
int relevantOffsetTop = sourceHeight - offsetBottom - relevantSourceHeight;
double widthPixels = effectiveSourceWidth / (double)targetWidth;
double heightPixels = relevantSourceHeight / (double)targetHeight;
if (widthPixels <= 0 || heightPixels <= 0 || (relevantSourceHeight + relevantOffsetTop > sourceHeight) ||
effectiveSourceWidth > sourceWidth)
{
colors = colors.ExtendHeight(targetHeight);
return colors.ToBGRArray();
}
int increment = Math.Max(1, Math.Min(20, settings.Downsampling));
for (int y = 0; y < relevantSourceHeight; y += increment)
{
int targetWidthIndex = 0;
double widthCounter = widthPixels;
for (int x = 0; x < effectiveSourceWidth; x += increment)
{
if (x >= widthCounter)
{
widthCounter += widthPixels;
targetWidthIndex++;
}
int colorsOffset = targetWidthIndex;
int sourceOffset = ((((relevantOffsetTop + y) * sourceWidth) + offsetLeft + x) * 4);
AvgColor color = colors[colorsOffset];
color.AddB(pixels[sourceOffset]);
color.AddG(pixels[sourceOffset + 1]);
color.AddR(pixels[sourceOffset + 2]);
}
}
colors = colors.Flip(targetWidth, settings.FlipMode);
colors = colors.ExtendHeight(targetHeight);
return colors.ToBGRArray();
}
#endregion
}
}

View File

@ -0,0 +1,83 @@
using System;
using Artemis.Profiles.Layers.Types.AmbientLight.Model;
using Artemis.Profiles.Layers.Types.AmbientLight.Model.Extensions;
namespace Artemis.Profiles.Layers.Types.AmbientLight.AmbienceCreator
{
public class AmbienceCreatorMirror : IAmbienceCreator
{
#region Methods
public byte[] GetAmbience(byte[] pixels, int sourceWidth, int sourceHeight,
int targetWidth, int targetHeight,
AmbientLightPropertiesModel settings)
{
AvgColor[] colors = new AvgColor[targetWidth * targetHeight];
for (int i = 0; i < colors.Length; i++)
colors[i] = new AvgColor();
int offsetLeft = settings.OffsetLeft + (settings.BlackBarDetectionMode.HasFlag(BlackBarDetectionMode.Left)
? pixels.DetectBlackBarLeft(sourceWidth, sourceHeight, settings.OffsetLeft, settings.OffsetRight, settings.OffsetTop, settings.OffsetBottom)
: 0);
int offsetRight = settings.OffsetRight + (settings.BlackBarDetectionMode.HasFlag(BlackBarDetectionMode.Right)
? pixels.DetectBlackBarRight(sourceWidth, sourceHeight, settings.OffsetLeft, settings.OffsetRight, settings.OffsetTop, settings.OffsetBottom)
: 0);
int offsetTop = settings.OffsetTop + (settings.BlackBarDetectionMode.HasFlag(BlackBarDetectionMode.Top)
? pixels.DetectBlackBarTop(sourceWidth, sourceHeight, settings.OffsetLeft, settings.OffsetRight, settings.OffsetTop, settings.OffsetBottom)
: 0);
int offsetBottom = settings.OffsetBottom + (settings.BlackBarDetectionMode.HasFlag(BlackBarDetectionMode.Bottom)
? pixels.DetectBlackBarBottom(sourceWidth, sourceHeight, settings.OffsetLeft, settings.OffsetRight, settings.OffsetTop, settings.OffsetBottom)
: 0);
int effectiveSourceWidth = sourceWidth - offsetLeft - offsetRight;
int effectiveSourceHeight = sourceHeight - offsetTop - offsetBottom;
int relevantSourceHeight = (int)Math.Round(effectiveSourceHeight * (settings.MirroredAmount / 100.0));
int relevantOffsetTop = sourceHeight - offsetBottom - relevantSourceHeight;
double widthPixels = effectiveSourceWidth / (double)targetWidth;
double heightPixels = relevantSourceHeight / (double)targetHeight;
if (widthPixels <= 0 || heightPixels <= 0 || (relevantSourceHeight + relevantOffsetTop > sourceHeight) || effectiveSourceWidth > sourceWidth)
return colors.ToBGRArray();
int targetHeightIndex = 0;
double heightCounter = heightPixels;
int increment = Math.Max(1, Math.Min(20, settings.Downsampling));
for (int y = 0; y < relevantSourceHeight; y += increment)
{
if (y >= heightCounter)
{
heightCounter += heightPixels;
targetHeightIndex++;
}
int targetWidthIndex = 0;
double widthCounter = widthPixels;
for (int x = 0; x < effectiveSourceWidth; x += increment)
{
if (x >= widthCounter)
{
widthCounter += widthPixels;
targetWidthIndex++;
}
int colorsOffset = (targetHeightIndex * targetWidth) + targetWidthIndex;
int sourceOffset = ((((relevantOffsetTop + y) * sourceWidth) + offsetLeft + x) * 4);
AvgColor color = colors[colorsOffset];
color.AddB(pixels[sourceOffset]);
color.AddG(pixels[sourceOffset + 1]);
color.AddR(pixels[sourceOffset + 2]);
}
}
colors = colors.Flip(targetWidth, settings.FlipMode);
return colors.ToBGRArray();
}
#endregion
}
}

View File

@ -0,0 +1,42 @@
namespace Artemis.Profiles.Layers.Types.AmbientLight.AmbienceCreator
{
public class AvgColor
{
#region Properties & Fields
private int _rCount = 0;
private int _r = 0;
private int _gCount = 0;
private int _g = 0;
private int _bCount = 0;
private int _b = 0;
public byte R => (byte)(_rCount > 0 ? (_r / _rCount) : 0);
public byte G => (byte)(_gCount > 0 ? (_g / _gCount) : 0);
public byte B => (byte)(_bCount > 0 ? (_b / _bCount) : 0);
#endregion
#region Methods
public void AddR(byte r)
{
_r += r;
_rCount++;
}
public void AddG(byte g)
{
_g += g;
_gCount++;
}
public void AddB(byte b)
{
_b += b;
_bCount++;
}
#endregion
}
}

View File

@ -0,0 +1,7 @@
namespace Artemis.Profiles.Layers.Types.AmbientLight.AmbienceCreator
{
public interface IAmbienceCreator
{
byte[] GetAmbience(byte[] pixels, int sourceWidth, int sourceHeight, int targetWidth, int targetHeight, AmbientLightPropertiesModel settings);
}
}

View File

@ -0,0 +1,42 @@
using System.Windows.Media;
using Artemis.Profiles.Layers.Models;
using Artemis.Profiles.Layers.Types.AmbientLight.Model;
using Newtonsoft.Json;
namespace Artemis.Profiles.Layers.Types.AmbientLight
{
public class AmbientLightPropertiesModel : LayerPropertiesModel
{
#region Properties & Fields
//HACK DarthAffe 30.10.2016: The 'normal' Brush-Property destoys the profile since Drawing-Brushes cannot be deserialized.
[JsonIgnore]
public Brush AmbientLightBrush { get; set; }
public AmbienceCreatorType AmbienceCreatorType { get; set; } = AmbienceCreatorType.Mirror;
public int OffsetLeft { get; set; } = 0;
public int OffsetRight { get; set; } = 0;
public int OffsetTop { get; set; } = 0;
public int OffsetBottom { get; set; } = 0;
public int Downsampling { get; set; } = 2;
public double MirroredAmount { get; set; } = 10;
public SmoothMode SmoothMode { get; set; } = SmoothMode.Low;
public BlackBarDetectionMode BlackBarDetectionMode { get; set; } = BlackBarDetectionMode.Bottom;
public FlipMode FlipMode { get; set; } = FlipMode.Vertical;
#endregion
#region Constructors
public AmbientLightPropertiesModel(LayerPropertiesModel properties)
: base(properties)
{
Brush = new SolidColorBrush(Color.FromRgb(0, 0, 0));
}
#endregion
}
}

View File

@ -0,0 +1,156 @@
<UserControl x:Class="Artemis.Profiles.Layers.Types.AmbientLight.AmbientLightPropertiesView"
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:converters="clr-namespace:Artemis.Utilities.Converters"
xmlns:system="clr-namespace:System;assembly=mscorlib"
xmlns:model="clr-namespace:Artemis.Profiles.Layers.Types.AmbientLight.Model"
xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
xmlns:helper="clr-namespace:Artemis.Profiles.Layers.Types.AmbientLight.Helper"
mc:Ignorable="d"
d:DesignHeight="600" d:DesignWidth="500">
<UserControl.Resources>
<converters:EnumDescriptionConverter x:Key="HEnumDescriptionConverter" />
<ObjectDataProvider x:Key="SmoothModeEnumValues" ObjectType="{x:Type system:Enum}" MethodName="GetValues">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="model:SmoothMode" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<ObjectDataProvider x:Key="AmbienceCreatorTypeValues" ObjectType="{x:Type system:Enum}" MethodName="GetValues">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="model:AmbienceCreatorType" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</UserControl.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<!-- AmbienceCreatorType -->
<TextBlock Grid.Row="0" Grid.Column="0" Margin="10,13,10,10" FontSize="13.333" Text="Ambilight-Mode:"
VerticalAlignment="Top" Height="18" />
<ComboBox Grid.Row="0" Grid.Column="1" ItemsSource="{Binding Source={StaticResource AmbienceCreatorTypeValues}}"
Margin="10,10,10,0" SelectedItem="{Binding Path=LayerModel.Properties.AmbienceCreatorType}"
VerticalAlignment="Top" Height="22">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Converter={StaticResource HEnumDescriptionConverter}}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<!-- MirrorAmount & Downsampling-->
<TextBlock Grid.Row="1" Grid.Column="0" Margin="10,13,10,10" FontSize="13.333" Text="Mirrored Amount (%):"
Height="18" VerticalAlignment="Top" />
<controls:NumericUpDown Grid.Row="1" Grid.Column="1" VerticalAlignment="Top" Minimum="0" Maximum="100"
Value="{Binding Path=LayerModel.Properties.MirroredAmount, Mode=TwoWay}" Margin="10,12,10,2" Height="24" />
<TextBlock Grid.Row="1" Grid.Column="2" Margin="10,13,10,10" FontSize="13.333" Text="Downsampling:"
Height="18" VerticalAlignment="Top" />
<controls:NumericUpDown Grid.Row="1" Grid.Column="3" VerticalAlignment="Top" Minimum="1" Maximum="20"
Value="{Binding Path=LayerModel.Properties.Downsampling, Mode=TwoWay}" Margin="10,12,10,2" Height="24" />
<!-- SmoothMode -->
<TextBlock Grid.Row="2" Grid.Column="0" Margin="10,13,10,10" FontSize="13.333" Text="Smoothing:"
VerticalAlignment="Top" Height="18" />
<ComboBox Grid.Row="2" Grid.Column="1" ItemsSource="{Binding Source={StaticResource SmoothModeEnumValues}}"
Margin="10,10,10,0" SelectedItem="{Binding Path=LayerModel.Properties.SmoothMode}"
VerticalAlignment="Top" Height="22">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Converter={StaticResource HEnumDescriptionConverter}}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<!-- FlipMode -->
<TextBlock Grid.Row="3" Grid.Column="0" Margin="10,13,10,10" FontSize="13.333" Text="Flip Horizontal:"
Height="18" VerticalAlignment="Top" />
<CheckBox Grid.Row="3" Grid.Column="1" VerticalAlignment="Top" Margin="10,12,10,2" Height="24"
helper:CheckboxEnumFlagHelper.Value="{x:Static model:FlipMode.Horizontal}"
helper:CheckboxEnumFlagHelper.Flags="{Binding Path=LayerModel.Properties.FlipMode}" />
<TextBlock Grid.Row="3" Grid.Column="2" Margin="10,13,10,10" FontSize="13.333" Text="Flip Vertical:"
Height="18" VerticalAlignment="Top" />
<CheckBox Grid.Row="3" Grid.Column="3" VerticalAlignment="Top" Margin="10,12,10,2" Height="24"
helper:CheckboxEnumFlagHelper.Value="{x:Static model:FlipMode.Vertical}"
helper:CheckboxEnumFlagHelper.Flags="{Binding Path=LayerModel.Properties.FlipMode}" />
<!-- Horizontal offsets -->
<TextBlock Grid.Row="4" Grid.Column="0" Margin="10,20,10,3" FontSize="13.333" Text="Offset"
Height="18" VerticalAlignment="Top" FontWeight="Black" />
<TextBlock Grid.Row="5" Grid.Column="0" Margin="10,13,10,10" FontSize="13.333" Text="Left:"
Height="18" VerticalAlignment="Top" />
<controls:NumericUpDown Grid.Row="5" Grid.Column="1" VerticalAlignment="Top" Minimum="0"
Value="{Binding Path=LayerModel.Properties.OffsetLeft, Mode=TwoWay}" Margin="10,12,10,2" Height="24" />
<TextBlock Grid.Row="5" Grid.Column="2" Margin="10,13,10,10" FontSize="13.333" Text="Right:"
Height="18" VerticalAlignment="Top" />
<controls:NumericUpDown Grid.Row="5" Grid.Column="3" VerticalAlignment="Top" Minimum="0"
Value="{Binding Path=LayerModel.Properties.OffsetRight, Mode=TwoWay}" Margin="10,12,10,2" Height="24" />
<!-- Vertical offsets -->
<TextBlock Grid.Row="6" Grid.Column="0" Margin="10,13,10,10" FontSize="13.333" Text="Top:"
Height="18" VerticalAlignment="Top" />
<controls:NumericUpDown Grid.Row="6" Grid.Column="1" VerticalAlignment="Top" Minimum="0"
Value="{Binding Path=LayerModel.Properties.OffsetTop, Mode=TwoWay}" Margin="10,12,10,2" Height="24" />
<TextBlock Grid.Row="6" Grid.Column="2" Margin="10,13,10,10" FontSize="13.333" Text="Bottom:"
Height="18" VerticalAlignment="Top" />
<controls:NumericUpDown Grid.Row="6" Grid.Column="3" VerticalAlignment="Top" Minimum="0"
Value="{Binding Path=LayerModel.Properties.OffsetBottom, Mode=TwoWay}" Margin="10,12,10,2" Height="24" />
<!-- Horizontal BlackBar-detection -->
<TextBlock Grid.Row="7" Grid.Column="0" Margin="10,20,10,3" FontSize="13.333" Text="Black-Bar detection"
Height="18" VerticalAlignment="Top" FontWeight="Black" />
<TextBlock Grid.Row="8" Grid.Column="0" Margin="10,13,10,10" FontSize="13.333" Text="Left:"
Height="18" VerticalAlignment="Top" />
<CheckBox Grid.Row="8" Grid.Column="1" VerticalAlignment="Top" Margin="10,12,10,2" Height="24"
helper:CheckboxEnumFlagHelper.Value="{x:Static model:BlackBarDetectionMode.Left}"
helper:CheckboxEnumFlagHelper.Flags="{Binding Path=LayerModel.Properties.BlackBarDetectionMode}" />
<TextBlock Grid.Row="8" Grid.Column="2" Margin="10,13,10,10" FontSize="13.333" Text="Right:"
Height="18" VerticalAlignment="Top" />
<CheckBox Grid.Row="8" Grid.Column="3" VerticalAlignment="Top" Margin="10,12,10,2" Height="24"
helper:CheckboxEnumFlagHelper.Value="{x:Static model:BlackBarDetectionMode.Right}"
helper:CheckboxEnumFlagHelper.Flags="{Binding Path=LayerModel.Properties.BlackBarDetectionMode}" />
<!-- Vertical BlackBar-detection -->
<TextBlock Grid.Row="9" Grid.Column="0" Margin="10,13,10,10" FontSize="13.333" Text="Top:"
Height="18" VerticalAlignment="Top" />
<CheckBox Grid.Row="9" Grid.Column="1" VerticalAlignment="Top" Margin="10,12,10,2" Height="24"
helper:CheckboxEnumFlagHelper.Value="{x:Static model:BlackBarDetectionMode.Top}"
helper:CheckboxEnumFlagHelper.Flags="{Binding Path=LayerModel.Properties.BlackBarDetectionMode}" />
<TextBlock Grid.Row="9" Grid.Column="2" Margin="10,13,10,10" FontSize="13.333" Text="Bottom:"
Height="18" VerticalAlignment="Top" />
<CheckBox Grid.Row="9" Grid.Column="3" VerticalAlignment="Top" Margin="10,12,10,2" Height="24"
helper:CheckboxEnumFlagHelper.Value="{x:Static model:BlackBarDetectionMode.Bottom}"
helper:CheckboxEnumFlagHelper.Flags="{Binding Path=LayerModel.Properties.BlackBarDetectionMode}" />
</Grid>
</UserControl>

View File

@ -0,0 +1,12 @@
using System.Windows.Controls;
namespace Artemis.Profiles.Layers.Types.AmbientLight
{
public partial class AmbientLightPropertiesView : UserControl
{
public AmbientLightPropertiesView()
{
InitializeComponent();
}
}
}

View File

@ -0,0 +1,23 @@
using Artemis.Profiles.Layers.Abstract;
using Artemis.ViewModels.Profiles;
namespace Artemis.Profiles.Layers.Types.AmbientLight
{
public class AmbientLightPropertiesViewModel : LayerPropertiesViewModel
{
#region Constructors
public AmbientLightPropertiesViewModel(LayerEditorViewModel editorVm)
: base(editorVm)
{ }
#endregion
#region Methods
public override void ApplyProperties()
{ }
#endregion
}
}

View File

@ -0,0 +1,110 @@
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Artemis.Models.Interfaces;
using Artemis.Profiles.Layers.Abstract;
using Artemis.Profiles.Layers.Interfaces;
using Artemis.Profiles.Layers.Models;
using Artemis.Profiles.Layers.Types.AmbientLight.AmbienceCreator;
using Artemis.Profiles.Layers.Types.AmbientLight.Model;
using Artemis.Profiles.Layers.Types.AmbientLight.Model.Extensions;
using Artemis.Profiles.Layers.Types.AmbientLight.ScreenCapturing;
using Artemis.Properties;
using Artemis.Utilities;
using Artemis.ViewModels.Profiles;
using Newtonsoft.Json;
namespace Artemis.Profiles.Layers.Types.AmbientLight
{
public class AmbientLightType : ILayerType
{
#region Properties & Fields
public string Name => "Keyboard - Ambient Light";
public bool ShowInEdtor => true;
public DrawType DrawType => DrawType.Keyboard;
[JsonIgnore]
private AmbienceCreatorType? _lastAmbienceCreatorType = null;
[JsonIgnore]
private IAmbienceCreator _lastAmbienceCreator;
[JsonIgnore]
private byte[] _lastData;
#endregion
#region Methods
public LayerPropertiesViewModel SetupViewModel(LayerEditorViewModel layerEditorViewModel,
LayerPropertiesViewModel layerPropertiesViewModel)
{
if (layerPropertiesViewModel is AmbientLightPropertiesViewModel)
return layerPropertiesViewModel;
return new AmbientLightPropertiesViewModel(layerEditorViewModel);
}
public void SetupProperties(LayerModel layerModel)
{
if (layerModel.Properties is AmbientLightPropertiesModel)
return;
layerModel.Properties = new AmbientLightPropertiesModel(layerModel.Properties);
}
public void Update(LayerModel layerModel, IDataModel dataModel, bool isPreview = false)
{
AmbientLightPropertiesModel properties = layerModel?.Properties as AmbientLightPropertiesModel;
if (properties == null) return;
int width = (int)Math.Round(properties.Width);
int height = (int)Math.Round(properties.Height);
byte[] data = ScreenCaptureManager.GetLastScreenCapture();
byte[] newData = GetAmbienceCreator(properties).GetAmbience(data, ScreenCaptureManager.LastCaptureWidth, ScreenCaptureManager.LastCaptureHeight, width, height, properties);
_lastData = _lastData?.Blend(newData, properties.SmoothMode) ?? newData;
int stride = (width * ScreenCaptureManager.LastCapturePixelFormat.BitsPerPixel + 7) / 8;
properties.AmbientLightBrush = new DrawingBrush(new ImageDrawing
(BitmapSource.Create(width, height, 96, 96, ScreenCaptureManager.LastCapturePixelFormat, null, _lastData, stride), new Rect(0, 0, width, height)));
}
public void Draw(LayerModel layer, DrawingContext c)
{
Rect rect = new Rect(layer.Properties.X * 4,
layer.Properties.Y * 4,
layer.Properties.Width * 4,
layer.Properties.Height * 4);
c.DrawRectangle(((AmbientLightPropertiesModel)layer.Properties).AmbientLightBrush, null, rect);
}
public ImageSource DrawThumbnail(LayerModel layer)
{
Rect thumbnailRect = new Rect(0, 0, 18, 18);
DrawingVisual visual = new DrawingVisual();
using (DrawingContext c = visual.RenderOpen())
c.DrawImage(ImageUtilities.BitmapToBitmapImage(Resources.ambilight), thumbnailRect);
return new DrawingImage(visual.Drawing);
}
private IAmbienceCreator GetAmbienceCreator(AmbientLightPropertiesModel properties)
{
if (_lastAmbienceCreatorType == properties.AmbienceCreatorType)
return _lastAmbienceCreator;
_lastAmbienceCreatorType = properties.AmbienceCreatorType;
switch (properties.AmbienceCreatorType)
{
case AmbienceCreatorType.Mirror: return _lastAmbienceCreator = new AmbienceCreatorMirror();
case AmbienceCreatorType.Extend: return _lastAmbienceCreator = new AmbienceCreatorExtend();
default: throw new InvalidEnumArgumentException();
}
}
#endregion
}
}

View File

@ -0,0 +1,93 @@
using System;
using System.Windows;
using System.Windows.Controls;
using Artemis.Profiles.Layers.Types.AmbientLight.Model.Extensions;
namespace Artemis.Profiles.Layers.Types.AmbientLight.Helper
{
public class CheckboxEnumFlagHelper
{
#region DependencyProperties
// ReSharper disable InconsistentNaming
public static readonly DependencyProperty FlagsProperty = DependencyProperty.RegisterAttached(
"Flags", typeof(Enum), typeof(CheckboxEnumFlagHelper), new FrameworkPropertyMetadata(default(Enum), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, FlagsChanged));
public static void SetFlags(DependencyObject element, Enum value)
{
element.SetValue(FlagsProperty, value);
}
public static Enum GetFlags(DependencyObject element)
{
return (Enum)element.GetValue(FlagsProperty);
}
public static readonly DependencyProperty ValueProperty = DependencyProperty.RegisterAttached(
"Value", typeof(Enum), typeof(CheckboxEnumFlagHelper), new PropertyMetadata(default(Enum), ValueChanged));
public static void SetValue(DependencyObject element, Enum value)
{
element.SetValue(ValueProperty, value);
}
public static Enum GetValue(DependencyObject element)
{
return (Enum)element.GetValue(ValueProperty);
}
// ReSharper restore InconsistentNaming
#endregion
#region Methods
private static void FlagsChanged(DependencyObject dependencyObject,
DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
{
UpdateTarget(dependencyObject as CheckBox, dependencyPropertyChangedEventArgs.NewValue as Enum);
}
private static void ValueChanged(DependencyObject dependencyObject,
DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
{
CheckBox checkbox = dependencyObject as CheckBox;
if (checkbox == null) return;
checkbox.Checked -= UpdateSource;
checkbox.Unchecked -= UpdateSource;
if (dependencyPropertyChangedEventArgs.NewValue != null)
{
checkbox.Checked += UpdateSource;
checkbox.Unchecked += UpdateSource;
}
UpdateTarget(checkbox, GetFlags(checkbox));
}
private static void UpdateTarget(CheckBox checkbox, Enum flags)
{
if (checkbox == null) return;
Enum value = GetValue(checkbox);
checkbox.IsChecked = value != null && (flags?.HasFlag(value) ?? false);
}
private static void UpdateSource(object sender, RoutedEventArgs routedEventArgs)
{
CheckBox checkbox = sender as CheckBox;
if (checkbox == null) return;
Enum flags = GetFlags(checkbox);
Enum value = GetValue(checkbox);
if (value == null) return;
if (checkbox.IsChecked ?? false)
SetFlags(checkbox, flags == null ? value : flags.SetFlag(value, true, flags.GetType()));
else
SetFlags(checkbox, flags?.SetFlag(value, false, flags.GetType()));
}
#endregion
}
}

View File

@ -0,0 +1,13 @@
using System.ComponentModel;
namespace Artemis.Profiles.Layers.Types.AmbientLight.Model
{
public enum AmbienceCreatorType
{
[Description("Mirror")]
Mirror,
[Description("Extend")]
Extend
}
}

View File

@ -0,0 +1,14 @@
using System;
namespace Artemis.Profiles.Layers.Types.AmbientLight.Model
{
[Flags]
public enum BlackBarDetectionMode
{
None = 0,
Left = 1 << 0,
Right = 1 << 1,
Top = 1 << 2,
Bottom = 1 << 3,
}
}

View File

@ -0,0 +1,74 @@
using System;
using System.Linq;
using Artemis.Profiles.Layers.Types.AmbientLight.AmbienceCreator;
namespace Artemis.Profiles.Layers.Types.AmbientLight.Model.Extensions
{
public static class AvgColorExtension
{
#region Methods
public static AvgColor[] Flip(this AvgColor[] colors, int width, FlipMode flipMode)
{
if (colors == null || width <= 0) return colors;
if (flipMode.HasFlag(FlipMode.Vertical))
return flipMode.HasFlag(FlipMode.Horizontal) ? colors.Reverse().ToArray() : colors.FlipVertical(width);
if (flipMode.HasFlag(FlipMode.Horizontal))
return colors.FlipHorizontal(width);
return colors;
}
public static AvgColor[] ExtendHeight(this AvgColor[] colors, int height)
{
AvgColor[] extended = new AvgColor[colors.Length * height];
for (int i = 0; i < height; i++)
Array.Copy(colors, 0, extended, i * colors.Length, colors.Length);
return extended;
}
public static AvgColor[] FlipVertical(this AvgColor[] colors, int width)
{
if (colors == null || width <= 0) return colors;
AvgColor[] flipped = new AvgColor[colors.Length];
for (int i = 0, j = colors.Length - width; i < colors.Length; i += width, j -= width)
for (int k = 0; k < width; ++k)
flipped[i + k] = colors[j + k];
return flipped;
}
public static AvgColor[] FlipHorizontal(this AvgColor[] colors, int width)
{
if (colors == null || width <= 0) return colors;
AvgColor[] flipped = new AvgColor[colors.Length];
for (int i = 0; i < colors.Length; i += width)
for (int j = 0, k = width - 1; j < width; ++j, --k)
flipped[i + j] = colors[i + k];
return flipped;
}
public static byte[] ToBGRArray(this AvgColor[] colors)
{
byte[] newData = new byte[colors.Length * 3];
int counter = 0;
foreach (AvgColor color in colors)
{
newData[counter++] = color.B;
newData[counter++] = color.G;
newData[counter++] = color.R;
}
return newData;
}
#endregion
}
}

View File

@ -0,0 +1,26 @@
using System;
namespace Artemis.Profiles.Layers.Types.AmbientLight.Model.Extensions
{
public static class EnumExtension
{
#region Methods
public static Enum SetFlag(this Enum e, Enum value, bool set, Type t)
{
if (e == null || value == null || t == null) return e;
int eValue = Convert.ToInt32(e);
int valueValue = Convert.ToInt32(value);
if (set)
eValue |= valueValue;
else
eValue &= ~valueValue;
return (Enum)Enum.ToObject(t, eValue);
}
#endregion
}
}

View File

@ -0,0 +1,111 @@
using System;
namespace Artemis.Profiles.Layers.Types.AmbientLight.Model.Extensions
{
public static class PixelDataExtension
{
#region Methods
public static int DetectBlackBarLeft(this byte[] pixels, int width, int height, int offsetLeft, int offsetRight, int offsetTop, int offsetBottom)
{
int bottomBorder = height - offsetBottom;
int rightBorder = width - offsetRight;
int blackBarWidth = 0;
for (int x = rightBorder - 1; x >= offsetLeft; x--)
{
for (int y = offsetTop; y < bottomBorder; y++)
{
int offset = ((y * width) + x) * 4;
if (pixels[offset] > 15 || pixels[offset + 1] > 15 || pixels[offset + 2] > 15)
return blackBarWidth;
}
blackBarWidth++;
}
return width;
}
public static int DetectBlackBarRight(this byte[] pixels, int width, int height, int offsetLeft, int offsetRight, int offsetTop, int offsetBottom)
{
int bottomBorder = height - offsetBottom;
int rightBorder = width - offsetRight;
int blackBarWidth = 0;
for (int x = offsetLeft; x < rightBorder; x++)
{
for (int y = offsetTop; y < bottomBorder; y++)
{
int offset = ((y * width) + x) * 4;
if (pixels[offset] > 15 || pixels[offset + 1] > 15 || pixels[offset + 2] > 15)
return blackBarWidth;
}
blackBarWidth++;
}
return width;
}
public static int DetectBlackBarTop(this byte[] pixels, int width, int height, int offsetLeft, int offsetRight, int offsetTop, int offsetBottom)
{
int bottomBorder = height - offsetBottom;
int rightBorder = width - offsetRight;
int blackBarHeight = 0;
for (int y = offsetTop; y < bottomBorder; y++)
{
for (int x = offsetLeft; x < rightBorder; x++)
{
int offset = ((y * width) + x) * 4;
if (pixels[offset] > 15 || pixels[offset + 1] > 15 || pixels[offset + 2] > 15)
return blackBarHeight;
}
blackBarHeight++;
}
return height;
}
public static int DetectBlackBarBottom(this byte[] pixels, int width, int height, int offsetLeft, int offsetRight, int offsetTop, int offsetBottom)
{
int bottomBorder = height - offsetBottom;
int rightBorder = width - offsetRight;
int blackBarHeight = 0;
for (int y = bottomBorder - 1; y >= offsetTop; y--)
{
for (int x = offsetLeft; x < rightBorder; x++)
{
int offset = ((y * width) + x) * 4;
if (pixels[offset] > 15 || pixels[offset + 1] > 15 || pixels[offset + 2] > 15)
return blackBarHeight;
}
blackBarHeight++;
}
return height;
}
public static byte[] Blend(this byte[] pixels, byte[] blendPixels, SmoothMode smoothMode)
{
if (smoothMode == SmoothMode.None || pixels.Length != blendPixels.Length) return blendPixels;
double percentage = smoothMode == SmoothMode.Low? 0.25: (smoothMode == SmoothMode.Medium ? 0.075 : 0.025 /*high*/);
byte[] blended = new byte[pixels.Length];
for (int i = 0; i < blended.Length; i++)
blended[i] = GetIntColor((blendPixels[i] / 255.0) * percentage + (pixels[i] / 255.0) * (1 - percentage));
return blended;
}
private static byte GetIntColor(double d)
{
double calcF = Math.Max(0, Math.Min(1, d));
return (byte)(calcF.Equals(1) ? 255 : calcF * 256);
}
#endregion
}
}

View File

@ -0,0 +1,12 @@
using System;
namespace Artemis.Profiles.Layers.Types.AmbientLight.Model
{
[Flags]
public enum FlipMode
{
None = 0,
Vertical = 1 << 0,
Horizontal = 1 << 1
}
}

Some files were not shown because too many files have changed in this diff Show More