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

Merge pull request #355 from SpoinkyNL/development

1.10.0.0
This commit is contained in:
Robert Beekman 2017-05-06 23:48:48 +02:00 committed by GitHub
commit 2edbf093a7
65 changed files with 1872 additions and 774 deletions

View File

@ -384,6 +384,13 @@
<DependentUpon>AssettoCorsaView.xaml</DependentUpon>
</Compile>
<Compile Include="Modules\Games\AssettoCorsa\AssettoCorsaViewModel.cs" />
<Compile Include="Modules\Games\Terraria\TerrariaDataModel.cs" />
<Compile Include="Modules\Games\Terraria\TerrariaSettings.cs" />
<Compile Include="Modules\Games\Terraria\TerrariaModel.cs" />
<Compile Include="Modules\Games\Terraria\TerrariaView.xaml.cs">
<DependentUpon>TerrariaView.xaml</DependentUpon>
</Compile>
<Compile Include="Modules\Games\Terraria\TerrariaViewModel.cs" />
<Compile Include="Modules\General\GeneralProfile\PerformanceInfo.cs" />
<Compile Include="Modules\Games\EurotruckSimulator2\Data\Ets2TelemetryData.cs" />
<Compile Include="Modules\Games\EurotruckSimulator2\Data\Ets2TelemetryDataReader.cs" />
@ -561,15 +568,27 @@
<Compile Include="Profiles\Lua\Modules\Events\LuaKeyPressEventArgs.cs" />
<Compile Include="Profiles\Lua\Modules\Events\LuaDeviceDrawingEventArgs.cs" />
<Compile Include="Profiles\Lua\Modules\Events\LuaDeviceUpdatingEventArgs.cs" />
<Compile Include="Profiles\Lua\Modules\Gui\EditorButton.cs" />
<Compile Include="Profiles\Lua\Modules\Gui\LuaButton.cs" />
<Compile Include="Profiles\Lua\Modules\Gui\LuaCheckBox.cs" />
<Compile Include="Profiles\Lua\Modules\Gui\LuaComboBox.cs" />
<Compile Include="Profiles\Lua\Modules\Gui\LuaLabel.cs" />
<Compile Include="Profiles\Lua\Modules\Gui\LuaTextBox.cs" />
<Compile Include="Profiles\Lua\Modules\Gui\LuaWindowView.xaml.cs">
<DependentUpon>LuaWindowView.xaml</DependentUpon>
</Compile>
<Compile Include="Profiles\Lua\Modules\Gui\LuaWindowViewModel.cs" />
<Compile Include="Profiles\Lua\Modules\LuaEventsModule.cs" />
<Compile Include="Profiles\Lua\Modules\LuaBrushesModule.cs" />
<Compile Include="Profiles\Lua\LuaModule.cs" />
<Compile Include="Profiles\Lua\Modules\Brushes\LuaSolidColorBrush.cs" />
<Compile Include="Profiles\Lua\Modules\LuaGuiModule.cs" />
<Compile Include="Profiles\Lua\Modules\LuaKeybindModule.cs" />
<Compile Include="Profiles\Lua\Modules\LuaKeyboardModule.cs" />
<Compile Include="Profiles\Lua\Modules\LuaLayerModule.cs" />
<Compile Include="Profiles\Lua\Modules\LuaMouseModule.cs" />
<Compile Include="Profiles\Lua\Modules\LuaProfileModule.cs" />
<Compile Include="Profiles\Lua\Modules\LuaStorageModule.cs" />
<Compile Include="Profiles\Lua\Modules\Timer\LuaTimer.cs" />
<Compile Include="Profiles\Lua\Modules\LuaTimerModule.cs" />
<Compile Include="Profiles\Lua\Wrappers\LuaDrawWrapper.cs" />
@ -645,6 +664,7 @@
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Services\CompatibilityService.cs" />
<Compile Include="Services\DialogService.cs" />
<Compile Include="Services\MetroDialogService.cs" />
<Compile Include="Services\WindowService.cs" />
@ -653,7 +673,11 @@
<Compile Include="Settings\OffsetSettings.cs" />
<Compile Include="Styles\DropTargetAdorners\DropTargetMetroHighlightAdorner.cs" />
<Compile Include="Styles\DropTargetAdorners\DropTargetMetroInsertionAdorner.cs" />
<Compile Include="Utilities\ActiveWindowHelper.cs" />
<Compile Include="Utilities\ActiveWindowDetection\ActiveWindowDetectionType.cs" />
<Compile Include="Utilities\ActiveWindowDetection\ActiveWindowHelper.cs" />
<Compile Include="Utilities\ActiveWindowDetection\EventActiveWindowDetector.cs" />
<Compile Include="Utilities\ActiveWindowDetection\IActiveWindowDetector.cs" />
<Compile Include="Utilities\ActiveWindowDetection\TimerActiveWindowDetector.cs" />
<Compile Include="Utilities\ColorHelpers.cs" />
<Compile Include="Utilities\Converters\JsonConverters.cs" />
<Compile Include="Utilities\Converters\NinjectCustomConverter.cs" />
@ -856,6 +880,10 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Modules\Games\Terraria\TerrariaView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Modules\General\Bubbles\BubblesView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
@ -924,6 +952,10 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Profiles\Lua\Modules\Gui\LuaWindowView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Resources\Icons.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>

View File

@ -8,8 +8,10 @@ using System.Windows.Controls;
using System.Windows.Input;
using Artemis.DAL;
using Artemis.InjectionModules;
using Artemis.Services;
using Artemis.Settings;
using Artemis.Utilities;
using Artemis.Utilities.ActiveWindowDetection;
using Artemis.Utilities.Converters;
using Artemis.Utilities.DataReaders;
using Artemis.ViewModels;
@ -31,10 +33,11 @@ namespace Artemis
Logging.SetupLogging(SettingsProvider.Load<GeneralSettings>().LogLevel);
// Restore DDLs before interacting with any SDKs
DllManager.RestoreLogitechDll();
// Check compatibility before trying to boot further
CompatibilityService.CheckRivaTuner();
Initialize();
BindSpecialValues();
InputHook.Start();
AppDomain.CurrentDomain.UnhandledException += CurrentDomainOnUnhandledException;
}
@ -61,7 +64,7 @@ namespace Artemis
}
// If there is another type of of IInputControl get the non-scaled position - or do some processing to get a scaled position, whatever needs to happen
if ((e != null) && (input != null))
if (e != null && input != null)
return e.GetPosition(input).X;
// Return 0 if no processing could be done
@ -98,6 +101,7 @@ namespace Artemis
logger.Info("Artemis was run using the autorun shortcut, sleeping for 15 sec.");
Thread.Sleep(15000);
}
_kernel = new StandardKernel(new BaseModules(), new ManagerModules());
_kernel.Bind<IWindowManager>().To<WindowManager>().InSingletonScope();
@ -113,7 +117,7 @@ namespace Artemis
//TODO DarthAffe 17.12.2016: Is this the right location for this?
//TODO Move to Mainmanager and make disposable
ActiveWindowHelper.Initialize();
ActiveWindowHelper.SetActiveWindowDetectionType(SettingsProvider.Load<GeneralSettings>().ActiveWindowDetection);
}
protected override void OnExit(object sender, EventArgs e)
@ -144,6 +148,7 @@ namespace Artemis
protected override void OnStartup(object sender, StartupEventArgs e)
{
DisplayRootViewFor<ShellViewModel>();
InputHook.Start();
}
}
}

View File

@ -134,7 +134,7 @@ namespace Artemis.DAL
return null;
return prof;
}
catch (JsonSerializationException)
catch (JsonException)
{
return null;
}

View File

@ -1,4 +1,5 @@
using System.Drawing;
using System;
using System.Drawing;
using System.Linq;
using System.Threading;
using System.Windows;
@ -67,6 +68,8 @@ namespace Artemis.DeviceProviders.CoolerMaster
for (var y = 0; y < Height; y++)
{
var c = b.GetPixel(x, y);
if (c.R != 0)
Console.WriteLine();
matrix.KeyColor[y, x] = new KEY_COLOR(c.R, c.G, c.B);
}
}

View File

@ -42,9 +42,16 @@ namespace Artemis.DeviceProviders.CoolerMaster
CmSdk.SetControlDevice(DEVICE_INDEX.DEV_MMouse_L);
// Doesn't seem reliable but better than nothing I suppose
CanUse = CmSdk.IsDevicePlug();
if (CanUse)
CmSdk.EnableLedControl(true);
try
{
CanUse = CmSdk.IsDevicePlug();
if (CanUse)
CmSdk.EnableLedControl(true);
}
catch (Exception)
{
CanUse = false;
}
Logger.Debug("Attempted to enable Mastermouse Pro L. CanUse: {0}", CanUse);
return CanUse;

View File

@ -38,10 +38,17 @@ namespace Artemis.DeviceProviders.CoolerMaster
CmSdk.SetControlDevice(DEVICE_INDEX.DEV_MMouse_S);
// Doesn't seem reliable but better than nothing I suppose
CanUse = CmSdk.IsDevicePlug();
if (CanUse)
CmSdk.EnableLedControl(true);
try
{
CanUse = CmSdk.IsDevicePlug();
if (CanUse)
CmSdk.EnableLedControl(true);
}
catch (Exception)
{
CanUse = false;
}
Logger.Debug("Attempted to enable Mastermouse Pro S. CanUse: {0}", CanUse);
return CanUse;
}

View File

@ -81,10 +81,10 @@ namespace Artemis.DeviceProviders.Corsair
PreviewSettings = new PreviewSettings(new Rect(15, 30, 751, 284), Resources.k65);
break;
case "STRAFE RGB":
Height = 7;
Height = 8;
Width = 22;
Slug = "corsair-strafe-rgb";
PreviewSettings = new PreviewSettings(new Rect(23, 30, 940, 303), Resources.strafe);
PreviewSettings = new PreviewSettings(new Rect(23, 12, 937, 324), Resources.strafe);
break;
}
@ -114,29 +114,8 @@ namespace Artemis.DeviceProviders.Corsair
/// <param name="bitmap"></param>
public override void DrawBitmap(Bitmap bitmap)
{
// For STRAFE, stretch the image on row 2.
if (_keyboard.DeviceInfo.Model == "STRAFE RGB")
{
using (var strafeBitmap = new Bitmap(22, 8))
{
using (var g = Graphics.FromImage(strafeBitmap))
{
g.DrawImage(bitmap, new Point(0, 0));
g.DrawImage(bitmap, new Rectangle(0, 3, 22, 7), new Rectangle(0, 2, 22, 7),
GraphicsUnit.Pixel);
_keyboardBrush.Image = strafeBitmap;
_keyboard.Update();
}
}
}
else
{
_keyboardBrush.Image = bitmap;
_keyboard.Update();
}
_keyboardBrush.Image = bitmap;
_keyboard.Update();
}
public override KeyMatch? GetKeyPosition(Keys keyCode)

View File

@ -14,8 +14,7 @@ namespace Artemis.DeviceProviders.Logitech
DllManager.RestoreLogitechDll();
// Check to see if VC++ 2012 x64 is installed.
if (Registry.LocalMachine.OpenSubKey(
@"SOFTWARE\Classes\Installer\Dependencies\{ca67548a-5ebe-413a-b50c-4b9ceb6d66c6}") == null)
if (Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Classes\Installer\Dependencies\{ca67548a-5ebe-413a-b50c-4b9ceb6d66c6}") == null)
{
CantEnableText = "Couldn't connect to your Logitech keyboard.\n" +
"The Visual C++ 2012 Redistributable v11.0.61030.0 could not be found, which is required.\n" +

View File

@ -37,8 +37,11 @@ namespace Artemis.DeviceProviders.Razer
return false;
// Some people have Synapse installed, but not a Chroma keyboard, deal with this
Chroma.Instance.Initialize();
var blackWidowFound = Chroma.Instance.Query(Devices.Blackwidow).Connected;
var blackWidowTeFound = Chroma.Instance.Query(Devices.BlackwidowTe).Connected;
Chroma.Instance.Uninitialize();
return blackWidowFound || blackWidowTeFound;
}

View File

@ -6,6 +6,7 @@ using Artemis.Profiles.Layers.Abstract;
using Artemis.Profiles.Layers.Interfaces;
using Artemis.Profiles.Layers.Types.Audio.AudioCapturing;
using Artemis.Profiles.Lua;
using Artemis.Profiles.Lua.Modules.Gui;
using Artemis.Services;
using Artemis.Utilities.DataReaders;
using Artemis.Utilities.GameState;
@ -116,6 +117,8 @@ namespace Artemis.InjectionModules
.InheritedFrom<LuaModule>()
.BindAllBaseClasses());
Bind<LuaWindowViewModel>().ToSelf();
#endregion
}
}

View File

@ -1,10 +1,12 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Artemis.DeviceProviders;
using Artemis.Profiles;
using Artemis.Profiles.Lua;
using Artemis.Profiles.Lua.Modules;
using Artemis.Profiles.Lua.Modules.Gui;
using Castle.Core.Internal;
using MoonSharp.Interpreter;
using Ninject;
@ -17,7 +19,6 @@ namespace Artemis.Managers
private readonly DeviceManager _deviceManager;
private readonly IKernel _kernel;
private readonly ILogger _logger;
private readonly Script _luaScript;
private List<LuaModule> _luaModules;
public LuaManager(IKernel kernel, ILogger logger, DeviceManager deviceManager)
@ -25,13 +26,17 @@ namespace Artemis.Managers
_kernel = kernel;
_logger = logger;
_deviceManager = deviceManager;
_luaScript = new Script(CoreModules.Preset_SoftSandbox);
EditorButtons = new ObservableCollection<EditorButton>();
LuaScript = new Script(CoreModules.Preset_SoftSandbox);
}
public ProfileModel ProfileModel { get; private set; }
public KeyboardProvider KeyboardProvider { get; private set; }
public LuaProfileModule ProfileModule { get; private set; }
public LuaEventsModule EventsModule { get; private set; }
public Script LuaScript { get; }
public ObservableCollection<EditorButton> EditorButtons { get; set; }
public void SetupLua(ProfileModel profileModel)
{
@ -52,11 +57,11 @@ namespace Artemis.Managers
EventsModule = (LuaEventsModule) _luaModules.First(m => m.ModuleName == "Events");
// Setup new state
_luaScript.Options.DebugPrint = LuaPrint;
LuaScript.Options.DebugPrint = LuaPrint;
// Insert each module into the script's globals
foreach (var luaModule in _luaModules)
_luaScript.Globals[luaModule.ModuleName] = luaModule;
// Insert each module with a ModuleName into the script's globals
foreach (var luaModule in _luaModules.Where(m => m.ModuleName != null))
LuaScript.Globals[luaModule.ModuleName] = luaModule;
// If there is no LUA script, don't bother executing the string
if (ProfileModel.LuaScript.IsNullOrEmpty())
@ -66,9 +71,9 @@ namespace Artemis.Managers
{
lock (EventsModule.InvokeLock)
{
lock (_luaScript)
lock (LuaScript)
{
_luaScript.DoString(ProfileModel.LuaScript);
LuaScript.DoString(ProfileModel.LuaScript);
}
}
}
@ -97,12 +102,12 @@ namespace Artemis.Managers
try
{
_luaScript.Globals.Clear();
_luaScript.Registry.Clear();
_luaScript.Registry.RegisterConstants();
_luaScript.Registry.RegisterCoreModules(CoreModules.Preset_SoftSandbox);
_luaScript.Globals.RegisterConstants();
_luaScript.Globals.RegisterCoreModules(CoreModules.Preset_SoftSandbox);
LuaScript.Globals.Clear();
LuaScript.Registry.Clear();
LuaScript.Registry.RegisterConstants();
LuaScript.Registry.RegisterCoreModules(CoreModules.Preset_SoftSandbox);
LuaScript.Globals.RegisterConstants();
LuaScript.Globals.RegisterCoreModules(CoreModules.Preset_SoftSandbox);
}
catch (NullReferenceException)
{
@ -112,15 +117,15 @@ namespace Artemis.Managers
if (EventsModule != null)
lock (EventsModule.InvokeLock)
{
lock (_luaScript)
lock (LuaScript)
{
_luaScript.DoString("");
LuaScript.DoString("");
}
}
else
lock (_luaScript)
lock (LuaScript)
{
_luaScript.DoString("");
LuaScript.DoString("");
}
}
@ -138,12 +143,12 @@ namespace Artemis.Managers
{
lock (EventsModule.InvokeLock)
{
lock (_luaScript)
lock (LuaScript)
{
if (args != null)
_luaScript.Call(function, args);
LuaScript.Call(function, args);
else
_luaScript.Call(function);
LuaScript.Call(function);
}
}
}

View File

@ -108,6 +108,7 @@ namespace Artemis.Managers
public async void EnableProgram()
{
Logger.Debug("Enabling program");
ProgramEnabled = true;
await LoopManager.StartAsync();
@ -121,9 +122,12 @@ namespace Artemis.Managers
public void DisableProgram()
{
Logger.Debug("Disabling program");
foreach (var overlayModule in ModuleManager.OverlayModules)
{
if (overlayModule.Settings.IsEnabled)
overlayModule.Dispose();
}
LoopManager.Stop();
ProgramEnabled = false;
RaiseEnabledChangedEvent(new EnabledChangedEventArgs(ProgramEnabled));
@ -178,4 +182,4 @@ namespace Artemis.Managers
handler?.Invoke(this, e);
}
}
}
}

View File

@ -5,6 +5,7 @@ using Artemis.DAL;
using Artemis.Modules.Abstract;
using Artemis.Settings;
using Artemis.Utilities;
using Artemis.Utilities.ActiveWindowDetection;
using Ninject.Extensions.Logging;
namespace Artemis.Managers

View File

@ -27,8 +27,7 @@ namespace Artemis.Models
private FileSystemWatcher _watcher;
private ModuleModel _luaModule;
public ProfileEditorModel(WindowService windowService, MetroDialogService dialogService,
DeviceManager deviceManager, LuaManager luaManager)
public ProfileEditorModel(WindowService windowService, MetroDialogService dialogService, DeviceManager deviceManager, LuaManager luaManager)
{
_windowService = windowService;
_dialogService = dialogService;
@ -50,7 +49,7 @@ namespace Artemis.Models
new ConstructorArgument("dataModel", dataModel),
new ConstructorArgument("layer", layer)
};
_windowService.ShowDialog<LayerEditorViewModel>("Artemis | Edit layer", args);
_windowService.ShowDialog<LayerEditorViewModel>("Artemis | Edit layer", null, args);
// If the layer was a folder, but isn't anymore, assign it's children to it's parent.
if (layer.LayerType is FolderType || !layer.Children.Any())
@ -345,7 +344,8 @@ namespace Artemis.Models
private void DisposeLuaWatcher()
{
if (_watcher == null) return;
if (_watcher == null)
return;
_watcher.Changed -= LuaFileChanged;
_watcher.Dispose();
_watcher = null;
@ -360,8 +360,6 @@ namespace Artemis.Models
#region Rendering
#endregion
}
}
}

View File

@ -22,7 +22,7 @@
<!-- Header -->
<Label Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" FontSize="20" HorizontalAlignment="Left">
<Label.Content>
<AccessText TextWrapping="Wrap" Text="By default shows RPM on the F-keys, gear on the other keys and track flags on the numpad." />
<AccessText TextWrapping="Wrap" Text="By default shows RPM on bottom half of the keyboard, engine stats on the top half and DRS on the numpad" />
</Label.Content>
</Label>

View File

@ -29,7 +29,6 @@ namespace Artemis.Modules.Games.GtaV
public override void Enable()
{
var process = System.Diagnostics.Process.GetProcessesByName("GTA5").First();
DllManager.PlaceLogitechDll();
_pipeServer.PipeMessage += PipeServerOnPipeMessage;
base.Enable();

View File

@ -36,7 +36,7 @@ namespace Artemis.Modules.Games.RocketLeague
{
if (!SettingsProvider.Load<GeneralSettings>().EnablePointersUpdate)
{
VersionText = "You disabled pointer updates, this could result in the Rocket League effect not working after a game update.";
VersionText = "You disabled pointer updates, this could result in the Rocket League module not working after a game update.";
return;
}

View File

@ -0,0 +1,18 @@
using Artemis.Modules.Abstract;
using MoonSharp.Interpreter;
namespace Artemis.Modules.Games.Terraria
{
[MoonSharpUserData]
public class TerrariaDataModel : ModuleDataModel
{
public int Hp { get; set; }
public int MaxHp { get; set; }
public int Mana { get; set; }
public int MaxMana { get; set; }
public int Breath { get; set; }
public int MaxBreath { get; set; }
public bool InWater { get; set; }
public bool InLava { get; set; }
}
}

View File

@ -0,0 +1,91 @@
using System;
using System.Linq;
using Artemis.DAL;
using Artemis.Managers;
using Artemis.Modules.Abstract;
using Artemis.Settings;
using Artemis.Utilities;
using Artemis.Utilities.Memory;
namespace Artemis.Modules.Games.Terraria
{
public class TerrariaModel : ModuleModel
{
private Memory _memory;
private GamePointersCollection _pointer;
public TerrariaModel(DeviceManager deviceManager, LuaManager luaManager) : base(deviceManager, luaManager)
{
Settings = SettingsProvider.Load<TerrariaSettings>();
DataModel = new TerrariaDataModel();
ProcessNames.Add("Terraria");
// Generate a new offset when the game is updated
//_pointer = new GamePointersCollection
//{
// Game = "Terraria",
// GameVersion = "1.3.4.4",
// GameAddresses = new List<GamePointer>
// {
// new GamePointer
// {
// Description = "PlayerBase",
// BasePointer = new IntPtr(0x0039C078),
// Offsets = new[] {0x280, 0x6C0, 0x674, 0x3C}
// }
// }
//};
//var res = JsonConvert.SerializeObject(_pointer, Formatting.Indented);
}
public override string Name => "Terraria";
public override bool IsOverlay => false;
public override bool IsBoundToProcess => true;
public override void Dispose()
{
base.Dispose();
_memory?.Dispose();
_memory = null;
}
public override void Enable()
{
Updater.GetPointers();
_pointer = SettingsProvider.Load<OffsetSettings>().Terraria;
base.Enable();
}
public override void Update()
{
if (_memory == null)
{
var tempProcess = MemoryHelpers.GetProcessIfRunning(ProcessNames[0]);
if (tempProcess == null)
return;
_memory = new Memory(tempProcess);
}
if (ProfileModel == null || DataModel == null || _memory == null)
return;
var offsets = _pointer.GameAddresses.First(ga => ga.Description == "PlayerBase").ToString();
var baseAddress = _memory.GetAddress("\"Terraria.exe\"" + offsets);
var basePointer = new IntPtr(_memory.ReadInt32(baseAddress));
var playerPointer = new IntPtr(_memory.ReadInt32(basePointer + 0x18));
var dataModel = (TerrariaDataModel) DataModel;
dataModel.Hp = _memory.ReadInt32(playerPointer + 0x340);
dataModel.MaxHp = _memory.ReadInt32(playerPointer + 0x338);
dataModel.Mana = _memory.ReadInt32(playerPointer + 0x344);
dataModel.MaxMana = _memory.ReadInt32(playerPointer + 0x348);
dataModel.Breath = _memory.ReadInt32(playerPointer + 0x2B4);
dataModel.MaxBreath = _memory.ReadInt32(playerPointer + 0x2B0);
dataModel.InWater = Convert.ToBoolean(_memory.ReadInt32(playerPointer + 0x1D));
dataModel.InLava = Convert.ToBoolean(_memory.ReadInt32(playerPointer + 0x20));
}
}
}

View File

@ -0,0 +1,8 @@
using Artemis.Modules.Abstract;
namespace Artemis.Modules.Games.Terraria
{
public class TerrariaSettings : ModuleSettings
{
}
}

View File

@ -0,0 +1,48 @@
<UserControl x:Class="Artemis.Modules.Games.Terraria.TerrariaView"
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:local="clr-namespace:Artemis.Modules.Games.Terraria"
xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
xmlns:cal="http://www.caliburnproject.org"
mc:Ignorable="d" d:DesignWidth="714.667" d:DesignHeight="384.667" >
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="30" />
</Grid.RowDefinitions>
<!-- Header -->
<Label Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" FontSize="20" HorizontalAlignment="Left">
<Label.Content>
<AccessText TextWrapping="Wrap" Text="By default does nothing! (default profiles coming soon)" />
</Label.Content>
</Label>
<!-- Sub header -->
<TextBlock x:Name="VersionText" Grid.Row="1" Grid.Column="0" VerticalAlignment="Bottom" TextWrapping="Wrap" HorizontalAlignment="Left" FontFamily="Segoe UI Semibold" TextAlignment="Justify" Margin="5,0,0,10" />
<!-- Enable -->
<StackPanel Grid.Row="1" Grid.Column="1" HorizontalAlignment="Right" Orientation="Horizontal">
<Label Content="Enable module" HorizontalAlignment="Right" Margin="0,0,0,3" />
<controls:ToggleSwitchButton IsChecked="{Binding Path=IsModuleEnabled, Mode=OneWay}" cal:Message.Attach="[Event Click] = [Action ToggleModule]"
Style="{StaticResource MahApps.Metro.Styles.ToggleSwitchButton.Win10}" ToolTip="Note: You can't enable an module when Artemis is disabled" />
</StackPanel>
<!-- Profile editor -->
<ContentControl Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" x:Name="ProfileEditor" />
<!-- Buttons -->
<StackPanel Grid.Column="0" Grid.Row="3" Orientation="Horizontal" VerticalAlignment="Bottom">
<Button x:Name="ResetSettings" Content="Reset effect" VerticalAlignment="Top" Width="100" Style="{DynamicResource SquareButtonStyle}" />
<Button x:Name="SaveSettings" Content="Save changes" VerticalAlignment="Top" Width="100" Margin="10,0,0,0" Style="{DynamicResource SquareButtonStyle}" />
</StackPanel>
</Grid>
</UserControl>

View File

@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Artemis.Modules.Games.Terraria
{
/// <summary>
/// Interaction logic for TerrariaView.xaml
/// </summary>
public partial class TerrariaView : UserControl
{
public TerrariaView()
{
InitializeComponent();
}
}
}

View File

@ -0,0 +1,47 @@
using Artemis.DAL;
using Artemis.Managers;
using Artemis.Modules.Abstract;
using Artemis.Settings;
using Artemis.Utilities;
using Ninject;
namespace Artemis.Modules.Games.Terraria
{
public sealed class TerrariaViewModel : ModuleViewModel
{
private string _versionText;
public TerrariaViewModel(MainManager mainManager, [Named(nameof(TerrariaModel))] ModuleModel moduleModel, IKernel kernel) : base(mainManager, moduleModel, kernel)
{
DisplayName = "Terraria";
SetVersionText();
}
public override bool UsesProfileEditor => true;
public string VersionText
{
get { return _versionText; }
set
{
if (value == _versionText) return;
_versionText = value;
NotifyOfPropertyChange(() => VersionText);
}
}
private void SetVersionText()
{
if (!SettingsProvider.Load<GeneralSettings>().EnablePointersUpdate)
{
VersionText = "You disabled pointer updates, this could result in the Terraria module not working after a game update.";
return;
}
Updater.GetPointers();
var version = SettingsProvider.Load<OffsetSettings>().Terraria?.GameVersion;
VersionText = $"Requires patch {version}. When a new patch is released Artemis downloads new pointers for the latest version (unless disabled in settings).";
}
}
}

View File

@ -11,6 +11,7 @@ using Artemis.Events;
using Artemis.Managers;
using Artemis.Modules.Abstract;
using Artemis.Utilities;
using Artemis.Utilities.ActiveWindowDetection;
using CSCore.CoreAudioAPI;
using Newtonsoft.Json;
using SpotifyAPI.Local;

View File

@ -1,12 +1,6 @@
<UserControl x:Class="Artemis.Modules.General.GeneralProfile.GeneralProfileView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:cal="http://www.caliburnproject.org"
xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
mc:Ignorable="d"
d:DesignHeight="476.986" d:DesignWidth="538.772">
<UserControl x:Class="Artemis.Modules.General.GeneralProfile.GeneralProfileView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:cal="http://www.caliburnproject.org" xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls" mc:Ignorable="d" d:DesignHeight="476.986" d:DesignWidth="538.772">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />

View File

@ -63,9 +63,15 @@ namespace Artemis.Profiles.Layers.Models
switch (ToggleType)
{
case ToggleType.Enable:
// Apply RenderAllowed only if this is the first keybind
if (index == 0)
layerModel.RenderAllowed = false;
action = () => layerModel.RenderAllowed = true;
break;
case ToggleType.Disable:
// Apply RenderAllowed only if this is the first keybind
if (index == 0)
layerModel.RenderAllowed = false;
action = () => layerModel.RenderAllowed = false;
break;
case ToggleType.Toggle:

View File

@ -1,261 +1,261 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Media;
using Artemis.Modules.Abstract;
using Artemis.Profiles.Layers.Abstract;
using Artemis.Profiles.Layers.Animations;
using Artemis.Profiles.Layers.Conditions;
using Artemis.Profiles.Layers.Interfaces;
using Artemis.Profiles.Layers.Types.Keyboard;
using Artemis.Utilities;
using Artemis.Utilities.ParentChild;
using Newtonsoft.Json;
namespace Artemis.Profiles.Layers.Models
{
public class LayerModel : IChildItem<LayerModel>, IChildItem<ProfileModel>
{
public LayerModel()
{
Children = new ChildItemCollection<LayerModel, LayerModel>(this);
TweenModel = new TweenModel(this);
RenderAllowed = true;
var model = Properties as KeyboardPropertiesModel;
if (model != null)
GifImage = new GifImage(model.GifFile, Properties.AnimationSpeed);
}
[JsonIgnore]
public ImageSource LayerImage => LayerType.DrawThumbnail(this);
[JsonIgnore]
public TweenModel TweenModel { get; set; }
/// <summary>
/// Checks whether this layers conditions are met.
/// If they are met and this layer is an event, this also triggers that event.
/// </summary>
/// <param name="dataModel"></param>
/// <returns></returns>
public bool AreConditionsMet(ModuleDataModel dataModel)
{
// Conditions are not even checked if the layer isn't enabled
return Enabled && LayerCondition.ConditionsMet(this, dataModel);
}
/// <summary>
/// Update the layer
/// </summary>
/// <param name="dataModel"></param>
/// <param name="preview"></param>
/// <param name="updateAnimations"></param>
public void Update(ModuleDataModel dataModel, bool preview, bool updateAnimations)
{
if (LayerType == null)
return;
LayerType.Update(this, dataModel, preview);
LayerAnimation?.Update(this, updateAnimations);
if (!preview)
TweenModel.Update();
LastRender = DateTime.Now;
}
/// <summary>
/// Applies the saved properties to the current properties
/// </summary>
/// <param name="advanced">Include advanced properties (opacity, brush)</param>
public void ApplyProperties(bool advanced)
{
X = Properties.X;
Y = Properties.Y;
Width = Properties.Width;
Height = Properties.Height;
if (!advanced)
return;
Opacity = Properties.Opacity;
Brush = Properties.Brush;
}
/// <summary>
/// Draw the layer using the provided context
/// </summary>
/// <param name="dataModel"></param>
/// <param name="c"></param>
/// <param name="preview"></param>
/// <param name="updateAnimations"></param>
public void Draw(ModuleDataModel dataModel, DrawingContext c, bool preview, bool updateAnimations)
{
if (Brush == null || !preview && !RenderAllowed)
return;
LayerType.Draw(this, c);
}
/// <summary>
/// Tells the current layer type to setup the layer's LayerProperties
/// </summary>
public void SetupProperties()
{
LayerType.SetupProperties(this);
// If the type is an event, set it up
if (IsEvent && EventProperties == null)
EventProperties = new KeyboardEventPropertiesModel
{
ExpirationType = ExpirationType.Time,
Length = new TimeSpan(0, 0, 1),
TriggerDelay = new TimeSpan(0)
};
}
/// <summary>
/// Ensures all child layers have a unique order
/// </summary>
public void FixOrder()
{
Children.Sort(l => l.Order);
for (var i = 0; i < Children.Count; i++)
Children[i].Order = i;
}
/// <summary>
/// Returns whether the layer meets the requirements to be drawn in the profile editor
/// </summary>
/// <returns></returns>
public bool MustDraw()
{
// If any of the parents are disabled, this layer must not be drawn
var parent = Parent;
while (parent != null)
{
if (!parent.Enabled)
return false;
parent = parent.Parent;
}
return Enabled && LayerType.ShowInEdtor;
}
/// <summary>
/// Returns every descendant of this layer
/// </summary>
/// <returns></returns>
public IEnumerable<LayerModel> GetLayers()
{
var layers = new List<LayerModel>();
foreach (var layerModel in Children.OrderBy(c => c.Order))
{
layers.Add(layerModel);
layers.AddRange(layerModel.GetLayers());
}
return layers;
}
/// <summary>
/// Creates a new Keyboard layer with default settings
/// </summary>
/// <returns></returns>
public static LayerModel CreateLayer()
{
return new LayerModel
{
Name = "New layer",
Enabled = true,
Order = -1,
LayerType = new KeyboardType(),
LayerCondition = new DataModelCondition(),
LayerAnimation = new NoneAnimation(),
Properties = new KeyboardPropertiesModel
{
Brush = new SolidColorBrush(ColorHelpers.GetRandomRainbowMediaColor()),
Height = 1,
Width = 1,
X = 0,
Y = 0,
Opacity = 1,
HeightEaseTime = 0,
HeightEase = "Linear",
WidthEaseTime = 0,
WidthEase = "Linear",
OpacityEaseTime = 0,
OpacityEase = "Linear"
}
};
}
/// <summary>
/// Insert this layer before the given layer
/// </summary>
/// <param name="source"></param>
public void InsertBefore(LayerModel source)
{
source.Order = Order;
Insert(source);
}
/// <summary>
/// Insert this layer after the given layer
/// </summary>
/// <param name="source"></param>
public void InsertAfter(LayerModel source)
{
source.Order = Order + 1;
Insert(source);
}
/// <summary>
/// Insert the layer as a sibling
/// </summary>
/// <param name="source"></param>
private void Insert(LayerModel source)
{
if (Parent != null)
{
foreach (var child in Parent.Children.OrderBy(c => c.Order))
if (child.Order >= source.Order)
child.Order++;
Parent.Children.Add(source);
}
else if (Profile != null)
{
foreach (var layer in Profile.Layers.OrderBy(l => l.Order))
if (layer.Order >= source.Order)
layer.Order++;
Profile.Layers.Add(source);
}
}
public Rect LayerRect(int scale = 4)
{
var width = Width;
var height = Height;
if (width < 0)
width = 0;
if (height < 0)
height = 0;
return new Rect(X * scale, Y * scale, width * scale, height * scale);
}
// TODO: Make this and ProfileModel's GetRenderLayers the same through inheritance
/// <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>
/// <param name="dataModel">Instance of said game data model</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(ModuleDataModel dataModel, bool keyboardOnly, bool ignoreConditions = false)
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Media;
using Artemis.Modules.Abstract;
using Artemis.Profiles.Layers.Abstract;
using Artemis.Profiles.Layers.Animations;
using Artemis.Profiles.Layers.Conditions;
using Artemis.Profiles.Layers.Interfaces;
using Artemis.Profiles.Layers.Types.Keyboard;
using Artemis.Utilities;
using Artemis.Utilities.ParentChild;
using Newtonsoft.Json;
namespace Artemis.Profiles.Layers.Models
{
public class LayerModel : IChildItem<LayerModel>, IChildItem<ProfileModel>
{
public LayerModel()
{
Children = new ChildItemCollection<LayerModel, LayerModel>(this);
TweenModel = new TweenModel(this);
RenderAllowed = true;
var model = Properties as KeyboardPropertiesModel;
if (model != null)
GifImage = new GifImage(model.GifFile, Properties.AnimationSpeed);
}
[JsonIgnore]
public ImageSource LayerImage => LayerType.DrawThumbnail(this);
[JsonIgnore]
public TweenModel TweenModel { get; set; }
/// <summary>
/// Checks whether this layers conditions are met.
/// If they are met and this layer is an event, this also triggers that event.
/// </summary>
/// <param name="dataModel"></param>
/// <returns></returns>
public bool AreConditionsMet(ModuleDataModel dataModel)
{
// Conditions are not even checked if the layer isn't enabled
return Enabled && LayerCondition.ConditionsMet(this, dataModel);
}
/// <summary>
/// Update the layer
/// </summary>
/// <param name="dataModel"></param>
/// <param name="preview"></param>
/// <param name="updateAnimations"></param>
public void Update(ModuleDataModel dataModel, bool preview, bool updateAnimations)
{
if (LayerType == null)
return;
LayerType.Update(this, dataModel, preview);
LayerAnimation?.Update(this, updateAnimations);
if (!preview)
TweenModel.Update();
LastRender = DateTime.Now;
}
/// <summary>
/// Applies the saved properties to the current properties
/// </summary>
/// <param name="advanced">Include advanced properties (opacity, brush)</param>
public void ApplyProperties(bool advanced)
{
X = Properties.X;
Y = Properties.Y;
Width = Properties.Width;
Height = Properties.Height;
if (!advanced)
return;
Opacity = Properties.Opacity;
Brush = Properties.Brush;
}
/// <summary>
/// Draw the layer using the provided context
/// </summary>
/// <param name="dataModel"></param>
/// <param name="c"></param>
/// <param name="preview"></param>
/// <param name="updateAnimations"></param>
public void Draw(ModuleDataModel dataModel, DrawingContext c, bool preview, bool updateAnimations)
{
if (Brush == null || !preview && !RenderAllowed)
return;
LayerType.Draw(this, c);
}
/// <summary>
/// Tells the current layer type to setup the layer's LayerProperties
/// </summary>
public void SetupProperties()
{
LayerType.SetupProperties(this);
// If the type is an event, set it up
if (IsEvent && EventProperties == null)
EventProperties = new KeyboardEventPropertiesModel
{
ExpirationType = ExpirationType.Time,
Length = new TimeSpan(0, 0, 1),
TriggerDelay = new TimeSpan(0)
};
}
/// <summary>
/// Ensures all child layers have a unique order
/// </summary>
public void FixOrder()
{
Children.Sort(l => l.Order);
for (var i = 0; i < Children.Count; i++)
Children[i].Order = i;
}
/// <summary>
/// Returns whether the layer meets the requirements to be drawn in the profile editor
/// </summary>
/// <returns></returns>
public bool MustDraw()
{
// If any of the parents are disabled, this layer must not be drawn
var parent = Parent;
while (parent != null)
{
if (!parent.Enabled)
return false;
parent = parent.Parent;
}
return Enabled && LayerType.ShowInEdtor;
}
/// <summary>
/// Returns every descendant of this layer
/// </summary>
/// <returns></returns>
public IEnumerable<LayerModel> GetLayers()
{
var layers = new List<LayerModel>();
foreach (var layerModel in Children.OrderBy(c => c.Order))
{
layers.Add(layerModel);
layers.AddRange(layerModel.GetLayers());
}
return layers;
}
/// <summary>
/// Creates a new Keyboard layer with default settings
/// </summary>
/// <returns></returns>
public static LayerModel CreateLayer()
{
return new LayerModel
{
Name = "New layer",
Enabled = true,
Order = -1,
LayerType = new KeyboardType(),
LayerCondition = new DataModelCondition(),
LayerAnimation = new NoneAnimation(),
Properties = new KeyboardPropertiesModel
{
Brush = new SolidColorBrush(ColorHelpers.GetRandomRainbowMediaColor()),
Height = 1,
Width = 1,
X = 0,
Y = 0,
Opacity = 1,
HeightEaseTime = 0,
HeightEase = "Linear",
WidthEaseTime = 0,
WidthEase = "Linear",
OpacityEaseTime = 0,
OpacityEase = "Linear"
}
};
}
/// <summary>
/// Insert this layer before the given layer
/// </summary>
/// <param name="source"></param>
public void InsertBefore(LayerModel source)
{
source.Order = Order;
Insert(source);
}
/// <summary>
/// Insert this layer after the given layer
/// </summary>
/// <param name="source"></param>
public void InsertAfter(LayerModel source)
{
source.Order = Order + 1;
Insert(source);
}
/// <summary>
/// Insert the layer as a sibling
/// </summary>
/// <param name="source"></param>
private void Insert(LayerModel source)
{
if (Parent != null)
{
foreach (var child in Parent.Children.OrderBy(c => c.Order))
if (child.Order >= source.Order)
child.Order++;
Parent.Children.Add(source);
}
else if (Profile != null)
{
foreach (var layer in Profile.Layers.OrderBy(l => l.Order))
if (layer.Order >= source.Order)
layer.Order++;
Profile.Layers.Add(source);
}
}
public Rect LayerRect(int scale = 4)
{
var width = Width;
var height = Height;
if (width < 0)
width = 0;
if (height < 0)
height = 0;
return new Rect(X * scale, Y * scale, width * scale, height * scale);
}
// TODO: Make this and ProfileModel's GetRenderLayers the same through inheritance
/// <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>
/// <param name="dataModel">Instance of said game data model</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(ModuleDataModel dataModel, bool keyboardOnly, bool ignoreConditions = false)
{
var layers = new List<LayerModel>();
foreach (var layerModel in Children.OrderByDescending(l => l.Order))
{
@ -272,149 +272,149 @@ namespace Artemis.Profiles.Layers.Models
layers.AddRange(layerModel.GetRenderLayers(dataModel, keyboardOnly, ignoreConditions));
}
return layers;
}
public void SetupCondition()
{
if (IsEvent && !(LayerCondition is EventCondition))
LayerCondition = new EventCondition();
else if (!IsEvent && !(LayerCondition is DataModelCondition))
LayerCondition = new DataModelCondition();
}
public void SetupKeybinds()
{
RenderAllowed = true;
// Clean up old keybinds
RemoveKeybinds();
for (var index = 0; index < Properties.LayerKeybindModels.Count; index++)
{
var keybindModel = Properties.LayerKeybindModels[index];
keybindModel.Register(this, index);
}
}
public void RemoveKeybinds()
{
foreach (var keybindModel in Properties.LayerKeybindModels)
keybindModel.Unregister();
}
#region Properties
#region Layer type properties
public ILayerType LayerType { get; set; }
public ILayerCondition LayerCondition { get; set; }
public ILayerAnimation LayerAnimation { get; set; }
#endregion
#region Generic properties
public string Name { get; set; }
public int Order { get; set; }
public bool Enabled { get; set; }
public bool RenderAllowed { get; set; }
public bool Expanded { get; set; }
public bool IsEvent { get; set; }
public LayerPropertiesModel Properties { get; set; }
public EventPropertiesModel EventProperties { get; set; }
#endregion
#region Relational properties
public ChildItemCollection<LayerModel, LayerModel> Children { get; }
[JsonIgnore]
public LayerModel Parent { get; internal set; }
[JsonIgnore]
public ProfileModel Profile { get; internal set; }
#endregion
#region Render properties
[JsonIgnore] private Brush _brush;
[JsonIgnore]
public double X { get; set; }
[JsonIgnore]
public double Y { get; set; }
[JsonIgnore]
public double Width { get; set; }
[JsonIgnore]
public double Height { get; set; }
[JsonIgnore]
public double Opacity { get; set; }
[JsonIgnore]
public Brush Brush
{
get { return _brush; }
set
{
if (value == null)
{
_brush = null;
return;
}
if (value.IsFrozen)
{
_brush = value;
return;
}
// Clone the brush off of the UI thread and freeze it
var cloned = value.Dispatcher.Invoke(value.CloneCurrentValue);
cloned.Freeze();
_brush = cloned;
}
}
[JsonIgnore]
public double AnimationProgress { get; set; }
[JsonIgnore]
public GifImage GifImage { get; set; }
[JsonIgnore]
public DateTime LastRender { get; set; }
#endregion
#endregion
#region IChildItem<Parent> Members
LayerModel IChildItem<LayerModel>.Parent
{
get { return Parent; }
set { Parent = value; }
}
ProfileModel IChildItem<ProfileModel>.Parent
{
get { return Profile; }
set { Profile = value; }
}
#endregion
/// <inheritdoc />
public override string ToString()
{
return $"{nameof(Name)}: {Name}, {nameof(Order)}: {Order}, {nameof(X)}: {X}, {nameof(Y)}: {Y}, {nameof(Width)}: {Width}, {nameof(Height)}: {Height}";
}
}
}
return layers;
}
public void SetupCondition()
{
if (IsEvent && !(LayerCondition is EventCondition))
LayerCondition = new EventCondition();
else if (!IsEvent && !(LayerCondition is DataModelCondition))
LayerCondition = new DataModelCondition();
}
public void SetupKeybinds()
{
RenderAllowed = true;
// Clean up old keybinds
RemoveKeybinds();
for (var index = 0; index < Properties.LayerKeybindModels.Count; index++)
{
var keybindModel = Properties.LayerKeybindModels[index];
keybindModel.Register(this, index);
}
}
public void RemoveKeybinds()
{
foreach (var keybindModel in Properties.LayerKeybindModels)
keybindModel.Unregister();
}
#region Properties
#region Layer type properties
public ILayerType LayerType { get; set; }
public ILayerCondition LayerCondition { get; set; }
public ILayerAnimation LayerAnimation { get; set; }
#endregion
#region Generic properties
public string Name { get; set; }
public int Order { get; set; }
public bool Enabled { get; set; }
public bool RenderAllowed { get; set; }
public bool Expanded { get; set; }
public bool IsEvent { get; set; }
public LayerPropertiesModel Properties { get; set; }
public EventPropertiesModel EventProperties { get; set; }
#endregion
#region Relational properties
public ChildItemCollection<LayerModel, LayerModel> Children { get; }
[JsonIgnore]
public LayerModel Parent { get; internal set; }
[JsonIgnore]
public ProfileModel Profile { get; internal set; }
#endregion
#region Render properties
[JsonIgnore] private Brush _brush;
[JsonIgnore]
public double X { get; set; }
[JsonIgnore]
public double Y { get; set; }
[JsonIgnore]
public double Width { get; set; }
[JsonIgnore]
public double Height { get; set; }
[JsonIgnore]
public double Opacity { get; set; }
[JsonIgnore]
public Brush Brush
{
get { return _brush; }
set
{
if (value == null)
{
_brush = null;
return;
}
if (value.IsFrozen)
{
_brush = value;
return;
}
// Clone the brush off of the UI thread and freeze it
var cloned = value.Dispatcher.Invoke(value.CloneCurrentValue);
cloned.Freeze();
_brush = cloned;
}
}
[JsonIgnore]
public double AnimationProgress { get; set; }
[JsonIgnore]
public GifImage GifImage { get; set; }
[JsonIgnore]
public DateTime LastRender { get; set; }
#endregion
#endregion
#region IChildItem<Parent> Members
LayerModel IChildItem<LayerModel>.Parent
{
get { return Parent; }
set { Parent = value; }
}
ProfileModel IChildItem<ProfileModel>.Parent
{
get { return Profile; }
set { Profile = value; }
}
#endregion
/// <inheritdoc />
public override string ToString()
{
return $"{nameof(Name)}: {Name}, {nameof(Order)}: {Order}, {nameof(X)}: {X}, {nameof(Y)}: {Y}, {nameof(Width)}: {Width}, {nameof(Height)}: {Height}";
}
}
}

View File

@ -1,95 +1,95 @@
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;
using System.Windows.Media;
using Artemis.Utilities.Converters;
using Newtonsoft.Json;
namespace Artemis.Profiles.Layers.Models
{
public abstract class LayerPropertiesModel
{
private Brush _brush;
public LayerPropertiesModel(LayerPropertiesModel source = null)
{
if (source == null)
return;
// Clone the source's properties onto the new properties model (useful when changing property type)
X = source.X;
Y = source.Y;
Width = source.Width;
Height = source.Height;
Contain = source.Contain;
Opacity = source.Opacity;
AnimationSpeed = source.AnimationSpeed;
Conditions = source.Conditions;
LayerKeybindModels = source.LayerKeybindModels;
ConditionType = source.ConditionType;
DynamicProperties = source.DynamicProperties;
Brush = source.Brush;
HeightEase = source.HeightEase;
WidthEase = source.WidthEase;
OpacityEase = source.OpacityEase;
HeightEaseTime = source.HeightEaseTime;
WidthEaseTime = source.WidthEaseTime;
OpacityEaseTime = source.OpacityEaseTime;
}
public double X { get; set; }
public double Y { get; set; }
public double Width { get; set; }
public double Height { get; set; }
public bool Contain { get; set; }
public double Opacity { get; set; }
public double AnimationSpeed { get; set; }
public double OpacityEaseTime { get; set; }
public double HeightEaseTime { get; set; }
public double WidthEaseTime { get; set; }
public string WidthEase { set; get; }
public string HeightEase { get; set; }
public string OpacityEase { get; set; }
public ConditionType ConditionType { get; set; }
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;
using System.Windows.Media;
using Artemis.Utilities.Converters;
using Newtonsoft.Json;
namespace Artemis.Profiles.Layers.Models
{
public abstract class LayerPropertiesModel
{
private Brush _brush;
public LayerPropertiesModel(LayerPropertiesModel source = null)
{
if (source == null)
return;
// Clone the source's properties onto the new properties model (useful when changing property type)
X = source.X;
Y = source.Y;
Width = source.Width;
Height = source.Height;
Contain = source.Contain;
Opacity = source.Opacity;
AnimationSpeed = source.AnimationSpeed;
Conditions = source.Conditions;
LayerKeybindModels = source.LayerKeybindModels;
ConditionType = source.ConditionType;
DynamicProperties = source.DynamicProperties;
Brush = source.Brush;
HeightEase = source.HeightEase;
WidthEase = source.WidthEase;
OpacityEase = source.OpacityEase;
HeightEaseTime = source.HeightEaseTime;
WidthEaseTime = source.WidthEaseTime;
OpacityEaseTime = source.OpacityEaseTime;
}
public double X { get; set; }
public double Y { get; set; }
public double Width { get; set; }
public double Height { get; set; }
public bool Contain { get; set; }
public double Opacity { get; set; }
public double AnimationSpeed { get; set; }
public double OpacityEaseTime { get; set; }
public double HeightEaseTime { get; set; }
public double WidthEaseTime { get; set; }
public string WidthEase { set; get; }
public string HeightEase { get; set; }
public string OpacityEase { get; set; }
public ConditionType ConditionType { get; set; }
public List<LayerConditionModel> Conditions { get; set; } = new List<LayerConditionModel>();
public List<LayerKeybindModel> LayerKeybindModels { get; set; } = new List<LayerKeybindModel>();
public List<DynamicPropertiesModel> DynamicProperties { get; set; } = new List<DynamicPropertiesModel>();
[JsonConverter(typeof(BrushJsonConverter))]
public Brush Brush
{
get { return _brush; }
set
{
if (value == null)
{
_brush = null;
return;
}
if (value.IsFrozen)
{
_brush = value;
return;
}
// Clone the brush off of the UI thread and freeze it
var cloned = value.Dispatcher.Invoke(value.CloneCurrentValue);
cloned.Freeze();
_brush = cloned;
}
}
public Rect PropertiesRect(int scale = 4)
{
return new Rect(X*scale, Y*scale, Width*scale, Height*scale);
}
}
public enum ConditionType
{
[Description("All met")] AllMet,
[Description("Any met")] AnyMet,
[Description("None met")] NoneMet
}
public List<LayerKeybindModel> LayerKeybindModels { get; set; } = new List<LayerKeybindModel>();
public List<DynamicPropertiesModel> DynamicProperties { get; set; } = new List<DynamicPropertiesModel>();
[JsonConverter(typeof(BrushJsonConverter))]
public Brush Brush
{
get { return _brush; }
set
{
if (value == null)
{
_brush = null;
return;
}
if (value.IsFrozen)
{
_brush = value;
return;
}
// Clone the brush off of the UI thread and freeze it
var cloned = value.Dispatcher.Invoke(value.CloneCurrentValue);
cloned.Freeze();
_brush = cloned;
}
}
public Rect PropertiesRect(int scale = 4)
{
return new Rect(X*scale, Y*scale, Width*scale, Height*scale);
}
}
public enum ConditionType
{
[Description("All met")] AllMet,
[Description("Any met")] AnyMet,
[Description("None met")] NoneMet
}
}

View File

@ -2,6 +2,7 @@
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Windows.Media;
using Microsoft.Win32;
using SharpDX.Direct3D9;
namespace Artemis.Profiles.Layers.Types.AmbientLight.ScreenCapturing
@ -15,6 +16,14 @@ namespace Artemis.Profiles.Layers.Types.AmbientLight.ScreenCapturing
Width = Screen.PrimaryScreen.Bounds.Width;
Height = Screen.PrimaryScreen.Bounds.Height;
//DarthAffe 08.04.2017: Fix for systems using windows-scaling. The primary screen size is reported 'wrong'.
double scaling = GetScaling();
if (Math.Abs(scaling - 1.0) > 0.01)
{
Width = (int)(Width / scaling);
Height = (int)(Height / scaling);
}
var presentParams = new PresentParameters(Width, Height)
{
Windowed = true,
@ -24,7 +33,7 @@ namespace Artemis.Profiles.Layers.Types.AmbientLight.ScreenCapturing
_device = new Device(new Direct3D(), 0, DeviceType.Hardware, IntPtr.Zero,
CreateFlags.SoftwareVertexProcessing, presentParams);
_surface = Surface.CreateOffscreenPlain(_device, Width, Height, Format.A8R8G8B8, Pool.Scratch);
_buffer = new byte[Width*Height*4];
_buffer = new byte[Width * Height * 4];
}
#endregion
@ -43,6 +52,19 @@ namespace Artemis.Profiles.Layers.Types.AmbientLight.ScreenCapturing
#region Methods
private double GetScaling()
{
try
{
int currentDpi = (int)Registry.GetValue("HKEY_CURRENT_USER\\Control Panel\\Desktop", "LogPixels", 96);
return 96.0 / currentDpi;
}
catch
{
return 1.0;
}
}
public byte[] CaptureScreen()
{
_device.GetFrontBufferData(0, _surface);

View File

@ -97,18 +97,23 @@ namespace Artemis.Profiles.Layers.Types.Audio.AudioCapturing
}
}
private LineSpectrum _lineSpectrum;
public LineSpectrum GetLineSpectrum(int barCount, ScalingStrategy scalingStrategy)
{
if (_spectrumProvider == null)
if (_spectrumProvider == null || barCount <= 0)
return null;
return new LineSpectrum(FftSize)
{
SpectrumProvider = _spectrumProvider,
UseAverage = true,
BarCount = barCount,
IsXLogScale = true,
ScalingStrategy = scalingStrategy
};
if (_lineSpectrum == null)
_lineSpectrum = new LineSpectrum(FftSize)
{
SpectrumProvider = _spectrumProvider,
UseAverage = true,
BarCount = barCount,
IsXLogScale = true,
ScalingStrategy = scalingStrategy
};
return _lineSpectrum;
}
/// <summary>
@ -148,13 +153,13 @@ namespace Artemis.Profiles.Layers.Types.Audio.AudioCapturing
if (Type == MmDeviceType.Input)
{
_soundIn = Device != null
? new WasapiCapture {Device = Device}
? new WasapiCapture { Device = Device }
: new WasapiCapture();
}
else
{
_soundIn = Device != null
? new WasapiLoopbackCapture {Device = Device}
? new WasapiLoopbackCapture { Device = Device }
: new WasapiLoopbackCapture();
}
@ -182,6 +187,7 @@ namespace Artemis.Profiles.Layers.Types.Audio.AudioCapturing
}
};
_lineSpectrum = null;
_singleSpectrum = new SingleSpectrum(FftSize, _spectrumProvider);
_mayStop = false;

View File

@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Media;
@ -26,6 +27,7 @@ namespace Artemis.Profiles.Layers.Types.Audio
private List<double> _lineValues;
private AudioPropertiesModel _properties;
private bool _subscribed;
private DateTime _lastRender;
public AudioType(AudioCaptureManager audioCaptureManager)
{
@ -123,8 +125,7 @@ namespace Artemis.Profiles.Layers.Types.Audio
SubscribeToAudioChange();
if (_audioCapture == null || newProperties.Device != _properties.Device ||
newProperties.DeviceType != _properties.DeviceType)
if (_audioCapture == null || newProperties.Device != _properties.Device || newProperties.DeviceType != _properties.DeviceType)
{
var device = GetMmDevice();
if (device != null)
@ -153,17 +154,19 @@ namespace Artemis.Profiles.Layers.Types.Audio
currentHeight = layerModel.Width;
}
if (_lines != currentLines || _lineSpectrum == null)
// Get a new line spectrum if the lines changed, it is null or the layer hasn't rendered for a few frames
if (_lines != currentLines || _lineSpectrum == null || DateTime.Now - _lastRender > TimeSpan.FromMilliseconds(100))
{
_lines = currentLines;
_lineSpectrum = _audioCapture.GetLineSpectrum(_lines, ScalingStrategy.Decibel);
if (_lineSpectrum == null)
return;
}
var newLineValues = _lineSpectrum?.GetLineValues(currentHeight);
var newLineValues = _audioCapture.GetLineSpectrum(_lines, ScalingStrategy.Decibel)?.GetLineValues(currentHeight);
if (newLineValues != null)
{
_lineValues = newLineValues;
_lastRender = DateTime.Now;
}
}
public void SetupProperties(LayerModel layerModel)

View File

@ -0,0 +1,25 @@
using Artemis.Managers;
using MoonSharp.Interpreter;
namespace Artemis.Profiles.Lua.Modules.Gui
{
public class EditorButton
{
private readonly LuaManager _luaManager;
public EditorButton(LuaManager luaManager, string text, DynValue action)
{
_luaManager = luaManager;
Text = text;
Action = action;
}
public void Invoke()
{
_luaManager.Call(Action);
}
public string Text { get; }
public DynValue Action { get; }
}
}

View File

@ -0,0 +1,49 @@
using System;
using System.Windows;
using System.Windows.Controls;
using Artemis.Managers;
using MoonSharp.Interpreter;
using MoonSharp.Interpreter.Interop;
namespace Artemis.Profiles.Lua.Modules.Gui
{
[MoonSharpUserData]
public class LuaButton
{
private readonly LuaManager _luaManager;
public LuaButton(LuaManager luaManager, string text, double x, double y, double? width, double? height)
{
_luaManager = luaManager;
Button = new Button {Content = text};
if (width != null)
Button.Width = width.Value;
if (height != null)
Button.Height = height.Value;
Button.Click += ButtonOnClick;
}
[MoonSharpVisible(false)]
public Button Button { get; }
public string Text
{
get => Button.Dispatcher.Invoke(() => (string) Button.Content);
set => Button.Dispatcher.Invoke(() => Button.Content = value);
}
private void ButtonOnClick(object sender, RoutedEventArgs routedEventArgs)
{
_luaManager.EventsModule.LuaInvoke(_luaManager.ProfileModel, () => OnClick(this));
}
public event EventHandler<EventArgs> Click;
protected virtual void OnClick(LuaButton button)
{
Click?.Invoke(button, null);
}
}
}

View File

@ -0,0 +1,55 @@
using System;
using System.Windows;
using System.Windows.Controls;
using Artemis.Managers;
using MoonSharp.Interpreter;
using MoonSharp.Interpreter.Interop;
namespace Artemis.Profiles.Lua.Modules.Gui
{
[MoonSharpUserData]
public class LuaCheckBox
{
private readonly LuaManager _luaManager;
public LuaCheckBox(LuaManager luaManager, string text, bool isChecked, double x, double y, double? width, double? height)
{
_luaManager = luaManager;
CheckBox = new CheckBox {Content = text, IsChecked = isChecked};
if (width != null)
CheckBox.Width = width.Value;
if (height != null)
CheckBox.Height = height.Value;
CheckBox.Click += CheckBoxOnClick;
}
[MoonSharpVisible(false)]
public CheckBox CheckBox { get; }
public string Text
{
get => CheckBox.Dispatcher.Invoke(() => (string) CheckBox.Content);
set => CheckBox.Dispatcher.Invoke(() => CheckBox.Content = value);
}
public bool IsChecked
{
get => CheckBox.Dispatcher.Invoke(() => CheckBox.IsChecked != null && (bool) CheckBox.IsChecked);
set => CheckBox.Dispatcher.Invoke(() => CheckBox.IsChecked = value);
}
private void CheckBoxOnClick(object sender, RoutedEventArgs routedEventArgs)
{
_luaManager.EventsModule.LuaInvoke(_luaManager.ProfileModel, () => OnClick(this));
}
public event EventHandler<EventArgs> Click;
protected virtual void OnClick(LuaCheckBox checkBox)
{
Click?.Invoke(checkBox, null);
}
}
}

View File

@ -0,0 +1,70 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows.Controls;
using Artemis.Managers;
using MoonSharp.Interpreter;
using MoonSharp.Interpreter.Interop;
namespace Artemis.Profiles.Lua.Modules.Gui
{
[MoonSharpUserData]
public class LuaComboBox
{
private readonly LuaManager _luaManager;
public LuaComboBox(LuaManager luaManager, string value, List<string> values, double x, double y, double? width, double? height)
{
_luaManager = luaManager;
ComboBox = new ComboBox {ItemsSource = new ObservableCollection<string>(values), SelectedItem = value};
if (width != null)
ComboBox.Width = (double) width;
if (height != null)
ComboBox.Height = (double) height;
ComboBox.SelectionChanged += ComboBoxOnSelectionChanged;
}
[MoonSharpVisible(false)]
public ComboBox ComboBox { get; }
public string Value
{
get => ComboBox.Dispatcher.Invoke(() => (string) ComboBox.SelectedItem);
set => ComboBox.Dispatcher.Invoke(() => ComboBox.SelectedItem = value);
}
public void SetValues(string[] values)
{
var collection = (ObservableCollection<string>) ComboBox.ItemsSource;
collection.Clear();
foreach (var value in values)
collection.Add(value);
}
public void AddValue(string value)
{
((ObservableCollection<string>) ComboBox.ItemsSource).Add(value);
}
public void RemoveValue(string value)
{
var collection = (ObservableCollection<string>) ComboBox.ItemsSource;
if (collection.Contains(value))
collection.Remove(value);
}
private void ComboBoxOnSelectionChanged(object sender, SelectionChangedEventArgs selectionChangedEventArgs)
{
_luaManager.EventsModule.LuaInvoke(_luaManager.ProfileModel, () => OnSelectionChanged(this));
}
public event EventHandler<EventArgs> SelectionChanged;
protected virtual void OnSelectionChanged(LuaComboBox comboBox)
{
SelectionChanged?.Invoke(comboBox, null);
}
}
}

View File

@ -0,0 +1,30 @@
using System.Windows;
using System.Windows.Controls;
using MoonSharp.Interpreter;
using MoonSharp.Interpreter.Interop;
namespace Artemis.Profiles.Lua.Modules.Gui
{
[MoonSharpUserData]
public class LuaLabel
{
public LuaLabel(string text, double x, double y, double fontSize = 12, int fontWeight = 400)
{
Label = new Label
{
Content = text,
FontSize = fontSize,
FontWeight = FontWeight.FromOpenTypeWeight(fontWeight)
};
}
[MoonSharpVisible(false)]
public Label Label { get; }
public string Text
{
get => Label.Dispatcher.Invoke(() => (string) Label.Content);
set => Label.Dispatcher.Invoke(() => Label.Content = value);
}
}
}

View File

@ -0,0 +1,48 @@
using System;
using System.Windows.Controls;
using Artemis.Managers;
using MoonSharp.Interpreter;
using MoonSharp.Interpreter.Interop;
namespace Artemis.Profiles.Lua.Modules.Gui
{
[MoonSharpUserData]
public class LuaTextBox
{
private readonly LuaManager _luaManager;
public LuaTextBox(LuaManager luaManager, string text, double x, double y, double? width, double? height)
{
_luaManager = luaManager;
TextBox = new TextBox {Text = text};
if (width != null)
TextBox.Width = width.Value;
if (height != null)
TextBox.Height = height.Value;
TextBox.TextChanged += TextBoxOnTextChanged;
}
[MoonSharpVisible(false)]
public TextBox TextBox { get; }
public string Text
{
get => TextBox.Dispatcher.Invoke(() => TextBox.Text);
set => TextBox.Dispatcher.Invoke(() => TextBox.Text = value);
}
private void TextBoxOnTextChanged(object sender, TextChangedEventArgs textChangedEventArgs)
{
_luaManager.EventsModule.LuaInvoke(_luaManager.ProfileModel, () => OnTextChanged(this));
}
public event EventHandler<EventArgs> TextChanged;
protected virtual void OnTextChanged(LuaTextBox button)
{
TextChanged?.Invoke(button, null);
}
}
}

View File

@ -0,0 +1,8 @@
<controls:MetroWindow x:Class="Artemis.Profiles.Lua.Modules.Gui.LuaWindowView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:Artemis.Profiles.Lua.Modules.Gui"
xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls" mc:Ignorable="d" Title="LuaWindowView" Height="300" Width="300" WindowStartupLocation="CenterScreen"
GlowBrush="{DynamicResource AccentColorBrush}">
<Grid>
<ItemsControl ItemsSource="{Binding Path=Content}" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto" />
</Grid>
</controls:MetroWindow>

View File

@ -0,0 +1,15 @@
using MahApps.Metro.Controls;
namespace Artemis.Profiles.Lua.Modules.Gui
{
/// <summary>
/// Interaction logic for LuaWindowView.xaml
/// </summary>
public partial class LuaWindowView : MetroWindow
{
public LuaWindowView()
{
InitializeComponent();
}
}
}

View File

@ -0,0 +1,93 @@
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using Artemis.Managers;
using Caliburn.Micro;
using MoonSharp.Interpreter;
namespace Artemis.Profiles.Lua.Modules.Gui
{
[MoonSharpUserData]
public class LuaWindowViewModel : Screen
{
private readonly LuaManager _luaManager;
public LuaWindowViewModel(LuaManager luaManager)
{
_luaManager = luaManager;
Canvas = new Canvas();
Content = new List<UIElement> {Canvas};
}
public Canvas Canvas { get; set; }
public List<UIElement> Content { get; set; }
public LuaLabel CreateLabel(string text, double x, double y, double fontSize = 12, int fontWeight = 400)
{
LuaLabel element = null;
Execute.OnUIThread(() =>
{
element = new LuaLabel(text, x, y, fontSize, fontWeight);
AddControl(element.Label, x, y);
});
return element;
}
public LuaButton CreateButton(string text, double x, double y, double? width, double? height)
{
LuaButton element = null;
Execute.OnUIThread(() =>
{
element = new LuaButton(_luaManager, text, x, y, width, height);
AddControl(element.Button, x, y);
});
return element;
}
public LuaTextBox CreateTextBox(string text, double x, double y, double? width, double? height)
{
LuaTextBox element = null;
Execute.OnUIThread(() =>
{
element = new LuaTextBox(_luaManager, text, x, y, width, height);
AddControl(element.TextBox, x, y);
});
return element;
}
public LuaComboBox CreateComboBox(string value, List<string> values, double x, double y, double? width, double? height)
{
LuaComboBox element = null;
Execute.OnUIThread(() =>
{
element = new LuaComboBox(_luaManager, value, values, x, y, width, height);
AddControl(element.ComboBox, x, y);
});
return element;
}
public LuaCheckBox CreateCheckBox(string text, bool isChecked, double x, double y, double? width, double? height)
{
LuaCheckBox element = null;
Execute.OnUIThread(() =>
{
element = new LuaCheckBox(_luaManager, text, isChecked, x, y, width, height);
AddControl(element.CheckBox, x, y);
});
return element;
}
private void AddControl(UIElement uiElement, double x, double y)
{
Canvas.Children.Add(uiElement);
Canvas.SetLeft(uiElement, x);
Canvas.SetTop(uiElement, y);
}
}
}

View File

@ -73,7 +73,7 @@ namespace Artemis.Profiles.Lua.Modules
}
}
private void LuaInvoke(ProfileModel profileModel, Action action)
public void LuaInvoke(ProfileModel profileModel, Action action)
{
lock (InvokeLock)
{

View File

@ -0,0 +1,64 @@
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using Artemis.Managers;
using Artemis.Profiles.Lua.Modules.Gui;
using Artemis.Services;
using Caliburn.Micro;
using MoonSharp.Interpreter;
using Ninject.Parameters;
namespace Artemis.Profiles.Lua.Modules
{
[MoonSharpUserData]
public class LuaGuiModule : LuaModule
{
private readonly WindowService _windowService;
private readonly List<LuaWindowViewModel> _windows;
public LuaGuiModule(LuaManager luaManager, WindowService windowService) : base(luaManager)
{
_windowService = windowService;
_windows = new List<LuaWindowViewModel>();
}
public override string ModuleName => "Gui";
public LuaWindowViewModel CreateWindow(string title, double width, double height)
{
lock (_windows)
{
dynamic settings = new ExpandoObject();
settings.Width = width;
settings.Height = height;
IParameter[] args =
{
new ConstructorArgument("luaManager", LuaManager)
};
Execute.OnUIThread(() => _windows.Add(_windowService.ShowWindow<LuaWindowViewModel>("Artemis | " + title, settings, args)));
return _windows.Last();
}
}
public void AddEditorButton(string name, DynValue action)
{
Execute.OnUIThread(() => LuaManager.EditorButtons.Add(new EditorButton(LuaManager, name, action)));
}
public void RemoveEditorButton(string name)
{
var button = LuaManager.EditorButtons.FirstOrDefault(b => b.Text == name);
if (button != null)
Execute.OnUIThread(() => LuaManager.EditorButtons.Remove(button));
}
public override void Dispose()
{
foreach (var window in _windows)
window.TryClose();
Execute.OnUIThread(() => LuaManager.EditorButtons.Clear());
}
}
}

View File

@ -0,0 +1,68 @@
using Artemis.DAL;
using Artemis.Managers;
using Artemis.Settings;
using MoonSharp.Interpreter;
using static MoonSharp.Interpreter.Serialization.Json.JsonTableConverter;
namespace Artemis.Profiles.Lua.Modules
{
[MoonSharpUserData]
public class LuaStorageModule : LuaModule
{
private readonly Table _globalValues;
private readonly Table _profileValues;
private readonly LuaGlobalSettings _globalSettings;
public LuaStorageModule(LuaManager luaManager) : base(luaManager)
{
_globalSettings = SettingsProvider.Load<LuaGlobalSettings>();
// Load profile values
if (LuaManager.ProfileModel.LuaStorage != null)
_profileValues = JsonToTable(LuaManager.ProfileModel.LuaStorage, LuaManager.LuaScript);
else
_profileValues = new Table(LuaManager.LuaScript);
// Load global values
if (_globalSettings.GlobalValues != null)
_globalValues = JsonToTable(_globalSettings.GlobalValues, LuaManager.LuaScript);
else
_globalValues = new Table(LuaManager.LuaScript);
// Set the values onto the globals table so scripters can access them
LuaManager.LuaScript.Globals["ProfileStorage"] = _profileValues;
LuaManager.LuaScript.Globals["GlobalStorage"] = _globalValues;
}
public override string ModuleName => null;
public override void Dispose()
{
// Store profile values
LuaManager.ProfileModel.LuaStorage = _profileValues.TableToJson();
ProfileProvider.AddOrUpdate(LuaManager.ProfileModel);
// Store global values
_globalSettings.GlobalValues = _globalValues.TableToJson();
_globalSettings.Save();
}
}
public class LuaGlobalSettings : IArtemisSettings
{
public string GlobalValues { get; set; }
public void Save()
{
SettingsProvider.Save(this);
}
public void Reset(bool save = false)
{
GlobalValues = null;
if (save)
Save();
}
}
}

View File

@ -38,6 +38,7 @@ namespace Artemis.Profiles
public int Width { get; set; }
public int Height { get; set; }
public string LuaScript { get; set; }
public string LuaStorage { get; set; }
[JsonIgnore]
public string Slug => new string(Name.Where(ch => !_invalidFileNameChars.Contains(ch)).ToArray());

View File

@ -53,7 +53,7 @@ using System.Windows;
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.9.0.0")]
[assembly: AssemblyFileVersion("1.9.0.0")]
[assembly: AssemblyVersion("1.10.0.0")]
[assembly: AssemblyFileVersion("1.10.0.0")]
[assembly: InternalsVisibleTo("Artemis.Explorables")]

View File

@ -0,0 +1,41 @@
using System.IO;
using System.Linq;
using System.Threading;
using Microsoft.Win32;
using NLog;
namespace Artemis.Services
{
public static class CompatibilityService
{
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
// Checks to see if RivaTuner Statistics Server is installed and if so places a profile disabling it for Artemis
public static void CheckRivaTuner()
{
// Find the installation path in the registry
var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\WOW6432Node\Unwinder\RTSS");
var value = key?.GetValue("InstallPath");
var installDir = Path.GetDirectoryName(value?.ToString());
if (installDir == null)
return;
var profilePath = Path.Combine(installDir, "ProfileTemplates\\Artemis.exe.cfg");
if (File.Exists(profilePath))
return;
File.WriteAllText(profilePath, "[Hooking]\r\nEnableHooking\t\t= 0");
// It's kill or be killed...
var rtssProcess = System.Diagnostics.Process.GetProcessesByName("RTSS").FirstOrDefault();
var rtssHookProcess = System.Diagnostics.Process.GetProcessesByName("RTSSHooksLoader64").FirstOrDefault();
rtssProcess?.Kill();
rtssHookProcess?.Kill();
// Funnily enough sleeping prevents the RTSS injection so that the process gets killed in time
Thread.Sleep(1000);
Logger.Info("Detected that RivaTuner Statistics Server is installed, inserted a profile to prevent crashes.");
}
}
}

View File

@ -1,39 +1,41 @@
using System.Dynamic;
using Caliburn.Micro;
using Ninject;
using Ninject.Parameters;
namespace Artemis.Services
{
public class WindowService
{
private readonly IKernel _kernel;
public WindowService(IKernel kernel)
{
_kernel = kernel;
}
public T ShowWindow<T>(string windowName, params IParameter[] param) where T : class
{
var windowManager = new WindowManager();
using System.Dynamic;
using Caliburn.Micro;
using Ninject;
using Ninject.Parameters;
namespace Artemis.Services
{
public class WindowService
{
private readonly IKernel _kernel;
public WindowService(IKernel kernel)
{
_kernel = kernel;
}
public T ShowWindow<T>(string windowName, dynamic settings = null, params IParameter[] param) where T : class
{
var windowManager = new WindowManager();
var viewModel = _kernel.Get<T>(param);
dynamic settings = new ExpandoObject();
settings.Title = windowName;
windowManager.ShowWindow(viewModel, null, settings);
return viewModel;
}
public T ShowDialog<T>(string dialogName, params IParameter[] param) where T : class
{
var windowManager = new WindowManager();
var viewModel = _kernel.Get<T>(param);
dynamic settings = new ExpandoObject();
settings.Title = dialogName;
windowManager.ShowDialog(viewModel, null, settings);
return viewModel;
}
}
if (settings == null)
settings = new ExpandoObject();
settings.Title = windowName;
windowManager.ShowWindow(viewModel, null, settings);
return viewModel;
}
public T ShowDialog<T>(string dialogName, dynamic settings = null, params IParameter[] param) where T : class
{
var windowManager = new WindowManager();
var viewModel = _kernel.Get<T>(param);
if (settings == null)
settings = new ExpandoObject();
settings.Title = dialogName;
windowManager.ShowDialog(viewModel, null, settings);
return viewModel;
}
}
}

View File

@ -5,9 +5,11 @@ using System.Windows;
using Artemis.DAL;
using Artemis.Profiles.Layers.Types.AmbientLight.ScreenCapturing;
using Artemis.Utilities;
using Artemis.Utilities.ActiveWindowDetection;
using Caliburn.Micro;
using MahApps.Metro;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Squirrel;
namespace Artemis.Settings
@ -68,6 +70,11 @@ namespace Artemis.Settings
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
public string LogLevel { get; set; }
[DefaultValue(ActiveWindowDetectionType.Events)]
[JsonConverter(typeof(StringEnumConverter))]
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
public ActiveWindowDetectionType ActiveWindowDetection { get; set; }
public Version LastRanVersion { get; set; }
public void Save()
@ -75,6 +82,7 @@ namespace Artemis.Settings
SettingsProvider.Save(this);
Logging.SetupLogging(LogLevel);
ActiveWindowHelper.SetActiveWindowDetectionType(ActiveWindowDetection);
ApplyAutorun();
ApplyTheme();
ApplyGamestatePort();

View File

@ -8,6 +8,7 @@ namespace Artemis.Settings
{
public GamePointersCollection RocketLeague { get; set; }
public GamePointersCollection WorldOfWarcraft { get; set; }
public GamePointersCollection Terraria { get; set; }
public void Save()
{

View File

@ -210,7 +210,7 @@
ItemsSource="{Binding AvailableBrushTypes, RelativeSource={RelativeSource TemplatedParent}}" HorizontalAlignment="Center">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Rows="1" Columns="4" />
<UniformGrid Rows="1" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemContainerStyle>

View File

@ -0,0 +1,9 @@
namespace Artemis.Utilities.ActiveWindowDetection
{
public enum ActiveWindowDetectionType
{
Disabled = -1,
Events = 0,
Timer = 1,
}
}

View File

@ -0,0 +1,48 @@
namespace Artemis.Utilities.ActiveWindowDetection
{
public static class ActiveWindowHelper
{
#region Properties & Fields
private static ActiveWindowDetectionType _currentDetectionType = ActiveWindowDetectionType.Disabled;
private static IActiveWindowDetector _activeWindowDetector;
public static string ActiveWindowProcessName => _activeWindowDetector?.ActiveWindowProcessName ?? string.Empty;
public static string ActiveWindowWindowTitle => _activeWindowDetector?.ActiveWindowWindowTitle ?? string.Empty;
public static bool MainWindowActive => ActiveWindowProcessName.Contains("Artemis");
#endregion
#region Methods
public static void Dispose()
{
_activeWindowDetector?.Dispose();
}
public static void SetActiveWindowDetectionType(ActiveWindowDetectionType detectionType)
{
if (detectionType == _currentDetectionType) return;
_activeWindowDetector?.Dispose();
switch (detectionType)
{
case ActiveWindowDetectionType.Events:
_activeWindowDetector = new EventActiveWindowDetector();
break;
case ActiveWindowDetectionType.Timer:
_activeWindowDetector = new TimerActiveWindowDetector();
break;
case ActiveWindowDetectionType.Disabled:
_activeWindowDetector = null;
break;
}
_activeWindowDetector?.Initialize();
_currentDetectionType = detectionType;
}
#endregion
}
}

View File

@ -2,9 +2,9 @@
using System.Runtime.InteropServices;
using System.Text;
namespace Artemis.Utilities
namespace Artemis.Utilities.ActiveWindowDetection
{
public static class ActiveWindowHelper
public class EventActiveWindowDetector : IActiveWindowDetector
{
#region DLL-Imports
@ -14,7 +14,7 @@ namespace Artemis.Utilities
[DllImport("user32.dll")]
private static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr hmodWinEventProc,
WinEventDelegate lpfnWinEventProc, uint idProcess, uint idThread, uint dwFlags);
WinEventDelegate lpfnWinEventProc, uint idProcess, uint idThread, uint dwFlags);
[DllImport("user32.dll")]
private static extern bool UnhookWinEvent(IntPtr hWinEventHook);
@ -41,47 +41,46 @@ namespace Artemis.Utilities
#region Properties & Fields
// DarthAffe 17.12.2016: We need to keep a reference to this or it might get collected by the garbage collector and cause some random crashes afterwards.
private static WinEventDelegate _activeWindowChangedDelegate;
private static IntPtr _activeWindowEventHook;
private WinEventDelegate _activeWindowChangedDelegate;
private IntPtr _activeWindowEventHook;
private static WinEventDelegate _windowTitleChangedDelegate;
private static IntPtr _windowTitleEventHook;
private WinEventDelegate _windowTitleChangedDelegate;
private IntPtr _windowTitleEventHook;
private static WinEventDelegate _windowMinimizedChangedDelegate;
private static IntPtr _windowMinimizedEventHook;
private WinEventDelegate _windowMinimizedChangedDelegate;
private IntPtr _windowMinimizedEventHook;
private static IntPtr _activeWindow;
private IntPtr _activeWindow;
public static string ActiveWindowProcessName { get; private set; } = string.Empty;
public static string ActiveWindowWindowTitle { get; private set; } = string.Empty;
public static bool MainWindowActive => ActiveWindowProcessName.Contains("Artemis");
public string ActiveWindowProcessName { get; private set; } = string.Empty;
public string ActiveWindowWindowTitle { get; private set; } = string.Empty;
#endregion
#region Methods
private static void ActiveWindowChanged(IntPtr hWinEventHook, uint eventType,
IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
private void ActiveWindowChanged(IntPtr hWinEventHook, uint eventType,
IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
{
UpdateForWindow(hwnd);
}
private static void WindowTitleChanged(IntPtr hWinEventHook, uint eventType,
IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
private void WindowTitleChanged(IntPtr hWinEventHook, uint eventType,
IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
{
if (_activeWindow == hwnd)
UpdateForWindow(hwnd);
}
private static void WindowMinimizedChanged(IntPtr hWinEventHook, uint eventType,
IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
private void WindowMinimizedChanged(IntPtr hWinEventHook, uint eventType,
IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
{
// DarthAffe 19.12.2016: We expect currently un-minimized windows to be active.
// DarthAffe 19.12.2016: The result of the API-function GetActiveWindow at this moment is 'idle' so we can't use this to validate this estimation.
UpdateForWindow(hwnd);
}
private static void UpdateForWindow(IntPtr hwnd)
private void UpdateForWindow(IntPtr hwnd)
{
_activeWindow = hwnd;
@ -89,13 +88,13 @@ namespace Artemis.Utilities
ActiveWindowWindowTitle = GetActiveWindowTitle(hwnd) ?? string.Empty;
}
private static string GetActiveWindowProcessName(IntPtr hwnd)
private string GetActiveWindowProcessName(IntPtr hwnd)
{
try
{
uint pid;
GetWindowThreadProcessId(hwnd, out pid);
return System.Diagnostics.Process.GetProcessById((int) pid).ProcessName;
return System.Diagnostics.Process.GetProcessById((int)pid).ProcessName;
}
catch
{
@ -103,7 +102,7 @@ namespace Artemis.Utilities
}
}
private static string GetActiveWindowTitle(IntPtr hwnd)
private string GetActiveWindowTitle(IntPtr hwnd)
{
try
{
@ -116,7 +115,7 @@ namespace Artemis.Utilities
}
}
public static void Initialize()
public void Initialize()
{
try
{
@ -124,21 +123,21 @@ namespace Artemis.Utilities
{
_activeWindowChangedDelegate = ActiveWindowChanged;
_activeWindowEventHook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND,
IntPtr.Zero, _activeWindowChangedDelegate, 0, 0, WINEVENT_OUTOFCONTEXT);
IntPtr.Zero, _activeWindowChangedDelegate, 0, 0, WINEVENT_OUTOFCONTEXT);
}
if (_windowTitleEventHook == IntPtr.Zero)
{
_windowTitleChangedDelegate = WindowTitleChanged;
_windowTitleEventHook = SetWinEventHook(EVENT_OBJECT_NAMECHANGE, EVENT_OBJECT_NAMECHANGE,
IntPtr.Zero, _windowTitleChangedDelegate, 0, 0, WINEVENT_OUTOFCONTEXT);
IntPtr.Zero, _windowTitleChangedDelegate, 0, 0, WINEVENT_OUTOFCONTEXT);
}
if (_windowMinimizedEventHook == IntPtr.Zero)
{
_windowMinimizedChangedDelegate = WindowMinimizedChanged;
_windowMinimizedEventHook = SetWinEventHook(EVENT_SYSTEM_MINIMIZEEND, EVENT_SYSTEM_MINIMIZEEND,
IntPtr.Zero, _windowMinimizedChangedDelegate, 0, 0, WINEVENT_OUTOFCONTEXT);
IntPtr.Zero, _windowMinimizedChangedDelegate, 0, 0, WINEVENT_OUTOFCONTEXT);
}
}
catch
@ -147,7 +146,7 @@ namespace Artemis.Utilities
}
}
public static void Dispose()
public void Dispose()
{
try
{
@ -180,4 +179,4 @@ namespace Artemis.Utilities
#endregion
}
}
}

View File

@ -0,0 +1,12 @@
using System;
namespace Artemis.Utilities.ActiveWindowDetection
{
public interface IActiveWindowDetector : IDisposable
{
string ActiveWindowProcessName { get; }
string ActiveWindowWindowTitle { get; }
void Initialize();
}
}

View File

@ -0,0 +1,91 @@
using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Timers;
namespace Artemis.Utilities.ActiveWindowDetection
{
public class TimerActiveWindowDetector : IActiveWindowDetector
{
#region DLL-Imports
[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
private static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
[DllImport("user32.dll")]
private static extern IntPtr GetWindowThreadProcessId(IntPtr hWnd, out uint processId);
#endregion
#region Constants
private const int TIMER_INTERVAL = 1000;
private const int MAX_TITLE_LENGTH = 256;
#endregion
#region Properties & Fields
private Timer _timer;
public string ActiveWindowProcessName { get; private set; }
public string ActiveWindowWindowTitle { get; private set; }
#endregion
#region Methods
private void TimerOnElapsed(object sender, ElapsedEventArgs elapsedEventArgs)
{
IntPtr activeWindow = GetForegroundWindow();
ActiveWindowProcessName = GetActiveWindowProcessName(activeWindow);
ActiveWindowWindowTitle = GetActiveWindowTitle(activeWindow);
}
private string GetActiveWindowProcessName(IntPtr hwnd)
{
try
{
uint pid;
GetWindowThreadProcessId(hwnd, out pid);
return System.Diagnostics.Process.GetProcessById((int)pid).ProcessName;
}
catch
{
return null;
}
}
private string GetActiveWindowTitle(IntPtr hwnd)
{
try
{
StringBuilder buffer = new StringBuilder(MAX_TITLE_LENGTH);
return GetWindowText(hwnd, buffer, MAX_TITLE_LENGTH) > 0 ? buffer.ToString() : null;
}
catch
{
return null;
}
}
public void Initialize()
{
_timer = new Timer(TIMER_INTERVAL) { AutoReset = true };
_timer.Elapsed += TimerOnElapsed;
_timer.Start();
}
public void Dispose()
{
_timer?.Stop();
_timer?.Dispose();
_timer = null;
}
#endregion
}
}

View File

@ -37,8 +37,11 @@ namespace Artemis.Utilities.DataReaders
try
{
// Change the registry key to point to the fake DLL
var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Classes\CLSID\{a6519e67-7632-4375-afdf-caa889744403}\ServerBinary", true);
key?.SetValue(null, DllPath + @"\LogitechLed.dll");
// Key doesn't exist yet on systems without LGS installed
var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Classes\CLSID\{a6519e67-7632-4375-afdf-caa889744403}\ServerBinary", true) ??
Registry.LocalMachine.CreateSubKey(@"SOFTWARE\Classes\CLSID\{a6519e67-7632-4375-afdf-caa889744403}\ServerBinary", true);
key.SetValue(null, DllPath + @"\LogitechLed.dll");
// Make sure the fake DLL is in place
if (!Directory.Exists(DllPath))

View File

@ -148,6 +148,8 @@ namespace Artemis.Utilities
offsetSettings.RocketLeague = pointers.FirstOrDefault(p => p.Game == "RocketLeague");
if (pointers.FirstOrDefault(p => p.Game == "WorldOfWarcraft") != null)
offsetSettings.WorldOfWarcraft = pointers.FirstOrDefault(p => p.Game == "WorldOfWarcraft");
if (pointers.FirstOrDefault(p => p.Game == "Terraria") != null)
offsetSettings.Terraria = pointers.FirstOrDefault(p => p.Game == "Terraria");
offsetSettings.Save();
}

View File

@ -8,6 +8,7 @@ using Artemis.Events;
using Artemis.Managers;
using Artemis.Services;
using Artemis.Settings;
using Artemis.Utilities.ActiveWindowDetection;
using Caliburn.Micro;
using MahApps.Metro.Controls;
using NLog;
@ -37,6 +38,8 @@ namespace Artemis.ViewModels.Flyouts
LogLevels = new BindableCollection<string>();
LogLevels.AddRange(LogLevel.AllLoggingLevels.Select(l => l.Name));
ActiveWindowDetections = new BindableCollection<ActiveWindowDetectionType>(Enum.GetValues(typeof(ActiveWindowDetectionType)).Cast<ActiveWindowDetectionType>());
PropertyChanged += KeyboardUpdater;
mainManager.EnabledChanged += MainManagerEnabledChanged;
mainManager.ModuleManager.EffectChanged += EffectManagerEffectChanged;
@ -96,6 +99,7 @@ namespace Artemis.ViewModels.Flyouts
public string VersionText => "Artemis " + Assembly.GetExecutingAssembly().GetName().Version;
public BindableCollection<string> LogLevels { get; set; }
public BindableCollection<ActiveWindowDetectionType> ActiveWindowDetections { get; set; }
public string SelectedTheme
{
@ -130,6 +134,17 @@ namespace Artemis.ViewModels.Flyouts
}
}
public ActiveWindowDetectionType SelectedActiveWindowDetection
{
get { return GeneralSettings.ActiveWindowDetection; }
set
{
if (value == GeneralSettings.ActiveWindowDetection) return;
GeneralSettings.ActiveWindowDetection = value;
NotifyOfPropertyChange(() => SelectedActiveWindowDetection);
}
}
public string SelectedKeyboardProvider
{
get { return _selectedKeyboardProvider; }

View File

@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@ -12,7 +11,6 @@ using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Media;
using Artemis.DAL;
using Artemis.DeviceProviders;
using Artemis.Events;
using Artemis.Managers;
using Artemis.Models;
@ -21,10 +19,12 @@ using Artemis.Profiles;
using Artemis.Profiles.Layers.Interfaces;
using Artemis.Profiles.Layers.Models;
using Artemis.Profiles.Layers.Types.Folder;
using Artemis.Profiles.Lua.Modules.Gui;
using Artemis.Properties;
using Artemis.Services;
using Artemis.Styles.DropTargetAdorners;
using Artemis.Utilities;
using Artemis.Utilities.ActiveWindowDetection;
using Caliburn.Micro;
using Castle.Components.DictionaryAdapter;
using GongSolutions.Wpf.DragDrop;
@ -46,21 +46,20 @@ namespace Artemis.ViewModels
{
public sealed class ProfileEditorViewModel : Screen, IDropTarget
{
private readonly KeybindModel _copyKeybind;
private readonly DeviceManager _deviceManager;
private readonly MetroDialogService _dialogService;
private readonly LoopManager _loopManager;
private readonly ModuleModel _moduleModel;
private readonly KeybindModel _copyKeybind;
private readonly KeybindModel _pasteKeybind;
private ImageSource _keyboardPreview;
private ObservableCollection<LayerModel> _layers;
private readonly KeybindModel _pasteKeybind;
private ObservableCollection<string> _profileNames;
private bool _saving;
private LayerModel _selectedLayer;
private bool _showAll;
public ProfileEditorViewModel(ProfileEditorModel profileEditorModel, DeviceManager deviceManager,
LoopManager loopManager, ModuleModel moduleModel, MetroDialogService dialogService)
public ProfileEditorViewModel(ProfileEditorModel profileEditorModel, DeviceManager deviceManager, LoopManager loopManager, LuaManager luaManager, ModuleModel moduleModel, MetroDialogService dialogService)
{
_deviceManager = deviceManager;
_loopManager = loopManager;
@ -72,6 +71,7 @@ namespace Artemis.ViewModels
ProfileNames = new ObservableCollection<string>();
Layers = new ObservableCollection<LayerModel>();
ProfileEditorModel = profileEditorModel;
LuaManager = luaManager;
ShowAll = true;
PropertyChanged += EditorStateHandler;
@ -102,6 +102,11 @@ namespace Artemis.ViewModels
#region LUA
public void ClickedLuaButton(EditorButton button)
{
button.Invoke();
}
public void EditLua()
{
if (SelectedProfile == null)
@ -123,6 +128,7 @@ namespace Artemis.ViewModels
#region Properties
public ProfileEditorModel ProfileEditorModel { get; }
public LuaManager LuaManager { get; }
public ObservableCollection<string> ProfileNames
{
@ -198,7 +204,7 @@ namespace Artemis.ViewModels
NotifyOfPropertyChange(() => LayerSelected);
}
}
public ProfileModel SelectedProfile => _moduleModel?.ProfileModel;
public bool ProfileSelected => SelectedProfile != null;
public bool LayerSelected => SelectedProfile != null && SelectedLayer != null;
@ -325,7 +331,7 @@ namespace Artemis.ViewModels
public void LayerToClipboard()
{
if (SelectedLayer == null || !ActiveWindowHelper.MainWindowActive)
if (SelectedLayer == null || !ActiveWindowHelper.MainWindowActive || !IsActive)
return;
// Probably not how the cool kids do it but leveraging on JsonConvert gives flawless serialization
@ -334,30 +340,35 @@ namespace Artemis.ViewModels
public void ClipboardToLayer()
{
if (!ActiveWindowHelper.MainWindowActive)
if (!ActiveWindowHelper.MainWindowActive || !IsActive)
return;
GeneralHelpers.ExecuteSta(() =>
try
{
var data = (string) Clipboard.GetData("layer");
if (data == null)
return;
var layerModel = JsonConvert.DeserializeObject<LayerModel>(data);
if (layerModel == null)
return;
if (SelectedLayer != null)
GeneralHelpers.ExecuteSta(() =>
{
SelectedLayer.InsertAfter(layerModel);
}
else
{
SelectedProfile.Layers.Add(layerModel);
SelectedProfile.FixOrder();
}
Execute.OnUIThread(() => UpdateLayerList(layerModel));
});
var data = (string) Clipboard.GetData("layer");
if (data == null)
return;
var layerModel = JsonConvert.DeserializeObject<LayerModel>(data);
if (layerModel == null)
return;
if (SelectedLayer != null)
SelectedLayer.InsertAfter(layerModel);
else
{
SelectedProfile.Layers.Add(layerModel);
SelectedProfile.FixOrder();
}
Execute.OnUIThread(() => UpdateLayerList(layerModel));
});
}
catch (Exception)
{
// ignored
}
}
private void UpdateLayerList(LayerModel selectModel)
@ -405,6 +416,9 @@ namespace Artemis.ViewModels
if (_saving || SelectedProfile == null || _deviceManager.ChangingKeyboard)
return;
SelectedProfile.Width = _deviceManager.ActiveKeyboard.Width;
SelectedProfile.Height = _deviceManager.ActiveKeyboard.Height;
_saving = true;
try
{
@ -421,8 +435,7 @@ namespace Artemis.ViewModels
{
if (_deviceManager.ActiveKeyboard == null)
{
_dialogService.ShowMessageBox("Cannot add profile.",
"To add a profile, please select a keyboard in the options menu first.");
_dialogService.ShowMessageBox("Cannot add profile.", "To add a profile, please select a keyboard in the options menu first.");
return;
}
@ -666,7 +679,7 @@ namespace Artemis.ViewModels
return;
var pos = GetScaledPosition(e);
var hoverLayer = GetLayers().Where(l => l.MustDraw()).FirstOrDefault(l => l.Properties.PropertiesRect(1).Contains(pos.X, pos.Y));
var hoverLayer = GetHoverLayer(pos.X, pos.Y);
if (hoverLayer != null)
SelectedLayer = hoverLayer;
@ -682,7 +695,7 @@ namespace Artemis.ViewModels
return;
var pos = GetScaledPosition(e);
var hoverLayer = GetLayers().Where(l => l.MustDraw()).FirstOrDefault(l => l.Properties.PropertiesRect(1).Contains(pos.X, pos.Y));
var hoverLayer = GetHoverLayer(pos.X, pos.Y);
HandleDragging(e, pos.X, pos.Y, hoverLayer);
@ -701,11 +714,10 @@ namespace Artemis.ViewModels
: Cursors.SizeAll;
}
else
{
KeyboardPreviewCursor = Cursors.Hand;
}
}
private Point GetScaledPosition(MouseEventArgs e)
{
var previewSettings = _deviceManager.ActiveKeyboard.PreviewSettings;
@ -716,16 +728,25 @@ namespace Artemis.ViewModels
var heightScale = sourceImage.ActualHeight / _deviceManager.ActiveKeyboard.PreviewSettings.BackgroundRectangle.Height;
// Remove the preview settings' offset from the cursor postion
pos.X = pos.X - (previewSettings.OverlayRectangle.X * widthScale);
pos.Y = pos.Y - (previewSettings.OverlayRectangle.Y * heightScale);
pos.X = pos.X - previewSettings.OverlayRectangle.X * widthScale;
pos.Y = pos.Y - previewSettings.OverlayRectangle.Y * heightScale;
// Scale the X and Y position down to match the keyboard's physical size and thus the layer positions
pos.X = pos.X * (SelectedProfile.Width / (previewSettings.OverlayRectangle.Width*widthScale));
pos.X = pos.X * (SelectedProfile.Width / (previewSettings.OverlayRectangle.Width * widthScale));
pos.Y = pos.Y * (SelectedProfile.Height / (previewSettings.OverlayRectangle.Height * heightScale));
return pos;
}
private LayerModel GetHoverLayer(double x, double y)
{
// Prefer the selected layer as the hover layer even if it's underneath something else
if (SelectedLayer != null && SelectedLayer.Properties.PropertiesRect(1).Contains(x, y))
return SelectedLayer;
return GetLayers().Where(l => l.MustDraw()).FirstOrDefault(l => l.Properties.PropertiesRect(1).Contains(x, y));
}
public Cursor KeyboardPreviewCursor
{
get { return _keyboardPreviewCursor; }

View File

@ -6,7 +6,7 @@
xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
xmlns:cal="http://www.caliburnproject.org"
mc:Ignorable="d"
d:DesignHeight="600" d:DesignWidth="300">
d:DesignHeight="600" d:DesignWidth="310">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
@ -25,6 +25,7 @@
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
@ -94,30 +95,36 @@
<controls:NumericUpDown Grid.Row="8" Grid.Column="1" Margin="10" VerticalAlignment="Center"
HorizontalAlignment="Right" Width="140" Minimum="1" Maximum="60"
Value="{Binding Path=GeneralSettings.ScreenCaptureFPS, Mode=TwoWay}" />
<!-- Logging -->
<Label Grid.Row="9" Grid.Column="0" Margin="5" VerticalAlignment="Center" HorizontalAlignment="Left"
Content="Log level:" />
<ComboBox Grid.Row="9" Grid.Column="1" x:Name="LogLevels" Margin="10" VerticalAlignment="Center"
Content="Active window detection" />
<ComboBox Grid.Row="9" Grid.Column="1" x:Name="ActiveWindowDetections" Margin="10" VerticalAlignment="Center"
HorizontalAlignment="Right"
Width="140" />
<Button Grid.Row="10" Grid.Column="0" Margin="10" x:Name="ShowLogs" Content="Show logs"
<!-- Logging -->
<Label Grid.Row="10" Grid.Column="0" Margin="5" VerticalAlignment="Center" HorizontalAlignment="Left"
Content="Log level:" />
<ComboBox Grid.Row="10" Grid.Column="1" x:Name="LogLevels" Margin="10" VerticalAlignment="Center"
HorizontalAlignment="Right"
Width="140" />
<Button Grid.Row="11" Grid.Column="0" Margin="10" x:Name="ShowLogs" Content="Show logs"
VerticalAlignment="Center" Width="100" HorizontalAlignment="Left"
Style="{DynamicResource SquareButtonStyle}" />
<Button Grid.Row="10" Grid.Column="1" Margin="10" x:Name="ShowDebug" Content="Show debugger"
<Button Grid.Row="11" Grid.Column="1" Margin="10" x:Name="ShowDebug" Content="Show debugger"
VerticalAlignment="Center" Width="100" HorizontalAlignment="Right"
Style="{DynamicResource SquareButtonStyle}" />
<!-- Buttons -->
<Button Grid.Row="11" Grid.Column="0" Margin="10" x:Name="ResetSettings" Content="Reset settings"
<Button Grid.Row="12" Grid.Column="0" Margin="10" x:Name="ResetSettings" Content="Reset settings"
VerticalAlignment="Center" HorizontalAlignment="Left" Width="100"
Style="{DynamicResource SquareButtonStyle}" />
<Button Grid.Row="11" Grid.Column="1" Margin="11" x:Name="SaveSettings" Content="Save changes"
<Button Grid.Row="12" Grid.Column="1" Margin="11" x:Name="SaveSettings" Content="Save changes"
VerticalAlignment="Center" HorizontalAlignment="Right" Width="100"
Style="{DynamicResource SquareButtonStyle}" />
<!-- Version -->
<Grid Grid.Row="12" Grid.Column="0" Grid.ColumnSpan="2" Margin="10" VerticalAlignment="Bottom">
<Grid Grid.Row="13" Grid.Column="0" Grid.ColumnSpan="2" Margin="10" VerticalAlignment="Bottom">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />

View File

@ -1,16 +1,8 @@
<UserControl x:Class="Artemis.Views.ProfileEditorView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:cal="http://www.caliburnproject.org"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:itemBehaviours="clr-namespace:Artemis.ItemBehaviours"
xmlns:dragDrop="clr-namespace:GongSolutions.Wpf.DragDrop;assembly=GongSolutions.Wpf.DragDrop"
xmlns:converters="clr-namespace:Artemis.Utilities.Converters"
xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
mc:Ignorable="d"
d:DesignHeight="400" d:DesignWidth="1060">
<UserControl x:Class="Artemis.Views.ProfileEditorView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:cal="http://www.caliburnproject.org"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:itemBehaviours="clr-namespace:Artemis.ItemBehaviours"
xmlns:dragDrop="clr-namespace:GongSolutions.Wpf.DragDrop;assembly=GongSolutions.Wpf.DragDrop" xmlns:converters="clr-namespace:Artemis.Utilities.Converters"
xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls" mc:Ignorable="d" d:DesignHeight="400" d:DesignWidth="1060">
<UserControl.Resources>
<converters:LayerOrderConverter x:Key="LayerOrderConverter" />
</UserControl.Resources>
@ -22,7 +14,8 @@
<Grid.RowDefinitions>
<RowDefinition Height="40" />
<RowDefinition Height="*" />
<RowDefinition Height="60" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<!-- Preview -->
@ -32,7 +25,9 @@
<Border.Effect>
<DropShadowEffect x:Name="ShadowEffect" ShadowDepth="0" Color="{DynamicResource HighlightColor}" Opacity="1" BlurRadius="25" />
</Border.Effect>
<Image Source="{Binding Path=KeyboardPreview}" MinHeight="10" MinWidth="10" Stretch="Uniform" Cursor="{Binding Path=KeyboardPreviewCursor}" IsEnabled="{Binding Path=EditorEnabled, Mode=OneWay}" cal:Message.Attach="
<Image Source="{Binding Path=KeyboardPreview}" MinHeight="10" MinWidth="10" Stretch="Uniform" Cursor="{Binding Path=KeyboardPreviewCursor}"
IsEnabled="{Binding Path=EditorEnabled, Mode=OneWay}"
cal:Message.Attach="
[Event MouseMove] = [Action MouseMoveKeyboardPreview($eventArgs)];
[Event MouseDown] = [Action MouseDownKeyboardPreview($eventArgs)];
[Event MouseUp] = [Action MouseUpKeyboardPreview($eventArgs)]" />
@ -43,8 +38,8 @@
<StackPanel Orientation="Horizontal" Margin="0,5,0,0">
<Label Content="Active profile" />
<ComboBox Width="220" VerticalAlignment="Top" x:Name="ProfileNames" Margin="5,0,0,0" />
<Button x:Name="AddProfile" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}"
Width="26" Height="26" HorizontalAlignment="Right" Margin="10,0,0,0" ToolTip="Add profile">
<Button x:Name="AddProfile" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}" Width="26" Height="26" HorizontalAlignment="Right" Margin="10,0,0,0"
ToolTip="Add profile">
<Button.Content>
<Rectangle Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}" Width="12" Height="12">
<Rectangle.OpacityMask>
@ -53,9 +48,8 @@
</Rectangle>
</Button.Content>
</Button>
<Button x:Name="RenameProfile" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}"
Width="26" Height="26" HorizontalAlignment="Right" Margin="10,0,0,0" ToolTip="Rename profile"
IsEnabled="{Binding Path=EditorEnabled, Mode=OneWay}">
<Button x:Name="RenameProfile" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}" Width="26" Height="26" HorizontalAlignment="Right" Margin="10,0,0,0"
ToolTip="Rename profile" IsEnabled="{Binding Path=EditorEnabled, Mode=OneWay}">
<Button.Content>
<Rectangle Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}" Width="12" Height="12">
<Rectangle.OpacityMask>
@ -74,7 +68,8 @@
</Rectangle>
</Button.Content>
</Button>
<Button x:Name="DeleteProfile" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}" Width="26" Height="26" HorizontalAlignment="Right" Margin="10,0,0,0" ToolTip="Delete profile" IsEnabled="{Binding Path=EditorEnabled, Mode=OneWay}">
<Button x:Name="DeleteProfile" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}" Width="26" Height="26" HorizontalAlignment="Right" Margin="10,0,0,0"
ToolTip="Delete profile" IsEnabled="{Binding Path=EditorEnabled, Mode=OneWay}">
<Button.Content>
<Rectangle Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}" Width="12" Height="12">
<Rectangle.OpacityMask>
@ -84,17 +79,12 @@
</Button.Content>
</Button>
</StackPanel>
<TextBlock VerticalAlignment="Top" Foreground="{DynamicResource HighlightBrush}" HorizontalAlignment="Left" Margin="5,5,0,0" Text="Note: To edit a default profile, duplicate it first." FontWeight="Bold" />
</StackPanel>
<StackPanel Grid.Column="0" Grid.Row="2" Orientation="Horizontal" Margin="0,5,0,0" HorizontalAlignment="Right">
<Button x:Name="ImportProfile" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}"
Height="26" HorizontalAlignment="Right">
<Button x:Name="ImportProfile" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}" Height="26" HorizontalAlignment="Right">
<Button.Content>
<StackPanel Orientation="Horizontal">
<Rectangle
Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}"
Width="12" Height="12" Margin="3,0">
<Rectangle Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}" Width="12" Height="12" Margin="3,0">
<Rectangle.OpacityMask>
<VisualBrush Visual="{StaticResource appbar_cabinet_in}" Stretch="Fill" />
</Rectangle.OpacityMask>
@ -103,13 +93,11 @@
</StackPanel>
</Button.Content>
</Button>
<Button x:Name="ExportProfile" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}"
Height="26" HorizontalAlignment="Right" Margin="10,0,0,0" IsEnabled="{Binding ProfileSelected}">
<Button x:Name="ExportProfile" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}" Height="26" HorizontalAlignment="Right" Margin="10,0,0,0"
IsEnabled="{Binding ProfileSelected}">
<Button.Content>
<StackPanel Orientation="Horizontal">
<Rectangle
Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}"
Width="12" Height="12" Margin="3,0">
<Rectangle Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}" Width="12" Height="12" Margin="3,0">
<Rectangle.OpacityMask>
<VisualBrush Visual="{StaticResource appbar_cabinet_out}" Stretch="Fill" />
</Rectangle.OpacityMask>
@ -118,14 +106,11 @@
</StackPanel>
</Button.Content>
</Button>
<Button x:Name="EditLua" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}" Height="26"
HorizontalAlignment="Right" Margin="10,0,0,0" IsEnabled="{Binding Path=EditorEnabled, Mode=OneWay}"
Visibility="{Binding Path=LuaButtonVisible, Converter={StaticResource BoolToVis} }">
<Button x:Name="EditLua" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}" Height="26" HorizontalAlignment="Right" Margin="10,0,0,0"
IsEnabled="{Binding Path=EditorEnabled, Mode=OneWay}" Visibility="{Binding Path=LuaButtonVisible, Converter={StaticResource BoolToVis} }">
<Button.Content>
<StackPanel Orientation="Horizontal">
<Rectangle
Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}"
Width="12" Height="12" Margin="3,0">
<Rectangle Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}" Width="12" Height="12" Margin="3,0">
<Rectangle.OpacityMask>
<VisualBrush Visual="{StaticResource appbar_code_xml}" Stretch="Fill" />
</Rectangle.OpacityMask>
@ -154,8 +139,7 @@
ItemsSource="{Binding Path=Layers, Converter={StaticResource LayerOrderConverter}, ConverterParameter=Order}" IsEnabled="{Binding Path=EditorEnabled, Mode=OneWay}"
cal:Message.Attach="[Event MouseDoubleClick] = [Action EditLayerFromDoubleClick]">
<i:Interaction.Behaviors>
<itemBehaviours:BindableSelectedItemBehavior
SelectedItem="{Binding SelectedLayer, Mode=TwoWay}" />
<itemBehaviours:BindableSelectedItemBehavior SelectedItem="{Binding SelectedLayer, Mode=TwoWay}" />
</i:Interaction.Behaviors>
<TreeView.Resources>
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseDark.xaml" />
@ -185,9 +169,8 @@
</TreeView>
</Border>
<StackPanel Grid.Column="1" Grid.Row="2" Orientation="Horizontal" Margin="0,5,0,0" HorizontalAlignment="Right">
<Button x:Name="AddLayer" VerticalAlignment="Top"
Style="{DynamicResource SquareButtonStyle}" IsEnabled="{Binding Path=EditorEnabled, Mode=OneWay}"
Width="26" Height="26" ToolTip="Add layer" HorizontalAlignment="Left">
<Button x:Name="AddLayer" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}" IsEnabled="{Binding Path=EditorEnabled, Mode=OneWay}" Width="26" Height="26"
ToolTip="Add layer" HorizontalAlignment="Left">
<Button.Content>
<Rectangle Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}" Width="12" Height="12">
<Rectangle.OpacityMask>
@ -196,9 +179,8 @@
</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 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>
@ -207,8 +189,7 @@
</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"
<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}">
<Button.Content>
<Rectangle Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}" Width="12" Height="12">
@ -218,9 +199,8 @@
</Rectangle>
</Button.Content>
</Button>
<Button x:Name="CloneLayer" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}"
Width="26" Height="26" HorizontalAlignment="Right" Margin="10,0,0,0" ToolTip="Duplicate layer"
IsEnabled="{Binding Path=LayerSelected}">
<Button x:Name="CloneLayer" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}" Width="26" Height="26" HorizontalAlignment="Right" Margin="10,0,0,0"
ToolTip="Duplicate layer" IsEnabled="{Binding Path=LayerSelected}">
<Button.Content>
<Rectangle Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}" Width="12" Height="12">
<Rectangle.OpacityMask>
@ -229,9 +209,8 @@
</Rectangle>
</Button.Content>
</Button>
<Button x:Name="RemoveLayer" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}"
Width="26" Height="26" HorizontalAlignment="Right" Margin="10,0,0,0" ToolTip="Delete layer"
IsEnabled="{Binding Path=LayerSelected}">
<Button x:Name="RemoveLayer" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}" Width="26" Height="26" HorizontalAlignment="Right" Margin="10,0,0,0"
ToolTip="Delete layer" IsEnabled="{Binding Path=LayerSelected}">
<Button.Content>
<Rectangle Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}" Width="12" Height="12">
<Rectangle.OpacityMask>
@ -241,5 +220,21 @@
</Button.Content>
</Button>
</StackPanel>
<TextBlock VerticalAlignment="Top" Grid.Column="0" Grid.Row="3" Foreground="{DynamicResource HighlightBrush}" Margin="0,5" HorizontalAlignment="Left"
Text="Note: To edit a default profile, duplicate it first." FontWeight="Bold" />
<ItemsControl ItemsSource="{Binding Path=LuaManager.EditorButtons}" Grid.Column="1" Grid.Row="3" Margin="0,5" HorizontalAlignment="Right">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="{Binding Text}" cal:Message.Attach="ClickedLuaButton($dataContext)" Style="{DynamicResource SquareButtonStyle}" Height="26" Margin="5,0,0,0" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</UserControl>

View File

@ -22,7 +22,7 @@
<ProjectGuid>{1A349CF5-2008-41E8-AC13-874CBBCDFA0A}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>LightFX2Artemis</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

View File

@ -23,6 +23,7 @@
<Keyword>Win32Proj</Keyword>
<RootNamespace>LogiLed2Artemis</RootNamespace>
<ProjectName>LogiLed2Artemis</ProjectName>
<WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

View File

@ -21,7 +21,7 @@
<PropertyGroup Label="Globals">
<ProjectGuid>{39711909-C1D5-46CE-A9EA-2D561692EA47}</ProjectGuid>
<RootNamespace>Razer2Artemis</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">