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

Merge pull request #162 from SpoinkyNL/development

1.3.3.0
This commit is contained in:
Robert Beekman 2016-09-19 19:48:20 +02:00 committed by GitHub
commit 4563027dee
70 changed files with 4097 additions and 559 deletions

View File

@ -40,7 +40,7 @@
<ProductName>Artemis</ProductName> <ProductName>Artemis</ProductName>
<PublisherName>Artemis</PublisherName> <PublisherName>Artemis</PublisherName>
<ApplicationRevision>0</ApplicationRevision> <ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.3.0.0</ApplicationVersion> <ApplicationVersion>1.3.3.0</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust> <UseApplicationTrust>false</UseApplicationTrust>
<CreateDesktopShortcut>true</CreateDesktopShortcut> <CreateDesktopShortcut>true</CreateDesktopShortcut>
<PublishWizardCompleted>true</PublishWizardCompleted> <PublishWizardCompleted>true</PublishWizardCompleted>
@ -151,8 +151,8 @@
<HintPath>..\packages\Colore.5.0.0\lib\net35\Corale.Colore.dll</HintPath> <HintPath>..\packages\Colore.5.0.0\lib\net35\Corale.Colore.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="CUE.NET, Version=1.0.3.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="CUE.NET, Version=1.1.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\CUE.NET.1.0.3\lib\net45\CUE.NET.dll</HintPath> <HintPath>..\packages\CUE.NET.1.1.0\lib\net45\CUE.NET.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="DeltaCompressionDotNet, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1d14d6e5194e7f4a, processorArchitecture=MSIL"> <Reference Include="DeltaCompressionDotNet, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1d14d6e5194e7f4a, processorArchitecture=MSIL">
@ -246,6 +246,10 @@
<HintPath>..\packages\squirrel.windows.1.4.4\lib\Net45\NuGet.Squirrel.dll</HintPath> <HintPath>..\packages\squirrel.windows.1.4.4\lib\Net45\NuGet.Squirrel.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="Process.NET, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Process.NET.1.0.1\lib\Process.NET.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Splat, Version=1.6.2.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="Splat, Version=1.6.2.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Splat.1.6.2\lib\Net45\Splat.dll</HintPath> <HintPath>..\packages\Splat.1.6.2\lib\Net45\Splat.dll</HintPath>
<Private>True</Private> <Private>True</Private>
@ -331,6 +335,7 @@
<Compile Include="DAL\SettingsProvider.cs" /> <Compile Include="DAL\SettingsProvider.cs" />
<Compile Include="DeviceProviders\Corsair\CorsairMice.cs" /> <Compile Include="DeviceProviders\Corsair\CorsairMice.cs" />
<Compile Include="DeviceProviders\Corsair\CorsairHeadsets.cs" /> <Compile Include="DeviceProviders\Corsair\CorsairHeadsets.cs" />
<Compile Include="DeviceProviders\Corsair\CorsairMousemats.cs" />
<Compile Include="DeviceProviders\Corsair\Utilities\KeyMap.cs" /> <Compile Include="DeviceProviders\Corsair\Utilities\KeyMap.cs" />
<Compile Include="DeviceProviders\DeviceProvider.cs" /> <Compile Include="DeviceProviders\DeviceProvider.cs" />
<Compile Include="DeviceProviders\Logitech\G810.cs" /> <Compile Include="DeviceProviders\Logitech\G810.cs" />
@ -363,7 +368,6 @@
<Compile Include="Managers\ProfileManager.cs" /> <Compile Include="Managers\ProfileManager.cs" />
<Compile Include="Models\EffectModel.cs" /> <Compile Include="Models\EffectModel.cs" />
<Compile Include="Models\Interfaces\IDataModel.cs" /> <Compile Include="Models\Interfaces\IDataModel.cs" />
<Compile Include="Modules\Effects\AudioVisualizer\AudioVisualization.cs" />
<Compile Include="Modules\Effects\Bubbles\Bubbles.cs" /> <Compile Include="Modules\Effects\Bubbles\Bubbles.cs" />
<Compile Include="Modules\Effects\WindowsProfile\PerformanceInfo.cs" /> <Compile Include="Modules\Effects\WindowsProfile\PerformanceInfo.cs" />
<Compile Include="Modules\Games\EurotruckSimulator2\Data\Ets2TelemetryData.cs" /> <Compile Include="Modules\Games\EurotruckSimulator2\Data\Ets2TelemetryData.cs" />
@ -385,11 +389,23 @@
<DependentUpon>UnrealTournamentView.xaml</DependentUpon> <DependentUpon>UnrealTournamentView.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Modules\Games\UnrealTournament\UnrealTournamentViewModel.cs" /> <Compile Include="Modules\Games\UnrealTournament\UnrealTournamentViewModel.cs" />
<Compile Include="Modules\Games\WorldofWarcraft\WoWDataModel.cs" /> <Compile Include="Modules\Games\WoW\Data\Int128.cs" />
<Compile Include="Modules\Games\WorldofWarcraft\WoWModel.cs" /> <Compile Include="Modules\Games\WoW\Data\WoWEnums.cs" />
<Compile Include="Modules\Games\WorldofWarcraft\WoWSettings.cs" /> <Compile Include="Modules\Games\WoW\Data\WoWOffsets.cs" />
<Compile Include="Modules\Games\WorldofWarcraft\WoWViewModel.cs" /> <Compile Include="Modules\Games\WoW\Data\WoWStructs.cs" />
<Compile Include="Modules\Games\WorldofWarcraft\WoWAddresses.cs" /> <Compile Include="Modules\Games\WoW\Data\WoWNameCache.cs" />
<Compile Include="Modules\Games\WoW\Data\WoWObjectManager.cs" />
<Compile Include="Modules\Games\WoW\Data\WoWObject.cs" />
<Compile Include="Modules\Games\WoW\Data\WoWPlayer.cs" />
<Compile Include="Modules\Games\WoW\Data\WoWUnit.cs" />
<Compile Include="Modules\Games\WoW\WoWView.xaml.cs">
<DependentUpon>WoWView.xaml</DependentUpon>
</Compile>
<Compile Include="Modules\Games\WoW\WoWDataModel.cs" />
<Compile Include="Modules\Games\WoW\WoWModel.cs" />
<Compile Include="Modules\Games\WoW\WoWSettings.cs" />
<Compile Include="Modules\Games\WoW\WoWViewModel.cs" />
<Compile Include="Modules\Games\WoW\WoWAddresses.cs" />
<Compile Include="Profiles\Layers\Animations\NoneAnimation.cs" /> <Compile Include="Profiles\Layers\Animations\NoneAnimation.cs" />
<Compile Include="Profiles\Layers\Models\EventPropertiesModel.cs" /> <Compile Include="Profiles\Layers\Models\EventPropertiesModel.cs" />
<Compile Include="Profiles\Layers\Models\KeyboardEventPropertiesModel.cs" /> <Compile Include="Profiles\Layers\Models\KeyboardEventPropertiesModel.cs" />
@ -410,10 +426,14 @@
</Compile> </Compile>
<Compile Include="Profiles\Layers\Types\KeyPress\KeyPressPropertiesViewModel.cs" /> <Compile Include="Profiles\Layers\Types\KeyPress\KeyPressPropertiesViewModel.cs" />
<Compile Include="Profiles\Layers\Types\KeyPress\KeyPressType.cs" /> <Compile Include="Profiles\Layers\Types\KeyPress\KeyPressType.cs" />
<Compile Include="Profiles\Layers\Types\Mousemat\MousematPropertiesView.xaml.cs">
<DependentUpon>MousematPropertiesView.xaml</DependentUpon>
</Compile>
<Compile Include="Profiles\Layers\Types\Mousemat\MousematPropertiesViewModel.cs" />
<Compile Include="Profiles\Layers\Types\Mousemat\MousematType.cs" />
<Compile Include="Profiles\ProfileModel.cs" /> <Compile Include="Profiles\ProfileModel.cs" />
<Compile Include="Profiles\Layers\Models\SimplePropertiesModel.cs" /> <Compile Include="Profiles\Layers\Models\SimplePropertiesModel.cs" />
<Compile Include="Profiles\Layers\Types\Keyboard\KeyboardPropertiesModel.cs" /> <Compile Include="Profiles\Layers\Types\Keyboard\KeyboardPropertiesModel.cs" />
<Compile Include="Modules\Effects\AudioVisualizer\AudioVisualizerModel.cs" />
<Compile Include="Modules\Effects\AudioVisualizer\Utilities\FftEventArgs.cs" /> <Compile Include="Modules\Effects\AudioVisualizer\Utilities\FftEventArgs.cs" />
<Compile Include="Modules\Effects\AudioVisualizer\Utilities\SampleAggregator.cs" /> <Compile Include="Modules\Effects\AudioVisualizer\Utilities\SampleAggregator.cs" />
<Compile Include="Modules\Effects\Bubbles\Bubble.cs" /> <Compile Include="Modules\Effects\Bubbles\Bubble.cs" />
@ -632,6 +652,8 @@
<Compile Include="Properties\AssemblyInfo.cs"> <Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>
<None Include="Resources\keypress.png" />
<None Include="Resources\mousemat.png" />
<EmbeddedResource Include="Modules\Games\UnrealTournament\Resources\ut-plugin.zip" /> <EmbeddedResource Include="Modules\Games\UnrealTournament\Resources\ut-plugin.zip" />
<EmbeddedResource Include="Modules\Games\Witcher3\Resources\witcher3-mod.zip" /> <EmbeddedResource Include="Modules\Games\Witcher3\Resources\witcher3-mod.zip" />
<None Include="app.manifest"> <None Include="app.manifest">
@ -713,6 +735,10 @@
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Page> </Page>
<Page Include="Modules\Games\WoW\WoWView.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Profiles\Layers\Types\Audio\AudioPropertiesView.xaml"> <Page Include="Profiles\Layers\Types\Audio\AudioPropertiesView.xaml">
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>
@ -725,6 +751,10 @@
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Page> </Page>
<Page Include="Profiles\Layers\Types\Mousemat\MousematPropertiesView.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Resources\Icons.xaml"> <Page Include="Resources\Icons.xaml">
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>
@ -841,6 +871,7 @@
<None Include="Modules\Games\UnrealTournament\Resources\redeemer.gif" /> <None Include="Modules\Games\UnrealTournament\Resources\redeemer.gif" />
<None Include="Modules\Games\EurotruckSimulator2\Resources\Win32\ets2-telemetry-server.dll" /> <None Include="Modules\Games\EurotruckSimulator2\Resources\Win32\ets2-telemetry-server.dll" />
<None Include="Modules\Games\EurotruckSimulator2\Resources\Win64\ets2-telemetry-server.dll" /> <None Include="Modules\Games\EurotruckSimulator2\Resources\Win64\ets2-telemetry-server.dll" />
<None Include="Resources\audio.png" />
<Content Include="Resources\CounterStrike\csgoGamestateConfiguration.txt" /> <Content Include="Resources\CounterStrike\csgoGamestateConfiguration.txt" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -857,12 +888,12 @@
</ItemGroup> </ItemGroup>
<ItemGroup /> <ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\packages\CUE.NET.1.0.3\build\net45\CUE.NET.targets" Condition="Exists('..\packages\CUE.NET.1.0.3\build\net45\CUE.NET.targets')" /> <Import Project="..\packages\CUE.NET.1.1.0\build\net45\CUE.NET.targets" Condition="Exists('..\packages\CUE.NET.1.1.0\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.0.3\build\net45\CUE.NET.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\CUE.NET.1.0.3\build\net45\CUE.NET.targets'))" /> <Error Condition="!Exists('..\packages\CUE.NET.1.1.0\build\net45\CUE.NET.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\CUE.NET.1.1.0\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.

View File

@ -22,12 +22,12 @@ namespace Artemis.DeviceProviders.Corsair
{ {
CanUse = CanInitializeSdk(); CanUse = CanInitializeSdk();
if (CanUse && !CueSDK.IsInitialized) if (CanUse && !CueSDK.IsInitialized)
CueSDK.Initialize(); CueSDK.Initialize(true);
Logger.Debug("Attempted to enable Corsair headset. CanUse: {0}", CanUse); Logger.Debug("Attempted to enable Corsair headset. CanUse: {0}", CanUse);
if (CanUse) if (CanUse)
CueSDK.HeadsetSDK.UpdateMode = UpdateMode.Manual; CueSDK.UpdateMode = UpdateMode.Manual;
return CanUse; return CanUse;
} }

View File

@ -8,9 +8,9 @@ using Artemis.Properties;
using Artemis.Utilities; using Artemis.Utilities;
using CUE.NET; using CUE.NET;
using CUE.NET.Brushes; using CUE.NET.Brushes;
using CUE.NET.Devices.Generic;
using CUE.NET.Devices.Generic.Enums; using CUE.NET.Devices.Generic.Enums;
using CUE.NET.Devices.Keyboard; using CUE.NET.Devices.Keyboard;
using CUE.NET.Devices.Keyboard.Keys;
using Ninject.Extensions.Logging; using Ninject.Extensions.Logging;
using Point = System.Drawing.Point; using Point = System.Drawing.Point;
@ -44,8 +44,9 @@ namespace Artemis.DeviceProviders.Corsair
public override void Enable() public override void Enable()
{ {
if (!CueSDK.IsInitialized) if (!CueSDK.IsInitialized)
CueSDK.Initialize(); CueSDK.Initialize(true);
CueSDK.UpdateMode = UpdateMode.Manual;
_keyboard = CueSDK.KeyboardSDK; _keyboard = CueSDK.KeyboardSDK;
switch (_keyboard.DeviceInfo.Model) switch (_keyboard.DeviceInfo.Model)
{ {
@ -114,32 +115,32 @@ namespace Artemis.DeviceProviders.Corsair
} }
_keyboardBrush.Image = image; _keyboardBrush.Image = image;
_keyboard.Update(); _keyboard.Update(true);
image.Dispose(); image.Dispose();
} }
public override KeyMatch? GetKeyPosition(Keys keyCode) public override KeyMatch? GetKeyPosition(Keys keyCode)
{ {
var widthMultiplier = Width/_keyboard.KeyboardRectangle.Width; var widthMultiplier = Width/_keyboard.Brush.RenderedRectangle.Width;
var heightMultiplier = Height/_keyboard.KeyboardRectangle.Height; var heightMultiplier = Height/_keyboard.Brush.RenderedRectangle.Height;
CorsairKey cueKey = null; CorsairLed cueLed = null;
try try
{ {
cueKey = _keyboard.Keys.FirstOrDefault(k => k.KeyId.ToString() == keyCode.ToString()) ?? cueLed = _keyboard.Leds.FirstOrDefault(k => k.Id.ToString() == keyCode.ToString()) ??
_keyboard.Keys.FirstOrDefault(k => k.KeyId == KeyMap.FormsKeys[keyCode]); _keyboard.Leds.FirstOrDefault(k => k.Id == KeyMap.FormsKeys[keyCode]);
} }
catch (Exception) catch (Exception)
{ {
// ignored // ignored
} }
if (cueKey != null) if (cueLed != null)
return new KeyMatch(keyCode, (int) (cueKey.KeyRectangle.X*widthMultiplier), return new KeyMatch(keyCode, (int) (cueLed.LedRectangle.X*widthMultiplier),
(int) (cueKey.KeyRectangle.Y*heightMultiplier)); (int) (cueLed.LedRectangle.Y*heightMultiplier));
return null; return null;
} }
} }
} }

View File

@ -22,12 +22,12 @@ namespace Artemis.DeviceProviders.Corsair
{ {
CanUse = CanInitializeSdk(); CanUse = CanInitializeSdk();
if (CanUse && !CueSDK.IsInitialized) if (CanUse && !CueSDK.IsInitialized)
CueSDK.Initialize(); CueSDK.Initialize(true);
Logger.Debug("Attempted to enable Corsair mice. CanUse: {0}", CanUse); Logger.Debug("Attempted to enable Corsair mice. CanUse: {0}", CanUse);
if (CanUse) if (CanUse)
CueSDK.MouseSDK.UpdateMode = UpdateMode.Manual; CueSDK.UpdateMode = UpdateMode.Manual;
return CanUse; return CanUse;
} }

View File

@ -0,0 +1,104 @@
using System;
using System.Drawing;
using System.Linq;
using System.Threading;
using CUE.NET;
using CUE.NET.Devices.Generic.Enums;
using CUE.NET.Devices.Mousemat.Enums;
using Ninject.Extensions.Logging;
namespace Artemis.DeviceProviders.Corsair
{
internal class CorsairMousemats : DeviceProvider
{
public CorsairMousemats(ILogger logger)
{
Logger = logger;
Type = DeviceType.Mousemat;
}
public ILogger Logger { get; set; }
public override bool TryEnable()
{
CanUse = CanInitializeSdk();
if (CanUse && !CueSDK.IsInitialized)
CueSDK.Initialize(true);
Logger.Debug("Attempted to enable Corsair mousemat. CanUse: {0}", CanUse);
if (CanUse)
CueSDK.UpdateMode = UpdateMode.Manual;
return CanUse;
}
public override void Disable()
{
throw new NotImplementedException("Can only disable a keyboard");
}
public override void UpdateDevice(Bitmap bitmap)
{
if (!CanUse || bitmap == null)
return;
if (bitmap.Width != bitmap.Height)
throw new ArgumentException("Bitmap must be a perfect square");
var yStep = (double) bitmap.Width/4;
var xStep = (double) bitmap.Width/6;
// This approach will break if any mousemats with different LED amounts are released, for now it will do.
using (bitmap)
{
var ledIndex = 0;
// Color each LED according to one of the pixels
foreach (var corsairLed in CueSDK.MousematSDK.Leds.OrderBy(l => l.ToString()))
{
Color col;
// Left side
if (ledIndex < 5)
{
col = ledIndex == 0
? bitmap.GetPixel(0, (int) (ledIndex*yStep))
: bitmap.GetPixel(0, (int) (ledIndex*yStep) - 1);
}
// Bottom
else if (ledIndex < 10)
{
// Start at index 1 because the corner belongs to the left side
var zoneIndex = ledIndex - 4;
col = bitmap.GetPixel((int) (zoneIndex*xStep), bitmap.Height - 1);
}
// Right side
else
{
var zoneIndex = ledIndex - 10;
col = zoneIndex == 4
? bitmap.GetPixel(bitmap.Height - 1, bitmap.Height - (int) (zoneIndex*yStep))
: bitmap.GetPixel(bitmap.Height - 1, bitmap.Height - 1 - (int) (zoneIndex*yStep));
}
corsairLed.Color = col;
ledIndex++;
}
}
CueSDK.MousematSDK.Update();
}
private static bool CanInitializeSdk()
{
// This will skip the check-loop if the SDK is initialized
if (CueSDK.IsInitialized)
return CueSDK.IsSDKAvailable(CorsairDeviceType.Mousemat);
for (var tries = 0; tries < 9; tries++)
{
if (CueSDK.IsSDKAvailable(CorsairDeviceType.Mousemat))
return true;
Thread.Sleep(2000);
}
return false;
}
}
}

View File

@ -1,6 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Windows.Forms; using System.Windows.Forms;
using CUE.NET.Devices.Keyboard.Enums; using CUE.NET.Devices.Generic.Enums;
namespace Artemis.DeviceProviders.Corsair.Utilities namespace Artemis.DeviceProviders.Corsair.Utilities
{ {
@ -8,64 +8,64 @@ namespace Artemis.DeviceProviders.Corsair.Utilities
{ {
static KeyMap() static KeyMap()
{ {
FormsKeys = new Dictionary<Keys, CorsairKeyboardKeyId> FormsKeys = new Dictionary<Keys, CorsairLedId>
{ {
{Keys.Scroll, CorsairKeyboardKeyId.ScrollLock}, {Keys.Scroll, CorsairLedId.ScrollLock},
{Keys.Pause, CorsairKeyboardKeyId.PauseBreak}, {Keys.Pause, CorsairLedId.PauseBreak},
{Keys.Back, CorsairKeyboardKeyId.Backspace}, {Keys.Back, CorsairLedId.Backspace},
{Keys.Oemtilde, CorsairKeyboardKeyId.GraveAccentAndTilde}, {Keys.Oemtilde, CorsairLedId.GraveAccentAndTilde},
{Keys.OemMinus, CorsairKeyboardKeyId.MinusAndUnderscore}, {Keys.OemMinus, CorsairLedId.MinusAndUnderscore},
{Keys.Oemplus, CorsairKeyboardKeyId.EqualsAndPlus}, {Keys.Oemplus, CorsairLedId.EqualsAndPlus},
{Keys.OemOpenBrackets, CorsairKeyboardKeyId.BracketLeft}, {Keys.OemOpenBrackets, CorsairLedId.BracketLeft},
{Keys.Oem6, CorsairKeyboardKeyId.BracketRight}, {Keys.Oem6, CorsairLedId.BracketRight},
{Keys.Return, CorsairKeyboardKeyId.Enter}, {Keys.Return, CorsairLedId.Enter},
{Keys.Next, CorsairKeyboardKeyId.PageDown}, {Keys.Next, CorsairLedId.PageDown},
{Keys.Capital, CorsairKeyboardKeyId.CapsLock}, {Keys.Capital, CorsairLedId.CapsLock},
{Keys.Oem1, CorsairKeyboardKeyId.SemicolonAndColon}, {Keys.Oem1, CorsairLedId.SemicolonAndColon},
{Keys.Oem7, CorsairKeyboardKeyId.ApostropheAndDoubleQuote}, {Keys.Oem7, CorsairLedId.ApostropheAndDoubleQuote},
{Keys.OemBackslash, CorsairKeyboardKeyId.Backslash}, {Keys.OemBackslash, CorsairLedId.Backslash},
{Keys.LShiftKey, CorsairKeyboardKeyId.LeftShift}, {Keys.LShiftKey, CorsairLedId.LeftShift},
{Keys.Oem5, CorsairKeyboardKeyId.NonUsBackslash}, {Keys.Oem5, CorsairLedId.NonUsBackslash},
{Keys.Oemcomma, CorsairKeyboardKeyId.CommaAndLessThan}, {Keys.Oemcomma, CorsairLedId.CommaAndLessThan},
{Keys.OemPeriod, CorsairKeyboardKeyId.PeriodAndBiggerThan}, {Keys.OemPeriod, CorsairLedId.PeriodAndBiggerThan},
{Keys.OemQuestion, CorsairKeyboardKeyId.SlashAndQuestionMark}, {Keys.OemQuestion, CorsairLedId.SlashAndQuestionMark},
{Keys.RShiftKey, CorsairKeyboardKeyId.RightShift}, {Keys.RShiftKey, CorsairLedId.RightShift},
{Keys.LControlKey, CorsairKeyboardKeyId.LeftCtrl}, {Keys.LControlKey, CorsairLedId.LeftCtrl},
{Keys.LWin, CorsairKeyboardKeyId.LeftGui}, {Keys.LWin, CorsairLedId.LeftGui},
{Keys.LMenu, CorsairKeyboardKeyId.LeftAlt}, {Keys.LMenu, CorsairLedId.LeftAlt},
{Keys.RMenu, CorsairKeyboardKeyId.RightAlt}, {Keys.RMenu, CorsairLedId.RightAlt},
{Keys.RWin, CorsairKeyboardKeyId.RightGui}, {Keys.RWin, CorsairLedId.RightGui},
{Keys.Apps, CorsairKeyboardKeyId.Application}, {Keys.Apps, CorsairLedId.Application},
{Keys.RControlKey, CorsairKeyboardKeyId.RightCtrl}, {Keys.RControlKey, CorsairLedId.RightCtrl},
{Keys.Left, CorsairKeyboardKeyId.LeftArrow}, {Keys.Left, CorsairLedId.LeftArrow},
{Keys.Down, CorsairKeyboardKeyId.DownArrow}, {Keys.Down, CorsairLedId.DownArrow},
{Keys.Right, CorsairKeyboardKeyId.RightArrow}, {Keys.Right, CorsairLedId.RightArrow},
{Keys.Up, CorsairKeyboardKeyId.UpArrow}, {Keys.Up, CorsairLedId.UpArrow},
{Keys.NumPad0, CorsairKeyboardKeyId.Keypad0}, {Keys.NumPad0, CorsairLedId.Keypad0},
{Keys.NumPad1, CorsairKeyboardKeyId.Keypad1}, {Keys.NumPad1, CorsairLedId.Keypad1},
{Keys.NumPad2, CorsairKeyboardKeyId.Keypad2}, {Keys.NumPad2, CorsairLedId.Keypad2},
{Keys.NumPad3, CorsairKeyboardKeyId.Keypad3}, {Keys.NumPad3, CorsairLedId.Keypad3},
{Keys.NumPad4, CorsairKeyboardKeyId.Keypad4}, {Keys.NumPad4, CorsairLedId.Keypad4},
{Keys.NumPad5, CorsairKeyboardKeyId.Keypad5}, {Keys.NumPad5, CorsairLedId.Keypad5},
{Keys.NumPad6, CorsairKeyboardKeyId.Keypad6}, {Keys.NumPad6, CorsairLedId.Keypad6},
{Keys.NumPad7, CorsairKeyboardKeyId.Keypad7}, {Keys.NumPad7, CorsairLedId.Keypad7},
{Keys.NumPad8, CorsairKeyboardKeyId.Keypad8}, {Keys.NumPad8, CorsairLedId.Keypad8},
{Keys.NumPad9, CorsairKeyboardKeyId.Keypad9}, {Keys.NumPad9, CorsairLedId.Keypad9},
{Keys.Divide, CorsairKeyboardKeyId.KeypadSlash}, {Keys.Divide, CorsairLedId.KeypadSlash},
{Keys.Multiply, CorsairKeyboardKeyId.KeypadAsterisk}, {Keys.Multiply, CorsairLedId.KeypadAsterisk},
{Keys.Subtract, CorsairKeyboardKeyId.KeypadMinus}, {Keys.Subtract, CorsairLedId.KeypadMinus},
{Keys.Add, CorsairKeyboardKeyId.KeypadPlus}, {Keys.Add, CorsairLedId.KeypadPlus},
{Keys.Decimal, CorsairKeyboardKeyId.KeypadPeriodAndDelete}, {Keys.Decimal, CorsairLedId.KeypadPeriodAndDelete},
{Keys.MediaStop, CorsairKeyboardKeyId.Stop}, {Keys.MediaStop, CorsairLedId.Stop},
{Keys.MediaPreviousTrack, CorsairKeyboardKeyId.ScanPreviousTrack}, {Keys.MediaPreviousTrack, CorsairLedId.ScanPreviousTrack},
{Keys.MediaNextTrack, CorsairKeyboardKeyId.ScanNextTrack}, {Keys.MediaNextTrack, CorsairLedId.ScanNextTrack},
{Keys.MediaPlayPause, CorsairKeyboardKeyId.PlayPause}, {Keys.MediaPlayPause, CorsairLedId.PlayPause},
{Keys.VolumeMute, CorsairKeyboardKeyId.Mute}, {Keys.VolumeMute, CorsairLedId.Mute},
{Keys.VolumeUp, CorsairKeyboardKeyId.VolumeUp}, {Keys.VolumeUp, CorsairLedId.VolumeUp},
{Keys.VolumeDown, CorsairKeyboardKeyId.VolumeDown} {Keys.VolumeDown, CorsairLedId.VolumeDown}
}; };
} }
public static Dictionary<Keys, CorsairKeyboardKeyId> FormsKeys { get; set; } public static Dictionary<Keys, CorsairLedId> FormsKeys { get; set; }
} }
} }

View File

@ -46,6 +46,7 @@ namespace Artemis.DeviceProviders
Keyboard, Keyboard,
Mouse, Mouse,
Headset, Headset,
Generic Generic,
Mousemat
} }
} }

View File

@ -22,6 +22,9 @@ namespace Artemis.InjectionModules
// Headsets // Headsets
Bind<DeviceProvider>().To<CorsairHeadsets>().InSingletonScope(); Bind<DeviceProvider>().To<CorsairHeadsets>().InSingletonScope();
// Mousemats
Bind<DeviceProvider>().To<CorsairMousemats>().InSingletonScope();
// Other // Other
Bind<DeviceProvider>().To<LogitechGeneric>().InSingletonScope(); Bind<DeviceProvider>().To<LogitechGeneric>().InSingletonScope();
} }

View File

@ -9,6 +9,7 @@ using Artemis.Profiles.Layers.Types.Keyboard;
using Artemis.Profiles.Layers.Types.KeyboardGif; using Artemis.Profiles.Layers.Types.KeyboardGif;
using Artemis.Profiles.Layers.Types.KeyPress; using Artemis.Profiles.Layers.Types.KeyPress;
using Artemis.Profiles.Layers.Types.Mouse; using Artemis.Profiles.Layers.Types.Mouse;
using Artemis.Profiles.Layers.Types.Mousemat;
using Ninject.Modules; using Ninject.Modules;
namespace Artemis.InjectionModules namespace Artemis.InjectionModules
@ -36,6 +37,7 @@ namespace Artemis.InjectionModules
Bind<ILayerType>().To<KeyboardType>(); Bind<ILayerType>().To<KeyboardType>();
Bind<ILayerType>().To<KeyboardGifType>(); Bind<ILayerType>().To<KeyboardGifType>();
Bind<ILayerType>().To<MouseType>(); Bind<ILayerType>().To<MouseType>();
Bind<ILayerType>().To<MousematType>();
Bind<ILayerType>().To<GenericType>(); Bind<ILayerType>().To<GenericType>();
Bind<ILayerType>().To<KeyPressType>(); Bind<ILayerType>().To<KeyPressType>();
Bind<ILayerType>().To<AudioType>(); Bind<ILayerType>().To<AudioType>();

View File

@ -31,6 +31,7 @@ namespace Artemis.Managers
MiceProviders = deviceProviders.Where(d => d.Type == DeviceType.Mouse).ToList(); MiceProviders = deviceProviders.Where(d => d.Type == DeviceType.Mouse).ToList();
HeadsetProviders = deviceProviders.Where(d => d.Type == DeviceType.Headset).ToList(); HeadsetProviders = deviceProviders.Where(d => d.Type == DeviceType.Headset).ToList();
GenericProviders = deviceProviders.Where(d => d.Type == DeviceType.Generic).ToList(); GenericProviders = deviceProviders.Where(d => d.Type == DeviceType.Generic).ToList();
MousematProviders = deviceProviders.Where(d => d.Type == DeviceType.Mousemat).ToList();
_logger.Info("Intialized DeviceManager with {0} device providers", deviceProviders.Count); _logger.Info("Intialized DeviceManager with {0} device providers", deviceProviders.Count);
} }
@ -38,6 +39,7 @@ namespace Artemis.Managers
public List<DeviceProvider> MiceProviders { get; set; } public List<DeviceProvider> MiceProviders { get; set; }
public List<DeviceProvider> HeadsetProviders { get; set; } public List<DeviceProvider> HeadsetProviders { get; set; }
public List<DeviceProvider> GenericProviders { get; set; } public List<DeviceProvider> GenericProviders { get; set; }
public List<DeviceProvider> MousematProviders { get; set; }
[Inject] [Inject]
public MetroDialogService DialogService { get; set; } public MetroDialogService DialogService { get; set; }
@ -47,6 +49,8 @@ namespace Artemis.Managers
public KeyboardProvider ActiveKeyboard { get; set; } public KeyboardProvider ActiveKeyboard { get; set; }
public bool ChangingKeyboard { get; private set; } public bool ChangingKeyboard { get; private set; }
public event EventHandler<KeyboardChangedEventArgs> OnKeyboardChangedEvent; public event EventHandler<KeyboardChangedEventArgs> OnKeyboardChangedEvent;
/// <summary> /// <summary>
@ -137,6 +141,8 @@ namespace Artemis.Managers
headsetProvider.TryEnableAsync(); headsetProvider.TryEnableAsync();
foreach (var genericProvider in GenericProviders) foreach (var genericProvider in GenericProviders)
genericProvider.TryEnableAsync(); genericProvider.TryEnableAsync();
foreach (var mousematProviders in MousematProviders)
mousematProviders.TryEnableAsync();
} }
/// <summary> /// <summary>

View File

@ -132,18 +132,20 @@ namespace Artemis.Managers
var mice = _deviceManager.MiceProviders.Where(m => m.CanUse).ToList(); var mice = _deviceManager.MiceProviders.Where(m => m.CanUse).ToList();
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 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))
{ {
if (renderEffect.Initialized) if (renderEffect.Initialized)
renderEffect.Render(frame, !mice.Any() && !headsets.Any() && !generics.Any()); renderEffect.Render(frame, keyboardOnly);
// Draw enabled overlays on top of the renderEffect // Draw enabled overlays on top of the renderEffect
foreach (var overlayModel in _effectManager.EnabledOverlays) foreach (var overlayModel in _effectManager.EnabledOverlays)
{ {
overlayModel.Update(); overlayModel.Update();
overlayModel.RenderOverlay(frame, !mice.Any() && !headsets.Any() && !generics.Any()); overlayModel.RenderOverlay(frame, keyboardOnly);
} }
// Update the keyboard // Update the keyboard
@ -156,6 +158,8 @@ namespace Artemis.Managers
headset.UpdateDevice(frame.HeadsetBitmap); headset.UpdateDevice(frame.HeadsetBitmap);
foreach (var generic in generics) foreach (var generic in generics)
generic.UpdateDevice(frame.GenericBitmap); generic.UpdateDevice(frame.GenericBitmap);
foreach (var mousemat in mousemats)
mousemat.UpdateDevice(frame.MousematBitmap);
} }
} }
} }
@ -177,6 +181,9 @@ namespace Artemis.Managers
GenericBitmap = new Bitmap(40, 40); GenericBitmap = new Bitmap(40, 40);
GenericBitmap.SetResolution(96, 96); 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);
using (var g = Graphics.FromImage(MouseBitmap)) using (var g = Graphics.FromImage(MouseBitmap))
@ -185,12 +192,15 @@ namespace Artemis.Managers
g.Clear(Color.Black); g.Clear(Color.Black);
using (var g = Graphics.FromImage(GenericBitmap)) using (var g = Graphics.FromImage(GenericBitmap))
g.Clear(Color.Black); g.Clear(Color.Black);
using (var g = Graphics.FromImage(MousematBitmap))
g.Clear(Color.Black);
} }
public Bitmap KeyboardBitmap { get; set; } public Bitmap KeyboardBitmap { get; set; }
public Bitmap MouseBitmap { get; set; } public Bitmap MouseBitmap { get; set; }
public Bitmap HeadsetBitmap { get; set; } public Bitmap HeadsetBitmap { get; set; }
public Bitmap GenericBitmap { get; set; } public Bitmap GenericBitmap { get; set; }
public Bitmap MousematBitmap { get; set; }
public void Dispose() public void Dispose()
{ {

View File

@ -114,7 +114,7 @@ namespace Artemis.Managers
if (!ProgramEnabled) if (!ProgramEnabled)
return; return;
var runningProcesses = Process.GetProcesses(); var runningProcesses = System.Diagnostics.Process.GetProcesses();
// If the currently active effect is a disabled game, get rid of it. // If the currently active effect is a disabled game, get rid of it.
if (EffectManager.ActiveEffect != null) if (EffectManager.ActiveEffect != null)

View File

@ -88,6 +88,12 @@ namespace Artemis.Models
Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Generic), Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Generic),
DataModel, devRec, false, true); DataModel, devRec, false, true);
} }
// Render mousemats layer-by-layer
using (var g = Graphics.FromImage(frame.MousematBitmap))
{
Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Mousemat),
DataModel, devRec, false, true);
}
// Trace debugging // Trace debugging
if (DateTime.Now.AddSeconds(-2) <= LastTrace) if (DateTime.Now.AddSeconds(-2) <= LastTrace)

View File

@ -1,23 +0,0 @@
using System.ComponentModel;
using System.Configuration;
namespace Artemis.Modules.Effects.AudioVisualizer
{
// This class allows you to handle specific events on the settings class:
// The SettingChanging event is raised before a setting's value is changed.
// The PropertyChanged event is raised after a setting's value is changed.
// The SettingsLoaded event is raised after the setting values are loaded.
// The SettingsSaving event is raised before the setting values are saved.
internal sealed partial class AudioVisualization
{
private void SettingChangingEventHandler(object sender, SettingChangingEventArgs e)
{
// Add code to handle the SettingChangingEvent event here.
}
private void SettingsSavingEventHandler(object sender, CancelEventArgs e)
{
// Add code to handle the SettingsSaving event here.
}
}
}

View File

@ -1,206 +0,0 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using Artemis.Managers;
using Artemis.Models;
using Artemis.Modules.Effects.AudioVisualizer.Utilities;
using Artemis.Profiles.Layers.Models;
using Artemis.Utilities;
using Artemis.Utilities.Keyboard;
using NAudio.CoreAudioApi;
using NAudio.Wave;
namespace Artemis.Modules.Effects.AudioVisualizer
{
public class AudioVisualizerModel : EffectModel
{
private const int FftLength = 2048;
private readonly SampleAggregator _sampleAggregator = new SampleAggregator(FftLength);
private bool _fromBottom;
private bool _generating;
private int _sensitivity;
private IWaveIn _waveIn;
public AudioVisualizerModel(MainManager mainManager) : base(mainManager, null, null)
{
Name = "Audiovisualizer";
DeviceIds = new List<string>();
SpectrumData = new List<byte>();
Initialized = false;
}
public int Lines { get; set; }
public List<byte> SpectrumData { get; set; }
public List<KeyboardRectangle> SoundRectangles { get; set; }
public List<string> DeviceIds { get; set; }
public string SelectedDeviceId { get; set; }
public override void Dispose()
{
Initialized = false;
_sampleAggregator.PerformFFT = false;
_sampleAggregator.FftCalculated -= FftCalculated;
if (_waveIn == null)
return;
_waveIn.StopRecording();
_waveIn.DataAvailable -= OnDataAvailable;
_waveIn = null;
}
public override void Enable()
{
Initialized = false;
Lines = MainManager.DeviceManager.ActiveKeyboard.Width;
// TODO: Device selection
SelectedDeviceId = new MMDeviceEnumerator()
.EnumerateAudioEndPoints(DataFlow.All, DeviceState.Active)
.FirstOrDefault()?.ID;
// Apply settings
SoundRectangles = new List<KeyboardRectangle>();
for (var i = 0; i < Lines; i++)
{
SoundRectangles.Add(new KeyboardRectangle(
MainManager.DeviceManager.ActiveKeyboard,
0, 0, new List<Color>
{
Color.Red,
Color.Yellow,
Color.Lime
},
LinearGradientMode.Vertical)
{ContainedBrush = false, Height = 0});
}
_sensitivity = 2;
_fromBottom = true;
_sampleAggregator.FftCalculated += FftCalculated;
_sampleAggregator.PerformFFT = true;
// Start listening for sound data
_waveIn = new WasapiLoopbackCapture();
_waveIn.DataAvailable += OnDataAvailable;
_waveIn.StartRecording();
Initialized = true;
}
public override void Update()
{
// TODO: Use lock instead of a bool
// Start filling the model
_generating = true;
if (SelectedDeviceId == null)
return;
var device = new MMDeviceEnumerator()
.EnumerateAudioEndPoints(DataFlow.All, DeviceState.Active)
.FirstOrDefault(d => d.ID == SelectedDeviceId);
if (device == null || SpectrumData == null)
return;
if (!SpectrumData.Any())
return;
// Parse spectrum data
for (var i = 0; i < Lines; i++)
{
int height;
if (SpectrumData.Count - 1 < i || SpectrumData[i] == 0)
height = 0;
else
height = (int) Math.Round(SpectrumData[i]/2.55);
// Apply Sensitivity setting
height = height*_sensitivity;
var keyboardHeight =
(int) Math.Round(MainManager.DeviceManager.ActiveKeyboard.Height/100.00*height*KeyboardScale);
if (keyboardHeight > SoundRectangles[i].Height)
SoundRectangles[i].Height = keyboardHeight;
else
SoundRectangles[i].Height = SoundRectangles[i].Height -
5; // was FadeSpeed setting
// Apply Bars setting
SoundRectangles[i].X = i*KeyboardScale;
SoundRectangles[i].Width = KeyboardScale;
if (_fromBottom)
SoundRectangles[i].Y = MainManager.DeviceManager.ActiveKeyboard.Height*KeyboardScale -
SoundRectangles[i].Height;
}
_generating = false;
}
private void OnDataAvailable(object sender, WaveInEventArgs e)
{
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);
}
}
private void FftCalculated(object sender, FftEventArgs e)
{
if (_generating)
return;
int x;
var b0 = 0;
SpectrumData.Clear();
for (x = 0; x < Lines; x++)
{
float peak = 0;
var b1 = (int) Math.Pow(2, x*10.0/(Lines - 1));
if (b1 > 2047)
b1 = 2047;
if (b1 <= b0)
b1 = b0 + 1;
for (; b0 < b1; b0++)
{
if (peak < e.Result[1 + b0].X)
peak = e.Result[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);
}
}
public override List<LayerModel> GetRenderLayers(bool keyboardOnly)
{
return null;
}
public override void Render(RenderFrame frame, bool keyboardOnly)
{
if (SpectrumData == null || SoundRectangles == null)
return;
// Lock the _spectrumData array while busy with it
_generating = true;
using (var g = Graphics.FromImage(frame.KeyboardBitmap))
{
foreach (var soundRectangle in SoundRectangles)
soundRectangle.Draw(g);
}
_generating = false;
}
}
}

View File

@ -3,110 +3,31 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
xmlns:cal="http://www.caliburnproject.org"
xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
mc:Ignorable="d" mc:Ignorable="d"
d:DesignHeight="476.986" d:DesignWidth="538.772"> d:DesignHeight="476.986" d:DesignWidth="538.772">
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto"> <ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
<Grid Margin="15, 5, 15, 5"> <Grid Margin="15, 5, 15, 5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<StackPanel Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Margin="0,0,1,0"> <Label Grid.Row="0" FontSize="20" MaxWidth="500" HorizontalAlignment="Left">
<Label FontSize="20" HorizontalAlignment="Left"> <Label.Content>
<Label.Content> <AccessText TextWrapping="Wrap" Text="Gone!" />
<AccessText TextWrapping="Wrap" </Label.Content>
Text="Visualizes the default audio device on the keyboard." /> </Label>
</Label.Content>
</Label>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Label Content="Enable effect" Margin="0 3 0 0" HorizontalAlignment="Right" />
<ToggleButton x:Name="EffectEnabled" Margin="0 3 0 0" Width="25" Height="25"
Style="{DynamicResource MetroCircleToggleButtonStyle}"
cal:Message.Attach="[Event Click] = [Action ToggleEffect]"
ToolTip="Note: You can't enable an effect when Artemis is disabled" />
</StackPanel>
</StackPanel>
<!-- Top color -->
<TextBlock Grid.Row="1" Grid.Column="0" HorizontalAlignment="Left" VerticalAlignment="Center"
Height="16" Margin="0,8">
Color used on top
</TextBlock>
<xctk:ColorPicker x:Name="TopColor"
SelectedColor="{Binding Path=EffectSettings.TopColor, Mode=TwoWay}"
Grid.Row="1" Grid.Column="1" Width="110" HorizontalAlignment="Right"
VerticalAlignment="Center" Margin="0,5,-1,5" Height="22" />
<!-- Middle color --> <TextBlock Grid.Row="1" VerticalAlignment="Center" Margin="0,8" TextWrapping="Wrap"
<TextBlock Grid.Row="2" Grid.Column="0" HorizontalAlignment="Left" VerticalAlignment="Center" HorizontalAlignment="Left" TextAlignment="Justify">
Height="16" Margin="0,8"> <Run Text="In case you're wondering where these effects went, they are now part of the layer system." />
Color used in the middle <LineBreak />
<Run Text="To use them, navigate to the Windows Profile effect and select one of these profiles:" />
<LineBreak /><Run Text="• Default - Type waves" /><LineBreak />
<Run Text="• Default - Audio visualization" /><LineBreak /><Run /><LineBreak />
<Run Text="You can also add these effects to your own profile, even in games! " /><LineBreak />
<Run
Text="To do so, create a new layer, open up its property window and change the type according to what you want it to be, 'key press' or 'audio visualization'." />
</TextBlock> </TextBlock>
<xctk:ColorPicker x:Name="MiddleColor"
SelectedColor="{Binding Path=EffectSettings.MiddleColor, Mode=TwoWay}"
Grid.Row="2" Grid.Column="1" Width="110" HorizontalAlignment="Right"
VerticalAlignment="Center" Margin="0,5,-1,5" Height="22" />
<!-- Bottom color -->
<TextBlock Grid.Row="3" Grid.Column="0" HorizontalAlignment="Left" VerticalAlignment="Center"
Height="16" Margin="0,8">
Color used on the bottom
</TextBlock>
<xctk:ColorPicker x:Name="Bottom"
SelectedColor="{Binding Path=EffectSettings.BottomColor, Mode=TwoWay}"
Grid.Row="3" Grid.Column="1" Width="110" HorizontalAlignment="Right"
VerticalAlignment="Center" Margin="0,5,-1,5" Height="22" />
<!-- Bar direction -->
<TextBlock Grid.Row="4" Grid.Column="0" HorizontalAlignment="Left" VerticalAlignment="Center"
Height="16" Margin="0,9,0,10">
Grow bars bottom
</TextBlock>
<controls:ToggleSwitch IsChecked="{Binding Path=EffectSettings.FromBottom, Mode=TwoWay}"
Grid.Row="4" Grid.Column="1" HorizontalAlignment="Right" OnLabel="Yes"
OffLabel="No" Margin="0,0,-5,0" Width="114" />
<!-- Sensitivity -->
<TextBlock Grid.Row="5" Grid.Column="0" HorizontalAlignment="Left" VerticalAlignment="Center"
Height="16" Margin="0,8">
Volume sensitivity multiplier
</TextBlock>
<Slider x:Name="Sensitivity" Grid.Row="5" Grid.Column="1" VerticalAlignment="Center"
HorizontalAlignment="Right" Width="110" TickPlacement="BottomRight" TickFrequency="1"
Value="{Binding Path=EffectSettings.Sensitivity, Mode=TwoWay}" Minimum="1" Maximum="10"
SmallChange="1" IsSnapToTickEnabled="True" />
<!-- Fade speed -->
<TextBlock Grid.Row="6" Grid.Column="0" HorizontalAlignment="Left" VerticalAlignment="Center"
Height="16" Margin="0,8">
Bar fade-out speed
</TextBlock>
<Slider x:Name="FadeSpeed" Grid.Row="6" Grid.Column="1" VerticalAlignment="Center"
HorizontalAlignment="Right" Width="110" TickPlacement="BottomRight" TickFrequency="1"
Value="{Binding Path=EffectSettings.FadeSpeed, Mode=TwoWay}" Minimum="1" Maximum="3"
SmallChange="1" IsSnapToTickEnabled="True" />
<!-- Buttons -->
<StackPanel Grid.Column="0" Grid.Row="7" Orientation="Horizontal" VerticalAlignment="Bottom">
<Button x:Name="ResetSettings" Content="Reset effect" VerticalAlignment="Top" Width="100"
Style="{DynamicResource SquareButtonStyle}" />
<Button x:Name="SaveSettings" Content="Save changes" VerticalAlignment="Top" Width="100"
Margin="10,0,0,0"
Style="{DynamicResource SquareButtonStyle}" />
</StackPanel>
</Grid> </Grid>
</ScrollViewer> </ScrollViewer>
</UserControl> </UserControl>

View File

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

View File

@ -79,6 +79,13 @@ namespace Artemis.Modules.Effects.ProfilePreview
DataModel, DataModel,
devRec, true, true); devRec, true, true);
} }
// Render mousemats layer-by-layer
using (var g = Graphics.FromImage(frame.MousematBitmap))
{
Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Mousemat),
DataModel,
devRec, true, true);
}
} }
} }
} }

View File

@ -19,21 +19,39 @@
<RowDefinition /> <RowDefinition />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<StackPanel Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Margin="0,0,1,0"> <Grid Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Margin="0,0,1,0">
<Label FontSize="20" HorizontalAlignment="Left"> <Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.ColumnSpan="2" FontSize="20" HorizontalAlignment="Left">
<Label.Content> <Label.Content>
<AccessText TextWrapping="Wrap" <AccessText TextWrapping="Wrap"
Text="By default colors the keyboard according to the chosen hero and shows ability cooldowns." /> Text="By default colors the keyboard according to the chosen hero and shows ability cooldowns." />
</Label.Content> </Label.Content>
</Label> </Label>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<TextBlock Grid.Row="1" Grid.Column="0" VerticalAlignment="Bottom"
TextWrapping="Wrap" HorizontalAlignment="Left" FontFamily="Segoe UI Semibold"
TextAlignment="Justify" Margin="5,0,0,10">
Note: If you're having trouble getting the profile to work, check out
<Hyperlink RequestNavigate="Hyperlink_RequestNavigate"
NavigateUri="https://github.com/SpoinkyNL/Artemis/wiki/Overwatch">
the wiki
</Hyperlink>
</TextBlock>
<StackPanel Orientation="Horizontal" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Right">
<Label Content="Enable effect" Margin="0 3 0 0" HorizontalAlignment="Right" /> <Label Content="Enable effect" Margin="0 3 0 0" HorizontalAlignment="Right" />
<ToggleButton x:Name="EffectEnabled" Margin="0 3 0 0" Width="25" Height="25" <ToggleButton x:Name="EffectEnabled" Margin="0 3 0 0" Width="25" Height="25"
IsChecked="{Binding Path=GameSettings.Enabled, Mode=TwoWay}" IsChecked="{Binding Path=GameSettings.Enabled, Mode=TwoWay}"
Style="{DynamicResource MetroCircleToggleButtonStyle}" Style="{DynamicResource MetroCircleToggleButtonStyle}"
cal:Message.Attach="[Event Click] = [Action ToggleEffect]" /> cal:Message.Attach="[Event Click] = [Action ToggleEffect]" />
</StackPanel> </StackPanel>
</StackPanel> </Grid>
<!-- Game directory --> <!-- Game directory -->
<StackPanel Grid.Row="1" <StackPanel Grid.Row="1"
@ -52,7 +70,8 @@
</StackPanel> </StackPanel>
<!-- Profile editor --> <!-- Profile editor -->
<ContentControl Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" x:Name="ProfileEditor" Margin="0,0,-30,0" /> <ContentControl Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" x:Name="ProfileEditor"
Margin="0,0,-30,0" />
<!-- Buttons --> <!-- Buttons -->
<StackPanel Grid.Column="0" Grid.Row="3" Orientation="Horizontal" VerticalAlignment="Bottom"> <StackPanel Grid.Column="0" Grid.Row="3" Orientation="Horizontal" VerticalAlignment="Bottom">
@ -63,5 +82,6 @@
Style="{DynamicResource SquareButtonStyle}" /> Style="{DynamicResource SquareButtonStyle}" />
</StackPanel> </StackPanel>
</Grid> </Grid>
</ScrollViewer> </ScrollViewer>
</UserControl> </UserControl>

View File

@ -1,4 +1,5 @@
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Navigation;
namespace Artemis.Modules.Games.Overwatch namespace Artemis.Modules.Games.Overwatch
{ {
@ -11,5 +12,10 @@ namespace Artemis.Modules.Games.Overwatch
{ {
InitializeComponent(); InitializeComponent();
} }
private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e)
{
System.Diagnostics.Process.Start(e.Uri.ToString());
}
} }
} }

View File

@ -74,8 +74,7 @@ namespace Artemis.Modules.Games.Witcher3
archive.ExtractToDirectory(folder + @"witcher3-mod", true); archive.ExtractToDirectory(folder + @"witcher3-mod", true);
Process.Start( System.Diagnostics.Process.Start(new ProcessStartInfo("https://github.com/SpoinkyNL/Artemis/wiki/The-Witcher-3"));
new ProcessStartInfo("https://github.com/SpoinkyNL/Artemis/wiki/The-Witcher-3"));
return; return;
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,157 @@
namespace Artemis.Modules.Games.WoW.Data
{
public static class WoWEnums
{
public enum GuidType : byte
{
Null = 0,
Uniq = 1,
Player = 2,
Item = 3,
StaticDoor = 4,
Transport = 5,
Conversation = 6,
Creature = 7,
Vehicle = 8,
Pet = 9,
GameObject = 10,
DynamicObject = 11,
AreaTrigger = 12,
Corpse = 13,
LootObject = 14,
SceneObject = 15,
Scenario = 16,
AiGroup = 17,
DynamicDoor = 18,
ClientActor = 19,
Vignette = 20,
CallForHelp = 21,
AiResource = 22,
AiLock = 23,
AiLockTicket = 24,
ChatChannel = 25,
Party = 26,
Guild = 27,
WowAccount = 28,
BNetAccount = 29,
GmTask = 30,
MobileSession = 31,
RaidGroup = 32,
Spell = 33,
Mail = 34,
WebObj = 35,
LfgObject = 36,
LfgList = 37,
UserRouter = 38,
PvpQueueGroup = 39,
UserClient = 40,
PetBattle = 41,
UniqueUserClient = 42,
BattlePet = 43
}
public enum ObjectType
{
Object = 0,
Item = 1,
Container = 2,
Unit = 3,
Player = 4,
GameObject = 5,
DynamicObject = 6,
Corpse = 7,
AreaTrigger = 8,
SceneObject = 9,
Conversation = 10
}
public enum PowerType
{
Mana = 0,
Rage = 1,
Focus = 2,
Energy = 3,
Happiness = 4,
RunicPower = 5,
Runes = 6,
Health = 7,
Maelstrom = 11,
Insanity = 13,
Fury = 17,
Pain = 18,
UNKNOWN
}
public enum Reaction
{
Hostile = 1,
Neutral = 3,
Friendly = 4
}
public enum ShapeshiftForm
{
Normal = 0,
Cat = 1,
TreeOfLife = 2,
Travel = 3,
Aqua = 4,
Bear = 5,
Ambient = 6,
Ghoul = 7,
DireBear = 8,
CreatureBear = 14,
CreatureCat = 15,
GhostWolf = 16,
BattleStance = 17,
DefensiveStance = 18,
BerserkerStance = 19,
EpicFlightForm = 27,
Shadow = 28,
Stealth = 30,
Moonkin = 31,
SpiritOfRedemption = 32
}
public enum WoWClass
{
None = 0,
Warrior = 1,
Paladin = 2,
Hunter = 3,
Rogue = 4,
Priest = 5,
DeathKnight = 6,
Shaman = 7,
Mage = 8,
Warlock = 9,
Druid = 11
}
public enum WoWRace
{
Human = 1,
Orc = 2,
Dwarf = 3,
NightElf = 4,
Undead = 5,
Tauren = 6,
Gnome = 7,
Troll = 8,
Goblin = 9,
BloodElf = 10,
Draenei = 11,
FelOrc = 12,
Naga = 13,
Broken = 14,
Skeleton = 15,
Worgen = 22
}
public enum WoWType
{
Player,
Npc
}
}
}

View File

@ -0,0 +1,63 @@
using System;
using System.Text;
using Process.NET;
namespace Artemis.Modules.Games.WoW.Data
{
public class WoWNameCache
{
public WoWNameCache(ProcessSharp process, IntPtr baseAddress)
{
Process = process;
CurrentCacheAddress = process.Native.MainModule.BaseAddress + baseAddress.ToInt32();
}
public ProcessSharp Process { get; set; }
public IntPtr CurrentCacheAddress { get; set; }
public WoWDetails GetNameByGuid(Guid searchGuid)
{
var current = Process.Memory.Read<IntPtr>(CurrentCacheAddress);
var index = 0;
while (current != IntPtr.Zero)
{
var guid = Process.Memory.Read<Guid>(current + 0x20);
if (guid.Equals(searchGuid))
{
var pRace = Process.Memory.Read<int>(current + 0x88);
var pClass = Process.Memory.Read<int>(current + 0x90);
var pName = Process.Memory.Read(current + 0x31, Encoding.ASCII, 48);
var name = new WoWDetails(guid, pRace, pClass, WoWEnums.WoWType.Player, pName);
return name;
}
if (index > 20000)
return null;
index++;
current = Process.Memory.Read<IntPtr>(current);
}
return null;
}
}
public class WoWDetails
{
public WoWDetails(Guid guid, int race, int @class, WoWEnums.WoWType type, string name)
{
Guid = guid;
Race = (WoWEnums.WoWRace) race;
Class = (WoWEnums.WoWClass) @class;
Type = type;
Name = name;
}
public Guid Guid { get; set; }
public WoWEnums.WoWRace Race { get; set; }
public WoWEnums.WoWClass Class { get; set; }
public WoWEnums.WoWType Type { get; set; }
public string Name { get; set; }
}
}

View File

@ -0,0 +1,73 @@
using System;
using System.Text;
using Newtonsoft.Json;
using Process.NET;
namespace Artemis.Modules.Games.WoW.Data
{
public class WoWObject
{
private readonly bool _readPointer;
public WoWObject(IProcess process, IntPtr baseAddress, bool readPointer = false)
{
Process = process;
BaseAddress = baseAddress;
_readPointer = readPointer;
Guid = ReadField<Guid>(0x00);
}
[JsonIgnore]
public IntPtr BaseAddress { get; set; }
[JsonIgnore]
public IProcess Process { get; set; }
public Guid Guid { get; set; }
[JsonIgnore]
public WoWStructs.ObjectData Data { get; set; }
public T ReadField<T>(int offset)
{
var address = GetAddress();
if (address == IntPtr.Zero)
return default(T);
var ptr = Process.Memory.Read<IntPtr>(address + 0x10);
return Process.Memory.Read<T>(ptr + offset);
}
public T ReadField<T>(Enum offset)
{
var address = GetAddress();
if (address == IntPtr.Zero)
return default(T);
var ptr = Process.Memory.Read<IntPtr>(address + 0x10);
return Process.Memory.Read<T>(ptr + Convert.ToInt32(offset));
}
private IntPtr GetAddress()
{
return _readPointer
? Process.Memory.Read<IntPtr>(Process.Native.MainModule.BaseAddress + BaseAddress.ToInt32())
: BaseAddress;
}
public WoWDetails GetNpcDetails()
{
var address = GetAddress();
if (address == IntPtr.Zero)
return null;
var npcCachePtr = Process.Memory.Read<IntPtr>(address + 0x1760);
if (npcCachePtr == IntPtr.Zero)
return null;
var npcName = Process.Memory.Read(Process.Memory.Read<IntPtr>(npcCachePtr + 0x00A0), Encoding.ASCII, 48);
return new WoWDetails(Guid, 0, 0, WoWEnums.WoWType.Npc, npcName);
}
}
}

View File

@ -0,0 +1,92 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Process.NET;
namespace Artemis.Modules.Games.WoW.Data
{
public class WoWObjectManager
{
public WoWObjectManager(IProcess process, IntPtr baseAddress)
{
Process = process;
CurrentManagerAddress = process.Native.MainModule.BaseAddress + baseAddress.ToInt32();
}
public IProcess Process { get; set; }
public IntPtr CurrentManagerAddress { get; set; }
public Dictionary<WoWStructs.Guid, WoWObject> WoWObjects { get; set; }
public IntPtr GetFirstObject()
{
var mgr = GetCurrentManager();
return mgr.VisibleObjects.m_fulllist.baseClass.m_terminator.m_next;
}
public WoWStructs.CurrentManager GetCurrentManager()
{
return Process.Memory.Read<WoWStructs.CurrentManager>(Process.Memory.Read<IntPtr>(CurrentManagerAddress));
}
public IntPtr GetNextObjectFromCurrent(IntPtr current)
{
var mgr = GetCurrentManager();
return Process.Memory.Read<IntPtr>(
current + mgr.VisibleObjects.m_fulllist.baseClass.m_linkoffset + IntPtr.Size);
}
public void Update()
{
WoWObjects.Clear();
var wowObjects = EnumVisibleObjects();
foreach (var wowObject in wowObjects)
WoWObjects[wowObject.Data.Guid] = wowObject;
OnObjectsUpdated(WoWObjects);
}
public event EventHandler<Dictionary<WoWStructs.Guid, WoWObject>> ObjectsUpdated;
// Loop through the games object list.
public IEnumerable<WoWObject> EnumVisibleObjects()
{
var first = GetFirstObject();
var typeOffset = Marshal.OffsetOf(typeof(WoWStructs.ObjectData), "ObjectType").ToInt32();
while (((first.ToInt64() & 1) == 0) && (first != IntPtr.Zero))
{
var type = (WoWEnums.ObjectType) Process.Memory.Read<int>(first + typeOffset);
// Fix below with other object types as added.
// ReSharper disable once SwitchStatementMissingSomeCases
switch (type)
{
case WoWEnums.ObjectType.Object:
yield return new WoWObject(Process, first);
break;
case WoWEnums.ObjectType.Container:
break;
case WoWEnums.ObjectType.Unit:
yield return new WoWUnit(Process, first);
break;
case WoWEnums.ObjectType.Player:
yield return new WoWPlayer(Process, first, new IntPtr(0x179A6E0));
break;
default:
yield return new WoWObject(Process, first);
break;
}
first = GetNextObjectFromCurrent(first);
}
}
protected virtual void OnObjectsUpdated(Dictionary<WoWStructs.Guid, WoWObject> e)
{
ObjectsUpdated?.Invoke(this, e);
}
}
}

View File

@ -0,0 +1,368 @@
namespace Artemis.Modules.Games.WoW.Data
{
internal static class WoWOffsets
{
internal enum AreaTriggerData
{
OverrideScaleCurve = 0x30, // Size: 0x7, Flags: 0x201
ExtraScaleCurve = 0x4C, // Size: 0x7, Flags: 0x201
Caster = 0x68, // Size: 0x4, Flags: 0x1
Duration = 0x78, // Size: 0x1, Flags: 0x1
TimeToTarget = 0x7C, // Size: 0x1, Flags: 0x201
TimeToTargetScale = 0x80, // Size: 0x1, Flags: 0x201
TimeToTargetExtraScale = 0x84, // Size: 0x1, Flags: 0x201
SpellId = 0x88, // Size: 0x1, Flags: 0x1
SpellVisualId = 0x8C, // Size: 0x1, Flags: 0x80
BoundsRadius2D = 0x90, // Size: 0x1, Flags: 0x280
DecalPropertiesId = 0x94 // Size: 0x1, Flags: 0x1
}
internal enum ContainerData
{
Slots = 0x150, // Size: 0x90, Flags: 0x1
NumSlots = 0x390 // Size: 0x1, Flags: 0x1
}
internal enum ConversationData
{
LastLineDuration = 0x30 // Size: 0x1, Flags: 0x80
}
internal enum CorpseData
{
Owner = 0x30, // Size: 0x4, Flags: 0x1
PartyGuid = 0x40, // Size: 0x4, Flags: 0x1
DisplayId = 0x50, // Size: 0x1, Flags: 0x1
Items = 0x54, // Size: 0x13, Flags: 0x1
SkinId = 0xA0, // Size: 0x1, Flags: 0x1
FacialHairStyleId = 0xA4, // Size: 0x1, Flags: 0x1
Flags = 0xA8, // Size: 0x1, Flags: 0x1
DynamicFlags = 0xAC, // Size: 0x1, Flags: 0x80
FactionTemplate = 0xB0, // Size: 0x1, Flags: 0x1
CustomDisplayOption = 0xB4 // Size: 0x1, Flags: 0x1
}
internal enum DynamicObjectData
{
Caster = 0x30, // Size: 0x4, Flags: 0x1
TypeAndVisualId = 0x40, // Size: 0x1, Flags: 0x80
SpellId = 0x44, // Size: 0x1, Flags: 0x1
Radius = 0x48, // Size: 0x1, Flags: 0x1
CastTime = 0x4C // Size: 0x1, Flags: 0x1
}
internal enum GameObjectData
{
CreatedBy = 0x30, // Size: 0x4, Flags: 0x1
DisplayId = 0x40, // Size: 0x1, Flags: 0x280
Flags = 0x44, // Size: 0x1, Flags: 0x201
ParentRotation = 0x48, // Size: 0x4, Flags: 0x1
FactionTemplate = 0x58, // Size: 0x1, Flags: 0x1
Level = 0x5C, // Size: 0x1, Flags: 0x1
PercentHealth = 0x60, // Size: 0x1, Flags: 0x201
SpellVisualId = 0x64, // Size: 0x1, Flags: 0x281
StateSpellVisualId = 0x68, // Size: 0x1, Flags: 0x280
StateAnimId = 0x6C, // Size: 0x1, Flags: 0x280
StateAnimKitId = 0x70, // Size: 0x1, Flags: 0x280
StateWorldEffectId = 0x74 // Size: 0x4, Flags: 0x280
}
internal enum ItemData
{
Owner = 0x30, // Size: 0x4, Flags: 0x1
ContainedIn = 0x40, // Size: 0x4, Flags: 0x1
Creator = 0x50, // Size: 0x4, Flags: 0x1
GiftCreator = 0x60, // Size: 0x4, Flags: 0x1
StackCount = 0x70, // Size: 0x1, Flags: 0x4
Expiration = 0x74, // Size: 0x1, Flags: 0x4
SpellCharges = 0x78, // Size: 0x5, Flags: 0x4
DynamicFlags = 0x8C, // Size: 0x1, Flags: 0x1
Enchantment = 0x90, // Size: 0x27, Flags: 0x1
PropertySeed = 0x12C, // Size: 0x1, Flags: 0x1
RandomPropertiesId = 0x130, // Size: 0x1, Flags: 0x1
Durability = 0x134, // Size: 0x1, Flags: 0x4
MaxDurability = 0x138, // Size: 0x1, Flags: 0x4
CreatePlayedTime = 0x13C, // Size: 0x1, Flags: 0x1
ModifiersMask = 0x140, // Size: 0x1, Flags: 0x4
Context = 0x144, // Size: 0x1, Flags: 0x1
ArtifactXp = 0x148, // Size: 0x1, Flags: 0x4
ItemAppearanceModId = 0x14C // Size: 0x1, Flags: 0x4
}
internal enum KeyBinding
{
NumKeyBindings = 0x1700030, // -0x17C0
First = 0xC8,
Next = 0xB8,
Key = 0x30,
Command = 0x58
}
internal enum ObjectData
{
Guid = 0x0, // Size: 0x4, Flags: 0x1
Data = 0x10, // Size: 0x4, Flags: 0x1
Type = 0x20, // Size: 0x1, Flags: 0x1
EntryId = 0x24, // Size: 0x1, Flags: 0x80
DynamicFlags = 0x28, // Size: 0x1, Flags: 0x280
Scale = 0x2C // Size: 0x1, Flags: 0x1
}
internal enum PlayerData
{
DuelArbiter = 0x360, // Size: 0x4, Flags: 0x1
WowAccount = 0x370, // Size: 0x4, Flags: 0x1
LootTargetGuid = 0x380, // Size: 0x4, Flags: 0x1
PlayerFlags = 0x390, // Size: 0x1, Flags: 0x1
PlayerFlagsEx = 0x394, // Size: 0x1, Flags: 0x1
GuildRankId = 0x398, // Size: 0x1, Flags: 0x1
GuildDeleteDate = 0x39C, // Size: 0x1, Flags: 0x1
GuildLevel = 0x3A0, // Size: 0x1, Flags: 0x1
HairColorId = 0x3A4, // Size: 0x1, Flags: 0x1
CustomDisplayOption = 0x3A8, // Size: 0x1, Flags: 0x1
Inebriation = 0x3AC, // Size: 0x1, Flags: 0x1
ArenaFaction = 0x3B0, // Size: 0x1, Flags: 0x1
DuelTeam = 0x3B4, // Size: 0x1, Flags: 0x1
GuildTimeStamp = 0x3B8, // Size: 0x1, Flags: 0x1
QuestLog = 0x3BC, // Size: 0x320, Flags: 0x20
VisibleItems = 0x103C, // Size: 0x26, Flags: 0x1
PlayerTitle = 0x10D4, // Size: 0x1, Flags: 0x1
FakeInebriation = 0x10D8, // Size: 0x1, Flags: 0x1
VirtualPlayerRealm = 0x10DC, // Size: 0x1, Flags: 0x1
CurrentSpecId = 0x10E0, // Size: 0x1, Flags: 0x1
TaxiMountAnimKitId = 0x10E4, // Size: 0x1, Flags: 0x1
AvgItemLevel = 0x10E8, // Size: 0x4, Flags: 0x1
CurrentBattlePetBreedQuality = 0x10F8, // Size: 0x1, Flags: 0x1
Prestige = 0x10FC, // Size: 0x1, Flags: 0x1
HonorLevel = 0x1100, // Size: 0x1, Flags: 0x1
InvSlots = 0x1104, // Size: 0x2EC, Flags: 0x2
FarsightObject = 0x1CB4, // Size: 0x4, Flags: 0x2
SummonedBattlePetGuid = 0x1CC4, // Size: 0x4, Flags: 0x2
KnownTitles = 0x1CD4, // Size: 0xC, Flags: 0x2
Coinage = 0x1D04, // Size: 0x2, Flags: 0x2
Xp = 0x1D0C, // Size: 0x1, Flags: 0x2
NextLevelXp = 0x1D10, // Size: 0x1, Flags: 0x2
Skill = 0x1D14, // Size: 0x1C0, Flags: 0x2
CharacterPoints = 0x2414, // Size: 0x1, Flags: 0x2
MaxTalentTiers = 0x2418, // Size: 0x1, Flags: 0x2
TrackCreatureMask = 0x241C, // Size: 0x1, Flags: 0x2
TrackResourceMask = 0x2420, // Size: 0x1, Flags: 0x2
MainhandExpertise = 0x2424, // Size: 0x1, Flags: 0x2
OffhandExpertise = 0x2428, // Size: 0x1, Flags: 0x2
RangedExpertise = 0x242C, // Size: 0x1, Flags: 0x2
CombatRatingExpertise = 0x2430, // Size: 0x1, Flags: 0x2
BlockPercentage = 0x2434, // Size: 0x1, Flags: 0x2
DodgePercentage = 0x2438, // Size: 0x1, Flags: 0x2
ParryPercentage = 0x243C, // Size: 0x1, Flags: 0x2
CritPercentage = 0x2440, // Size: 0x1, Flags: 0x2
RangedCritPercentage = 0x2444, // Size: 0x1, Flags: 0x2
OffhandCritPercentage = 0x2448, // Size: 0x1, Flags: 0x2
SpellCritPercentage = 0x244C, // Size: 0x1, Flags: 0x2
ShieldBlock = 0x2450, // Size: 0x1, Flags: 0x2
ShieldBlockCritPercentage = 0x2454, // Size: 0x1, Flags: 0x2
Mastery = 0x2458, // Size: 0x1, Flags: 0x2
Speed = 0x245C, // Size: 0x1, Flags: 0x2
Lifesteal = 0x2460, // Size: 0x1, Flags: 0x2
Avoidance = 0x2464, // Size: 0x1, Flags: 0x2
Sturdiness = 0x2468, // Size: 0x1, Flags: 0x2
Versatility = 0x246C, // Size: 0x1, Flags: 0x2
VersatilityBonus = 0x2470, // Size: 0x1, Flags: 0x2
PvpPowerDamage = 0x2474, // Size: 0x1, Flags: 0x2
PvpPowerHealing = 0x2478, // Size: 0x1, Flags: 0x2
ExploredZones = 0x247C, // Size: 0x100, Flags: 0x2
RestInfo = 0x287C, // Size: 0x4, Flags: 0x2
ModDamageDonePos = 0x288C, // Size: 0x7, Flags: 0x2
ModDamageDoneNeg = 0x28A8, // Size: 0x7, Flags: 0x2
ModDamageDonePercent = 0x28C4, // Size: 0x7, Flags: 0x2
ModHealingDonePos = 0x28E0, // Size: 0x1, Flags: 0x2
ModHealingPercent = 0x28E4, // Size: 0x1, Flags: 0x2
ModHealingDonePercent = 0x28E8, // Size: 0x1, Flags: 0x2
ModPeriodicHealingDonePercent = 0x28EC, // Size: 0x1, Flags: 0x2
WeaponDmgMultipliers = 0x28F0, // Size: 0x3, Flags: 0x2
WeaponAtkSpeedMultipliers = 0x28FC, // Size: 0x3, Flags: 0x2
ModSpellPowerPercent = 0x2908, // Size: 0x1, Flags: 0x2
ModResiliencePercent = 0x290C, // Size: 0x1, Flags: 0x2
OverrideSpellPowerByApPercent = 0x2910, // Size: 0x1, Flags: 0x2
OverrideApBySpellPowerPercent = 0x2914, // Size: 0x1, Flags: 0x2
ModTargetResistance = 0x2918, // Size: 0x1, Flags: 0x2
ModTargetPhysicalResistance = 0x291C, // Size: 0x1, Flags: 0x2
LocalFlags = 0x2920, // Size: 0x1, Flags: 0x2
NumRespecs = 0x2924, // Size: 0x1, Flags: 0x2
SelfResSpell = 0x2928, // Size: 0x1, Flags: 0x2
PvpMedals = 0x292C, // Size: 0x1, Flags: 0x2
BuybackPrice = 0x2930, // Size: 0xC, Flags: 0x2
BuybackTimestamp = 0x2960, // Size: 0xC, Flags: 0x2
YesterdayHonorableKills = 0x2990, // Size: 0x1, Flags: 0x2
LifetimeHonorableKills = 0x2994, // Size: 0x1, Flags: 0x2
WatchedFactionIndex = 0x2998, // Size: 0x1, Flags: 0x2
CombatRatings = 0x299C, // Size: 0x20, Flags: 0x2
PvpInfo = 0x2A1C, // Size: 0x24, Flags: 0x2
MaxLevel = 0x2AAC, // Size: 0x1, Flags: 0x2
ScalingPlayerLevelDelta = 0x2AB0, // Size: 0x1, Flags: 0x2
MaxCreatureScalingLevel = 0x2AB4, // Size: 0x1, Flags: 0x2
NoReagentCostMask = 0x2AB8, // Size: 0x4, Flags: 0x2
PetSpellPower = 0x2AC8, // Size: 0x1, Flags: 0x2
Researching = 0x2ACC, // Size: 0xA, Flags: 0x2
ProfessionSkillLine = 0x2AF4, // Size: 0x2, Flags: 0x2
UiHitModifier = 0x2AFC, // Size: 0x1, Flags: 0x2
UiSpellHitModifier = 0x2B00, // Size: 0x1, Flags: 0x2
HomeRealmTimeOffset = 0x2B04, // Size: 0x1, Flags: 0x2
ModPetHaste = 0x2B08, // Size: 0x1, Flags: 0x2
OverrideSpellsId = 0x2B0C, // Size: 0x1, Flags: 0x402
LfgBonusFactionId = 0x2B10, // Size: 0x1, Flags: 0x2
LootSpecId = 0x2B14, // Size: 0x1, Flags: 0x2
OverrideZonePvpType = 0x2B18, // Size: 0x1, Flags: 0x402
BagSlotFlags = 0x2B1C, // Size: 0x4, Flags: 0x2
BankBagSlotFlags = 0x2B2C, // Size: 0x7, Flags: 0x2
InsertItemsLeftToRight = 0x2B48, // Size: 0x1, Flags: 0x2
QuestCompleted = 0x2B4C, // Size: 0x36B, Flags: 0x2
Honor = 0x38F8, // Size: 0x1, Flags: 0x2
HonorNextLevel = 0x38FC // Size: 0x1, Flags: 0x2
}
internal enum SceneObjectData
{
ScriptPackageId = 0x30, // Size: 0x1, Flags: 0x1
RndSeedVal = 0x34, // Size: 0x1, Flags: 0x1
CreatedBy = 0x38, // Size: 0x4, Flags: 0x1
SceneType = 0x48 // Size: 0x1, Flags: 0x1
}
internal enum Unit
{
CurrentCastId = 0x1B98,
CurrentChanneledId = 0x1BB8,
AuraTable = 0x1D10,
AuraCount = 0x2390,
AuraSize = 0x68,
ClientRace = 0x2670,
DisplayData = 0x1718
}
// Note: Invalid possibly!
internal enum UnitAuras : uint
{
AuraCount1 = 0x2390,
AuraCount2 = 0x1D10,
AuraTable1 = 0x1D14,
AuraTable2 = 0x1D18,
AuraSize = 0x68,
OwnerGuid = 0x40,
AuraSpellId = 0x50,
//AuraFlags = 0x54, //Not exactly sure here.
//AuraLevel = 0x58, //Not exactly sure here.
AuraStack = 0x59,
TimeLeft = 0x60,
//In case I need it:
DruidEclipse = 0x2694
}
// Below is all of the World of Warcraft in-game object field offsets.
// Commenting is not used on purpose and enums below should remain internal.
internal enum UnitData
{
Charm = 0x30, // Size: 0x4, Flags: 0x1
Summon = 0x40, // Size: 0x4, Flags: 0x1
Critter = 0x50, // Size: 0x4, Flags: 0x2
CharmedBy = 0x60, // Size: 0x4, Flags: 0x1
SummonedBy = 0x70, // Size: 0x4, Flags: 0x1
CreatedBy = 0x80, // Size: 0x4, Flags: 0x1
DemonCreator = 0x90, // Size: 0x4, Flags: 0x1
Target = 0xA0, // Size: 0x4, Flags: 0x1
BattlePetCompanionGuid = 0xB0, // Size: 0x4, Flags: 0x1
BattlePetDbid = 0xC0, // Size: 0x2, Flags: 0x1
ChannelObject = 0xC8, // Size: 0x4, Flags: 0x201
ChannelSpell = 0xD8, // Size: 0x1, Flags: 0x201
ChannelSpellXSpellVisual = 0xDC, // Size: 0x1, Flags: 0x201
SummonedByHomeRealm = 0xE0, // Size: 0x1, Flags: 0x1
Sex = 0xE4, // Size: 0x1, Flags: 0x1
DisplayPower = 0xE8, // Size: 0x1, Flags: 0x1
OverrideDisplayPowerId = 0xEC, // Size: 0x1, Flags: 0x1
Health = 0xF0, // Size: 0x2, Flags: 0x1
Power = 0xF8, // Size: 0x6, Flags: 0x401
TertiaryPower = 0xFC,
SecondaryPower = 0x100,
MaxHealth = 0x110, // Size: 0x2, Flags: 0x1
MaxPower = 0x118, // Size: 0x6, Flags: 0x1
PowerRegenFlatModifier = 0x130, // Size: 0x6, Flags: 0x46
PowerRegenInterruptedFlatModifier = 0x148, // Size: 0x6, Flags: 0x46
Level = 0x160, // Size: 0x1, Flags: 0x1
EffectiveLevel = 0x164, // Size: 0x1, Flags: 0x1
ScalingLevelMin = 0x168, // Size: 0x1, Flags: 0x1
ScalingLevelMax = 0x16C, // Size: 0x1, Flags: 0x1
ScalingLevelDelta = 0x170, // Size: 0x1, Flags: 0x1
FactionTemplate = 0x174, // Size: 0x1, Flags: 0x1
VirtualItems = 0x178, // Size: 0x6, Flags: 0x1
Flags = 0x190, // Size: 0x1, Flags: 0x201
Flags2 = 0x194, // Size: 0x1, Flags: 0x201
Flags3 = 0x198, // Size: 0x1, Flags: 0x201
AuraState = 0x19C, // Size: 0x1, Flags: 0x1
AttackRoundBaseTime = 0x1A0, // Size: 0x2, Flags: 0x1
RangedAttackRoundBaseTime = 0x1A8, // Size: 0x1, Flags: 0x2
BoundingRadius = 0x1AC, // Size: 0x1, Flags: 0x1
CombatReach = 0x1B0, // Size: 0x1, Flags: 0x1
DisplayId = 0x1B4, // Size: 0x1, Flags: 0x280
NativeDisplayId = 0x1B8, // Size: 0x1, Flags: 0x201
MountDisplayId = 0x1BC, // Size: 0x1, Flags: 0x201
MinDamage = 0x1C0, // Size: 0x1, Flags: 0x16
MaxDamage = 0x1C4, // Size: 0x1, Flags: 0x16
MinOffHandDamage = 0x1C8, // Size: 0x1, Flags: 0x16
MaxOffHandDamage = 0x1CC, // Size: 0x1, Flags: 0x16
AnimTier = 0x1D0, // Size: 0x1, Flags: 0x1
PetNumber = 0x1D4, // Size: 0x1, Flags: 0x1
PetNameTimestamp = 0x1D8, // Size: 0x1, Flags: 0x1
PetExperience = 0x1DC, // Size: 0x1, Flags: 0x4
PetNextLevelExperience = 0x1E0, // Size: 0x1, Flags: 0x4
ModCastingSpeed = 0x1E4, // Size: 0x1, Flags: 0x1
ModSpellHaste = 0x1E8, // Size: 0x1, Flags: 0x1
ModHaste = 0x1EC, // Size: 0x1, Flags: 0x1
ModRangedHaste = 0x1F0, // Size: 0x1, Flags: 0x1
ModHasteRegen = 0x1F4, // Size: 0x1, Flags: 0x1
ModTimeRate = 0x1F8, // Size: 0x1, Flags: 0x1
CreatedBySpell = 0x1FC, // Size: 0x1, Flags: 0x1
NpcFlags = 0x200, // Size: 0x2, Flags: 0x81
EmoteState = 0x208, // Size: 0x1, Flags: 0x1
Stats = 0x20C, // Size: 0x4, Flags: 0x6
StatPosBuff = 0x21C, // Size: 0x4, Flags: 0x6
StatNegBuff = 0x22C, // Size: 0x4, Flags: 0x6
Resistances = 0x23C, // Size: 0x7, Flags: 0x16
ResistanceBuffModsPositive = 0x258, // Size: 0x7, Flags: 0x6
ResistanceBuffModsNegative = 0x274, // Size: 0x7, Flags: 0x6
ModBonusArmor = 0x290, // Size: 0x1, Flags: 0x6
BaseMana = 0x294, // Size: 0x1, Flags: 0x1
BaseHealth = 0x298, // Size: 0x1, Flags: 0x6
ShapeshiftForm = 0x29C, // Size: 0x1, Flags: 0x1
AttackPower = 0x2A0, // Size: 0x1, Flags: 0x6
AttackPowerModPos = 0x2A4, // Size: 0x1, Flags: 0x6
AttackPowerModNeg = 0x2A8, // Size: 0x1, Flags: 0x6
AttackPowerMultiplier = 0x2AC, // Size: 0x1, Flags: 0x6
RangedAttackPower = 0x2B0, // Size: 0x1, Flags: 0x6
RangedAttackPowerModPos = 0x2B4, // Size: 0x1, Flags: 0x6
RangedAttackPowerModNeg = 0x2B8, // Size: 0x1, Flags: 0x6
RangedAttackPowerMultiplier = 0x2BC, // Size: 0x1, Flags: 0x6
SetAttackSpeedAura = 0x2C0, // Size: 0x1, Flags: 0x6
MinRangedDamage = 0x2C4, // Size: 0x1, Flags: 0x6
MaxRangedDamage = 0x2C8, // Size: 0x1, Flags: 0x6
PowerCostModifier = 0x2CC, // Size: 0x7, Flags: 0x6
PowerCostMultiplier = 0x2E8, // Size: 0x7, Flags: 0x6
MaxHealthModifier = 0x304, // Size: 0x1, Flags: 0x6
HoverHeight = 0x308, // Size: 0x1, Flags: 0x1
MinItemLevelCutoff = 0x30C, // Size: 0x1, Flags: 0x1
MinItemLevel = 0x310, // Size: 0x1, Flags: 0x1
MaxItemLevel = 0x314, // Size: 0x1, Flags: 0x1
WildBattlePetLevel = 0x318, // Size: 0x1, Flags: 0x1
BattlePetCompanionNameTimestamp = 0x31C, // Size: 0x1, Flags: 0x1
InteractSpellId = 0x320, // Size: 0x1, Flags: 0x1
StateSpellVisualId = 0x324, // Size: 0x1, Flags: 0x280
StateAnimId = 0x328, // Size: 0x1, Flags: 0x280
StateAnimKitId = 0x32C, // Size: 0x1, Flags: 0x280
StateWorldEffectId = 0x330, // Size: 0x4, Flags: 0x280
ScaleDuration = 0x340, // Size: 0x1, Flags: 0x1
LooksLikeMountId = 0x344, // Size: 0x1, Flags: 0x1
LooksLikeCreatureId = 0x348, // Size: 0x1, Flags: 0x1
LookAtControllerId = 0x34C, // Size: 0x1, Flags: 0x1
LookAtControllerTarget = 0x350 // Size: 0x4, Flags: 0x1
}
}
}

View File

@ -0,0 +1,23 @@
using System;
using System.Linq;
using Process.NET;
namespace Artemis.Modules.Games.WoW.Data
{
public class WoWPlayer : WoWUnit
{
private readonly IntPtr _targetIntPtr;
public WoWPlayer(IProcess process, IntPtr baseAddress, IntPtr targetIntPtr, bool readPointer = false)
: base(process, baseAddress, readPointer)
{
_targetIntPtr = targetIntPtr;
}
public WoWObject GetTarget(WoWObjectManager manager)
{
var targetGuid = Process.Memory.Read<Guid>(Process.Native.MainModule.BaseAddress + _targetIntPtr.ToInt32());
return manager.EnumVisibleObjects().FirstOrDefault(o => o.Guid == targetGuid);
}
}
}

View File

@ -0,0 +1,181 @@
using System;
using System.Runtime.InteropServices;
using Artemis.Modules.Games.WoW.Data.WowSharp.Client.Patchables;
namespace Artemis.Modules.Games.WoW.Data
{
public static class WoWStructs
{
[StructLayout(LayoutKind.Explicit)]
public struct ObjectData
{
// x32 : x64
[FieldOffset(0)] private readonly IntPtr vtable; // 0x00 0x00
[FieldOffset(10)] public IntPtr Descriptors; // 0x04 0x10
[FieldOffset(18)] private readonly IntPtr unk1; // 0x08 0x18
[FieldOffset(20)] public int ObjectType; // 0x0C 0x20
[FieldOffset(24)] private readonly IntPtr unk3; // 0x10 0x24
[FieldOffset(28)] private readonly IntPtr unk4; // 0x14 0x28
[FieldOffset(30)] private readonly IntPtr unk5; // 0x18 0x30
[FieldOffset(38)] private readonly IntPtr unk6; // 0x1C 0x38
[FieldOffset(40)] private readonly IntPtr unk7; // 0x20 0x40
[FieldOffset(48)] private readonly IntPtr unk8; // 0x24 0x48
[FieldOffset(50)] public Guid Guid; // 0x28 0x50
}
public struct Guid
{
private readonly Int128 _mGuid;
public static readonly Guid Zero = new Guid(0);
public Guid(Int128 guid)
{
_mGuid = guid;
}
public override string ToString()
{
// ReSharper disable once SwitchStatementMissingSomeCases
switch (Type)
{
case WoWEnums.GuidType.Creature:
case WoWEnums.GuidType.Vehicle:
case WoWEnums.GuidType.Pet:
case WoWEnums.GuidType.GameObject:
case WoWEnums.GuidType.AreaTrigger:
case WoWEnums.GuidType.DynamicObject:
case WoWEnums.GuidType.Corpse:
case WoWEnums.GuidType.LootObject:
case WoWEnums.GuidType.SceneObject:
case WoWEnums.GuidType.Scenario:
case WoWEnums.GuidType.AiGroup:
case WoWEnums.GuidType.DynamicDoor:
case WoWEnums.GuidType.Vignette:
case WoWEnums.GuidType.Conversation:
case WoWEnums.GuidType.CallForHelp:
case WoWEnums.GuidType.AiResource:
case WoWEnums.GuidType.AiLock:
case WoWEnums.GuidType.AiLockTicket:
return $"{Type}-{SubType}-{RealmId}-{MapId}-{ServerId}-{Id}-{CreationBits:X10}";
case WoWEnums.GuidType.Player:
return $"{Type}-{RealmId}-{(ulong) (_mGuid >> 64):X8}";
case WoWEnums.GuidType.Item:
return $"{Type}-{RealmId}-{(uint) ((_mGuid >> 18) & 0xFFFFFF)}-{(ulong) (_mGuid >> 64):X10}";
//case GuidType.ClientActor:
// return String.Format("{0}-{1}-{2}", Type, RealmId, CreationBits);
//case GuidType.Transport:
//case GuidType.StaticDoor:
// return String.Format("{0}-{1}-{2}", Type, RealmId, CreationBits);
default:
return $"{Type}-{_mGuid:X32}";
}
}
public override bool Equals(object obj)
{
if (obj is Guid)
return _mGuid == ((Guid) obj)._mGuid;
return false;
}
public override int GetHashCode()
{
return _mGuid.GetHashCode();
}
public WoWEnums.GuidType Type => (WoWEnums.GuidType) (byte) ((_mGuid >> 58) & 0x3F);
public byte SubType => (byte) ((_mGuid >> 120) & 0x3F);
public ushort RealmId => (ushort) ((_mGuid >> 42) & 0x1FFF);
public ushort ServerId => (ushort) ((_mGuid >> 104) & 0x1FFF);
public ushort MapId => (ushort) ((_mGuid >> 29) & 0x1FFF);
// Creature, Pet, Vehicle
public uint Id => (uint) ((_mGuid >> 6) & 0x7FFFFF);
public ulong CreationBits => (ulong) ((_mGuid >> 64) & 0xFFFFFFFFFF);
}
#region Manager
// Region is here due to the large amount of structs-
// the CurremtManager struct depends on.
[StructLayout(LayoutKind.Sequential)]
public struct CurrentManager
{
public TsHashTable VisibleObjects; // m_objects
public TsHashTable LazyCleanupObjects; // m_lazyCleanupObjects
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 13)]
// m_lazyCleanupFifo, m_freeObjects, m_visibleObjects, m_reenabledObjects, whateverObjects...
public TsExplicitList[] Links; // Links[13] has all objects stored in VisibleObjects it seems
#if !X64
public int Unknown1; // wtf is that and why x86 only?
#endif
public Int128 ActivePlayer;
public int MapId;
public IntPtr ClientConnection;
public IntPtr MovementGlobals;
public int Unk1;
}
[StructLayout(LayoutKind.Sequential)]
public struct Ts
{
public IntPtr vtable;
public uint m_alloc;
public uint m_count;
public IntPtr m_data; //TSExplicitList* m_data;
}
[StructLayout(LayoutKind.Sequential)]
public struct TsExplicitList
{
public TsList baseClass;
}
[StructLayout(LayoutKind.Sequential)]
public struct TsFixedArray
{
public Ts baseClass;
}
[StructLayout(LayoutKind.Sequential)]
public struct TsGrowableArray
{
public TsFixedArray baseclass;
public uint m_chunk;
}
[StructLayout(LayoutKind.Sequential)]
public struct TsHashTable
{
public IntPtr vtable;
public TsExplicitList m_fulllist;
public int m_fullnessIndicator;
public TsGrowableArray m_slotlistarray;
public int m_slotmask;
}
[StructLayout(LayoutKind.Sequential)]
public struct TsLink
{
public IntPtr m_prevlink; //TSLink *m_prevlink
public IntPtr m_next; // C_OBJECTHASH *m_next
}
[StructLayout(LayoutKind.Sequential)]
public struct TsList
{
public int m_linkoffset;
public TsLink m_terminator;
}
#endregion;
}
}

View File

@ -0,0 +1,31 @@
using System;
using Process.NET;
using static Artemis.Modules.Games.WoW.Data.WoWEnums;
using static Artemis.Modules.Games.WoW.Data.WoWOffsets;
namespace Artemis.Modules.Games.WoW.Data
{
public class WoWUnit : WoWObject
{
public WoWUnit(IProcess process, IntPtr baseAddress, bool readPointer = false)
: base(process, baseAddress, readPointer)
{
}
public int Health => ReadField<int>(UnitData.Health);
public int MaxHealth => ReadField<int>(UnitData.MaxHealth);
public int Power => ReadField<int>(UnitData.Power);
public int SecondaryPower => ReadField<int>(UnitData.SecondaryPower);
public int TertiaryPower => ReadField<int>(UnitData.TertiaryPower);
public int MaxPower => ReadField<int>(UnitData.MaxPower);
public PowerType PowerType => (PowerType) ReadField<int>(UnitData.DisplayPower);
public int Level => ReadField<int>(UnitData.Level);
public WoWDetails Details { get; set; }
public void UpdateDetails(WoWNameCache nameCache)
{
Details = GetNpcDetails() ?? nameCache.GetNameByGuid(Guid);
}
}
}

View File

@ -1,4 +1,4 @@
namespace Artemis.Modules.Games.WorldofWarcraft namespace Artemis.Modules.Games.WoW
{ {
public static class WoWAddresses public static class WoWAddresses
{ {

View File

@ -0,0 +1,11 @@
using Artemis.Models.Interfaces;
using Artemis.Modules.Games.WoW.Data;
namespace Artemis.Modules.Games.WoW
{
public class WoWDataModel : IDataModel
{
public WoWUnit Player { get; set; }
public WoWUnit Target { get; set; }
}
}

View File

@ -0,0 +1,113 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Artemis.DAL;
using Artemis.Managers;
using Artemis.Models;
using Artemis.Modules.Games.WoW.Data;
using Artemis.Profiles.Layers.Models;
using Artemis.Settings;
using Artemis.Utilities.Memory;
using Process.NET;
namespace Artemis.Modules.Games.WoW
{
public class WoWModel : GameModel
{
private readonly GamePointersCollection _pointer;
private ProcessSharp _process;
public WoWModel(MainManager mainManager)
: base(mainManager, SettingsProvider.Load<WoWSettings>(), new WoWDataModel())
{
Name = "WoW";
ProcessName = "Wow-64";
Scale = 4;
// Currently WoW is locked behind a hidden trigger (obviously not that hidden if you're reading this)
// It is using memory reading and lets first try to contact Blizzard
var settings = SettingsProvider.Load<GeneralSettings>();
Enabled = settings.GamestatePort == 62575 && Settings.Enabled;
Initialized = false;
// TODO: Retrieve from GitHub
_pointer = new GamePointersCollection
{
Game = "WorldOfWarcraft",
GameVersion = "7.0.3.22522",
GameAddresses = new List<GamePointer>
{
new GamePointer
{
Description = "ObjectManager",
BasePointer = new IntPtr(0x1575E10)
},
new GamePointer
{
Description = "LocalPlayer",
BasePointer = new IntPtr(0x169BCB0)
}
}
};
}
public int Scale { get; set; }
public override void Dispose()
{
Initialized = false;
_process.Dispose();
_process = null;
}
public override void Enable()
{
var tempProcess = MemoryHelpers.GetProcessIfRunning(ProcessName);
if (tempProcess == null)
return;
_process = new ProcessSharp(tempProcess);
_process.Memory = new ExternalProcessMemory(_process.Handle);
Initialized = true;
}
public override void Update()
{
if ((Profile == null) || (DataModel == null) || (_process == null))
return;
var dataModel = (WoWDataModel) DataModel;
var objectManager = new WoWObjectManager(_process,
_pointer.GameAddresses.First(a => a.Description == "ObjectManager").BasePointer);
var nameCache = new WoWNameCache(_process, new IntPtr(0x151BA88));
var player = new WoWPlayer(_process,
_pointer.GameAddresses.First(a => a.Description == "LocalPlayer").BasePointer, new IntPtr(0x179A6E0),
true);
dataModel.Player = player;
if (dataModel.Player != null && dataModel.Player.Guid != Guid.Empty)
{
dataModel.Player.UpdateDetails(nameCache);
var target = player.GetTarget(objectManager);
if (target == null)
return;
dataModel.Target = new WoWUnit(target.Process, target.BaseAddress);
dataModel.Target.UpdateDetails(nameCache);
}
else
{
dataModel.Target = null;
}
}
public override List<LayerModel> GetRenderLayers(bool keyboardOnly)
{
return Profile.GetRenderLayers(DataModel, keyboardOnly);
}
}
}

View File

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

View File

@ -0,0 +1,56 @@
<UserControl x:Class="Artemis.Modules.Games.WoW.WoWView"
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:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
xmlns:cal="http://www.caliburnproject.org"
xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
mc:Ignorable="d"
d:DesignHeight="476.986" d:DesignWidth="538.772">
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
<Grid Margin="15, 5, 15, 5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Margin="0,0,1,0">
<Label FontSize="20" HorizontalAlignment="Left">
<Label.Content>
<AccessText TextWrapping="Wrap"
Text="Fight The Burning Legion in style with reactive lighting" />
</Label.Content>
</Label>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Label Content="Enable effect" Margin="0 3 0 0" HorizontalAlignment="Right" />
<ToggleButton x:Name="EffectEnabled" Margin="0 3 0 0" Width="25" Height="25"
IsChecked="{Binding Path=GameSettings.Enabled, Mode=TwoWay}"
Style="{DynamicResource MetroCircleToggleButtonStyle}"
cal:Message.Attach="[Event Click] = [Action ToggleEffect]" />
</StackPanel>
</StackPanel>
<!-- Profile editor -->
<ContentControl Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" x:Name="ProfileEditor" Margin="0,0,-30,0" />
<!-- Buttons -->
<StackPanel Grid.Column="0" Grid.Row="9" Orientation="Horizontal" VerticalAlignment="Bottom">
<Button x:Name="ResetSettings" Content="Reset effect" VerticalAlignment="Top" Width="100"
Style="{DynamicResource SquareButtonStyle}" />
<Button x:Name="SaveSettings" Content="Save changes" VerticalAlignment="Top" Width="100"
Margin="10,0,0,0"
Style="{DynamicResource SquareButtonStyle}" />
</StackPanel>
</Grid>
</ScrollViewer>
</UserControl>

View File

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

View File

@ -0,0 +1,15 @@
using Artemis.InjectionFactories;
using Artemis.Managers;
using Artemis.ViewModels.Abstract;
namespace Artemis.Modules.Games.WoW
{
public sealed class WoWViewModel : GameViewModel
{
public WoWViewModel(MainManager main, IProfileEditorVmFactory pFactory, WoWModel model)
: base(main, model, pFactory)
{
DisplayName = "WoW";
}
}
}

View File

@ -1,17 +0,0 @@
using Artemis.Models.Interfaces;
namespace Artemis.Modules.Games.WorldofWarcraft
{
public class WoWDataModel : IDataModel
{
public Player Player { get; set; } = new Player();
}
public class Player
{
public string Name { get; set; }
public int Health { get; set; }
public int MaxHealth { get; set; }
}
}

View File

@ -1,54 +0,0 @@
//using System.Collections.Generic;
//using Artemis.Managers;
//using Artemis.Models;
//using Artemis.Profiles.Layers.Models;
//using Artemis.Utilities.Memory;
//
//namespace Artemis.Modules.Games.WorldofWarcraft
//{
// public class WoWModel : GameModel
// {
// private Memory _memory;
//
// public WoWModel(MainManager mainManager): base(mainManager, SettingsProvider.Load<WoWSettings>(), new WoWDataModel())
// {
// Name = "WoW";
// ProcessName = "Wow-64";
// Scale = 4;
// Enabled = Settings.Enabled;
// Initialized = false;
// }
//
// public int Scale { get; set; }
//
// public override void Dispose()
// {
// Initialized = false;
// }
//
// public override void Enable()
// {
// var tempProcess = MemoryHelpers.GetProcessIfRunning(ProcessName);
// if (tempProcess == null)
// return;
//
// _memory = new Memory(tempProcess);
//
// Initialized = true;
// }
//
// public override void Update()
// {
// if (Profile == null || DataModel == null || _memory == null)
// return;
//
//// _memory.ReadMemory();
// }
//
// public override List<LayerModel> GetRenderLayers(bool keyboardOnly)
// {
// return Profile.GetRenderLayers(DataModel, keyboardOnly);
// }
// }
//}

View File

@ -1,11 +0,0 @@
using Artemis.Settings;
namespace Artemis.Modules.Games.WorldofWarcraft
{
public class WoWSettings : GameSettings
{
private WoWSettings()
{
}
}
}

View File

@ -1,15 +0,0 @@
//using Artemis.InjectionFactories;
//using Artemis.Managers;
//using Artemis.ViewModels.Abstract;
//
//namespace Artemis.Modules.Games.WorldofWarcraft
//{
// public sealed class WoWViewModel : GameViewModel
// {
// public WoWViewModel(MainManager main, IProfileEditorVmFactory pFactory, WoWModel model): base(main, model, pFactory)
// {
// DisplayName = "WoW";
// }
// }
//}

View File

@ -12,8 +12,9 @@ namespace Artemis.Profiles.Layers.Animations
public void Update(LayerModel layerModel, bool updateAnimations) public void Update(LayerModel layerModel, bool updateAnimations)
{ {
// TODO: Generic implementation
// Reset animation progress if layer wasn't drawn for 100ms // Reset animation progress if layer wasn't drawn for 100ms
if (new TimeSpan(0, 0, 0, 0, 100) < DateTime.Now - layerModel.LastRender) if ((new TimeSpan(0, 0, 0, 0, 100) < DateTime.Now - layerModel.LastRender) && updateAnimations)
layerModel.Properties.AnimationProgress = 0; layerModel.Properties.AnimationProgress = 0;
var progress = layerModel.Properties.AnimationProgress; var progress = layerModel.Properties.AnimationProgress;

View File

@ -12,8 +12,9 @@ namespace Artemis.Profiles.Layers.Animations
public void Update(LayerModel layerModel, bool updateAnimations) public void Update(LayerModel layerModel, bool updateAnimations)
{ {
// TODO: Generic implementation
// Reset animation progress if layer wasn't drawn for 100ms // Reset animation progress if layer wasn't drawn for 100ms
if (new TimeSpan(0, 0, 0, 0, 100) < DateTime.Now - layerModel.LastRender) if ((new TimeSpan(0, 0, 0, 0, 100) < DateTime.Now - layerModel.LastRender) && updateAnimations)
layerModel.Properties.AnimationProgress = 0; layerModel.Properties.AnimationProgress = 0;
var progress = layerModel.Properties.AnimationProgress; var progress = layerModel.Properties.AnimationProgress;

View File

@ -9,7 +9,10 @@ namespace Artemis.Profiles.Layers.Conditions
{ {
public bool ConditionsMet(LayerModel layer, IDataModel dataModel) public bool ConditionsMet(LayerModel layer, IDataModel dataModel)
{ {
return layer.Properties.Conditions.All(cm => cm.ConditionMet(dataModel)); lock (layer.Properties.Conditions)
{
return layer.Properties.Conditions.All(cm => cm.ConditionMet(dataModel));
}
} }
} }
} }

View File

@ -70,6 +70,7 @@ namespace Artemis.Profiles.Layers.Interfaces
Keyboard, Keyboard,
Mouse, Mouse,
Headset, Headset,
Generic Generic,
Mousemat
} }
} }

View File

@ -72,9 +72,8 @@ namespace Artemis.Profiles.Layers.Models
{ {
LayerType.Update(this, dataModel, preview); LayerType.Update(this, dataModel, preview);
LayerAnimation?.Update(this, updateAnimations); LayerAnimation?.Update(this, updateAnimations);
if (!preview) LastRender = DateTime.Now;
LastRender = DateTime.Now;
} }
public void Draw(IDataModel dataModel, DrawingContext c, bool preview, bool updateAnimations) public void Draw(IDataModel dataModel, DrawingContext c, bool preview, bool updateAnimations)

View File

@ -3,7 +3,6 @@ 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.Managers;
using Artemis.Models.Interfaces; using Artemis.Models.Interfaces;
using Artemis.Modules.Effects.AudioVisualizer.Utilities; using Artemis.Modules.Effects.AudioVisualizer.Utilities;
using Artemis.Profiles.Layers.Abstract; using Artemis.Profiles.Layers.Abstract;
@ -28,10 +27,10 @@ namespace Artemis.Profiles.Layers.Types.Audio
private int _lines; private int _lines;
private AudioPropertiesModel _previousSettings; private AudioPropertiesModel _previousSettings;
public AudioType(MainManager mainManager) public AudioType()
{ {
_device = _device = new MMDeviceEnumerator()
new MMDeviceEnumerator().EnumerateAudioEndPoints(DataFlow.All, DeviceState.Active).FirstOrDefault(); .EnumerateAudioEndPoints(DataFlow.All, DeviceState.Active).FirstOrDefault();
_sampleAggregator.FftCalculated += FftCalculated; _sampleAggregator.FftCalculated += FftCalculated;
_sampleAggregator.PerformFFT = true; _sampleAggregator.PerformFFT = true;
@ -55,7 +54,7 @@ namespace Artemis.Profiles.Layers.Types.Audio
var visual = new DrawingVisual(); var visual = new DrawingVisual();
using (var c = visual.RenderOpen()) using (var c = visual.RenderOpen())
{ {
c.DrawImage(ImageUtilities.BitmapToBitmapImage(Resources.gif), thumbnailRect); c.DrawImage(ImageUtilities.BitmapToBitmapImage(Resources.audio), thumbnailRect);
} }
var image = new DrawingImage(visual.Drawing); var image = new DrawingImage(visual.Drawing);

View File

@ -33,7 +33,7 @@
<!-- Animation Speed --> <!-- Animation Speed -->
<TextBlock Grid.Row="0" Grid.Column="2" Margin="10,13,10,10" FontSize="13.333" Text="Animation speed:" <TextBlock Grid.Row="0" Grid.Column="2" Margin="10,13,10,10" FontSize="13.333" Text="Animation speed:"
VerticalAlignment="Top" Height="18" /> VerticalAlignment="Top" Height="18" />
<Slider x:Name="RotationSpeed" Grid.Row="0" Grid.Column="3" VerticalAlignment="Top" <Slider x:Name="AnimationSpeed" Grid.Row="0" Grid.Column="3" VerticalAlignment="Top"
TickPlacement="None" TickFrequency="0.05" TickPlacement="None" TickFrequency="0.05"
Value="{Binding Path=LayerModel.Properties.AnimationSpeed, Mode=TwoWay}" Minimum="0.5" Maximum="5" Value="{Binding Path=LayerModel.Properties.AnimationSpeed, Mode=TwoWay}" Minimum="0.5" Maximum="5"
SmallChange="0" IsSnapToTickEnabled="True" Margin="10,12,10,2" Height="24" /> SmallChange="0" IsSnapToTickEnabled="True" Margin="10,12,10,2" Height="24" />

View File

@ -42,7 +42,7 @@ namespace Artemis.Profiles.Layers.Types.KeyPress
var visual = new DrawingVisual(); var visual = new DrawingVisual();
using (var c = visual.RenderOpen()) using (var c = visual.RenderOpen())
{ {
c.DrawImage(ImageUtilities.BitmapToBitmapImage(Resources.gif), thumbnailRect); c.DrawImage(ImageUtilities.BitmapToBitmapImage(Resources.keypress), thumbnailRect);
} }
var image = new DrawingImage(visual.Drawing); var image = new DrawingImage(visual.Drawing);
@ -87,7 +87,20 @@ namespace Artemis.Profiles.Layers.Types.KeyPress
if (layerModel.Properties is KeyPressPropertiesModel) if (layerModel.Properties is KeyPressPropertiesModel)
return; return;
layerModel.Properties = new KeyPressPropertiesModel(layerModel.Properties); // Setup brush as a radial
layerModel.Properties = new KeyPressPropertiesModel(layerModel.Properties)
{
Brush = new RadialGradientBrush(new GradientStopCollection
{
new GradientStop(Colors.Red, 0.85),
new GradientStop(Color.FromArgb(0, 255, 0, 0), 0.95),
new GradientStop(Colors.Red, 0.55),
new GradientStop(Color.FromArgb(0, 255, 0, 0), 0.45)
})
};
// Setup defaults
((KeyPressPropertiesModel) layerModel.Properties).AnimationSpeed = 2.5;
((KeyPressPropertiesModel) layerModel.Properties).Scale = 8;
} }
public LayerPropertiesViewModel SetupViewModel(LayerEditorViewModel layerEditorViewModel, public LayerPropertiesViewModel SetupViewModel(LayerEditorViewModel layerEditorViewModel,

View File

@ -0,0 +1,68 @@
<UserControl x:Class="Artemis.Profiles.Layers.Types.Mousemat.MousematPropertiesView"
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:ncore="http://schemas.ncore.com/wpf/xaml/colorbox"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<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" />
<!-- Colors -->
<StackPanel Grid.Row="1" Grid.Column="0" 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 Path=Brush, Mode=TwoWay}" Height="24" Width="134" />
</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="OpacityProperties" />
<!-- Note -->
<TextBlock Grid.Row="5" Grid.Column="0" Grid.ColumnSpan="4" Margin="10,2,10,10" FontSize="13.333"
Foreground="{DynamicResource HighlightBrush}"
Text="Note: If your mousemat has multiple controllable LEDs you can create a gradient. Artemis will take the colors in the gradient and assign them to the LEDs"
VerticalAlignment="Top" Height="Auto" TextWrapping="Wrap" />
</Grid>
</UserControl>

View File

@ -0,0 +1,15 @@
using System.Windows.Controls;
namespace Artemis.Profiles.Layers.Types.Mousemat
{
/// <summary>
/// Interaction logic for MousematPropertiesView.xaml
/// </summary>
public partial class MousematPropertiesView : UserControl
{
public MousematPropertiesView()
{
InitializeComponent();
}
}
}

View File

@ -0,0 +1,44 @@
using System.Linq;
using Artemis.Profiles.Layers.Abstract;
using Artemis.Profiles.Layers.Interfaces;
using Artemis.ViewModels.Profiles;
using Caliburn.Micro;
namespace Artemis.Profiles.Layers.Types.Mousemat
{
public class MousematPropertiesViewModel : LayerPropertiesViewModel
{
private ILayerAnimation _selectedLayerAnimation;
public MousematPropertiesViewModel(LayerEditorViewModel editorVm) : base(editorVm)
{
LayerAnimations = new BindableCollection<ILayerAnimation>(editorVm.LayerAnimations);
OpacityProperties = new LayerDynamicPropertiesViewModel("Opacity", editorVm);
SelectedLayerAnimation =
LayerAnimations.FirstOrDefault(l => l.Name == editorVm.ProposedLayer.LayerAnimation?.Name) ??
LayerAnimations.First(l => l.Name == "None");
}
public BindableCollection<ILayerAnimation> LayerAnimations { get; set; }
public LayerDynamicPropertiesViewModel OpacityProperties { get; set; }
public ILayerAnimation SelectedLayerAnimation
{
get { return _selectedLayerAnimation; }
set
{
if (Equals(value, _selectedLayerAnimation)) return;
_selectedLayerAnimation = value;
NotifyOfPropertyChange(() => SelectedLayerAnimation);
}
}
public override void ApplyProperties()
{
OpacityProperties.Apply(LayerModel);
LayerModel.Properties.Brush = Brush;
LayerModel.LayerAnimation = SelectedLayerAnimation;
}
}
}

View File

@ -0,0 +1,95 @@
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Media;
using Artemis.Models.Interfaces;
using Artemis.Profiles.Layers.Abstract;
using Artemis.Profiles.Layers.Animations;
using Artemis.Profiles.Layers.Interfaces;
using Artemis.Profiles.Layers.Models;
using Artemis.Properties;
using Artemis.Utilities;
using Artemis.ViewModels.Profiles;
namespace Artemis.Profiles.Layers.Types.Mousemat
{
public class MousematType : ILayerType
{
public string Name { get; } = "Mousemat";
public bool ShowInEdtor { get; } = false;
public DrawType DrawType { get; } = DrawType.Mousemat;
public ImageSource DrawThumbnail(LayerModel layer)
{
var thumbnailRect = new Rect(0, 0, 18, 18);
var visual = new DrawingVisual();
using (var c = visual.RenderOpen())
c.DrawImage(ImageUtilities.BitmapToBitmapImage(Resources.mousemat), thumbnailRect);
var image = new DrawingImage(visual.Drawing);
return image;
}
public void Draw(LayerModel layer, DrawingContext c)
{
// If an animation is present, let it handle the drawing
if (layer.LayerAnimation != null && !(layer.LayerAnimation is NoneAnimation))
{
layer.LayerAnimation.Draw(layer.Properties, layer.AppliedProperties, c);
return;
}
// Otherwise draw the rectangle with its applied dimensions and brush
var rect = new Rect(layer.AppliedProperties.X*4,
layer.AppliedProperties.Y*4,
layer.AppliedProperties.Width*4,
layer.AppliedProperties.Height*4);
c.PushClip(new RectangleGeometry(rect));
c.DrawRectangle(layer.AppliedProperties.Brush, null, rect);
c.Pop();
}
public void Update(LayerModel layerModel, IDataModel dataModel, bool isPreview = false)
{
// Mousemat layers are always drawn 10*10 (which is 40*40 when scaled up)
layerModel.Properties.Width = 10;
layerModel.Properties.Height = 10;
layerModel.Properties.X = 0;
layerModel.Properties.Y = 0;
layerModel.Properties.Contain = true;
layerModel.AppliedProperties = new SimplePropertiesModel(layerModel.Properties);
if (isPreview || dataModel == null)
return;
// If not previewing, apply dynamic properties according to datamodel
var props = (SimplePropertiesModel) layerModel.AppliedProperties;
foreach (var dynamicProperty in props.DynamicProperties)
dynamicProperty.ApplyProperty(dataModel, layerModel.AppliedProperties);
}
public void SetupProperties(LayerModel layerModel)
{
if (layerModel.Properties is SimplePropertiesModel)
return;
layerModel.Properties = new SimplePropertiesModel(layerModel.Properties);
// Remove height and width dynamic properties since they are not applicable
layerModel.Properties.DynamicProperties.Remove(
layerModel.Properties.DynamicProperties.FirstOrDefault(d => d.LayerProperty == "Height"));
layerModel.Properties.DynamicProperties.Remove(
layerModel.Properties.DynamicProperties.FirstOrDefault(d => d.LayerProperty == "Width"));
}
public LayerPropertiesViewModel SetupViewModel(LayerEditorViewModel layerEditorViewModel,
LayerPropertiesViewModel layerPropertiesViewModel)
{
if (layerPropertiesViewModel is MousematPropertiesViewModel)
return layerPropertiesViewModel;
return new MousematPropertiesViewModel(layerEditorViewModel);
}
}
}

View File

@ -52,5 +52,5 @@ 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.3.2.0")] [assembly: AssemblyVersion("1.3.3.0")]
[assembly: AssemblyFileVersion("1.3.2.0")] [assembly: AssemblyFileVersion("1.3.3.0")]

View File

@ -60,6 +60,16 @@ namespace Artemis.Properties {
} }
} }
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap audio {
get {
object obj = ResourceManager.GetObject("audio", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary> /// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap. /// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary> /// </summary>
@ -258,6 +268,16 @@ namespace Artemis.Properties {
} }
} }
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap keypress {
get {
object obj = ResourceManager.GetObject("keypress", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary> /// <summary>
/// Looks up a localized resource of type System.Byte[]. /// Looks up a localized resource of type System.Byte[].
/// </summary> /// </summary>
@ -298,6 +318,16 @@ namespace Artemis.Properties {
} }
} }
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap mousemat {
get {
object obj = ResourceManager.GetObject("mousemat", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary> /// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap. /// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary> /// </summary>

View File

@ -199,4 +199,13 @@
<data name="ets2_telemetry_server_x86" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="ets2_telemetry_server_x86" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Modules\Games\EurotruckSimulator2\Resources\Win32\ets2-telemetry-server.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>..\Modules\Games\EurotruckSimulator2\Resources\Win32\ets2-telemetry-server.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data> </data>
<data name="mousemat" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\mousemat.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="keypress" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\keypress.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="audio" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\audio.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root> </root>

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using Microsoft.Win32; using Microsoft.Win32;
@ -76,9 +77,14 @@ namespace Artemis.Utilities
if (friendlyName != Empty) if (friendlyName != Empty)
list.Add(parent); list.Add(parent);
if (propertyInfo.PropertyType.Name != "String" && propertyInfo.PropertyType.Name != "DateTime") // Don't go into Strings, DateTimes or anything with JsonIgnore on it
if (propertyInfo.PropertyType.Name != "String" &&
propertyInfo.PropertyType.Name != "DateTime" &&
propertyInfo.CustomAttributes.All(a => a.AttributeType != typeof(JsonIgnoreAttribute)))
{
list.AddRange(GenerateTypeMap(propertyInfo.PropertyType.GetProperties(), list.AddRange(GenerateTypeMap(propertyInfo.PropertyType.GetProperties(),
path + $"{propertyInfo.Name}.")); path + $"{propertyInfo.Name}."));
}
} }
return list; return list;
} }

View File

@ -212,7 +212,7 @@ namespace Artemis.ViewModels.Flyouts
public void NavigateTo(string url) public void NavigateTo(string url)
{ {
Process.Start(new ProcessStartInfo(url)); System.Diagnostics.Process.Start(new ProcessStartInfo(url));
} }
protected override void HandleOpen() protected override void HandleOpen()

View File

@ -1,6 +1,9 @@
using System.Linq; using System.Linq;
using Artemis.DAL;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Modules.Effects.ProfilePreview; using Artemis.Modules.Effects.ProfilePreview;
using Artemis.Modules.Games.WoW;
using Artemis.Settings;
using Artemis.ViewModels.Abstract; using Artemis.ViewModels.Abstract;
namespace Artemis.ViewModels namespace Artemis.ViewModels
@ -23,8 +26,14 @@ namespace Artemis.ViewModels
{ {
base.OnActivate(); base.OnActivate();
var settings = SettingsProvider.Load<GeneralSettings>();
foreach (var gameViewModel in _gameViewModels.OrderBy(g => g.DisplayName)) foreach (var gameViewModel in _gameViewModels.OrderBy(g => g.DisplayName))
{
if (settings.GamestatePort != 62575 && gameViewModel is WoWViewModel)
continue;
ActivateItem(gameViewModel); ActivateItem(gameViewModel);
}
} }
} }
} }

View File

@ -31,6 +31,7 @@ namespace Artemis.ViewModels.Profiles
{ {
Layer = layer; Layer = layer;
ProposedLayer = Clone(layer); ProposedLayer = Clone(layer);
ProposedLayer.Children.Clear();
DataModel = DataModel; DataModel = DataModel;
LayerTypes = new BindableCollection<ILayerType>(types); LayerTypes = new BindableCollection<ILayerType>(types);
LayerAnimations = layerAnimations; LayerAnimations = layerAnimations;
@ -201,7 +202,7 @@ namespace Artemis.ViewModels.Profiles
ProposedLayer.Properties.Conditions.Add(conditionViewModel.LayerConditionModel); ProposedLayer.Properties.Conditions.Add(conditionViewModel.LayerConditionModel);
// If not a keyboard, ignore size and position // If not a keyboard, ignore size and position
if (ProposedLayer.LayerType.DrawType != DrawType.Keyboard) if (ProposedLayer.LayerType.DrawType != DrawType.Keyboard || !ProposedLayer.LayerType.ShowInEdtor)
{ {
ProposedLayer.Properties.Width = Layer.Properties.Width; ProposedLayer.Properties.Width = Layer.Properties.Width;
ProposedLayer.Properties.Height = Layer.Properties.Height; ProposedLayer.Properties.Height = Layer.Properties.Height;
@ -209,9 +210,9 @@ namespace Artemis.ViewModels.Profiles
ProposedLayer.Properties.Y = Layer.Properties.Y; ProposedLayer.Properties.Y = Layer.Properties.Y;
ProposedLayer.Properties.Contain = Layer.Properties.Contain; ProposedLayer.Properties.Contain = Layer.Properties.Contain;
} }
// Ignore the children, can't just temporarily add them to the proposed layer because // Ignore the children, can't just temporarily add them to the proposed layer because
// that would upset the child layers' relations (sounds like an episode of Dr. Phil amirite?) // that would upset the child layers' relations (sounds like Dr. Phil amirite?)
var currentObj = Clone(Layer); var currentObj = Clone(Layer);
currentObj.Children.Clear(); currentObj.Children.Clear();
var current = JsonConvert.SerializeObject(currentObj, Formatting.Indented); var current = JsonConvert.SerializeObject(currentObj, Formatting.Indented);

View File

@ -21,7 +21,7 @@
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<!-- Left --> <!-- Left -->
<ComboBox x:Name="DataModelProps" Grid.Column="0" Width="210" MaxDropDownHeight="125" <ComboBox x:Name="DataModelProps" Grid.Column="0" Width="210" MaxDropDownHeight="400"
HorizontalAlignment="Center" VerticalAlignment="Top"> HorizontalAlignment="Center" VerticalAlignment="Top">
<ComboBox.ItemTemplate> <ComboBox.ItemTemplate>
<DataTemplate> <DataTemplate>

View File

@ -31,11 +31,11 @@
<TextBlock x:Name="Name" Grid.Column="0" Margin="10" FontSize="13.333" VerticalAlignment="Center" Height="18" /> <TextBlock x:Name="Name" Grid.Column="0" Margin="10" FontSize="13.333" VerticalAlignment="Center" Height="18" />
<!-- Target property --> <!-- Target property -->
<ComboBox x:Name="Targets" Grid.Column="1" Margin="10,0" MaxDropDownHeight="125" VerticalAlignment="Center" <ComboBox x:Name="Targets" Grid.Column="1" Margin="10,0" MaxDropDownHeight="300" VerticalAlignment="Center"
Height="22"> Height="22">
<ComboBox.ItemTemplate> <ComboBox.ItemTemplate>
<DataTemplate> <DataTemplate>
<Grid MinWidth="435"> <Grid MinWidth="482">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />
@ -62,7 +62,7 @@
<!-- PercentageOfProperty --> <!-- PercentageOfProperty -->
<StackPanel Grid.Column="3" x:Name="SourcesIsVisible" VerticalAlignment="Center"> <StackPanel Grid.Column="3" x:Name="SourcesIsVisible" VerticalAlignment="Center">
<ComboBox x:Name="Sources" Margin="10,0" MaxDropDownHeight="125" Height="22" <ComboBox x:Name="Sources" Margin="10,0" MaxDropDownHeight="300" Height="22"
IsEnabled="{Binding Path=ControlsEnabled}"> IsEnabled="{Binding Path=ControlsEnabled}">
<ComboBox.ItemTemplate> <ComboBox.ItemTemplate>
<DataTemplate> <DataTemplate>

View File

@ -7,29 +7,18 @@
d:DesignHeight="476.986" d:DesignWidth="538.772"> d:DesignHeight="476.986" d:DesignWidth="538.772">
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto"> <ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
<Grid Margin="15, 5, 15, 5"> <Grid Margin="15, 5, 15, 5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" FontSize="20" MaxWidth="500" <Label Grid.Row="0" FontSize="20" MaxWidth="500" HorizontalAlignment="Left">
HorizontalAlignment="Left">
<Label.Content> <Label.Content>
<AccessText TextWrapping="Wrap" Text="Welcome to Artemis" /> <AccessText TextWrapping="Wrap" Text="Welcome to Artemis" />
</Label.Content> </Label.Content>
</Label> </Label>
<TextBlock Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" VerticalAlignment="Center" Margin="0,8" <TextBlock Grid.Row="1" VerticalAlignment="Center" Margin="0,8" TextWrapping="Wrap"
TextWrapping="Wrap" HorizontalAlignment="Left" HorizontalAlignment="Left" MaxWidth="520" TextAlignment="Justify">
MaxWidth="520" TextAlignment="Justify">
Hello, <LineBreak /><LineBreak /> Hello, <LineBreak /><LineBreak />
Thanks a bunch for downloading this application. You're going to enjoy this! :)<LineBreak /> Thanks a bunch for downloading this application. You're going to enjoy this! :)<LineBreak />
<LineBreak /> <LineBreak />

Binary file not shown.

View File

@ -4,7 +4,7 @@
<package id="Caliburn.Micro.Core" version="3.0.1" targetFramework="net452" /> <package id="Caliburn.Micro.Core" version="3.0.1" targetFramework="net452" />
<package id="Castle.Core" version="3.3.3" targetFramework="net452" /> <package id="Castle.Core" version="3.3.3" targetFramework="net452" />
<package id="Colore" version="5.0.0" targetFramework="net461" /> <package id="Colore" version="5.0.0" targetFramework="net461" />
<package id="CUE.NET" version="1.0.3" targetFramework="net452" /> <package id="CUE.NET" version="1.1.0" targetFramework="net461" />
<package id="DeltaCompressionDotNet" version="1.0.0" targetFramework="net461" /> <package id="DeltaCompressionDotNet" version="1.0.0" targetFramework="net461" />
<package id="DynamicExpresso.Core" version="1.3.1.0" targetFramework="net452" /> <package id="DynamicExpresso.Core" version="1.3.1.0" targetFramework="net452" />
<package id="Extended.Wpf.Toolkit" version="2.9" targetFramework="net461" /> <package id="Extended.Wpf.Toolkit" version="2.9" targetFramework="net461" />
@ -23,6 +23,7 @@
<package id="Ninject.Extensions.Logging.nlog4" version="3.2.3.0" targetFramework="net452" /> <package id="Ninject.Extensions.Logging.nlog4" version="3.2.3.0" targetFramework="net452" />
<package id="NLog" version="4.3.7" targetFramework="net461" /> <package id="NLog" version="4.3.7" targetFramework="net461" />
<package id="NLog.Schema" version="4.3.7" targetFramework="net461" /> <package id="NLog.Schema" version="4.3.7" targetFramework="net461" />
<package id="Process.NET" version="1.0.1" targetFramework="net461" />
<package id="Splat" version="1.6.2" targetFramework="net461" /> <package id="Splat" version="1.6.2" targetFramework="net461" />
<package id="SpotifyAPI-NET" version="2.11.0" targetFramework="net461" /> <package id="SpotifyAPI-NET" version="2.11.0" targetFramework="net461" />
<package id="squirrel.windows" version="1.4.4" targetFramework="net461" /> <package id="squirrel.windows" version="1.4.4" targetFramework="net461" />