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
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Razer2Artemis", "Razer2Artemis\Razer2Artemis.vcxproj", "{39711909-C1D5-46CE-A9EA-2D561692EA47}"
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}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LogiLed2Artemis", "LogiLed2Artemis\LogiLed2Artemis.vcxproj", "{D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
CD_ROM|Any CPU = CD_ROM|Any CPU
@ -88,34 +88,6 @@ Global
{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.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.Build.0 = 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|x86.ActiveCfg = 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
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

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

View File

@ -167,8 +167,8 @@
<HintPath>..\packages\DynamicExpresso.Core.1.3.3.4\lib\net40\DynamicExpresso.Core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="GongSolutions.Wpf.DragDrop, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\gong-wpf-dragdrop.1.0.0\lib\net46\GongSolutions.Wpf.DragDrop.dll</HintPath>
<Reference Include="GongSolutions.Wpf.DragDrop, Version=0.1.4.3, Culture=neutral, PublicKeyToken=d19974ea350ccea1, processorArchitecture=MSIL">
<HintPath>..\packages\gong-wpf-dragdrop.0.1.4.3\lib\net40\GongSolutions.Wpf.DragDrop.dll</HintPath>
<Private>True</Private>
</Reference>
<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>
<Private>True</Private>
</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">
<HintPath>..\packages\NAudio.1.7.3\lib\net35\NAudio.dll</HintPath>
<Private>True</Private>
@ -222,10 +226,6 @@
<HintPath>..\packages\Ninject.Extensions.Conventions.3.2.0.0\lib\net45-full\Ninject.Extensions.Conventions.dll</HintPath>
<Private>True</Private>
</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">
<HintPath>..\packages\Ninject.Extensions.Logging.3.2.3.0\lib\net45-full\Ninject.Extensions.Logging.dll</HintPath>
<Private>True</Private>
@ -235,7 +235,7 @@
<Private>True</Private>
</Reference>
<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>
</Reference>
<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>
<Private>True</Private>
</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">
<HintPath>..\packages\Splat.1.6.2\lib\Net45\Splat.dll</HintPath>
<Private>True</Private>
@ -303,8 +311,14 @@
<SubType>Code</SubType>
</Compile>
<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\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\CorsairHeadsets.cs" />
<Compile Include="DeviceProviders\Corsair\CorsairMousemats.cs" />
@ -313,13 +327,14 @@
<Compile Include="DeviceProviders\Logitech\G810.cs" />
<Compile Include="DeviceProviders\Logitech\LogitechGeneric.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\EnabledChangedEventArgs.cs" />
<Compile Include="Events\KeyboardChangedEventArgs.cs" />
<Compile Include="Events\RazerColorArrayChanged.cs" />
<Compile Include="Events\RazerColorsChangedEventArgs.cs" />
<Compile Include="InjectionFactories\ILayerEditorVmFactory.cs" />
<Compile Include="InjectionFactories\IProfileEditorVmFactory.cs" />
<Compile Include="InjectionModules\DeviceModules.cs" />
<Compile Include="InjectionModules\EffectModules.cs" />
<Compile Include="InjectionModules\ProfileModules.cs" />
@ -354,6 +369,13 @@
<DependentUpon>EurotruckSimulator2View.xaml</DependentUpon>
</Compile>
<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\UnrealTournamentModel.cs" />
<Compile Include="Modules\Games\UnrealTournament\UnrealTournamentSettings.cs" />
@ -381,6 +403,28 @@
<Compile Include="Profiles\Layers\Animations\NoneAnimation.cs" />
<Compile Include="Profiles\Layers\Models\EventPropertiesModel.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\AudioPropertiesView.xaml.cs">
<DependentUpon>AudioPropertiesView.xaml</DependentUpon>
@ -403,6 +447,22 @@
</Compile>
<Compile Include="Profiles\Layers\Types\Mousemat\MousematPropertiesViewModel.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\Layers\Models\SimplePropertiesModel.cs" />
<Compile Include="Profiles\Layers\Types\Keyboard\KeyboardPropertiesModel.cs" />
@ -489,6 +549,7 @@
</Compile>
<Compile Include="Services\DialogService.cs" />
<Compile Include="Services\MetroDialogService.cs" />
<Compile Include="Services\WindowService.cs" />
<Compile Include="Settings\EffectSettings.cs" />
<Compile Include="Settings\GameSettings.cs" />
<Compile Include="Settings\GeneralSettings.cs" />
@ -511,6 +572,8 @@
<Compile Include="Utilities\Keyboard\KeyboardHook.cs" />
<Compile Include="Utilities\Logging.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\Keyboard\KeyboardRectangle.cs" />
<Compile Include="Utilities\Memory\Memory.cs" />
@ -548,7 +611,6 @@
<Compile Include="Modules\Overlays\VolumeDisplay\VolumeDisplayViewModel.cs" />
<Compile Include="ViewModels\Profiles\ProfileEditorViewModel.cs" />
<Compile Include="ViewModels\ShellViewModel.cs" />
<Compile Include="ViewModels\SystemTrayViewModel.cs" />
<Compile Include="ViewModels\WelcomeViewModel.cs" />
<Compile Include="Views\DebugView.xaml.cs">
<DependentUpon>DebugView.xaml</DependentUpon>
@ -624,6 +686,9 @@
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</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">
<SubType>Designer</SubType>
</None>
@ -649,9 +714,13 @@
<SubType>Designer</SubType>
</None>
<AppDesigner Include="Properties\" />
<Resource Include="Resources\slkscr.ttf" />
<Resource Include="Resources\bow.png" />
<Content Include="lib\CUE.NET.dll" />
<Content Include="lib\Ets2SdkClient.dll" />
<Content Include="lib\SDKDLL.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="LogitechLedEnginesWrapper.dll">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
@ -686,6 +755,14 @@
</None>
</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">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
@ -698,6 +775,10 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Modules\Games\GtaV\GtaVView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Modules\Games\Overwatch\OverwatchView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
@ -714,6 +795,10 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</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">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
@ -746,6 +831,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Styles\MarkdownStyles.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\DebugView.xaml">
<SubType>Designer</SubType>
<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\Win64\ets2-telemetry-server.dll" />
<None Include="Resources\audio.png" />
<None Include="Resources\ambilight.png" />
<Content Include="Resources\CounterStrike\csgoGamestateConfiguration.txt" />
</ItemGroup>
<ItemGroup>
@ -864,6 +954,9 @@
<Name>ColorBox</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Folder Include="Resources\Lua\" />
</ItemGroup>
<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')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">

View File

@ -10,6 +10,7 @@ using Artemis.Utilities;
using Artemis.Utilities.Converters;
using Artemis.ViewModels;
using Caliburn.Micro;
using MoonSharp.Interpreter;
using Newtonsoft.Json;
using Ninject;
@ -80,6 +81,7 @@ namespace Artemis
_kernel.Bind<IWindowManager>().To<WindowManager>().InSingletonScope();
_kernel.Bind<IEventAggregator>().To<EventAggregator>().InSingletonScope();
// Configure JSON.NET
var settings = new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto,
@ -114,7 +116,7 @@ namespace Artemis
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.Properties;
using Artemis.Utilities;
using MoonSharp.Interpreter;
using Newtonsoft.Json;
using NLog;
@ -23,40 +24,34 @@ namespace Artemis.DAL
private static readonly string ProfileFolder =
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\Artemis\profiles";
private static readonly List<ProfileModel> Profiles = new List<ProfileModel>();
private static bool _installedDefaults;
/// <summary>
/// Get all profiles
/// </summary>
/// <returns>All profiles</returns>
public static List<ProfileModel> GetAll()
static ProfileProvider()
{
lock (Profiles)
{
if (!Profiles.Any())
ReadProfiles();
// Return a new list, this'll make sure removing/updating the retrieved list doesn't
// affect the datastore
return Profiles.ToList();
}
// Configure MoonSharp
UserData.RegisterAssembly();
CheckProfiles();
InstallDefaults();
}
/// <summary>
/// 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)
public static List<string> GetProfileNames(KeyboardProvider keyboard, EffectModel effect)
{
if (game == null)
throw new ArgumentNullException(nameof(game));
if (keyboard == null)
throw new ArgumentNullException(nameof(keyboard));
if (keyboard == null || effect == null)
return null;
return ReadProfiles(keyboard.Slug + "/" + effect.Name).Select(p => p.Name).ToList();
}
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>
@ -69,12 +64,6 @@ namespace Artemis.DAL
if (prof == null)
throw new ArgumentNullException(nameof(prof));
lock (Profiles)
{
if (!Profiles.Contains(prof))
Profiles.Add(prof);
}
lock (prof)
{
// Store the file
@ -100,103 +89,34 @@ namespace Artemis.DAL
}
File.WriteAllText(path + $@"\{prof.Name}.json", json);
}
}
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);
}
}
Logger.Debug("Saved profile {0}/{1}/{2}", prof.KeyboardSlug, prof.GameName, prof.Name);
}
}
/// <summary>
/// Unpacks the default profiles into the profile directory
/// Renames the profile on the model and filesystem
/// </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 (_installedDefaults)
if (string.IsNullOrEmpty(name))
return;
_installedDefaults = true;
// Load the ZIP from resources
var stream = Assembly.GetExecutingAssembly()
.GetManifestResourceStream("Artemis.Resources.Keyboards.default-profiles.zip");
// Remove the old profile
DeleteProfile(profile);
// Extract it over the old defaults in case one was updated
if (stream == null)
return;
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");
// Update the profile, creating a new file
profile.Name = name;
AddOrUpdate(profile);
}
public static void InsertGif(IEnumerable<ProfileModel> profileModels, string layerName, Bitmap gifFile,
string fileName)
public static void DeleteProfile(ProfileModel prof)
{
// Extract the GIF file
var gifDir = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\Artemis\gifs";
Directory.CreateDirectory(gifDir);
var gifPath = gifDir + $"\\{fileName}.gif";
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);
// Remove the file
var path = ProfileFolder + $@"\{prof.KeyboardSlug}\{prof.GameName}\{prof.Name}.json";
if (File.Exists(path))
File.Delete(path);
}
/// <summary>
@ -222,7 +142,7 @@ namespace Artemis.DAL
}
/// <summary>
/// Exports the given profile to the provided path in XML
/// Exports the given profile to the provided path in JSON
/// </summary>
/// <param name="prof">The profile to export</param>
/// <param name="path">The path to save the profile to</param>
@ -232,41 +152,102 @@ namespace Artemis.DAL
File.WriteAllText(path, json);
}
/// <summary>
/// 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)
public static void InsertGif(string effectName, string profileName, string layerName, Bitmap gifFile, string fileName)
{
if (string.IsNullOrEmpty(name))
return;
var directories = new DirectoryInfo(ProfileFolder).GetDirectories();
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
DeleteProfile(profile);
foreach (var profile in profiles)
{
var gifLayer = profile.GetLayers().FirstOrDefault(l => l.Name == layerName);
if (gifLayer == null)
continue;
// Update the profile, creating a new file
profile.Name = name;
AddOrUpdate(profile);
((KeyboardPropertiesModel) gifLayer.Properties).GifFile = gifPath;
AddOrUpdate(profile);
}
}
public static void DeleteProfile(ProfileModel prof)
private static List<ProfileModel> ReadProfiles(string subDirectory)
{
// Remove from datastore
lock (Profiles)
{
// Get the profile from the datastore instead of just the provided value, to be certain it is removed
var dsProfile = Profiles.FirstOrDefault(p => p.GameName == prof.GameName &&
p.Name == prof.Name &&
p.KeyboardSlug == prof.KeyboardSlug);
if (dsProfile != null)
Profiles.Remove(dsProfile);
}
var profiles = new List<ProfileModel>();
var directory = ProfileFolder + "/" + subDirectory;
if (!Directory.Exists(directory))
return profiles;
// Remove the file
var path = ProfileFolder + $@"\{prof.KeyboardSlug}\{prof.GameName}\{prof.Name}.json";
if (File.Exists(path))
File.Delete(path);
// Create the directory structure
var profilePaths = Directory.GetFiles(directory, "*.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.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.Enums;
using CUE.NET.Devices.Keyboard;
using CUE.NET.Helper;
using Ninject.Extensions.Logging;
using Point = System.Drawing.Point;
@ -82,6 +83,7 @@ namespace Artemis.DeviceProviders.Corsair
}
Logger.Debug("Corsair SDK reported device as: {0}", _keyboard.DeviceInfo.Model);
_keyboard.Brush = _keyboardBrush ?? (_keyboardBrush = new ImageBrush());
}
@ -103,19 +105,21 @@ namespace Artemis.DeviceProviders.Corsair
// For STRAFE, stretch the image on row 2.
if (_keyboard.DeviceInfo.Model == "STRAFE RGB")
{
var strafeBitmap = new Bitmap(22, 8);
using (var g = Graphics.FromImage(strafeBitmap))
using (var strafeBitmap = new Bitmap(22, 8))
{
g.DrawImage(image, new Point(0, 0));
g.DrawImage(image, new Rectangle(0, 3, 22, 7), new Rectangle(0, 2, 22, 7), GraphicsUnit.Pixel);
}
using (var g = Graphics.FromImage(strafeBitmap))
{
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 = strafeBitmap;
image.Dispose();
image = strafeBitmap;
}
}
_keyboardBrush.Image = image;
_keyboard.Update(true);
_keyboard.Update();
image.Dispose();
}
@ -136,11 +140,11 @@ namespace Artemis.DeviceProviders.Corsair
// ignored
}
if (cueLed != null)
return new KeyMatch(keyCode, (int) (cueLed.LedRectangle.X*widthMultiplier),
(int) (cueLed.LedRectangle.Y*heightMultiplier));
if (cueLed == null)
return null;
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>
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>
/// 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)
{
return _generalSettings.Layout == "Qwerty"
? KeyMap.QwertyLayout.FirstOrDefault(k => k.KeyCode == keyCode)
: KeyMap.AzertyLayout.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

@ -30,9 +30,19 @@ namespace Artemis.DeviceProviders.Logitech
public override KeyMatch? GetKeyPosition(Keys keyCode)
{
var value = _generalSettings.Layout == "Qwerty"
? KeyMap.QwertyLayout.FirstOrDefault(k => k.KeyCode == keyCode)
: KeyMap.AzertyLayout.FirstOrDefault(k => k.KeyCode == keyCode);
KeyMatch value;
switch (_generalSettings.Layout)
{
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
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.
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" +
"The Visual C++ 2012 Redistributable could not be found, which is required.\n" +
"Please download it by going to the following URL:\n\n" +
"https://www.microsoft.com/download/confirmation.aspx?id=30679";
"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 (link also in wiki):\n\n" +
"https://download.microsoft.com/download/1/6/B/16B06F60-3B20-4FF2-B699-5E9B7962F9AE/VSU_4/vcredist_x64.exe";
return false;
}

View File

@ -8,6 +8,9 @@ namespace Artemis.DeviceProviders.Logitech.Utilities
static KeyMap()
{
// There are several keyboard layouts
#region Qwerty
QwertyLayout = new List<KeyMatch>
{
// Row 1
@ -129,6 +132,135 @@ namespace Artemis.DeviceProviders.Logitech.Utilities
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>
{
// Row 1
@ -249,9 +381,12 @@ namespace Artemis.DeviceProviders.Logitech.Utilities
new KeyMatch(Keys.NumPad0, 18, 5),
new KeyMatch(Keys.Decimal, 19, 5)
};
#endregion
}
public static List<KeyMatch> QwertyLayout { get; set; }
public static List<KeyMatch> QwertzLayout { 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.CompositingQuality = CompositingQuality.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.SmoothingMode = SmoothingMode.AntiAlias;
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())
{
wrapMode.SetWrapMode(WrapMode.TileFlipXY);

View File

@ -2,9 +2,11 @@
using System.Linq;
using System.Windows;
using System.Windows.Forms;
using Artemis.DAL;
using Artemis.DeviceProviders.Logitech.Utilities;
using Artemis.DeviceProviders.Razer.Utilities;
using Artemis.Properties;
using Artemis.Settings;
using Corale.Colore.Core;
using Corale.Colore.Razer;
using Constants = Corale.Colore.Razer.Keyboard.Constants;
@ -13,6 +15,8 @@ namespace Artemis.DeviceProviders.Razer
{
public class BlackWidow : KeyboardProvider
{
private GeneralSettings _generalSettings;
public BlackWidow()
{
Name = "Razer BlackWidow Chroma";
@ -24,6 +28,7 @@ namespace Artemis.DeviceProviders.Razer
Height = Constants.MaxRows;
Width = Constants.MaxColumns;
PreviewSettings = new PreviewSettings(665, 175, new Thickness(0, -15, 0, 0), Resources.blackwidow);
_generalSettings = SettingsProvider.Load<GeneralSettings>();
}
public override bool CanEnable()
@ -56,7 +61,15 @@ namespace Artemis.DeviceProviders.Razer
public override KeyMatch? GetKeyPosition(Keys keyCode)
{
// 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)
{
var keyboardGrid = Custom.Create();
if (b.Width > width || b.Height > height)
b = ImageUtilities.ResizeImage(b, width, height);
for (var y = 0; y < b.Height; y++)
// Resize the bitmap
using (b = ImageUtilities.ResizeImage(b, width, height))
{
// Map the bytes to the grid
for (var x = 0; x < b.Width; x++)
{
var pixel = b.GetPixel(x, y);
keyboardGrid[y, x] = new Color(pixel.R, pixel.G, pixel.B);
for (var y = 0; y < b.Height; y++)
{
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.Utilities.DataReaders;
using Artemis.Utilities.GameState;
using Artemis.ViewModels;
using Artemis.ViewModels.Abstract;
using Artemis.ViewModels.Profiles;
using Caliburn.Micro;
using Ninject.Extensions.Factory;
using Ninject.Modules;
namespace Artemis.InjectionModules
@ -15,22 +14,26 @@ namespace Artemis.InjectionModules
public override void Load()
{
// ViewModels
Bind<IScreen>().To<ShellViewModel>().InSingletonScope();
Bind<IProfileEditorVmFactory>().ToFactory();
Bind<ILayerEditorVmFactory>().ToFactory();
Bind<ShellViewModel>().ToSelf().InSingletonScope();
Bind<ProfileViewModel>().ToSelf();
Bind<ProfileEditorViewModel>().ToSelf();
Bind<DebugViewModel>().ToSelf().InSingletonScope();
Bind<BaseViewModel>().To<WelcomeViewModel>().InSingletonScope();
Bind<BaseViewModel>().To<EffectsViewModel>().InSingletonScope();
Bind<BaseViewModel>().To<GamesViewModel>().InSingletonScope();
Bind<BaseViewModel>().To<OverlaysViewModel>().InSingletonScope();
Bind<BaseViewModel>().To<WelcomeViewModel>();
Bind<BaseViewModel>().To<EffectsViewModel>();
Bind<BaseViewModel>().To<GamesViewModel>();
Bind<BaseViewModel>().To<OverlaysViewModel>();
// Models
Bind<ProfilePreviewModel>().ToSelf().InSingletonScope();
// Services
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.CoolerMaster;
using Artemis.DeviceProviders.Corsair;
using Artemis.DeviceProviders.Logitech;
using Artemis.DeviceProviders.Razer;
@ -15,6 +16,7 @@ namespace Artemis.InjectionModules
Bind<DeviceProvider>().To<G910>().InSingletonScope();
Bind<DeviceProvider>().To<G810>().InSingletonScope();
Bind<DeviceProvider>().To<BlackWidow>().InSingletonScope();
Bind<DeviceProvider>().To<MasterkeysProL>().InSingletonScope();
// Mice
Bind<DeviceProvider>().To<CorsairMice>().InSingletonScope();

View File

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

View File

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

View File

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

View File

@ -21,14 +21,24 @@ namespace Artemis.Managers
private EffectModel _waitEffect;
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>();
_logger = logger;
_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");
}

View File

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

View File

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

View File

@ -51,34 +51,39 @@ namespace Artemis.Managers
ProfilePreviewModel == null)
return;
var activePreview = GameViewModels.FirstOrDefault(vm => vm.IsActive);
if (activePreview == null)
lock (GameViewModels)
{
// Should not be active if no selected profile is set
if (_effectManager.ActiveEffect != ProfilePreviewModel)
return;
var activePreview = GameViewModels.FirstOrDefault(vm => vm.IsActive);
_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))
if (activePreview == null)
{
_logger.Debug("Activate profile preview");
_effectManager.ChangeEffect(ProfilePreviewModel);
// Should not be active if no selected profile is set
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.StartAsync();
// LoopManager might be running, this method won't do any harm in that case.
_loopManager.StartAsync();
ProfilePreviewModel.ProfileViewModel = activePreview.ProfileEditor.ProfileViewModel;
if (!ReferenceEquals(ProfilePreviewModel.Profile, activePreview.ProfileEditor.SelectedProfile))
ProfilePreviewModel.Profile = activePreview.ProfileEditor.SelectedProfile;
ProfilePreviewModel.ProfileViewModel = activePreview.ProfileEditor.ProfileViewModel;
if (!ReferenceEquals(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.Linq;
using System.Windows;
using Artemis.DAL;
using Artemis.Events;
using Artemis.Managers;
using Artemis.Models.Interfaces;
using Artemis.Profiles;
@ -10,6 +12,8 @@ using Artemis.Profiles.Layers.Interfaces;
using Artemis.Profiles.Layers.Models;
using Artemis.Settings;
using Newtonsoft.Json;
using Ninject;
using Ninject.Extensions.Logging;
namespace Artemis.Models
{
@ -19,26 +23,41 @@ namespace Artemis.Models
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;
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 MainManager MainManager { get; set; }
public DeviceManager DeviceManager { get; set; }
public EffectSettings Settings { get; set; }
public string Name { get; set; }
public int KeyboardScale { get; set; } = 4;
// Used by profile system
public IDataModel DataModel { 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
public abstract void Enable();
@ -54,7 +73,7 @@ namespace Artemis.Models
/// <param name="keyboardOnly"></param>
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;
lock (DataModel)
@ -62,49 +81,53 @@ namespace Artemis.Models
// Get all enabled layers who's conditions are met
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
var keyboardRect = MainManager.DeviceManager.ActiveKeyboard.KeyboardRectangle(KeyboardScale);
var keyboardRect = DeviceManager.ActiveKeyboard.KeyboardRectangle(KeyboardScale);
using (var g = Graphics.FromImage(frame.KeyboardBitmap))
{
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
var devRec = new Rect(0, 0, 40, 40);
using (var g = Graphics.FromImage(frame.MouseBitmap))
{
Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Mouse), DataModel,
devRec, false, true);
devRec, false, true, "mouse");
}
// Render headsets layer-by-layer
using (var g = Graphics.FromImage(frame.HeadsetBitmap))
{
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
using (var g = Graphics.FromImage(frame.GenericBitmap))
{
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
using (var g = Graphics.FromImage(frame.MousematBitmap))
{
Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Mousemat),
DataModel, devRec, false, true);
DataModel, devRec, false, true, "mousemat");
}
// Trace debugging
if (DateTime.Now.AddSeconds(-2) <= LastTrace)
if (DateTime.Now.AddSeconds(-2) <= LastTrace || Logger == null)
return;
LastTrace = DateTime.Now;
MainManager.Logger.Trace("Effect datamodel as JSON: \r\n{0}",
JsonConvert.SerializeObject(DataModel, Formatting.Indented));
MainManager.Logger.Trace("Effect {0} has to render {1} layers", Name, renderLayers.Count);
var dmJson = JsonConvert.SerializeObject(DataModel, Formatting.Indented);
Logger.Trace("Effect datamodel as JSON: \r\n{0}", dmJson);
Logger.Trace("Effect {0} has to render {1} layers", Name, renderLayers.Count);
foreach (var renderLayer in renderLayers)
MainManager.Logger.Trace("- Layer name: {0}, layer type: {1}", renderLayer.Name,
renderLayer.LayerType);
Logger.Trace("- Layer name: {0}, layer type: {1}", renderLayer.Name, renderLayer.LayerType);
}
}

View File

@ -6,7 +6,7 @@ namespace Artemis.Models
{
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
Settings = settings;

View File

@ -8,7 +8,7 @@ namespace Artemis.Models
private bool _enabled;
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;
Enabled = settings.Enabled;

View File

@ -1,12 +1,14 @@
using Artemis.Managers;
using Artemis.Models;
using Artemis.Modules.Effects.ProfilePreview;
using Artemis.ViewModels.Abstract;
using Ninject;
namespace Artemis.Modules.Effects.AudioVisualizer
{
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";
}

View File

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

View File

@ -1,6 +1,8 @@
using System.Windows.Media;
using Artemis.Managers;
using Artemis.Models;
using Artemis.ViewModels.Abstract;
using Ninject;
namespace Artemis.Modules.Effects.Bubbles
{
@ -9,11 +11,11 @@ namespace Artemis.Modules.Effects.Bubbles
private readonly BubblesModel _model;
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";
BubbleColor = new SolidColorBrush(model.Settings.BubbleColor);
BubbleColor = new SolidColorBrush(_model.Settings.BubbleColor);
}
/// <summary>

View File

@ -7,14 +7,17 @@ using Artemis.Models;
using Artemis.Models.Interfaces;
using Artemis.Profiles.Layers.Interfaces;
using Artemis.Profiles.Layers.Models;
using Artemis.Profiles.Lua;
using Artemis.ViewModels.Profiles;
using Castle.Components.DictionaryAdapter;
using MoonSharp.Interpreter;
namespace Artemis.Modules.Effects.ProfilePreview
{
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";
}
@ -24,6 +27,7 @@ namespace Artemis.Modules.Effects.ProfilePreview
public override void Dispose()
{
Initialized = false;
base.Dispose();
}
public override void Enable()
@ -42,7 +46,7 @@ namespace Artemis.Modules.Effects.ProfilePreview
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;
lock (DataModel)
@ -50,46 +54,47 @@ namespace Artemis.Modules.Effects.ProfilePreview
// Get all enabled layers who's conditions are met
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
var keyboardRect = MainManager.DeviceManager.ActiveKeyboard.KeyboardRectangle(KeyboardScale);
var keyboardRect = DeviceManager.ActiveKeyboard.KeyboardRectangle(KeyboardScale);
using (var g = Graphics.FromImage(frame.KeyboardBitmap))
{
Profile.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Keyboard),
DataModel,
keyboardRect, true, true);
DataModel, keyboardRect, true, true, "keyboard");
}
// Render mice layer-by-layer
var devRec = new Rect(0, 0, 40, 40);
using (var g = Graphics.FromImage(frame.MouseBitmap))
{
Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Mouse), DataModel,
devRec, true, true);
devRec, true, true, "mouse");
}
// Render headsets layer-by-layer
using (var g = Graphics.FromImage(frame.HeadsetBitmap))
{
Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Headset),
DataModel,
devRec, true, true);
DataModel, devRec, true, true, "headset");
}
// Render generic devices layer-by-layer
using (var g = Graphics.FromImage(frame.GenericBitmap))
{
Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Generic),
DataModel,
devRec, true, true);
DataModel, devRec, true, true, "generic");
}
// Render mousemats layer-by-layer
using (var g = Graphics.FromImage(frame.MousematBitmap))
{
Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Mousemat),
DataModel,
devRec, true, true);
DataModel, devRec, true, true, "mousemat");
}
}
}
}
[MoonSharpUserData]
public class ProfilePreviewDataModel : IDataModel
{
}

View File

@ -1,12 +1,15 @@
using Artemis.Models.Interfaces;
using MoonSharp.Interpreter;
namespace Artemis.Modules.Effects.WindowsProfile
{
[MoonSharpUserData]
public class WindowsProfileDataModel : IDataModel
{
public WindowsProfileDataModel()
{
Spotify = new Spotify();
GooglePlayMusic = new GooglePlayMusic();
Cpu = new CpuDataModel();
Performance = new PerformanceDataModel();
CurrentTime = new CurrentTime();
@ -15,9 +18,11 @@ namespace Artemis.Modules.Effects.WindowsProfile
public CpuDataModel Cpu { get; set; }
public PerformanceDataModel Performance { get; set; }
public Spotify Spotify { get; set; }
public GooglePlayMusic GooglePlayMusic { get; set; }
public CurrentTime CurrentTime { get; set; }
}
[MoonSharpUserData]
public class CurrentTime
{
public int Hours24 { get; set; }
@ -26,6 +31,7 @@ namespace Artemis.Modules.Effects.WindowsProfile
public int Seconds { get; set; }
}
[MoonSharpUserData]
public class CpuDataModel
{
public int TotalUsage { get; set; }
@ -39,11 +45,13 @@ namespace Artemis.Modules.Effects.WindowsProfile
public int Core8Usage { get; set; }
}
[MoonSharpUserData]
public class PerformanceDataModel
{
public int RAMUsage { get; set; }
}
[MoonSharpUserData]
public class Spotify
{
public bool Running { get; set; }
@ -57,4 +65,39 @@ namespace Artemis.Modules.Effects.WindowsProfile
public bool Playing { 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.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Artemis.DAL;
using Artemis.Managers;
using Artemis.Models;
using Artemis.Profiles.Layers.Models;
using Ninject.Extensions.Logging;
using Newtonsoft.Json;
using SpotifyAPI.Local;
namespace Artemis.Modules.Effects.WindowsProfile
{
public class WindowsProfileModel : EffectModel
{
private readonly ILogger _logger;
private List<PerformanceCounter> _cores;
private int _cpuFrames;
private DateTime _lastMusicUpdate;
private PerformanceCounter _overallCpu;
private SpotifyLocalAPI _spotify;
private bool _spotifySetupBusy;
public WindowsProfileModel(ILogger logger, MainManager mainManager)
: base(mainManager, SettingsProvider.Load<WindowsProfileSettings>(), new WindowsProfileDataModel())
public WindowsProfileModel(DeviceManager deviceManager)
: base(deviceManager, SettingsProvider.Load<WindowsProfileSettings>(), new WindowsProfileDataModel())
{
_logger = logger;
_lastMusicUpdate = DateTime.Now;
Name = "WindowsProfile";
}
public override void Dispose()
{
Initialized = false;
base.Dispose();
}
public override void Enable()
@ -45,7 +48,7 @@ namespace Artemis.Modules.Effects.WindowsProfile
{
var dataModel = (WindowsProfileDataModel) DataModel;
UpdateCpu(dataModel);
UpdateSpotify(dataModel);
UpdateMusicPlayers(dataModel);
UpdateDay(dataModel);
}
@ -79,7 +82,7 @@ namespace Artemis.Modules.Effects.WindowsProfile
}
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
#region Spotify
#region Music
public void SetupSpotify()
{
@ -163,10 +166,7 @@ namespace Artemis.Modules.Effects.WindowsProfile
return;
_spotifySetupBusy = true;
_spotify = new SpotifyLocalAPI {ListenForEvents = true};
_spotify.OnPlayStateChange += UpdateSpotifyPlayState;
_spotify.OnTrackChange += UpdateSpotifyTrack;
_spotify.OnTrackTimeChange += UpdateSpotifyTrackTime;
_spotify = new SpotifyLocalAPI();
// Connecting can sometimes use a little bit more conviction
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())
SetupSpotify();
var status = _spotify.GetStatus();
if (status == null)
return;
dataModel.Spotify.Playing = status.Playing;
dataModel.Spotify.Running = SpotifyLocalAPI.IsSpotifyRunning();
}
private void UpdateSpotifyPlayState(object sender, PlayStateEventArgs e)
{
((WindowsProfileDataModel) DataModel).Spotify.Playing = e.Playing;
}
if (status.Track != null)
{
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)
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

View File

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

View File

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

View File

@ -1,47 +1,57 @@
using System;
using System.Collections.Generic;
using System.IO;
using Artemis.DAL;
using Artemis.Managers;
using Artemis.Models;
using Artemis.Profiles.Layers.Models;
using Artemis.Properties;
using Artemis.Services;
using Artemis.Utilities;
using Artemis.Utilities.GameState;
using Newtonsoft.Json;
using Ninject.Extensions.Logging;
namespace Artemis.Modules.Games.CounterStrike
{
public class CounterStrikeModel : GameModel
{
private readonly MetroDialogService _dialogService;
private readonly GameStateWebServer _gameStateWebServer;
private DateTime _lastHeadshot;
private int _lastHeadshots;
private DateTime _lastKill;
private int _lastKills;
public CounterStrikeModel(MainManager mainManager)
: base(mainManager, SettingsProvider.Load<CounterStrikeSettings>(), new CounterStrikeDataModel())
public CounterStrikeModel(DeviceManager deviceManager, GameStateWebServer gameStateWebServer,
MetroDialogService dialogService)
: base(deviceManager, SettingsProvider.Load<CounterStrikeSettings>(), new CounterStrikeDataModel())
{
_gameStateWebServer = gameStateWebServer;
_dialogService = dialogService;
Name = "CounterStrike";
ProcessName = "csgo";
Scale = 4;
Enabled = Settings.Enabled;
Initialized = false;
FindGameDir();
PlaceConfigFile();
}
public ILogger Logger { get; set; }
public int Scale { get; set; }
public override void Dispose()
{
Initialized = false;
MainManager.GameStateWebServer.GameDataReceived -= HandleGameData;
_gameStateWebServer.GameDataReceived -= HandleGameData;
base.Dispose();
}
public override void Enable()
{
Initialized = false;
MainManager.GameStateWebServer.GameDataReceived += HandleGameData;
_gameStateWebServer.GameDataReceived += HandleGameData;
Initialized = true;
}
@ -89,6 +99,42 @@ namespace Artemis.Modules.Games.CounterStrike
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)
{
var jsonString = e.Json.ToString();
@ -111,6 +157,7 @@ namespace Artemis.Modules.Games.CounterStrike
}
}
public override List<LayerModel> GetRenderLayers(bool keyboardOnly)
{
return Profile.GetRenderLayers(DataModel, keyboardOnly);

View File

@ -1,72 +1,22 @@
using System.IO;
using System.Windows.Forms;
using Artemis.InjectionFactories;
using Artemis.Managers;
using Artemis.Properties;
using Artemis.Utilities;
using Artemis.Managers;
using Artemis.Models;
using Artemis.ViewModels.Abstract;
using Ninject;
namespace Artemis.Modules.Games.CounterStrike
{
public sealed class CounterStrikeViewModel : GameViewModel
{
public CounterStrikeViewModel(MainManager main, IProfileEditorVmFactory pFactory, CounterStrikeModel model)
: base(main, model, pFactory)
public CounterStrikeViewModel(MainManager main, IKernel kernel, [Named("CounterStrikeModel")] GameModel model)
: base(main, model, kernel)
{
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()
{
var dialog = new FolderBrowserDialog {SelectedPath = ((CounterStrikeSettings) GameSettings).GameDirectory};
var result = dialog.ShowDialog();
if (result != DialogResult.OK)
return;
((CounterStrikeSettings) GameSettings).GameDirectory = Path.GetDirectoryName(dialog.SelectedPath);
((CounterStrikeModel) GameModel).PlaceConfigFile();
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 MoonSharp.Interpreter;
namespace Artemis.Modules.Games.Dota2
{
[MoonSharpUserData]
public class Dota2DataModel : IDataModel
{
public Provider provider { get; set; }
@ -13,6 +15,7 @@ namespace Artemis.Modules.Games.Dota2
public Previously previously { get; set; }
}
[MoonSharpUserData]
public class Provider
{
public string name { get; set; }
@ -21,6 +24,7 @@ namespace Artemis.Modules.Games.Dota2
public int timestamp { get; set; }
}
[MoonSharpUserData]
public class Map
{
public int dayCyclePercentage;
@ -36,6 +40,7 @@ namespace Artemis.Modules.Games.Dota2
public int ward_purchase_cooldown { get; set; }
}
[MoonSharpUserData]
public class Player
{
public string steamid { get; set; }
@ -55,6 +60,7 @@ namespace Artemis.Modules.Games.Dota2
public int xpm { get; set; }
}
[MoonSharpUserData]
public class Hero
{
public int id { get; set; }
@ -80,6 +86,7 @@ namespace Artemis.Modules.Games.Dota2
public bool has_debuff { get; set; }
}
[MoonSharpUserData]
public class Abilities
{
public Ability0 ability0 { get; set; }
@ -90,6 +97,7 @@ namespace Artemis.Modules.Games.Dota2
public Attributes attributes { get; set; }
}
[MoonSharpUserData]
public class Ability0
{
public string name { get; set; }
@ -101,6 +109,7 @@ namespace Artemis.Modules.Games.Dota2
public bool ultimate { get; set; }
}
[MoonSharpUserData]
public class Ability1
{
public string name { get; set; }
@ -112,6 +121,7 @@ namespace Artemis.Modules.Games.Dota2
public bool ultimate { get; set; }
}
[MoonSharpUserData]
public class Ability2
{
public string name { get; set; }
@ -123,6 +133,7 @@ namespace Artemis.Modules.Games.Dota2
public bool ultimate { get; set; }
}
[MoonSharpUserData]
public class Ability3
{
public string name { get; set; }
@ -134,11 +145,13 @@ namespace Artemis.Modules.Games.Dota2
public bool ultimate { get; set; }
}
[MoonSharpUserData]
public class Attributes
{
public int level { get; set; }
}
[MoonSharpUserData]
public class Items
{
public Slot0 slot0 { get; set; }
@ -155,71 +168,85 @@ namespace Artemis.Modules.Games.Dota2
public Stash5 stash5 { get; set; }
}
[MoonSharpUserData]
public class Slot0
{
public string name { get; set; }
}
[MoonSharpUserData]
public class Slot1
{
public string name { get; set; }
}
[MoonSharpUserData]
public class Slot2
{
public string name { get; set; }
}
[MoonSharpUserData]
public class Slot3
{
public string name { get; set; }
}
[MoonSharpUserData]
public class Slot4
{
public string name { get; set; }
}
[MoonSharpUserData]
public class Slot5
{
public string name { get; set; }
}
[MoonSharpUserData]
public class Stash0
{
public string name { get; set; }
}
[MoonSharpUserData]
public class Stash1
{
public string name { get; set; }
}
[MoonSharpUserData]
public class Stash2
{
public string name { get; set; }
}
[MoonSharpUserData]
public class Stash3
{
public string name { get; set; }
}
[MoonSharpUserData]
public class Stash4
{
public string name { get; set; }
}
[MoonSharpUserData]
public class Stash5
{
public string name { get; set; }
}
[MoonSharpUserData]
public class Previously
{
public Player1 player { get; set; }
}
[MoonSharpUserData]
public class Player1
{
public int gold { get; set; }

View File

@ -1,8 +1,12 @@
using System.Collections.Generic;
using System.IO;
using Artemis.DAL;
using Artemis.Managers;
using Artemis.Models;
using Artemis.Profiles.Layers.Models;
using Artemis.Properties;
using Artemis.Services;
using Artemis.Utilities;
using Artemis.Utilities.GameState;
using Newtonsoft.Json;
@ -10,14 +14,24 @@ namespace Artemis.Modules.Games.Dota2
{
public class Dota2Model : GameModel
{
public Dota2Model(MainManager mainManager)
: base(mainManager, SettingsProvider.Load<Dota2Settings>(), new Dota2DataModel())
private readonly MetroDialogService _dialogService;
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";
ProcessName = "dota2";
Enabled = Settings.Enabled;
Initialized = false;
Scale = 4;
FindGameDir();
PlaceConfigFile();
}
public int Scale { get; set; }
@ -25,14 +39,13 @@ namespace Artemis.Modules.Games.Dota2
public override void Dispose()
{
Initialized = false;
MainManager.GameStateWebServer.GameDataReceived -= HandleGameData;
_gameStateWebServer.GameDataReceived -= HandleGameData;
base.Dispose();
}
public override void Enable()
{
Initialized = false;
MainManager.GameStateWebServer.GameDataReceived += HandleGameData;
_gameStateWebServer.GameDataReceived += HandleGameData;
Initialized = true;
}
@ -41,6 +54,55 @@ namespace Artemis.Modules.Games.Dota2
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()
{
var dataModel = DataModel as Dota2DataModel;

View File

@ -1,88 +1,22 @@
using System.IO;
using System.Windows.Forms;
using Artemis.InjectionFactories;
using Artemis.Managers;
using Artemis.Properties;
using Artemis.Utilities;
using Artemis.Managers;
using Artemis.Models;
using Artemis.ViewModels.Abstract;
using Ninject;
namespace Artemis.Modules.Games.Dota2
{
public sealed class Dota2ViewModel : GameViewModel
{
public Dota2ViewModel(MainManager main, IProfileEditorVmFactory pFactory, Dota2Model model)
: base(main, model, pFactory)
public Dota2ViewModel(MainManager main, IKernel kernel, [Named("Dota2Model")] GameModel model)
: base(main, model, kernel)
{
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()
{
if (((Dota2Settings) GameSettings).GameDirectory == string.Empty)
return;
if (Directory.Exists(((Dota2Settings) GameSettings).GameDirectory + "/game/dota/cfg"))
{
var cfgFile = Resources.dotaGamestateConfiguration.Replace("{{port}}",
MainManager.GameStateWebServer.Port.ToString());
try
{
File.WriteAllText(
((Dota2Settings) GameSettings).GameDirectory +
"/game/dota/cfg/gamestate_integration/gamestate_integration_artemis.cfg",
cfgFile);
}
catch (DirectoryNotFoundException)
{
Directory.CreateDirectory(((Dota2Settings) GameSettings).GameDirectory +
"/game/dota/cfg/gamestate_integration/");
File.WriteAllText(
((Dota2Settings) GameSettings).GameDirectory +
"/game/dota/cfg/gamestate_integration/gamestate_integration_artemis.cfg",
cfgFile);
}
return;
}
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;
((Dota2Model) GameModel).PlaceConfigFile();
NotifyOfPropertyChange(() => GameSettings);
GameSettings.Save();
}
}
}

View File

@ -1,10 +1,22 @@
using Artemis.Models.Interfaces;
using Artemis.Modules.Games.EurotruckSimulator2.Data;
using MoonSharp.Interpreter;
namespace Artemis.Modules.Games.EurotruckSimulator2
{
[MoonSharpUserData]
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 IEts2Job Job { 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.Managers;
using Artemis.Models;
using Artemis.Modules.Games.EurotruckSimulator2.Data;
using Artemis.Profiles.Layers.Models;
using Artemis.Properties;
using Artemis.Services;
using Artemis.Settings;
using Artemis.Utilities;
using Ninject.Extensions.Logging;
namespace Artemis.Modules.Games.EurotruckSimulator2
{
public class EurotruckSimulator2Model : GameModel
{
public EurotruckSimulator2Model(MainManager mainManager)
: base(mainManager, SettingsProvider.Load<EurotruckSimulator2Settings>(), new EurotruckSimulator2DataModel()
)
private readonly MetroDialogService _dialogService;
public EurotruckSimulator2Model(DeviceManager deviceManager, MetroDialogService dialogService)
: base(
deviceManager, SettingsProvider.Load<EurotruckSimulator2Settings>(), new EurotruckSimulator2DataModel())
{
_dialogService = dialogService;
Name = "EurotruckSimulator2";
ProcessName = "eurotrucks2";
Scale = 4;
Enabled = Settings.Enabled;
Initialized = false;
FindGameDir();
}
public ILogger Logger { get; set; }
public int Scale { get; set; }
public override void Dispose()
{
Initialized = false;
base.Dispose();
}
public override void Enable()
@ -46,6 +57,66 @@ namespace Artemis.Modules.Games.EurotruckSimulator2
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)
{
return Profile.GetRenderLayers(DataModel, keyboardOnly);

View File

@ -1,40 +1,18 @@
using System;
using System.IO;
using System.IO;
using System.Windows.Forms;
using Artemis.InjectionFactories;
using Artemis.Managers;
using Artemis.Properties;
using Artemis.Utilities;
using Artemis.Models;
using Artemis.ViewModels.Abstract;
using Ninject;
namespace Artemis.Modules.Games.EurotruckSimulator2
{
public sealed class EurotruckSimulator2ViewModel : GameViewModel
{
public EurotruckSimulator2ViewModel(MainManager main, IProfileEditorVmFactory pFactory,
EurotruckSimulator2Model model) : base(main, model, pFactory)
public EurotruckSimulator2ViewModel(MainManager main, IKernel kernel,
[Named("EurotruckSimulator2Model")] GameModel model) : base(main, model, kernel)
{
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()
@ -51,49 +29,7 @@ namespace Artemis.Modules.Games.EurotruckSimulator2
NotifyOfPropertyChange(() => GameSettings);
GameSettings.Save();
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;
}
((EurotruckSimulator2Model) GameModel).PlacePlugin();
}
}
}

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 MoonSharp.Interpreter;
namespace Artemis.Modules.Games.Overwatch
{
[MoonSharpUserData]
public class OverwatchDataModel : IDataModel
{
public OverwatchStatus Status { get; set; }

View File

@ -1,19 +1,23 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows.Media;
using Artemis.DAL;
using Artemis.Managers;
using Artemis.Models;
using Artemis.Models.Interfaces;
using Artemis.Profiles.Layers.Models;
using Artemis.Settings;
using Artemis.Services;
using Artemis.Utilities;
using Artemis.Utilities.DataReaders;
using Microsoft.Win32;
namespace Artemis.Modules.Games.Overwatch
{
public class OverwatchModel : GameModel
{
private readonly PipeServer _pipeServer;
private readonly MetroDialogService _dialogService;
private DateTime _characterChange;
private string _lastMessage;
// Using sticky values on these since they can cause flickering
@ -23,9 +27,11 @@ namespace Artemis.Modules.Games.Overwatch
private DateTime _ultimateReady;
private DateTime _ultimateUsed;
public OverwatchModel(MainManager mainManager)
: base(mainManager, SettingsProvider.Load<OverwatchSettings>(), new OverwatchDataModel())
public OverwatchModel(DeviceManager deviceManager, PipeServer pipeServer, MetroDialogService dialogService)
: base(deviceManager, SettingsProvider.Load<OverwatchSettings>(), new OverwatchDataModel())
{
_pipeServer = pipeServer;
_dialogService = dialogService;
Name = "Overwatch";
ProcessName = "Overwatch";
Scale = 4;
@ -33,11 +39,7 @@ namespace Artemis.Modules.Games.Overwatch
Initialized = false;
LoadOverwatchCharacters();
}
public OverwatchModel(MainManager mainManager, GameSettings settings, IDataModel dataModel)
: base(mainManager, settings, dataModel)
{
FindOverwatch();
}
public List<CharacterColor> OverwatchCharacters { get; set; }
@ -77,7 +79,7 @@ namespace Artemis.Modules.Games.Overwatch
_stickyStatus = new StickyValue<OverwatchStatus>(300);
_stickyUltimateReady = new StickyValue<bool>(350);
_stickyUltimateUsed = new StickyValue<bool>(350);
MainManager.PipeServer.PipeMessage += PipeServerOnPipeMessage;
_pipeServer.PipeMessage += PipeServerOnPipeMessage;
Initialized = true;
}
@ -86,11 +88,12 @@ namespace Artemis.Modules.Games.Overwatch
{
Initialized = false;
_stickyStatus.Dispose();
_stickyUltimateReady.Dispose();
_stickyUltimateUsed.Dispose();
_stickyStatus?.Dispose();
_stickyUltimateReady?.Dispose();
_stickyUltimateUsed?.Dispose();
MainManager.PipeServer.PipeMessage -= PipeServerOnPipeMessage;
_pipeServer.PipeMessage -= PipeServerOnPipeMessage;
base.Dispose();
}
private void PipeServerOnPipeMessage(string message)
@ -176,7 +179,7 @@ namespace Artemis.Modules.Games.Overwatch
}
catch (FormatException e)
{
MainManager.Logger.Trace(e, "Failed to parse to color array");
Logger?.Trace(e, "Failed to parse to color array");
return null;
}
}
@ -270,6 +273,46 @@ namespace Artemis.Modules.Games.Overwatch
{
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

View File

@ -1,43 +1,17 @@
using System.IO;
using System.Windows.Forms;
using Artemis.InjectionFactories;
using System.Windows.Forms;
using Artemis.Managers;
using Artemis.Utilities.DataReaders;
using Artemis.Models;
using Artemis.ViewModels.Abstract;
using Microsoft.Win32;
using Ninject;
namespace Artemis.Modules.Games.Overwatch
{
public sealed class OverwatchViewModel : GameViewModel
{
public OverwatchViewModel(MainManager main, IProfileEditorVmFactory pFactory, OverwatchModel model)
: base(main, model, pFactory)
public OverwatchViewModel(MainManager main, IKernel kernel, [Named("OverwatchModel")] GameModel model)
: base(main, model, kernel)
{
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()
@ -48,28 +22,9 @@ namespace Artemis.Modules.Games.Overwatch
return;
((OverwatchSettings) GameSettings).GameDirectory = dialog.SelectedPath;
NotifyOfPropertyChange(() => GameSettings);
GameSettings.Save();
PlaceDll();
}
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);
((OverwatchModel) GameModel).PlaceDll();
NotifyOfPropertyChange(() => GameSettings);
}
}
}

View File

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

View File

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

View File

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

View File

@ -1,14 +1,11 @@
using Artemis.Models.Interfaces;
using MoonSharp.Interpreter;
namespace Artemis.Modules.Games.TheDivision
{
[MoonSharpUserData]
public class TheDivisionDataModel : IDataModel
{
public TheDivisionDataModel()
{
TestyTest = new TestTest();
}
public PlayerState PartyMember1 { get; set; }
public PlayerState PartyMember2 { get; set; }
public PlayerState PartyMember3 { get; set; }
@ -16,17 +13,8 @@ namespace Artemis.Modules.Games.TheDivision
public bool LowAmmo { get; set; }
public bool LowHp { 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
{
HasGrenade,

View File

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

View File

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

View File

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

View File

@ -1,22 +1,35 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Timers;
using Artemis.DAL;
using Artemis.Managers;
using Artemis.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.Linq;
namespace Artemis.Modules.Games.UnrealTournament
{
public class UnrealTournamentModel : GameModel
{
private readonly PipeServer _pipeServer;
private readonly MetroDialogService _dialogService;
private Timer _killTimer;
private int _lastScore;
public UnrealTournamentModel(MainManager mainManager)
: base(mainManager, SettingsProvider.Load<UnrealTournamentSettings>(), new UnrealTournamentDataModel())
public UnrealTournamentModel(DeviceManager deviceManager, PipeServer pipeServer, MetroDialogService dialogService)
: base(deviceManager, SettingsProvider.Load<UnrealTournamentSettings>(), new UnrealTournamentDataModel())
{
_pipeServer = pipeServer;
_dialogService = dialogService;
Name = "UnrealTournament";
ProcessName = "UE4-Win64-Shipping";
Scale = 4;
@ -25,6 +38,77 @@ namespace Artemis.Modules.Games.UnrealTournament
_killTimer = new Timer(3500);
_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; }
@ -34,12 +118,13 @@ namespace Artemis.Modules.Games.UnrealTournament
Initialized = false;
_killTimer.Stop();
MainManager.PipeServer.PipeMessage -= PipeServerOnPipeMessage;
_pipeServer.PipeMessage -= PipeServerOnPipeMessage;
base.Dispose();
}
public override void Enable()
{
MainManager.PipeServer.PipeMessage += PipeServerOnPipeMessage;
_pipeServer.PipeMessage += PipeServerOnPipeMessage;
_killTimer.Start();
Initialized = true;

View File

@ -1,65 +1,24 @@
using System;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
using System.Windows.Forms;
using Artemis.DAL;
using Artemis.InjectionFactories;
using Artemis.Managers;
using Artemis.Models;
using Artemis.Properties;
using Artemis.Utilities;
using Artemis.ViewModels.Abstract;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Ninject;
namespace Artemis.Modules.Games.UnrealTournament
{
public sealed class UnrealTournamentViewModel : GameViewModel
{
public UnrealTournamentViewModel(MainManager main, IProfileEditorVmFactory pFactory, UnrealTournamentModel model)
: base(main, model, pFactory)
public UnrealTournamentViewModel(MainManager main, IKernel kernel,
[Named("UnrealTournamentModel")] GameModel model) : base(main, model, kernel)
{
DisplayName = "Unreal Tournament";
MainManager.EffectManager.EffectModels.Add(GameModel);
FindGame();
InstallGif();
}
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()
{
@ -72,52 +31,19 @@ namespace Artemis.Modules.Games.UnrealTournament
return;
((UnrealTournamentSettings) GameSettings).GameDirectory = dialog.SelectedPath;
NotifyOfPropertyChange(() => GameSettings);
GameSettings.Save();
PlaceFiles();
}
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);
((UnrealTournamentModel) GameModel).PlaceFiles();
NotifyOfPropertyChange(() => GameSettings);
}
// Installing GIF on editor open to make sure the proper profiles are loaded
private void InstallGif()
{
var gif = Resources.redeemer;
ProfileProvider.InsertGif(ProfileProvider.GetAll()
.Where(p => (p.GameName == "UnrealTournament") && (p.Name == "Default")), "Redeemer GIF", gif,
"redeemer");
if (gif == null)
return;
ProfileProvider.InsertGif("UnrealTournament", "Default", "Redeemer GIF", gif, "redeemer");
}
}
}

View File

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

View File

@ -17,8 +17,8 @@ namespace Artemis.Modules.Games.Witcher3
private readonly Stopwatch _updateSw;
private string _witcherSettings;
public Witcher3Model(MainManager mainManager)
: base(mainManager, SettingsProvider.Load<Witcher3Settings>(), new Witcher3DataModel())
public Witcher3Model(DeviceManager deviceManager)
: base(deviceManager, SettingsProvider.Load<Witcher3Settings>(), new Witcher3DataModel())
{
Name = "Witcher3";
ProcessName = "witcher3";
@ -38,6 +38,7 @@ namespace Artemis.Modules.Games.Witcher3
_witcherSettings = null;
_updateSw.Reset();
base.Dispose();
}
public override void Enable()
@ -66,10 +67,11 @@ namespace Artemis.Modules.Games.Witcher3
if (_witcherSettings == null)
return;
var reader = new StreamReader(
File.Open(_witcherSettings, FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
var reader =
new StreamReader(File.Open(_witcherSettings, FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
var configContent = reader.ReadToEnd();
reader.Close();
reader.Dispose();
var signRes = _configRegex.Match(configContent);
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.Compression;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
using Artemis.InjectionFactories;
using Artemis.Managers;
using Artemis.Models;
using Artemis.Properties;
using Artemis.Utilities;
using Artemis.ViewModels.Abstract;
using Ninject;
namespace Artemis.Modules.Games.Witcher3
{
public sealed class Witcher3ViewModel : GameViewModel
{
public Witcher3ViewModel(MainManager main, IProfileEditorVmFactory pFactory, Witcher3Model model)
: base(main, model, pFactory)
public Witcher3ViewModel(MainManager main, IKernel kernel, [Named("Witcher3Model")] GameModel model)
: base(main, model, kernel)
{
DisplayName = "The Witcher 3";
}
@ -48,39 +48,43 @@ namespace Artemis.Modules.Games.Witcher3
}
// Load the ZIP from resources
var stream = new MemoryStream(Resources.witcher3_mod);
var archive = new ZipArchive(stream);
// Look for any conflicting mods
if (Directory.Exists(dialog.SelectedPath + @"\mods"))
using (var stream = new MemoryStream(Resources.witcher3_mod))
{
var file =
Directory.GetFiles(dialog.SelectedPath + @"\mods", "playerWitcher.ws", SearchOption.AllDirectories)
.FirstOrDefault();
if (file != null)
if (!file.Contains("modArtemis"))
using (var archive = new ZipArchive(stream))
{
// Look for any conflicting mods
if (Directory.Exists(dialog.SelectedPath + @"\mods"))
{
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;
var file = Directory.GetFiles(dialog.SelectedPath + @"\mods", "playerWitcher.ws",
SearchOption.AllDirectories)
.FirstOrDefault();
if (file != null)
if (!file.Contains("modArtemis"))
{
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
// Create the directory structure
var folder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\Artemis";
// Put the mod in the documents folder instead
// Create the directory structure
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"));
return;
System.Diagnostics.Process.Start(
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.Settings;
using Artemis.Utilities.Memory;
using Newtonsoft.Json;
using Process.NET;
using Process.NET.Memory;
@ -19,21 +18,21 @@ namespace Artemis.Modules.Games.WoW
private readonly GamePointersCollection _pointer;
private ProcessSharp _process;
public WoWModel(MainManager mainManager)
: base(mainManager, SettingsProvider.Load<WoWSettings>(), new WoWDataModel())
public WoWModel(DeviceManager deviceManager)
: base(deviceManager, SettingsProvider.Load<WoWSettings>(), new WoWDataModel())
{
Name = "WoW";
ProcessName = "Wow-64";
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
var settings = SettingsProvider.Load<GeneralSettings>();
Enabled = settings.GamestatePort == 62575 && Settings.Enabled;
Enabled = (settings.GamestatePort == 62575) && Settings.Enabled;
Initialized = false;
_pointer = SettingsProvider.Load<OffsetSettings>().WorldOfWarcraft;
_pointer = SettingsProvider.Load<OffsetSettings>().WorldOfWarcraft;
//_pointer = new GamePointersCollection
//{
// Game = "WorldOfWarcraft",
@ -71,8 +70,9 @@ namespace Artemis.Modules.Games.WoW
{
Initialized = false;
_process.Dispose();
_process?.Dispose();
_process = null;
base.Dispose();
}
public override void Enable()
@ -102,7 +102,7 @@ namespace Artemis.Modules.Games.WoW
_pointer.GameAddresses.First(a => a.Description == "TargetGuid").BasePointer, true);
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);
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 Ninject;
namespace Artemis.Modules.Games.WoW
{
public sealed class WoWViewModel : GameViewModel
{
public WoWViewModel(MainManager main, IProfileEditorVmFactory pFactory, WoWModel model)
: base(main, model, pFactory)
public WoWViewModel(MainManager main, IKernel kernel, [Named("WoWModel")] GameModel model)
: base(main, model, kernel)
{
DisplayName = "WoW";
}

View File

@ -13,12 +13,11 @@ namespace Artemis.Modules.Overlays.VolumeDisplay
{
public class VolumeDisplayModel : OverlayModel
{
public VolumeDisplayModel(MainManager mainManager)
: base(mainManager, SettingsProvider.Load<VolumeDisplaySettings>())
public VolumeDisplayModel(DeviceManager deviceManager): base(deviceManager, SettingsProvider.Load<VolumeDisplaySettings>())
{
Name = "VolumeDisplay";
Settings = (VolumeDisplaySettings) base.Settings;
VolumeDisplay = new VolumeBar(MainManager.DeviceManager, Settings);
VolumeDisplay = new VolumeBar(DeviceManager, Settings);
}
public new VolumeDisplaySettings Settings { get; set; }
@ -79,7 +78,7 @@ namespace Artemis.Modules.Overlays.VolumeDisplay
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;
using (var g = Graphics.FromImage(frame.KeyboardBitmap))

View File

@ -1,6 +1,8 @@
using System.Windows.Media;
using Artemis.Managers;
using Artemis.Models;
using Artemis.ViewModels.Abstract;
using Ninject;
namespace Artemis.Modules.Overlays.VolumeDisplay
{
@ -10,13 +12,14 @@ namespace Artemis.Modules.Overlays.VolumeDisplay
private SolidColorBrush _mainColor;
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";
MainColor = new SolidColorBrush(model.Settings.MainColor);
SecondaryColor = new SolidColorBrush(model.Settings.SecondaryColor);
MainColor = new SolidColorBrush(_model.Settings.MainColor);
SecondaryColor = new SolidColorBrush(_model.Settings.SecondaryColor);
}
public Brush MainColor

View File

@ -531,6 +531,7 @@
<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-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="errorStream" minOccurs="0" maxOccurs="1" type="xs:boolean" />
</xs:choice>
@ -559,6 +560,11 @@
<xs:documentation>Indicates whether to use default row highlighting rules.</xs:documentation>
</xs:annotation>
</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:annotation>
<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="footer" minOccurs="0" maxOccurs="1" type="Layout" />
<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:choice>
<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:annotation>
</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:annotation>
<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;
// 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(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;
// 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(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;
// 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(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;
// 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(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;
// 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(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;
// 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(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