mirror of
https://github.com/Artemis-RGB/Artemis
synced 2026-01-02 10:43:31 +00:00
commit
507265b274
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio 14
|
# Visual Studio 14
|
||||||
VisualStudioVersion = 14.0.25123.0
|
VisualStudioVersion = 14.0.25420.1
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Artemis", "Artemis\Artemis.csproj", "{ED9997A2-E54C-4E9F-9350-62BE672C3ABE}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Artemis", "Artemis\Artemis.csproj", "{ED9997A2-E54C-4E9F-9350-62BE672C3ABE}"
|
||||||
EndProject
|
EndProject
|
||||||
|
|||||||
@ -56,6 +56,7 @@
|
|||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<Prefer32Bit>false</Prefer32Bit>
|
<Prefer32Bit>false</Prefer32Bit>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
@ -65,6 +66,7 @@
|
|||||||
<DefineConstants>TRACE</DefineConstants>
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<ManifestCertificateThumbprint>EAC088BE27A2DE790AE6F37A020409F4A1B5EC0E</ManifestCertificateThumbprint>
|
<ManifestCertificateThumbprint>EAC088BE27A2DE790AE6F37A020409F4A1B5EC0E</ManifestCertificateThumbprint>
|
||||||
@ -108,6 +110,7 @@
|
|||||||
<PlatformTarget>x64</PlatformTarget>
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||||
<OutputPath>bin\x64\Release\</OutputPath>
|
<OutputPath>bin\x64\Release\</OutputPath>
|
||||||
@ -118,6 +121,7 @@
|
|||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||||
<Prefer32Bit>true</Prefer32Bit>
|
<Prefer32Bit>true</Prefer32Bit>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup />
|
<PropertyGroup />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
@ -131,16 +135,16 @@
|
|||||||
<HintPath>..\packages\Betwixt.1.4.1\lib\net35\Betwixt.dll</HintPath>
|
<HintPath>..\packages\Betwixt.1.4.1\lib\net35\Betwixt.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Caliburn.Micro, Version=3.0.2.0, Culture=neutral, PublicKeyToken=8e5891231f2ed21f, processorArchitecture=MSIL">
|
<Reference Include="Caliburn.Micro, Version=3.0.3.0, Culture=neutral, PublicKeyToken=8e5891231f2ed21f, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\Caliburn.Micro.Core.3.0.2\lib\net45\Caliburn.Micro.dll</HintPath>
|
<HintPath>..\packages\Caliburn.Micro.Core.3.0.3\lib\net45\Caliburn.Micro.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Caliburn.Micro.Platform, Version=3.0.2.0, Culture=neutral, PublicKeyToken=8e5891231f2ed21f, processorArchitecture=MSIL">
|
<Reference Include="Caliburn.Micro.Platform, Version=3.0.3.0, Culture=neutral, PublicKeyToken=8e5891231f2ed21f, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\Caliburn.Micro.3.0.2\lib\net45\Caliburn.Micro.Platform.dll</HintPath>
|
<HintPath>..\packages\Caliburn.Micro.3.0.3\lib\net45\Caliburn.Micro.Platform.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Caliburn.Micro.Platform.Core, Version=3.0.2.0, Culture=neutral, PublicKeyToken=8e5891231f2ed21f, processorArchitecture=MSIL">
|
<Reference Include="Caliburn.Micro.Platform.Core, Version=3.0.3.0, Culture=neutral, PublicKeyToken=8e5891231f2ed21f, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\Caliburn.Micro.3.0.2\lib\net45\Caliburn.Micro.Platform.Core.dll</HintPath>
|
<HintPath>..\packages\Caliburn.Micro.3.0.3\lib\net45\Caliburn.Micro.Platform.Core.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Castle.Core, Version=3.3.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
|
<Reference Include="Castle.Core, Version=3.3.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
|
||||||
@ -151,8 +155,12 @@
|
|||||||
<HintPath>..\packages\Colore.5.1.0\lib\net35\Corale.Colore.dll</HintPath>
|
<HintPath>..\packages\Colore.5.1.0\lib\net35\Corale.Colore.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="CUE.NET, Version=1.1.0.2, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="CSCore, Version=1.1.5992.18249, Culture=neutral, PublicKeyToken=5a08f2b6f4415dea, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\CUE.NET.1.1.0.2\lib\net45\CUE.NET.dll</HintPath>
|
<HintPath>..\packages\CSCore.1.1.0\lib\net35-client\CSCore.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="CUE.NET, Version=1.1.1.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\CUE.NET.1.1.1\lib\net45\CUE.NET.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="DeltaCompressionDotNet, Version=1.1.0.0, Culture=neutral, PublicKeyToken=1d14d6e5194e7f4a, processorArchitecture=MSIL">
|
<Reference Include="DeltaCompressionDotNet, Version=1.1.0.0, Culture=neutral, PublicKeyToken=1d14d6e5194e7f4a, processorArchitecture=MSIL">
|
||||||
@ -168,7 +176,7 @@
|
|||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="DynamicExpresso.Core, Version=1.3.3.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="DynamicExpresso.Core, Version=1.3.3.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\DynamicExpresso.Core.1.3.3.4\lib\net40\DynamicExpresso.Core.dll</HintPath>
|
<HintPath>..\packages\DynamicExpresso.Core.1.3.3.5\lib\net40\DynamicExpresso.Core.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="GongSolutions.Wpf.DragDrop, Version=0.1.4.3, Culture=neutral, PublicKeyToken=d19974ea350ccea1, processorArchitecture=MSIL">
|
<Reference Include="GongSolutions.Wpf.DragDrop, Version=0.1.4.3, Culture=neutral, PublicKeyToken=d19974ea350ccea1, processorArchitecture=MSIL">
|
||||||
@ -180,15 +188,15 @@
|
|||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\squirrel.windows.1.4.4\lib\Net45\ICSharpCode.SharpZipLib.dll</HintPath>
|
<HintPath>..\packages\squirrel.windows.1.5.1\lib\Net45\ICSharpCode.SharpZipLib.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="log4net, Version=1.2.15.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
|
<Reference Include="log4net, Version=2.0.7.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\log4net.2.0.5\lib\net45-full\log4net.dll</HintPath>
|
<HintPath>..\packages\log4net.2.0.7\lib\net45-full\log4net.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="MahApps.Metro, Version=1.3.0.0, Culture=neutral, PublicKeyToken=f4fb5a3c4d1e5b4f, processorArchitecture=MSIL">
|
<Reference Include="MahApps.Metro, Version=1.4.1.0, Culture=neutral, PublicKeyToken=f4fb5a3c4d1e5b4f, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\MahApps.Metro.1.3.0\lib\net45\MahApps.Metro.dll</HintPath>
|
<HintPath>..\packages\MahApps.Metro.1.4.1\lib\net45\MahApps.Metro.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Mono.Cecil, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
|
<Reference Include="Mono.Cecil, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
|
||||||
@ -211,10 +219,6 @@
|
|||||||
<HintPath>..\packages\MoonSharp.2.0.0.0\lib\net40-client\MoonSharp.Interpreter.dll</HintPath>
|
<HintPath>..\packages\MoonSharp.2.0.0.0\lib\net40-client\MoonSharp.Interpreter.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</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>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
<Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
<HintPath>..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
@ -240,11 +244,15 @@
|
|||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="NuGet.Squirrel, Version=3.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="NuGet.Squirrel, Version=3.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\squirrel.windows.1.4.4\lib\Net45\NuGet.Squirrel.dll</HintPath>
|
<HintPath>..\packages\squirrel.windows.1.5.1\lib\Net45\NuGet.Squirrel.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Open.WinKeyboardHook, Version=1.0.11.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Open.WinKeyboardHook.1.0.11\lib\net45\Open.WinKeyboardHook.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Process.NET, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="Process.NET, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\Process.NET.1.0.5\lib\Process.NET.dll</HintPath>
|
<HintPath>..\packages\Process.NET.1.0.8\lib\Process.NET.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="SharpDX, Version=3.1.1.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
|
<Reference Include="SharpDX, Version=3.1.1.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
|
||||||
@ -263,8 +271,8 @@
|
|||||||
<HintPath>..\packages\SpotifyAPI-NET.2.12.0\lib\SpotifyAPI.dll</HintPath>
|
<HintPath>..\packages\SpotifyAPI-NET.2.12.0\lib\SpotifyAPI.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Squirrel, Version=1.4.3.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="Squirrel, Version=1.5.1.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\squirrel.windows.1.4.4\lib\Net45\Squirrel.dll</HintPath>
|
<HintPath>..\packages\squirrel.windows.1.5.1\lib\Net45\Squirrel.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
@ -278,7 +286,7 @@
|
|||||||
<Reference Include="System.Web" />
|
<Reference Include="System.Web" />
|
||||||
<Reference Include="System.Windows.Forms" />
|
<Reference Include="System.Windows.Forms" />
|
||||||
<Reference Include="System.Windows.Interactivity, Version=4.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
<Reference Include="System.Windows.Interactivity, Version=4.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\MahApps.Metro.1.3.0\lib\net45\System.Windows.Interactivity.dll</HintPath>
|
<HintPath>..\packages\MahApps.Metro.1.4.1\lib\net45\System.Windows.Interactivity.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
@ -294,10 +302,6 @@
|
|||||||
<HintPath>..\packages\WpfExceptionViewer.1.0.0.0\lib\VioletTape.WpfExceptionViewer.dll</HintPath>
|
<HintPath>..\packages\WpfExceptionViewer.1.0.0.0\lib\VioletTape.WpfExceptionViewer.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="VirtualInput, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
|
||||||
<HintPath>..\packages\VirtualInput.1.0.1\lib\net20\VirtualInput.dll</HintPath>
|
|
||||||
<Private>True</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="WindowsBase" />
|
<Reference Include="WindowsBase" />
|
||||||
<Reference Include="PresentationCore" />
|
<Reference Include="PresentationCore" />
|
||||||
<Reference Include="PresentationFramework" />
|
<Reference Include="PresentationFramework" />
|
||||||
@ -350,12 +354,15 @@
|
|||||||
<Compile Include="DeviceProviders\Logitech\Utilities\OrionUtilities.cs" />
|
<Compile Include="DeviceProviders\Logitech\Utilities\OrionUtilities.cs" />
|
||||||
<Compile Include="DeviceProviders\Razer\BlackWidow.cs" />
|
<Compile Include="DeviceProviders\Razer\BlackWidow.cs" />
|
||||||
<Compile Include="DeviceProviders\Razer\Utilities\RazerUtilities.cs" />
|
<Compile Include="DeviceProviders\Razer\Utilities\RazerUtilities.cs" />
|
||||||
|
<Compile Include="Managers\MigrationManager.cs" />
|
||||||
<Compile Include="Managers\ModuleManager.cs" />
|
<Compile Include="Managers\ModuleManager.cs" />
|
||||||
<Compile Include="Managers\DeviceManager.cs" />
|
<Compile Include="Managers\DeviceManager.cs" />
|
||||||
<Compile Include="Managers\LoopManager.cs" />
|
<Compile Include="Managers\LoopManager.cs" />
|
||||||
<Compile Include="Managers\LuaManager.cs" />
|
<Compile Include="Managers\LuaManager.cs" />
|
||||||
<Compile Include="Managers\MainManager.cs" />
|
<Compile Include="Managers\MainManager.cs" />
|
||||||
<Compile Include="Managers\ProfileManager.cs" />
|
<Compile Include="Managers\PreviewManager.cs" />
|
||||||
|
<Compile Include="Models\LayerEditorModel.cs" />
|
||||||
|
<Compile Include="Models\ProfileEditorModel.cs" />
|
||||||
<Compile Include="Modules\Abstract\ModuleDataModel.cs" />
|
<Compile Include="Modules\Abstract\ModuleDataModel.cs" />
|
||||||
<Compile Include="Modules\Abstract\ModuleModel.cs" />
|
<Compile Include="Modules\Abstract\ModuleModel.cs" />
|
||||||
<Compile Include="Modules\Abstract\ModuleSettings.cs" />
|
<Compile Include="Modules\Abstract\ModuleSettings.cs" />
|
||||||
@ -489,9 +496,21 @@
|
|||||||
<Compile Include="Profiles\Layers\Types\AmbientLight\ScreenCapturing\DX9ScreenCapture.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\IScreenCapture.cs" />
|
||||||
<Compile Include="Profiles\Layers\Types\AmbientLight\ScreenCapturing\ScreenCaptureManager.cs" />
|
<Compile Include="Profiles\Layers\Types\AmbientLight\ScreenCapturing\ScreenCaptureManager.cs" />
|
||||||
<Compile Include="Profiles\Layers\Types\Audio\AudioCapturing\AudioCaptureManager.cs" />
|
<Compile Include="Profiles\Layers\Types\ConicalBrush\ConicalBrushPropertiesModel.cs" />
|
||||||
<Compile Include="Profiles\Layers\Types\Audio\AudioCapturing\FftEventArgs.cs" />
|
<Compile Include="Profiles\Layers\Types\ConicalBrush\ConicalBrushPropertiesView.xaml.cs">
|
||||||
<Compile Include="Profiles\Layers\Types\Audio\AudioCapturing\SampleAggregator.cs" />
|
<DependentUpon>ConicalBrushPropertiesView.xaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Profiles\Layers\Types\ConicalBrush\ConicalBrushPropertiesViewModel.cs" />
|
||||||
|
<Compile Include="Profiles\Layers\Types\ConicalBrush\ConicalBrushType.cs" />
|
||||||
|
<Compile Include="Profiles\Layers\Types\ConicalBrush\Drawing\ConicalGradientDrawer.cs" />
|
||||||
|
<Compile Include="Profiles\Layers\Types\Audio\AudioCapturing\AudioCapture.cs" />
|
||||||
|
<Compile Include="Managers\AudioCaptureManager.cs" />
|
||||||
|
<Compile Include="Events\AudioDeviceChangedEventArgs.cs" />
|
||||||
|
<Compile Include="Profiles\Layers\Types\Audio\AudioCapturing\BaseSpectrumProvider.cs" />
|
||||||
|
<Compile Include="Profiles\Layers\Types\Audio\AudioCapturing\ISpectrumProvider.cs" />
|
||||||
|
<Compile Include="Profiles\Layers\Types\Audio\AudioCapturing\LineSpectrum.cs" />
|
||||||
|
<Compile Include="Profiles\Layers\Types\Audio\AudioCapturing\SingleSpectrum.cs" />
|
||||||
|
<Compile Include="Profiles\Layers\Types\Audio\AudioCapturing\SpectrumBase.cs" />
|
||||||
<Compile Include="Profiles\Layers\Types\Audio\AudioPropertiesModel.cs" />
|
<Compile Include="Profiles\Layers\Types\Audio\AudioPropertiesModel.cs" />
|
||||||
<Compile Include="Profiles\Layers\Types\Audio\AudioPropertiesView.xaml.cs">
|
<Compile Include="Profiles\Layers\Types\Audio\AudioPropertiesView.xaml.cs">
|
||||||
<DependentUpon>AudioPropertiesView.xaml</DependentUpon>
|
<DependentUpon>AudioPropertiesView.xaml</DependentUpon>
|
||||||
@ -618,6 +637,7 @@
|
|||||||
<Compile Include="Utilities\Converters\NinjectCustomConverter.cs" />
|
<Compile Include="Utilities\Converters\NinjectCustomConverter.cs" />
|
||||||
<Compile Include="Utilities\Converters\ValueConverters.cs" />
|
<Compile Include="Utilities\Converters\ValueConverters.cs" />
|
||||||
<Compile Include="Utilities\DataReaders\DllManager.cs" />
|
<Compile Include="Utilities\DataReaders\DllManager.cs" />
|
||||||
|
<Compile Include="Utilities\EditorHelper.cs" />
|
||||||
<Compile Include="Utilities\ExtensionMethods.cs" />
|
<Compile Include="Utilities\ExtensionMethods.cs" />
|
||||||
<Compile Include="Utilities\GameState\GameDataReceivedEventArgs.cs" />
|
<Compile Include="Utilities\GameState\GameDataReceivedEventArgs.cs" />
|
||||||
<Compile Include="Utilities\GameState\GameStateWebServer.cs" />
|
<Compile Include="Utilities\GameState\GameStateWebServer.cs" />
|
||||||
@ -649,17 +669,16 @@
|
|||||||
<Compile Include="Modules\Games\Witcher3\Witcher3ViewModel.cs" />
|
<Compile Include="Modules\Games\Witcher3\Witcher3ViewModel.cs" />
|
||||||
<Compile Include="ViewModels\Profiles\LayerTweenViewModel.cs" />
|
<Compile Include="ViewModels\Profiles\LayerTweenViewModel.cs" />
|
||||||
<Compile Include="ViewModels\Profiles\Events\EventPropertiesViewModel.cs" />
|
<Compile Include="ViewModels\Profiles\Events\EventPropertiesViewModel.cs" />
|
||||||
<Compile Include="ViewModels\Profiles\ProfileViewModel.cs" />
|
|
||||||
<Compile Include="Profiles\Layers\Types\Keyboard\KeyboardPropertiesViewModel.cs" />
|
<Compile Include="Profiles\Layers\Types\Keyboard\KeyboardPropertiesViewModel.cs" />
|
||||||
<Compile Include="ViewModels\Profiles\LayerConditionViewModel.cs" />
|
<Compile Include="ViewModels\Profiles\LayerConditionViewModel.cs" />
|
||||||
<Compile Include="ViewModels\Profiles\LayerDynamicPropertiesViewModel.cs" />
|
<Compile Include="ViewModels\Profiles\LayerDynamicPropertiesViewModel.cs" />
|
||||||
<Compile Include="ViewModels\Profiles\LayerEditorViewModel.cs" />
|
<Compile Include="ViewModels\LayerEditorViewModel.cs" />
|
||||||
<Compile Include="Profiles\Layers\Abstract\LayerPropertiesViewModel.cs" />
|
<Compile Include="Profiles\Layers\Abstract\LayerPropertiesViewModel.cs" />
|
||||||
<Compile Include="Profiles\Layers\Types\Headset\HeadsetPropertiesViewModel.cs" />
|
<Compile Include="Profiles\Layers\Types\Headset\HeadsetPropertiesViewModel.cs" />
|
||||||
<Compile Include="Profiles\Layers\Types\Folder\FolderPropertiesViewModel.cs" />
|
<Compile Include="Profiles\Layers\Types\Folder\FolderPropertiesViewModel.cs" />
|
||||||
<Compile Include="Profiles\Layers\Types\Mouse\MousePropertiesViewModel.cs" />
|
<Compile Include="Profiles\Layers\Types\Mouse\MousePropertiesViewModel.cs" />
|
||||||
<Compile Include="ViewModels\OverlaysViewModel.cs" />
|
<Compile Include="ViewModels\OverlaysViewModel.cs" />
|
||||||
<Compile Include="ViewModels\Profiles\ProfileEditorViewModel.cs" />
|
<Compile Include="ViewModels\ProfileEditorViewModel.cs" />
|
||||||
<Compile Include="ViewModels\ShellViewModel.cs" />
|
<Compile Include="ViewModels\ShellViewModel.cs" />
|
||||||
<Compile Include="ViewModels\WelcomeViewModel.cs" />
|
<Compile Include="ViewModels\WelcomeViewModel.cs" />
|
||||||
<Compile Include="Views\DebugView.xaml.cs">
|
<Compile Include="Views\DebugView.xaml.cs">
|
||||||
@ -704,7 +723,7 @@
|
|||||||
<Compile Include="Views\Profiles\LayerDynamicPropertiesView.xaml.cs">
|
<Compile Include="Views\Profiles\LayerDynamicPropertiesView.xaml.cs">
|
||||||
<DependentUpon>LayerDynamicPropertiesView.xaml</DependentUpon>
|
<DependentUpon>LayerDynamicPropertiesView.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Views\Profiles\LayerEditorView.xaml.cs">
|
<Compile Include="Views\LayerEditorView.xaml.cs">
|
||||||
<DependentUpon>LayerEditorView.xaml</DependentUpon>
|
<DependentUpon>LayerEditorView.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Profiles\Layers\Types\Mouse\MousePropertiesView.xaml.cs">
|
<Compile Include="Profiles\Layers\Types\Mouse\MousePropertiesView.xaml.cs">
|
||||||
@ -716,7 +735,7 @@
|
|||||||
<Compile Include="Views\Profiles\LayerTweenView.xaml.cs">
|
<Compile Include="Views\Profiles\LayerTweenView.xaml.cs">
|
||||||
<DependentUpon>LayerTweenView.xaml</DependentUpon>
|
<DependentUpon>LayerTweenView.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Views\Profiles\ProfileEditorView.xaml.cs">
|
<Compile Include="Views\ProfileEditorView.xaml.cs">
|
||||||
<DependentUpon>ProfileEditorView.xaml</DependentUpon>
|
<DependentUpon>ProfileEditorView.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Views\ShellView.xaml.cs">
|
<Compile Include="Views\ShellView.xaml.cs">
|
||||||
@ -855,6 +874,10 @@
|
|||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</Page>
|
</Page>
|
||||||
|
<Page Include="Profiles\Layers\Types\ConicalBrush\ConicalBrushPropertiesView.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
</Page>
|
||||||
<Page Include="Profiles\Layers\Types\Audio\AudioPropertiesView.xaml">
|
<Page Include="Profiles\Layers\Types\Audio\AudioPropertiesView.xaml">
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
@ -947,7 +970,7 @@
|
|||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
</Page>
|
</Page>
|
||||||
<Page Include="Views\Profiles\LayerEditorView.xaml">
|
<Page Include="Views\LayerEditorView.xaml">
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</Page>
|
</Page>
|
||||||
@ -963,7 +986,7 @@
|
|||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
</Page>
|
</Page>
|
||||||
<Page Include="Views\Profiles\ProfileEditorView.xaml">
|
<Page Include="Views\ProfileEditorView.xaml">
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
</Page>
|
</Page>
|
||||||
@ -1010,12 +1033,12 @@
|
|||||||
<Folder Include="Resources\Lua\" />
|
<Folder Include="Resources\Lua\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
<Import Project="..\packages\CUE.NET.1.1.0.2\build\net45\CUE.NET.targets" Condition="Exists('..\packages\CUE.NET.1.1.0.2\build\net45\CUE.NET.targets')" />
|
<Import Project="..\packages\CUE.NET.1.1.1\build\net45\CUE.NET.targets" Condition="Exists('..\packages\CUE.NET.1.1.1\build\net45\CUE.NET.targets')" />
|
||||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Error Condition="!Exists('..\packages\CUE.NET.1.1.0.2\build\net45\CUE.NET.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\CUE.NET.1.1.0.2\build\net45\CUE.NET.targets'))" />
|
<Error Condition="!Exists('..\packages\CUE.NET.1.1.1\build\net45\CUE.NET.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\CUE.NET.1.1.1\build\net45\CUE.NET.targets'))" />
|
||||||
</Target>
|
</Target>
|
||||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
Other similar extension points exist, see Microsoft.Common.targets.
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
@ -9,6 +10,7 @@ using Artemis.Settings;
|
|||||||
using Artemis.Utilities;
|
using Artemis.Utilities;
|
||||||
using Artemis.Utilities.Converters;
|
using Artemis.Utilities.Converters;
|
||||||
using Artemis.Utilities.DataReaders;
|
using Artemis.Utilities.DataReaders;
|
||||||
|
using Artemis.Utilities.Keyboard;
|
||||||
using Artemis.ViewModels;
|
using Artemis.ViewModels;
|
||||||
using Caliburn.Micro;
|
using Caliburn.Micro;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
@ -29,6 +31,7 @@ namespace Artemis
|
|||||||
|
|
||||||
Initialize();
|
Initialize();
|
||||||
BindSpecialValues();
|
BindSpecialValues();
|
||||||
|
KeyboardHook.SetupKeyboardHook();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BindSpecialValues()
|
private void BindSpecialValues()
|
||||||
@ -91,6 +94,7 @@ namespace Artemis
|
|||||||
JsonConvert.DefaultSettings = () => settings;
|
JsonConvert.DefaultSettings = () => settings;
|
||||||
|
|
||||||
//TODO DarthAffe 17.12.2016: Is this the right location for this?
|
//TODO DarthAffe 17.12.2016: Is this the right location for this?
|
||||||
|
//TODO Move to Mainmanager and make disposable
|
||||||
ActiveWindowHelper.Initialize();
|
ActiveWindowHelper.Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -21,7 +21,7 @@ namespace Artemis.DAL
|
|||||||
{
|
{
|
||||||
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
private static readonly string ProfileFolder =
|
public static readonly string ProfileFolder =
|
||||||
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\Artemis\profiles";
|
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\Artemis\profiles";
|
||||||
|
|
||||||
private static bool _installedDefaults;
|
private static bool _installedDefaults;
|
||||||
@ -89,7 +89,7 @@ namespace Artemis.DAL
|
|||||||
}
|
}
|
||||||
|
|
||||||
File.WriteAllText(path + $@"\{prof.Slug}.json", json);
|
File.WriteAllText(path + $@"\{prof.Slug}.json", json);
|
||||||
Logger.Trace("Saved profile {0}/{1}/{2}", prof.KeyboardSlug, prof.GameName, prof.Name);
|
Logger.Debug("Saved profile {0}/{1}/{2}", prof.KeyboardSlug, prof.GameName, prof.Name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,7 +177,7 @@ namespace Artemis.DAL
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<ProfileModel> ReadProfiles(string subDirectory)
|
public static List<ProfileModel> ReadProfiles(string subDirectory)
|
||||||
{
|
{
|
||||||
var profiles = new List<ProfileModel>();
|
var profiles = new List<ProfileModel>();
|
||||||
var directory = ProfileFolder + "/" + subDirectory;
|
var directory = ProfileFolder + "/" + subDirectory;
|
||||||
|
|||||||
@ -34,7 +34,7 @@ namespace Artemis.DeviceProviders.Corsair
|
|||||||
|
|
||||||
public override void Disable()
|
public override void Disable()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException("Can only disable a keyboard");
|
throw new NotSupportedException("Can only disable a keyboard");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void UpdateDevice(Bitmap bitmap)
|
public override void UpdateDevice(Bitmap bitmap)
|
||||||
@ -45,7 +45,7 @@ namespace Artemis.DeviceProviders.Corsair
|
|||||||
throw new ArgumentException("Bitmap must be a perfect square");
|
throw new ArgumentException("Bitmap must be a perfect square");
|
||||||
|
|
||||||
var leds = CueSDK.HeadsetSDK.Leds.Count();
|
var leds = CueSDK.HeadsetSDK.Leds.Count();
|
||||||
var step = (double) bitmap.Width/leds;
|
var step = (double)bitmap.Width / leds;
|
||||||
|
|
||||||
var ledIndex = 0;
|
var ledIndex = 0;
|
||||||
// Color each LED according to one of the pixels
|
// Color each LED according to one of the pixels
|
||||||
@ -53,7 +53,7 @@ namespace Artemis.DeviceProviders.Corsair
|
|||||||
{
|
{
|
||||||
var col = ledIndex == 0
|
var col = ledIndex == 0
|
||||||
? bitmap.GetPixel(0, 0)
|
? bitmap.GetPixel(0, 0)
|
||||||
: bitmap.GetPixel((int) ((ledIndex + 1)*step - 1), (int) ((ledIndex + 1)*step - 1));
|
: bitmap.GetPixel((int)((ledIndex + 1) * step - 1), (int)((ledIndex + 1) * step - 1));
|
||||||
|
|
||||||
corsairLed.Color = col;
|
corsairLed.Color = col;
|
||||||
ledIndex++;
|
ledIndex++;
|
||||||
|
|||||||
@ -136,8 +136,8 @@ namespace Artemis.DeviceProviders.Corsair
|
|||||||
|
|
||||||
public override KeyMatch? GetKeyPosition(Keys keyCode)
|
public override KeyMatch? GetKeyPosition(Keys keyCode)
|
||||||
{
|
{
|
||||||
var widthMultiplier = Width/_keyboard.Brush.RenderedRectangle.Width;
|
var widthMultiplier = Width / _keyboard.Brush.RenderedRectangle.Width;
|
||||||
var heightMultiplier = Height/_keyboard.Brush.RenderedRectangle.Height;
|
var heightMultiplier = Height / _keyboard.Brush.RenderedRectangle.Height;
|
||||||
|
|
||||||
CorsairLed cueLed = null;
|
CorsairLed cueLed = null;
|
||||||
try
|
try
|
||||||
@ -154,7 +154,7 @@ namespace Artemis.DeviceProviders.Corsair
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
var center = cueLed.LedRectangle.GetCenter();
|
var center = cueLed.LedRectangle.GetCenter();
|
||||||
return new KeyMatch(keyCode, (int) (center.X*widthMultiplier), (int) (center.Y*heightMultiplier));
|
return new KeyMatch(keyCode, (int)(center.X * widthMultiplier), (int)(center.Y * heightMultiplier));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -34,7 +34,7 @@ namespace Artemis.DeviceProviders.Corsair
|
|||||||
|
|
||||||
public override void Disable()
|
public override void Disable()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException("Can only disable a keyboard");
|
throw new NotSupportedException("Can only disable a keyboard");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void UpdateDevice(Bitmap bitmap)
|
public override void UpdateDevice(Bitmap bitmap)
|
||||||
@ -45,7 +45,7 @@ namespace Artemis.DeviceProviders.Corsair
|
|||||||
throw new ArgumentException("Bitmap must be a perfect square");
|
throw new ArgumentException("Bitmap must be a perfect square");
|
||||||
|
|
||||||
var leds = CueSDK.MouseSDK.Leds.Count();
|
var leds = CueSDK.MouseSDK.Leds.Count();
|
||||||
var step = (double) bitmap.Width/leds;
|
var step = (double)bitmap.Width / leds;
|
||||||
|
|
||||||
var ledIndex = 0;
|
var ledIndex = 0;
|
||||||
// Color each LED according to one of the pixels
|
// Color each LED according to one of the pixels
|
||||||
@ -53,7 +53,7 @@ namespace Artemis.DeviceProviders.Corsair
|
|||||||
{
|
{
|
||||||
var col = ledIndex == 0
|
var col = ledIndex == 0
|
||||||
? bitmap.GetPixel(0, 0)
|
? bitmap.GetPixel(0, 0)
|
||||||
: bitmap.GetPixel((int) ((ledIndex + 1)*step - 1), (int) ((ledIndex + 1)*step - 1));
|
: bitmap.GetPixel((int)((ledIndex + 1) * step - 1), (int)((ledIndex + 1) * step - 1));
|
||||||
|
|
||||||
corsairLed.Color = col;
|
corsairLed.Color = col;
|
||||||
ledIndex++;
|
ledIndex++;
|
||||||
|
|||||||
@ -34,7 +34,7 @@ namespace Artemis.DeviceProviders.Corsair
|
|||||||
|
|
||||||
public override void Disable()
|
public override void Disable()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException("Can only disable a keyboard");
|
throw new NotSupportedException("Can only disable a keyboard");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void UpdateDevice(Bitmap bitmap)
|
public override void UpdateDevice(Bitmap bitmap)
|
||||||
@ -44,8 +44,8 @@ namespace Artemis.DeviceProviders.Corsair
|
|||||||
if (bitmap.Width != bitmap.Height)
|
if (bitmap.Width != bitmap.Height)
|
||||||
throw new ArgumentException("Bitmap must be a perfect square");
|
throw new ArgumentException("Bitmap must be a perfect square");
|
||||||
|
|
||||||
var yStep = (double) bitmap.Width/4;
|
var yStep = (double)bitmap.Width / 4;
|
||||||
var xStep = (double) bitmap.Width/6;
|
var xStep = (double)bitmap.Width / 6;
|
||||||
|
|
||||||
// This approach will break if any mousemats with different LED amounts are released, for now it will do.
|
// This approach will break if any mousemats with different LED amounts are released, for now it will do.
|
||||||
var ledIndex = 0;
|
var ledIndex = 0;
|
||||||
@ -57,23 +57,23 @@ namespace Artemis.DeviceProviders.Corsair
|
|||||||
if (ledIndex < 5)
|
if (ledIndex < 5)
|
||||||
{
|
{
|
||||||
col = ledIndex == 0
|
col = ledIndex == 0
|
||||||
? bitmap.GetPixel(0, (int) (ledIndex*yStep))
|
? bitmap.GetPixel(0, (int)(ledIndex * yStep))
|
||||||
: bitmap.GetPixel(0, (int) (ledIndex*yStep) - 1);
|
: bitmap.GetPixel(0, (int)(ledIndex * yStep) - 1);
|
||||||
}
|
}
|
||||||
// Bottom
|
// Bottom
|
||||||
else if (ledIndex < 10)
|
else if (ledIndex < 10)
|
||||||
{
|
{
|
||||||
// Start at index 1 because the corner belongs to the left side
|
// Start at index 1 because the corner belongs to the left side
|
||||||
var zoneIndex = ledIndex - 4;
|
var zoneIndex = ledIndex - 4;
|
||||||
col = bitmap.GetPixel((int) (zoneIndex*xStep), bitmap.Height - 1);
|
col = bitmap.GetPixel((int)(zoneIndex * xStep), bitmap.Height - 1);
|
||||||
}
|
}
|
||||||
// Right side
|
// Right side
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var zoneIndex = ledIndex - 10;
|
var zoneIndex = ledIndex - 10;
|
||||||
col = zoneIndex == 4
|
col = zoneIndex == 4
|
||||||
? bitmap.GetPixel(bitmap.Height - 1, bitmap.Height - (int) (zoneIndex*yStep))
|
? bitmap.GetPixel(bitmap.Height - 1, bitmap.Height - (int)(zoneIndex * yStep))
|
||||||
: bitmap.GetPixel(bitmap.Height - 1, bitmap.Height - 1 - (int) (zoneIndex*yStep));
|
: bitmap.GetPixel(bitmap.Height - 1, bitmap.Height - 1 - (int)(zoneIndex * yStep));
|
||||||
}
|
}
|
||||||
|
|
||||||
corsairLed.Color = col;
|
corsairLed.Color = col;
|
||||||
|
|||||||
@ -27,17 +27,11 @@ namespace Artemis.DeviceProviders
|
|||||||
public abstract void Enable();
|
public abstract void Enable();
|
||||||
public abstract void DrawBitmap(Bitmap bitmap);
|
public abstract void DrawBitmap(Bitmap bitmap);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns a bitmap matching the keyboard's dimensions
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public Bitmap KeyboardBitmap() => new Bitmap(Width, Height);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a bitmap matching the keyboard's dimensions using the provided scale
|
/// Returns a bitmap matching the keyboard's dimensions using the provided scale
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public Bitmap KeyboardBitmap(int scale) => new Bitmap(Width*scale, Height*scale);
|
public Bitmap KeyboardBitmap(int scale = 4) => new Bitmap(Width*scale, Height*scale);
|
||||||
|
|
||||||
public Rect KeyboardRectangle(int scale = 4) => new Rect(new Size(Width*scale, Height*scale));
|
public Rect KeyboardRectangle(int scale = 4) => new Rect(new Size(Width*scale, Height*scale));
|
||||||
|
|
||||||
@ -89,13 +83,12 @@ namespace Artemis.DeviceProviders
|
|||||||
|
|
||||||
public override void UpdateDevice(Bitmap bitmap)
|
public override void UpdateDevice(Bitmap bitmap)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException("KeyboardProvider doesn't implement UpdateDevice, use DrawBitmap instead.");
|
throw new NotSupportedException("KeyboardProvider doesn't implement UpdateDevice, use DrawBitmap instead.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool TryEnable()
|
public override bool TryEnable()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException(
|
throw new NotSupportedException("KeyboardProvider doesn't implement TryEnable, use CanEnableAsync instead.");
|
||||||
"KeyboardProvider doesn't implement TryEnable, use CanEnableAsync instead.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@ -49,7 +49,7 @@ namespace Artemis.DeviceProviders.Logitech
|
|||||||
|
|
||||||
public override void Disable()
|
public override void Disable()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException("Can only disable a keyboard");
|
throw new NotSupportedException("Can only disable a keyboard");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
17
Artemis/Artemis/Events/AudioDeviceChangedEventArgs.cs
Normal file
17
Artemis/Artemis/Events/AudioDeviceChangedEventArgs.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
using System;
|
||||||
|
using CSCore.CoreAudioAPI;
|
||||||
|
|
||||||
|
namespace Artemis.Events
|
||||||
|
{
|
||||||
|
public class AudioDeviceChangedEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
public AudioDeviceChangedEventArgs(MMDevice defaultPlayback, MMDevice defaultRecording)
|
||||||
|
{
|
||||||
|
DefaultPlayback = defaultPlayback;
|
||||||
|
DefaultRecording = defaultRecording;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MMDevice DefaultPlayback { get; }
|
||||||
|
public MMDevice DefaultRecording { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,4 +1,6 @@
|
|||||||
using Artemis.DeviceProviders;
|
using Artemis.DeviceProviders;
|
||||||
|
using Artemis.Managers;
|
||||||
|
using Artemis.Models;
|
||||||
using Artemis.Modules.Abstract;
|
using Artemis.Modules.Abstract;
|
||||||
using Artemis.Profiles.Layers.Interfaces;
|
using Artemis.Profiles.Layers.Interfaces;
|
||||||
using Artemis.Profiles.Layers.Types.Audio.AudioCapturing;
|
using Artemis.Profiles.Layers.Types.Audio.AudioCapturing;
|
||||||
@ -8,7 +10,6 @@ using Artemis.Utilities.DataReaders;
|
|||||||
using Artemis.Utilities.GameState;
|
using Artemis.Utilities.GameState;
|
||||||
using Artemis.ViewModels;
|
using Artemis.ViewModels;
|
||||||
using Artemis.ViewModels.Abstract;
|
using Artemis.ViewModels.Abstract;
|
||||||
using Artemis.ViewModels.Profiles;
|
|
||||||
using Ninject.Extensions.Conventions;
|
using Ninject.Extensions.Conventions;
|
||||||
using Ninject.Modules;
|
using Ninject.Modules;
|
||||||
|
|
||||||
@ -18,10 +19,16 @@ namespace Artemis.InjectionModules
|
|||||||
{
|
{
|
||||||
public override void Load()
|
public override void Load()
|
||||||
{
|
{
|
||||||
|
#region Models
|
||||||
|
|
||||||
|
Bind<ProfileEditorModel>().ToSelf();
|
||||||
|
Bind<LayerEditorModel>().ToSelf();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region ViewModels
|
#region ViewModels
|
||||||
|
|
||||||
Bind<ShellViewModel>().ToSelf().InSingletonScope();
|
Bind<ShellViewModel>().ToSelf().InSingletonScope();
|
||||||
Bind<ProfileViewModel>().ToSelf();
|
|
||||||
Bind<ProfileEditorViewModel>().ToSelf();
|
Bind<ProfileEditorViewModel>().ToSelf();
|
||||||
Bind<DebugViewModel>().ToSelf().InSingletonScope();
|
Bind<DebugViewModel>().ToSelf().InSingletonScope();
|
||||||
Kernel.Bind(x =>
|
Kernel.Bind(x =>
|
||||||
@ -98,9 +105,6 @@ namespace Artemis.InjectionModules
|
|||||||
.InheritedFrom<ILayerType>()
|
.InheritedFrom<ILayerType>()
|
||||||
.BindToSelf());
|
.BindToSelf());
|
||||||
|
|
||||||
// Type helpers
|
|
||||||
Bind<AudioCaptureManager>().ToSelf().InSingletonScope();
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Lua
|
#region Lua
|
||||||
|
|||||||
@ -11,8 +11,10 @@ namespace Artemis.InjectionModules
|
|||||||
Bind<LoopManager>().ToSelf().InSingletonScope();
|
Bind<LoopManager>().ToSelf().InSingletonScope();
|
||||||
Bind<DeviceManager>().ToSelf().InSingletonScope();
|
Bind<DeviceManager>().ToSelf().InSingletonScope();
|
||||||
Bind<ModuleManager>().ToSelf().InSingletonScope();
|
Bind<ModuleManager>().ToSelf().InSingletonScope();
|
||||||
Bind<ProfileManager>().ToSelf().InSingletonScope();
|
Bind<PreviewManager>().ToSelf().InSingletonScope();
|
||||||
Bind<LuaManager>().ToSelf().InSingletonScope();
|
Bind<LuaManager>().ToSelf().InSingletonScope();
|
||||||
|
Bind<AudioCaptureManager>().ToSelf().InSingletonScope();
|
||||||
|
Bind<MigrationManager>().ToSelf().InSingletonScope();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
67
Artemis/Artemis/Managers/AudioCaptureManager.cs
Normal file
67
Artemis/Artemis/Managers/AudioCaptureManager.cs
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Timers;
|
||||||
|
using Artemis.Events;
|
||||||
|
using Artemis.Profiles.Layers.Types.Audio;
|
||||||
|
using Artemis.Profiles.Layers.Types.Audio.AudioCapturing;
|
||||||
|
using CSCore.CoreAudioAPI;
|
||||||
|
using Ninject.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace Artemis.Managers
|
||||||
|
{
|
||||||
|
public class AudioCaptureManager
|
||||||
|
{
|
||||||
|
private readonly List<AudioCapture> _audioCaptures;
|
||||||
|
private MMDevice _lastDefaultPlayback;
|
||||||
|
private MMDevice _lastDefaultRecording;
|
||||||
|
|
||||||
|
public AudioCaptureManager(ILogger logger)
|
||||||
|
{
|
||||||
|
Logger = logger;
|
||||||
|
_audioCaptures = new List<AudioCapture>();
|
||||||
|
_lastDefaultPlayback = MMDeviceEnumerator.TryGetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia);
|
||||||
|
_lastDefaultRecording = MMDeviceEnumerator.TryGetDefaultAudioEndpoint(DataFlow.Capture, Role.Multimedia);
|
||||||
|
|
||||||
|
var defaultDeviceTimer = new Timer(1000);
|
||||||
|
defaultDeviceTimer.Elapsed += DefaultDeviceTimerOnElapsed;
|
||||||
|
defaultDeviceTimer.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public event EventHandler<AudioDeviceChangedEventArgs> AudioDeviceChanged;
|
||||||
|
|
||||||
|
private void DefaultDeviceTimerOnElapsed(object sender, ElapsedEventArgs e)
|
||||||
|
{
|
||||||
|
var defaultPlayback = MMDeviceEnumerator.TryGetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia);
|
||||||
|
var defaultRecording = MMDeviceEnumerator.TryGetDefaultAudioEndpoint(DataFlow.Capture, Role.Multimedia);
|
||||||
|
|
||||||
|
if (defaultPlayback?.DeviceID == _lastDefaultPlayback?.DeviceID &&
|
||||||
|
defaultRecording?.DeviceID == _lastDefaultRecording?.DeviceID)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_lastDefaultPlayback = defaultPlayback;
|
||||||
|
_lastDefaultRecording = defaultRecording;
|
||||||
|
OnAudioDeviceChanged(new AudioDeviceChangedEventArgs(_lastDefaultPlayback, _lastDefaultRecording));
|
||||||
|
}
|
||||||
|
|
||||||
|
public AudioCapture GetAudioCapture(MMDevice device, MmDeviceType type)
|
||||||
|
{
|
||||||
|
// Return existing audio capture if found
|
||||||
|
var audioCapture = _audioCaptures.FirstOrDefault(a => a.Device.DeviceID == device.DeviceID);
|
||||||
|
if (audioCapture != null)
|
||||||
|
return audioCapture;
|
||||||
|
|
||||||
|
// Else create a new one and return that
|
||||||
|
var newAudioCapture = new AudioCapture(Logger, device, type);
|
||||||
|
_audioCaptures.Add(newAudioCapture);
|
||||||
|
return newAudioCapture;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ILogger Logger { get; set; }
|
||||||
|
|
||||||
|
protected virtual void OnAudioDeviceChanged(AudioDeviceChangedEventArgs e)
|
||||||
|
{
|
||||||
|
AudioDeviceChanged?.Invoke(this, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -3,13 +3,10 @@ using System.Drawing;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Timers;
|
|
||||||
using System.Windows.Media;
|
|
||||||
using Artemis.DeviceProviders;
|
using Artemis.DeviceProviders;
|
||||||
using Artemis.ViewModels;
|
using Artemis.ViewModels;
|
||||||
using Ninject.Extensions.Logging;
|
using Ninject.Extensions.Logging;
|
||||||
using Color = System.Drawing.Color;
|
using Color = System.Drawing.Color;
|
||||||
using Timer = System.Timers.Timer;
|
|
||||||
|
|
||||||
namespace Artemis.Managers
|
namespace Artemis.Managers
|
||||||
{
|
{
|
||||||
@ -21,7 +18,8 @@ namespace Artemis.Managers
|
|||||||
private readonly DebugViewModel _debugViewModel;
|
private readonly DebugViewModel _debugViewModel;
|
||||||
private readonly DeviceManager _deviceManager;
|
private readonly DeviceManager _deviceManager;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private readonly Timer _loopTimer;
|
//private readonly Timer _loopTimer;
|
||||||
|
private readonly Task _loopTask;
|
||||||
private readonly ModuleManager _moduleManager;
|
private readonly ModuleManager _moduleManager;
|
||||||
|
|
||||||
public LoopManager(ILogger logger, ModuleManager moduleManager, DeviceManager deviceManager,
|
public LoopManager(ILogger logger, ModuleManager moduleManager, DeviceManager deviceManager,
|
||||||
@ -33,10 +31,7 @@ namespace Artemis.Managers
|
|||||||
_debugViewModel = debugViewModel;
|
_debugViewModel = debugViewModel;
|
||||||
|
|
||||||
// Setup timers
|
// Setup timers
|
||||||
_loopTimer = new Timer(40);
|
_loopTask = Task.Factory.StartNew(ProcessLoop);
|
||||||
_loopTimer.Elapsed += LoopTimerOnElapsed;
|
|
||||||
_loopTimer.Start();
|
|
||||||
|
|
||||||
_logger.Info("Intialized LoopManager");
|
_logger.Info("Intialized LoopManager");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,21 +44,31 @@ namespace Artemis.Managers
|
|||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_loopTimer.Stop();
|
_loopTask.Dispose();
|
||||||
_loopTimer.Dispose();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LoopTimerOnElapsed(object sender, ElapsedEventArgs elapsedEventArgs)
|
private void ProcessLoop()
|
||||||
|
{
|
||||||
|
//TODO DarthAffe 14.01.2017: A stop-condition and a real cleanup instead of just aborting might be better
|
||||||
|
while (true)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
long preUpdateTicks = DateTime.Now.Ticks;
|
||||||
|
|
||||||
Render();
|
Render();
|
||||||
|
|
||||||
|
int sleep = (int)(40f - ((DateTime.Now.Ticks - preUpdateTicks) / 10000f));
|
||||||
|
if (sleep > 0)
|
||||||
|
Thread.Sleep(sleep);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
_logger.Warn(e, "Exception in render loop");
|
_logger.Warn(e, "Exception in render loop");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// ReSharper disable once FunctionNeverReturns
|
||||||
|
}
|
||||||
|
|
||||||
public Task StartAsync()
|
public Task StartAsync()
|
||||||
{
|
{
|
||||||
@ -93,7 +98,7 @@ namespace Artemis.Managers
|
|||||||
if (_moduleManager.ActiveModule == null)
|
if (_moduleManager.ActiveModule == null)
|
||||||
{
|
{
|
||||||
var lastModule = _moduleManager.GetLastModule();
|
var lastModule = _moduleManager.GetLastModule();
|
||||||
if (lastModule == null)
|
if (lastModule == null || !lastModule.Settings.IsEnabled)
|
||||||
{
|
{
|
||||||
_logger.Debug("Cancel LoopManager start, no module");
|
_logger.Debug("Cancel LoopManager start, no module");
|
||||||
return;
|
return;
|
||||||
@ -152,10 +157,11 @@ namespace Artemis.Managers
|
|||||||
var headsets = _deviceManager.HeadsetProviders.Where(m => m.CanUse).ToList();
|
var headsets = _deviceManager.HeadsetProviders.Where(m => m.CanUse).ToList();
|
||||||
var generics = _deviceManager.GenericProviders.Where(m => m.CanUse).ToList();
|
var generics = _deviceManager.GenericProviders.Where(m => m.CanUse).ToList();
|
||||||
var mousemats = _deviceManager.MousematProviders.Where(m => m.CanUse).ToList();
|
var mousemats = _deviceManager.MousematProviders.Where(m => m.CanUse).ToList();
|
||||||
|
|
||||||
var keyboardOnly = !mice.Any() && !headsets.Any() && !generics.Any() && !mousemats.Any();
|
var keyboardOnly = !mice.Any() && !headsets.Any() && !generics.Any() && !mousemats.Any();
|
||||||
|
|
||||||
// Setup the frame for this tick
|
// Setup the frame for this tick
|
||||||
using (var frame = new RenderFrame(_deviceManager.ActiveKeyboard))
|
using (var frame = new RenderFrame(_deviceManager.ActiveKeyboard, mice.Any(), headsets.Any(), generics.Any(), mousemats.Any()))
|
||||||
{
|
{
|
||||||
if (renderModule.IsInitialized)
|
if (renderModule.IsInitialized)
|
||||||
renderModule.Render(frame, keyboardOnly);
|
renderModule.Render(frame, keyboardOnly);
|
||||||
@ -197,47 +203,55 @@ namespace Artemis.Managers
|
|||||||
|
|
||||||
public class RenderFrame : IDisposable
|
public class RenderFrame : IDisposable
|
||||||
{
|
{
|
||||||
public RenderFrame(KeyboardProvider keyboard)
|
public RenderFrame(KeyboardProvider keyboard, bool renderMice, bool renderHeadsets, bool renderGenerics, bool renderMousemats)
|
||||||
{
|
{
|
||||||
if (keyboard == null)
|
if (keyboard == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
KeyboardBitmap = keyboard.KeyboardBitmap(4);
|
KeyboardBitmap = keyboard.KeyboardBitmap();
|
||||||
KeyboardBitmap.SetResolution(96, 96);
|
KeyboardBitmap.SetResolution(96, 96);
|
||||||
|
|
||||||
MouseBitmap = new Bitmap(40, 40);
|
|
||||||
MouseBitmap.SetResolution(96, 96);
|
|
||||||
|
|
||||||
HeadsetBitmap = new Bitmap(40, 40);
|
|
||||||
HeadsetBitmap.SetResolution(96, 96);
|
|
||||||
|
|
||||||
GenericBitmap = new Bitmap(40, 40);
|
|
||||||
GenericBitmap.SetResolution(96, 96);
|
|
||||||
|
|
||||||
MousematBitmap = new Bitmap(40, 40);
|
|
||||||
MousematBitmap.SetResolution(96, 96);
|
|
||||||
|
|
||||||
using (var g = Graphics.FromImage(KeyboardBitmap))
|
using (var g = Graphics.FromImage(KeyboardBitmap))
|
||||||
{
|
{
|
||||||
g.Clear(Color.Black);
|
g.Clear(Color.Black);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (renderMice)
|
||||||
|
{
|
||||||
|
MouseBitmap = new Bitmap(10, 10);
|
||||||
|
MouseBitmap.SetResolution(96, 96);
|
||||||
using (var g = Graphics.FromImage(MouseBitmap))
|
using (var g = Graphics.FromImage(MouseBitmap))
|
||||||
{
|
{
|
||||||
g.Clear(Color.Black);
|
g.Clear(Color.Black);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (renderHeadsets)
|
||||||
|
{
|
||||||
|
HeadsetBitmap = new Bitmap(10, 10);
|
||||||
|
HeadsetBitmap.SetResolution(96, 96);
|
||||||
using (var g = Graphics.FromImage(HeadsetBitmap))
|
using (var g = Graphics.FromImage(HeadsetBitmap))
|
||||||
{
|
{
|
||||||
g.Clear(Color.Black);
|
g.Clear(Color.Black);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (renderGenerics)
|
||||||
|
{
|
||||||
|
GenericBitmap = new Bitmap(10, 10);
|
||||||
|
GenericBitmap.SetResolution(96, 96);
|
||||||
using (var g = Graphics.FromImage(GenericBitmap))
|
using (var g = Graphics.FromImage(GenericBitmap))
|
||||||
{
|
{
|
||||||
g.Clear(Color.Black);
|
g.Clear(Color.Black);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (renderMousemats)
|
||||||
|
{
|
||||||
|
MousematBitmap = new Bitmap(10, 10);
|
||||||
|
MousematBitmap.SetResolution(96, 96);
|
||||||
using (var g = Graphics.FromImage(MousematBitmap))
|
using (var g = Graphics.FromImage(MousematBitmap))
|
||||||
{
|
{
|
||||||
g.Clear(Color.Black);
|
g.Clear(Color.Black);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Bitmap KeyboardBitmap { get; set; }
|
public Bitmap KeyboardBitmap { get; set; }
|
||||||
public Bitmap MouseBitmap { get; set; }
|
public Bitmap MouseBitmap { get; set; }
|
||||||
|
|||||||
@ -19,17 +19,19 @@ namespace Artemis.Managers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class MainManager : IDisposable
|
public class MainManager : IDisposable
|
||||||
{
|
{
|
||||||
|
private readonly MigrationManager _migrationManager;
|
||||||
private readonly Timer _processTimer;
|
private readonly Timer _processTimer;
|
||||||
|
|
||||||
public MainManager(ILogger logger, LoopManager loopManager, DeviceManager deviceManager,
|
public MainManager(ILogger logger, LoopManager loopManager, DeviceManager deviceManager,
|
||||||
ModuleManager moduleManager, ProfileManager profileManager, PipeServer pipeServer,
|
ModuleManager moduleManager, PreviewManager previewManager, MigrationManager migrationManager,
|
||||||
GameStateWebServer gameStateWebServer)
|
PipeServer pipeServer, GameStateWebServer gameStateWebServer)
|
||||||
{
|
{
|
||||||
|
_migrationManager = migrationManager;
|
||||||
Logger = logger;
|
Logger = logger;
|
||||||
LoopManager = loopManager;
|
LoopManager = loopManager;
|
||||||
DeviceManager = deviceManager;
|
DeviceManager = deviceManager;
|
||||||
ModuleManager = moduleManager;
|
ModuleManager = moduleManager;
|
||||||
ProfileManager = profileManager;
|
PreviewManager = previewManager;
|
||||||
PipeServer = pipeServer;
|
PipeServer = pipeServer;
|
||||||
|
|
||||||
_processTimer = new Timer(1000);
|
_processTimer = new Timer(1000);
|
||||||
@ -64,7 +66,7 @@ namespace Artemis.Managers
|
|||||||
public LoopManager LoopManager { get; }
|
public LoopManager LoopManager { get; }
|
||||||
public DeviceManager DeviceManager { get; set; }
|
public DeviceManager DeviceManager { get; set; }
|
||||||
public ModuleManager ModuleManager { get; set; }
|
public ModuleManager ModuleManager { get; set; }
|
||||||
public ProfileManager ProfileManager { get; set; }
|
public PreviewManager PreviewManager { get; set; }
|
||||||
|
|
||||||
public PipeServer PipeServer { get; set; }
|
public PipeServer PipeServer { get; set; }
|
||||||
public GameStateWebServer GameStateWebServer { get; set; }
|
public GameStateWebServer GameStateWebServer { get; set; }
|
||||||
@ -105,11 +107,13 @@ namespace Artemis.Managers
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Loads the last active effect and starts the program
|
/// Loads the last active effect and starts the program
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void EnableProgram()
|
public async void EnableProgram()
|
||||||
{
|
{
|
||||||
Logger.Debug("Enabling program");
|
Logger.Debug("Enabling program");
|
||||||
ProgramEnabled = true;
|
ProgramEnabled = true;
|
||||||
LoopManager.StartAsync();
|
await LoopManager.StartAsync();
|
||||||
|
|
||||||
|
_migrationManager.MigrateProfiles();
|
||||||
RaiseEnabledChangedEvent(new EnabledChangedEventArgs(ProgramEnabled));
|
RaiseEnabledChangedEvent(new EnabledChangedEventArgs(ProgramEnabled));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,6 +123,9 @@ namespace Artemis.Managers
|
|||||||
public void DisableProgram()
|
public void DisableProgram()
|
||||||
{
|
{
|
||||||
Logger.Debug("Disabling program");
|
Logger.Debug("Disabling program");
|
||||||
|
foreach (var overlayModule in ModuleManager.OverlayModules)
|
||||||
|
if (overlayModule.Settings.IsEnabled)
|
||||||
|
overlayModule.Dispose();
|
||||||
LoopManager.Stop();
|
LoopManager.Stop();
|
||||||
ProgramEnabled = false;
|
ProgramEnabled = false;
|
||||||
RaiseEnabledChangedEvent(new EnabledChangedEventArgs(ProgramEnabled));
|
RaiseEnabledChangedEvent(new EnabledChangedEventArgs(ProgramEnabled));
|
||||||
@ -148,7 +155,7 @@ namespace Artemis.Managers
|
|||||||
ModuleManager.DisableProcessBoundModule();
|
ModuleManager.DisableProcessBoundModule();
|
||||||
|
|
||||||
// If the currently active effect is a no longer running game, get rid of it.
|
// If the currently active effect is a no longer running game, get rid of it.
|
||||||
if (!processes.Any(p => p.ProcessName == module.ProcessName && p.HasExited == false))
|
if (!processes.Any(p => module.ProcessNames.Contains(p.ProcessName) && !p.HasExited))
|
||||||
{
|
{
|
||||||
Logger.Info("Disabling process bound module because process stopped: {0}", module.Name);
|
Logger.Info("Disabling process bound module because process stopped: {0}", module.Name);
|
||||||
ModuleManager.DisableProcessBoundModule();
|
ModuleManager.DisableProcessBoundModule();
|
||||||
@ -157,7 +164,7 @@ namespace Artemis.Managers
|
|||||||
|
|
||||||
// Look for running games, stopping on the first one that's found.
|
// Look for running games, stopping on the first one that's found.
|
||||||
var newModule = ModuleManager.ProcessModules.Where(g => g.Settings.IsEnabled && g.Settings.IsEnabled)
|
var newModule = ModuleManager.ProcessModules.Where(g => g.Settings.IsEnabled && g.Settings.IsEnabled)
|
||||||
.FirstOrDefault(g => processes.Any(p => p.ProcessName == g.ProcessName && p.HasExited == false));
|
.FirstOrDefault(g => processes.Any(p => g.ProcessNames.Contains(p.ProcessName) && !p.HasExited));
|
||||||
|
|
||||||
if (newModule == null || module == newModule)
|
if (newModule == null || module == newModule)
|
||||||
return;
|
return;
|
||||||
|
|||||||
40
Artemis/Artemis/Managers/MigrationManager.cs
Normal file
40
Artemis/Artemis/Managers/MigrationManager.cs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
using System.IO;
|
||||||
|
using Artemis.DAL;
|
||||||
|
|
||||||
|
namespace Artemis.Managers
|
||||||
|
{
|
||||||
|
public class MigrationManager
|
||||||
|
{
|
||||||
|
private readonly DeviceManager _deviceManager;
|
||||||
|
|
||||||
|
public MigrationManager(DeviceManager deviceManager)
|
||||||
|
{
|
||||||
|
_deviceManager = deviceManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Migrates old versions of profiles to new versions
|
||||||
|
/// </summary>
|
||||||
|
public void MigrateProfiles()
|
||||||
|
{
|
||||||
|
// 1.8.0.0 - Rename WindowsProfile to GeneralProfile
|
||||||
|
foreach (var keyboardProvider in _deviceManager.KeyboardProviders)
|
||||||
|
{
|
||||||
|
var folder = ProfileProvider.ProfileFolder + "/" + keyboardProvider.Slug + "/WindowsProfile";
|
||||||
|
if (!Directory.Exists(folder))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Get all the profiles
|
||||||
|
var profiles = ProfileProvider.ReadProfiles(keyboardProvider.Slug + "/WindowsProfile");
|
||||||
|
foreach (var profile in profiles)
|
||||||
|
{
|
||||||
|
// Change their GameName and save, effectively moving them to the new folder
|
||||||
|
profile.GameName = "GeneralProfile";
|
||||||
|
ProfileProvider.AddOrUpdate(profile);
|
||||||
|
}
|
||||||
|
// Delete the old profiles
|
||||||
|
Directory.Delete(folder, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -169,6 +169,8 @@ namespace Artemis.Managers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void DisableProcessBoundModule()
|
public void DisableProcessBoundModule()
|
||||||
{
|
{
|
||||||
|
if (ActiveModule == null)
|
||||||
|
return;
|
||||||
if (!ActiveModule.IsBoundToProcess)
|
if (!ActiveModule.IsBoundToProcess)
|
||||||
{
|
{
|
||||||
_logger.Warn("Active module {0} is not process bound but is being disabled as if it is.",
|
_logger.Warn("Active module {0} is not process bound but is being disabled as if it is.",
|
||||||
@ -176,10 +178,11 @@ namespace Artemis.Managers
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetLastModule() == null)
|
var lastModule = GetLastModule();
|
||||||
|
if (lastModule == null || !lastModule.Settings.IsEnabled)
|
||||||
ClearActiveModule();
|
ClearActiveModule();
|
||||||
else
|
else
|
||||||
ChangeActiveModule(GetLastModule());
|
ChangeActiveModule(lastModule);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void RaiseEffectChangedEvent(ModuleChangedEventArgs e)
|
protected virtual void RaiseEffectChangedEvent(ModuleChangedEventArgs e)
|
||||||
|
|||||||
@ -9,7 +9,7 @@ using Ninject.Extensions.Logging;
|
|||||||
|
|
||||||
namespace Artemis.Managers
|
namespace Artemis.Managers
|
||||||
{
|
{
|
||||||
public class ProfileManager
|
public class PreviewManager
|
||||||
{
|
{
|
||||||
private readonly DeviceManager _deviceManager;
|
private readonly DeviceManager _deviceManager;
|
||||||
private readonly GeneralSettings _generalSettings;
|
private readonly GeneralSettings _generalSettings;
|
||||||
@ -17,7 +17,7 @@ namespace Artemis.Managers
|
|||||||
private readonly LoopManager _loopManager;
|
private readonly LoopManager _loopManager;
|
||||||
private readonly ModuleManager _moduleManager;
|
private readonly ModuleManager _moduleManager;
|
||||||
|
|
||||||
public ProfileManager(ILogger logger, ModuleManager moduleManager, DeviceManager deviceManager,
|
public PreviewManager(ILogger logger, ModuleManager moduleManager, DeviceManager deviceManager,
|
||||||
LoopManager loopManager)
|
LoopManager loopManager)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
@ -32,7 +32,7 @@ namespace Artemis.Managers
|
|||||||
profilePreviewTimer.Elapsed += SetupProfilePreview;
|
profilePreviewTimer.Elapsed += SetupProfilePreview;
|
||||||
profilePreviewTimer.Start();
|
profilePreviewTimer.Start();
|
||||||
|
|
||||||
_logger.Info("Intialized ProfileManager");
|
_logger.Info("Intialized PreviewManager");
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ModuleViewModel> PreviewViewModules { get; set; }
|
public List<ModuleViewModel> PreviewViewModules { get; set; }
|
||||||
@ -76,8 +76,13 @@ namespace Artemis.Managers
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
_logger.Debug("Deactivate profile preview");
|
_logger.Debug("Deactivate profile preview");
|
||||||
|
|
||||||
|
// Save the profile the editor was using
|
||||||
|
var activePreview = PreviewViewModules.FirstOrDefault(p => p.IsModuleActive);
|
||||||
|
activePreview?.ProfileEditor?.SaveSelectedProfile();
|
||||||
|
|
||||||
var lastModule = _moduleManager.GetLastModule();
|
var lastModule = _moduleManager.GetLastModule();
|
||||||
if (lastModule != null)
|
if (lastModule != null && lastModule.Settings.IsEnabled)
|
||||||
_moduleManager.ChangeActiveModule(lastModule);
|
_moduleManager.ChangeActiveModule(lastModule);
|
||||||
else
|
else
|
||||||
_moduleManager.ClearActiveModule();
|
_moduleManager.ClearActiveModule();
|
||||||
12
Artemis/Artemis/Models/LayerEditorModel.cs
Normal file
12
Artemis/Artemis/Models/LayerEditorModel.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Artemis.Models
|
||||||
|
{
|
||||||
|
public class LayerEditorModel
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
367
Artemis/Artemis/Models/ProfileEditorModel.cs
Normal file
367
Artemis/Artemis/Models/ProfileEditorModel.cs
Normal file
@ -0,0 +1,367 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using Artemis.DAL;
|
||||||
|
using Artemis.Managers;
|
||||||
|
using Artemis.Modules.Abstract;
|
||||||
|
using Artemis.Profiles;
|
||||||
|
using Artemis.Profiles.Layers.Models;
|
||||||
|
using Artemis.Profiles.Layers.Types.Folder;
|
||||||
|
using Artemis.Properties;
|
||||||
|
using Artemis.Services;
|
||||||
|
using Artemis.Utilities;
|
||||||
|
using Artemis.ViewModels;
|
||||||
|
using Ninject.Parameters;
|
||||||
|
|
||||||
|
namespace Artemis.Models
|
||||||
|
{
|
||||||
|
public class ProfileEditorModel : IDisposable
|
||||||
|
{
|
||||||
|
private readonly DeviceManager _deviceManager;
|
||||||
|
private readonly LuaManager _luaManager;
|
||||||
|
private readonly DialogService _dialogService;
|
||||||
|
private readonly WindowService _windowService;
|
||||||
|
private FileSystemWatcher _watcher;
|
||||||
|
private ModuleModel _luaModule;
|
||||||
|
|
||||||
|
public ProfileEditorModel(WindowService windowService, MetroDialogService dialogService,
|
||||||
|
DeviceManager deviceManager, LuaManager luaManager)
|
||||||
|
{
|
||||||
|
_windowService = windowService;
|
||||||
|
_dialogService = dialogService;
|
||||||
|
_deviceManager = deviceManager;
|
||||||
|
_luaManager = luaManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Layers
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Opens a new LayerEditorView for the given layer
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="layer">The layer to open the view for</param>
|
||||||
|
/// <param name="dataModel">The datamodel to bind the editor to</param>
|
||||||
|
public void EditLayer(LayerModel layer, ModuleDataModel dataModel)
|
||||||
|
{
|
||||||
|
IParameter[] args =
|
||||||
|
{
|
||||||
|
new ConstructorArgument("dataModel", dataModel),
|
||||||
|
new ConstructorArgument("layer", layer)
|
||||||
|
};
|
||||||
|
_windowService.ShowDialog<LayerEditorViewModel>(args);
|
||||||
|
|
||||||
|
// If the layer was a folder, but isn't anymore, assign it's children to it's parent.
|
||||||
|
if (layer.LayerType is FolderType || !layer.Children.Any())
|
||||||
|
return;
|
||||||
|
|
||||||
|
while (layer.Children.Any())
|
||||||
|
{
|
||||||
|
var child = layer.Children[0];
|
||||||
|
layer.Children.Remove(child);
|
||||||
|
if (layer.Parent != null)
|
||||||
|
{
|
||||||
|
layer.Parent.Children.Add(child);
|
||||||
|
layer.Parent.FixOrder();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
layer.Profile.Layers.Add(child);
|
||||||
|
layer.Profile.FixOrder();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes the given layer from the profile
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="layer">The layer to remove</param>
|
||||||
|
/// <param name="profileModel">The profile to remove it from</param>
|
||||||
|
public void RemoveLayer(LayerModel layer, ProfileModel profileModel)
|
||||||
|
{
|
||||||
|
if (layer == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (layer.Parent != null)
|
||||||
|
{
|
||||||
|
var parent = layer.Parent;
|
||||||
|
layer.Parent.Children.Remove(layer);
|
||||||
|
parent.FixOrder();
|
||||||
|
}
|
||||||
|
else if (layer.Profile != null)
|
||||||
|
{
|
||||||
|
var profile = layer.Profile;
|
||||||
|
layer.Profile.Layers.Remove(layer);
|
||||||
|
profile.FixOrder();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extra cleanup in case of a wonky layer that has no parent
|
||||||
|
if (profileModel.Layers.Contains(layer))
|
||||||
|
profileModel.Layers.Remove(layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Profiles
|
||||||
|
|
||||||
|
public async Task<ProfileModel> AddProfile(ModuleModel moduleModel)
|
||||||
|
{
|
||||||
|
if (_deviceManager.ActiveKeyboard == null)
|
||||||
|
{
|
||||||
|
_dialogService.ShowMessageBox("Cannot add profile.",
|
||||||
|
"To add a profile, please select a keyboard in the options menu first.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var name = await GetValidProfileName("Name profile", "Please enter a unique name for your new profile");
|
||||||
|
// User cancelled
|
||||||
|
if (name == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var profile = new ProfileModel
|
||||||
|
{
|
||||||
|
Name = name,
|
||||||
|
KeyboardSlug = _deviceManager.ActiveKeyboard.Slug,
|
||||||
|
Width = _deviceManager.ActiveKeyboard.Width,
|
||||||
|
Height = _deviceManager.ActiveKeyboard.Height,
|
||||||
|
GameName = moduleModel.Name
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!ProfileProvider.IsProfileUnique(profile))
|
||||||
|
{
|
||||||
|
var overwrite = await _dialogService.ShowQuestionMessageBox("Overwrite existing profile",
|
||||||
|
"A profile with this name already exists for this game. Would you like to overwrite it?");
|
||||||
|
if (!overwrite.Value)
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProfileProvider.AddOrUpdate(profile);
|
||||||
|
return profile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task RenameProfile(ProfileModel profileModel)
|
||||||
|
{
|
||||||
|
var name = await GetValidProfileName("Rename profile", "Please enter a unique new profile name");
|
||||||
|
// User cancelled
|
||||||
|
if (name == null)
|
||||||
|
return;
|
||||||
|
var doRename = await MakeProfileUnique(profileModel, name, profileModel.Name);
|
||||||
|
if (!doRename)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ProfileProvider.RenameProfile(profileModel, profileModel.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<ProfileModel> DuplicateProfile(ProfileModel selectedProfile)
|
||||||
|
{
|
||||||
|
var newProfile = GeneralHelpers.Clone(selectedProfile);
|
||||||
|
var name = await GetValidProfileName("Duplicate profile", "Please enter a unique new profile name");
|
||||||
|
// User cancelled
|
||||||
|
if (name == null)
|
||||||
|
return null;
|
||||||
|
var doRename = await MakeProfileUnique(newProfile, name, newProfile.Name);
|
||||||
|
if (!doRename)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// Make sure it's not default, in case of copying a default profile
|
||||||
|
newProfile.IsDefault = false;
|
||||||
|
ProfileProvider.AddOrUpdate(newProfile);
|
||||||
|
|
||||||
|
return newProfile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> DeleteProfile(ProfileModel selectedProfile, ModuleModel moduleModel)
|
||||||
|
{
|
||||||
|
var confirm = await _dialogService.ShowQuestionMessageBox("Delete profile",
|
||||||
|
$"Are you sure you want to delete the profile named: {selectedProfile.Name}?\n\n" +
|
||||||
|
"This cannot be undone.");
|
||||||
|
if (!confirm.Value)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var defaultProfile = ProfileProvider.GetProfile(_deviceManager.ActiveKeyboard, moduleModel, "Default");
|
||||||
|
var deleteProfile = selectedProfile;
|
||||||
|
|
||||||
|
moduleModel.ChangeProfile(defaultProfile);
|
||||||
|
ProfileProvider.DeleteProfile(deleteProfile);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<ProfileModel> ImportProfile(ModuleModel moduleModel)
|
||||||
|
{
|
||||||
|
var dialog = new OpenFileDialog {Filter = "Artemis profile (*.json)|*.json"};
|
||||||
|
var result = dialog.ShowDialog();
|
||||||
|
if (result != DialogResult.OK)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var profileModel = ProfileProvider.LoadProfileIfValid(dialog.FileName);
|
||||||
|
if (profileModel == null)
|
||||||
|
{
|
||||||
|
_dialogService.ShowErrorMessageBox("Oh noes, the profile you provided is invalid. " +
|
||||||
|
"If this keeps happening, please make an issue on GitHub and provide the profile.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify the game
|
||||||
|
if (profileModel.GameName != moduleModel.Name)
|
||||||
|
{
|
||||||
|
_dialogService.ShowErrorMessageBox(
|
||||||
|
$"Oh oops! This profile is ment for {profileModel.GameName}, not {moduleModel.Name} :c");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify the keyboard
|
||||||
|
var deviceManager = _deviceManager;
|
||||||
|
if (profileModel.KeyboardSlug != deviceManager.ActiveKeyboard.Slug)
|
||||||
|
{
|
||||||
|
var adjustKeyboard = await _dialogService.ShowQuestionMessageBox("Profile not made for this keyboard",
|
||||||
|
$"Watch out, this profile wasn't ment for this keyboard, but for the {profileModel.KeyboardSlug}. " +
|
||||||
|
"You can still import it but you'll probably have to do some adjusting\n\n" +
|
||||||
|
"Continue?");
|
||||||
|
if (!adjustKeyboard.Value)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// Resize layers that are on the full keyboard width
|
||||||
|
profileModel.ResizeLayers(deviceManager.ActiveKeyboard);
|
||||||
|
// Put layers back into the canvas if they fell outside it
|
||||||
|
profileModel.FixBoundaries(deviceManager.ActiveKeyboard.KeyboardRectangle(1));
|
||||||
|
|
||||||
|
// Setup profile metadata to match the new keyboard
|
||||||
|
profileModel.KeyboardSlug = deviceManager.ActiveKeyboard.Slug;
|
||||||
|
profileModel.Width = deviceManager.ActiveKeyboard.Width;
|
||||||
|
profileModel.Height = deviceManager.ActiveKeyboard.Height;
|
||||||
|
}
|
||||||
|
|
||||||
|
var name = await GetValidProfileName("Rename profile", "Please enter a unique new profile name");
|
||||||
|
// User cancelled
|
||||||
|
if (name == null)
|
||||||
|
return null;
|
||||||
|
var doRename = await MakeProfileUnique(profileModel, name, profileModel.Name);
|
||||||
|
if (!doRename)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
profileModel.IsDefault = false;
|
||||||
|
ProfileProvider.AddOrUpdate(profileModel);
|
||||||
|
return profileModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ChangeProfileByName(ModuleModel moduleModel, string profileName)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(profileName))
|
||||||
|
profileName = "Default";
|
||||||
|
|
||||||
|
moduleModel.ChangeProfile(ProfileProvider.GetProfile(_deviceManager.ActiveKeyboard, moduleModel, profileName));
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<string> GetValidProfileName(string title, string text)
|
||||||
|
{
|
||||||
|
var name = await _dialogService.ShowInputDialog(title, text);
|
||||||
|
|
||||||
|
// Null when the user cancelled
|
||||||
|
if (name == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (name.Length >= 2)
|
||||||
|
return name;
|
||||||
|
|
||||||
|
_dialogService.ShowMessageBox("Invalid profile name",
|
||||||
|
"Please provide a valid profile name that's longer than 2 symbols");
|
||||||
|
|
||||||
|
return await GetValidProfileName(title, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<bool> MakeProfileUnique(ProfileModel profileModel, string name, string oldName)
|
||||||
|
{
|
||||||
|
profileModel.Name = name;
|
||||||
|
if (ProfileProvider.IsProfileUnique(profileModel))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
name = await GetValidProfileName("Rename profile", "Please enter a unique new profile name");
|
||||||
|
if (name != null)
|
||||||
|
return await MakeProfileUnique(profileModel, name, oldName);
|
||||||
|
|
||||||
|
// If cancelled, restore old name and stop
|
||||||
|
profileModel.Name = oldName;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region LUA
|
||||||
|
|
||||||
|
public void OpenLuaEditor(ModuleModel moduleModel)
|
||||||
|
{
|
||||||
|
// Clean up old environment
|
||||||
|
DisposeLuaWatcher();
|
||||||
|
|
||||||
|
// Create a temp file
|
||||||
|
var fileName = Guid.NewGuid() + ".lua";
|
||||||
|
var file = File.Create(Path.GetTempPath() + fileName);
|
||||||
|
file.Dispose();
|
||||||
|
|
||||||
|
// Add instructions to LUA script if it's a new file
|
||||||
|
if (string.IsNullOrEmpty(moduleModel.ProfileModel.LuaScript))
|
||||||
|
moduleModel.ProfileModel.LuaScript = Encoding.UTF8.GetString(Resources.lua_placeholder);
|
||||||
|
File.WriteAllText(Path.GetTempPath() + fileName, moduleModel.ProfileModel.LuaScript);
|
||||||
|
|
||||||
|
// Watch the file for changes
|
||||||
|
_luaModule = moduleModel;
|
||||||
|
_watcher = new FileSystemWatcher(Path.GetTempPath(), fileName);
|
||||||
|
_watcher.Changed += LuaFileChanged;
|
||||||
|
_watcher.EnableRaisingEvents = true;
|
||||||
|
_watcher.Path = Path.GetTempPath();
|
||||||
|
_watcher.Filter = fileName;
|
||||||
|
|
||||||
|
// Open the temp file with the default editor
|
||||||
|
System.Diagnostics.Process.Start(Path.GetTempPath() + fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LuaFileChanged(object sender, FileSystemEventArgs args)
|
||||||
|
{
|
||||||
|
if (_luaModule == null)
|
||||||
|
{
|
||||||
|
DisposeLuaWatcher();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.ChangeType != WatcherChangeTypes.Changed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
lock (_luaModule)
|
||||||
|
{
|
||||||
|
using (var fs = new FileStream(args.FullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||||
|
{
|
||||||
|
using (var sr = new StreamReader(fs))
|
||||||
|
{
|
||||||
|
_luaModule.ProfileModel.LuaScript = sr.ReadToEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ProfileProvider.AddOrUpdate(_luaModule.ProfileModel);
|
||||||
|
_luaManager.SetupLua(_luaModule.ProfileModel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DisposeLuaWatcher()
|
||||||
|
{
|
||||||
|
if (_watcher == null) return;
|
||||||
|
_watcher.Changed -= LuaFileChanged;
|
||||||
|
_watcher.Dispose();
|
||||||
|
_watcher = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
DisposeLuaWatcher();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Rendering
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -79,15 +79,17 @@ namespace Artemis.Modules.Abstract
|
|||||||
public List<LayerModel> PreviewLayers { get; set; }
|
public List<LayerModel> PreviewLayers { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The process the module is bound to
|
/// The processes the module is bound to
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string ProcessName { get; protected set; }
|
public List<string> ProcessNames { get; protected set; } = new List<string>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The currently active profile of the module
|
/// The currently active profile of the module
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ProfileModel ProfileModel { get; protected set; }
|
public ProfileModel ProfileModel { get; protected set; }
|
||||||
|
|
||||||
|
public bool IsGeneral => !IsOverlay && !IsBoundToProcess;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Base methods
|
#region Base methods
|
||||||
@ -98,7 +100,13 @@ namespace Artemis.Modules.Abstract
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
ProfileModel = profileModel;
|
ProfileModel = profileModel;
|
||||||
|
if (!IsOverlay)
|
||||||
ProfileModel?.Activate(_luaManager);
|
ProfileModel?.Activate(_luaManager);
|
||||||
|
if (ProfileModel != null)
|
||||||
|
{
|
||||||
|
Settings.LastProfile = ProfileModel.Name;
|
||||||
|
Settings.Save();
|
||||||
|
}
|
||||||
|
|
||||||
RaiseProfileChangedEvent(new ProfileChangedEventArgs(ProfileModel));
|
RaiseProfileChangedEvent(new ProfileChangedEventArgs(ProfileModel));
|
||||||
}
|
}
|
||||||
@ -157,26 +165,38 @@ namespace Artemis.Modules.Abstract
|
|||||||
ProfileModel?.DrawLayers(g, layers, DrawType.Keyboard, DataModel, keyboardRect, preview);
|
ProfileModel?.DrawLayers(g, layers, DrawType.Keyboard, DataModel, keyboardRect, preview);
|
||||||
}
|
}
|
||||||
// Render mice layer-by-layer
|
// Render mice layer-by-layer
|
||||||
var devRec = new Rect(0, 0, 40, 40);
|
var devRec = new Rect(0, 0, 10, 10);
|
||||||
|
if (frame.MouseBitmap != null)
|
||||||
|
{
|
||||||
using (var g = Graphics.FromImage(frame.MouseBitmap))
|
using (var g = Graphics.FromImage(frame.MouseBitmap))
|
||||||
{
|
{
|
||||||
ProfileModel?.DrawLayers(g, layers, DrawType.Mouse, DataModel, devRec, preview);
|
ProfileModel?.DrawLayers(g, layers, DrawType.Mouse, DataModel, devRec, preview);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Render headsets layer-by-layer
|
// Render headsets layer-by-layer
|
||||||
|
if (frame.HeadsetBitmap != null)
|
||||||
|
{
|
||||||
using (var g = Graphics.FromImage(frame.HeadsetBitmap))
|
using (var g = Graphics.FromImage(frame.HeadsetBitmap))
|
||||||
{
|
{
|
||||||
ProfileModel?.DrawLayers(g, layers, DrawType.Headset, DataModel, devRec, preview);
|
ProfileModel?.DrawLayers(g, layers, DrawType.Headset, DataModel, devRec, preview);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Render generic devices layer-by-layer
|
// Render generic devices layer-by-layer
|
||||||
|
if (frame.GenericBitmap != null)
|
||||||
|
{
|
||||||
using (var g = Graphics.FromImage(frame.GenericBitmap))
|
using (var g = Graphics.FromImage(frame.GenericBitmap))
|
||||||
{
|
{
|
||||||
ProfileModel?.DrawLayers(g, layers, DrawType.Generic, DataModel, devRec, preview);
|
ProfileModel?.DrawLayers(g, layers, DrawType.Generic, DataModel, devRec, preview);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Render mousemats layer-by-layer
|
// Render mousemats layer-by-layer
|
||||||
|
if (frame.MousematBitmap != null)
|
||||||
|
{
|
||||||
using (var g = Graphics.FromImage(frame.MousematBitmap))
|
using (var g = Graphics.FromImage(frame.MousematBitmap))
|
||||||
{
|
{
|
||||||
ProfileModel?.DrawLayers(g, layers, DrawType.Mousemat, DataModel, devRec, preview);
|
ProfileModel?.DrawLayers(g, layers, DrawType.Mousemat, DataModel, devRec, preview);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Trace debugging
|
// Trace debugging
|
||||||
if (DateTime.Now.AddSeconds(-2) <= _lastTrace || Logger == null)
|
if (DateTime.Now.AddSeconds(-2) <= _lastTrace || Logger == null)
|
||||||
@ -185,6 +205,10 @@ namespace Artemis.Modules.Abstract
|
|||||||
_lastTrace = DateTime.Now;
|
_lastTrace = DateTime.Now;
|
||||||
var dmJson = JsonConvert.SerializeObject(DataModel, Formatting.Indented);
|
var dmJson = JsonConvert.SerializeObject(DataModel, Formatting.Indented);
|
||||||
Logger.Trace("Effect datamodel as JSON: \r\n{0}", dmJson);
|
Logger.Trace("Effect datamodel as JSON: \r\n{0}", dmJson);
|
||||||
|
|
||||||
|
if (layers == null)
|
||||||
|
return;
|
||||||
|
|
||||||
Logger.Trace("Effect {0} has to render {1} layers", Name, layers.Count);
|
Logger.Trace("Effect {0} has to render {1} layers", Name, layers.Count);
|
||||||
foreach (var renderLayer in layers)
|
foreach (var renderLayer in layers)
|
||||||
Logger.Trace("- Layer name: {0}, layer type: {1}", renderLayer.Name, renderLayer.LayerType);
|
Logger.Trace("- Layer name: {0}, layer type: {1}", renderLayer.Name, renderLayer.LayerType);
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
using Artemis.Events;
|
using Artemis.DAL;
|
||||||
|
using Artemis.Events;
|
||||||
using Artemis.Managers;
|
using Artemis.Managers;
|
||||||
using Artemis.Services;
|
using Artemis.Services;
|
||||||
using Artemis.Settings;
|
using Artemis.Settings;
|
||||||
using Artemis.ViewModels.Profiles;
|
using Artemis.ViewModels;
|
||||||
using Caliburn.Micro;
|
using Caliburn.Micro;
|
||||||
using Ninject;
|
using Ninject;
|
||||||
using Ninject.Extensions.Logging;
|
using Ninject.Extensions.Logging;
|
||||||
@ -12,24 +13,33 @@ namespace Artemis.Modules.Abstract
|
|||||||
{
|
{
|
||||||
public abstract class ModuleViewModel : Screen
|
public abstract class ModuleViewModel : Screen
|
||||||
{
|
{
|
||||||
private readonly ModuleManager _moduleManager;
|
|
||||||
private readonly MainManager _mainManager;
|
private readonly MainManager _mainManager;
|
||||||
private readonly IKernel _kernel;
|
private readonly ModuleManager _moduleManager;
|
||||||
|
private readonly GeneralSettings _generalSettings;
|
||||||
private ModuleSettings _settings;
|
private ModuleSettings _settings;
|
||||||
private GeneralSettings _generalSettings;
|
|
||||||
|
|
||||||
public ModuleViewModel(MainManager mainManager, ModuleModel moduleModel, IKernel kernel)
|
public ModuleViewModel(MainManager mainManager, ModuleModel moduleModel, IKernel kernel)
|
||||||
{
|
{
|
||||||
_mainManager = mainManager;
|
_mainManager = mainManager;
|
||||||
_kernel = kernel;
|
|
||||||
_moduleManager = mainManager.ModuleManager;
|
_moduleManager = mainManager.ModuleManager;
|
||||||
_generalSettings = DAL.SettingsProvider.Load<GeneralSettings>();
|
_generalSettings = SettingsProvider.Load<GeneralSettings>();
|
||||||
ModuleModel = moduleModel;
|
ModuleModel = moduleModel;
|
||||||
Settings = moduleModel.Settings;
|
Settings = moduleModel.Settings;
|
||||||
|
|
||||||
|
|
||||||
_mainManager.EnabledChanged += MainManagerOnEnabledChanged;
|
_mainManager.EnabledChanged += MainManagerOnEnabledChanged;
|
||||||
_moduleManager.EffectChanged += ModuleManagerOnModuleChanged;
|
_moduleManager.EffectChanged += ModuleManagerOnModuleChanged;
|
||||||
|
|
||||||
|
// ReSharper disable once VirtualMemberCallInConstructor
|
||||||
|
if (!UsesProfileEditor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
IParameter[] args =
|
||||||
|
{
|
||||||
|
new ConstructorArgument("mainManager", _mainManager),
|
||||||
|
new ConstructorArgument("moduleModel", ModuleModel),
|
||||||
|
new ConstructorArgument("lastProfile", Settings.LastProfile)
|
||||||
|
};
|
||||||
|
ProfileEditor = kernel.Get<ProfileEditorViewModel>(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProfileEditorViewModel ProfileEditor { get; set; }
|
public ProfileEditorViewModel ProfileEditor { get; set; }
|
||||||
@ -58,7 +68,7 @@ namespace Artemis.Modules.Abstract
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (ModuleModel.IsBoundToProcess || ModuleModel.IsBoundToProcess)
|
if (!ModuleModel.IsGeneral)
|
||||||
return Settings.IsEnabled;
|
return Settings.IsEnabled;
|
||||||
return _generalSettings.LastModule == ModuleModel.Name;
|
return _generalSettings.LastModule == ModuleModel.Name;
|
||||||
}
|
}
|
||||||
@ -81,7 +91,7 @@ namespace Artemis.Modules.Abstract
|
|||||||
|
|
||||||
private void UpdatedEnabledSetting()
|
private void UpdatedEnabledSetting()
|
||||||
{
|
{
|
||||||
if (ModuleModel.IsBoundToProcess || ModuleModel.IsOverlay)
|
if (!ModuleModel.IsGeneral || (_moduleManager.ActiveModule != null && !_moduleManager.ActiveModule.IsGeneral || Settings.IsEnabled == IsModuleActive))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Settings.IsEnabled = IsModuleActive;
|
Settings.IsEnabled = IsModuleActive;
|
||||||
@ -96,7 +106,7 @@ namespace Artemis.Modules.Abstract
|
|||||||
NotifyOfPropertyChange(() => Settings);
|
NotifyOfPropertyChange(() => Settings);
|
||||||
|
|
||||||
// On process-bound modules, only set the module model
|
// On process-bound modules, only set the module model
|
||||||
if (ModuleModel.IsBoundToProcess || ModuleModel.IsOverlay)
|
if (!ModuleModel.IsGeneral)
|
||||||
{
|
{
|
||||||
NotifyOfPropertyChange(() => IsModuleActive);
|
NotifyOfPropertyChange(() => IsModuleActive);
|
||||||
NotifyOfPropertyChange(() => IsModuleEnabled);
|
NotifyOfPropertyChange(() => IsModuleEnabled);
|
||||||
@ -142,24 +152,13 @@ namespace Artemis.Modules.Abstract
|
|||||||
protected override void OnActivate()
|
protected override void OnActivate()
|
||||||
{
|
{
|
||||||
base.OnActivate();
|
base.OnActivate();
|
||||||
|
ProfileEditor?.OnActivate();
|
||||||
if (!UsesProfileEditor)
|
|
||||||
return;
|
|
||||||
|
|
||||||
IParameter[] args =
|
|
||||||
{
|
|
||||||
new ConstructorArgument("mainManager", _mainManager),
|
|
||||||
new ConstructorArgument("moduleModel", ModuleModel),
|
|
||||||
new ConstructorArgument("lastProfile", Settings.LastProfile)
|
|
||||||
};
|
|
||||||
ProfileEditor = _kernel.Get<ProfileEditorViewModel>(args);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnDeactivate(bool close)
|
protected override void OnDeactivate(bool close)
|
||||||
{
|
{
|
||||||
base.OnDeactivate(close);
|
base.OnDeactivate(close);
|
||||||
ProfileEditor?.Dispose();
|
ProfileEditor?.OnDeactivate(close);
|
||||||
ProfileEditor = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -28,7 +28,7 @@ namespace Artemis.Modules.Games.CounterStrike
|
|||||||
|
|
||||||
Settings = SettingsProvider.Load<CounterStrikeSettings>();
|
Settings = SettingsProvider.Load<CounterStrikeSettings>();
|
||||||
DataModel = new CounterStrikeDataModel();
|
DataModel = new CounterStrikeDataModel();
|
||||||
ProcessName = "csgo";
|
ProcessNames.Add("csgo");
|
||||||
|
|
||||||
FindGameDir();
|
FindGameDir();
|
||||||
PlaceConfigFile();
|
PlaceConfigFile();
|
||||||
|
|||||||
@ -48,7 +48,7 @@
|
|||||||
cal:Message.Attach="[Event LostFocus] = [Action PlaceConfigFile]" />
|
cal:Message.Attach="[Event LostFocus] = [Action PlaceConfigFile]" />
|
||||||
<Button x:Name="BrowseDirectory" Content="..." RenderTransformOrigin="-0.039,-0.944"
|
<Button x:Name="BrowseDirectory" Content="..." RenderTransformOrigin="-0.039,-0.944"
|
||||||
HorizontalAlignment="Right" Width="25"
|
HorizontalAlignment="Right" Width="25"
|
||||||
Style="{DynamicResource SquareButtonStyle}" Height="26" Margin="0,-2,0,0" />
|
Style="{DynamicResource SquareButtonStyle}" Height="26" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
|
|||||||
@ -24,7 +24,7 @@ namespace Artemis.Modules.Games.Dota2
|
|||||||
|
|
||||||
Settings = SettingsProvider.Load<Dota2Settings>();
|
Settings = SettingsProvider.Load<Dota2Settings>();
|
||||||
DataModel = new Dota2DataModel();
|
DataModel = new Dota2DataModel();
|
||||||
ProcessName = "dota2";
|
ProcessNames.Add("dota2");
|
||||||
|
|
||||||
FindGameDir();
|
FindGameDir();
|
||||||
PlaceConfigFile();
|
PlaceConfigFile();
|
||||||
|
|||||||
@ -47,7 +47,7 @@
|
|||||||
cal:Message.Attach="[Event LostFocus] = [Action PlaceConfigFile]" />
|
cal:Message.Attach="[Event LostFocus] = [Action PlaceConfigFile]" />
|
||||||
<Button x:Name="BrowseDirectory" Content="..." RenderTransformOrigin="-0.039,-0.944"
|
<Button x:Name="BrowseDirectory" Content="..." RenderTransformOrigin="-0.039,-0.944"
|
||||||
HorizontalAlignment="Right" Width="25"
|
HorizontalAlignment="Right" Width="25"
|
||||||
Style="{DynamicResource SquareButtonStyle}" Height="26" Margin="0,-2,0,0" />
|
Style="{DynamicResource SquareButtonStyle}" Height="26" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
|
|||||||
@ -17,10 +17,17 @@ namespace Artemis.Modules.Games.EurotruckSimulator2
|
|||||||
UserData.RegisterType<IEts2Truck>();
|
UserData.RegisterType<IEts2Truck>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TruckSimulatorGameName GameName { get; set; }
|
||||||
public IEts2Game Game { get; set; }
|
public IEts2Game Game { get; set; }
|
||||||
public IEts2Job Job { get; set; }
|
public IEts2Job Job { get; set; }
|
||||||
public IEts2Navigation Navigation { get; set; }
|
public IEts2Navigation Navigation { get; set; }
|
||||||
public IEts2Trailer Trailer { get; set; }
|
public IEts2Trailer Trailer { get; set; }
|
||||||
public IEts2Truck Truck { get; set; }
|
public IEts2Truck Truck { get; set; }
|
||||||
|
|
||||||
|
public enum TruckSimulatorGameName
|
||||||
|
{
|
||||||
|
EuroTruckSimulator2,
|
||||||
|
AmericanTruckSimulator
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -7,6 +7,8 @@ using Artemis.Modules.Games.EurotruckSimulator2.Data;
|
|||||||
using Artemis.Properties;
|
using Artemis.Properties;
|
||||||
using Artemis.Services;
|
using Artemis.Services;
|
||||||
using Artemis.Utilities;
|
using Artemis.Utilities;
|
||||||
|
using Artemis.Utilities.Memory;
|
||||||
|
using static Artemis.Modules.Games.EurotruckSimulator2.EurotruckSimulator2DataModel;
|
||||||
|
|
||||||
namespace Artemis.Modules.Games.EurotruckSimulator2
|
namespace Artemis.Modules.Games.EurotruckSimulator2
|
||||||
{
|
{
|
||||||
@ -22,9 +24,11 @@ namespace Artemis.Modules.Games.EurotruckSimulator2
|
|||||||
|
|
||||||
Settings = SettingsProvider.Load<EurotruckSimulator2Settings>();
|
Settings = SettingsProvider.Load<EurotruckSimulator2Settings>();
|
||||||
DataModel = new EurotruckSimulator2DataModel();
|
DataModel = new EurotruckSimulator2DataModel();
|
||||||
ProcessName = "eurotrucks2";
|
ProcessNames.Add("eurotrucks2");
|
||||||
|
ProcessNames.Add("amtrucks");
|
||||||
|
|
||||||
FindGameDir();
|
FindEts2GameDir();
|
||||||
|
FindAtsGameDir();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Name => "EurotruckSimulator2";
|
public override string Name => "EurotruckSimulator2";
|
||||||
@ -33,9 +37,18 @@ namespace Artemis.Modules.Games.EurotruckSimulator2
|
|||||||
|
|
||||||
public override void Update()
|
public override void Update()
|
||||||
{
|
{
|
||||||
|
var etsProcess = MemoryHelpers.GetProcessIfRunning("eurotrucks2");
|
||||||
|
var atsProcess = MemoryHelpers.GetProcessIfRunning("amtrucks");
|
||||||
|
if (etsProcess == null && atsProcess == null)
|
||||||
|
return;
|
||||||
|
|
||||||
var dataModel = (EurotruckSimulator2DataModel) DataModel;
|
var dataModel = (EurotruckSimulator2DataModel) DataModel;
|
||||||
var telemetryData = Ets2TelemetryDataReader.Instance.Read();
|
var telemetryData = Ets2TelemetryDataReader.Instance.Read();
|
||||||
|
|
||||||
|
dataModel.GameName = etsProcess != null
|
||||||
|
? TruckSimulatorGameName.EuroTruckSimulator2
|
||||||
|
: TruckSimulatorGameName.AmericanTruckSimulator;
|
||||||
|
|
||||||
dataModel.Game = telemetryData.Game;
|
dataModel.Game = telemetryData.Game;
|
||||||
dataModel.Job = telemetryData.Job;
|
dataModel.Job = telemetryData.Job;
|
||||||
dataModel.Navigation = telemetryData.Navigation;
|
dataModel.Navigation = telemetryData.Navigation;
|
||||||
@ -43,7 +56,7 @@ namespace Artemis.Modules.Games.EurotruckSimulator2
|
|||||||
dataModel.Truck = telemetryData.Truck;
|
dataModel.Truck = telemetryData.Truck;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void FindGameDir()
|
public void FindEts2GameDir()
|
||||||
{
|
{
|
||||||
// Demo is also supported but resides in a different directory, the full game can also be 64-bits
|
// 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") ??
|
var dir = GeneralHelpers.FindSteamGame(@"\Euro Truck Simulator 2\bin\win_x64\eurotrucks2.exe") ??
|
||||||
@ -53,19 +66,34 @@ namespace Artemis.Modules.Games.EurotruckSimulator2
|
|||||||
if (string.IsNullOrEmpty(dir))
|
if (string.IsNullOrEmpty(dir))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
((EurotruckSimulator2Settings) Settings).GameDirectory = dir;
|
((EurotruckSimulator2Settings) Settings).Ets2GameDirectory = dir;
|
||||||
Settings.Save();
|
Settings.Save();
|
||||||
|
|
||||||
if (!File.Exists(dir + "/plugins/ets2-telemetry-server.dll"))
|
if (!File.Exists(dir + "/plugins/ets2-telemetry-server.dll"))
|
||||||
PlacePlugin();
|
PlaceTruckSimulatorPlugin(dir, "eurotrucks2.exe");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PlacePlugin()
|
public void FindAtsGameDir()
|
||||||
{
|
{
|
||||||
if (((EurotruckSimulator2Settings) Settings).GameDirectory == string.Empty)
|
// Demo is also supported but resides in a different directory, the full game can also be 32-bits (I think)
|
||||||
|
var dir = GeneralHelpers.FindSteamGame(@"\American Truck Simulator\bin\win_x64\amtrucks.exe") ??
|
||||||
|
GeneralHelpers.FindSteamGame(@"\American Truck Simulator\bin\win_x86\amtrucks.exe") ??
|
||||||
|
GeneralHelpers.FindSteamGame(@"\American Truck Simulator Demo\bin\win_x64\amtrucks.exe");
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(dir))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var path = ((EurotruckSimulator2Settings) Settings).GameDirectory;
|
((EurotruckSimulator2Settings) Settings).AtsGameDirectory = dir;
|
||||||
|
Settings.Save();
|
||||||
|
|
||||||
|
if (!File.Exists(dir + "/plugins/ets2-telemetry-server.dll"))
|
||||||
|
PlaceTruckSimulatorPlugin(dir, "amtrucks.exe");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PlaceTruckSimulatorPlugin(string path, string game)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(path))
|
||||||
|
return;
|
||||||
|
|
||||||
// Ensure the selected directory exists
|
// Ensure the selected directory exists
|
||||||
if (!Directory.Exists(path))
|
if (!Directory.Exists(path))
|
||||||
@ -73,11 +101,15 @@ namespace Artemis.Modules.Games.EurotruckSimulator2
|
|||||||
_dialogService.ShowErrorMessageBox($"Directory '{path}' not found.");
|
_dialogService.ShowErrorMessageBox($"Directory '{path}' not found.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Ensure it's the ETS2 directory by looking for the executable
|
// Ensure it's the proper directory by looking for the executable
|
||||||
if (!File.Exists(path + "/eurotrucks2.exe"))
|
if (!File.Exists(path + "/" + game))
|
||||||
{
|
{
|
||||||
|
if (game == "eurotrucks2.exe")
|
||||||
_dialogService.ShowErrorMessageBox("Please select a valid Eurotruck Simulator 2 directory\n\n" +
|
_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");
|
@"By default ETS2 is in \SteamApps\common\Euro Truck Simulator 2\bin\win_x64");
|
||||||
|
else
|
||||||
|
_dialogService.ShowErrorMessageBox("Please select a valid American Truck Simulator directory\n\n" +
|
||||||
|
@"By default ATS is in \SteamApps\common\American Truck Simulator\bin\win_x64");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,11 +124,11 @@ namespace Artemis.Modules.Games.EurotruckSimulator2
|
|||||||
else
|
else
|
||||||
File.WriteAllBytes(path + "/plugins/ets2-telemetry-server.dll", Resources.ets2_telemetry_server_x86);
|
File.WriteAllBytes(path + "/plugins/ets2-telemetry-server.dll", Resources.ets2_telemetry_server_x86);
|
||||||
|
|
||||||
Logger?.Debug("Installed ETS2 plugin in {0}", path);
|
Logger?.Debug("Installed Truck Simulator plugin in {0}", path);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Logger?.Error(e, "Failed to install ETS2 plugin in {0}", path);
|
Logger?.Error(e, "Failed to install Truck Simulator plugin in {0}", path);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ namespace Artemis.Modules.Games.EurotruckSimulator2
|
|||||||
{
|
{
|
||||||
public class EurotruckSimulator2Settings : ModuleSettings
|
public class EurotruckSimulator2Settings : ModuleSettings
|
||||||
{
|
{
|
||||||
public string GameDirectory { get; set; }
|
public string Ets2GameDirectory { get; set; }
|
||||||
|
public string AtsGameDirectory { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -17,6 +17,7 @@
|
|||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="*" />
|
<RowDefinition Height="*" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
@ -39,7 +40,7 @@
|
|||||||
<TextBlock Grid.Row="1" Grid.Column="0" VerticalAlignment="Bottom"
|
<TextBlock Grid.Row="1" Grid.Column="0" VerticalAlignment="Bottom"
|
||||||
TextWrapping="Wrap" HorizontalAlignment="Left" FontFamily="Segoe UI Semibold"
|
TextWrapping="Wrap" HorizontalAlignment="Left" FontFamily="Segoe UI Semibold"
|
||||||
TextAlignment="Justify" Margin="5,0,0,10">
|
TextAlignment="Justify" Margin="5,0,0,10">
|
||||||
The Euro Truck Simulator 2 module uses code from the
|
The Truck Simulator module uses code from the
|
||||||
<Hyperlink RequestNavigate="Hyperlink_RequestNavigate"
|
<Hyperlink RequestNavigate="Hyperlink_RequestNavigate"
|
||||||
NavigateUri="https://github.com/Funbit/ets2-telemetry-server">
|
NavigateUri="https://github.com/Funbit/ets2-telemetry-server">
|
||||||
ETS2 Telemetry Web Server
|
ETS2 Telemetry Web Server
|
||||||
@ -56,26 +57,41 @@
|
|||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<StackPanel Grid.Row="2"
|
<Grid Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2">
|
||||||
Grid.Column="0"
|
<!-- ETS2 dir -->
|
||||||
Grid.ColumnSpan="2" Margin="0,0,1,0">
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition />
|
||||||
<Label FontSize="20" HorizontalAlignment="Left" Content="Euro Truck Simulator 2 directory" />
|
<ColumnDefinition />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<StackPanel Margin="0,0,1,0" Grid.Column="0">
|
||||||
|
<Label FontSize="16" HorizontalAlignment="Left" Content="Euro Truck Simulator 2 directory" />
|
||||||
<Grid>
|
<Grid>
|
||||||
<TextBox x:Name="GameDirectory" Height="23" TextWrapping="Wrap" Margin="5,0,30,0"
|
<TextBox x:Name="Ets2GameDirectory" Height="23" TextWrapping="Wrap" Margin="5,0,30,0"
|
||||||
Text="{Binding Path=Settings.GameDirectory, Mode=TwoWay}"
|
Text="{Binding Path=Settings.Ets2GameDirectory, Mode=TwoWay}"
|
||||||
cal:Message.Attach="[Event LostFocus] = [Action PlacePlugin]" />
|
cal:Message.Attach="[Event LostFocus] = [Action Ets2PlacePlugin]" />
|
||||||
<Button x:Name="BrowseDirectory" Content="..." RenderTransformOrigin="-0.039,-0.944"
|
<Button x:Name="Ets2BrowseDirectory" Content="..." RenderTransformOrigin="-0.039,-0.944"
|
||||||
HorizontalAlignment="Right" Width="25"
|
HorizontalAlignment="Right" Width="25"
|
||||||
Style="{DynamicResource SquareButtonStyle}" Height="26" Margin="0,-2,0,0" />
|
Style="{DynamicResource SquareButtonStyle}" Height="26" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
<!-- ATS dir -->
|
||||||
|
<StackPanel Margin="0,0,1,0" Grid.Column="1">
|
||||||
|
<Label FontSize="16" HorizontalAlignment="Left" Content="American Truck Simulator directory" />
|
||||||
|
<Grid>
|
||||||
|
<TextBox x:Name="AtsGameDirectory" Height="23" TextWrapping="Wrap" Margin="5,0,30,0"
|
||||||
|
Text="{Binding Path=Settings.AtsGameDirectory, Mode=TwoWay}"
|
||||||
|
cal:Message.Attach="[Event LostFocus] = [Action AtsPlacePlugin]" />
|
||||||
|
<Button x:Name="AtsBrowseDirectory" Content="..." RenderTransformOrigin="-0.039,-0.944"
|
||||||
|
HorizontalAlignment="Right" Width="25"
|
||||||
|
Style="{DynamicResource SquareButtonStyle}" Height="26" />
|
||||||
|
</Grid>
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
<!-- Profile editor -->
|
<!-- Profile editor -->
|
||||||
<ContentControl Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" x:Name="ProfileEditor" Margin="0,0,-20,0" />
|
<ContentControl Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="2" x:Name="ProfileEditor" Margin="0,0,-20,0" />
|
||||||
|
|
||||||
<!-- Buttons -->
|
<!-- Buttons -->
|
||||||
<StackPanel Grid.Column="0" Grid.Row="4" Orientation="Horizontal" VerticalAlignment="Bottom">
|
<StackPanel Grid.Column="0" Grid.Row="5" Orientation="Horizontal" VerticalAlignment="Bottom">
|
||||||
<Button x:Name="ResetSettings" Content="Reset effect" VerticalAlignment="Top" Width="100"
|
<Button x:Name="ResetSettings" Content="Reset effect" VerticalAlignment="Top" Width="100"
|
||||||
Style="{DynamicResource SquareButtonStyle}" />
|
Style="{DynamicResource SquareButtonStyle}" />
|
||||||
<Button x:Name="SaveSettings" Content="Save changes" VerticalAlignment="Top" Width="100"
|
<Button x:Name="SaveSettings" Content="Save changes" VerticalAlignment="Top" Width="100"
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
using System.IO;
|
using System.Windows.Forms;
|
||||||
using System.Windows.Forms;
|
|
||||||
using Artemis.Managers;
|
using Artemis.Managers;
|
||||||
using Artemis.Modules.Abstract;
|
using Artemis.Modules.Abstract;
|
||||||
using Ninject;
|
using Ninject;
|
||||||
@ -12,24 +11,53 @@ namespace Artemis.Modules.Games.EurotruckSimulator2
|
|||||||
[Named(nameof(EurotruckSimulator2Model))] ModuleModel moduleModel,
|
[Named(nameof(EurotruckSimulator2Model))] ModuleModel moduleModel,
|
||||||
IKernel kernel) : base(mainManager, moduleModel, kernel)
|
IKernel kernel) : base(mainManager, moduleModel, kernel)
|
||||||
{
|
{
|
||||||
DisplayName = "ETS 2";
|
DisplayName = "Truck Simulator";
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool UsesProfileEditor => true;
|
public override bool UsesProfileEditor => true;
|
||||||
public new EurotruckSimulator2Settings Settings { get; set; }
|
|
||||||
|
|
||||||
public void BrowseDirectory()
|
public void Ets2BrowseDirectory()
|
||||||
{
|
{
|
||||||
var dialog = new FolderBrowserDialog {SelectedPath = Settings.GameDirectory};
|
var settings = (EurotruckSimulator2Settings) Settings;
|
||||||
|
var model = (EurotruckSimulator2Model) ModuleModel;
|
||||||
|
|
||||||
|
var dialog = new FolderBrowserDialog {SelectedPath = settings.Ets2GameDirectory};
|
||||||
var result = dialog.ShowDialog();
|
var result = dialog.ShowDialog();
|
||||||
if (result != DialogResult.OK)
|
if (result != DialogResult.OK)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Settings.GameDirectory = Path.GetDirectoryName(dialog.SelectedPath);
|
settings.Ets2GameDirectory = dialog.SelectedPath;
|
||||||
NotifyOfPropertyChange(() => Settings);
|
NotifyOfPropertyChange(() => Settings);
|
||||||
Settings.Save();
|
Settings.Save();
|
||||||
|
model.PlaceTruckSimulatorPlugin(settings.Ets2GameDirectory, "eurotrucks2.exe");
|
||||||
|
}
|
||||||
|
|
||||||
((EurotruckSimulator2Model) ModuleModel).PlacePlugin();
|
public void AtsBrowseDirectory()
|
||||||
|
{
|
||||||
|
var settings = (EurotruckSimulator2Settings) Settings;
|
||||||
|
var model = (EurotruckSimulator2Model)ModuleModel;
|
||||||
|
|
||||||
|
var dialog = new FolderBrowserDialog {SelectedPath = settings.AtsGameDirectory};
|
||||||
|
var result = dialog.ShowDialog();
|
||||||
|
if (result != DialogResult.OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
settings.AtsGameDirectory = dialog.SelectedPath;
|
||||||
|
NotifyOfPropertyChange(() => Settings);
|
||||||
|
Settings.Save();
|
||||||
|
model.PlaceTruckSimulatorPlugin(settings.AtsGameDirectory, "amtrucks.exe");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Ets2PlacePlugin()
|
||||||
|
{
|
||||||
|
var ets2Path = ((EurotruckSimulator2Settings)Settings).Ets2GameDirectory;
|
||||||
|
((EurotruckSimulator2Model)ModuleModel).PlaceTruckSimulatorPlugin(ets2Path, "eurotrucks2.exe");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AtsPlacePlugin()
|
||||||
|
{
|
||||||
|
var atsPath = ((EurotruckSimulator2Settings)Settings).AtsGameDirectory;
|
||||||
|
((EurotruckSimulator2Model)ModuleModel).PlaceTruckSimulatorPlugin(atsPath, "amtrucks.exe");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -20,7 +20,7 @@ namespace Artemis.Modules.Games.GtaV
|
|||||||
|
|
||||||
Settings = SettingsProvider.Load<GtaVSettings>();
|
Settings = SettingsProvider.Load<GtaVSettings>();
|
||||||
DataModel = new GtaVDataModel();
|
DataModel = new GtaVDataModel();
|
||||||
ProcessName = "GTA5";
|
ProcessNames.Add("GTA5");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Name => "GTAV";
|
public override string Name => "GTAV";
|
||||||
|
|||||||
@ -15,7 +15,7 @@ namespace Artemis.Modules.Games.LightFx
|
|||||||
{
|
{
|
||||||
Settings = SettingsProvider.Load<LightFxSettings>();
|
Settings = SettingsProvider.Load<LightFxSettings>();
|
||||||
DataModel = new LightFxDataModel();
|
DataModel = new LightFxDataModel();
|
||||||
ProcessName = "LoL";
|
ProcessNames.Add("LoL");
|
||||||
|
|
||||||
// This model can enable itself by changing its process name to the currently running Light FX game.
|
// This model can enable itself by changing its process name to the currently running Light FX game.
|
||||||
pipeServer.PipeMessage += PipeServerOnPipeMessage;
|
pipeServer.PipeMessage += PipeServerOnPipeMessage;
|
||||||
@ -43,7 +43,9 @@ namespace Artemis.Modules.Games.LightFx
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Setup process name
|
// Setup process name
|
||||||
ProcessName = Path.GetFileNameWithoutExtension(((LightFxDataModel) DataModel).LightFxState.game);
|
var processName = Path.GetFileNameWithoutExtension(((LightFxDataModel) DataModel).LightFxState.game);
|
||||||
|
if (!ProcessNames.Contains(processName))
|
||||||
|
ProcessNames.Add(processName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Update()
|
public override void Update()
|
||||||
|
|||||||
@ -38,7 +38,7 @@ namespace Artemis.Modules.Games.Overwatch
|
|||||||
|
|
||||||
Settings = SettingsProvider.Load<OverwatchSettings>();
|
Settings = SettingsProvider.Load<OverwatchSettings>();
|
||||||
DataModel = new OverwatchDataModel();
|
DataModel = new OverwatchDataModel();
|
||||||
ProcessName = "Overwatch";
|
ProcessNames.Add("Overwatch");
|
||||||
|
|
||||||
LoadOverwatchCharacters();
|
LoadOverwatchCharacters();
|
||||||
FindOverwatch();
|
FindOverwatch();
|
||||||
|
|||||||
@ -66,7 +66,7 @@
|
|||||||
cal:Message.Attach="[Event LostFocus] = [Action PlaceDll]" />
|
cal:Message.Attach="[Event LostFocus] = [Action PlaceDll]" />
|
||||||
<Button x:Name="BrowseDirectory" Content="..." RenderTransformOrigin="-0.039,-0.944"
|
<Button x:Name="BrowseDirectory" Content="..." RenderTransformOrigin="-0.039,-0.944"
|
||||||
HorizontalAlignment="Right" Width="25"
|
HorizontalAlignment="Right" Width="25"
|
||||||
Style="{DynamicResource SquareButtonStyle}" Height="26" Margin="0,-2,0,0" />
|
Style="{DynamicResource SquareButtonStyle}" Height="26" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,7 @@ namespace Artemis.Modules.Games.ProjectCars
|
|||||||
{
|
{
|
||||||
Settings = SettingsProvider.Load<ProjectCarsSettings>();
|
Settings = SettingsProvider.Load<ProjectCarsSettings>();
|
||||||
DataModel = new ProjectCarsDataModel();
|
DataModel = new ProjectCarsDataModel();
|
||||||
ProcessName = "pCARS64";
|
ProcessNames.Add("pCARS64");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Name => "ProjectCars";
|
public override string Name => "ProjectCars";
|
||||||
|
|||||||
@ -18,7 +18,7 @@ namespace Artemis.Modules.Games.RocketLeague
|
|||||||
{
|
{
|
||||||
Settings = SettingsProvider.Load<RocketLeagueSettings>();
|
Settings = SettingsProvider.Load<RocketLeagueSettings>();
|
||||||
DataModel = new RocketLeagueDataModel();
|
DataModel = new RocketLeagueDataModel();
|
||||||
ProcessName = "RocketLeague";
|
ProcessNames.Add("RocketLeague");
|
||||||
|
|
||||||
// Generate a new offset when the game is updated
|
// Generate a new offset when the game is updated
|
||||||
//var offset = new GamePointersCollection
|
//var offset = new GamePointersCollection
|
||||||
@ -55,17 +55,20 @@ namespace Artemis.Modules.Games.RocketLeague
|
|||||||
Updater.GetPointers();
|
Updater.GetPointers();
|
||||||
_pointer = SettingsProvider.Load<OffsetSettings>().RocketLeague;
|
_pointer = SettingsProvider.Load<OffsetSettings>().RocketLeague;
|
||||||
|
|
||||||
var tempProcess = MemoryHelpers.GetProcessIfRunning(ProcessName);
|
|
||||||
if (tempProcess == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_memory = new Memory(tempProcess);
|
|
||||||
|
|
||||||
base.Enable();
|
base.Enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Update()
|
public override void Update()
|
||||||
{
|
{
|
||||||
|
if (_memory == null)
|
||||||
|
{
|
||||||
|
var tempProcess = MemoryHelpers.GetProcessIfRunning(ProcessNames[0]);
|
||||||
|
if (tempProcess == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_memory = new Memory(tempProcess);
|
||||||
|
}
|
||||||
|
|
||||||
if (ProfileModel == null || DataModel == null || _memory == null)
|
if (ProfileModel == null || DataModel == null || _memory == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|||||||
@ -32,8 +32,6 @@ namespace Artemis.Modules.Games.RocketLeague
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public RocketLeagueModel RocketLeagueModel { get; set; }
|
|
||||||
|
|
||||||
private void SetVersionText()
|
private void SetVersionText()
|
||||||
{
|
{
|
||||||
if (!SettingsProvider.Load<GeneralSettings>().EnablePointersUpdate)
|
if (!SettingsProvider.Load<GeneralSettings>().EnablePointersUpdate)
|
||||||
|
|||||||
@ -22,7 +22,7 @@ namespace Artemis.Modules.Games.TheDivision
|
|||||||
|
|
||||||
Settings = SettingsProvider.Load<TheDivisionSettings>();
|
Settings = SettingsProvider.Load<TheDivisionSettings>();
|
||||||
DataModel = new TheDivisionDataModel();
|
DataModel = new TheDivisionDataModel();
|
||||||
ProcessName = "TheDivision";
|
ProcessNames.Add("TheDivision");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Name => "TheDivision";
|
public override string Name => "TheDivision";
|
||||||
|
|||||||
@ -30,7 +30,7 @@ namespace Artemis.Modules.Games.UnrealTournament
|
|||||||
|
|
||||||
Settings = SettingsProvider.Load<UnrealTournamentSettings>();
|
Settings = SettingsProvider.Load<UnrealTournamentSettings>();
|
||||||
DataModel = new UnrealTournamentDataModel();
|
DataModel = new UnrealTournamentDataModel();
|
||||||
ProcessName = "UE4-Win64-Shipping";
|
ProcessNames.Add("UE4-Win64-Shipping");
|
||||||
|
|
||||||
_killTimer = new Timer(3500);
|
_killTimer = new Timer(3500);
|
||||||
_killTimer.Elapsed += KillTimerOnElapsed;
|
_killTimer.Elapsed += KillTimerOnElapsed;
|
||||||
|
|||||||
@ -50,7 +50,7 @@
|
|||||||
cal:Message.Attach="[Event LostFocus] = [Action PlaceFiles]" />
|
cal:Message.Attach="[Event LostFocus] = [Action PlaceFiles]" />
|
||||||
<Button x:Name="BrowseDirectory" Content="..." RenderTransformOrigin="-0.039,-0.944"
|
<Button x:Name="BrowseDirectory" Content="..." RenderTransformOrigin="-0.039,-0.944"
|
||||||
HorizontalAlignment="Right" Width="25"
|
HorizontalAlignment="Right" Width="25"
|
||||||
Style="{DynamicResource SquareButtonStyle}" Height="26" Margin="0,-2,0,0" />
|
Style="{DynamicResource SquareButtonStyle}" Height="26" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
|
|||||||
@ -22,7 +22,7 @@ namespace Artemis.Modules.Games.Witcher3
|
|||||||
|
|
||||||
Settings = SettingsProvider.Load<Witcher3Settings>();
|
Settings = SettingsProvider.Load<Witcher3Settings>();
|
||||||
DataModel = new Witcher3DataModel();
|
DataModel = new Witcher3DataModel();
|
||||||
ProcessName = "witcher3";
|
ProcessNames.Add("witcher3");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Name => "Witcher3";
|
public override string Name => "Witcher3";
|
||||||
|
|||||||
@ -21,7 +21,7 @@ namespace Artemis.Modules.Games.WoW
|
|||||||
{
|
{
|
||||||
Settings = SettingsProvider.Load<WoWSettings>();
|
Settings = SettingsProvider.Load<WoWSettings>();
|
||||||
DataModel = new WoWDataModel();
|
DataModel = new WoWDataModel();
|
||||||
ProcessName = "Wow-64";
|
ProcessNames.Add("Wow-64");
|
||||||
|
|
||||||
// Currently WoW is locked behind a hidden trigger (obviously not that hidden since you're reading this)
|
// Currently WoW is locked behind a hidden trigger (obviously not that hidden since you're reading this)
|
||||||
// It is using memory reading and lets first try to contact Blizzard
|
// It is using memory reading and lets first try to contact Blizzard
|
||||||
@ -72,19 +72,17 @@ namespace Artemis.Modules.Games.WoW
|
|||||||
_process = null;
|
_process = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Enable()
|
public override void Update()
|
||||||
{
|
{
|
||||||
var tempProcess = MemoryHelpers.GetProcessIfRunning(ProcessName);
|
if (_process == null)
|
||||||
|
{
|
||||||
|
var tempProcess = MemoryHelpers.GetProcessIfRunning(ProcessNames[0]);
|
||||||
if (tempProcess == null)
|
if (tempProcess == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_process = new ProcessSharp(tempProcess, MemoryType.Remote);
|
_process = new ProcessSharp(tempProcess, MemoryType.Remote);
|
||||||
|
|
||||||
base.Enable();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Update()
|
|
||||||
{
|
|
||||||
if (ProfileModel == null || DataModel == null || _process == null)
|
if (ProfileModel == null || DataModel == null || _process == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|||||||
@ -15,6 +15,7 @@ namespace Artemis.Modules.General.GeneralProfile
|
|||||||
CurrentTime = new CurrentTime();
|
CurrentTime = new CurrentTime();
|
||||||
Keyboard = new KbDataModel();
|
Keyboard = new KbDataModel();
|
||||||
ActiveWindow = new ActiveWindow();
|
ActiveWindow = new ActiveWindow();
|
||||||
|
Audio = new Audio();
|
||||||
}
|
}
|
||||||
|
|
||||||
public CpuDataModel Cpu { get; set; }
|
public CpuDataModel Cpu { get; set; }
|
||||||
@ -24,6 +25,23 @@ namespace Artemis.Modules.General.GeneralProfile
|
|||||||
public CurrentTime CurrentTime { get; set; }
|
public CurrentTime CurrentTime { get; set; }
|
||||||
public KbDataModel Keyboard { get; set; }
|
public KbDataModel Keyboard { get; set; }
|
||||||
public ActiveWindow ActiveWindow { get; set; }
|
public ActiveWindow ActiveWindow { get; set; }
|
||||||
|
public Audio Audio { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[MoonSharpUserData]
|
||||||
|
public class Audio
|
||||||
|
{
|
||||||
|
public float Volume { get; set; }
|
||||||
|
public AudioDevice Recording { get; set; } = new AudioDevice();
|
||||||
|
public AudioDevice Playback { get; set; } = new AudioDevice();
|
||||||
|
}
|
||||||
|
|
||||||
|
[MoonSharpUserData]
|
||||||
|
public class AudioDevice
|
||||||
|
{
|
||||||
|
public float OverallPeak { get; set; }
|
||||||
|
public float LeftPeak { get; set; }
|
||||||
|
public float RightPeak { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[MoonSharpUserData]
|
[MoonSharpUserData]
|
||||||
|
|||||||
@ -7,9 +7,11 @@ using System.Runtime.InteropServices;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Artemis.DAL;
|
using Artemis.DAL;
|
||||||
|
using Artemis.Events;
|
||||||
using Artemis.Managers;
|
using Artemis.Managers;
|
||||||
using Artemis.Modules.Abstract;
|
using Artemis.Modules.Abstract;
|
||||||
using Artemis.Utilities;
|
using Artemis.Utilities;
|
||||||
|
using CSCore.CoreAudioAPI;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using SpotifyAPI.Local;
|
using SpotifyAPI.Local;
|
||||||
|
|
||||||
@ -17,19 +19,19 @@ namespace Artemis.Modules.General.GeneralProfile
|
|||||||
{
|
{
|
||||||
public class GeneralProfileModel : ModuleModel
|
public class GeneralProfileModel : ModuleModel
|
||||||
{
|
{
|
||||||
private List<PerformanceCounter> _cores;
|
|
||||||
private int _cpuFrames;
|
|
||||||
private DateTime _lastMusicUpdate;
|
private DateTime _lastMusicUpdate;
|
||||||
private PerformanceCounter _overallCpu;
|
|
||||||
private SpotifyLocalAPI _spotify;
|
private SpotifyLocalAPI _spotify;
|
||||||
private bool _spotifySetupBusy;
|
private bool _spotifySetupBusy;
|
||||||
|
|
||||||
public GeneralProfileModel(DeviceManager deviceManager, LuaManager luaManager) : base(deviceManager, luaManager)
|
public GeneralProfileModel(DeviceManager deviceManager, LuaManager luaManager,
|
||||||
|
AudioCaptureManager audioCaptureManager) : base(deviceManager, luaManager)
|
||||||
{
|
{
|
||||||
_lastMusicUpdate = DateTime.Now;
|
_lastMusicUpdate = DateTime.Now;
|
||||||
|
|
||||||
Settings = SettingsProvider.Load<GeneralProfileSettings>();
|
Settings = SettingsProvider.Load<GeneralProfileSettings>();
|
||||||
DataModel = new GeneralProfileDataModel();
|
DataModel = new GeneralProfileDataModel();
|
||||||
|
|
||||||
|
audioCaptureManager.AudioDeviceChanged += AudioDeviceChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Name => "GeneralProfile";
|
public override string Name => "GeneralProfile";
|
||||||
@ -40,6 +42,7 @@ namespace Artemis.Modules.General.GeneralProfile
|
|||||||
{
|
{
|
||||||
SetupCpu();
|
SetupCpu();
|
||||||
SetupSpotify();
|
SetupSpotify();
|
||||||
|
SetupAudio();
|
||||||
|
|
||||||
base.Enable();
|
base.Enable();
|
||||||
}
|
}
|
||||||
@ -52,6 +55,7 @@ namespace Artemis.Modules.General.GeneralProfile
|
|||||||
UpdateDay(dataModel);
|
UpdateDay(dataModel);
|
||||||
UpdateKeyStates(dataModel);
|
UpdateKeyStates(dataModel);
|
||||||
UpdateActiveWindow(dataModel);
|
UpdateActiveWindow(dataModel);
|
||||||
|
UpdateAudio(dataModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Current Time
|
#region Current Time
|
||||||
@ -67,8 +71,63 @@ namespace Artemis.Modules.General.GeneralProfile
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Audio
|
||||||
|
|
||||||
|
private MMDevice _defaultRecording;
|
||||||
|
private MMDevice _defaultPlayback;
|
||||||
|
private AudioMeterInformation _recordingInfo;
|
||||||
|
private AudioMeterInformation _playbackInfo;
|
||||||
|
|
||||||
|
private void SetupAudio()
|
||||||
|
{
|
||||||
|
_defaultRecording = MMDeviceEnumerator.TryGetDefaultAudioEndpoint(DataFlow.Capture, Role.Multimedia);
|
||||||
|
_defaultPlayback = MMDeviceEnumerator.TryGetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia);
|
||||||
|
|
||||||
|
if (_defaultRecording != null)
|
||||||
|
_recordingInfo = AudioMeterInformation.FromDevice(_defaultRecording);
|
||||||
|
if (_defaultPlayback != null)
|
||||||
|
_playbackInfo = AudioMeterInformation.FromDevice(_defaultPlayback);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AudioDeviceChanged(object sender, AudioDeviceChangedEventArgs e)
|
||||||
|
{
|
||||||
|
_defaultRecording = e.DefaultRecording;
|
||||||
|
_defaultPlayback = e.DefaultPlayback;
|
||||||
|
|
||||||
|
if (_defaultRecording != null)
|
||||||
|
_recordingInfo = AudioMeterInformation.FromDevice(_defaultRecording);
|
||||||
|
if (_defaultPlayback != null)
|
||||||
|
_playbackInfo = AudioMeterInformation.FromDevice(_defaultPlayback);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateAudio(GeneralProfileDataModel dataModel)
|
||||||
|
{
|
||||||
|
// Update microphone, only bother with OverallPeak
|
||||||
|
if (_defaultRecording != null)
|
||||||
|
dataModel.Audio.Recording.OverallPeak = _recordingInfo.PeakValue;
|
||||||
|
|
||||||
|
if (_defaultPlayback == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Update volume if a default device is found
|
||||||
|
dataModel.Audio.Volume = AudioEndpointVolume.FromDevice(_defaultPlayback).GetMasterVolumeLevelScalar();
|
||||||
|
|
||||||
|
// Update speakers, only do overall, left and right for now
|
||||||
|
// TODO: When adding list support lets do all channels
|
||||||
|
var peakValues = _playbackInfo.GetChannelsPeakValues();
|
||||||
|
dataModel.Audio.Playback.OverallPeak = _playbackInfo.PeakValue;
|
||||||
|
dataModel.Audio.Playback.LeftPeak = peakValues[0];
|
||||||
|
dataModel.Audio.Playback.LeftPeak = peakValues[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region CPU
|
#region CPU
|
||||||
|
|
||||||
|
private List<PerformanceCounter> _cores;
|
||||||
|
private int _cpuFrames;
|
||||||
|
private PerformanceCounter _overallCpu;
|
||||||
|
|
||||||
private void SetupCpu()
|
private void SetupCpu()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
using Artemis.Modules.Abstract;
|
using Artemis.Modules.Abstract;
|
||||||
using Artemis.Modules.General.GeneralProfile;
|
using Artemis.Modules.General.GeneralProfile;
|
||||||
|
using MoonSharp.Interpreter;
|
||||||
|
|
||||||
namespace Artemis.Modules.Overlays.OverlayProfile
|
namespace Artemis.Modules.Overlays.OverlayProfile
|
||||||
{
|
{
|
||||||
@ -7,9 +8,17 @@ namespace Artemis.Modules.Overlays.OverlayProfile
|
|||||||
{
|
{
|
||||||
public OverlayProfileDataModel()
|
public OverlayProfileDataModel()
|
||||||
{
|
{
|
||||||
GeneralDataModel = new GeneralProfileDataModel();
|
Keyboard = new KbDataModel();
|
||||||
|
Audio = new Audio();
|
||||||
}
|
}
|
||||||
|
|
||||||
public GeneralProfileDataModel GeneralDataModel { get; set; }
|
public KbDataModel Keyboard { get; set; }
|
||||||
|
public Audio Audio { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[MoonSharpUserData]
|
||||||
|
public class Audio
|
||||||
|
{
|
||||||
|
public float Volume { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,32 +1,65 @@
|
|||||||
using Artemis.DAL;
|
using Artemis.DAL;
|
||||||
|
using Artemis.Events;
|
||||||
using Artemis.Managers;
|
using Artemis.Managers;
|
||||||
using Artemis.Modules.Abstract;
|
using Artemis.Modules.Abstract;
|
||||||
using Artemis.Modules.General.GeneralProfile;
|
using Artemis.Modules.General.GeneralProfile;
|
||||||
using Ninject;
|
using CSCore.CoreAudioAPI;
|
||||||
|
|
||||||
namespace Artemis.Modules.Overlays.OverlayProfile
|
namespace Artemis.Modules.Overlays.OverlayProfile
|
||||||
{
|
{
|
||||||
public class OverlayProfileModel : ModuleModel
|
public class OverlayProfileModel : ModuleModel
|
||||||
{
|
{
|
||||||
private readonly GeneralProfileModel _generalProfileModel;
|
private AudioEndpointVolume _endPointVolume;
|
||||||
|
|
||||||
public OverlayProfileModel(DeviceManager deviceManager, LuaManager luaManager,
|
public OverlayProfileModel(DeviceManager deviceManager, LuaManager luaManager,
|
||||||
[Named(nameof(GeneralProfileModel))] ModuleModel generalProfileModel) : base(deviceManager, luaManager)
|
AudioCaptureManager audioCaptureManager) : base(deviceManager, luaManager)
|
||||||
{
|
{
|
||||||
_generalProfileModel = (GeneralProfileModel) generalProfileModel;
|
|
||||||
Settings = SettingsProvider.Load<OverlayProfileSettings>();
|
Settings = SettingsProvider.Load<OverlayProfileSettings>();
|
||||||
DataModel = new OverlayProfileDataModel();
|
DataModel = new OverlayProfileDataModel();
|
||||||
|
|
||||||
|
var defaultPlayback = MMDeviceEnumerator.TryGetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia);
|
||||||
|
if (defaultPlayback != null)
|
||||||
|
_endPointVolume = AudioEndpointVolume.FromDevice(defaultPlayback);
|
||||||
|
|
||||||
|
audioCaptureManager.AudioDeviceChanged += OnAudioDeviceChanged;
|
||||||
|
|
||||||
|
Enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Name => "OverlayProfile";
|
public override string Name => "OverlayProfile";
|
||||||
public override bool IsOverlay => true;
|
public override bool IsOverlay => true;
|
||||||
public override bool IsBoundToProcess => false;
|
public override bool IsBoundToProcess => false;
|
||||||
|
|
||||||
|
private void OnAudioDeviceChanged(object sender, AudioDeviceChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.DefaultPlayback != null)
|
||||||
|
_endPointVolume = AudioEndpointVolume.FromDevice(e.DefaultPlayback);
|
||||||
|
}
|
||||||
|
|
||||||
public override void Update()
|
public override void Update()
|
||||||
{
|
{
|
||||||
// TODO: Find a clean way to update the parent profile model
|
if (!Settings.IsEnabled)
|
||||||
((OverlayProfileDataModel) DataModel).GeneralDataModel =
|
return;
|
||||||
(GeneralProfileDataModel) _generalProfileModel.DataModel;
|
|
||||||
|
var dataModel = (OverlayProfileDataModel) DataModel;
|
||||||
|
|
||||||
|
dataModel.Keyboard.NumLock = ((ushort) GeneralProfileModel.GetKeyState(0x90) & 0xffff) != 0;
|
||||||
|
dataModel.Keyboard.CapsLock = ((ushort) GeneralProfileModel.GetKeyState(0x14) & 0xffff) != 0;
|
||||||
|
dataModel.Keyboard.ScrollLock = ((ushort) GeneralProfileModel.GetKeyState(0x91) & 0xffff) != 0;
|
||||||
|
|
||||||
|
if (_endPointVolume != null)
|
||||||
|
dataModel.Audio.Volume = _endPointVolume.GetMasterVolumeLevelScalar();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Render(RenderFrame frame, bool keyboardOnly)
|
||||||
|
{
|
||||||
|
if (Settings.IsEnabled)
|
||||||
|
base.Render(frame, keyboardOnly);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Dispose()
|
||||||
|
{
|
||||||
|
PreviewLayers = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,5 +1,6 @@
|
|||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
using Artemis.Profiles.Layers.Models;
|
using Artemis.Profiles.Layers.Models;
|
||||||
|
using Artemis.ViewModels;
|
||||||
using Artemis.ViewModels.Profiles;
|
using Artemis.ViewModels.Profiles;
|
||||||
using Caliburn.Micro;
|
using Caliburn.Micro;
|
||||||
|
|
||||||
|
|||||||
@ -27,17 +27,17 @@ namespace Artemis.Profiles.Layers.Animations
|
|||||||
layerModel.AnimationProgress = progress;
|
layerModel.AnimationProgress = progress;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Draw(LayerModel layerModel, DrawingContext c)
|
public void Draw(LayerModel layerModel, DrawingContext c, int drawScale)
|
||||||
{
|
{
|
||||||
if (layerModel.Brush == null)
|
if (layerModel.Brush == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Set up variables for this frame
|
// Set up variables for this frame
|
||||||
var rect = layerModel.Properties.Contain
|
var rect = layerModel.Properties.Contain
|
||||||
? layerModel.LayerRect()
|
? layerModel.LayerRect(drawScale)
|
||||||
: layerModel.Properties.PropertiesRect();
|
: layerModel.Properties.PropertiesRect(drawScale);
|
||||||
|
|
||||||
var clip = layerModel.LayerRect();
|
var clip = layerModel.LayerRect(drawScale);
|
||||||
|
|
||||||
// Take an offset of 4 to allow layers to slightly leave their bounds
|
// Take an offset of 4 to allow layers to slightly leave their bounds
|
||||||
var progress = (6.0 - layerModel.AnimationProgress)*10.0;
|
var progress = (6.0 - layerModel.AnimationProgress)*10.0;
|
||||||
|
|||||||
@ -12,7 +12,7 @@ namespace Artemis.Profiles.Layers.Animations
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Draw(LayerModel layerModel, DrawingContext c)
|
public void Draw(LayerModel layerModel, DrawingContext c, int drawScale)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -27,17 +27,17 @@ namespace Artemis.Profiles.Layers.Animations
|
|||||||
layerModel.AnimationProgress = progress;
|
layerModel.AnimationProgress = progress;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Draw(LayerModel layerModel, DrawingContext c)
|
public void Draw(LayerModel layerModel, DrawingContext c, int drawScale)
|
||||||
{
|
{
|
||||||
if (layerModel.Brush == null)
|
if (layerModel.Brush == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Set up variables for this frame
|
// Set up variables for this frame
|
||||||
var rect = layerModel.Properties.Contain
|
var rect = layerModel.Properties.Contain
|
||||||
? layerModel.LayerRect()
|
? layerModel.LayerRect(drawScale)
|
||||||
: layerModel.Properties.PropertiesRect();
|
: layerModel.Properties.PropertiesRect(drawScale);
|
||||||
|
|
||||||
var clip = layerModel.LayerRect();
|
var clip = layerModel.LayerRect(drawScale);
|
||||||
|
|
||||||
// Can't meddle with the original brush because it's frozen.
|
// Can't meddle with the original brush because it's frozen.
|
||||||
var brush = layerModel.Brush.Clone();
|
var brush = layerModel.Brush.Clone();
|
||||||
|
|||||||
@ -14,29 +14,29 @@ namespace Artemis.Profiles.Layers.Animations
|
|||||||
var progress = layerModel.AnimationProgress;
|
var progress = layerModel.AnimationProgress;
|
||||||
if (MustExpire(layerModel))
|
if (MustExpire(layerModel))
|
||||||
progress = 0;
|
progress = 0;
|
||||||
progress = progress + layerModel.Properties.AnimationSpeed*2;
|
progress = progress + layerModel.Properties.AnimationSpeed * 2 / 4 * layerModel.LayerType.DrawScale;
|
||||||
|
|
||||||
// If not previewing, store the animation progress in the actual model for the next frame
|
// If not previewing, store the animation progress in the actual model for the next frame
|
||||||
if (updateAnimations)
|
if (updateAnimations)
|
||||||
layerModel.AnimationProgress = progress;
|
layerModel.AnimationProgress = progress;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Draw(LayerModel layerModel, DrawingContext c)
|
public void Draw(LayerModel layerModel, DrawingContext c, int drawScale)
|
||||||
{
|
{
|
||||||
if (layerModel.Brush == null)
|
if (layerModel.Brush == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Set up variables for this frame
|
// Set up variables for this frame
|
||||||
var rect = layerModel.Properties.Contain
|
var rect = layerModel.Properties.Contain
|
||||||
? layerModel.LayerRect()
|
? layerModel.LayerRect(drawScale)
|
||||||
: layerModel.Properties.PropertiesRect();
|
: layerModel.Properties.PropertiesRect(drawScale);
|
||||||
|
|
||||||
var s1 = new Rect(new Point(rect.X, rect.Y + layerModel.AnimationProgress),
|
var s1 = new Rect(new Point(rect.X, rect.Y + layerModel.AnimationProgress),
|
||||||
new Size(rect.Width, rect.Height));
|
new Size(rect.Width, rect.Height));
|
||||||
var s2 = new Rect(new Point(s1.X, s1.Y - rect.Height),
|
var s2 = new Rect(new Point(s1.X, s1.Y - rect.Height),
|
||||||
new Size(rect.Width, rect.Height + .5));
|
new Size(rect.Width, rect.Height + .5));
|
||||||
|
|
||||||
var clip = layerModel.LayerRect();
|
var clip = layerModel.LayerRect(drawScale);
|
||||||
|
|
||||||
c.PushClip(new RectangleGeometry(clip));
|
c.PushClip(new RectangleGeometry(clip));
|
||||||
c.DrawRectangle(layerModel.Brush, null, s1);
|
c.DrawRectangle(layerModel.Brush, null, s1);
|
||||||
@ -46,7 +46,8 @@ namespace Artemis.Profiles.Layers.Animations
|
|||||||
|
|
||||||
public bool MustExpire(LayerModel layer)
|
public bool MustExpire(LayerModel layer)
|
||||||
{
|
{
|
||||||
return layer.AnimationProgress + layer.Properties.AnimationSpeed*2 >= layer.Properties.Height*4;
|
return layer.AnimationProgress + layer.Properties.AnimationSpeed * 2 >=
|
||||||
|
layer.Properties.Height * layer.LayerType.DrawScale;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -14,29 +14,29 @@ namespace Artemis.Profiles.Layers.Animations
|
|||||||
var progress = layerModel.AnimationProgress;
|
var progress = layerModel.AnimationProgress;
|
||||||
if (MustExpire(layerModel))
|
if (MustExpire(layerModel))
|
||||||
progress = 0;
|
progress = 0;
|
||||||
progress = progress + layerModel.Properties.AnimationSpeed*2;
|
progress = progress + layerModel.Properties.AnimationSpeed * 2 / 4 * layerModel.LayerType.DrawScale;
|
||||||
|
|
||||||
// If not previewing, store the animation progress in the actual model for the next frame
|
// If not previewing, store the animation progress in the actual model for the next frame
|
||||||
if (updateAnimations)
|
if (updateAnimations)
|
||||||
layerModel.AnimationProgress = progress;
|
layerModel.AnimationProgress = progress;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Draw(LayerModel layerModel, DrawingContext c)
|
public void Draw(LayerModel layerModel, DrawingContext c, int drawScale)
|
||||||
{
|
{
|
||||||
if (layerModel.Brush == null)
|
if (layerModel.Brush == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Set up variables for this frame
|
// Set up variables for this frame
|
||||||
var rect = layerModel.Properties.Contain
|
var rect = layerModel.Properties.Contain
|
||||||
? layerModel.LayerRect()
|
? layerModel.LayerRect(drawScale)
|
||||||
: layerModel.Properties.PropertiesRect();
|
: layerModel.Properties.PropertiesRect(drawScale);
|
||||||
|
|
||||||
var s1 = new Rect(new Point(rect.X - layerModel.AnimationProgress, rect.Y),
|
var s1 = new Rect(new Point(rect.X - layerModel.AnimationProgress, rect.Y),
|
||||||
new Size(rect.Width + .5, rect.Height));
|
new Size(rect.Width + .5, rect.Height));
|
||||||
var s2 = new Rect(new Point(s1.X + rect.Width, rect.Y),
|
var s2 = new Rect(new Point(s1.X + rect.Width, rect.Y),
|
||||||
new Size(rect.Width, rect.Height));
|
new Size(rect.Width, rect.Height));
|
||||||
|
|
||||||
var clip = layerModel.LayerRect();
|
var clip = layerModel.LayerRect(drawScale);
|
||||||
|
|
||||||
c.PushClip(new RectangleGeometry(clip));
|
c.PushClip(new RectangleGeometry(clip));
|
||||||
c.DrawRectangle(layerModel.Brush, null, s1);
|
c.DrawRectangle(layerModel.Brush, null, s1);
|
||||||
@ -46,7 +46,8 @@ namespace Artemis.Profiles.Layers.Animations
|
|||||||
|
|
||||||
public bool MustExpire(LayerModel layer)
|
public bool MustExpire(LayerModel layer)
|
||||||
{
|
{
|
||||||
return layer.AnimationProgress + layer.Properties.AnimationSpeed*2 >= layer.Properties.Width*4;
|
return layer.AnimationProgress + layer.Properties.AnimationSpeed * 2 >=
|
||||||
|
layer.Properties.Width * layer.LayerType.DrawScale;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -14,29 +14,29 @@ namespace Artemis.Profiles.Layers.Animations
|
|||||||
var progress = layerModel.AnimationProgress;
|
var progress = layerModel.AnimationProgress;
|
||||||
if (MustExpire(layerModel))
|
if (MustExpire(layerModel))
|
||||||
progress = 0;
|
progress = 0;
|
||||||
progress = progress + layerModel.Properties.AnimationSpeed*2;
|
progress = progress + layerModel.Properties.AnimationSpeed * 2 / 4 * layerModel.LayerType.DrawScale;
|
||||||
|
|
||||||
// If not previewing, store the animation progress in the actual model for the next frame
|
// If not previewing, store the animation progress in the actual model for the next frame
|
||||||
if (updateAnimations)
|
if (updateAnimations)
|
||||||
layerModel.AnimationProgress = progress;
|
layerModel.AnimationProgress = progress;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Draw(LayerModel layerModel, DrawingContext c)
|
public void Draw(LayerModel layerModel, DrawingContext c, int drawScale)
|
||||||
{
|
{
|
||||||
if (layerModel.Brush == null)
|
if (layerModel.Brush == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Set up variables for this frame
|
// Set up variables for this frame
|
||||||
var rect = layerModel.Properties.Contain
|
var rect = layerModel.Properties.Contain
|
||||||
? layerModel.LayerRect()
|
? layerModel.LayerRect(drawScale)
|
||||||
: layerModel.Properties.PropertiesRect();
|
: layerModel.Properties.PropertiesRect(drawScale);
|
||||||
|
|
||||||
var s1 = new Rect(new Point(rect.X + layerModel.AnimationProgress, rect.Y),
|
var s1 = new Rect(new Point(rect.X + layerModel.AnimationProgress, rect.Y),
|
||||||
new Size(rect.Width, rect.Height));
|
new Size(rect.Width, rect.Height));
|
||||||
var s2 = new Rect(new Point(s1.X - rect.Width, rect.Y),
|
var s2 = new Rect(new Point(s1.X - rect.Width, rect.Y),
|
||||||
new Size(rect.Width + .5, rect.Height));
|
new Size(rect.Width + .5, rect.Height));
|
||||||
|
|
||||||
var clip = layerModel.LayerRect();
|
var clip = layerModel.LayerRect(drawScale);
|
||||||
|
|
||||||
c.PushClip(new RectangleGeometry(clip));
|
c.PushClip(new RectangleGeometry(clip));
|
||||||
c.DrawRectangle(layerModel.Brush, null, s1);
|
c.DrawRectangle(layerModel.Brush, null, s1);
|
||||||
@ -46,7 +46,8 @@ namespace Artemis.Profiles.Layers.Animations
|
|||||||
|
|
||||||
public bool MustExpire(LayerModel layer)
|
public bool MustExpire(LayerModel layer)
|
||||||
{
|
{
|
||||||
return layer.AnimationProgress + layer.Properties.AnimationSpeed*2 >= layer.Properties.Width*4;
|
return layer.AnimationProgress + layer.Properties.AnimationSpeed * 2 >=
|
||||||
|
layer.Properties.Width * layer.LayerType.DrawScale;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -14,28 +14,28 @@ namespace Artemis.Profiles.Layers.Animations
|
|||||||
var progress = layerModel.AnimationProgress;
|
var progress = layerModel.AnimationProgress;
|
||||||
if (MustExpire(layerModel))
|
if (MustExpire(layerModel))
|
||||||
progress = 0;
|
progress = 0;
|
||||||
progress = progress + layerModel.Properties.AnimationSpeed*2;
|
progress = progress + layerModel.Properties.AnimationSpeed * 2 / 4 * layerModel.LayerType.DrawScale;
|
||||||
|
|
||||||
// If not previewing, store the animation progress in the actual model for the next frame
|
// If not previewing, store the animation progress in the actual model for the next frame
|
||||||
if (updateAnimations)
|
if (updateAnimations)
|
||||||
layerModel.AnimationProgress = progress;
|
layerModel.AnimationProgress = progress;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Draw(LayerModel layerModel, DrawingContext c)
|
public void Draw(LayerModel layerModel, DrawingContext c, int drawScale)
|
||||||
{
|
{
|
||||||
if (layerModel.Brush == null)
|
if (layerModel.Brush == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Set up variables for this frame
|
// Set up variables for this frame
|
||||||
var rect = layerModel.Properties.Contain
|
var rect = layerModel.Properties.Contain
|
||||||
? layerModel.LayerRect()
|
? layerModel.LayerRect(drawScale)
|
||||||
: layerModel.Properties.PropertiesRect();
|
: layerModel.Properties.PropertiesRect(drawScale);
|
||||||
|
|
||||||
var s1 = new Rect(new Point(rect.X, rect.Y - layerModel.AnimationProgress),
|
var s1 = new Rect(new Point(rect.X, rect.Y - layerModel.AnimationProgress),
|
||||||
new Size(rect.Width, rect.Height + .5));
|
new Size(rect.Width, rect.Height + .5));
|
||||||
var s2 = new Rect(new Point(s1.X, s1.Y + rect.Height), new Size(rect.Width, rect.Height));
|
var s2 = new Rect(new Point(s1.X, s1.Y + rect.Height), new Size(rect.Width, rect.Height));
|
||||||
|
|
||||||
var clip = layerModel.LayerRect();
|
var clip = layerModel.LayerRect(drawScale);
|
||||||
|
|
||||||
c.PushClip(new RectangleGeometry(clip));
|
c.PushClip(new RectangleGeometry(clip));
|
||||||
c.DrawRectangle(layerModel.Brush, null, s1);
|
c.DrawRectangle(layerModel.Brush, null, s1);
|
||||||
@ -45,7 +45,8 @@ namespace Artemis.Profiles.Layers.Animations
|
|||||||
|
|
||||||
public bool MustExpire(LayerModel layer)
|
public bool MustExpire(LayerModel layer)
|
||||||
{
|
{
|
||||||
return layer.AnimationProgress + layer.Properties.AnimationSpeed*2 >= layer.Properties.Height*4;
|
return layer.AnimationProgress + layer.Properties.AnimationSpeed * 2 >=
|
||||||
|
layer.Properties.Height * layer.LayerType.DrawScale;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -10,7 +10,7 @@ namespace Artemis.Profiles.Layers.Interfaces
|
|||||||
string Name { get; }
|
string Name { get; }
|
||||||
|
|
||||||
void Update(LayerModel layerModel, bool updateAnimations);
|
void Update(LayerModel layerModel, bool updateAnimations);
|
||||||
void Draw(LayerModel layerModel, DrawingContext c);
|
void Draw(LayerModel layerModel, DrawingContext c, int drawScale);
|
||||||
bool MustExpire(LayerModel layerModel);
|
bool MustExpire(LayerModel layerModel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2,7 +2,7 @@
|
|||||||
using Artemis.Modules.Abstract;
|
using Artemis.Modules.Abstract;
|
||||||
using Artemis.Profiles.Layers.Abstract;
|
using Artemis.Profiles.Layers.Abstract;
|
||||||
using Artemis.Profiles.Layers.Models;
|
using Artemis.Profiles.Layers.Models;
|
||||||
using Artemis.ViewModels.Profiles;
|
using Artemis.ViewModels;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace Artemis.Profiles.Layers.Interfaces
|
namespace Artemis.Profiles.Layers.Interfaces
|
||||||
@ -28,6 +28,12 @@ namespace Artemis.Profiles.Layers.Interfaces
|
|||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
DrawType DrawType { get; }
|
DrawType DrawType { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the scale on which the layer should be drawn
|
||||||
|
/// </summary>
|
||||||
|
[JsonIgnore]
|
||||||
|
int DrawScale { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The the thumbnail for this layer type
|
/// The the thumbnail for this layer type
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
using Artemis.Modules.Abstract;
|
using Artemis.Modules.Abstract;
|
||||||
using Artemis.Utilities;
|
using Artemis.Utilities;
|
||||||
using DynamicExpresso;
|
using DynamicExpresso;
|
||||||
@ -8,6 +9,7 @@ namespace Artemis.Profiles.Layers.Models
|
|||||||
public class LayerConditionModel
|
public class LayerConditionModel
|
||||||
{
|
{
|
||||||
private readonly Interpreter _interpreter;
|
private readonly Interpreter _interpreter;
|
||||||
|
private object _lastValue;
|
||||||
|
|
||||||
public LayerConditionModel()
|
public LayerConditionModel()
|
||||||
{
|
{
|
||||||
@ -23,11 +25,60 @@ namespace Artemis.Profiles.Layers.Models
|
|||||||
{
|
{
|
||||||
lock (subject)
|
lock (subject)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(Field) || string.IsNullOrEmpty(Value) || string.IsNullOrEmpty(Type))
|
if (string.IsNullOrEmpty(Field) || string.IsNullOrEmpty(Type))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var inspect = GeneralHelpers.GetPropertyValue(subject, Field);
|
var inspect = GeneralHelpers.GetPropertyValue(subject, Field);
|
||||||
if (inspect == null)
|
if (inspect == null)
|
||||||
|
{
|
||||||
|
_lastValue = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool returnValue;
|
||||||
|
if (Operator == "changed" || Operator == "decreased" || Operator == "increased")
|
||||||
|
returnValue = EvaluateEventOperator(subject, inspect);
|
||||||
|
else
|
||||||
|
returnValue = EvaluateOperator(subject);
|
||||||
|
|
||||||
|
_lastValue = inspect;
|
||||||
|
return returnValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool EvaluateEventOperator(ModuleDataModel subject, object inspect)
|
||||||
|
{
|
||||||
|
// DynamicExpresso doesn't want a null so when it was previously null (should only happen first iteration)
|
||||||
|
// return false since that would be the only possible outcome
|
||||||
|
if (_lastValue == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Assign the right parameter
|
||||||
|
var rightParam = new Parameter("value", _lastValue);
|
||||||
|
|
||||||
|
// Come up with the proper operator
|
||||||
|
var changeOperator = "";
|
||||||
|
if (Operator == "changed")
|
||||||
|
changeOperator = "!=";
|
||||||
|
else if (Operator == "decreased")
|
||||||
|
changeOperator = "<";
|
||||||
|
else if (Operator == "increased")
|
||||||
|
changeOperator = ">";
|
||||||
|
|
||||||
|
// Evaluate the result and store it
|
||||||
|
var returnValue = _interpreter.Eval<bool>($"subject.{Field} {changeOperator} value",
|
||||||
|
new Parameter("subject", subject.GetType(), subject), rightParam);
|
||||||
|
|
||||||
|
// Set the last value to the new value
|
||||||
|
_lastValue = inspect;
|
||||||
|
// Return the evaluated result
|
||||||
|
return returnValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool EvaluateOperator(ModuleDataModel subject)
|
||||||
|
{
|
||||||
|
// Since _lastValue won't be used, rely on Value to not be null
|
||||||
|
if (string.IsNullOrEmpty(Value))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Put the subject in a list, allowing Dynamic Linq to be used.
|
// Put the subject in a list, allowing Dynamic Linq to be used.
|
||||||
@ -51,11 +102,15 @@ namespace Artemis.Profiles.Layers.Models
|
|||||||
case "Int32":
|
case "Int32":
|
||||||
rightParam = new Parameter("value", int.Parse(Value));
|
rightParam = new Parameter("value", int.Parse(Value));
|
||||||
break;
|
break;
|
||||||
|
case "Single":
|
||||||
|
// Parse commas as decimals
|
||||||
|
rightParam = new Parameter("value", float.Parse(Value.Replace(",", "."),
|
||||||
|
CultureInfo.InvariantCulture));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _interpreter.Eval<bool>($"subject.{Field} {Operator} value",
|
return _interpreter.Eval<bool>($"subject.{Field} {Operator} value",
|
||||||
new Parameter("subject", subject.GetType(), subject), rightParam);
|
new Parameter("subject", subject.GetType(), subject), rightParam);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@ -26,61 +26,88 @@ namespace Artemis.Profiles.Layers.Models
|
|||||||
_heightTweener = new Tweener<float>((float) layerModel.Height, (float) layerModel.Height, 0);
|
_heightTweener = new Tweener<float>((float) layerModel.Height, (float) layerModel.Height, 0);
|
||||||
_opacityTweener = new Tweener<float>((float) layerModel.Opacity, (float) layerModel.Opacity, 0);
|
_opacityTweener = new Tweener<float>((float) layerModel.Opacity, (float) layerModel.Opacity, 0);
|
||||||
|
|
||||||
StoreCurrentValues();
|
_x = (float)_layerModel.X;
|
||||||
|
_y = (float)_layerModel.Y;
|
||||||
|
_width = (float)_layerModel.Width;
|
||||||
|
_height = (float)_layerModel.Height;
|
||||||
|
_opacity = (float)_layerModel.Opacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Update()
|
public void Update()
|
||||||
{
|
{
|
||||||
|
UpdateWidth();
|
||||||
|
UpdateHeight();
|
||||||
|
UpdateOpacity();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateWidth()
|
||||||
|
{
|
||||||
|
if (_layerModel.Properties.WidthEaseTime < 0.001)
|
||||||
|
return;
|
||||||
|
|
||||||
// Width
|
// Width
|
||||||
if (Math.Abs(_layerModel.Width - _width) > 0.001)
|
if (Math.Abs(_layerModel.Width - _width) > 0.001)
|
||||||
{
|
{
|
||||||
var widthFunc = GetEaseFunction(_layerModel.Properties.WidthEase);
|
var widthFunc = GetEaseFunction(_layerModel.Properties.WidthEase);
|
||||||
var widthSpeed = _layerModel.Properties.WidthEaseTime;
|
var widthSpeed = _layerModel.Properties.WidthEaseTime;
|
||||||
|
|
||||||
_xTweener = new Tweener<float>(_xTweener.Value, (float) _layerModel.X, widthSpeed, widthFunc);
|
_xTweener = new Tweener<float>(_xTweener.Value, (float)_layerModel.X, widthSpeed, widthFunc);
|
||||||
_widthTweener = new Tweener<float>(_widthTweener.Value, (float) _layerModel.Width, widthSpeed, widthFunc);
|
_widthTweener = new Tweener<float>(_widthTweener.Value, (float)_layerModel.Width, widthSpeed, widthFunc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_xTweener.Update(40);
|
||||||
|
_widthTweener.Update(40);
|
||||||
|
|
||||||
|
_x = (float) _layerModel.X;
|
||||||
|
_width = (float)_layerModel.Width;
|
||||||
|
|
||||||
|
_layerModel.X = _xTweener.Value;
|
||||||
|
_layerModel.Width = _widthTweener.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateHeight()
|
||||||
|
{
|
||||||
|
if (_layerModel.Properties.HeightEaseTime < 0.001)
|
||||||
|
return;
|
||||||
|
|
||||||
// Height
|
// Height
|
||||||
if (Math.Abs(_layerModel.Height - _height) > 0.001)
|
if (Math.Abs(_layerModel.Height - _height) > 0.001)
|
||||||
{
|
{
|
||||||
var heightFunc = GetEaseFunction(_layerModel.Properties.HeightEase);
|
var heightFunc = GetEaseFunction(_layerModel.Properties.HeightEase);
|
||||||
var heightSpeed = _layerModel.Properties.HeightEaseTime;
|
var heightSpeed = _layerModel.Properties.HeightEaseTime;
|
||||||
_yTweener = new Tweener<float>(_y, (float) _layerModel.Y, heightSpeed, heightFunc);
|
_yTweener = new Tweener<float>(_y, (float)_layerModel.Y, heightSpeed, heightFunc);
|
||||||
_heightTweener = new Tweener<float>(_height, (float) _layerModel.Height, heightSpeed, heightFunc);
|
_heightTweener = new Tweener<float>(_height, (float)_layerModel.Height, heightSpeed, heightFunc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_yTweener.Update(40);
|
||||||
|
_heightTweener.Update(40);
|
||||||
|
|
||||||
|
_y = (float)_layerModel.Y;
|
||||||
|
_height = (float)_layerModel.Height;
|
||||||
|
|
||||||
|
_layerModel.Y = _yTweener.Value;
|
||||||
|
_layerModel.Height = _heightTweener.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateOpacity()
|
||||||
|
{
|
||||||
|
if (_layerModel.Properties.OpacityEaseTime < 0.001)
|
||||||
|
return;
|
||||||
|
|
||||||
// Opacity
|
// Opacity
|
||||||
if (Math.Abs(_layerModel.Opacity - _opacity) > 0.001)
|
if (Math.Abs(_layerModel.Opacity - _opacity) > 0.001)
|
||||||
{
|
{
|
||||||
_opacityTweener = new Tweener<float>(_opacity, (float) _layerModel.Opacity,
|
_opacityTweener = new Tweener<float>(_opacity, (float)_layerModel.Opacity,
|
||||||
_layerModel.Properties.OpacityEaseTime, GetEaseFunction(_layerModel.Properties.OpacityEase));
|
_layerModel.Properties.OpacityEaseTime, GetEaseFunction(_layerModel.Properties.OpacityEase));
|
||||||
}
|
}
|
||||||
|
|
||||||
_xTweener.Update(40);
|
|
||||||
_yTweener.Update(40);
|
|
||||||
_widthTweener.Update(40);
|
|
||||||
_heightTweener.Update(40);
|
|
||||||
_opacityTweener.Update(40);
|
_opacityTweener.Update(40);
|
||||||
|
|
||||||
StoreCurrentValues();
|
_opacity = (float)_layerModel.Opacity;
|
||||||
|
|
||||||
_layerModel.X = _xTweener.Value;
|
|
||||||
_layerModel.Y = _yTweener.Value;
|
|
||||||
_layerModel.Width = _widthTweener.Value;
|
|
||||||
_layerModel.Height = _heightTweener.Value;
|
|
||||||
_layerModel.Opacity = _opacityTweener.Value;
|
_layerModel.Opacity = _opacityTweener.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void StoreCurrentValues()
|
|
||||||
{
|
|
||||||
_x = (float) _layerModel.X;
|
|
||||||
_y = (float) _layerModel.Y;
|
|
||||||
_width = (float) _layerModel.Width;
|
|
||||||
_height = (float) _layerModel.Height;
|
|
||||||
_opacity = (float) _layerModel.Opacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static EaseFunc GetEaseFunction(string functionName)
|
private static EaseFunc GetEaseFunction(string functionName)
|
||||||
{
|
{
|
||||||
switch (functionName)
|
switch (functionName)
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using Artemis.Profiles.Layers.Abstract;
|
using Artemis.Profiles.Layers.Abstract;
|
||||||
|
using Artemis.ViewModels;
|
||||||
using Artemis.ViewModels.Profiles;
|
using Artemis.ViewModels.Profiles;
|
||||||
|
|
||||||
namespace Artemis.Profiles.Layers.Types.AmbientLight
|
namespace Artemis.Profiles.Layers.Types.AmbientLight
|
||||||
|
|||||||
@ -13,7 +13,7 @@ using Artemis.Profiles.Layers.Types.AmbientLight.Model.Extensions;
|
|||||||
using Artemis.Profiles.Layers.Types.AmbientLight.ScreenCapturing;
|
using Artemis.Profiles.Layers.Types.AmbientLight.ScreenCapturing;
|
||||||
using Artemis.Properties;
|
using Artemis.Properties;
|
||||||
using Artemis.Utilities;
|
using Artemis.Utilities;
|
||||||
using Artemis.ViewModels.Profiles;
|
using Artemis.ViewModels;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace Artemis.Profiles.Layers.Types.AmbientLight
|
namespace Artemis.Profiles.Layers.Types.AmbientLight
|
||||||
@ -25,6 +25,7 @@ namespace Artemis.Profiles.Layers.Types.AmbientLight
|
|||||||
public string Name => "Keyboard - Ambient Light";
|
public string Name => "Keyboard - Ambient Light";
|
||||||
public bool ShowInEdtor => true;
|
public bool ShowInEdtor => true;
|
||||||
public DrawType DrawType => DrawType.Keyboard;
|
public DrawType DrawType => DrawType.Keyboard;
|
||||||
|
public int DrawScale => 4;
|
||||||
|
|
||||||
[JsonIgnore] private AmbienceCreatorType? _lastAmbienceCreatorType;
|
[JsonIgnore] private AmbienceCreatorType? _lastAmbienceCreatorType;
|
||||||
|
|
||||||
@ -76,11 +77,7 @@ namespace Artemis.Profiles.Layers.Types.AmbientLight
|
|||||||
|
|
||||||
public void Draw(LayerModel layerModel, DrawingContext c)
|
public void Draw(LayerModel layerModel, DrawingContext c)
|
||||||
{
|
{
|
||||||
var rect = new Rect(layerModel.Properties.X*4,
|
var rect = layerModel.LayerRect(DrawScale);
|
||||||
layerModel.Properties.Y*4,
|
|
||||||
layerModel.Properties.Width*4,
|
|
||||||
layerModel.Properties.Height*4);
|
|
||||||
|
|
||||||
c.DrawRectangle(((AmbientLightPropertiesModel) layerModel.Properties).AmbientLightBrush, null, rect);
|
c.DrawRectangle(((AmbientLightPropertiesModel) layerModel.Properties).AmbientLightBrush, null, rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,216 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Timers;
|
||||||
|
using CSCore;
|
||||||
|
using CSCore.CoreAudioAPI;
|
||||||
|
using CSCore.DSP;
|
||||||
|
using CSCore.SoundIn;
|
||||||
|
using CSCore.SoundOut;
|
||||||
|
using CSCore.Streams;
|
||||||
|
using Ninject.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace Artemis.Profiles.Layers.Types.Audio.AudioCapturing
|
||||||
|
{
|
||||||
|
public class AudioCapture
|
||||||
|
{
|
||||||
|
private const FftSize FftSize = CSCore.DSP.FftSize.Fft1024;
|
||||||
|
private readonly Timer _volumeTimer;
|
||||||
|
private readonly double[] _volumeValues;
|
||||||
|
private readonly Timer _disableTimer;
|
||||||
|
private bool _mayStop;
|
||||||
|
private SingleSpectrum _singleSpectrum;
|
||||||
|
private ISoundIn _soundIn;
|
||||||
|
private GainSource _source;
|
||||||
|
private BasicSpectrumProvider _spectrumProvider;
|
||||||
|
private GainSource _volume;
|
||||||
|
private int _volumeIndex;
|
||||||
|
|
||||||
|
public AudioCapture(ILogger logger, MMDevice device, MmDeviceType type)
|
||||||
|
{
|
||||||
|
Logger = logger;
|
||||||
|
Device = device;
|
||||||
|
Type = type;
|
||||||
|
DesiredAverage = 0.75;
|
||||||
|
|
||||||
|
_volumeValues = new double[5];
|
||||||
|
_volumeIndex = 0;
|
||||||
|
_disableTimer = new Timer(1000);
|
||||||
|
_disableTimer.Elapsed += CheckStop;
|
||||||
|
_volumeTimer = new Timer(200);
|
||||||
|
_volumeTimer.Elapsed += VolumeTimerOnElapsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ILogger Logger { get; }
|
||||||
|
public MMDevice Device { get; }
|
||||||
|
public MmDeviceType Type { get; }
|
||||||
|
public double DesiredAverage { get; set; }
|
||||||
|
|
||||||
|
public float Volume
|
||||||
|
{
|
||||||
|
get { return _volume.Volume; }
|
||||||
|
set { _volume.Volume = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Running { get; set; }
|
||||||
|
|
||||||
|
private void VolumeTimerOnElapsed(object sender, ElapsedEventArgs e)
|
||||||
|
{
|
||||||
|
if (Volume <= 0)
|
||||||
|
Volume = 1;
|
||||||
|
|
||||||
|
var currentValue = _singleSpectrum.GetValue();
|
||||||
|
if (currentValue == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_volumeValues[_volumeIndex] = currentValue.Value;
|
||||||
|
|
||||||
|
if (_volumeIndex == 4)
|
||||||
|
{
|
||||||
|
_volumeIndex = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_volumeIndex++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var averageVolume = _volumeValues.Average();
|
||||||
|
// Don't adjust when there is virtually no audio
|
||||||
|
if (averageVolume < 0.01)
|
||||||
|
return;
|
||||||
|
// Don't bother when the volume with within a certain marigin
|
||||||
|
if (averageVolume > DesiredAverage - 0.1 && averageVolume < DesiredAverage + 0.1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (averageVolume < DesiredAverage && Volume < 50)
|
||||||
|
{
|
||||||
|
Logger.Trace("averageVolume:{0} | DesiredAverage:{1} | Volume:{2} so increase.", currentValue,
|
||||||
|
DesiredAverage, Volume);
|
||||||
|
Volume++;
|
||||||
|
}
|
||||||
|
else if (Volume > 1)
|
||||||
|
{
|
||||||
|
Logger.Trace("averageVolume:{0} | DesiredAverage:{1} | Volume:{2} so decrease.", currentValue,
|
||||||
|
DesiredAverage, Volume);
|
||||||
|
Volume--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public LineSpectrum GetLineSpectrum(int barCount, ScalingStrategy scalingStrategy)
|
||||||
|
{
|
||||||
|
if (_spectrumProvider == null)
|
||||||
|
return null;
|
||||||
|
return new LineSpectrum(FftSize)
|
||||||
|
{
|
||||||
|
SpectrumProvider = _spectrumProvider,
|
||||||
|
UseAverage = true,
|
||||||
|
BarCount = barCount,
|
||||||
|
IsXLogScale = true,
|
||||||
|
ScalingStrategy = scalingStrategy
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Keeps the audio capture active, when not called for longer than 1 sec the capture will
|
||||||
|
/// stop capturing until Pulse is called again
|
||||||
|
/// </summary>
|
||||||
|
public void Pulse()
|
||||||
|
{
|
||||||
|
_mayStop = false;
|
||||||
|
if (!Running)
|
||||||
|
Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CheckStop(object sender, ElapsedEventArgs e)
|
||||||
|
{
|
||||||
|
if (_mayStop)
|
||||||
|
{
|
||||||
|
Logger.Debug("Stopping idle audio capture for device: {0}", Device?.FriendlyName ?? "default");
|
||||||
|
Stop();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_mayStop = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Start()
|
||||||
|
{
|
||||||
|
Logger.Debug("Starting audio capture for device: {0}", Device?.FriendlyName ?? "default");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Stop();
|
||||||
|
|
||||||
|
if (Type == MmDeviceType.Input)
|
||||||
|
{
|
||||||
|
_soundIn = Device != null
|
||||||
|
? new WasapiCapture {Device = Device}
|
||||||
|
: new WasapiCapture();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_soundIn = Device != null
|
||||||
|
? new WasapiLoopbackCapture {Device = Device}
|
||||||
|
: new WasapiLoopbackCapture();
|
||||||
|
}
|
||||||
|
|
||||||
|
_soundIn.Initialize();
|
||||||
|
|
||||||
|
var soundInSource = new SoundInSource(_soundIn);
|
||||||
|
_source = soundInSource.ToSampleSource().AppendSource(x => new GainSource(x), out _volume);
|
||||||
|
|
||||||
|
// create a spectrum provider which provides fft data based on some input
|
||||||
|
_spectrumProvider = new BasicSpectrumProvider(_source.WaveFormat.Channels, _source.WaveFormat.SampleRate,
|
||||||
|
FftSize);
|
||||||
|
|
||||||
|
// the SingleBlockNotificationStream is used to intercept the played samples
|
||||||
|
var notificationSource = new SingleBlockNotificationStream(_source);
|
||||||
|
// pass the intercepted samples as input data to the spectrumprovider (which will calculate a fft based on them)
|
||||||
|
notificationSource.SingleBlockRead += (s, a) => _spectrumProvider.Add(a.Left, a.Right);
|
||||||
|
|
||||||
|
var waveSource = notificationSource.ToWaveSource(16);
|
||||||
|
// We need to read from our source otherwise SingleBlockRead is never called and our spectrum provider is not populated
|
||||||
|
var buffer = new byte[waveSource.WaveFormat.BytesPerSecond / 2];
|
||||||
|
soundInSource.DataAvailable += (s, aEvent) =>
|
||||||
|
{
|
||||||
|
while (waveSource.Read(buffer, 0, buffer.Length) > 0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
_singleSpectrum = new SingleSpectrum(FftSize, _spectrumProvider);
|
||||||
|
_mayStop = false;
|
||||||
|
|
||||||
|
_disableTimer.Start();
|
||||||
|
_volumeTimer.Start();
|
||||||
|
_soundIn.Start();
|
||||||
|
|
||||||
|
Running = true;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Logger.Warn(e, "Failed to start WASAPI audio capture");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Stop()
|
||||||
|
{
|
||||||
|
Running = false;
|
||||||
|
|
||||||
|
|
||||||
|
if (_soundIn != null)
|
||||||
|
{
|
||||||
|
_soundIn.Stop();
|
||||||
|
_soundIn.Dispose();
|
||||||
|
_soundIn = null;
|
||||||
|
}
|
||||||
|
if (_source != null)
|
||||||
|
{
|
||||||
|
_source.Dispose();
|
||||||
|
_source = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
_disableTimer.Stop();
|
||||||
|
_volumeTimer.Stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,133 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using NAudio.CoreAudioApi;
|
|
||||||
using NAudio.Dsp;
|
|
||||||
using NAudio.Wave;
|
|
||||||
using Ninject.Extensions.Logging;
|
|
||||||
|
|
||||||
namespace Artemis.Profiles.Layers.Types.Audio.AudioCapturing
|
|
||||||
{
|
|
||||||
public class AudioCaptureManager
|
|
||||||
{
|
|
||||||
private readonly SampleAggregator _sampleAggregator = new SampleAggregator(1024);
|
|
||||||
private readonly WasapiLoopbackCapture _waveIn;
|
|
||||||
private Complex[] _fft;
|
|
||||||
private DateTime _lastAudioUpdate;
|
|
||||||
private DateTime _lastRequest;
|
|
||||||
|
|
||||||
public AudioCaptureManager(ILogger logger)
|
|
||||||
{
|
|
||||||
Logger = logger;
|
|
||||||
Device = new MMDeviceEnumerator().EnumerateAudioEndPoints(DataFlow.All, DeviceState.Active).FirstOrDefault();
|
|
||||||
|
|
||||||
_sampleAggregator.FftCalculated += FftCalculated;
|
|
||||||
_sampleAggregator.PerformFFT = true;
|
|
||||||
|
|
||||||
// Start listening for sound data
|
|
||||||
_waveIn = new WasapiLoopbackCapture();
|
|
||||||
_waveIn.DataAvailable += OnDataAvailable;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ILogger Logger { get; set; }
|
|
||||||
public MMDevice Device { get; set; }
|
|
||||||
|
|
||||||
public bool Running { get; set; }
|
|
||||||
|
|
||||||
public void Start()
|
|
||||||
{
|
|
||||||
if (Running)
|
|
||||||
return;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_waveIn.StartRecording();
|
|
||||||
Running = true;
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Logger.Warn(e, "Failed to start WASAPI audio capture");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Stop()
|
|
||||||
{
|
|
||||||
if (!Running)
|
|
||||||
return;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_waveIn.StopRecording();
|
|
||||||
Running = false;
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Logger.Warn(e, "Failed to start WASAPI audio capture");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void FftCalculated(object sender, FftEventArgs e)
|
|
||||||
{
|
|
||||||
_fft = e.Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnDataAvailable(object sender, WaveInEventArgs e)
|
|
||||||
{
|
|
||||||
if (DateTime.Now - _lastAudioUpdate < TimeSpan.FromMilliseconds(40))
|
|
||||||
return;
|
|
||||||
if (DateTime.Now - _lastRequest > TimeSpan.FromSeconds(5))
|
|
||||||
{
|
|
||||||
Stop();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_lastAudioUpdate = DateTime.Now;
|
|
||||||
|
|
||||||
var buffer = e.Buffer;
|
|
||||||
var bytesRecorded = e.BytesRecorded;
|
|
||||||
var bufferIncrement = _waveIn.WaveFormat.BlockAlign;
|
|
||||||
|
|
||||||
for (var index = 0; index < bytesRecorded; index += bufferIncrement)
|
|
||||||
{
|
|
||||||
var sample32 = BitConverter.ToSingle(buffer, index);
|
|
||||||
_sampleAggregator.Add(sample32);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<byte> GetSpectrumData(int lines)
|
|
||||||
{
|
|
||||||
_lastRequest = DateTime.Now;
|
|
||||||
if (!Running)
|
|
||||||
Start();
|
|
||||||
|
|
||||||
var spectrumData = new List<byte>();
|
|
||||||
|
|
||||||
if (_fft == null)
|
|
||||||
return spectrumData;
|
|
||||||
|
|
||||||
int x;
|
|
||||||
var b0 = 0;
|
|
||||||
|
|
||||||
for (x = 0; x < lines; x++)
|
|
||||||
{
|
|
||||||
float peak = 0;
|
|
||||||
var b1 = (int) Math.Pow(2, x*10.0/(lines - 1));
|
|
||||||
if (b1 > 1023)
|
|
||||||
b1 = 1023;
|
|
||||||
if (b1 <= b0)
|
|
||||||
b1 = b0 + 1;
|
|
||||||
for (; b0 < b1; b0++)
|
|
||||||
if (peak < _fft[1 + b0].X)
|
|
||||||
peak = _fft[1 + b0].X;
|
|
||||||
var y = (int) (Math.Sqrt(peak)*3*255 - 4);
|
|
||||||
if (y > 255)
|
|
||||||
y = 255;
|
|
||||||
if (y < 0)
|
|
||||||
y = 0;
|
|
||||||
spectrumData.Add((byte) y);
|
|
||||||
}
|
|
||||||
|
|
||||||
return spectrumData;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -0,0 +1,54 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using CSCore.DSP;
|
||||||
|
|
||||||
|
namespace Artemis.Profiles.Layers.Types.Audio.AudioCapturing
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// BasicSpectrumProvider
|
||||||
|
/// </summary>
|
||||||
|
public class BasicSpectrumProvider : FftProvider, ISpectrumProvider
|
||||||
|
{
|
||||||
|
private readonly List<object> _contexts = new List<object>();
|
||||||
|
private readonly int _sampleRate;
|
||||||
|
|
||||||
|
public BasicSpectrumProvider(int channels, int sampleRate, FftSize fftSize)
|
||||||
|
: base(channels, fftSize)
|
||||||
|
{
|
||||||
|
if (sampleRate <= 0)
|
||||||
|
throw new ArgumentOutOfRangeException("sampleRate");
|
||||||
|
_sampleRate = sampleRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetFftBandIndex(float frequency)
|
||||||
|
{
|
||||||
|
var fftSize = (int) FftSize;
|
||||||
|
var f = _sampleRate / 2.0;
|
||||||
|
// ReSharper disable once PossibleLossOfFraction
|
||||||
|
return (int) (frequency / f * (fftSize / 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool GetFftData(float[] fftResultBuffer, object context)
|
||||||
|
{
|
||||||
|
if (_contexts.Contains(context))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
_contexts.Add(context);
|
||||||
|
GetFftData(fftResultBuffer);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Add(float[] samples, int count)
|
||||||
|
{
|
||||||
|
base.Add(samples, count);
|
||||||
|
if (count > 0)
|
||||||
|
_contexts.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Add(float left, float right)
|
||||||
|
{
|
||||||
|
base.Add(left, right);
|
||||||
|
_contexts.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,17 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using NAudio.Dsp;
|
|
||||||
|
|
||||||
namespace Artemis.Profiles.Layers.Types.Audio.AudioCapturing
|
|
||||||
{
|
|
||||||
public class FftEventArgs : EventArgs
|
|
||||||
{
|
|
||||||
[DebuggerStepThrough]
|
|
||||||
public FftEventArgs(Complex[] result)
|
|
||||||
{
|
|
||||||
Result = result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Complex[] Result { get; private set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
namespace Artemis.Profiles.Layers.Types.Audio.AudioCapturing
|
||||||
|
{
|
||||||
|
public interface ISpectrumProvider
|
||||||
|
{
|
||||||
|
bool GetFftData(float[] fftBuffer, object context);
|
||||||
|
int GetFftBandIndex(float frequency);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Windows;
|
||||||
|
using CSCore.DSP;
|
||||||
|
|
||||||
|
namespace Artemis.Profiles.Layers.Types.Audio.AudioCapturing
|
||||||
|
{
|
||||||
|
public class LineSpectrum : SpectrumBase
|
||||||
|
{
|
||||||
|
private int _barCount;
|
||||||
|
|
||||||
|
public LineSpectrum(FftSize fftSize)
|
||||||
|
{
|
||||||
|
FftSize = fftSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int BarCount
|
||||||
|
{
|
||||||
|
get { return _barCount; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value <= 0)
|
||||||
|
throw new ArgumentOutOfRangeException("value");
|
||||||
|
_barCount = value;
|
||||||
|
SpectrumResolution = value;
|
||||||
|
UpdateFrequencyMapping();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<double> GetLineValues(double height)
|
||||||
|
{
|
||||||
|
var fftBuffer = new float[(int) FftSize];
|
||||||
|
|
||||||
|
// get the fft result from the spectrum provider
|
||||||
|
if (!SpectrumProvider.GetFftData(fftBuffer, this))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var spectrumPoints = CalculateSpectrumPoints(height, fftBuffer);
|
||||||
|
return spectrumPoints?.Select(s => s.Value).ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,52 +0,0 @@
|
|||||||
using System;
|
|
||||||
using NAudio.Dsp;
|
|
||||||
|
|
||||||
namespace Artemis.Profiles.Layers.Types.Audio.AudioCapturing
|
|
||||||
{
|
|
||||||
public class SampleAggregator
|
|
||||||
{
|
|
||||||
private readonly FftEventArgs fftArgs;
|
|
||||||
|
|
||||||
// This Complex is NAudio's own!
|
|
||||||
private readonly Complex[] fftBuffer;
|
|
||||||
private readonly int fftLength;
|
|
||||||
private readonly int m;
|
|
||||||
private int fftPos;
|
|
||||||
|
|
||||||
public SampleAggregator(int fftLength)
|
|
||||||
{
|
|
||||||
if (!IsPowerOfTwo(fftLength))
|
|
||||||
throw new ArgumentException("FFT Length must be a power of two");
|
|
||||||
m = (int) Math.Log(fftLength, 2.0);
|
|
||||||
this.fftLength = fftLength;
|
|
||||||
fftBuffer = new Complex[fftLength];
|
|
||||||
fftArgs = new FftEventArgs(fftBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool PerformFFT { get; set; }
|
|
||||||
// FFT
|
|
||||||
public event EventHandler<FftEventArgs> FftCalculated;
|
|
||||||
|
|
||||||
private bool IsPowerOfTwo(int x)
|
|
||||||
{
|
|
||||||
return (x & (x - 1)) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Add(float value)
|
|
||||||
{
|
|
||||||
if (PerformFFT && FftCalculated != null)
|
|
||||||
{
|
|
||||||
// Remember the window function! There are many others as well.
|
|
||||||
fftBuffer[fftPos].X = (float) (value * FastFourierTransform.HammingWindow(fftPos, fftLength));
|
|
||||||
fftBuffer[fftPos].Y = 0; // This is always zero with audio.
|
|
||||||
fftPos++;
|
|
||||||
if (fftPos >= fftLength)
|
|
||||||
{
|
|
||||||
fftPos = 0;
|
|
||||||
FastFourierTransform.FFT(true, m, fftBuffer);
|
|
||||||
FftCalculated(this, fftArgs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Artemis.Profiles.Layers.Models;
|
||||||
|
using CSCore.DSP;
|
||||||
|
|
||||||
|
namespace Artemis.Profiles.Layers.Types.Audio.AudioCapturing
|
||||||
|
{
|
||||||
|
public sealed class SingleSpectrum : SpectrumBase
|
||||||
|
{
|
||||||
|
public SingleSpectrum(FftSize fftSize, ISpectrumProvider spectrumProvider)
|
||||||
|
{
|
||||||
|
SpectrumProvider = spectrumProvider;
|
||||||
|
SpectrumResolution = 1;
|
||||||
|
FftSize = fftSize;
|
||||||
|
|
||||||
|
UpdateFrequencyMapping();
|
||||||
|
}
|
||||||
|
|
||||||
|
public double? GetValue()
|
||||||
|
{
|
||||||
|
var fftBuffer = new float[(int)FftSize];
|
||||||
|
|
||||||
|
// get the fft result from the spectrum provider
|
||||||
|
if (SpectrumProvider == null || !SpectrumProvider.GetFftData(fftBuffer, this))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var spectrumPoints = CalculateSpectrumPoints(1, fftBuffer);
|
||||||
|
return spectrumPoints[0].Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,189 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using CSCore;
|
||||||
|
using CSCore.DSP;
|
||||||
|
|
||||||
|
namespace Artemis.Profiles.Layers.Types.Audio.AudioCapturing
|
||||||
|
{
|
||||||
|
public class SpectrumBase
|
||||||
|
{
|
||||||
|
private const int ScaleFactorLinear = 9;
|
||||||
|
protected const int ScaleFactorSqr = 2;
|
||||||
|
protected const double MinDbValue = -90;
|
||||||
|
protected const double MaxDbValue = 0;
|
||||||
|
protected const double DbScale = MaxDbValue - MinDbValue;
|
||||||
|
|
||||||
|
private int _fftSize;
|
||||||
|
private bool _isXLogScale;
|
||||||
|
private int _maxFftIndex;
|
||||||
|
private int _maximumFrequency = 20000;
|
||||||
|
private int _maximumFrequencyIndex;
|
||||||
|
private int _minimumFrequency = 20; //Default spectrum from 20Hz to 20kHz
|
||||||
|
private int _minimumFrequencyIndex;
|
||||||
|
private int[] _spectrumIndexMax;
|
||||||
|
private int[] _spectrumLogScaleIndexMax;
|
||||||
|
private ISpectrumProvider _spectrumProvider;
|
||||||
|
|
||||||
|
protected int SpectrumResolution;
|
||||||
|
|
||||||
|
public int MaximumFrequency
|
||||||
|
{
|
||||||
|
get { return _maximumFrequency; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value <= MinimumFrequency)
|
||||||
|
throw new ArgumentOutOfRangeException("value",
|
||||||
|
"Value must not be less or equal the MinimumFrequency.");
|
||||||
|
_maximumFrequency = value;
|
||||||
|
UpdateFrequencyMapping();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int MinimumFrequency
|
||||||
|
{
|
||||||
|
get { return _minimumFrequency; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value < 0)
|
||||||
|
throw new ArgumentOutOfRangeException("value");
|
||||||
|
_minimumFrequency = value;
|
||||||
|
UpdateFrequencyMapping();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Browsable(false)]
|
||||||
|
public ISpectrumProvider SpectrumProvider
|
||||||
|
{
|
||||||
|
get { return _spectrumProvider; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
throw new ArgumentNullException("value");
|
||||||
|
_spectrumProvider = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsXLogScale
|
||||||
|
{
|
||||||
|
get { return _isXLogScale; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_isXLogScale = value;
|
||||||
|
UpdateFrequencyMapping();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScalingStrategy ScalingStrategy { get; set; }
|
||||||
|
|
||||||
|
public bool UseAverage { get; set; }
|
||||||
|
|
||||||
|
[Browsable(false)]
|
||||||
|
public FftSize FftSize
|
||||||
|
{
|
||||||
|
get { return (FftSize) _fftSize; }
|
||||||
|
protected set
|
||||||
|
{
|
||||||
|
if ((int) Math.Log((int) value, 2) % 1 != 0)
|
||||||
|
throw new ArgumentOutOfRangeException("value");
|
||||||
|
|
||||||
|
_fftSize = (int) value;
|
||||||
|
_maxFftIndex = _fftSize / 2 - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void UpdateFrequencyMapping()
|
||||||
|
{
|
||||||
|
_maximumFrequencyIndex = Math.Min(_spectrumProvider.GetFftBandIndex(MaximumFrequency) + 1, _maxFftIndex);
|
||||||
|
_minimumFrequencyIndex = Math.Min(_spectrumProvider.GetFftBandIndex(MinimumFrequency), _maxFftIndex);
|
||||||
|
|
||||||
|
var actualResolution = SpectrumResolution;
|
||||||
|
|
||||||
|
var indexCount = _maximumFrequencyIndex - _minimumFrequencyIndex;
|
||||||
|
var linearIndexBucketSize = Math.Round(indexCount / (double) actualResolution, 3);
|
||||||
|
|
||||||
|
_spectrumIndexMax = _spectrumIndexMax.CheckBuffer(actualResolution, true);
|
||||||
|
_spectrumLogScaleIndexMax = _spectrumLogScaleIndexMax.CheckBuffer(actualResolution, true);
|
||||||
|
|
||||||
|
var maxLog = Math.Log(actualResolution, actualResolution);
|
||||||
|
for (var i = 1; i < actualResolution; i++)
|
||||||
|
{
|
||||||
|
var logIndex =
|
||||||
|
(int) ((maxLog - Math.Log(actualResolution + 1 - i, actualResolution + 1)) * indexCount) +
|
||||||
|
_minimumFrequencyIndex;
|
||||||
|
|
||||||
|
_spectrumIndexMax[i - 1] = _minimumFrequencyIndex + (int) (i * linearIndexBucketSize);
|
||||||
|
_spectrumLogScaleIndexMax[i - 1] = logIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actualResolution > 0)
|
||||||
|
_spectrumIndexMax[_spectrumIndexMax.Length - 1] =
|
||||||
|
_spectrumLogScaleIndexMax[_spectrumLogScaleIndexMax.Length - 1] = _maximumFrequencyIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual SpectrumPointData[] CalculateSpectrumPoints(double maxValue, float[] fftBuffer)
|
||||||
|
{
|
||||||
|
var dataPoints = new List<SpectrumPointData>();
|
||||||
|
|
||||||
|
double value0 = 0, value = 0;
|
||||||
|
double lastValue = 0;
|
||||||
|
var actualMaxValue = maxValue;
|
||||||
|
var spectrumPointIndex = 0;
|
||||||
|
|
||||||
|
for (var i = _minimumFrequencyIndex; i <= _maximumFrequencyIndex; i++)
|
||||||
|
{
|
||||||
|
switch (ScalingStrategy)
|
||||||
|
{
|
||||||
|
case ScalingStrategy.Decibel:
|
||||||
|
value0 = (20 * Math.Log10(fftBuffer[i]) - MinDbValue) / DbScale * actualMaxValue;
|
||||||
|
break;
|
||||||
|
case ScalingStrategy.Linear:
|
||||||
|
value0 = fftBuffer[i] * ScaleFactorLinear * actualMaxValue;
|
||||||
|
break;
|
||||||
|
case ScalingStrategy.Sqrt:
|
||||||
|
value0 = Math.Sqrt(fftBuffer[i]) * ScaleFactorSqr * actualMaxValue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
var recalc = true;
|
||||||
|
|
||||||
|
value = Math.Max(0, Math.Max(value0, value));
|
||||||
|
|
||||||
|
while (spectrumPointIndex <= _spectrumIndexMax.Length - 1 &&
|
||||||
|
i ==
|
||||||
|
(IsXLogScale
|
||||||
|
? _spectrumLogScaleIndexMax[spectrumPointIndex]
|
||||||
|
: _spectrumIndexMax[spectrumPointIndex]))
|
||||||
|
{
|
||||||
|
if (!recalc)
|
||||||
|
value = lastValue;
|
||||||
|
|
||||||
|
if (value > maxValue)
|
||||||
|
value = maxValue;
|
||||||
|
|
||||||
|
if (UseAverage && spectrumPointIndex > 0)
|
||||||
|
value = (lastValue + value) / 2.0;
|
||||||
|
|
||||||
|
dataPoints.Add(new SpectrumPointData {SpectrumPointIndex = spectrumPointIndex, Value = value});
|
||||||
|
|
||||||
|
lastValue = value;
|
||||||
|
value = 0.0;
|
||||||
|
spectrumPointIndex++;
|
||||||
|
recalc = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//value = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dataPoints.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
[DebuggerDisplay("{Value}")]
|
||||||
|
protected struct SpectrumPointData
|
||||||
|
{
|
||||||
|
public int SpectrumPointIndex;
|
||||||
|
public double Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -9,9 +9,23 @@ namespace Artemis.Profiles.Layers.Types.Audio
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Sensitivity { get; set; }
|
[DefaultValue(MmDeviceType.Ouput)]
|
||||||
public double FadeSpeed { get; set; }
|
public MmDeviceType DeviceType { get; set; }
|
||||||
|
|
||||||
|
[DefaultValue("Default")]
|
||||||
|
public string Device { get; set; }
|
||||||
|
|
||||||
|
[DefaultValue(Direction.BottomToTop)]
|
||||||
public Direction Direction { get; set; }
|
public Direction Direction { get; set; }
|
||||||
|
|
||||||
|
[DefaultValue(ScalingStrategy.Decibel)]
|
||||||
|
public ScalingStrategy ScalingStrategy { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum MmDeviceType
|
||||||
|
{
|
||||||
|
[Description("Ouput")] Ouput,
|
||||||
|
[Description("Input")] Input
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum Direction
|
public enum Direction
|
||||||
@ -21,4 +35,11 @@ namespace Artemis.Profiles.Layers.Types.Audio
|
|||||||
[Description("Left to right")] LeftToRight,
|
[Description("Left to right")] LeftToRight,
|
||||||
[Description("Right to left")] RightToLeft
|
[Description("Right to left")] RightToLeft
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum ScalingStrategy
|
||||||
|
{
|
||||||
|
[Description("Decibel")] Decibel,
|
||||||
|
[Description("Linear")] Linear,
|
||||||
|
[Description("Square root")] Sqrt
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -11,6 +11,13 @@
|
|||||||
d:DesignHeight="600" d:DesignWidth="500">
|
d:DesignHeight="600" d:DesignWidth="500">
|
||||||
<UserControl.Resources>
|
<UserControl.Resources>
|
||||||
<converters:EnumDescriptionConverter x:Key="HEnumDescriptionConverter" />
|
<converters:EnumDescriptionConverter x:Key="HEnumDescriptionConverter" />
|
||||||
|
<ObjectDataProvider MethodName="GetValues"
|
||||||
|
ObjectType="{x:Type system:Enum}"
|
||||||
|
x:Key="MmDeviceTypeEnumValues">
|
||||||
|
<ObjectDataProvider.MethodParameters>
|
||||||
|
<x:Type TypeName="properties:MmDeviceType" />
|
||||||
|
</ObjectDataProvider.MethodParameters>
|
||||||
|
</ObjectDataProvider>
|
||||||
<ObjectDataProvider MethodName="GetValues"
|
<ObjectDataProvider MethodName="GetValues"
|
||||||
ObjectType="{x:Type system:Enum}"
|
ObjectType="{x:Type system:Enum}"
|
||||||
x:Key="DirectionEnumValues">
|
x:Key="DirectionEnumValues">
|
||||||
@ -55,21 +62,22 @@
|
|||||||
Value="{Binding Path=LayerModel.Properties.AnimationSpeed, Mode=TwoWay}" Minimum="0.05" Maximum="3"
|
Value="{Binding Path=LayerModel.Properties.AnimationSpeed, Mode=TwoWay}" Minimum="0.05" Maximum="3"
|
||||||
SmallChange="0" IsSnapToTickEnabled="True" Margin="10,12,10,2" Height="24" />
|
SmallChange="0" IsSnapToTickEnabled="True" Margin="10,12,10,2" Height="24" />
|
||||||
|
|
||||||
<!-- Volume sensitivity -->
|
<!-- Device type -->
|
||||||
<TextBlock Grid.Row="1" Grid.Column="0" Margin="10,13,10,10" FontSize="13.333" Text="Volume sensitivity:"
|
<TextBlock Grid.Row="1" Grid.Column="0" Margin="10,13,10,10" FontSize="13.333" Text="Device type:"
|
||||||
Height="18" VerticalAlignment="Top" />
|
Height="18" VerticalAlignment="Top" />
|
||||||
<Slider x:Name="Scale" Grid.Row="1" Grid.Column="1" VerticalAlignment="Top"
|
<ComboBox Grid.Row="1" Grid.Column="1" ItemsSource="{Binding Source={StaticResource MmDeviceTypeEnumValues}}"
|
||||||
Value="{Binding Path=LayerModel.Properties.Sensitivity, Mode=TwoWay}" Margin="10,12,10,2" Height="24"
|
Margin="10,10,10,0" SelectedItem="{Binding Path=DeviceType}"
|
||||||
TickPlacement="BottomRight" TickFrequency="1" Minimum="1" Maximum="10" SmallChange="1"
|
VerticalAlignment="Top" Height="22">
|
||||||
IsSnapToTickEnabled="True" />
|
<ComboBox.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
<!-- Fade-out speed -->
|
<TextBlock Text="{Binding Converter={StaticResource HEnumDescriptionConverter}}" />
|
||||||
<TextBlock Grid.Row="1" Grid.Column="2" Margin="10,13,10,10" FontSize="13.333" Text="Fade-out speed:"
|
</DataTemplate>
|
||||||
|
</ComboBox.ItemTemplate>
|
||||||
|
</ComboBox>
|
||||||
|
<!-- Device -->
|
||||||
|
<TextBlock Grid.Row="1" Grid.Column="2" Margin="10,13,10,10" FontSize="13.333" Text="Device:"
|
||||||
VerticalAlignment="Top" Height="18" />
|
VerticalAlignment="Top" Height="18" />
|
||||||
<Slider Grid.Row="1" Grid.Column="3" VerticalAlignment="Top"
|
<ComboBox Grid.Row="1" Grid.Column="3" x:Name="Devices" Margin="10,10,10,0" VerticalAlignment="Top" />
|
||||||
Value="{Binding Path=LayerModel.Properties.FadeSpeed, Mode=TwoWay}" Margin="10,12,10,2"
|
|
||||||
Height="24" TickPlacement="BottomRight" TickFrequency="0.1" Minimum="0.1" Maximum="1" SmallChange="0.1"
|
|
||||||
IsSnapToTickEnabled="True" />
|
|
||||||
|
|
||||||
<!-- Colors -->
|
<!-- Colors -->
|
||||||
<StackPanel Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" Orientation="Horizontal" x:Name="ShowBrush">
|
<StackPanel Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" Orientation="Horizontal" x:Name="ShowBrush">
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Artemis.Profiles.Layers.Abstract;
|
using Artemis.Profiles.Layers.Abstract;
|
||||||
using Artemis.Profiles.Layers.Interfaces;
|
using Artemis.Profiles.Layers.Interfaces;
|
||||||
using Artemis.ViewModels.Profiles;
|
using Artemis.ViewModels;
|
||||||
using Caliburn.Micro;
|
using Caliburn.Micro;
|
||||||
|
using CSCore.CoreAudioAPI;
|
||||||
|
|
||||||
namespace Artemis.Profiles.Layers.Types.Audio
|
namespace Artemis.Profiles.Layers.Types.Audio
|
||||||
{
|
{
|
||||||
@ -13,12 +14,18 @@ namespace Artemis.Profiles.Layers.Types.Audio
|
|||||||
public AudioPropertiesViewModel(LayerEditorViewModel editorVm) : base(editorVm)
|
public AudioPropertiesViewModel(LayerEditorViewModel editorVm) : base(editorVm)
|
||||||
{
|
{
|
||||||
LayerAnimations = new BindableCollection<ILayerAnimation>(editorVm.LayerAnimations);
|
LayerAnimations = new BindableCollection<ILayerAnimation>(editorVm.LayerAnimations);
|
||||||
|
Devices = new BindableCollection<string>();
|
||||||
SelectedLayerAnimation =
|
SelectedLayerAnimation =
|
||||||
LayerAnimations.FirstOrDefault(l => l.Name == editorVm.ProposedLayer.LayerAnimation?.Name) ??
|
LayerAnimations.FirstOrDefault(l => l.Name == editorVm.ProposedLayer.LayerAnimation?.Name) ??
|
||||||
LayerAnimations.First(l => l.Name == "None");
|
LayerAnimations.First(l => l.Name == "None");
|
||||||
|
|
||||||
|
SetupAudioSelection();
|
||||||
|
if (SelectedDevice == null)
|
||||||
|
SelectedDevice = Devices.First();
|
||||||
}
|
}
|
||||||
|
|
||||||
public BindableCollection<ILayerAnimation> LayerAnimations { get; set; }
|
public BindableCollection<ILayerAnimation> LayerAnimations { get; set; }
|
||||||
|
public BindableCollection<string> Devices { get; set; }
|
||||||
|
|
||||||
public ILayerAnimation SelectedLayerAnimation
|
public ILayerAnimation SelectedLayerAnimation
|
||||||
{
|
{
|
||||||
@ -31,6 +38,45 @@ namespace Artemis.Profiles.Layers.Types.Audio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MmDeviceType DeviceType
|
||||||
|
{
|
||||||
|
get { return ((AudioPropertiesModel) LayerModel.Properties).DeviceType; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == ((AudioPropertiesModel) LayerModel.Properties).DeviceType) return;
|
||||||
|
((AudioPropertiesModel) LayerModel.Properties).DeviceType = value;
|
||||||
|
SetupAudioSelection();
|
||||||
|
SelectedDevice = Devices.First();
|
||||||
|
NotifyOfPropertyChange(() => DeviceType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string SelectedDevice
|
||||||
|
{
|
||||||
|
get { return ((AudioPropertiesModel) LayerModel.Properties).Device; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == ((AudioPropertiesModel) LayerModel.Properties).Device) return;
|
||||||
|
((AudioPropertiesModel) LayerModel.Properties).Device = value;
|
||||||
|
NotifyOfPropertyChange(() => SelectedDevice);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetupAudioSelection()
|
||||||
|
{
|
||||||
|
var properties = (AudioPropertiesModel) LayerModel.Properties;
|
||||||
|
|
||||||
|
Devices.Clear();
|
||||||
|
Devices.Add("Default");
|
||||||
|
|
||||||
|
// Select the proper devices and make sure they are unique
|
||||||
|
Devices.AddRange(properties.DeviceType == MmDeviceType.Input
|
||||||
|
? MMDeviceEnumerator.EnumerateDevices(DataFlow.Capture, DeviceState.Active)
|
||||||
|
.Select(d => d.FriendlyName).GroupBy(d => d).Select(g => g.First())
|
||||||
|
: MMDeviceEnumerator.EnumerateDevices(DataFlow.Render, DeviceState.Active)
|
||||||
|
.Select(d => d.FriendlyName).GroupBy(d => d).Select(g => g.First()));
|
||||||
|
}
|
||||||
|
|
||||||
public override void ApplyProperties()
|
public override void ApplyProperties()
|
||||||
{
|
{
|
||||||
LayerModel.Properties.Brush = Brush;
|
LayerModel.Properties.Brush = Brush;
|
||||||
|
|||||||
@ -1,42 +1,50 @@
|
|||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
|
using Artemis.Events;
|
||||||
|
using Artemis.Managers;
|
||||||
using Artemis.Modules.Abstract;
|
using Artemis.Modules.Abstract;
|
||||||
using Artemis.Profiles.Layers.Abstract;
|
using Artemis.Profiles.Layers.Abstract;
|
||||||
|
using Artemis.Profiles.Layers.Animations;
|
||||||
using Artemis.Profiles.Layers.Interfaces;
|
using Artemis.Profiles.Layers.Interfaces;
|
||||||
using Artemis.Profiles.Layers.Models;
|
using Artemis.Profiles.Layers.Models;
|
||||||
using Artemis.Profiles.Layers.Types.Audio.AudioCapturing;
|
using Artemis.Profiles.Layers.Types.Audio.AudioCapturing;
|
||||||
using Artemis.Properties;
|
using Artemis.Properties;
|
||||||
using Artemis.Utilities;
|
using Artemis.Utilities;
|
||||||
using Artemis.ViewModels.Profiles;
|
using Artemis.ViewModels;
|
||||||
using Newtonsoft.Json;
|
using CSCore.CoreAudioAPI;
|
||||||
using Ninject;
|
|
||||||
|
|
||||||
namespace Artemis.Profiles.Layers.Types.Audio
|
namespace Artemis.Profiles.Layers.Types.Audio
|
||||||
{
|
{
|
||||||
public class AudioType : ILayerType
|
public class AudioType : ILayerType
|
||||||
{
|
{
|
||||||
private readonly List<LayerModel> _audioLayers = new List<LayerModel>();
|
private readonly AudioCaptureManager _audioCaptureManager;
|
||||||
private readonly IKernel _kernel;
|
private AudioCapture _audioCapture;
|
||||||
|
|
||||||
private DateTime _lastUpdate;
|
|
||||||
private int _lines;
|
private int _lines;
|
||||||
private string _previousSettings;
|
private LineSpectrum _lineSpectrum;
|
||||||
|
private List<double> _lineValues;
|
||||||
|
private AudioPropertiesModel _properties;
|
||||||
|
private bool _subscribed;
|
||||||
|
|
||||||
public AudioType(IKernel kernel, AudioCaptureManager audioCaptureManager)
|
public AudioType(AudioCaptureManager audioCaptureManager)
|
||||||
{
|
{
|
||||||
_kernel = kernel;
|
_audioCaptureManager = audioCaptureManager;
|
||||||
AudioCaptureManager = audioCaptureManager;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[JsonIgnore]
|
private void SubscribeToAudioChange()
|
||||||
public AudioCaptureManager AudioCaptureManager { get; set; }
|
{
|
||||||
|
if (_subscribed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_audioCaptureManager.AudioDeviceChanged += OnAudioDeviceChanged;
|
||||||
|
_subscribed = true;
|
||||||
|
}
|
||||||
|
|
||||||
public string Name => "Keyboard - Audio visualization";
|
public string Name => "Keyboard - Audio visualization";
|
||||||
public bool ShowInEdtor => true;
|
public bool ShowInEdtor => true;
|
||||||
public DrawType DrawType => DrawType.Keyboard;
|
public DrawType DrawType => DrawType.Keyboard;
|
||||||
|
public int DrawScale => 4;
|
||||||
|
|
||||||
public ImageSource DrawThumbnail(LayerModel layer)
|
public ImageSource DrawThumbnail(LayerModel layer)
|
||||||
{
|
{
|
||||||
@ -53,56 +61,109 @@ namespace Artemis.Profiles.Layers.Types.Audio
|
|||||||
|
|
||||||
public void Draw(LayerModel layerModel, DrawingContext c)
|
public void Draw(LayerModel layerModel, DrawingContext c)
|
||||||
{
|
{
|
||||||
lock (_audioLayers)
|
if (_lineValues == null)
|
||||||
{
|
return;
|
||||||
foreach (var audioLayer in _audioLayers)
|
|
||||||
{
|
|
||||||
// This is cheating but it ensures that the brush is drawn across the entire main-layer
|
|
||||||
var oldWidth = audioLayer.Properties.Width;
|
|
||||||
var oldHeight = audioLayer.Properties.Height;
|
|
||||||
var oldX = audioLayer.Properties.X;
|
|
||||||
var oldY = audioLayer.Properties.Y;
|
|
||||||
|
|
||||||
audioLayer.Properties.Width = layerModel.Properties.Width;
|
var parentX = layerModel.X;
|
||||||
audioLayer.Properties.Height = layerModel.Properties.Height;
|
var parentY = layerModel.Y;
|
||||||
audioLayer.Properties.X = layerModel.Properties.X;
|
var direction = ((AudioPropertiesModel) layerModel.Properties).Direction;
|
||||||
audioLayer.Properties.Y = layerModel.Properties.Y;
|
|
||||||
audioLayer.LayerType.Draw(audioLayer, c);
|
|
||||||
|
|
||||||
audioLayer.Properties.Width = oldWidth;
|
// Create a geometry that will be formed by all the bars
|
||||||
audioLayer.Properties.Height = oldHeight;
|
var barGeometry = new GeometryGroup();
|
||||||
audioLayer.Properties.X = oldX;
|
|
||||||
audioLayer.Properties.Y = oldY;
|
switch (direction)
|
||||||
|
{
|
||||||
|
case Direction.TopToBottom:
|
||||||
|
for (var index = 0; index < _lineValues.Count; index++)
|
||||||
|
{
|
||||||
|
var clipRect = new Rect((parentX + index) * 4, parentY * 4, 4, _lineValues[index] * 4);
|
||||||
|
var barRect = new RectangleGeometry(clipRect);
|
||||||
|
barGeometry.Children.Add(barRect);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case Direction.BottomToTop:
|
||||||
|
for (var index = 0; index < _lineValues.Count; index++)
|
||||||
|
{
|
||||||
|
var clipRect = new Rect((parentX + index) * 4, parentY * 4, 4, _lineValues[index] * 4);
|
||||||
|
clipRect.Y = clipRect.Y + layerModel.Height * 4 - clipRect.Height;
|
||||||
|
var barRect = new RectangleGeometry(clipRect);
|
||||||
|
barGeometry.Children.Add(barRect);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case Direction.LeftToRight:
|
||||||
|
for (var index = 0; index < _lineValues.Count; index++)
|
||||||
|
{
|
||||||
|
var clipRect = new Rect((parentX + index) * 4, parentY * 4, 4, _lineValues[index] * 4);
|
||||||
|
var barRect = new RectangleGeometry(clipRect);
|
||||||
|
barGeometry.Children.Add(barRect);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
for (var index = 0; index < _lineValues.Count; index++)
|
||||||
|
{
|
||||||
|
var clipRect = new Rect((parentX + index) * 4, parentY * 4, 4, _lineValues[index] * 4);
|
||||||
|
var barRect = new RectangleGeometry(clipRect);
|
||||||
|
barGeometry.Children.Add(barRect);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Push the created geometry
|
||||||
|
c.PushClip(barGeometry);
|
||||||
|
BrushDraw(layerModel, c);
|
||||||
|
c.Pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Update(LayerModel layerModel, ModuleDataModel dataModel, bool isPreview = false)
|
public void Update(LayerModel layerModel, ModuleDataModel dataModel, bool isPreview = false)
|
||||||
{
|
{
|
||||||
layerModel.ApplyProperties(true);
|
layerModel.ApplyProperties(true);
|
||||||
if (isPreview)
|
var newProperties = (AudioPropertiesModel) layerModel.Properties;
|
||||||
|
if (_properties == null)
|
||||||
|
_properties = newProperties;
|
||||||
|
|
||||||
|
SubscribeToAudioChange();
|
||||||
|
|
||||||
|
if (_audioCapture == null || newProperties.Device != _properties.Device ||
|
||||||
|
newProperties.DeviceType != _properties.DeviceType)
|
||||||
|
{
|
||||||
|
var device = GetMmDevice();
|
||||||
|
if (device != null)
|
||||||
|
_audioCapture = _audioCaptureManager.GetAudioCapture(device, newProperties.DeviceType);
|
||||||
|
}
|
||||||
|
|
||||||
|
_properties = newProperties;
|
||||||
|
|
||||||
|
if (_audioCapture == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
lock (_audioLayers)
|
_audioCapture.Pulse();
|
||||||
{
|
|
||||||
SetupLayers(layerModel);
|
|
||||||
var spectrumData = AudioCaptureManager.GetSpectrumData(_lines);
|
|
||||||
if (!spectrumData.Any())
|
|
||||||
return;
|
|
||||||
|
|
||||||
var settings = (AudioPropertiesModel) layerModel.Properties;
|
var direction = ((AudioPropertiesModel) layerModel.Properties).Direction;
|
||||||
switch (settings.Direction)
|
|
||||||
|
int currentLines;
|
||||||
|
double currentHeight;
|
||||||
|
if (direction == Direction.BottomToTop || direction == Direction.TopToBottom)
|
||||||
{
|
{
|
||||||
case Direction.TopToBottom:
|
currentLines = (int) layerModel.Width;
|
||||||
case Direction.BottomToTop:
|
currentHeight = layerModel.Height;
|
||||||
ApplyVertical(spectrumData, settings);
|
|
||||||
break;
|
|
||||||
case Direction.LeftToRight:
|
|
||||||
case Direction.RightToLeft:
|
|
||||||
ApplyHorizontal(spectrumData, settings);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
currentLines = (int) layerModel.Height;
|
||||||
|
currentHeight = layerModel.Width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_lines != currentLines || _lineSpectrum == null)
|
||||||
|
{
|
||||||
|
_lines = currentLines;
|
||||||
|
_lineSpectrum = _audioCapture.GetLineSpectrum(_lines, ScalingStrategy.Decibel);
|
||||||
|
if (_lineSpectrum == null)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var newLineValues = _lineSpectrum?.GetLineValues(currentHeight);
|
||||||
|
if (newLineValues != null)
|
||||||
|
_lineValues = newLineValues;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetupProperties(LayerModel layerModel)
|
public void SetupProperties(LayerModel layerModel)
|
||||||
@ -112,8 +173,10 @@ namespace Artemis.Profiles.Layers.Types.Audio
|
|||||||
|
|
||||||
layerModel.Properties = new AudioPropertiesModel(layerModel.Properties)
|
layerModel.Properties = new AudioPropertiesModel(layerModel.Properties)
|
||||||
{
|
{
|
||||||
FadeSpeed = 0.2,
|
DeviceType = MmDeviceType.Ouput,
|
||||||
Sensitivity = 2
|
Device = "Default",
|
||||||
|
Direction = Direction.BottomToTop,
|
||||||
|
ScalingStrategy = ScalingStrategy.Decibel
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,170 +188,65 @@ namespace Artemis.Profiles.Layers.Types.Audio
|
|||||||
return new AudioPropertiesViewModel(layerEditorViewModel);
|
return new AudioPropertiesViewModel(layerEditorViewModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ApplyVertical(List<byte> spectrumData, AudioPropertiesModel settings)
|
public void BrushDraw(LayerModel layerModel, DrawingContext c)
|
||||||
{
|
{
|
||||||
var index = 0;
|
// If an animation is present, let it handle the drawing
|
||||||
foreach (var audioLayer in _audioLayers)
|
if (layerModel.LayerAnimation != null && !(layerModel.LayerAnimation is NoneAnimation))
|
||||||
{
|
{
|
||||||
int height;
|
layerModel.LayerAnimation.Draw(layerModel, c, DrawScale);
|
||||||
if (spectrumData.Count > index)
|
|
||||||
height = (int) Math.Round(spectrumData[index]/2.55);
|
|
||||||
else
|
|
||||||
height = 0;
|
|
||||||
|
|
||||||
// Apply Sensitivity setting
|
|
||||||
height = height*settings.Sensitivity;
|
|
||||||
|
|
||||||
var newHeight = settings.Height/100.0*height;
|
|
||||||
if (newHeight >= audioLayer.Properties.Height)
|
|
||||||
audioLayer.Properties.Height = newHeight;
|
|
||||||
else
|
|
||||||
audioLayer.Properties.Height = audioLayer.Properties.Height - settings.FadeSpeed;
|
|
||||||
if (audioLayer.Properties.Height < 0)
|
|
||||||
audioLayer.Properties.Height = 0;
|
|
||||||
|
|
||||||
// Reverse the direction if settings require it
|
|
||||||
if (settings.Direction == Direction.BottomToTop)
|
|
||||||
audioLayer.Properties.Y = settings.Y + (settings.Height - audioLayer.Properties.Height);
|
|
||||||
|
|
||||||
FakeUpdate(settings, audioLayer);
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ApplyHorizontal(List<byte> spectrumData, AudioPropertiesModel settings)
|
|
||||||
{
|
|
||||||
var index = 0;
|
|
||||||
foreach (var audioLayer in _audioLayers)
|
|
||||||
{
|
|
||||||
int width;
|
|
||||||
if (spectrumData.Count > index)
|
|
||||||
width = (int) Math.Round(spectrumData[index]/2.55);
|
|
||||||
else
|
|
||||||
width = 0;
|
|
||||||
|
|
||||||
// Apply Sensitivity setting
|
|
||||||
width = width*settings.Sensitivity;
|
|
||||||
|
|
||||||
var newWidth = settings.Width/100.0*width;
|
|
||||||
if (newWidth >= audioLayer.Properties.Width)
|
|
||||||
audioLayer.Properties.Width = newWidth;
|
|
||||||
else
|
|
||||||
audioLayer.Properties.Width = audioLayer.Properties.Width - settings.FadeSpeed;
|
|
||||||
if (audioLayer.Properties.Width < 0)
|
|
||||||
audioLayer.Properties.Width = 0;
|
|
||||||
|
|
||||||
audioLayer.Properties.Brush = settings.Brush;
|
|
||||||
audioLayer.Properties.Contain = false;
|
|
||||||
|
|
||||||
// Reverse the direction if settings require it
|
|
||||||
if (settings.Direction == Direction.RightToLeft)
|
|
||||||
audioLayer.Properties.X = settings.X + (settings.Width - audioLayer.Properties.Width);
|
|
||||||
|
|
||||||
FakeUpdate(settings, audioLayer);
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Updates the layer manually faking the width and height for a properly working animation
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="settings"></param>
|
|
||||||
/// <param name="audioLayer"></param>
|
|
||||||
private static void FakeUpdate(LayerPropertiesModel settings, LayerModel audioLayer)
|
|
||||||
{
|
|
||||||
// Call the regular update
|
|
||||||
audioLayer.LayerType?.Update(audioLayer, null);
|
|
||||||
|
|
||||||
// Store the original height and width
|
|
||||||
var oldHeight = audioLayer.Properties.Height;
|
|
||||||
var oldWidth = audioLayer.Properties.Width;
|
|
||||||
|
|
||||||
// Fake the height and width and update the animation
|
|
||||||
audioLayer.Properties.Width = settings.Width;
|
|
||||||
audioLayer.Properties.Height = settings.Height;
|
|
||||||
audioLayer.LastRender = DateTime.Now;
|
|
||||||
audioLayer.LayerAnimation?.Update(audioLayer, true);
|
|
||||||
|
|
||||||
// Restore the height and width
|
|
||||||
audioLayer.Properties.Height = oldHeight;
|
|
||||||
audioLayer.Properties.Width = oldWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets up the inner layers when the settings have changed
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="layerModel"></param>
|
|
||||||
private void SetupLayers(LayerModel layerModel)
|
|
||||||
{
|
|
||||||
// Checking on settings update is expensive, only do it every second
|
|
||||||
if (DateTime.Now - _lastUpdate < TimeSpan.FromSeconds(1))
|
|
||||||
return;
|
return;
|
||||||
_lastUpdate = DateTime.Now;
|
}
|
||||||
|
|
||||||
var settings = (AudioPropertiesModel) layerModel.Properties;
|
// Otherwise draw the rectangle with its layer.AppliedProperties dimensions and brush
|
||||||
var currentSettings = JsonConvert.SerializeObject(settings, Formatting.Indented);
|
var rect = layerModel.Properties.Contain
|
||||||
var currentType = _audioLayers.FirstOrDefault()?.LayerAnimation?.GetType();
|
? layerModel.LayerRect()
|
||||||
|
: new Rect(layerModel.Properties.X * 4, layerModel.Properties.Y * 4,
|
||||||
|
layerModel.Properties.Width * 4, layerModel.Properties.Height * 4);
|
||||||
|
|
||||||
if (currentSettings == _previousSettings && (layerModel.LayerAnimation.GetType() == currentType))
|
var clip = layerModel.LayerRect(DrawScale);
|
||||||
|
|
||||||
|
// Can't meddle with the original brush because it's frozen.
|
||||||
|
var brush = layerModel.Brush.Clone();
|
||||||
|
brush.Opacity = layerModel.Opacity;
|
||||||
|
|
||||||
|
c.PushClip(new RectangleGeometry(clip));
|
||||||
|
c.DrawRectangle(brush, null, rect);
|
||||||
|
c.Pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnAudioDeviceChanged(object sender, AudioDeviceChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (_properties == null || _properties.Device != "Default")
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_previousSettings = JsonConvert.SerializeObject(settings, Formatting.Indented);
|
if (_properties.DeviceType == MmDeviceType.Input)
|
||||||
|
|
||||||
_audioLayers.Clear();
|
|
||||||
switch (settings.Direction)
|
|
||||||
{
|
{
|
||||||
case Direction.TopToBottom:
|
if (e.DefaultRecording != null)
|
||||||
case Direction.BottomToTop:
|
_audioCapture = _audioCaptureManager.GetAudioCapture(e.DefaultRecording, MmDeviceType.Input);
|
||||||
SetupVertical(layerModel);
|
|
||||||
break;
|
|
||||||
case Direction.LeftToRight:
|
|
||||||
case Direction.RightToLeft:
|
|
||||||
SetupHorizontal(layerModel);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new ArgumentOutOfRangeException();
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (e.DefaultPlayback != null)
|
||||||
|
_audioCapture = _audioCaptureManager.GetAudioCapture(e.DefaultPlayback, MmDeviceType.Ouput);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetupVertical(LayerModel layerModel)
|
_lines = 0;
|
||||||
{
|
|
||||||
_lines = (int) layerModel.Properties.Width;
|
|
||||||
for (var i = 0; i < _lines; i++)
|
|
||||||
{
|
|
||||||
var layer = LayerModel.CreateLayer();
|
|
||||||
layer.Properties.X = layerModel.Properties.X + i;
|
|
||||||
layer.Properties.Y = layerModel.Properties.Y;
|
|
||||||
layer.Properties.Width = 1;
|
|
||||||
layer.Properties.Height = 0;
|
|
||||||
layer.Properties.AnimationSpeed = layerModel.Properties.AnimationSpeed;
|
|
||||||
layer.Properties.Brush = layerModel.Properties.Brush;
|
|
||||||
layer.Properties.Contain = false;
|
|
||||||
layer.LayerAnimation = (ILayerAnimation) _kernel.Get(layerModel.LayerAnimation.GetType());
|
|
||||||
|
|
||||||
_audioLayers.Add(layer);
|
|
||||||
layer.Update(null, false, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetupHorizontal(LayerModel layerModel)
|
private MMDevice GetMmDevice()
|
||||||
{
|
{
|
||||||
_lines = (int) layerModel.Properties.Height;
|
if (_properties == null)
|
||||||
for (var i = 0; i < _lines; i++)
|
return null;
|
||||||
{
|
|
||||||
var layer = LayerModel.CreateLayer();
|
|
||||||
layer.Properties.X = layerModel.Properties.X;
|
|
||||||
layer.Properties.Y = layerModel.Properties.Y + i;
|
|
||||||
layer.Properties.Width = 0;
|
|
||||||
layer.Properties.Height = 1;
|
|
||||||
layer.Properties.AnimationSpeed = layerModel.Properties.AnimationSpeed;
|
|
||||||
layer.Properties.Brush = layerModel.Properties.Brush;
|
|
||||||
layer.Properties.Contain = false;
|
|
||||||
layer.LayerAnimation = (ILayerAnimation) _kernel.Get(layerModel.LayerAnimation.GetType());
|
|
||||||
|
|
||||||
_audioLayers.Add(layer);
|
if (_properties.DeviceType == MmDeviceType.Input)
|
||||||
layer.Update(null, false, true);
|
return _properties.Device == "Default"
|
||||||
}
|
? MMDeviceEnumerator.TryGetDefaultAudioEndpoint(DataFlow.Capture, Role.Multimedia)
|
||||||
|
: MMDeviceEnumerator.EnumerateDevices(DataFlow.Capture)
|
||||||
|
.FirstOrDefault(d => d.FriendlyName == _properties.Device);
|
||||||
|
return _properties.Device == "Default"
|
||||||
|
? MMDeviceEnumerator.TryGetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia)
|
||||||
|
: MMDeviceEnumerator.EnumerateDevices(DataFlow.Render)
|
||||||
|
.FirstOrDefault(d => d.FriendlyName == _properties.Device);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using Artemis.Profiles.Layers.Models;
|
||||||
|
|
||||||
|
namespace Artemis.Profiles.Layers.Types.ConicalBrush
|
||||||
|
{
|
||||||
|
public class ConicalBrushPropertiesModel : LayerPropertiesModel
|
||||||
|
{
|
||||||
|
#region Properties & Fields
|
||||||
|
|
||||||
|
public IList<Tuple<double, Color>> GradientStops { get; set; }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
|
||||||
|
public ConicalBrushPropertiesModel(LayerPropertiesModel properties = null)
|
||||||
|
: base(properties)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,80 @@
|
|||||||
|
<UserControl x:Class="Artemis.Profiles.Layers.Types.ConicalBrush.ConicalBrushPropertiesView"
|
||||||
|
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:controls="http://metro.mahapps.com/winfx/xaml/controls"
|
||||||
|
xmlns:ncore="http://schemas.ncore.com/wpf/xaml/colorbox"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
d:DesignHeight="300" d:DesignWidth="300">
|
||||||
|
<Grid>
|
||||||
|
<!-- Colors -->
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition />
|
||||||
|
<ColumnDefinition />
|
||||||
|
<ColumnDefinition />
|
||||||
|
<ColumnDefinition />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<!-- Animation -->
|
||||||
|
<TextBlock Grid.Row="0" Grid.Column="0" Margin="10" FontSize="13.333" Text="Animation:"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Height="18" />
|
||||||
|
<ComboBox Grid.Row="0" Grid.Column="1" Margin="10,10,10,0" x:Name="LayerAnimations" VerticalAlignment="Top"
|
||||||
|
Height="22">
|
||||||
|
<ComboBox.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<TextBlock Text="{Binding Path=Name, Mode=OneWay}" />
|
||||||
|
</DataTemplate>
|
||||||
|
</ComboBox.ItemTemplate>
|
||||||
|
</ComboBox>
|
||||||
|
|
||||||
|
<!-- Animation Speed -->
|
||||||
|
<TextBlock Grid.Row="0" Grid.Column="2" Margin="10" FontSize="13.333" Text="Animation speed:"
|
||||||
|
VerticalAlignment="Center" Height="18" />
|
||||||
|
<Slider x:Name="RotationSpeed" Grid.Row="0" Grid.Column="3" VerticalAlignment="Center"
|
||||||
|
TickPlacement="None" TickFrequency="0.05"
|
||||||
|
Value="{Binding Path=LayerModel.Properties.AnimationSpeed, Mode=TwoWay}" Minimum="0.05" Maximum="3"
|
||||||
|
SmallChange="0" IsSnapToTickEnabled="True" Margin="10,12,10,2" Height="24" />
|
||||||
|
|
||||||
|
<!-- ClippingType -->
|
||||||
|
<TextBlock Grid.Row="1" Grid.Column="0" Margin="10, 13, 10, 10" FontSize="13.333" Text="Clipping type:"
|
||||||
|
VerticalAlignment="Center" Height="23" />
|
||||||
|
<controls:ToggleSwitch IsChecked="{Binding Path=LayerModel.Properties.Contain, Mode=TwoWay}"
|
||||||
|
Grid.Row="1"
|
||||||
|
Grid.Column="1" OnLabel="Contain" OffLabel="Cut-off" Margin="10,1,5,1"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Height="36" />
|
||||||
|
|
||||||
|
<!-- Colors -->
|
||||||
|
<StackPanel Grid.Row="1" Grid.Column="2" Grid.ColumnSpan="2" Orientation="Horizontal" x:Name="ShowBrush">
|
||||||
|
<TextBlock Margin="10,13,10,0" FontSize="13.333" Text="Color(s):"
|
||||||
|
VerticalAlignment="Top" Height="18" Width="130" />
|
||||||
|
<Border Margin="10" BorderBrush="{StaticResource ControlBorderBrush}"
|
||||||
|
BorderThickness="1" SnapsToDevicePixels="True" ToolTip="Click to edit">
|
||||||
|
<ncore:ColorBox Brush="{Binding Brush, Mode=TwoWay}" ShowNone="False" Height="24" Width="134"
|
||||||
|
VerticalAlignment="Top" ShowLinear="True" ShowRadial="False" ShowSolid="False" />
|
||||||
|
</Border>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<!-- Dynamic -->
|
||||||
|
<Label Grid.Row="3" Grid.Column="0" FontSize="20" HorizontalAlignment="Left"
|
||||||
|
Content="Dynamic" Width="97" VerticalAlignment="Bottom" />
|
||||||
|
|
||||||
|
<!-- Dynamic property views -->
|
||||||
|
<ContentControl Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="4" x:Name="HeightProperties" />
|
||||||
|
<ContentControl Grid.Row="5" Grid.Column="0" Grid.ColumnSpan="4" x:Name="WidthProperties" />
|
||||||
|
<ContentControl Grid.Row="6" Grid.Column="0" Grid.ColumnSpan="4" x:Name="OpacityProperties" />
|
||||||
|
|
||||||
|
<ContentControl Grid.Row="7" Grid.Column="0" Grid.ColumnSpan="4" x:Name="LayerTweenViewModel" />
|
||||||
|
</Grid>
|
||||||
|
</UserControl>
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
using System.Windows.Controls;
|
||||||
|
|
||||||
|
namespace Artemis.Profiles.Layers.Types.ConicalBrush
|
||||||
|
{
|
||||||
|
public partial class ConicalBrushPropertiesView : UserControl
|
||||||
|
{
|
||||||
|
public ConicalBrushPropertiesView()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,70 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using Artemis.Profiles.Layers.Abstract;
|
||||||
|
using Artemis.Profiles.Layers.Interfaces;
|
||||||
|
using Artemis.Utilities;
|
||||||
|
using Artemis.ViewModels;
|
||||||
|
using Artemis.ViewModels.Profiles;
|
||||||
|
using Caliburn.Micro;
|
||||||
|
|
||||||
|
namespace Artemis.Profiles.Layers.Types.ConicalBrush
|
||||||
|
{
|
||||||
|
public class ConicalBrushPropertiesViewModel : LayerPropertiesViewModel
|
||||||
|
{
|
||||||
|
#region Properties & Fields
|
||||||
|
|
||||||
|
private ILayerAnimation _selectedLayerAnimation;
|
||||||
|
|
||||||
|
public BindableCollection<GeneralHelpers.PropertyCollection> DataModelProps { get; set; }
|
||||||
|
public BindableCollection<ILayerAnimation> LayerAnimations { get; set; }
|
||||||
|
public LayerDynamicPropertiesViewModel HeightProperties { get; set; }
|
||||||
|
public LayerDynamicPropertiesViewModel WidthProperties { get; set; }
|
||||||
|
public LayerDynamicPropertiesViewModel OpacityProperties { get; set; }
|
||||||
|
public LayerTweenViewModel LayerTweenViewModel { get; set; }
|
||||||
|
|
||||||
|
public ILayerAnimation SelectedLayerAnimation
|
||||||
|
{
|
||||||
|
get { return _selectedLayerAnimation; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (Equals(value, _selectedLayerAnimation)) return;
|
||||||
|
_selectedLayerAnimation = value;
|
||||||
|
NotifyOfPropertyChange(() => SelectedLayerAnimation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
|
||||||
|
public ConicalBrushPropertiesViewModel(LayerEditorViewModel editorVm)
|
||||||
|
: base(editorVm)
|
||||||
|
{
|
||||||
|
LayerAnimations = new BindableCollection<ILayerAnimation>(editorVm.LayerAnimations);
|
||||||
|
|
||||||
|
HeightProperties = new LayerDynamicPropertiesViewModel("Height", editorVm);
|
||||||
|
WidthProperties = new LayerDynamicPropertiesViewModel("Width", editorVm);
|
||||||
|
OpacityProperties = new LayerDynamicPropertiesViewModel("Opacity", editorVm);
|
||||||
|
LayerTweenViewModel = new LayerTweenViewModel(editorVm);
|
||||||
|
|
||||||
|
SelectedLayerAnimation =
|
||||||
|
LayerAnimations.FirstOrDefault(l => l.Name == editorVm.ProposedLayer.LayerAnimation?.Name) ??
|
||||||
|
LayerAnimations.First(l => l.Name == "None");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
|
||||||
|
public override void ApplyProperties()
|
||||||
|
{
|
||||||
|
HeightProperties.Apply(LayerModel);
|
||||||
|
WidthProperties.Apply(LayerModel);
|
||||||
|
OpacityProperties.Apply(LayerModel);
|
||||||
|
|
||||||
|
LayerModel.Properties.Brush = Brush;
|
||||||
|
LayerModel.LayerAnimation = SelectedLayerAnimation;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,132 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using Artemis.Modules.Abstract;
|
||||||
|
using Artemis.Profiles.Layers.Abstract;
|
||||||
|
using Artemis.Profiles.Layers.Animations;
|
||||||
|
using Artemis.Profiles.Layers.Interfaces;
|
||||||
|
using Artemis.Profiles.Layers.Models;
|
||||||
|
using Artemis.Profiles.Layers.Types.ConicalBrush.Drawing;
|
||||||
|
using Artemis.ViewModels;
|
||||||
|
|
||||||
|
namespace Artemis.Profiles.Layers.Types.ConicalBrush
|
||||||
|
{
|
||||||
|
public class ConicalBrushType : ILayerType
|
||||||
|
{
|
||||||
|
#region Properties & Fields
|
||||||
|
|
||||||
|
private ConicalGradientDrawer _conicalGradientDrawer;
|
||||||
|
private ConicalGradientDrawer _conicalGradientDrawerThumbnail;
|
||||||
|
|
||||||
|
public string Name => "Conical Brush";
|
||||||
|
public bool ShowInEdtor => true;
|
||||||
|
public DrawType DrawType => DrawType.Keyboard;
|
||||||
|
public int DrawScale => 4;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public ConicalBrushType()
|
||||||
|
{
|
||||||
|
_conicalGradientDrawer = new ConicalGradientDrawer();
|
||||||
|
_conicalGradientDrawerThumbnail = new ConicalGradientDrawer(18, 18);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
|
||||||
|
public ImageSource DrawThumbnail(LayerModel layer)
|
||||||
|
{
|
||||||
|
_conicalGradientDrawerThumbnail.GradientStops = GetGradientStops(layer.Brush).Select(x => new Tuple<double, Color>(x.Offset, x.Color)).ToList();
|
||||||
|
_conicalGradientDrawerThumbnail.Update();
|
||||||
|
|
||||||
|
Rect thumbnailRect = new Rect(0, 0, 18, 18);
|
||||||
|
DrawingVisual visual = new DrawingVisual();
|
||||||
|
using (DrawingContext c = visual.RenderOpen())
|
||||||
|
if (_conicalGradientDrawerThumbnail.Brush != null)
|
||||||
|
c.DrawRectangle(_conicalGradientDrawerThumbnail.Brush.Clone(), new Pen(new SolidColorBrush(Colors.White), 1), thumbnailRect);
|
||||||
|
|
||||||
|
DrawingImage image = new DrawingImage(visual.Drawing);
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Draw(LayerModel layerModel, DrawingContext c)
|
||||||
|
{
|
||||||
|
ConicalBrushPropertiesModel properties = layerModel.Properties as ConicalBrushPropertiesModel;
|
||||||
|
if (properties == null) return;
|
||||||
|
|
||||||
|
Brush origBrush = layerModel.Brush;
|
||||||
|
|
||||||
|
_conicalGradientDrawer.GradientStops = GetGradientStops(layerModel.Brush).Select(x => new Tuple<double, Color>(x.Offset, x.Color)).ToList();
|
||||||
|
_conicalGradientDrawer.Update();
|
||||||
|
layerModel.Brush = _conicalGradientDrawer.Brush;
|
||||||
|
|
||||||
|
// If an animation is present, let it handle the drawing
|
||||||
|
if (layerModel.LayerAnimation != null && !(layerModel.LayerAnimation is NoneAnimation))
|
||||||
|
{
|
||||||
|
layerModel.LayerAnimation.Draw(layerModel, c, DrawScale);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise draw the rectangle with its layer.AppliedProperties dimensions and brush
|
||||||
|
Rect rect = layerModel.Properties.Contain
|
||||||
|
? layerModel.LayerRect(DrawScale)
|
||||||
|
: new Rect(layerModel.Properties.X * DrawScale, layerModel.Properties.Y * DrawScale,
|
||||||
|
layerModel.Properties.Width * DrawScale, layerModel.Properties.Height * DrawScale);
|
||||||
|
|
||||||
|
Rect clip = layerModel.LayerRect();
|
||||||
|
|
||||||
|
// Can't meddle with the original brush because it's frozen.
|
||||||
|
Brush brush = layerModel.Brush.Clone();
|
||||||
|
brush.Opacity = layerModel.Opacity;
|
||||||
|
|
||||||
|
c.PushClip(new RectangleGeometry(clip));
|
||||||
|
c.DrawRectangle(brush, null, rect);
|
||||||
|
c.Pop();
|
||||||
|
|
||||||
|
layerModel.Brush = origBrush;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update(LayerModel layerModel, ModuleDataModel dataModel, bool isPreview = false)
|
||||||
|
{
|
||||||
|
layerModel.ApplyProperties(true);
|
||||||
|
if (isPreview || dataModel == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// If not previewing, apply dynamic properties according to datamodel
|
||||||
|
foreach (DynamicPropertiesModel dynamicProperty in layerModel.Properties.DynamicProperties)
|
||||||
|
dynamicProperty.ApplyProperty(dataModel, layerModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetupProperties(LayerModel layerModel)
|
||||||
|
{
|
||||||
|
if (layerModel.Properties is ConicalBrushPropertiesModel)
|
||||||
|
return;
|
||||||
|
|
||||||
|
layerModel.Properties = new ConicalBrushPropertiesModel(layerModel.Properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LayerPropertiesViewModel SetupViewModel(LayerEditorViewModel layerEditorViewModel, LayerPropertiesViewModel layerPropertiesViewModel)
|
||||||
|
{
|
||||||
|
return (layerPropertiesViewModel as ConicalBrushPropertiesViewModel) ?? new ConicalBrushPropertiesViewModel(layerEditorViewModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
private GradientStopCollection GetGradientStops(Brush brush)
|
||||||
|
{
|
||||||
|
LinearGradientBrush linearBrush = brush as LinearGradientBrush;
|
||||||
|
if (linearBrush != null)
|
||||||
|
return linearBrush.GradientStops;
|
||||||
|
|
||||||
|
RadialGradientBrush radialBrush = brush as RadialGradientBrush;
|
||||||
|
if (radialBrush != null)
|
||||||
|
return radialBrush.GradientStops;
|
||||||
|
|
||||||
|
SolidColorBrush solidBrush = brush as SolidColorBrush;
|
||||||
|
if (solidBrush != null)
|
||||||
|
return new GradientStopCollection(new[] { new GradientStop(solidBrush.Color, 0), new GradientStop(solidBrush.Color, 1) });
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,201 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using System.Windows.Media.Imaging;
|
||||||
|
using Brush = System.Windows.Media.Brush;
|
||||||
|
using Color = System.Windows.Media.Color;
|
||||||
|
|
||||||
|
namespace Artemis.Profiles.Layers.Types.ConicalBrush.Drawing
|
||||||
|
{
|
||||||
|
public class ConicalGradientDrawer
|
||||||
|
{
|
||||||
|
#region Constants
|
||||||
|
|
||||||
|
private static readonly double ORIGIN = Math.Atan2(-1, 0);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Properties & Fields
|
||||||
|
|
||||||
|
private int _width;
|
||||||
|
private int _height;
|
||||||
|
|
||||||
|
private bool _isDirty = true;
|
||||||
|
private int _lastGradientHash;
|
||||||
|
|
||||||
|
private WriteableBitmap _bitmap;
|
||||||
|
|
||||||
|
private IList<Tuple<double, Color>> _gradientStops;
|
||||||
|
public IList<Tuple<double, Color>> GradientStops
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
int hash = GetHash(value);
|
||||||
|
if (_lastGradientHash != hash)
|
||||||
|
{
|
||||||
|
_gradientStops = FixGradientStops(value);
|
||||||
|
_lastGradientHash = hash;
|
||||||
|
_isDirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private PointF _center = new PointF(0.5f, 0.5f);
|
||||||
|
public PointF Center
|
||||||
|
{
|
||||||
|
get { return _center; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_center != value)
|
||||||
|
{
|
||||||
|
_center = value;
|
||||||
|
_isDirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Brush Brush { get; private set; }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
|
||||||
|
public ConicalGradientDrawer()
|
||||||
|
: this(100, 100)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public ConicalGradientDrawer(int width, int height)
|
||||||
|
{
|
||||||
|
this._width = width;
|
||||||
|
this._height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
|
||||||
|
public void Update(bool force = false)
|
||||||
|
{
|
||||||
|
if (!_isDirty && !force) return;
|
||||||
|
|
||||||
|
if (_bitmap == null)
|
||||||
|
CreateBrush();
|
||||||
|
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
_bitmap.Lock();
|
||||||
|
byte* buffer = (byte*)_bitmap.BackBuffer.ToPointer();
|
||||||
|
|
||||||
|
for (int y = 0; y < _height; y++)
|
||||||
|
for (int x = 0; x < _width; x++)
|
||||||
|
{
|
||||||
|
int offset = (((y * _width) + x) * 4);
|
||||||
|
|
||||||
|
double gradientOffset = CalculateGradientOffset(x, y, _width * Center.X, _height * Center.Y);
|
||||||
|
GetColor(_gradientStops, gradientOffset,
|
||||||
|
ref buffer[offset + 3], ref buffer[offset + 2],
|
||||||
|
ref buffer[offset + 1], ref buffer[offset]);
|
||||||
|
}
|
||||||
|
|
||||||
|
_bitmap.AddDirtyRect(new Int32Rect(0, 0, _width, _height));
|
||||||
|
_bitmap.Unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
_isDirty = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateBrush()
|
||||||
|
{
|
||||||
|
_bitmap = new WriteableBitmap(_width, _height, 96, 96, PixelFormats.Bgra32, null);
|
||||||
|
Brush = new ImageBrush(_bitmap) { Stretch = Stretch.UniformToFill };
|
||||||
|
}
|
||||||
|
|
||||||
|
private double CalculateGradientOffset(double x, double y, double centerX, double centerY)
|
||||||
|
{
|
||||||
|
double angle = Math.Atan2(y - centerY, x - centerX) - ORIGIN;
|
||||||
|
if (angle < 0) angle += Math.PI * 2;
|
||||||
|
return angle / (Math.PI * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GetColor(IList<Tuple<double, Color>> gradientStops, double offset, ref byte colA, ref byte colR, ref byte colG, ref byte colB)
|
||||||
|
{
|
||||||
|
if (gradientStops.Count == 0)
|
||||||
|
{
|
||||||
|
colA = 0;
|
||||||
|
colR = 0;
|
||||||
|
colG = 0;
|
||||||
|
colB = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (gradientStops.Count == 1)
|
||||||
|
{
|
||||||
|
Color color = gradientStops.First().Item2;
|
||||||
|
colA = color.A;
|
||||||
|
colR = color.R;
|
||||||
|
colG = color.G;
|
||||||
|
colB = color.B;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Tuple<double, Color> beforeStop = null;
|
||||||
|
double afterOffset = -1;
|
||||||
|
Color afterColor = default(Color);
|
||||||
|
|
||||||
|
for (int i = 0; i < gradientStops.Count; i++)
|
||||||
|
{
|
||||||
|
Tuple<double, Color> gradientStop = gradientStops[i];
|
||||||
|
double o = gradientStop.Item1;
|
||||||
|
if (o <= offset)
|
||||||
|
beforeStop = gradientStop;
|
||||||
|
|
||||||
|
if (o >= offset)
|
||||||
|
{
|
||||||
|
afterOffset = gradientStop.Item1;
|
||||||
|
afterColor = gradientStop.Item2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
double beforeOffset = beforeStop.Item1;
|
||||||
|
Color beforeColor = beforeStop.Item2;
|
||||||
|
|
||||||
|
double blendFactor = 0f;
|
||||||
|
if (beforeOffset != afterOffset)
|
||||||
|
blendFactor = ((offset - beforeOffset) / (afterOffset - beforeOffset));
|
||||||
|
|
||||||
|
colA = (byte)((afterColor.A - beforeColor.A) * blendFactor + beforeColor.A);
|
||||||
|
colR = (byte)((afterColor.R - beforeColor.R) * blendFactor + beforeColor.R);
|
||||||
|
colG = (byte)((afterColor.G - beforeColor.G) * blendFactor + beforeColor.G);
|
||||||
|
colB = (byte)((afterColor.B - beforeColor.B) * blendFactor + beforeColor.B);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IList<Tuple<double, Color>> FixGradientStops(IList<Tuple<double, Color>> gradientStops)
|
||||||
|
{
|
||||||
|
if (gradientStops == null) return new List<Tuple<double, Color>>();
|
||||||
|
|
||||||
|
List<Tuple<double, Color>> stops = gradientStops.OrderBy(x => x.Item1).ToList();
|
||||||
|
|
||||||
|
Tuple<double, Color> firstStop = stops.First();
|
||||||
|
if (firstStop.Item1 > 0)
|
||||||
|
stops.Insert(0, new Tuple<double, Color>(0, firstStop.Item2));
|
||||||
|
|
||||||
|
Tuple<double, Color> lastStop = stops.Last();
|
||||||
|
if (lastStop.Item1 < 1)
|
||||||
|
stops.Add(new Tuple<double, Color>(1, lastStop.Item2));
|
||||||
|
|
||||||
|
return stops;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int GetHash(IList<Tuple<double, Color>> sequence)
|
||||||
|
{
|
||||||
|
unchecked
|
||||||
|
{
|
||||||
|
return sequence.Aggregate(487, (current, item) => (((current * 31) + item.Item1.GetHashCode()) * 31) + item.Item2.GetHashCode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,4 +1,5 @@
|
|||||||
using Artemis.Profiles.Layers.Abstract;
|
using Artemis.Profiles.Layers.Abstract;
|
||||||
|
using Artemis.ViewModels;
|
||||||
using Artemis.ViewModels.Profiles;
|
using Artemis.ViewModels.Profiles;
|
||||||
|
|
||||||
namespace Artemis.Profiles.Layers.Types.Folder
|
namespace Artemis.Profiles.Layers.Types.Folder
|
||||||
|
|||||||
@ -6,6 +6,7 @@ using Artemis.Profiles.Layers.Interfaces;
|
|||||||
using Artemis.Profiles.Layers.Models;
|
using Artemis.Profiles.Layers.Models;
|
||||||
using Artemis.Properties;
|
using Artemis.Properties;
|
||||||
using Artemis.Utilities;
|
using Artemis.Utilities;
|
||||||
|
using Artemis.ViewModels;
|
||||||
using Artemis.ViewModels.Profiles;
|
using Artemis.ViewModels.Profiles;
|
||||||
|
|
||||||
namespace Artemis.Profiles.Layers.Types.Folder
|
namespace Artemis.Profiles.Layers.Types.Folder
|
||||||
@ -16,6 +17,7 @@ namespace Artemis.Profiles.Layers.Types.Folder
|
|||||||
public bool ShowInEdtor => false;
|
public bool ShowInEdtor => false;
|
||||||
// FolderType pretents to be a keyboard so it's children get drawn
|
// FolderType pretents to be a keyboard so it's children get drawn
|
||||||
public DrawType DrawType => DrawType.Keyboard;
|
public DrawType DrawType => DrawType.Keyboard;
|
||||||
|
public int DrawScale => 1;
|
||||||
|
|
||||||
public ImageSource DrawThumbnail(LayerModel layer)
|
public ImageSource DrawThumbnail(LayerModel layer)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Artemis.Profiles.Layers.Abstract;
|
using Artemis.Profiles.Layers.Abstract;
|
||||||
using Artemis.Profiles.Layers.Interfaces;
|
using Artemis.Profiles.Layers.Interfaces;
|
||||||
|
using Artemis.ViewModels;
|
||||||
using Artemis.ViewModels.Profiles;
|
using Artemis.ViewModels.Profiles;
|
||||||
using Caliburn.Micro;
|
using Caliburn.Micro;
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,7 @@ using Artemis.Profiles.Layers.Interfaces;
|
|||||||
using Artemis.Profiles.Layers.Models;
|
using Artemis.Profiles.Layers.Models;
|
||||||
using Artemis.Properties;
|
using Artemis.Properties;
|
||||||
using Artemis.Utilities;
|
using Artemis.Utilities;
|
||||||
|
using Artemis.ViewModels;
|
||||||
using Artemis.ViewModels.Profiles;
|
using Artemis.ViewModels.Profiles;
|
||||||
|
|
||||||
namespace Artemis.Profiles.Layers.Types.Generic
|
namespace Artemis.Profiles.Layers.Types.Generic
|
||||||
@ -17,6 +18,7 @@ namespace Artemis.Profiles.Layers.Types.Generic
|
|||||||
public string Name => "Generic (Logitech)";
|
public string Name => "Generic (Logitech)";
|
||||||
public bool ShowInEdtor => false;
|
public bool ShowInEdtor => false;
|
||||||
public DrawType DrawType => DrawType.Generic;
|
public DrawType DrawType => DrawType.Generic;
|
||||||
|
public int DrawScale => 1;
|
||||||
|
|
||||||
public ImageSource DrawThumbnail(LayerModel layer)
|
public ImageSource DrawThumbnail(LayerModel layer)
|
||||||
{
|
{
|
||||||
@ -34,12 +36,12 @@ namespace Artemis.Profiles.Layers.Types.Generic
|
|||||||
// If an animation is present, let it handle the drawing
|
// If an animation is present, let it handle the drawing
|
||||||
if (layerModel.LayerAnimation != null && !(layerModel.LayerAnimation is NoneAnimation))
|
if (layerModel.LayerAnimation != null && !(layerModel.LayerAnimation is NoneAnimation))
|
||||||
{
|
{
|
||||||
layerModel.LayerAnimation.Draw(layerModel, c);
|
layerModel.LayerAnimation.Draw(layerModel, c, DrawScale);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise draw the rectangle with its applied dimensions and brush
|
// Otherwise draw the rectangle with its applied dimensions and brush
|
||||||
var rect = layerModel.LayerRect();
|
var rect = layerModel.LayerRect(DrawScale);
|
||||||
|
|
||||||
// Can't meddle with the original brush because it's frozen.
|
// Can't meddle with the original brush because it's frozen.
|
||||||
var brush = layerModel.Brush.Clone();
|
var brush = layerModel.Brush.Clone();
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Artemis.Profiles.Layers.Abstract;
|
using Artemis.Profiles.Layers.Abstract;
|
||||||
using Artemis.Profiles.Layers.Interfaces;
|
using Artemis.Profiles.Layers.Interfaces;
|
||||||
|
using Artemis.ViewModels;
|
||||||
using Artemis.ViewModels.Profiles;
|
using Artemis.ViewModels.Profiles;
|
||||||
using Caliburn.Micro;
|
using Caliburn.Micro;
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,7 @@ using Artemis.Profiles.Layers.Interfaces;
|
|||||||
using Artemis.Profiles.Layers.Models;
|
using Artemis.Profiles.Layers.Models;
|
||||||
using Artemis.Properties;
|
using Artemis.Properties;
|
||||||
using Artemis.Utilities;
|
using Artemis.Utilities;
|
||||||
|
using Artemis.ViewModels;
|
||||||
using Artemis.ViewModels.Profiles;
|
using Artemis.ViewModels.Profiles;
|
||||||
|
|
||||||
namespace Artemis.Profiles.Layers.Types.Headset
|
namespace Artemis.Profiles.Layers.Types.Headset
|
||||||
@ -17,6 +18,7 @@ namespace Artemis.Profiles.Layers.Types.Headset
|
|||||||
public string Name => "Headset";
|
public string Name => "Headset";
|
||||||
public bool ShowInEdtor => false;
|
public bool ShowInEdtor => false;
|
||||||
public DrawType DrawType => DrawType.Headset;
|
public DrawType DrawType => DrawType.Headset;
|
||||||
|
public int DrawScale => 1;
|
||||||
|
|
||||||
public ImageSource DrawThumbnail(LayerModel layer)
|
public ImageSource DrawThumbnail(LayerModel layer)
|
||||||
{
|
{
|
||||||
@ -34,12 +36,12 @@ namespace Artemis.Profiles.Layers.Types.Headset
|
|||||||
// If an animation is present, let it handle the drawing
|
// If an animation is present, let it handle the drawing
|
||||||
if (layerModel.LayerAnimation != null && !(layerModel.LayerAnimation is NoneAnimation))
|
if (layerModel.LayerAnimation != null && !(layerModel.LayerAnimation is NoneAnimation))
|
||||||
{
|
{
|
||||||
layerModel.LayerAnimation.Draw(layerModel, c);
|
layerModel.LayerAnimation.Draw(layerModel, c, DrawScale);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise draw the rectangle with its applied dimensions and brush
|
// Otherwise draw the rectangle with its applied dimensions and brush
|
||||||
var rect = layerModel.LayerRect();
|
var rect = layerModel.LayerRect(DrawScale);
|
||||||
|
|
||||||
// Can't meddle with the original brush because it's frozen.
|
// Can't meddle with the original brush because it's frozen.
|
||||||
var brush = layerModel.Brush.Clone();
|
var brush = layerModel.Brush.Clone();
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using Artemis.Profiles.Layers.Abstract;
|
using Artemis.Profiles.Layers.Abstract;
|
||||||
|
using Artemis.ViewModels;
|
||||||
using Artemis.ViewModels.Profiles;
|
using Artemis.ViewModels.Profiles;
|
||||||
|
|
||||||
namespace Artemis.Profiles.Layers.Types.KeyPress
|
namespace Artemis.Profiles.Layers.Types.KeyPress
|
||||||
|
|||||||
@ -13,6 +13,7 @@ using Artemis.Profiles.Layers.Models;
|
|||||||
using Artemis.Properties;
|
using Artemis.Properties;
|
||||||
using Artemis.Utilities;
|
using Artemis.Utilities;
|
||||||
using Artemis.Utilities.Keyboard;
|
using Artemis.Utilities.Keyboard;
|
||||||
|
using Artemis.ViewModels;
|
||||||
using Artemis.ViewModels.Profiles;
|
using Artemis.ViewModels.Profiles;
|
||||||
|
|
||||||
namespace Artemis.Profiles.Layers.Types.KeyPress
|
namespace Artemis.Profiles.Layers.Types.KeyPress
|
||||||
@ -22,6 +23,7 @@ namespace Artemis.Profiles.Layers.Types.KeyPress
|
|||||||
private readonly DeviceManager _deviceManager;
|
private readonly DeviceManager _deviceManager;
|
||||||
private List<LayerModel> _keyPressLayers;
|
private List<LayerModel> _keyPressLayers;
|
||||||
private LayerModel _layerModel;
|
private LayerModel _layerModel;
|
||||||
|
public int DrawScale => 4;
|
||||||
|
|
||||||
public KeyPressType(DeviceManager deviceManager)
|
public KeyPressType(DeviceManager deviceManager)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -3,6 +3,7 @@ using System.Windows.Forms;
|
|||||||
using Artemis.Profiles.Layers.Abstract;
|
using Artemis.Profiles.Layers.Abstract;
|
||||||
using Artemis.Profiles.Layers.Interfaces;
|
using Artemis.Profiles.Layers.Interfaces;
|
||||||
using Artemis.Utilities;
|
using Artemis.Utilities;
|
||||||
|
using Artemis.ViewModels;
|
||||||
using Artemis.ViewModels.Profiles;
|
using Artemis.ViewModels.Profiles;
|
||||||
using Caliburn.Micro;
|
using Caliburn.Micro;
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,7 @@ using Artemis.Profiles.Layers.Abstract;
|
|||||||
using Artemis.Profiles.Layers.Animations;
|
using Artemis.Profiles.Layers.Animations;
|
||||||
using Artemis.Profiles.Layers.Interfaces;
|
using Artemis.Profiles.Layers.Interfaces;
|
||||||
using Artemis.Profiles.Layers.Models;
|
using Artemis.Profiles.Layers.Models;
|
||||||
|
using Artemis.ViewModels;
|
||||||
using Artemis.ViewModels.Profiles;
|
using Artemis.ViewModels.Profiles;
|
||||||
|
|
||||||
namespace Artemis.Profiles.Layers.Types.Keyboard
|
namespace Artemis.Profiles.Layers.Types.Keyboard
|
||||||
@ -14,6 +15,7 @@ namespace Artemis.Profiles.Layers.Types.Keyboard
|
|||||||
public string Name => "Keyboard";
|
public string Name => "Keyboard";
|
||||||
public bool ShowInEdtor => true;
|
public bool ShowInEdtor => true;
|
||||||
public DrawType DrawType => DrawType.Keyboard;
|
public DrawType DrawType => DrawType.Keyboard;
|
||||||
|
public int DrawScale => 4;
|
||||||
|
|
||||||
public ImageSource DrawThumbnail(LayerModel layer)
|
public ImageSource DrawThumbnail(LayerModel layer)
|
||||||
{
|
{
|
||||||
@ -38,7 +40,7 @@ namespace Artemis.Profiles.Layers.Types.Keyboard
|
|||||||
// If an animation is present, let it handle the drawing
|
// If an animation is present, let it handle the drawing
|
||||||
if (layerModel.LayerAnimation != null && !(layerModel.LayerAnimation is NoneAnimation))
|
if (layerModel.LayerAnimation != null && !(layerModel.LayerAnimation is NoneAnimation))
|
||||||
{
|
{
|
||||||
layerModel.LayerAnimation.Draw(layerModel, c);
|
layerModel.LayerAnimation.Draw(layerModel, c, DrawScale);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,7 +50,7 @@ namespace Artemis.Profiles.Layers.Types.Keyboard
|
|||||||
: new Rect(layerModel.Properties.X*4, layerModel.Properties.Y*4,
|
: new Rect(layerModel.Properties.X*4, layerModel.Properties.Y*4,
|
||||||
layerModel.Properties.Width*4, layerModel.Properties.Height*4);
|
layerModel.Properties.Width*4, layerModel.Properties.Height*4);
|
||||||
|
|
||||||
var clip = layerModel.LayerRect();
|
var clip = layerModel.LayerRect(DrawScale);
|
||||||
|
|
||||||
// Can't meddle with the original brush because it's frozen.
|
// Can't meddle with the original brush because it's frozen.
|
||||||
var brush = layerModel.Brush.Clone();
|
var brush = layerModel.Brush.Clone();
|
||||||
|
|||||||
@ -9,6 +9,7 @@ using Artemis.Profiles.Layers.Models;
|
|||||||
using Artemis.Profiles.Layers.Types.Keyboard;
|
using Artemis.Profiles.Layers.Types.Keyboard;
|
||||||
using Artemis.Properties;
|
using Artemis.Properties;
|
||||||
using Artemis.Utilities;
|
using Artemis.Utilities;
|
||||||
|
using Artemis.ViewModels;
|
||||||
using Artemis.ViewModels.Profiles;
|
using Artemis.ViewModels.Profiles;
|
||||||
|
|
||||||
namespace Artemis.Profiles.Layers.Types.KeyboardGif
|
namespace Artemis.Profiles.Layers.Types.KeyboardGif
|
||||||
@ -18,6 +19,7 @@ namespace Artemis.Profiles.Layers.Types.KeyboardGif
|
|||||||
public string Name => "Keyboard - GIF";
|
public string Name => "Keyboard - GIF";
|
||||||
public bool ShowInEdtor => true;
|
public bool ShowInEdtor => true;
|
||||||
public DrawType DrawType => DrawType.Keyboard;
|
public DrawType DrawType => DrawType.Keyboard;
|
||||||
|
public int DrawScale => 4;
|
||||||
|
|
||||||
public ImageSource DrawThumbnail(LayerModel layer)
|
public ImageSource DrawThumbnail(LayerModel layer)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Artemis.Profiles.Layers.Abstract;
|
using Artemis.Profiles.Layers.Abstract;
|
||||||
using Artemis.Profiles.Layers.Interfaces;
|
using Artemis.Profiles.Layers.Interfaces;
|
||||||
|
using Artemis.ViewModels;
|
||||||
using Artemis.ViewModels.Profiles;
|
using Artemis.ViewModels.Profiles;
|
||||||
using Caliburn.Micro;
|
using Caliburn.Micro;
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,7 @@ using Artemis.Profiles.Layers.Interfaces;
|
|||||||
using Artemis.Profiles.Layers.Models;
|
using Artemis.Profiles.Layers.Models;
|
||||||
using Artemis.Properties;
|
using Artemis.Properties;
|
||||||
using Artemis.Utilities;
|
using Artemis.Utilities;
|
||||||
|
using Artemis.ViewModels;
|
||||||
using Artemis.ViewModels.Profiles;
|
using Artemis.ViewModels.Profiles;
|
||||||
|
|
||||||
namespace Artemis.Profiles.Layers.Types.Mouse
|
namespace Artemis.Profiles.Layers.Types.Mouse
|
||||||
@ -17,6 +18,7 @@ namespace Artemis.Profiles.Layers.Types.Mouse
|
|||||||
public string Name => "Mouse";
|
public string Name => "Mouse";
|
||||||
public bool ShowInEdtor => false;
|
public bool ShowInEdtor => false;
|
||||||
public DrawType DrawType => DrawType.Mouse;
|
public DrawType DrawType => DrawType.Mouse;
|
||||||
|
public int DrawScale => 1;
|
||||||
|
|
||||||
public ImageSource DrawThumbnail(LayerModel layer)
|
public ImageSource DrawThumbnail(LayerModel layer)
|
||||||
{
|
{
|
||||||
@ -36,12 +38,12 @@ namespace Artemis.Profiles.Layers.Types.Mouse
|
|||||||
// If an animation is present, let it handle the drawing
|
// If an animation is present, let it handle the drawing
|
||||||
if (layerModel.LayerAnimation != null && !(layerModel.LayerAnimation is NoneAnimation))
|
if (layerModel.LayerAnimation != null && !(layerModel.LayerAnimation is NoneAnimation))
|
||||||
{
|
{
|
||||||
layerModel.LayerAnimation.Draw(layerModel, c);
|
layerModel.LayerAnimation.Draw(layerModel, c, DrawScale);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise draw the rectangle with its applied dimensions and brush
|
// Otherwise draw the rectangle with its applied dimensions and brush
|
||||||
var rect = layerModel.LayerRect();
|
var rect = layerModel.LayerRect(DrawScale);
|
||||||
|
|
||||||
// Can't meddle with the original brush because it's frozen.
|
// Can't meddle with the original brush because it's frozen.
|
||||||
var brush = layerModel.Brush.Clone();
|
var brush = layerModel.Brush.Clone();
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Artemis.Profiles.Layers.Abstract;
|
using Artemis.Profiles.Layers.Abstract;
|
||||||
using Artemis.Profiles.Layers.Interfaces;
|
using Artemis.Profiles.Layers.Interfaces;
|
||||||
|
using Artemis.ViewModels;
|
||||||
using Artemis.ViewModels.Profiles;
|
using Artemis.ViewModels.Profiles;
|
||||||
using Caliburn.Micro;
|
using Caliburn.Micro;
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,7 @@ using Artemis.Profiles.Layers.Interfaces;
|
|||||||
using Artemis.Profiles.Layers.Models;
|
using Artemis.Profiles.Layers.Models;
|
||||||
using Artemis.Properties;
|
using Artemis.Properties;
|
||||||
using Artemis.Utilities;
|
using Artemis.Utilities;
|
||||||
|
using Artemis.ViewModels;
|
||||||
using Artemis.ViewModels.Profiles;
|
using Artemis.ViewModels.Profiles;
|
||||||
|
|
||||||
namespace Artemis.Profiles.Layers.Types.Mousemat
|
namespace Artemis.Profiles.Layers.Types.Mousemat
|
||||||
@ -17,6 +18,7 @@ namespace Artemis.Profiles.Layers.Types.Mousemat
|
|||||||
public string Name => "Mousemat";
|
public string Name => "Mousemat";
|
||||||
public bool ShowInEdtor => false;
|
public bool ShowInEdtor => false;
|
||||||
public DrawType DrawType => DrawType.Mousemat;
|
public DrawType DrawType => DrawType.Mousemat;
|
||||||
|
public int DrawScale => 1;
|
||||||
|
|
||||||
public ImageSource DrawThumbnail(LayerModel layer)
|
public ImageSource DrawThumbnail(LayerModel layer)
|
||||||
{
|
{
|
||||||
@ -34,12 +36,12 @@ namespace Artemis.Profiles.Layers.Types.Mousemat
|
|||||||
// If an animation is present, let it handle the drawing
|
// If an animation is present, let it handle the drawing
|
||||||
if (layerModel.LayerAnimation != null && !(layerModel.LayerAnimation is NoneAnimation))
|
if (layerModel.LayerAnimation != null && !(layerModel.LayerAnimation is NoneAnimation))
|
||||||
{
|
{
|
||||||
layerModel.LayerAnimation.Draw(layerModel, c);
|
layerModel.LayerAnimation.Draw(layerModel, c, DrawScale);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise draw the rectangle with its applied dimensions and brush
|
// Otherwise draw the rectangle with its applied dimensions and brush
|
||||||
var rect = layerModel.LayerRect();
|
var rect = layerModel.LayerRect(1);
|
||||||
|
|
||||||
// Can't meddle with the original brush because it's frozen.
|
// Can't meddle with the original brush because it's frozen.
|
||||||
var brush = layerModel.Brush.Clone();
|
var brush = layerModel.Brush.Clone();
|
||||||
|
|||||||
@ -108,8 +108,10 @@ namespace Artemis.Profiles
|
|||||||
Rect rect, bool preview)
|
Rect rect, bool preview)
|
||||||
{
|
{
|
||||||
renderLayers = renderLayers.Where(rl => rl.LayerType.DrawType == drawType).ToList();
|
renderLayers = renderLayers.Where(rl => rl.LayerType.DrawType == drawType).ToList();
|
||||||
|
if (!renderLayers.Any())
|
||||||
|
return;
|
||||||
|
|
||||||
var visual = new DrawingVisual();
|
var visual = new DrawingVisual();
|
||||||
var layerModels = renderLayers.ToList();
|
|
||||||
using (var c = visual.RenderOpen())
|
using (var c = visual.RenderOpen())
|
||||||
{
|
{
|
||||||
// Setup the DrawingVisual's size
|
// Setup the DrawingVisual's size
|
||||||
@ -117,12 +119,12 @@ namespace Artemis.Profiles
|
|||||||
c.DrawRectangle(new SolidColorBrush(Color.FromArgb(0, 0, 0, 0)), null, rect);
|
c.DrawRectangle(new SolidColorBrush(Color.FromArgb(0, 0, 0, 0)), null, rect);
|
||||||
|
|
||||||
// Update the layers
|
// Update the layers
|
||||||
foreach (var layerModel in layerModels)
|
foreach (var layerModel in renderLayers)
|
||||||
layerModel.Update(dataModel, preview, true);
|
layerModel.Update(dataModel, preview, true);
|
||||||
RaiseDeviceUpdatedEvent(new ProfileDeviceEventsArg(drawType, dataModel, preview, null));
|
RaiseDeviceUpdatedEvent(new ProfileDeviceEventsArg(drawType, dataModel, preview, null));
|
||||||
|
|
||||||
// Draw the layers
|
// Draw the layers
|
||||||
foreach (var layerModel in layerModels)
|
foreach (var layerModel in renderLayers)
|
||||||
layerModel.Draw(dataModel, c, preview, true);
|
layerModel.Draw(dataModel, c, preview, true);
|
||||||
RaiseDeviceDrawnEvent(new ProfileDeviceEventsArg(drawType, dataModel, preview, c));
|
RaiseDeviceDrawnEvent(new ProfileDeviceEventsArg(drawType, dataModel, preview, c));
|
||||||
|
|
||||||
@ -190,7 +192,6 @@ namespace Artemis.Profiles
|
|||||||
|
|
||||||
public void Activate(LuaManager luaManager)
|
public void Activate(LuaManager luaManager)
|
||||||
{
|
{
|
||||||
if (!Equals(luaManager.ProfileModel, this) || luaManager.ProfileModel.LuaScript != LuaScript)
|
|
||||||
luaManager.SetupLua(this);
|
luaManager.SetupLua(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -53,7 +53,7 @@ using System.Windows;
|
|||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
|
|
||||||
[assembly: AssemblyVersion("1.7.1.0")]
|
[assembly: AssemblyVersion("1.8.0.0")]
|
||||||
[assembly: AssemblyFileVersion("1.7.1.0")]
|
[assembly: AssemblyFileVersion("1.8.0.0")]
|
||||||
[assembly: InternalsVisibleTo("Artemis.Explorables")]
|
[assembly: InternalsVisibleTo("Artemis.Explorables")]
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
12
Artemis/Artemis/Utilities/EditorHelper.cs
Normal file
12
Artemis/Artemis/Utilities/EditorHelper.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Artemis.Utilities
|
||||||
|
{
|
||||||
|
public static class EditorHelper
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user