1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-13 05:48:35 +00:00
* Changed Rocket League to no longer rely on float but int for boost reading

* Small fixes
Fixed layer sometimes losing it's parent after edit
Reoganized layer type view(models)
Added animations to headsets (broken for Corsair atm)

* Working toward 1.2.0
Fixed sliding animations sometimes leaving a blank pixel
Added a 'new folder' button (resolves #123)
Added official G810 support (needs testing, shares profiles with the G910, resolves #114)
Added support for generic Logitech RGB devices (needs testing, pretends to be a headset for now, resolves #45)

* Implemented a generic fix for transparency issues

* Rendering cleanup
Added a RenderFrame class to encapsulate all bitmaps that must be rendered
LayerTypes now define a target device
LayerTypes can set wheter to be drawn in the editor or not
Added Generic device type

* Resharper cleanup

* Fixed startup issues, together with the refactor this resolves #111 it seems.

* Fixed profile editor crash
Fixed boolean condition not showing last value in editor

* Added missing generic device type usage check

* Generic device fixes

* Fixed folder cloning
Fixed unsaved changes false-positive

* Profile editor no longer takes over keyboard if a game is running
Updated Rocket League for 1.21

* Added JsonIgnore to ILayerType properties
Renamed Generic device to Generic (Logitech)

* Reduced profile editor CPU usage

* Non-keyboard types clean up keyboard properties when selected
Fixed a crash while saving

* Added layer resize on import
Null reference fixes
Cleaned up JSON some more
Added default animation to layer (NoneAnimation)
Removed unnecessary layer properties casts

* Updated default profiles for all keyboards

* Bumped version number to 1.2.0
This commit is contained in:
Robert Beekman 2016-07-19 21:56:58 +02:00 committed by GitHub
parent 86e4f83b1d
commit 11035f7920
92 changed files with 1196 additions and 571 deletions

View File

@ -2,24 +2,59 @@
<configuration>
<configSections>
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<section name="Artemis.Modules.Effects.Bubbles.Bubbles" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<section name="Artemis.Modules.Effects.WindowsProfile.WindowsProfile" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<section name="Artemis.Modules.Games.Overwatch.Overwatch" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<section name="Artemis.Modules.Games.TheDivision.TheDivision" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<section name="Artemis.Modules.Games.Dota2.Dota2" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<section name="Artemis.Modules.Overlays.VolumeDisplay.VolumeDisplay" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<section name="Artemis.Modules.Games.RocketLeague.RocketLeague" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<section name="Artemis.Settings.Offsets" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<section name="Artemis.Modules.Games.Witcher3.Witcher3" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<section name="Artemis.Modules.Effects.AudioVisualizer.AudioVisualization" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<section name="Artemis.Modules.Games.CounterStrike.CounterStrike" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<section name="Artemis.Settings.CounterStrike" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<section name="Artemis.Settings.AudioVisualization" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<section name="Artemis.Settings.RocketLeague" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<section name="Artemis.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<section name="Artemis.Settings.TypeWave" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<section name="Artemis.Settings.General" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<sectionGroup name="userSettings"
type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<section name="Artemis.Modules.Effects.Bubbles.Bubbles"
type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<section name="Artemis.Modules.Effects.WindowsProfile.WindowsProfile"
type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<section name="Artemis.Modules.Games.Overwatch.Overwatch"
type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<section name="Artemis.Modules.Games.TheDivision.TheDivision"
type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<section name="Artemis.Modules.Games.Dota2.Dota2"
type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<section name="Artemis.Modules.Overlays.VolumeDisplay.VolumeDisplay"
type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<section name="Artemis.Modules.Games.RocketLeague.RocketLeague"
type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<section name="Artemis.Settings.Offsets"
type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<section name="Artemis.Modules.Games.Witcher3.Witcher3"
type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<section name="Artemis.Modules.Effects.AudioVisualizer.AudioVisualization"
type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<section name="Artemis.Modules.Games.CounterStrike.CounterStrike"
type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<section name="Artemis.Settings.CounterStrike"
type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<section name="Artemis.Settings.AudioVisualization"
type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<section name="Artemis.Settings.RocketLeague"
type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<section name="Artemis.Properties.Settings"
type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<section name="Artemis.Settings.TypeWave"
type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<section name="Artemis.Settings.General"
type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
allowExeDefinition="MachineToLocalUser" requirePermission="false" />
</sectionGroup>
</configSections>
<connectionStrings />

View File

@ -38,8 +38,8 @@
<SupportUrl>https://github.com/SpoinkyNL/Artemis/wiki/Frequently-Asked-Questions-%28FAQ%29</SupportUrl>
<ProductName>Artemis</ProductName>
<PublisherName>Artemis</PublisherName>
<ApplicationRevision>3</ApplicationRevision>
<ApplicationVersion>1.1.3.3</ApplicationVersion>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.2.0.0</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<CreateDesktopShortcut>true</CreateDesktopShortcut>
<PublishWizardCompleted>true</PublishWizardCompleted>
@ -275,6 +275,9 @@
<Compile Include="DeviceProviders\Corsair\CorsairMice.cs" />
<Compile Include="DeviceProviders\Corsair\CorsairHeadsets.cs" />
<Compile Include="DeviceProviders\DeviceProvider.cs" />
<Compile Include="DeviceProviders\Logitech\G810.cs" />
<Compile Include="DeviceProviders\Logitech\LogitechGeneric.cs" />
<Compile Include="DeviceProviders\Logitech\LogitechKeyboard.cs" />
<Compile Include="Events\ActiveKeyboardChanged.cs" />
<Compile Include="Events\RazerColorArrayChanged.cs" />
<Compile Include="Events\ToggleEnabled.cs" />
@ -282,9 +285,9 @@
<Compile Include="InjectionFactories\ILayerEditorVmFactory.cs" />
<Compile Include="InjectionFactories\IProfileEditorVmFactory.cs" />
<Compile Include="ItemBehaviours\BindableSelectedItemBehavior.cs" />
<Compile Include="DeviceProviders\Corsair\CorsairRGB.cs" />
<Compile Include="DeviceProviders\Corsair\CorsairKeyboards.cs" />
<Compile Include="DeviceProviders\KeyboardProvider.cs" />
<Compile Include="DeviceProviders\Logitech\Orion.cs" />
<Compile Include="DeviceProviders\Logitech\G910.cs" />
<Compile Include="DeviceProviders\Logitech\Utilities\KeyboardNames.cs" />
<Compile Include="DeviceProviders\Logitech\Utilities\KeyMap.cs" />
<Compile Include="DeviceProviders\Logitech\Utilities\LogitechGSDK.cs" />
@ -306,6 +309,11 @@
<Compile Include="Profiles\Layers\Animations\NoneAnimation.cs" />
<Compile Include="Profiles\Layers\Models\EventPropertiesModel.cs" />
<Compile Include="Profiles\Layers\Models\KeyboardEventPropertiesModel.cs" />
<Compile Include="Profiles\Layers\Types\Generic\GenericPropertiesView.xaml.cs">
<DependentUpon>GenericPropertiesView.xaml</DependentUpon>
</Compile>
<Compile Include="Profiles\Layers\Types\Generic\GenericPropertiesViewModel.cs" />
<Compile Include="Profiles\Layers\Types\Generic\GenericType.cs" />
<Compile Include="Profiles\ProfileModel.cs" />
<Compile Include="Profiles\Layers\Models\SimplePropertiesModel.cs" />
<Compile Include="Profiles\Layers\Types\Keyboard\KeyboardPropertiesModel.cs" />
@ -503,14 +511,14 @@
<Compile Include="Modules\Games\Witcher3\Witcher3ViewModel.cs" />
<Compile Include="ViewModels\Profiles\Events\EventPropertiesViewModel.cs" />
<Compile Include="ViewModels\Profiles\ProfileViewModel.cs" />
<Compile Include="ViewModels\Profiles\Layers\KeyboardPropertiesViewModel.cs" />
<Compile Include="Profiles\Layers\Types\Keyboard\KeyboardPropertiesViewModel.cs" />
<Compile Include="ViewModels\Profiles\LayerConditionViewModel.cs" />
<Compile Include="ViewModels\Profiles\LayerDynamicPropertiesViewModel.cs" />
<Compile Include="ViewModels\Profiles\LayerEditorViewModel.cs" />
<Compile Include="ViewModels\Profiles\Layers\LayerPropertiesViewModel.cs" />
<Compile Include="ViewModels\Profiles\Layers\HeadsetPropertiesViewModel.cs" />
<Compile Include="ViewModels\Profiles\Layers\FolderPropertiesViewModel.cs" />
<Compile Include="ViewModels\Profiles\Layers\MousePropertiesViewModel.cs" />
<Compile Include="Profiles\Layers\Abstract\LayerPropertiesViewModel.cs" />
<Compile Include="Profiles\Layers\Types\Headset\HeadsetPropertiesViewModel.cs" />
<Compile Include="Profiles\Layers\Types\Folder\FolderPropertiesViewModel.cs" />
<Compile Include="Profiles\Layers\Types\Mouse\MousePropertiesViewModel.cs" />
<Compile Include="ViewModels\OverlaysViewModel.cs" />
<Compile Include="Modules\Overlays\VolumeDisplay\VolumeDisplayViewModel.cs" />
<Compile Include="ViewModels\Profiles\ProfileEditorViewModel.cs" />
@ -550,13 +558,13 @@
<Compile Include="Views\Profiles\Events\EventPropertiesView.xaml.cs">
<DependentUpon>EventPropertiesView.xaml</DependentUpon>
</Compile>
<Compile Include="Views\Profiles\Layers\FolderPropertiesView.xaml.cs">
<Compile Include="Profiles\Layers\Types\Folder\FolderPropertiesView.xaml.cs">
<DependentUpon>FolderPropertiesView.xaml</DependentUpon>
</Compile>
<Compile Include="Views\Profiles\Layers\HeadsetPropertiesView.xaml.cs">
<Compile Include="Profiles\Layers\Types\Headset\HeadsetPropertiesView.xaml.cs">
<DependentUpon>HeadsetPropertiesView.xaml</DependentUpon>
</Compile>
<Compile Include="Views\Profiles\Layers\KeyboardPropertiesView.xaml.cs">
<Compile Include="Profiles\Layers\Types\Keyboard\KeyboardPropertiesView.xaml.cs">
<DependentUpon>KeyboardPropertiesView.xaml</DependentUpon>
</Compile>
<Compile Include="Views\Profiles\LayerConditionView.xaml.cs">
@ -568,7 +576,7 @@
<Compile Include="Views\Profiles\LayerEditorView.xaml.cs">
<DependentUpon>LayerEditorView.xaml</DependentUpon>
</Compile>
<Compile Include="Views\Profiles\Layers\MousePropertiesView.xaml.cs">
<Compile Include="Profiles\Layers\Types\Mouse\MousePropertiesView.xaml.cs">
<DependentUpon>MousePropertiesView.xaml</DependentUpon>
</Compile>
<Compile Include="Views\OverlaysView.xaml.cs">
@ -594,6 +602,8 @@
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<None Include="Resources\generic.png" />
<None Include="Resources\Keyboards\g810.png" />
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<SubType>Designer</SubType>
@ -707,6 +717,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Profiles\Layers\Types\Generic\GenericPropertiesView.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Resources\Icons.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
@ -767,15 +781,15 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\Profiles\Layers\FolderPropertiesView.xaml">
<Page Include="Profiles\Layers\Types\Folder\FolderPropertiesView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\Profiles\Layers\HeadsetPropertiesView.xaml">
<Page Include="Profiles\Layers\Types\Headset\HeadsetPropertiesView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\Profiles\Layers\KeyboardPropertiesView.xaml">
<Page Include="Profiles\Layers\Types\Keyboard\KeyboardPropertiesView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
@ -791,7 +805,7 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\Profiles\Layers\MousePropertiesView.xaml">
<Page Include="Profiles\Layers\Types\Mouse\MousePropertiesView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>

View File

@ -117,7 +117,7 @@ namespace Artemis
private void CheckDuplicateInstances()
{
bool aIsNewInstance;
Mutex = new Mutex(true, "ArtemisMutex2", out aIsNewInstance);
Mutex = new Mutex(true, "ArtemisMutex", out aIsNewInstance);
if (aIsNewInstance)
return;

View File

@ -58,15 +58,32 @@ namespace Artemis.DAL
{
if (prof == null)
throw new ArgumentNullException(nameof(prof));
if (!(prof.GameName?.Length > 1) || !(prof.KeyboardSlug?.Length > 1) || !(prof.Name?.Length > 1))
throw new ArgumentException("Profile is invalid. Name, GameName and KeyboardSlug are required");
var path = ProfileFolder + $@"\{prof.KeyboardSlug}\{prof.GameName}";
if (!Directory.Exists(path))
Directory.CreateDirectory(path);
lock (prof)
{
if (!(prof.GameName?.Length > 1) || !(prof.KeyboardSlug?.Length > 1) || !(prof.Name?.Length > 1))
throw new ArgumentException("Profile is invalid. Name, GameName and KeyboardSlug are required");
var json = JsonConvert.SerializeObject(prof, Formatting.Indented);
File.WriteAllText(path + $@"\{prof.Name}.json", json);
var path = ProfileFolder + $@"\{prof.KeyboardSlug}\{prof.GameName}";
if (!Directory.Exists(path))
Directory.CreateDirectory(path);
string json;
// Should saving fail for whatever reason, catch the exception and log it
// But DON'T touch the profile file.
try
{
json = JsonConvert.SerializeObject(prof, Formatting.Indented);
}
catch (Exception e)
{
Logger.Error(e, "Couldn't save profile '{0}.json'", prof.Name);
return;
}
File.WriteAllText(path + $@"\{prof.Name}.json", json);
}
}
private static List<ProfileModel> ReadProfiles()

View File

@ -25,13 +25,16 @@ namespace Artemis.DeviceProviders.Corsair
CueSDK.Initialize();
Logger.Debug("Attempted to enable Corsair headset. CanUse: {0}", CanUse);
if (CanUse)
CueSDK.HeadsetSDK.UpdateMode = UpdateMode.Manual;
return CanUse;
}
public override void Disable()
{
if (CueSDK.IsInitialized)
CueSDK.Reinitialize();
throw new NotImplementedException("Can only disable a keyboard");
}
public override void UpdateDevice(Bitmap bitmap)
@ -51,7 +54,7 @@ namespace Artemis.DeviceProviders.Corsair
{
var col = ledIndex == 0
? bitmap.GetPixel(0, 0)
: bitmap.GetPixel((int)((ledIndex + 1) * step - 1), (int)((ledIndex + 1) * step - 1));
: bitmap.GetPixel((int) ((ledIndex + 1)*step - 1), (int) ((ledIndex + 1)*step - 1));
corsairLed.Color = col;
ledIndex++;

View File

@ -11,12 +11,12 @@ using Point = System.Drawing.Point;
namespace Artemis.DeviceProviders.Corsair
{
public class CorsairRGB : KeyboardProvider
public class CorsairKeyboards : KeyboardProvider
{
private CorsairKeyboard _keyboard;
private ImageBrush _keyboardBrush;
public CorsairRGB(ILogger logger)
public CorsairKeyboards(ILogger logger)
{
Logger = logger;
Name = "Corsair RGB Keyboards";
@ -68,6 +68,7 @@ namespace Artemis.DeviceProviders.Corsair
}
Logger.Debug("Corsair SDK reported device as: {0}", _keyboard.DeviceInfo.Model);
Slug = "corsair-" + _keyboard.DeviceInfo.Model.Replace(' ', '-').ToLower();
_keyboard.Brush = _keyboardBrush ?? (_keyboardBrush = new ImageBrush());
}

View File

@ -25,13 +25,16 @@ namespace Artemis.DeviceProviders.Corsair
CueSDK.Initialize();
Logger.Debug("Attempted to enable Corsair mice. CanUse: {0}", CanUse);
if (CanUse)
CueSDK.MouseSDK.UpdateMode = UpdateMode.Manual;
return CanUse;
}
public override void Disable()
{
if (CueSDK.IsInitialized)
CueSDK.Reinitialize();
throw new NotImplementedException("Can only disable a keyboard");
}
public override void UpdateDevice(Bitmap bitmap)

View File

@ -45,6 +45,7 @@ namespace Artemis.DeviceProviders
{
Keyboard,
Mouse,
Headset
Headset,
Generic
}
}

View File

@ -0,0 +1,21 @@
using System.Windows;
using Artemis.Properties;
namespace Artemis.DeviceProviders.Logitech
{
internal class G810 : LogitechKeyboard
{
public G810()
{
Name = "Logitech G810 RGB";
Slug = "logitech-g910"; // Shares slugs with the G910 because the layout is identical
CantEnableText = "Couldn't connect to your Logitech G810.\n" +
"Please check your cables and updating the Logitech Gaming Software\n" +
"A minimum version of 8.81.15 is required.\n\n" +
"If needed, you can select a different keyboard in Artemis under settings.";
Height = 6;
Width = 21;
PreviewSettings = new PreviewSettings(675, 185, new Thickness(0, 35, 0, 0), Resources.g810);
}
}
}

View File

@ -0,0 +1,21 @@
using System.Windows;
using Artemis.Properties;
namespace Artemis.DeviceProviders.Logitech
{
internal class G910 : LogitechKeyboard
{
public G910()
{
Name = "Logitech G910 RGB";
Slug = "logitech-g910";
CantEnableText = "Couldn't connect to your Logitech G910.\n" +
"Please check your cables and updating the Logitech Gaming Software\n" +
"A minimum version of 8.81.15 is required.\n\n" +
"If needed, you can select a different keyboard in Artemis under settings.";
Height = 6;
Width = 21;
PreviewSettings = new PreviewSettings(540, 154, new Thickness(25, -80, 0, 0), Resources.g910);
}
}
}

View File

@ -0,0 +1,58 @@
using System;
using System.Drawing;
using Artemis.DeviceProviders.Logitech.Utilities;
using Ninject.Extensions.Logging;
namespace Artemis.DeviceProviders.Logitech
{
// TODO: Handle shutdown, maybe implement Disable() afterall?
public class LogitechGeneric : DeviceProvider
{
/// <summary>
/// A generic Logitech DeviceProvider. Because the Logitech SDK currently doesn't allow specific
/// device targeting (only very broad per-key-RGB and full RGB etc..)
/// </summary>
public LogitechGeneric(ILogger logger)
{
Logger = logger;
Type = DeviceType.Generic;
}
public ILogger Logger { get; set; }
public override void UpdateDevice(Bitmap bitmap)
{
if (!CanUse || bitmap == null)
return;
using (bitmap)
{
var col = bitmap.GetPixel(bitmap.Width/2, bitmap.Height/2);
LogitechGSDK.LogiLedSetTargetDevice(LogitechGSDK.LOGI_DEVICETYPE_RGB);
LogitechGSDK.LogiLedSetLighting((int) (col.R/2.55), (int) (col.G/2.55), (int) (col.B/2.55));
}
}
public override bool TryEnable()
{
var majorNum = 0;
var minorNum = 0;
var buildNum = 0;
LogitechGSDK.LogiLedInit();
LogitechGSDK.LogiLedGetSdkVersion(ref majorNum, ref minorNum, ref buildNum);
// Turn it into one long number...
var version = int.Parse($"{majorNum}{minorNum}{buildNum}");
CanUse = version >= 88115;
Logger.Debug("Attempted to enable Logitech generic device. CanUse: {0}", CanUse);
return CanUse;
}
public override void Disable()
{
throw new NotImplementedException("Can only disable a keyboard");
}
}
}

View File

@ -2,36 +2,21 @@
using System.Threading;
using System.Windows;
using Artemis.DeviceProviders.Logitech.Utilities;
using Artemis.Properties;
using Artemis.Utilities;
using Artemis.Utilities.LogitechDll;
using Microsoft.Win32;
namespace Artemis.DeviceProviders.Logitech
{
internal class Orion : KeyboardProvider
public abstract class LogitechKeyboard : KeyboardProvider
{
public Orion()
{
Name = "Logitech G910 RGB";
Slug = "logitech-g910";
CantEnableText = "Couldn't connect to your Logitech G910.\n" +
"Please check your cables and updating the Logitech Gaming Software\n" +
"A minimum version of 8.81.15 is required.\n\n" +
"If needed, you can select a different keyboard in Artemis under settings.";
Height = 6;
Width = 21;
PreviewSettings = new PreviewSettings(540, 154, new Thickness(25, -80, 0, 0), Resources.g910);
}
public override bool CanEnable()
{
//Check to see if VC++ 2012 x64 is installed.
if (Registry.LocalMachine.OpenSubKey(
@"SOFTWARE\Classes\Installer\Dependencies\{ca67548a-5ebe-413a-b50c-4b9ceb6d66c6}") == null)
{
CantEnableText = "Couldn't connect to your Logitech G910.\n" +
CantEnableText = "Couldn't connect to your Logitech keyboard.\n" +
"The Visual C 2012 Redistributable could not be found, which is required.\n" +
"Please download it by going to the following URL:\n\n" +
"https://www.microsoft.com/download/confirmation.aspx?id=30679";
@ -77,9 +62,9 @@ namespace Artemis.DeviceProviders.Logitech
Thread.Sleep(200);
LogitechGSDK.LogiLedSaveCurrentLighting();
LogitechGSDK.LogiLedSetTargetDevice(LogitechGSDK.LOGI_DEVICETYPE_PERKEY_RGB);
// Disable keys we can't color
LogitechGSDK.LogiLedSetTargetDevice(LogitechGSDK.LOGI_DEVICETYPE_PERKEY_RGB);
LogitechGSDK.LogiLedSetLighting(0, 0, 0);
}
@ -92,6 +77,7 @@ namespace Artemis.DeviceProviders.Logitech
public override void DrawBitmap(Bitmap bitmap)
{
LogitechGSDK.LogiLedSetTargetDevice(LogitechGSDK.LOGI_DEVICETYPE_PERKEY_RGB);
LogitechGSDK.LogiLedSetLightingFromBitmap(OrionUtilities.BitmapToByteArray(bitmap));
}
}

View File

@ -27,7 +27,7 @@ namespace Artemis.DeviceProviders.Razer
{
if (!Chroma.IsSdkAvailable())
return false;
// Some people have Synapse installed, but not a Chroma keyboard, deal with this
var blackWidowFound = Chroma.Instance.Query(Devices.Blackwidow).Connected;
var blackWidowTeFound = Chroma.Instance.Query(Devices.BlackwidowTe).Connected;

View File

@ -17,6 +17,7 @@ using Artemis.Profiles.Layers.Animations;
using Artemis.Profiles.Layers.Conditions;
using Artemis.Profiles.Layers.Interfaces;
using Artemis.Profiles.Layers.Types.Folder;
using Artemis.Profiles.Layers.Types.Generic;
using Artemis.Profiles.Layers.Types.Headset;
using Artemis.Profiles.Layers.Types.Keyboard;
using Artemis.Profiles.Layers.Types.KeyboardGif;
@ -54,13 +55,16 @@ namespace Artemis.InjectionModules
#region Devices
// Keyboards
Bind<DeviceProvider>().To<CorsairRGB>().InSingletonScope();
Bind<DeviceProvider>().To<Orion>().InSingletonScope();
Bind<DeviceProvider>().To<CorsairKeyboards>().InSingletonScope();
Bind<DeviceProvider>().To<G910>().InSingletonScope();
Bind<DeviceProvider>().To<G810>().InSingletonScope();
Bind<DeviceProvider>().To<BlackWidow>().InSingletonScope();
// Mice
Bind<DeviceProvider>().To<CorsairMice>().InSingletonScope();
// Headsets
Bind<DeviceProvider>().To<CorsairHeadsets>().InSingletonScope();
// Other
Bind<DeviceProvider>().To<LogitechGeneric>().InSingletonScope();
#endregion
@ -83,6 +87,7 @@ namespace Artemis.InjectionModules
Bind<ILayerType>().To<KeyboardType>();
Bind<ILayerType>().To<KeyboardGifType>();
Bind<ILayerType>().To<MouseType>();
Bind<ILayerType>().To<GenericType>();
#endregion
}

View File

@ -30,13 +30,14 @@ namespace Artemis.Managers
.Cast<KeyboardProvider>().ToList();
MiceProviders = deviceProviders.Where(d => d.Type == DeviceType.Mouse).ToList();
HeadsetProviders = deviceProviders.Where(d => d.Type == DeviceType.Headset).ToList();
GenericProviders = deviceProviders.Where(d => d.Type == DeviceType.Generic).ToList();
_logger.Info("Intialized DeviceManager with {0} device providers", deviceProviders.Count);
}
public List<DeviceProvider> HeadsetProviders { get; set; }
public List<DeviceProvider> MiceProviders { get; set; }
public List<DeviceProvider> HeadsetProviders { get; set; }
public List<DeviceProvider> GenericProviders { get; set; }
[Inject]
public MetroDialogService DialogService { get; set; }
@ -133,6 +134,8 @@ namespace Artemis.Managers
mouseProvider.TryEnableAsync();
foreach (var headsetProvider in HeadsetProviders)
headsetProvider.TryEnableAsync();
foreach (var genericProvider in GenericProviders)
genericProvider.TryEnableAsync();
}
/// <summary>

View File

@ -1,24 +1,25 @@
using System;
using System.Drawing;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Timers;
using Artemis.Events;
using Artemis.DeviceProviders;
using Caliburn.Micro;
using Ninject.Extensions.Logging;
using Timer = System.Timers.Timer;
namespace Artemis.Managers
{
/// <summary>
/// Manages the main programn loop
/// </summary>
public class LoopManager : IDisposable, IHandle<ActiveKeyboardChanged>, IHandle<ActiveEffectChanged>
public class LoopManager : IDisposable
{
private readonly DeviceManager _deviceManager;
private readonly EffectManager _effectManager;
private readonly ILogger _logger;
private readonly Timer _loopTimer;
private Bitmap _keyboardBitmap;
public LoopManager(IEventAggregator events, ILogger logger, EffectManager effectManager,
DeviceManager deviceManager)
@ -45,19 +46,6 @@ namespace Artemis.Managers
{
_loopTimer.Stop();
_loopTimer.Dispose();
_keyboardBitmap?.Dispose();
}
public void Handle(ActiveEffectChanged message)
{
if (_deviceManager.ActiveKeyboard != null && _effectManager.ActiveEffect != null)
_keyboardBitmap = _deviceManager.ActiveKeyboard.KeyboardBitmap(_effectManager.ActiveEffect.KeyboardScale);
}
public void Handle(ActiveKeyboardChanged message)
{
if (_deviceManager.ActiveKeyboard != null && _effectManager.ActiveEffect != null)
_keyboardBitmap = _deviceManager.ActiveKeyboard.KeyboardBitmap(_effectManager.ActiveEffect.KeyboardScale);
}
public Task StartAsync()
@ -74,6 +62,10 @@ namespace Artemis.Managers
if (_deviceManager.ActiveKeyboard == null)
_deviceManager.EnableLastKeyboard();
while (_deviceManager.ChangingKeyboard)
Thread.Sleep(200);
// If still null, no last keyboard, so stop.
if (_deviceManager.ActiveKeyboard == null)
{
@ -104,13 +96,11 @@ namespace Artemis.Managers
Running = false;
_deviceManager.ReleaseActiveKeyboard();
_keyboardBitmap?.Dispose();
_keyboardBitmap = null;
}
private void Render(object sender, ElapsedEventArgs e)
{
if (!Running)
if (!Running || _deviceManager.ChangingKeyboard)
return;
// Stop if no active effect
@ -122,9 +112,6 @@ namespace Artemis.Managers
}
var renderEffect = _effectManager.ActiveEffect;
if (_deviceManager.ChangingKeyboard || _keyboardBitmap == null)
return;
// Stop if no active keyboard
if (_deviceManager.ActiveKeyboard == null)
{
@ -143,32 +130,69 @@ namespace Artemis.Managers
if (renderEffect.Initialized)
renderEffect.Update();
// Get ActiveEffect's bitmap
Bitmap mouseBitmap = null;
Bitmap headsetBitmap = null;
// Get the devices that must be rendered to
var mice = _deviceManager.MiceProviders.Where(m => m.CanUse).ToList();
var headsets = _deviceManager.HeadsetProviders.Where(m => m.CanUse).ToList();
var generics = _deviceManager.GenericProviders.Where(m => m.CanUse).ToList();
if (renderEffect.Initialized)
renderEffect.Render(_keyboardBitmap, out mouseBitmap, out headsetBitmap, mice.Any(), headsets.Any());
// Draw enabled overlays on top of the renderEffect
foreach (var overlayModel in _effectManager.EnabledOverlays)
// Setup the frame for this tick
using (var frame = new RenderFrame(_deviceManager.ActiveKeyboard))
{
overlayModel.Update();
overlayModel.RenderOverlay(_keyboardBitmap, ref mouseBitmap, ref headsetBitmap, mice.Any(),
headsets.Any());
if (renderEffect.Initialized)
renderEffect.Render(frame, !mice.Any() && !headsets.Any() && !generics.Any());
// Draw enabled overlays on top of the renderEffect
foreach (var overlayModel in _effectManager.EnabledOverlays)
{
overlayModel.Update();
overlayModel.RenderOverlay(frame, !mice.Any() && !headsets.Any() && !generics.Any());
}
// Update the keyboard
_deviceManager.ActiveKeyboard?.DrawBitmap(frame.KeyboardBitmap);
// Update the other devices
foreach (var mouse in mice)
mouse.UpdateDevice(frame.MouseBitmap);
foreach (var headset in headsets)
headset.UpdateDevice(frame.HeadsetBitmap);
foreach (var generic in generics)
generic.UpdateDevice(frame.GenericBitmap);
}
// Update mice and headsets
foreach (var mouse in mice)
mouse.UpdateDevice(mouseBitmap);
foreach (var headset in headsets)
headset.UpdateDevice(headsetBitmap);
// Update the keyboard
_deviceManager.ActiveKeyboard?.DrawBitmap(_keyboardBitmap);
}
}
}
public class RenderFrame : IDisposable
{
public RenderFrame(KeyboardProvider keyboard)
{
KeyboardBitmap = keyboard.KeyboardBitmap(4);
MouseBitmap = new Bitmap(40, 40);
HeadsetBitmap = new Bitmap(40, 40);
GenericBitmap = new Bitmap(40, 40);
using (var g = Graphics.FromImage(KeyboardBitmap))
g.Clear(Color.Black);
using (var g = Graphics.FromImage(MouseBitmap))
g.Clear(Color.Black);
using (var g = Graphics.FromImage(HeadsetBitmap))
g.Clear(Color.Black);
using (var g = Graphics.FromImage(GenericBitmap))
g.Clear(Color.Black);
}
public Bitmap KeyboardBitmap { get; set; }
public Bitmap MouseBitmap { get; set; }
public Bitmap HeadsetBitmap { get; set; }
public Bitmap GenericBitmap { get; set; }
public void Dispose()
{
KeyboardBitmap.Dispose();
MouseBitmap.Dispose();
HeadsetBitmap.Dispose();
GenericBitmap.Dispose();
}
}
}

View File

@ -122,9 +122,6 @@ namespace Artemis.Managers
if (EffectManager.ActiveEffect != null)
EffectManager.DisableInactiveGame();
if (EffectManager.ActiveEffect is ProfilePreviewModel)
return;
// If the currently active effect is a no longer running game, get rid of it.
var activeGame = EffectManager.ActiveEffect as GameModel;
if (activeGame != null)

View File

@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Timers;
using Artemis.Models;
using Artemis.Modules.Effects.ProfilePreview;
using Artemis.Settings;
using Artemis.ViewModels.Abstract;
@ -63,7 +64,7 @@ namespace Artemis.Managers
}
else
{
if (_effectManager.ActiveEffect != ProfilePreviewModel)
if (_effectManager.ActiveEffect != ProfilePreviewModel && !(_effectManager.ActiveEffect is GameModel))
{
_logger.Debug("Activate profile preview");
_effectManager.ChangeEffect(ProfilePreviewModel);

View File

@ -6,9 +6,8 @@ using System.Windows;
using Artemis.Managers;
using Artemis.Models.Interfaces;
using Artemis.Profiles;
using Artemis.Profiles.Layers.Interfaces;
using Artemis.Profiles.Layers.Models;
using Artemis.Profiles.Layers.Types.Headset;
using Artemis.Profiles.Layers.Types.Mouse;
using Newtonsoft.Json;
namespace Artemis.Models
@ -43,59 +42,61 @@ namespace Artemis.Models
public abstract void Update();
// Called after every update
public virtual void Render(Bitmap keyboard, out Bitmap mouse, out Bitmap headset, bool renderMice,
bool renderHeadsets)
/// <summary>
/// Renders the currently active profile
/// </summary>
/// <param name="frame"></param>
/// <param name="keyboardOnly"></param>
public virtual void Render(RenderFrame frame, bool keyboardOnly)
{
mouse = null;
headset = null;
if (Profile == null || DataModel == null || MainManager.DeviceManager.ActiveKeyboard == null)
return;
// Get all enabled layers who's conditions are met
var renderLayers = GetRenderLayers(renderMice, renderHeadsets);
// Render the keyboard layer-by-layer
var keyboardRect = MainManager.DeviceManager.ActiveKeyboard.KeyboardRectangle(KeyboardScale);
using (var g = Graphics.FromImage(keyboard))
lock (DataModel)
{
// Fill the bitmap's background with black to avoid trailing colors on some keyboards
g.Clear(Color.Black);
Profile.DrawLayers(g, renderLayers.Where(rl => rl.MustDraw()), DataModel, keyboardRect, false, true);
}
// Get all enabled layers who's conditions are met
var renderLayers = GetRenderLayers(keyboardOnly);
// Render the mouse layer-by-layer
var smallRect = new Rect(0, 0, 40, 40);
mouse = new Bitmap(40, 40);
using (var g = Graphics.FromImage(mouse))
{
// Not all SDK's handle transparency
g.Clear(Color.Black);
Profile.DrawLayers(g, renderLayers.Where(rl => rl.LayerType is MouseType), DataModel, smallRect,
false, true);
}
// Render the keyboard layer-by-layer
var keyboardRect = MainManager.DeviceManager.ActiveKeyboard.KeyboardRectangle(KeyboardScale);
using (var g = Graphics.FromImage(frame.KeyboardBitmap))
{
Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Keyboard),
DataModel, keyboardRect, false, true);
}
// Render mice layer-by-layer
var devRec = new Rect(0, 0, 40, 40);
using (var g = Graphics.FromImage(frame.MouseBitmap))
{
Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Mouse), DataModel,
devRec, false, true);
}
// Render headsets layer-by-layer
using (var g = Graphics.FromImage(frame.HeadsetBitmap))
{
Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Headset),
DataModel, devRec, false, true);
}
// Render generic devices layer-by-layer
using (var g = Graphics.FromImage(frame.GenericBitmap))
{
Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Generic),
DataModel, devRec, false, true);
}
// Render the headset layer-by-layer
headset = new Bitmap(40, 40);
using (var g = Graphics.FromImage(headset))
{
// Not all SDK's handle transparency
g.Clear(Color.Black);
Profile.DrawLayers(g, renderLayers.Where(rl => rl.LayerType is HeadsetType), DataModel, smallRect,
false, true);
// Trace debugging
if (DateTime.Now.AddSeconds(-2) <= LastTrace)
return;
LastTrace = DateTime.Now;
MainManager.Logger.Trace("Effect datamodel as JSON: \r\n{0}",
JsonConvert.SerializeObject(DataModel, Formatting.Indented));
MainManager.Logger.Trace("Effect {0} has to render {1} layers", Name, renderLayers.Count);
foreach (var renderLayer in renderLayers)
MainManager.Logger.Trace("- Layer name: {0}, layer type: {1}", renderLayer.Name,
renderLayer.LayerType);
}
// Trace debugging
if (DateTime.Now.AddSeconds(-2) <= LastTrace)
return;
LastTrace = DateTime.Now;
MainManager.Logger.Trace("Effect datamodel as JSON: \r\n{0}",
JsonConvert.SerializeObject(DataModel, Formatting.Indented));
MainManager.Logger.Trace("Effect {0} has to render {1} layers", Name, renderLayers.Count);
foreach (var renderLayer in renderLayers)
MainManager.Logger.Trace("- Layer name: {0}, layer type: {1}", renderLayer.Name, renderLayer.LayerType);
}
public abstract List<LayerModel> GetRenderLayers(bool renderMice, bool renderHeadsets);
public abstract List<LayerModel> GetRenderLayers(bool keyboardOnly);
}
}

View File

@ -1,5 +1,4 @@
using System.Drawing;
using Artemis.Managers;
using Artemis.Managers;
namespace Artemis.Models
{
@ -28,7 +27,6 @@ namespace Artemis.Models
}
}
public abstract void RenderOverlay(Bitmap keyboard, ref Bitmap mouse, ref Bitmap headset, bool renderMice,
bool renderHeadsets);
public abstract void RenderOverlay(RenderFrame frame, bool keyboardOnly);
}
}

View File

@ -1,28 +1,23 @@
namespace Artemis.Modules.Effects.AudioVisualizer {
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 {
public AudioVisualization() {
// // To add event handlers for saving and changing settings, uncomment the lines below:
//
// this.SettingChanging += this.SettingChangingEventHandler;
//
// this.SettingsSaving += this.SettingsSavingEventHandler;
//
}
private void SettingChangingEventHandler(object sender, System.Configuration.SettingChangingEventArgs e) {
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, System.ComponentModel.CancelEventArgs e) {
private void SettingsSavingEventHandler(object sender, CancelEventArgs e)
{
// Add code to handle the SettingsSaving event here.
}
}
}
}

View File

@ -182,24 +182,20 @@ namespace Artemis.Modules.Effects.AudioVisualizer
}
}
public override List<LayerModel> GetRenderLayers(bool renderMice, bool renderHeadsets)
public override List<LayerModel> GetRenderLayers(bool keyboardOnly)
{
return null;
}
public override void Render(Bitmap keyboard, out Bitmap mouse, out Bitmap headset, bool renderMice,
bool renderHeadsets)
public override void Render(RenderFrame frame, bool keyboardOnly)
{
mouse = null;
headset = null;
if (SpectrumData == null || SoundRectangles == null)
return;
// Lock the _spectrumData array while busy with it
_generating = true;
using (var g = Graphics.FromImage(keyboard))
using (var g = Graphics.FromImage(frame.KeyboardBitmap))
{
foreach (var soundRectangle in SoundRectangles)
soundRectangle.Draw(g);

View File

@ -1,28 +1,23 @@
namespace Artemis.Modules.Effects.Bubbles {
using System.ComponentModel;
using System.Configuration;
namespace Artemis.Modules.Effects.Bubbles
{
// 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 Bubbles {
public Bubbles() {
// // To add event handlers for saving and changing settings, uncomment the lines below:
//
// this.SettingChanging += this.SettingChangingEventHandler;
//
// this.SettingsSaving += this.SettingsSavingEventHandler;
//
}
private void SettingChangingEventHandler(object sender, System.Configuration.SettingChangingEventArgs e) {
internal sealed partial class Bubbles
{
private void SettingChangingEventHandler(object sender, SettingChangingEventArgs e)
{
// Add code to handle the SettingChangingEvent event here.
}
private void SettingsSavingEventHandler(object sender, System.ComponentModel.CancelEventArgs e) {
private void SettingsSavingEventHandler(object sender, CancelEventArgs e)
{
// Add code to handle the SettingsSaving event here.
}
}
}
}

View File

@ -88,20 +88,16 @@ namespace Artemis.Modules.Effects.Bubbles
}
}
public override void Render(Bitmap keyboard, out Bitmap mouse, out Bitmap headset, bool renderMice,
bool renderHeadsets)
public override void Render(RenderFrame frame, bool keyboardOnly)
{
mouse = null;
headset = null;
using (var g = Graphics.FromImage(keyboard))
using (var g = Graphics.FromImage(frame.KeyboardBitmap))
{
foreach (var bubble in _bubbles)
bubble.Draw(g);
}
}
public override List<LayerModel> GetRenderLayers(bool renderMice, bool renderHeadsets)
public override List<LayerModel> GetRenderLayers(bool keyboardOnly)
{
return null;
}

View File

@ -5,9 +5,8 @@ using System.Windows;
using Artemis.Managers;
using Artemis.Models;
using Artemis.Models.Interfaces;
using Artemis.Profiles.Layers.Interfaces;
using Artemis.Profiles.Layers.Models;
using Artemis.Profiles.Layers.Types.Headset;
using Artemis.Profiles.Layers.Types.Mouse;
namespace Artemis.Modules.Effects.ProfilePreview
{
@ -32,47 +31,50 @@ namespace Artemis.Modules.Effects.ProfilePreview
{
}
public override List<LayerModel> GetRenderLayers(bool renderMice, bool renderHeadsets)
public override List<LayerModel> GetRenderLayers(bool keyboardOnly)
{
return Profile.GetRenderLayers(DataModel, renderMice, renderHeadsets, true);
return Profile.GetRenderLayers(DataModel, keyboardOnly, true);
}
public override void Render(Bitmap keyboard, out Bitmap mouse, out Bitmap headset, bool renderMice,
bool renderHeadsets)
public override void Render(RenderFrame frame, bool keyboardOnly)
{
mouse = null;
headset = null;
if (Profile == null || DataModel == null)
if (Profile == null || DataModel == null || MainManager.DeviceManager.ActiveKeyboard == null)
return;
// Get all enabled layers who's conditions are met
var renderLayers = GetRenderLayers(renderMice, renderHeadsets);
// Render the keyboard layer-by-layer
var keyboardRect = MainManager.DeviceManager.ActiveKeyboard.KeyboardRectangle(KeyboardScale);
using (var g = Graphics.FromImage(keyboard))
lock (DataModel)
{
// Fill the bitmap's background with black to avoid trailing colors on some keyboards
g.Clear(Color.Black);
Profile.DrawLayers(g, renderLayers.Where(rl => rl.MustDraw()), DataModel, keyboardRect, true, true);
}
// Get all enabled layers who's conditions are met
var renderLayers = GetRenderLayers(keyboardOnly);
// Render the mouse layer-by-layer
var smallRect = new Rect(0, 0, 40, 40);
mouse = new Bitmap(40, 40);
using (var g = Graphics.FromImage(mouse))
{
Profile.DrawLayers(g, renderLayers.Where(rl => rl.LayerType is MouseType), DataModel, smallRect,
true, true);
}
// Render the headset layer-by-layer
headset = new Bitmap(40, 40);
using (var g = Graphics.FromImage(headset))
{
Profile.DrawLayers(g, renderLayers.Where(rl => rl.LayerType is HeadsetType), DataModel, smallRect,
true, true);
// Render the keyboard layer-by-layer
var keyboardRect = MainManager.DeviceManager.ActiveKeyboard.KeyboardRectangle(KeyboardScale);
using (var g = Graphics.FromImage(frame.KeyboardBitmap))
{
Profile.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Keyboard),
DataModel,
keyboardRect, true, true);
}
// Render mice layer-by-layer
var devRec = new Rect(0, 0, 40, 40);
using (var g = Graphics.FromImage(frame.MouseBitmap))
{
Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Mouse), DataModel,
devRec, true, true);
}
// Render headsets layer-by-layer
using (var g = Graphics.FromImage(frame.HeadsetBitmap))
{
Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Headset),
DataModel,
devRec, true, true);
}
// Render generic devices layer-by-layer
using (var g = Graphics.FromImage(frame.GenericBitmap))
{
Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Generic),
DataModel,
devRec, true, true);
}
}
}
}

View File

@ -3,7 +3,6 @@ using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Windows.Forms;
using Artemis.DeviceProviders.Corsair;
using Artemis.DeviceProviders.Logitech.Utilities;
using Artemis.Managers;
using Artemis.Models;
@ -89,17 +88,13 @@ namespace Artemis.Modules.Effects.TypeWave
}
}
public override List<LayerModel> GetRenderLayers(bool renderMice, bool renderHeadsets)
public override List<LayerModel> GetRenderLayers(bool keyboardOnly)
{
return null;
}
public override void Render(Bitmap keyboard, out Bitmap mouse, out Bitmap headset, bool renderMice,
bool renderHeadsets)
public override void Render(RenderFrame frame, bool keyboardOnly)
{
mouse = null;
headset = null;
if (_waves.Count == 0)
return;
@ -113,19 +108,13 @@ namespace Artemis.Modules.Effects.TypeWave
path.AddEllipse(_waves[i].Point.X - _waves[i].Size/2, _waves[i].Point.Y - _waves[i].Size/2,
_waves[i].Size, _waves[i].Size);
Color fillColor;
if (MainManager.DeviceManager.ActiveKeyboard is CorsairRGB)
fillColor = Color.Black;
else
fillColor = Color.Transparent;
var pthGrBrush = new PathGradientBrush(path)
{
SurroundColors = new[] {_waves[i].Color},
CenterColor = fillColor
CenterColor = Color.Transparent
};
using (var g = Graphics.FromImage(keyboard))
using (var g = Graphics.FromImage(frame.KeyboardBitmap))
{
g.FillPath(pthGrBrush, path);
pthGrBrush.FocusScales = new PointF(0.3f, 0.8f);

View File

@ -24,7 +24,6 @@ namespace Artemis.Modules.Effects.WindowsProfile
public int Hours12 { get; set; }
public int Minutes { get; set; }
public int Seconds { get; set; }
}
public class CpuDataModel

View File

@ -60,7 +60,6 @@ namespace Artemis.Modules.Effects.WindowsProfile
}
public class WindowsProfileModel : EffectModel
{
private readonly ILogger _logger;
@ -101,6 +100,19 @@ namespace Artemis.Modules.Effects.WindowsProfile
UpdateDay(dataModel);
}
#region Current Time
private void UpdateDay(WindowsProfileDataModel dataModel)
{
var now = DateTime.Now;
dataModel.CurrentTime.Hours24 = int.Parse(now.ToString("HH"));
dataModel.CurrentTime.Hours12 = int.Parse(now.ToString("hh"));
dataModel.CurrentTime.Minutes = int.Parse(now.ToString("mm"));
dataModel.CurrentTime.Seconds = int.Parse(now.ToString("ss"));
}
#endregion
#region CPU
private void SetupCpu()
@ -163,9 +175,9 @@ namespace Artemis.Modules.Effects.WindowsProfile
dataModel.Performance.RAMUsage = (int) percentOccupied;
}
public override List<LayerModel> GetRenderLayers(bool renderMice, bool renderHeadsets)
public override List<LayerModel> GetRenderLayers(bool keyboardOnly)
{
return Profile.GetRenderLayers(DataModel, renderMice, renderHeadsets, false);
return Profile.GetRenderLayers(DataModel, keyboardOnly, false);
}
public static PerformanceCounter GetOverallPerformanceCounter()
@ -194,19 +206,6 @@ namespace Artemis.Modules.Effects.WindowsProfile
#endregion
#region Current Time
private void UpdateDay(WindowsProfileDataModel dataModel)
{
var now = DateTime.Now;
dataModel.CurrentTime.Hours24 = int.Parse(now.ToString("HH"));
dataModel.CurrentTime.Hours12 = int.Parse(now.ToString("hh"));
dataModel.CurrentTime.Minutes = int.Parse(now.ToString("mm"));
dataModel.CurrentTime.Seconds = int.Parse(now.ToString("ss"));
}
#endregion
#region Spotify
public void SetupSpotify()

View File

@ -57,13 +57,13 @@ namespace Artemis.Modules.Effects.WindowsProfile
protected override void OnActivate()
{
base.OnActivate();
ProfileEditor.ProfileViewModel.Activate();
ProfileEditor.Activate();
}
protected override void OnDeactivate(bool close)
{
base.OnDeactivate(close);
ProfileEditor.ProfileViewModel.Deactivate();
ProfileEditor.Deactivate();
}
}
}

View File

@ -1,5 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="Artemis.Modules.Games.CounterStrike" GeneratedClassName="CounterStrike">
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)"
GeneratedClassNamespace="Artemis.Modules.Games.CounterStrike" GeneratedClassName="CounterStrike">
<Profiles />
<Settings>
<Setting Name="Enabled" Type="System.Boolean" Scope="User">

View File

@ -64,9 +64,9 @@ namespace Artemis.Modules.Games.CounterStrike
}
}
public override List<LayerModel> GetRenderLayers(bool renderMice, bool renderHeadsets)
public override List<LayerModel> GetRenderLayers(bool keyboardOnly)
{
return Profile.GetRenderLayers(DataModel, renderMice, renderHeadsets);
return Profile.GetRenderLayers(DataModel, keyboardOnly);
}
}
}

View File

@ -1,5 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="Artemis.Modules.Games.Dota2" GeneratedClassName="Dota2">
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)"
GeneratedClassNamespace="Artemis.Modules.Games.Dota2" GeneratedClassName="Dota2">
<Profiles />
<Settings>
<Setting Name="Enabled" Type="System.Boolean" Scope="User">

View File

@ -64,9 +64,9 @@ namespace Artemis.Modules.Games.Dota2
DataModel = JsonConvert.DeserializeObject<Dota2DataModel>(jsonString);
}
public override List<LayerModel> GetRenderLayers(bool renderMice, bool renderHeadsets)
public override List<LayerModel> GetRenderLayers(bool keyboardOnly)
{
return Profile.GetRenderLayers(DataModel, renderMice, renderHeadsets);
return Profile.GetRenderLayers(DataModel, keyboardOnly);
}
}
}

View File

@ -115,8 +115,6 @@ namespace Artemis.Modules.Games.Overwatch
return;
_events.PublishOnUIThread(new RazerColorArrayChanged(colors));
//MainManager.Logger.Trace("DataModel: \r\n{0}",
// JsonConvert.SerializeObject(gameDataModel, Formatting.Indented));
// Determine general game state
ParseGameSate(gameDataModel, colors);
@ -222,9 +220,9 @@ namespace Artemis.Modules.Games.Overwatch
gameDataModel.Ability2Ready = colors[2, 4].Equals(Color.FromRgb(4, 141, 144));
}
public override List<LayerModel> GetRenderLayers(bool renderMice, bool renderHeadsets)
public override List<LayerModel> GetRenderLayers(bool keyboardOnly)
{
return Profile.GetRenderLayers(DataModel, renderMice, renderHeadsets);
return Profile.GetRenderLayers(DataModel, keyboardOnly);
}
}

View File

@ -24,6 +24,23 @@ namespace Artemis.Modules.Games.RocketLeague
Scale = 4;
Enabled = Settings.Enabled;
Initialized = false;
// Generate a new offset when the game is updated
//var offset = new GamePointersCollection
//{
// Game = "RocketLeague",
// GameVersion = "1.21",
// GameAddresses = new List<GamePointer>
// {
// new GamePointer
// {
// Description = "Boost",
// BasePointer = new IntPtr(0x016AD528),
// Offsets = new[] {0x304, 0x8, 0x50, 0x720, 0x224}
// }
// }
//};
//var res = JsonConvert.SerializeObject(offset, Formatting.Indented);
}
public int Scale { get; set; }
@ -57,15 +74,13 @@ namespace Artemis.Modules.Games.RocketLeague
var offsets = _pointer.GameAddresses.First(ga => ga.Description == "Boost").ToString();
var boostAddress = _memory.GetAddress("\"RocketLeague.exe\"" + offsets);
var boostFloat = _memory.ReadFloat(boostAddress)*100/3;
var boostInt = (int) (_memory.ReadFloat(boostAddress)*100);
if (boostInt > 100)
boostInt = 100;
if (boostInt < 0)
boostInt = 0;
((RocketLeagueDataModel) DataModel).Boost = (int) Math.Ceiling(boostFloat);
// Take care of any reading errors resulting in an OutOfMemory on draw
if (((RocketLeagueDataModel) DataModel).Boost < 0)
((RocketLeagueDataModel) DataModel).Boost = 0;
if (((RocketLeagueDataModel) DataModel).Boost > 100)
((RocketLeagueDataModel) DataModel).Boost = 100;
((RocketLeagueDataModel) DataModel).Boost = boostInt;
if (DateTime.Now.AddSeconds(-2) <= LastTrace)
return;
@ -74,12 +89,12 @@ namespace Artemis.Modules.Games.RocketLeague
JsonConvert.SerializeObject(_pointer.GameAddresses, Formatting.Indented));
MainManager.Logger.Trace("RL specific offsets: {0}", offsets);
MainManager.Logger.Trace("Boost address: {0}", boostAddress);
MainManager.Logger.Trace("Boost float: {0}", boostFloat);
MainManager.Logger.Trace("Boost int: {0}", boostInt);
}
public override List<LayerModel> GetRenderLayers(bool renderMice, bool renderHeadsets)
public override List<LayerModel> GetRenderLayers(bool keyboardOnly)
{
return Profile.GetRenderLayers(DataModel, renderMice, renderHeadsets);
return Profile.GetRenderLayers(DataModel, keyboardOnly);
}
}
}

View File

@ -129,9 +129,9 @@ namespace Artemis.Modules.Games.TheDivision
// DataModel updating is done whenever a pipe message is received
}
public override List<LayerModel> GetRenderLayers(bool renderMice, bool renderHeadsets)
public override List<LayerModel> GetRenderLayers(bool keyboardOnly)
{
return Profile.GetRenderLayers(DataModel, renderMice, renderHeadsets);
return Profile.GetRenderLayers(DataModel, keyboardOnly);
}
}
}

View File

@ -136,9 +136,9 @@ namespace Artemis.Modules.Games.Witcher3
}
}
public override List<LayerModel> GetRenderLayers(bool renderMice, bool renderHeadsets)
public override List<LayerModel> GetRenderLayers(bool keyboardOnly)
{
return Profile.GetRenderLayers(DataModel, renderMice, renderHeadsets);
return Profile.GetRenderLayers(DataModel, keyboardOnly);
}
}
}

View File

@ -63,7 +63,7 @@ namespace Artemis.Modules.Overlays.VolumeDisplay
}
}
public override List<LayerModel> GetRenderLayers(bool renderMice, bool renderHeadsets)
public override List<LayerModel> GetRenderLayers(bool keyboardOnly)
{
return null;
}
@ -77,13 +77,12 @@ namespace Artemis.Modules.Overlays.VolumeDisplay
VolumeDisplay.Transparancy = 255;
}
public override void RenderOverlay(Bitmap keyboard, ref Bitmap mouse, ref Bitmap headset, bool renderMice,
bool renderHeadsets)
public override void RenderOverlay(RenderFrame frame, bool keyboardOnly)
{
if (MainManager.DeviceManager.ActiveKeyboard == null || VolumeDisplay == null || VolumeDisplay.Ttl < 1)
return;
using (var g = Graphics.FromImage(keyboard))
using (var g = Graphics.FromImage(frame.KeyboardBitmap))
{
VolumeDisplay.Draw(g);
}

View File

@ -1,15 +1,14 @@
using System.Drawing;
using System.Windows.Media;
using Artemis.Models.Interfaces;
using Artemis.Profiles.Layers.Models;
using Caliburn.Micro;
using Brush = System.Windows.Media.Brush;
namespace Artemis.ViewModels.Profiles.Layers
namespace Artemis.Profiles.Layers.Abstract
{
public abstract class LayerPropertiesViewModel : PropertyChangedBase
{
private LayerModel _layerModel;
private Brush _brush;
private LayerModel _layerModel;
protected LayerPropertiesViewModel(LayerModel layerModel, IDataModel dataModel)
{

View File

@ -33,7 +33,7 @@ namespace Artemis.Profiles.Layers.Animations
: new Rect(props.X*scale, props.Y*scale, props.Width*scale, props.Height*scale);
var s1 = new Rect(new Point(rect.X, rect.Y + props.AnimationProgress), new Size(rect.Width, rect.Height));
var s2 = new Rect(new Point(s1.X, s1.Y - rect.Height), new Size(rect.Width, rect.Height));
var s2 = new Rect(new Point(s1.X, s1.Y - rect.Height), new Size(rect.Width, rect.Height + .5));
var clip = new Rect(applied.X*scale, applied.Y*scale, applied.Width*scale, applied.Height*scale);

View File

@ -33,7 +33,7 @@ namespace Artemis.Profiles.Layers.Animations
: new Rect(props.X*scale, props.Y*scale, props.Width*scale, props.Height*scale);
var s1 = new Rect(new Point(rect.X - props.AnimationProgress, rect.Y),
new Size(rect.Width + 0.05, rect.Height));
new Size(rect.Width + .5, rect.Height));
var s2 = new Rect(new Point(s1.X + rect.Width, rect.Y), new Size(rect.Width, rect.Height));
var clip = new Rect(applied.X*scale, applied.Y*scale, applied.Width*scale, applied.Height*scale);

View File

@ -33,7 +33,7 @@ namespace Artemis.Profiles.Layers.Animations
: new Rect(props.X*scale, props.Y*scale, props.Width*scale, props.Height*scale);
var s1 = new Rect(new Point(rect.X + props.AnimationProgress, rect.Y), new Size(rect.Width, rect.Height));
var s2 = new Rect(new Point(s1.X - rect.Width, rect.Y), new Size(rect.Width + 1, rect.Height));
var s2 = new Rect(new Point(s1.X - rect.Width, rect.Y), new Size(rect.Width + .5, rect.Height));
var clip = new Rect(applied.X*scale, applied.Y*scale, applied.Width*scale, applied.Height*scale);

View File

@ -32,7 +32,8 @@ namespace Artemis.Profiles.Layers.Animations
? new Rect(applied.X*scale, applied.Y*scale, applied.Width*scale, applied.Height*scale)
: new Rect(props.X*scale, props.Y*scale, props.Width*scale, props.Height*scale);
var s1 = new Rect(new Point(rect.X, rect.Y - props.AnimationProgress), new Size(rect.Width, rect.Height));
var s1 = new Rect(new Point(rect.X, rect.Y - props.AnimationProgress),
new Size(rect.Width, rect.Height + .5));
var s2 = new Rect(new Point(s1.X, s1.Y + rect.Height), new Size(rect.Width, rect.Height));
var clip = new Rect(applied.X*scale, applied.Y*scale, applied.Width*scale, applied.Height*scale);

View File

@ -1,10 +1,12 @@
using System.Windows.Media;
using Artemis.Profiles.Layers.Models;
using Newtonsoft.Json;
namespace Artemis.Profiles.Layers.Interfaces
{
public interface ILayerAnimation
{
[JsonIgnore]
string Name { get; }
void Update(LayerModel layerModel, bool updateAnimations);
void Draw(LayerPropertiesModel props, LayerPropertiesModel applied, DrawingContext c);

View File

@ -1,8 +1,9 @@
using System.Collections.Generic;
using System.Windows.Media;
using Artemis.Models.Interfaces;
using Artemis.Profiles.Layers.Abstract;
using Artemis.Profiles.Layers.Models;
using Artemis.ViewModels.Profiles.Layers;
using Newtonsoft.Json;
namespace Artemis.Profiles.Layers.Interfaces
{
@ -11,12 +12,21 @@ namespace Artemis.Profiles.Layers.Interfaces
/// <summary>
/// Layer type name
/// </summary>
[JsonIgnore]
string Name { get; }
/// <summary>
/// Gets whether this type must be drawn on the keyboard/the editor or not
/// Gets whether this type must be drawn in the editor or not. Setting this to true
/// enables moving and resizing the layer
/// </summary>
bool MustDraw { get; }
[JsonIgnore]
bool ShowInEdtor { get; }
/// <summary>
/// Gets for what kind of device this layer should be drawn.
/// </summary>
[JsonIgnore]
DrawType DrawType { get; }
/// <summary>
/// The the thumbnail for this layer type
@ -52,6 +62,16 @@ namespace Artemis.Profiles.Layers.Interfaces
/// <param name="layerAnimations"></param>
/// <param name="dataModel">The datamodel to use in the new viewmodel</param>
/// <param name="proposedLayer">The layer to use in the new viewmodel</param>
LayerPropertiesViewModel SetupViewModel(LayerPropertiesViewModel layerPropertiesViewModel, List<ILayerAnimation> layerAnimations, IDataModel dataModel, LayerModel proposedLayer);
LayerPropertiesViewModel SetupViewModel(LayerPropertiesViewModel layerPropertiesViewModel,
List<ILayerAnimation> layerAnimations, IDataModel dataModel, LayerModel proposedLayer);
}
public enum DrawType
{
None,
Keyboard,
Mouse,
Headset,
Generic
}
}

View File

@ -3,11 +3,10 @@ using System.Collections.Generic;
using System.Linq;
using System.Windows.Media;
using Artemis.Models.Interfaces;
using Artemis.Profiles.Layers.Animations;
using Artemis.Profiles.Layers.Conditions;
using Artemis.Profiles.Layers.Interfaces;
using Artemis.Profiles.Layers.Types.Headset;
using Artemis.Profiles.Layers.Types.Keyboard;
using Artemis.Profiles.Layers.Types.Mouse;
using Artemis.Utilities;
using Artemis.Utilities.ParentChild;
using Newtonsoft.Json;
@ -114,7 +113,7 @@ namespace Artemis.Profiles.Layers.Models
return false;
parent = parent.Parent;
}
return Enabled && LayerType.MustDraw;
return Enabled && LayerType.ShowInEdtor;
}
/// <summary>
@ -146,6 +145,7 @@ namespace Artemis.Profiles.Layers.Models
Order = -1,
LayerType = new KeyboardType(),
LayerCondition = new DataModelCondition(),
LayerAnimation = new NoneAnimation(),
Properties = new KeyboardPropertiesModel
{
Brush = new SolidColorBrush(ColorHelpers.GetRandomRainbowMediaColor()),
@ -192,49 +192,31 @@ namespace Artemis.Profiles.Layers.Models
}
}
public void Replace(LayerModel layer)
{
layer.Order = Order;
layer.Parent = null;
layer.Profile = null;
if (Parent != null)
{
Parent.Children.Add(layer);
Parent.Children.Remove(this);
}
else if (Profile != null)
{
Profile.Layers.Add(layer);
Profile.Layers.Remove(this);
}
}
/// <summary>
/// Generates a flat list containing all layers that must be rendered on the keyboard,
/// the first mouse layer to be rendered and the first headset layer to be rendered
/// </summary>
/// <typeparam name="T">The game data model to base the conditions on</typeparam>
/// <param name="dataModel">Instance of said game data model</param>
/// <param name="includeMice">Whether or not to include mice in the list</param>
/// <param name="includeHeadsets">Whether or not to include headsets in the list</param>
/// <param name="keyboardOnly">Whether or not to ignore anything but keyboards</param>
/// <param name="ignoreConditions"></param>
/// <returns>A flat list containing all layers that must be rendered</returns>
public List<LayerModel> GetRenderLayers(IDataModel dataModel, bool includeMice, bool includeHeadsets,
bool ignoreConditions = false)
public List<LayerModel> GetRenderLayers(IDataModel dataModel, bool keyboardOnly, bool ignoreConditions = false)
{
var layers = new List<LayerModel>();
foreach (var layerModel in Children.OrderByDescending(c => c.Order))
foreach (var layerModel in Children.OrderByDescending(l => l.Order))
{
if (!layerModel.Enabled || !includeMice && layerModel.LayerType is MouseType ||
!includeHeadsets && layerModel.LayerType is HeadsetType)
if (!layerModel.Enabled || keyboardOnly && layerModel.LayerType.DrawType != DrawType.Keyboard)
continue;
if (!ignoreConditions && !layerModel.ConditionsMet(dataModel))
continue;
if (!ignoreConditions)
{
if (!layerModel.ConditionsMet(dataModel))
continue;
}
layers.Add(layerModel);
layers.AddRange(layerModel.GetRenderLayers(dataModel, includeMice, includeHeadsets, ignoreConditions));
layers.AddRange(layerModel.GetRenderLayers(dataModel, keyboardOnly, ignoreConditions));
}
return layers;

View File

@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media;
using Artemis.Utilities.Converters;
using Newtonsoft.Json;
@ -7,6 +8,8 @@ namespace Artemis.Profiles.Layers.Models
{
public abstract class LayerPropertiesModel
{
private Brush _brush;
public LayerPropertiesModel(LayerPropertiesModel source = null)
{
if (source == null)
@ -25,8 +28,6 @@ namespace Artemis.Profiles.Layers.Models
Brush = source.Brush;
}
private Brush _brush;
public double X { get; set; }
public double Y { get; set; }
public double Width { get; set; }
@ -38,7 +39,6 @@ namespace Artemis.Profiles.Layers.Models
public List<DynamicPropertiesModel> DynamicProperties { get; set; } = new List<DynamicPropertiesModel>();
[JsonIgnore]
public double AnimationProgress { get; set; }
[JsonConverter(typeof(BrushJsonConverter))]
@ -65,5 +65,10 @@ namespace Artemis.Profiles.Layers.Models
_brush = cloned;
}
}
public Rect GetRect(int scale = 4)
{
return new Rect(X * scale, Y * scale, Width * scale, Height * scale);
}
}
}

View File

@ -1,4 +1,4 @@
<UserControl x:Class="Artemis.Views.Profiles.Layers.FolderPropertiesView"
<UserControl x:Class="Artemis.Profiles.Layers.Types.Folder.FolderPropertiesView"
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"

View File

@ -1,6 +1,6 @@
using System.Windows.Controls;
namespace Artemis.Views.Profiles.Layers
namespace Artemis.Profiles.Layers.Types.Folder
{
/// <summary>
/// Interaction logic for FolderPropertiesView.xaml

View File

@ -1,7 +1,8 @@
using Artemis.Models.Interfaces;
using Artemis.Profiles.Layers.Abstract;
using Artemis.Profiles.Layers.Models;
namespace Artemis.ViewModels.Profiles.Layers
namespace Artemis.Profiles.Layers.Types.Folder
{
public class FolderPropertiesViewModel : LayerPropertiesViewModel
{

View File

@ -2,18 +2,20 @@
using System.Windows;
using System.Windows.Media;
using Artemis.Models.Interfaces;
using Artemis.Profiles.Layers.Abstract;
using Artemis.Profiles.Layers.Interfaces;
using Artemis.Profiles.Layers.Models;
using Artemis.Properties;
using Artemis.Utilities;
using Artemis.ViewModels.Profiles.Layers;
namespace Artemis.Profiles.Layers.Types.Folder
{
public class FolderType : ILayerType
{
public string Name { get; } = "Folder";
public bool MustDraw { get; } = false;
public bool ShowInEdtor { get; } = false;
// FolderType pretents to be a keyboard so it's children get drawn
public DrawType DrawType { get; } = DrawType.Keyboard;
public ImageSource DrawThumbnail(LayerModel layer)
{

View File

@ -0,0 +1,76 @@
<UserControl x:Class="Artemis.Profiles.Layers.Types.Generic.GenericPropertiesView"
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="600" d:DesignWidth="500">
<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}"
VerticalAlignment="Top" Height="Auto" TextWrapping="Wrap">
<Run Text="Note: Generic devices are devices over which Artemis has limited control." /><LineBreak />
<Run /><LineBreak />
<Run Text="You can use this layer type to assign a color to all generic devices at once." /><LineBreak />
<Run
Text="Should your generic device have multiple LEDs, Artemis will try to take the colors from the Brush and spread them over the LEDs." />
<LineBreak /><Run /><LineBreak /><Run Text="Examples of supported generic devices:" /><LineBreak />
<Run Text="- Logitech mice and headsets" /><LineBreak /><Run Text="- Logitech G19" /><LineBreak />
<Run Text="- Logitech G510" /><LineBreak /><Run />
</TextBlock>
</Grid>
</UserControl>

View File

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

View File

@ -0,0 +1,50 @@
using System.Collections.Generic;
using System.Linq;
using Artemis.Models.Interfaces;
using Artemis.Profiles.Layers.Abstract;
using Artemis.Profiles.Layers.Interfaces;
using Artemis.Profiles.Layers.Models;
using Artemis.Utilities;
using Artemis.ViewModels.Profiles;
using Caliburn.Micro;
namespace Artemis.Profiles.Layers.Types.Generic
{
public class GenericPropertiesViewModel : LayerPropertiesViewModel
{
private ILayerAnimation _selectedLayerAnimation;
public GenericPropertiesViewModel(LayerModel layerModel, IDataModel dataModel,
IEnumerable<ILayerAnimation> layerAnimations) : base(layerModel, dataModel)
{
LayerAnimations = new BindableCollection<ILayerAnimation>(layerAnimations);
OpacityProperties = new LayerDynamicPropertiesViewModel("Opacity",
new BindableCollection<GeneralHelpers.PropertyCollection>(GeneralHelpers.GenerateTypeMap(dataModel)),
layerModel.Properties);
SelectedLayerAnimation = LayerAnimations.FirstOrDefault(l => l.Name == layerModel.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,96 @@
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;
namespace Artemis.Profiles.Layers.Types.Generic
{
public class GenericType : ILayerType
{
public string Name { get; } = "Generic (Logitech)";
public bool ShowInEdtor { get; } = false;
public DrawType DrawType { get; } = DrawType.Generic;
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.generic), 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)
{
// Generic 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(LayerPropertiesViewModel layerPropertiesViewModel,
List<ILayerAnimation> layerAnimations, IDataModel dataModel, LayerModel proposedLayer)
{
if (layerPropertiesViewModel is GenericPropertiesViewModel)
return layerPropertiesViewModel;
return new GenericPropertiesViewModel(proposedLayer, dataModel, layerAnimations);
}
}
}

View File

@ -0,0 +1,68 @@
<UserControl x:Class="Artemis.Profiles.Layers.Types.Headset.HeadsetPropertiesView"
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 headset 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

@ -1,6 +1,6 @@
using System.Windows.Controls;
namespace Artemis.Views.Profiles.Layers
namespace Artemis.Profiles.Layers.Types.Headset
{
/// <summary>
/// Interaction logic for HeadsetPropertiesView.xaml

View File

@ -1,11 +1,14 @@
using System.Collections.Generic;
using System.Linq;
using Artemis.Models.Interfaces;
using Artemis.Profiles.Layers.Abstract;
using Artemis.Profiles.Layers.Interfaces;
using Artemis.Profiles.Layers.Models;
using Artemis.Utilities;
using Artemis.ViewModels.Profiles;
using Caliburn.Micro;
namespace Artemis.ViewModels.Profiles.Layers
namespace Artemis.Profiles.Layers.Types.Headset
{
public class HeadsetPropertiesViewModel : LayerPropertiesViewModel
{
@ -18,6 +21,9 @@ namespace Artemis.ViewModels.Profiles.Layers
OpacityProperties = new LayerDynamicPropertiesViewModel("Opacity",
new BindableCollection<GeneralHelpers.PropertyCollection>(GeneralHelpers.GenerateTypeMap(dataModel)),
layerModel.Properties);
SelectedLayerAnimation = LayerAnimations.FirstOrDefault(l => l.Name == layerModel.LayerAnimation?.Name) ??
LayerAnimations.First(l => l.Name == "None");
}
public BindableCollection<ILayerAnimation> LayerAnimations { get; set; }

View File

@ -1,21 +1,22 @@
using System;
using System.Collections.Generic;
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.Layers;
namespace Artemis.Profiles.Layers.Types.Headset
{
public class HeadsetType : ILayerType
{
public string Name { get; } = "Headset";
public bool MustDraw { get; } = false;
public bool ShowInEdtor { get; } = false;
public DrawType DrawType { get; } = DrawType.Headset;
public ImageSource DrawThumbnail(LayerModel layer)
{
@ -38,10 +39,10 @@ namespace Artemis.Profiles.Layers.Types.Headset
}
// 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);
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);
@ -63,7 +64,7 @@ namespace Artemis.Profiles.Layers.Types.Headset
return;
// If not previewing, apply dynamic properties according to datamodel
var props = (SimplePropertiesModel)layerModel.AppliedProperties;
var props = (SimplePropertiesModel) layerModel.AppliedProperties;
foreach (var dynamicProperty in props.DynamicProperties)
dynamicProperty.ApplyProperty(dataModel, layerModel.AppliedProperties);
}
@ -74,6 +75,12 @@ namespace Artemis.Profiles.Layers.Types.Headset
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(LayerPropertiesViewModel layerPropertiesViewModel,

View File

@ -1,5 +1,4 @@
using System.Windows;
using Artemis.Profiles.Layers.Models;
using Artemis.Profiles.Layers.Models;
namespace Artemis.Profiles.Layers.Types.Keyboard
{
@ -10,10 +9,5 @@ namespace Artemis.Profiles.Layers.Types.Keyboard
}
public string GifFile { get; set; }
public Rect GetRect(int scale = 4)
{
return new Rect(X*scale, Y*scale, Width*scale, Height*scale);
}
}
}

View File

@ -1,4 +1,4 @@
<UserControl x:Class="Artemis.Views.Profiles.Layers.KeyboardPropertiesView"
<UserControl x:Class="Artemis.Profiles.Layers.Types.Keyboard.KeyboardPropertiesView"
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"
@ -28,10 +28,11 @@
<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 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}"/>
<TextBlock Text="{Binding Path=Name, Mode=OneWay}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>

View File

@ -1,6 +1,6 @@
using System.Windows.Controls;
namespace Artemis.Views.Profiles.Layers
namespace Artemis.Profiles.Layers.Types.Keyboard
{
/// <summary>
/// Interaction logic for KeyboardPropertiesView.xaml

View File

@ -2,13 +2,14 @@
using System.Linq;
using System.Windows.Forms;
using Artemis.Models.Interfaces;
using Artemis.Profiles.Layers.Abstract;
using Artemis.Profiles.Layers.Interfaces;
using Artemis.Profiles.Layers.Models;
using Artemis.Profiles.Layers.Types.Keyboard;
using Artemis.Utilities;
using Artemis.ViewModels.Profiles;
using Caliburn.Micro;
using static Artemis.Utilities.GeneralHelpers;
namespace Artemis.ViewModels.Profiles.Layers
namespace Artemis.Profiles.Layers.Types.Keyboard
{
public class KeyboardPropertiesViewModel : LayerPropertiesViewModel
{
@ -20,7 +21,8 @@ namespace Artemis.ViewModels.Profiles.Layers
{
LayerAnimations = new BindableCollection<ILayerAnimation>(layerAnimations);
var dataModelProps = new BindableCollection<PropertyCollection>(GenerateTypeMap(dataModel));
var dataModelProps =
new BindableCollection<GeneralHelpers.PropertyCollection>(GeneralHelpers.GenerateTypeMap(dataModel));
HeightProperties = new LayerDynamicPropertiesViewModel("Height", dataModelProps, layerModel.Properties);
WidthProperties = new LayerDynamicPropertiesViewModel("Width", dataModelProps, layerModel.Properties);
OpacityProperties = new LayerDynamicPropertiesViewModel("Opacity", dataModelProps, layerModel.Properties);
@ -31,7 +33,7 @@ namespace Artemis.ViewModels.Profiles.Layers
public bool ShowGif => IsGif;
public bool ShowBrush => !IsGif;
public BindableCollection<PropertyCollection> DataModelProps { get; set; }
public BindableCollection<GeneralHelpers.PropertyCollection> DataModelProps { get; set; }
public BindableCollection<ILayerAnimation> LayerAnimations { get; set; }
public LayerDynamicPropertiesViewModel HeightProperties { get; set; }
public LayerDynamicPropertiesViewModel WidthProperties { get; set; }

View File

@ -2,19 +2,18 @@
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.Utilities;
using Artemis.ViewModels.Profiles.Layers;
namespace Artemis.Profiles.Layers.Types.Keyboard
{
public class KeyboardType : ILayerType
{
public string Name { get; } = "Keyboard";
public bool MustDraw { get; } = true;
public bool ShowInEdtor { get; } = true;
public DrawType DrawType { get; } = DrawType.Keyboard;
public ImageSource DrawThumbnail(LayerModel layer)
{

View File

@ -4,20 +4,20 @@ using System.IO;
using System.Windows;
using System.Windows.Media;
using Artemis.Models.Interfaces;
using Artemis.Profiles.Layers.Abstract;
using Artemis.Profiles.Layers.Interfaces;
using Artemis.Profiles.Layers.Models;
using Artemis.Profiles.Layers.Types.Keyboard;
using Artemis.Properties;
using Artemis.Utilities;
using Artemis.ViewModels.Profiles.Layers;
namespace Artemis.Profiles.Layers.Types.KeyboardGif
{
internal class KeyboardGifType : ILayerType
{
public string Name { get; } = "Keyboard - GIF";
public bool MustDraw { get; } = true;
public bool ShowInEdtor { get; } = true;
public DrawType DrawType { get; } = DrawType.Keyboard;
public ImageSource DrawThumbnail(LayerModel layer)
{

View File

@ -1,4 +1,4 @@
<UserControl x:Class="Artemis.Views.Profiles.Layers.MousePropertiesView"
<UserControl x:Class="Artemis.Profiles.Layers.Types.Mouse.MousePropertiesView"
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"
@ -25,10 +25,11 @@
<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 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}"/>
<TextBlock Text="{Binding Path=Name, Mode=OneWay}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
@ -40,7 +41,7 @@
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):"

View File

@ -1,6 +1,6 @@
using System.Windows.Controls;
namespace Artemis.Views.Profiles.Layers
namespace Artemis.Profiles.Layers.Types.Mouse
{
/// <summary>
/// Interaction logic for MousePropertiesView.xaml

View File

@ -1,12 +1,14 @@
using System.Collections.Generic;
using System.Linq;
using Artemis.Models.Interfaces;
using Artemis.Profiles.Layers.Abstract;
using Artemis.Profiles.Layers.Interfaces;
using Artemis.Profiles.Layers.Models;
using Artemis.Utilities;
using Artemis.ViewModels.Profiles;
using Caliburn.Micro;
namespace Artemis.ViewModels.Profiles.Layers
namespace Artemis.Profiles.Layers.Types.Mouse
{
public class MousePropertiesViewModel : LayerPropertiesViewModel
{

View File

@ -1,29 +1,31 @@
using System;
using System.Collections.Generic;
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.Layers;
namespace Artemis.Profiles.Layers.Types.Mouse
{
public class MouseType : ILayerType
{
public string Name { get; } = "Mouse";
public bool MustDraw { get; } = false;
public bool ShowInEdtor { get; } = false;
public DrawType DrawType { get; } = DrawType.Mouse;
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.mouse), thumbnailRect);
}
var image = new DrawingImage(visual.Drawing);
return image;
@ -39,10 +41,10 @@ namespace Artemis.Profiles.Layers.Types.Mouse
}
// 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);
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);
@ -64,7 +66,7 @@ namespace Artemis.Profiles.Layers.Types.Mouse
return;
// If not previewing, apply dynamic properties according to datamodel
var props = (SimplePropertiesModel)layerModel.AppliedProperties;
var props = (SimplePropertiesModel) layerModel.AppliedProperties;
foreach (var dynamicProperty in props.DynamicProperties)
dynamicProperty.ApplyProperty(dataModel, layerModel.AppliedProperties);
}
@ -75,6 +77,12 @@ namespace Artemis.Profiles.Layers.Types.Mouse
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(LayerPropertiesViewModel layerPropertiesViewModel,

View File

@ -1,13 +1,13 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows;
using System.Windows.Media;
using Artemis.DeviceProviders;
using Artemis.Models.Interfaces;
using Artemis.Profiles.Layers.Interfaces;
using Artemis.Profiles.Layers.Models;
using Artemis.Profiles.Layers.Types.Headset;
using Artemis.Profiles.Layers.Types.Keyboard;
using Artemis.Profiles.Layers.Types.Mouse;
using Artemis.Utilities;
using Artemis.Utilities.ParentChild;
using Newtonsoft.Json;
@ -31,9 +31,10 @@ namespace Artemis.Profiles
public bool IsDefault { get; set; }
public string KeyboardSlug { get; set; }
public string GameName { get; set; }
public int Width { get; set; }
public int Height { get; set; }
[JsonIgnore]
public DrawingVisual DrawingVisual { get; set; }
public void FixOrder()
@ -88,52 +89,30 @@ namespace Artemis.Profiles
/// </summary>
/// <typeparam name="T">The game data model to base the conditions on</typeparam>
/// <param name="dataModel">Instance of said game data model</param>
/// <param name="includeMice">Whether or not to include mice in the list</param>
/// <param name="includeHeadsets">Whether or not to include headsets in the list</param>
/// <param name="keyboardOnly">Whether or not to ignore anything but keyboards</param>
/// <param name="ignoreConditions"></param>
/// <returns>A flat list containing all layers that must be rendered</returns>
public List<LayerModel> GetRenderLayers(IDataModel dataModel, bool includeMice, bool includeHeadsets,
bool ignoreConditions = false)
public List<LayerModel> GetRenderLayers(IDataModel dataModel, bool keyboardOnly, bool ignoreConditions = false)
{
var layers = new List<LayerModel>();
foreach (var layerModel in Layers.OrderByDescending(l => l.Order))
{
if (!layerModel.Enabled || !includeMice && layerModel.LayerType is MouseType ||
!includeHeadsets && layerModel.LayerType is HeadsetType)
if (!layerModel.Enabled || keyboardOnly && layerModel.LayerType.DrawType != DrawType.Keyboard)
continue;
if (!ignoreConditions && !layerModel.ConditionsMet(dataModel))
continue;
if (!ignoreConditions)
{
if (!layerModel.ConditionsMet(dataModel))
continue;
}
layers.Add(layerModel);
layers.AddRange(layerModel.GetRenderLayers(dataModel, includeMice, includeHeadsets, ignoreConditions));
layers.AddRange(layerModel.GetRenderLayers(dataModel, keyboardOnly, ignoreConditions));
}
return layers;
}
/// <summary>
/// Looks at all the layers wthin the profile and makes sure they are within boundaries of the given rectangle
/// </summary>
/// <param name="keyboardRectangle"></param>
public void FixBoundaries(Rect keyboardRectangle)
{
foreach (var layer in GetLayers())
{
if (!layer.LayerType.MustDraw)
continue;
var props = (KeyboardPropertiesModel) layer.Properties;
var layerRect = new Rect(new Point(props.X, props.Y), new Size(props.Width, props.Height));
if (keyboardRectangle.Contains(layerRect))
continue;
props.X = 0;
props.Y = 0;
layer.Properties = props;
}
}
/// <summary>
/// Draw all the given layers on the given rect
/// </summary>
@ -168,6 +147,47 @@ namespace Artemis.Profiles
g.DrawImage(bmp, new PointF(0, 0));
}
/// <summary>
/// Looks at all the layers wthin the profile and makes sure they are within boundaries of the given rectangle
/// </summary>
/// <param name="keyboardRectangle"></param>
public void FixBoundaries(Rect keyboardRectangle)
{
foreach (var layer in GetLayers())
{
if (!layer.LayerType.ShowInEdtor)
continue;
var props = layer.Properties;
var layerRect = new Rect(new Point(props.X, props.Y), new Size(props.Width, props.Height));
if (keyboardRectangle.Contains(layerRect))
continue;
props.X = 0;
props.Y = 0;
layer.Properties = props;
}
}
/// <summary>
/// Resizes layers that are shown in the editor and match exactly the full keyboard widht and height
/// </summary>
/// <param name="source">The keyboard the profile was made for</param>
/// <param name="target">The new keyboard to adjust the layers for</param>
public void ResizeLayers(KeyboardProvider target)
{
foreach (var layer in GetLayers())
{
if (!layer.LayerType.ShowInEdtor ||
!(Math.Abs(layer.Properties.Width - Width) < 0.01) ||
!(Math.Abs(layer.Properties.Height - Height) < 0.01))
continue;
layer.Properties.Width = target.Width;
layer.Properties.Height = target.Height;
}
}
#region Compare
protected bool Equals(ProfileModel other)

View File

@ -158,6 +158,16 @@ namespace Artemis.Properties {
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap g810 {
get {
object obj = ResourceManager.GetObject("g810", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
@ -168,6 +178,16 @@ namespace Artemis.Properties {
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap generic {
get {
object obj = ResourceManager.GetObject("generic", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>

View File

@ -181,4 +181,10 @@
<data name="Witcher3Artemis" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Witcher3\Witcher3Artemis.zip;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="g810" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Keyboards\g810.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="generic" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\generic.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -8,7 +8,7 @@ using Newtonsoft.Json.Linq;
namespace Artemis.Utilities.Converters
{
/// <summary>
/// Stores a brush by temporarily serializing it to XAML because Json.NET has trouble
/// Stores a brush by temporarily serializing it to XAML because Json.NET has trouble
/// saving it as JSON
/// </summary>
public class BrushJsonConverter : JsonConverter

View File

@ -68,12 +68,12 @@ namespace Artemis.Utilities.Converters
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value == null ? 0.0 : ((TimeSpan)value).TotalMilliseconds;
return value == null ? 0.0 : ((TimeSpan) value).TotalMilliseconds;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return value == null ? new TimeSpan() : TimeSpan.FromMilliseconds((double)value);
return value == null ? new TimeSpan() : TimeSpan.FromMilliseconds((double) value);
}
}
}

View File

@ -55,7 +55,7 @@ namespace Artemis.Utilities
ObjectCreationHandling = ObjectCreationHandling.Replace,
TypeNameHandling = TypeNameHandling.Auto
};
return (T)JsonConvert.DeserializeObject(JsonConvert.SerializeObject(source), source.GetType(),
return (T) JsonConvert.DeserializeObject(JsonConvert.SerializeObject(source), source.GetType(),
deserializeSettings);
}

View File

@ -15,12 +15,12 @@ namespace Artemis.Utilities
{
public static class Updater
{
public static int CurrentVersion = 113;
public static int CurrentVersion = 120;
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
public static async Task<Action> CheckForUpdate(MetroDialogService dialogService)
{
Logger.Info("Checking for updates - Current version: 1.1.3");
Logger.Info("Checking for updates - Current version: 1.2.0");
if (!General.Default.CheckForUpdates)
return null;

View File

@ -108,13 +108,13 @@ namespace Artemis.ViewModels.Abstract
protected override void OnActivate()
{
base.OnActivate();
ProfileEditor.ProfileViewModel.Activate();
ProfileEditor.Activate();
}
protected override void OnDeactivate(bool close)
{
base.OnDeactivate(close);
ProfileEditor.ProfileViewModel.Deactivate();
ProfileEditor.Deactivate();
}
}

View File

@ -3,7 +3,6 @@ using Artemis.Profiles.Layers.Models;
using Artemis.Utilities;
using Caliburn.Micro;
namespace Artemis.ViewModels.Profiles.Events
{
public class EventPropertiesViewModel : PropertyChangedBase

View File

@ -213,7 +213,7 @@ namespace Artemis.ViewModels.Profiles
SelectedDataModelProp = DataModelProps.FirstOrDefault(m => m.Path == LayerConditionModel.Field);
SelectedOperator = Operators.FirstOrDefault(o => o.Value == LayerConditionModel.Operator);
LayerConditionModel.Type = SelectedDataModelProp.Type;
if (LayerConditionModel.Type == "Enum")
if (LayerConditionModel.Type == "Enum" || LayerConditionModel.Type == "Boolean")
SelectedEnum = LayerConditionModel.Value;
else
UserValue = LayerConditionModel.Value;

View File

@ -5,7 +5,6 @@ using Artemis.Utilities;
using Caliburn.Micro;
using Castle.Core.Internal;
namespace Artemis.ViewModels.Profiles
{
public sealed class LayerDynamicPropertiesViewModel : PropertyChangedBase

View File

@ -4,6 +4,7 @@ using System.ComponentModel;
using System.IO;
using System.Linq;
using Artemis.Models.Interfaces;
using Artemis.Profiles.Layers.Abstract;
using Artemis.Profiles.Layers.Interfaces;
using Artemis.Profiles.Layers.Models;
using Artemis.Profiles.Layers.Types.Keyboard;
@ -11,9 +12,7 @@ using Artemis.Profiles.Layers.Types.KeyboardGif;
using Artemis.Services;
using Artemis.Utilities;
using Artemis.ViewModels.Profiles.Events;
using Artemis.ViewModels.Profiles.Layers;
using Caliburn.Micro;
using Newtonsoft.Json;
using Ninject;
@ -35,20 +34,20 @@ namespace Artemis.ViewModels.Profiles
_dataModel = dataModel;
_layerAnimations = layerAnimations;
LayerTypes = new BindableCollection<ILayerType>(layerTypes);
DataModelProps = new BindableCollection<GeneralHelpers.PropertyCollection>(
GeneralHelpers.GenerateTypeMap(dataModel));
Layer = layer;
ProposedLayer = GeneralHelpers.Clone(layer);
if (Layer.Properties == null)
Layer.SetupProperties();
LayerTypes = new BindableCollection<ILayerType>(layerTypes);
DataModelProps = new BindableCollection<GeneralHelpers.PropertyCollection>(
GeneralHelpers.GenerateTypeMap(dataModel));
LayerConditionVms = new BindableCollection<LayerConditionViewModel>(
layer.Properties.Conditions.Select(c => new LayerConditionViewModel(this, c, DataModelProps)));
PropertyChanged += PropertiesViewModelHandler;
PreSelect();
}
@ -166,8 +165,25 @@ namespace Artemis.ViewModels.Profiles
public void Apply()
{
LayerPropertiesViewModel?.ApplyProperties();
Layer = GeneralHelpers.Clone(ProposedLayer);
var appliedLayer = GeneralHelpers.Clone(ProposedLayer);
// Fix relations
if (Layer.Parent != null)
{
Layer.Parent.Children.Add(appliedLayer);
Layer.Parent.Children.Remove(Layer);
}
else
{
Layer.Profile.Layers.Add(appliedLayer);
Layer.Profile.Layers.Remove(Layer);
}
appliedLayer.Children.Clear();
foreach (var layerModel in Layer.Children)
appliedLayer.Children.Add(layerModel);
Layer = appliedLayer;
// TODO: EventPropVM must have layer too
if (EventPropertiesViewModel != null)
Layer.EventProperties = EventPropertiesViewModel.GetAppliedProperties();
@ -201,8 +217,20 @@ namespace Artemis.ViewModels.Profiles
foreach (var conditionViewModel in LayerConditionVms)
ProposedLayer.Properties.Conditions.Add(conditionViewModel.LayerConditionModel);
// Ignore children on the comparison
var currentNoChildren = GeneralHelpers.Clone(Layer);
currentNoChildren.Children.Clear();
// If not a keyboard, ignore size and position
if (ProposedLayer.LayerType.DrawType != DrawType.Keyboard)
{
ProposedLayer.Properties.Width = currentNoChildren.Properties.Width;
ProposedLayer.Properties.Height = currentNoChildren.Properties.Height;
ProposedLayer.Properties.X = currentNoChildren.Properties.X;
ProposedLayer.Properties.Y = currentNoChildren.Properties.Y;
ProposedLayer.Properties.Contain = currentNoChildren.Properties.Contain;
}
var current = JsonConvert.SerializeObject(Layer, Formatting.Indented);
var current = JsonConvert.SerializeObject(currentNoChildren, Formatting.Indented);
var proposed = JsonConvert.SerializeObject(ProposedLayer, Formatting.Indented);
if (current.Equals(proposed))

View File

@ -1,8 +1,10 @@
using System.ComponentModel;
using System;
using System.ComponentModel;
using System.Dynamic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Timers;
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Media;
@ -21,12 +23,12 @@ using Artemis.Utilities;
using Caliburn.Micro;
using GongSolutions.Wpf.DragDrop;
using MahApps.Metro.Controls.Dialogs;
using Ninject;
using DragDropEffects = System.Windows.DragDropEffects;
using IDropTarget = GongSolutions.Wpf.DragDrop.IDropTarget;
using MouseEventArgs = System.Windows.Input.MouseEventArgs;
using Screen = Caliburn.Micro.Screen;
using Timer = System.Timers.Timer;
namespace Artemis.ViewModels.Profiles
{
@ -35,9 +37,11 @@ namespace Artemis.ViewModels.Profiles
private readonly EffectModel _gameModel;
private readonly ILayerEditorVmFactory _layerEditorVmFactory;
private readonly MainManager _mainManager;
private readonly Timer _saveTimer;
private ImageSource _keyboardPreview;
private BindableCollection<LayerModel> _layers;
private BindableCollection<ProfileModel> _profiles;
private bool _saving;
private ProfileModel _selectedProfile;
public ProfileEditorViewModel(IEventAggregator events, MainManager mainManager, EffectModel gameModel,
@ -56,8 +60,13 @@ namespace Artemis.ViewModels.Profiles
events.Subscribe(this);
ProfileViewModel.PropertyChanged += PropertyChangeHandler;
PropertyChanged += PropertyChangeHandler;
PropertyChanged += EditorStateHandler;
ProfileViewModel.PropertyChanged += LayerSelectedHandler;
_saveTimer = new Timer(5000);
_saveTimer.Elapsed += ProfileSaveHandler;
LoadProfiles();
}
@ -201,38 +210,16 @@ namespace Artemis.ViewModels.Profiles
LoadProfiles();
}
/// <summary>
/// Handles refreshing the layer preview
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void PropertyChangeHandler(object sender, PropertyChangedEventArgs e)
public void Activate()
{
if (e.PropertyName == "KeyboardPreview")
return;
ProfileViewModel.Activate();
_saveTimer.Start();
}
if (e.PropertyName == "SelectedLayer")
{
NotifyOfPropertyChange(() => LayerSelected);
return;
}
if (SelectedProfile != null)
ProfileProvider.AddOrUpdate(SelectedProfile);
if (e.PropertyName != "SelectedProfile")
return;
// Update editor enabled state
NotifyOfPropertyChange(() => EditorEnabled);
// Update ProfileViewModel
ProfileViewModel.SelectedProfile = SelectedProfile;
// Update interface
Layers.Clear();
if (SelectedProfile != null)
Layers.AddRange(SelectedProfile.Layers);
NotifyOfPropertyChange(() => ProfileSelected);
public void Deactivate()
{
ProfileViewModel.Deactivate();
_saveTimer.Stop();
}
/// <summary>
@ -267,7 +254,8 @@ namespace Artemis.ViewModels.Profiles
if (ProfileViewModel.SelectedLayer == null)
return;
EditLayer(ProfileViewModel.SelectedLayer);
var selectedLayer = ProfileViewModel.SelectedLayer;
EditLayer(selectedLayer);
}
/// <summary>
@ -276,8 +264,12 @@ namespace Artemis.ViewModels.Profiles
/// <param name="layer">The layer to open the view for</param>
public void EditLayer(LayerModel layer)
{
if (layer == null)
return;
IWindowManager manager = new WindowManager();
var editorVm = _layerEditorVmFactory.CreateLayerEditorVm(_gameModel.DataModel, layer);
dynamic settings = new ExpandoObject();
var icon = ImageUtilities.GenerateWindowIcon();
@ -286,9 +278,9 @@ namespace Artemis.ViewModels.Profiles
manager.ShowDialog(editorVm, null, settings);
// The layer editor VM may have created a new instance of the layer, reapply it to the list
layer.Replace(editorVm.Layer);
layer = editorVm.Layer;
//// The layer editor VM may have created a new instance of the layer, reapply it to the list
//layer.Replace(editorVm.Layer);
//layer = editorVm.Layer;
// If the layer was a folder, but isn't anymore, assign it's children to it's parent.
if (!(layer.LayerType is FolderType) && layer.Children.Any())
@ -316,10 +308,10 @@ namespace Artemis.ViewModels.Profiles
/// <summary>
/// Adds a new layer to the profile and selects it
/// </summary>
public void AddLayer()
public LayerModel AddLayer()
{
if (SelectedProfile == null)
return;
return null;
// Create a new layer
var layer = LayerModel.CreateLayer();
@ -333,6 +325,20 @@ namespace Artemis.ViewModels.Profiles
}
UpdateLayerList(layer);
return layer;
}
public LayerModel AddFolder()
{
var layer = AddLayer();
if (layer == null)
return null;
layer.Name = "New folder";
layer.LayerType = new FolderType();
layer.LayerType.SetupProperties(layer);
return layer;
}
/// <summary>
@ -408,6 +414,8 @@ namespace Artemis.ViewModels.Profiles
{
var clone = GeneralHelpers.Clone(layer);
layer.InsertAfter(clone);
foreach (var layerModel in layer.Children)
clone.Children.Add(GeneralHelpers.Clone(layerModel));
UpdateLayerList(clone);
}
@ -487,6 +495,8 @@ namespace Artemis.ViewModels.Profiles
{
Name = name,
KeyboardSlug = _mainManager.DeviceManager.ActiveKeyboard.Slug,
Width = _mainManager.DeviceManager.ActiveKeyboard.Width,
Height = _mainManager.DeviceManager.ActiveKeyboard.Height,
GameName = _gameModel.Name
};
@ -613,7 +623,8 @@ namespace Artemis.ViewModels.Profiles
}
// Verify the keyboard
if (profile.KeyboardSlug != _mainManager.DeviceManager.ActiveKeyboard.Slug)
var deviceManager = _mainManager.DeviceManager;
if (profile.KeyboardSlug != deviceManager.ActiveKeyboard.Slug)
{
var adjustKeyboard = await DialogService.ShowQuestionMessageBox("Profile not inteded for this keyboard",
$"Watch out, this profile wasn't ment for this keyboard, but for the {profile.KeyboardSlug}. " +
@ -622,9 +633,16 @@ namespace Artemis.ViewModels.Profiles
if (!adjustKeyboard.Value)
return;
profile.KeyboardSlug = _mainManager.DeviceManager.ActiveKeyboard.Slug;
// Resize layers that are on the full keyboard width
profile.ResizeLayers(deviceManager.ActiveKeyboard);
// Put layers back into the canvas if they fell outside it
profile.FixBoundaries(deviceManager.ActiveKeyboard.KeyboardRectangle(1));
// Setup profile metadata to match the new keyboard
profile.KeyboardSlug = deviceManager.ActiveKeyboard.Slug;
profile.Width = deviceManager.ActiveKeyboard.Width;
profile.Height = deviceManager.ActiveKeyboard.Height;
profile.IsDefault = false;
profile.FixBoundaries(_mainManager.DeviceManager.ActiveKeyboard.KeyboardRectangle(1));
}
// Verify the name
@ -656,5 +674,48 @@ namespace Artemis.ViewModels.Profiles
ProfileProvider.ExportProfile(SelectedProfile, dialog.FileName);
}
private void EditorStateHandler(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName != "SelectedProfile")
return;
// Update editor enabled state
NotifyOfPropertyChange(() => EditorEnabled);
// Update ProfileViewModel
ProfileViewModel.SelectedProfile = SelectedProfile;
// Update interface
Layers.Clear();
if (SelectedProfile != null)
Layers.AddRange(SelectedProfile.Layers);
NotifyOfPropertyChange(() => ProfileSelected);
}
private void LayerSelectedHandler(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName != "SelectedLayer")
return;
NotifyOfPropertyChange(() => LayerSelected);
}
private void ProfileSaveHandler(object sender, ElapsedEventArgs e)
{
if (_saving || SelectedProfile == null)
return;
_saving = true;
try
{
ProfileProvider.AddOrUpdate(SelectedProfile);
}
catch (Exception)
{
// ignored
}
_saving = false;
}
}
}

View File

@ -110,11 +110,12 @@ namespace Artemis.ViewModels.Profiles
drawingContext.DrawRectangle(new SolidColorBrush(Color.FromArgb(0, 0, 0, 0)), null, keyboardRect);
// Draw the layers
var drawLayers = SelectedProfile.GetRenderLayers(new ProfilePreviewDataModel(), false, false, true);
var drawLayers = SelectedProfile.GetRenderLayers(new ProfilePreviewDataModel(), false, true);
foreach (var layer in drawLayers)
{
layer.Update(null, true, false);
layer.Draw(null, drawingContext, true, false);
if (layer.LayerType.ShowInEdtor)
layer.Draw(null, drawingContext, true, false);
}
// Get the selection color
@ -127,7 +128,7 @@ namespace Artemis.ViewModels.Profiles
// Draw the selection outline and resize indicator
if (SelectedLayer != null && SelectedLayer.MustDraw())
{
var layerRect = ((KeyboardPropertiesModel) SelectedLayer.Properties).GetRect();
var layerRect = SelectedLayer.Properties.GetRect();
// Deflate the rect so that the border is drawn on the inside
layerRect.Inflate(-0.2, -0.2);
@ -200,9 +201,7 @@ namespace Artemis.ViewModels.Profiles
var hoverLayer = SelectedProfile.GetLayers()
.Where(l => l.MustDraw())
.FirstOrDefault(l => ((KeyboardPropertiesModel) l.Properties)
.GetRect(1)
.Contains(x, y));
.FirstOrDefault(l => l.Properties.GetRect(1).Contains(x, y));
SelectedLayer = hoverLayer;
}
@ -222,8 +221,7 @@ namespace Artemis.ViewModels.Profiles
var y = pos.Y/((double) keyboard.PreviewSettings.Height/keyboard.Height);
var hoverLayer = SelectedProfile.GetLayers()
.Where(l => l.MustDraw())
.FirstOrDefault(l => ((KeyboardPropertiesModel) l.Properties)
.GetRect(1).Contains(x, y));
.FirstOrDefault(l => l.Properties.GetRect(1).Contains(x, y));
HandleDragging(e, x, y, hoverLayer);
@ -233,11 +231,10 @@ namespace Artemis.ViewModels.Profiles
return;
}
// Turn the mouse pointer into a hand if hovering over an active layer
if (hoverLayer == SelectedLayer)
{
var rect = ((KeyboardPropertiesModel) hoverLayer.Properties).GetRect(1);
var rect = hoverLayer.Properties.GetRect(1);
KeyboardPreviewCursor =
Math.Sqrt(Math.Pow(x - rect.BottomRight.X, 2) + Math.Pow(y - rect.BottomRight.Y, 2)) < 0.6
? Cursors.SizeNWSE
@ -276,16 +273,15 @@ namespace Artemis.ViewModels.Profiles
return;
}
if (SelectedLayer == null)
if (SelectedLayer == null || (SelectedLayer.LayerType != null && !SelectedLayer.LayerType.ShowInEdtor))
return;
// Setup the dragging state on mouse press
if (_draggingLayerOffset == null && hoverLayer != null && e.LeftButton == MouseButtonState.Pressed)
{
var layerRect = ((KeyboardPropertiesModel) hoverLayer.Properties).GetRect(1);
var selectedProps = (KeyboardPropertiesModel) SelectedLayer.Properties;
var layerRect = hoverLayer.Properties.GetRect(1);
_draggingLayerOffset = new Point(x - selectedProps.X, y - selectedProps.Y);
_draggingLayerOffset = new Point(x - SelectedLayer.Properties.X, y - SelectedLayer.Properties.Y);
_draggingLayer = hoverLayer;
// Detect dragging if cursor is in the bottom right
_resizing = Math.Sqrt(Math.Pow(x - layerRect.BottomRight.X, 2) +
@ -295,8 +291,7 @@ namespace Artemis.ViewModels.Profiles
if (_draggingLayerOffset == null || _draggingLayer == null || (_draggingLayer != SelectedLayer))
return;
var draggingProps = (KeyboardPropertiesModel) _draggingLayer?.Properties;
var draggingProps = _draggingLayer.Properties;
// If no setup or reset was done, handle the actual dragging action
if (_resizing)
{

View File

@ -113,7 +113,7 @@
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.ColumnSpan="2" x:Name="ActiveEffectName" />
<TextBlock Grid.Row="1" Grid.Column="0" Text="Artemis 1.1.3" VerticalAlignment="Center"
<TextBlock Grid.Row="1" Grid.Column="0" Text="Artemis 1.2.0" VerticalAlignment="Center"
HorizontalAlignment="Left" />
<Button Grid.Row="1" Grid.Column="1" Focusable="False"
Style="{StaticResource AccentedSquareButtonStyle}"

View File

@ -49,10 +49,10 @@
<TextBlock Grid.Row="1" Grid.Column="2" Margin="10,12" FontSize="13.333" Text="Type:"
VerticalAlignment="Center" Height="18" />
<ComboBox Grid.Row="1" Grid.Column="3" Margin="10" Width="120" x:Name="LayerTypes" >
<ComboBox Grid.Row="1" Grid.Column="3" Margin="10" Width="120" x:Name="LayerTypes">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Name, Mode=OneWay}"/>
<TextBlock Text="{Binding Path=Name, Mode=OneWay}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>

View File

@ -1,34 +0,0 @@
<UserControl x:Class="Artemis.Views.Profiles.Layers.HeadsetPropertiesView"
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 />
</Grid.RowDefinitions>
<!-- Colors -->
<StackPanel Grid.Row="0" 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>
<TextBlock Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="4" Margin="10,2,10,10" FontSize="13.333"
Foreground="{DynamicResource HighlightBrush}"
Text="Note: If your headset 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

@ -205,6 +205,19 @@
</Rectangle>
</Button.Content>
</Button>
<Button x:Name="AddFolder" VerticalAlignment="Top"
Style="{DynamicResource SquareButtonStyle}" IsEnabled="{Binding Path=EditorEnabled, Mode=OneWay}"
Width="26" Height="26" ToolTip="Add folder" HorizontalAlignment="Left" Margin="10,0,0,0">
<Button.Content>
<Rectangle
Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}"
Width="12" Height="12">
<Rectangle.OpacityMask>
<VisualBrush Visual="{StaticResource appbar_folder}" Stretch="Fill" />
</Rectangle.OpacityMask>
</Rectangle>
</Button.Content>
</Button>
<Button x:Name="EditLayer" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}"
Width="26" Height="26" HorizontalAlignment="Right" Margin="10,0,0,0" ToolTip="Edit layer"
IsEnabled="{Binding Path=LayerSelected}">

View File

@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Caliburn.Micro" version="3.0.1" targetFramework="net452" />
<package id="Caliburn.Micro.Core" version="3.0.1" targetFramework="net452" />

View File

@ -88,10 +88,14 @@
<SDLCheck>
</SDLCheck>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BrowseInformation>true</BrowseInformation>
</ClCompile>
<Link>
<ModuleDefinitionFile>Razer2Artemis.def</ModuleDefinitionFile>
</Link>
<Bscmake>
<PreserveSbr>true</PreserveSbr>
</Bscmake>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>