1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2026-01-01 10:13:30 +00:00

Misc fixes

Made labels in editor consistent
Rendering everything in one visual now, gaining a bit of perf
Upped device draw scale  (was 4, then 1, now 2)
Replaced RAM usage with a quicker alternative
Split up ram into total ram, used ram, available ram
Replaced current time with a quicker alternative
Use image brush on Corsair devices <3 CUE.NET
This commit is contained in:
SpoinkyNL 2017-02-01 17:52:12 +01:00
parent f7b61f11c0
commit d4ca54a35a
24 changed files with 312 additions and 291 deletions

View File

@ -354,6 +354,8 @@
<Compile Include="DeviceProviders\Logitech\Utilities\OrionUtilities.cs" /> <Compile Include="DeviceProviders\Logitech\Utilities\OrionUtilities.cs" />
<Compile Include="DeviceProviders\Razer\BlackWidow.cs" /> <Compile Include="DeviceProviders\Razer\BlackWidow.cs" />
<Compile Include="DeviceProviders\Razer\Utilities\RazerUtilities.cs" /> <Compile Include="DeviceProviders\Razer\Utilities\RazerUtilities.cs" />
<Compile Include="Models\DeviceVisualModel.cs" />
<Compile Include="Models\FrameModel.cs" />
<Compile Include="Managers\MigrationManager.cs" /> <Compile Include="Managers\MigrationManager.cs" />
<Compile Include="Managers\ModuleManager.cs" /> <Compile Include="Managers\ModuleManager.cs" />
<Compile Include="Managers\DeviceManager.cs" /> <Compile Include="Managers\DeviceManager.cs" />

View File

@ -33,7 +33,8 @@ namespace Artemis.DeviceProviders.CoolerMaster
} }
public override void Disable() public override void Disable()
{ {
CmSdk.SetControlDevice(DEVICE_INDEX.DEV_MKeys_L);
CmSdk.EnableLedControl(false); CmSdk.EnableLedControl(false);
Thread.Sleep(500); Thread.Sleep(500);
} }

View File

@ -34,13 +34,14 @@ namespace Artemis.DeviceProviders.CoolerMaster
public override void Disable() public override void Disable()
{ {
CmSdk.SetControlDevice(DEVICE_INDEX.DEV_MKeys_S);
CmSdk.EnableLedControl(false); CmSdk.EnableLedControl(false);
Thread.Sleep(500); Thread.Sleep(500);
} }
public override bool CanEnable() public override bool CanEnable()
{ {
CmSdk.SetControlDevice(DEVICE_INDEX.DEV_MKeys_L); CmSdk.SetControlDevice(DEVICE_INDEX.DEV_MKeys_S);
// Doesn't seem reliable but better than nothing I suppose // Doesn't seem reliable but better than nothing I suppose
return CmSdk.IsDevicePlug(); return CmSdk.IsDevicePlug();

View File

@ -1,8 +1,8 @@
using System; using System;
using System.Drawing; using System.Drawing;
using System.Linq;
using System.Threading; using System.Threading;
using CUE.NET; using CUE.NET;
using CUE.NET.Brushes;
using CUE.NET.Devices.Generic.Enums; using CUE.NET.Devices.Generic.Enums;
using Ninject.Extensions.Logging; using Ninject.Extensions.Logging;
@ -10,10 +10,13 @@ namespace Artemis.DeviceProviders.Corsair
{ {
public class CorsairHeadset : DeviceProvider public class CorsairHeadset : DeviceProvider
{ {
private readonly ImageBrush _headsetBrush;
public CorsairHeadset(ILogger logger) public CorsairHeadset(ILogger logger)
{ {
Logger = logger; Logger = logger;
Type = DeviceType.Headset; Type = DeviceType.Headset;
_headsetBrush = new ImageBrush();
} }
public ILogger Logger { get; set; } public ILogger Logger { get; set; }
@ -27,7 +30,10 @@ namespace Artemis.DeviceProviders.Corsair
Logger.Debug("Attempted to enable Corsair headset. CanUse: {0}", CanUse); Logger.Debug("Attempted to enable Corsair headset. CanUse: {0}", CanUse);
if (CanUse) if (CanUse)
{
CueSDK.UpdateMode = UpdateMode.Manual; CueSDK.UpdateMode = UpdateMode.Manual;
CueSDK.HeadsetSDK.Brush = _headsetBrush;
}
return CanUse; return CanUse;
} }
@ -44,21 +50,7 @@ namespace Artemis.DeviceProviders.Corsair
if (bitmap.Width != bitmap.Height) if (bitmap.Width != bitmap.Height)
throw new ArgumentException("Bitmap must be a perfect square"); throw new ArgumentException("Bitmap must be a perfect square");
var leds = CueSDK.HeadsetSDK.Leds.Count(); _headsetBrush.Image = bitmap;
var step = (double)bitmap.Width / leds;
var ledIndex = 0;
// Color each LED according to one of the pixels
foreach (var corsairLed in CueSDK.HeadsetSDK.Leds)
{
var col = ledIndex == 0
? bitmap.GetPixel(0, 0)
: bitmap.GetPixel((int)((ledIndex + 1) * step - 1), (int)((ledIndex + 1) * step - 1));
corsairLed.Color = col;
ledIndex++;
}
CueSDK.HeadsetSDK.Update(); CueSDK.HeadsetSDK.Update();
} }

View File

@ -1,8 +1,8 @@
using System; using System;
using System.Drawing; using System.Drawing;
using System.Linq;
using System.Threading; using System.Threading;
using CUE.NET; using CUE.NET;
using CUE.NET.Brushes;
using CUE.NET.Devices.Generic.Enums; using CUE.NET.Devices.Generic.Enums;
using Ninject.Extensions.Logging; using Ninject.Extensions.Logging;
@ -10,10 +10,13 @@ namespace Artemis.DeviceProviders.Corsair
{ {
public class CorsairMouse : DeviceProvider public class CorsairMouse : DeviceProvider
{ {
private readonly ImageBrush _mouseBrush;
public CorsairMouse(ILogger logger) public CorsairMouse(ILogger logger)
{ {
Logger = logger; Logger = logger;
Type = DeviceType.Mouse; Type = DeviceType.Mouse;
_mouseBrush = new ImageBrush();
} }
public ILogger Logger { get; set; } public ILogger Logger { get; set; }
@ -27,7 +30,10 @@ namespace Artemis.DeviceProviders.Corsair
Logger.Debug("Attempted to enable Corsair mice. CanUse: {0}", CanUse); Logger.Debug("Attempted to enable Corsair mice. CanUse: {0}", CanUse);
if (CanUse) if (CanUse)
{
CueSDK.UpdateMode = UpdateMode.Manual; CueSDK.UpdateMode = UpdateMode.Manual;
CueSDK.MouseSDK.Brush = _mouseBrush;
}
return CanUse; return CanUse;
} }
@ -44,21 +50,7 @@ namespace Artemis.DeviceProviders.Corsair
if (bitmap.Width != bitmap.Height) if (bitmap.Width != bitmap.Height)
throw new ArgumentException("Bitmap must be a perfect square"); throw new ArgumentException("Bitmap must be a perfect square");
var leds = CueSDK.MouseSDK.Leds.Count(); _mouseBrush.Image = bitmap;
var step = (double)bitmap.Width / leds;
var ledIndex = 0;
// Color each LED according to one of the pixels
foreach (var corsairLed in CueSDK.MouseSDK.Leds)
{
var col = ledIndex == 0
? bitmap.GetPixel(0, 0)
: bitmap.GetPixel((int)((ledIndex + 1) * step - 1), (int)((ledIndex + 1) * step - 1));
corsairLed.Color = col;
ledIndex++;
}
CueSDK.MouseSDK.Update(); CueSDK.MouseSDK.Update();
} }

View File

@ -1,8 +1,8 @@
using System; using System;
using System.Drawing; using System.Drawing;
using System.Linq;
using System.Threading; using System.Threading;
using CUE.NET; using CUE.NET;
using CUE.NET.Brushes;
using CUE.NET.Devices.Generic.Enums; using CUE.NET.Devices.Generic.Enums;
using Ninject.Extensions.Logging; using Ninject.Extensions.Logging;
@ -10,10 +10,13 @@ namespace Artemis.DeviceProviders.Corsair
{ {
public class CorsairMousemat : DeviceProvider public class CorsairMousemat : DeviceProvider
{ {
private readonly ImageBrush _mousematBrush;
public CorsairMousemat(ILogger logger) public CorsairMousemat(ILogger logger)
{ {
Logger = logger; Logger = logger;
Type = DeviceType.Mousemat; Type = DeviceType.Mousemat;
_mousematBrush = new ImageBrush();
} }
public ILogger Logger { get; set; } public ILogger Logger { get; set; }
@ -27,7 +30,10 @@ namespace Artemis.DeviceProviders.Corsair
Logger.Debug("Attempted to enable Corsair mousemat. CanUse: {0}", CanUse); Logger.Debug("Attempted to enable Corsair mousemat. CanUse: {0}", CanUse);
if (CanUse) if (CanUse)
{
CueSDK.UpdateMode = UpdateMode.Manual; CueSDK.UpdateMode = UpdateMode.Manual;
CueSDK.MousematSDK.Brush = _mousematBrush;
}
return CanUse; return CanUse;
} }
@ -39,46 +45,12 @@ namespace Artemis.DeviceProviders.Corsair
public override void UpdateDevice(Bitmap bitmap) public override void UpdateDevice(Bitmap bitmap)
{ {
if (!CanUse || (bitmap == null)) if (!CanUse || bitmap == null)
return; return;
if (bitmap.Width != bitmap.Height) if (bitmap.Width != bitmap.Height)
throw new ArgumentException("Bitmap must be a perfect square"); throw new ArgumentException("Bitmap must be a perfect square");
var yStep = (double)bitmap.Width / 4; _mousematBrush.Image = bitmap;
var xStep = (double)bitmap.Width / 6;
// This approach will break if any mousemats with different LED amounts are released, for now it will do.
var ledIndex = 0;
// Color each LED according to one of the pixels
foreach (var corsairLed in CueSDK.MousematSDK.Leds.OrderBy(l => l.ToString()))
{
Color col;
// Left side
if (ledIndex < 5)
{
col = ledIndex == 0
? bitmap.GetPixel(0, (int)(ledIndex * yStep))
: bitmap.GetPixel(0, (int)(ledIndex * yStep) - 1);
}
// Bottom
else if (ledIndex < 10)
{
// Start at index 1 because the corner belongs to the left side
var zoneIndex = ledIndex - 4;
col = bitmap.GetPixel((int)(zoneIndex * xStep), bitmap.Height - 1);
}
// Right side
else
{
var zoneIndex = ledIndex - 10;
col = zoneIndex == 4
? bitmap.GetPixel(bitmap.Height - 1, bitmap.Height - (int)(zoneIndex * yStep))
: bitmap.GetPixel(bitmap.Height - 1, bitmap.Height - 1 - (int)(zoneIndex * yStep));
}
corsairLed.Color = col;
ledIndex++;
}
CueSDK.MousematSDK.Update(); CueSDK.MousematSDK.Update();
} }

View File

@ -1,12 +1,10 @@
using System; using System;
using System.Drawing;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Artemis.DeviceProviders; using Artemis.Models;
using Artemis.ViewModels; using Artemis.ViewModels;
using Ninject.Extensions.Logging; using Ninject.Extensions.Logging;
using Color = System.Drawing.Color;
namespace Artemis.Managers namespace Artemis.Managers
{ {
@ -58,7 +56,7 @@ namespace Artemis.Managers
Render(); Render();
int sleep = (int)(40f - ((DateTime.Now.Ticks - preUpdateTicks) / 10000f)); int sleep = (int)(40f - (DateTime.Now.Ticks - preUpdateTicks) / 10000f);
if (sleep > 0) if (sleep > 0)
Thread.Sleep(sleep); Thread.Sleep(sleep);
} }
@ -161,7 +159,7 @@ namespace Artemis.Managers
var keyboardOnly = !mice.Any() && !headsets.Any() && !generics.Any() && !mousemats.Any(); var keyboardOnly = !mice.Any() && !headsets.Any() && !generics.Any() && !mousemats.Any();
// Setup the frame for this tick // Setup the frame for this tick
using (var frame = new RenderFrame(_deviceManager.ActiveKeyboard, mice.Any(), headsets.Any(), generics.Any(), mousemats.Any())) using (var frame = new FrameModel(_deviceManager.ActiveKeyboard, mice.Any(), headsets.Any(), generics.Any(), mousemats.Any()))
{ {
if (renderModule.IsInitialized) if (renderModule.IsInitialized)
renderModule.Render(frame, keyboardOnly); renderModule.Render(frame, keyboardOnly);
@ -173,6 +171,9 @@ namespace Artemis.Managers
overlayModel.Render(frame, keyboardOnly); overlayModel.Render(frame, keyboardOnly);
} }
// Render the frame's drawing context to bitmaps
frame.RenderBitmaps();
// Update the keyboard // Update the keyboard
_deviceManager.ActiveKeyboard?.DrawBitmap(frame.KeyboardBitmap); _deviceManager.ActiveKeyboard?.DrawBitmap(frame.KeyboardBitmap);
@ -200,72 +201,4 @@ namespace Artemis.Managers
RenderCompleted?.Invoke(this, EventArgs.Empty); RenderCompleted?.Invoke(this, EventArgs.Empty);
} }
} }
public class RenderFrame : IDisposable
{
public RenderFrame(KeyboardProvider keyboard, bool renderMice, bool renderHeadsets, bool renderGenerics, bool renderMousemats)
{
if (keyboard == null)
return;
KeyboardBitmap = keyboard.KeyboardBitmap();
KeyboardBitmap.SetResolution(96, 96);
using (var g = Graphics.FromImage(KeyboardBitmap))
{
g.Clear(Color.Black);
}
if (renderMice)
{
MouseBitmap = new Bitmap(10, 10);
MouseBitmap.SetResolution(96, 96);
using (var g = Graphics.FromImage(MouseBitmap))
{
g.Clear(Color.Black);
}
}
if (renderHeadsets)
{
HeadsetBitmap = new Bitmap(10, 10);
HeadsetBitmap.SetResolution(96, 96);
using (var g = Graphics.FromImage(HeadsetBitmap))
{
g.Clear(Color.Black);
}
}
if (renderGenerics)
{
GenericBitmap = new Bitmap(10, 10);
GenericBitmap.SetResolution(96, 96);
using (var g = Graphics.FromImage(GenericBitmap))
{
g.Clear(Color.Black);
}
}
if (renderMousemats)
{
MousematBitmap = new Bitmap(10, 10);
MousematBitmap.SetResolution(96, 96);
using (var g = Graphics.FromImage(MousematBitmap))
{
g.Clear(Color.Black);
}
}
}
public Bitmap KeyboardBitmap { get; set; }
public Bitmap MouseBitmap { get; set; }
public Bitmap HeadsetBitmap { get; set; }
public Bitmap GenericBitmap { get; set; }
public Bitmap MousematBitmap { get; set; }
public void Dispose()
{
KeyboardBitmap?.Dispose();
MouseBitmap?.Dispose();
HeadsetBitmap?.Dispose();
GenericBitmap?.Dispose();
MousematBitmap?.Dispose();
}
}
} }

View File

@ -0,0 +1,63 @@
using System.Drawing;
using System.Windows;
using System.Windows.Media;
using Artemis.DeviceProviders;
using Artemis.Profiles.Layers.Interfaces;
using Color = System.Drawing.Color;
namespace Artemis.Models
{
public class DeviceVisualModel : DrawingVisual
{
private readonly int _x;
private readonly KeyboardProvider _keyboard;
public DeviceVisualModel(DrawType drawType, int x)
{
_x = x;
DrawType = drawType;
VisualBitmapScalingMode = BitmapScalingMode.LowQuality;
}
public DeviceVisualModel(KeyboardProvider keyboard, int x)
{
_x = x;
_keyboard = keyboard;
DrawType = DrawType.Keyboard;
VisualBitmapScalingMode = BitmapScalingMode.LowQuality;
}
public DrawType DrawType { get; }
public Rect RelativeRect => DrawType == DrawType.Keyboard
? new Rect(_x, 0, _keyboard.Width * 4, _keyboard.Height * 4)
: new Rect(_x, 0, 20, 20);
public Rect Rect => DrawType == DrawType.Keyboard
? new Rect(0, 0, _keyboard.Width * 4, _keyboard.Height * 4)
: new Rect(0, 0, 20, 20);
public Rectangle RelativeRectangle => DrawType == DrawType.Keyboard
? new Rectangle(_x, 0, _keyboard.Width * 4, _keyboard.Height * 4)
: new Rectangle(_x, 0, 20, 20);
public Bitmap GetBitmapFromFrame(Bitmap frame)
{
var bitmap = DrawType == DrawType.Keyboard
? new Bitmap(_keyboard.Width * 4, _keyboard.Height * 4)
: new Bitmap(20, 20);
bitmap.SetResolution(96, 96);
using (var g = Graphics.FromImage(bitmap))
{
g.Clear(Color.Black);
g.DrawImage(frame, new Rectangle(0, 0, bitmap.Width, bitmap.Height), RelativeRectangle,
GraphicsUnit.Pixel);
}
return bitmap;
}
}
}

View File

@ -0,0 +1,109 @@
using System;
using System.Drawing;
using System.Windows;
using System.Windows.Media;
using Artemis.DeviceProviders;
using Artemis.Profiles.Layers.Interfaces;
using Artemis.Utilities;
using Color = System.Windows.Media.Color;
using Pen = System.Windows.Media.Pen;
namespace Artemis.Models
{
public class FrameModel : IDisposable
{
private readonly Rect _rect;
public FrameModel(KeyboardProvider keyboard, bool renderMice, bool renderHeadsets, bool renderGenerics,
bool renderMousemats)
{
if (keyboard == null)
return;
// Setup bitmaps
var x = 0;
if (renderMice)
{
MouseModel = new DeviceVisualModel(DrawType.Mouse, x);
x += 20;
}
if (renderHeadsets)
{
HeadsetModel = new DeviceVisualModel(DrawType.Headset, x);
x += 20;
}
if (renderGenerics)
{
GenericModel = new DeviceVisualModel(DrawType.Generic, x);
x += 20;
}
if (renderMousemats)
{
MousematModel = new DeviceVisualModel(DrawType.Mousemat, x);
x += 20;
}
KeyboardModel = new DeviceVisualModel(keyboard, x);
// If not rendering anything but keyboard, use keyboard height, else default to 40
var height = 20;
if (keyboard.Height * 4 > height)
height = keyboard.Height * 4;
_rect = new Rect(0, 0, x + keyboard.Width * 4, height);
}
public DeviceVisualModel MouseModel { get; }
public DeviceVisualModel HeadsetModel { get; }
public DeviceVisualModel GenericModel { get; }
public DeviceVisualModel MousematModel { get; }
public DeviceVisualModel KeyboardModel { get; }
public Bitmap KeyboardBitmap { get; private set; }
public Bitmap MouseBitmap { get; private set; }
public Bitmap HeadsetBitmap { get; private set; }
public Bitmap GenericBitmap { get; private set; }
public Bitmap MousematBitmap { get; private set; }
public void Dispose()
{
KeyboardBitmap?.Dispose();
MouseBitmap?.Dispose();
HeadsetBitmap?.Dispose();
GenericBitmap?.Dispose();
MousematBitmap?.Dispose();
}
public void RenderBitmaps()
{
var visual = new DrawingVisual();
using (var c = visual.RenderOpen())
{
c.PushClip(new RectangleGeometry(_rect));
c.DrawRectangle(new SolidColorBrush(Color.FromArgb(0, 0, 0, 0)), null, _rect);
if (MouseModel != null)
c.DrawRectangle(new VisualBrush(MouseModel), new Pen(), MouseModel.RelativeRect);
if (HeadsetModel != null)
c.DrawRectangle(new VisualBrush(HeadsetModel), new Pen(), HeadsetModel.RelativeRect);
if (GenericModel != null)
c.DrawRectangle(new VisualBrush(GenericModel), new Pen(), GenericModel.RelativeRect);
if (MousematModel != null)
c.DrawRectangle(new VisualBrush(MousematModel), new Pen(), MousematModel.RelativeRect);
c.DrawRectangle(new VisualBrush(KeyboardModel), new Pen(), KeyboardModel.RelativeRect);
c.Pop();
}
var frameBitmap = ImageUtilities.DrawingVisualToBitmap(visual, _rect);
if (MouseModel != null)
MouseBitmap = MouseModel.GetBitmapFromFrame(frameBitmap);
if (HeadsetModel != null)
HeadsetBitmap = HeadsetModel.GetBitmapFromFrame(frameBitmap);
if (GenericModel != null)
GenericBitmap = GenericModel.GetBitmapFromFrame(frameBitmap);
if (MousematModel != null)
MousematBitmap = MousematModel.GetBitmapFromFrame(frameBitmap);
KeyboardBitmap = KeyboardModel.GetBitmapFromFrame(frameBitmap);
}
}
}

View File

@ -1,10 +1,10 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing;
using System.Windows; using System.Windows;
using Artemis.DAL; using Artemis.DAL;
using Artemis.Events; using Artemis.Events;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Models;
using Artemis.Profiles; using Artemis.Profiles;
using Artemis.Profiles.Layers.Interfaces; using Artemis.Profiles.Layers.Interfaces;
using Artemis.Profiles.Layers.Models; using Artemis.Profiles.Layers.Models;
@ -145,7 +145,7 @@ namespace Artemis.Modules.Abstract
public abstract void Update(); public abstract void Update();
public virtual void Render(RenderFrame frame, bool keyboardOnly) public virtual void Render(FrameModel frameModel, bool keyboardOnly)
{ {
if (ProfileModel == null || DataModel == null || DeviceManager.ActiveKeyboard == null) if (ProfileModel == null || DataModel == null || DeviceManager.ActiveKeyboard == null)
return; return;
@ -159,44 +159,19 @@ namespace Artemis.Modules.Abstract
var preview = PreviewLayers != null; var preview = PreviewLayers != null;
// Render the keyboard layer-by-layer // Render the keyboard layer-by-layer
var keyboardRect = DeviceManager.ActiveKeyboard.KeyboardRectangle(); ProfileModel?.DrawLayers(frameModel.KeyboardModel, layers, DataModel, preview);
using (var g = Graphics.FromImage(frame.KeyboardBitmap))
{
ProfileModel?.DrawLayers(g, layers, DrawType.Keyboard, DataModel, keyboardRect, preview);
}
// Render mice layer-by-layer // Render mice layer-by-layer
var devRec = new Rect(0, 0, 10, 10); if (frameModel.MouseModel != null)
if (frame.MouseBitmap != null) ProfileModel?.DrawLayers(frameModel.MouseModel, layers, DataModel, preview);
{
using (var g = Graphics.FromImage(frame.MouseBitmap))
{
ProfileModel?.DrawLayers(g, layers, DrawType.Mouse, DataModel, devRec, preview);
}
}
// Render headsets layer-by-layer // Render headsets layer-by-layer
if (frame.HeadsetBitmap != null) if (frameModel.HeadsetModel != null)
{ ProfileModel?.DrawLayers(frameModel.HeadsetModel, layers, DataModel, preview);
using (var g = Graphics.FromImage(frame.HeadsetBitmap))
{
ProfileModel?.DrawLayers(g, layers, DrawType.Headset, DataModel, devRec, preview);
}
}
// Render generic devices layer-by-layer // Render generic devices layer-by-layer
if (frame.GenericBitmap != null) if (frameModel.GenericModel != null)
{ ProfileModel?.DrawLayers(frameModel.GenericModel, layers, DataModel, preview);
using (var g = Graphics.FromImage(frame.GenericBitmap))
{
ProfileModel?.DrawLayers(g, layers, DrawType.Generic, DataModel, devRec, preview);
}
}
// Render mousemats layer-by-layer // Render mousemats layer-by-layer
if (frame.MousematBitmap != null) if (frameModel.MousematModel != null)
{ ProfileModel?.DrawLayers(frameModel.MousematModel, layers, DataModel, preview);
using (var g = Graphics.FromImage(frame.MousematBitmap))
{
ProfileModel?.DrawLayers(g, layers, DrawType.Mousemat, DataModel, devRec, preview);
}
}
// Trace debugging // Trace debugging
if (DateTime.Now.AddSeconds(-2) <= _lastTrace || Logger == null) if (DateTime.Now.AddSeconds(-2) <= _lastTrace || Logger == null)

View File

@ -13,7 +13,6 @@ namespace Artemis.Modules.Games.RocketLeague
private Memory _memory; private Memory _memory;
private GamePointersCollection _pointer; private GamePointersCollection _pointer;
public RocketLeagueModel(DeviceManager deviceManager, LuaManager luaManager) : base(deviceManager, luaManager) public RocketLeagueModel(DeviceManager deviceManager, LuaManager luaManager) : base(deviceManager, luaManager)
{ {
Settings = SettingsProvider.Load<RocketLeagueSettings>(); Settings = SettingsProvider.Load<RocketLeagueSettings>();
@ -24,14 +23,14 @@ namespace Artemis.Modules.Games.RocketLeague
//var offset = new GamePointersCollection //var offset = new GamePointersCollection
//{ //{
// Game = "RocketLeague", // Game = "RocketLeague",
// GameVersion = "1.26", // GameVersion = "1.27",
// GameAddresses = new List<GamePointer> // GameAddresses = new List<GamePointer>
// { // {
// new GamePointer // new GamePointer
// { // {
// Description = "Boost", // Description = "Boost",
// BasePointer = new IntPtr(0x01666C38), // BasePointer = new IntPtr(0x016D5084),
// Offsets = new[] { 0x58, 0x668, 0x73C, 0x224} // Offsets = new[] {0xC4, 0x214, 0x320, 0x73C, 0x224}
// } // }
// } // }
//}; //};
@ -54,7 +53,7 @@ namespace Artemis.Modules.Games.RocketLeague
{ {
Updater.GetPointers(); Updater.GetPointers();
_pointer = SettingsProvider.Load<OffsetSettings>().RocketLeague; _pointer = SettingsProvider.Load<OffsetSettings>().RocketLeague;
base.Enable(); base.Enable();
} }
@ -68,7 +67,7 @@ namespace Artemis.Modules.Games.RocketLeague
_memory = new Memory(tempProcess); _memory = new Memory(tempProcess);
} }
if (ProfileModel == null || DataModel == null || _memory == null) if (ProfileModel == null || DataModel == null || _memory == null)
return; return;

View File

@ -4,6 +4,7 @@ using System.Drawing;
using System.Windows; using System.Windows;
using Artemis.DAL; using Artemis.DAL;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Models;
using Artemis.Modules.Abstract; using Artemis.Modules.Abstract;
using Artemis.Utilities; using Artemis.Utilities;
using Point = System.Windows.Point; using Point = System.Windows.Point;
@ -90,9 +91,9 @@ namespace Artemis.Modules.General.Bubbles
} }
} }
public override void Render(RenderFrame frame, bool keyboardOnly) public override void Render(FrameModel frameModel, bool keyboardOnly)
{ {
using (var g = Graphics.FromImage(frame.KeyboardBitmap)) using (var g = Graphics.FromImage(frameModel.KeyboardBitmap))
{ {
foreach (var bubble in _bubbles) foreach (var bubble in _bubbles)
bubble.Draw(g); bubble.Draw(g);

View File

@ -70,7 +70,9 @@ namespace Artemis.Modules.General.GeneralProfile
[MoonSharpUserData] [MoonSharpUserData]
public class PerformanceDataModel public class PerformanceDataModel
{ {
public int RAMUsage { get; set; } public float RamTotal { get; set; }
public float RamUsed { get; set; }
public float RamFree { get; set; }
} }
[MoonSharpUserData] [MoonSharpUserData]

View File

@ -63,10 +63,12 @@ namespace Artemis.Modules.General.GeneralProfile
private void UpdateDay(GeneralProfileDataModel dataModel) private void UpdateDay(GeneralProfileDataModel dataModel)
{ {
var now = DateTime.Now; var now = DateTime.Now;
dataModel.CurrentTime.Hours24 = int.Parse(now.ToString("HH")); dataModel.CurrentTime.Hours24 = now.Hour;
dataModel.CurrentTime.Hours12 = int.Parse(now.ToString("hh")); dataModel.CurrentTime.Minutes = now.Minute;
dataModel.CurrentTime.Minutes = int.Parse(now.ToString("mm")); dataModel.CurrentTime.Seconds = now.Second;
dataModel.CurrentTime.Seconds = int.Parse(now.ToString("ss")); dataModel.CurrentTime.Hours12 = now.Hour >= 13
? now.Hour - 12
: now.Hour;
} }
#endregion #endregion
@ -105,7 +107,7 @@ namespace Artemis.Modules.General.GeneralProfile
// Update microphone, only bother with OverallPeak // Update microphone, only bother with OverallPeak
if (_defaultRecording != null) if (_defaultRecording != null)
dataModel.Audio.Recording.OverallPeak = _recordingInfo.PeakValue; dataModel.Audio.Recording.OverallPeak = _recordingInfo.PeakValue;
if (_defaultPlayback == null) if (_defaultPlayback == null)
return; return;
@ -176,16 +178,16 @@ namespace Artemis.Modules.General.GeneralProfile
dataModel.Cpu.Core7Usage = (int) _cores[6].NextValue(); dataModel.Cpu.Core7Usage = (int) _cores[6].NextValue();
if (_cores[7] != null) if (_cores[7] != null)
dataModel.Cpu.Core8Usage = (int) _cores[7].NextValue(); dataModel.Cpu.Core8Usage = (int) _cores[7].NextValue();
//From Ted - Let's get overall RAM and CPU usage here
dataModel.Cpu.TotalUsage = (int) _overallCpu.NextValue(); dataModel.Cpu.TotalUsage = (int) _overallCpu.NextValue();
var phav = PerformanceInfo.GetPhysicalAvailableMemoryInMiB(); // Get RAM usage
var tot = PerformanceInfo.GetTotalMemoryInMiB(); var memoryStatus = new PerformanceInfo.MEMORYSTATUSEX();
var percentFree = phav / (decimal) tot * 100; var gotMemoryStatus = PerformanceInfo.GlobalMemoryStatusEx(memoryStatus);
var percentOccupied = 100 - percentFree; if (!gotMemoryStatus)
return;
dataModel.Performance.RAMUsage = (int) percentOccupied; dataModel.Performance.RamTotal = (memoryStatus.ullTotalPhys / 1024f) / 1024f;
dataModel.Performance.RamFree = (memoryStatus.ullAvailPhys / 1024f) / 1024f;
dataModel.Performance.RamUsed = dataModel.Performance.RamTotal - dataModel.Performance.RamFree;
} }
public static PerformanceCounter GetOverallPerformanceCounter() public static PerformanceCounter GetOverallPerformanceCounter()

View File

@ -4,45 +4,28 @@ using System.Runtime.InteropServices;
namespace Artemis.Modules.General.GeneralProfile namespace Artemis.Modules.General.GeneralProfile
{ {
internal static class PerformanceInfo internal static class PerformanceInfo
{ {
[DllImport("psapi.dll", SetLastError = true)] [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public class MEMORYSTATUSEX
{
public uint dwLength;
public uint dwMemoryLoad;
public ulong ullTotalPhys;
public ulong ullAvailPhys;
public ulong ullTotalPageFile;
public ulong ullAvailPageFile;
public ulong ullTotalVirtual;
public ulong ullAvailVirtual;
public ulong ullAvailExtendedVirtual;
public MEMORYSTATUSEX()
{
this.dwLength = (uint)Marshal.SizeOf(typeof(MEMORYSTATUSEX));
}
}
[return: MarshalAs(UnmanagedType.Bool)] [return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetPerformanceInfo([Out] out PerformanceInformation performanceInformation, [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[In] int size); public static extern bool GlobalMemoryStatusEx([In, Out] MEMORYSTATUSEX lpBuffer);
public static long GetPhysicalAvailableMemoryInMiB()
{
var pi = new PerformanceInformation();
if (GetPerformanceInfo(out pi, Marshal.SizeOf(pi)))
return Convert.ToInt64(pi.PhysicalAvailable.ToInt64()*pi.PageSize.ToInt64()/1048576);
return -1;
}
public static long GetTotalMemoryInMiB()
{
var pi = new PerformanceInformation();
if (GetPerformanceInfo(out pi, Marshal.SizeOf(pi)))
return Convert.ToInt64(pi.PhysicalTotal.ToInt64()*pi.PageSize.ToInt64()/1048576);
return -1;
}
[StructLayout(LayoutKind.Sequential)]
public struct PerformanceInformation
{
public int Size;
public IntPtr CommitTotal;
public IntPtr CommitLimit;
public IntPtr CommitPeak;
public IntPtr PhysicalTotal;
public IntPtr PhysicalAvailable;
public IntPtr SystemCache;
public IntPtr KernelTotal;
public IntPtr KernelPaged;
public IntPtr KernelNonPaged;
public IntPtr PageSize;
public int HandlesCount;
public int ProcessCount;
public int ThreadCount;
}
} }
} }

View File

@ -1,6 +1,7 @@
using Artemis.DAL; using Artemis.DAL;
using Artemis.Events; using Artemis.Events;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Models;
using Artemis.Modules.Abstract; using Artemis.Modules.Abstract;
using Artemis.Modules.General.GeneralProfile; using Artemis.Modules.General.GeneralProfile;
using CSCore.CoreAudioAPI; using CSCore.CoreAudioAPI;
@ -51,10 +52,10 @@ namespace Artemis.Modules.Overlays.OverlayProfile
dataModel.Audio.Volume = _endPointVolume.GetMasterVolumeLevelScalar(); dataModel.Audio.Volume = _endPointVolume.GetMasterVolumeLevelScalar();
} }
public override void Render(RenderFrame frame, bool keyboardOnly) public override void Render(FrameModel frameModel, bool keyboardOnly)
{ {
if (Settings.IsEnabled) if (Settings.IsEnabled)
base.Render(frame, keyboardOnly); base.Render(frameModel, keyboardOnly);
} }
public override void Dispose() public override void Dispose()

View File

@ -18,7 +18,7 @@ namespace Artemis.Profiles.Layers.Types.Generic
public string Name => "Generic (Logitech)"; public string Name => "Generic (Logitech)";
public bool ShowInEdtor => false; public bool ShowInEdtor => false;
public DrawType DrawType => DrawType.Generic; public DrawType DrawType => DrawType.Generic;
public int DrawScale => 1; public int DrawScale => 2;
public ImageSource DrawThumbnail(LayerModel layer) public ImageSource DrawThumbnail(LayerModel layer)
{ {

View File

@ -9,7 +9,6 @@ using Artemis.Profiles.Layers.Models;
using Artemis.Properties; using Artemis.Properties;
using Artemis.Utilities; using Artemis.Utilities;
using Artemis.ViewModels; using Artemis.ViewModels;
using Artemis.ViewModels.Profiles;
namespace Artemis.Profiles.Layers.Types.Headset namespace Artemis.Profiles.Layers.Types.Headset
{ {
@ -18,7 +17,7 @@ namespace Artemis.Profiles.Layers.Types.Headset
public string Name => "Headset"; public string Name => "Headset";
public bool ShowInEdtor => false; public bool ShowInEdtor => false;
public DrawType DrawType => DrawType.Headset; public DrawType DrawType => DrawType.Headset;
public int DrawScale => 1; public int DrawScale => 2;
public ImageSource DrawThumbnail(LayerModel layer) public ImageSource DrawThumbnail(LayerModel layer)
{ {

View File

@ -9,7 +9,6 @@ using Artemis.Profiles.Layers.Models;
using Artemis.Properties; using Artemis.Properties;
using Artemis.Utilities; using Artemis.Utilities;
using Artemis.ViewModels; using Artemis.ViewModels;
using Artemis.ViewModels.Profiles;
namespace Artemis.Profiles.Layers.Types.Mouse namespace Artemis.Profiles.Layers.Types.Mouse
{ {
@ -18,7 +17,7 @@ namespace Artemis.Profiles.Layers.Types.Mouse
public string Name => "Mouse"; public string Name => "Mouse";
public bool ShowInEdtor => false; public bool ShowInEdtor => false;
public DrawType DrawType => DrawType.Mouse; public DrawType DrawType => DrawType.Mouse;
public int DrawScale => 1; public int DrawScale => 2;
public ImageSource DrawThumbnail(LayerModel layer) public ImageSource DrawThumbnail(LayerModel layer)
{ {

View File

@ -9,7 +9,6 @@ using Artemis.Profiles.Layers.Models;
using Artemis.Properties; using Artemis.Properties;
using Artemis.Utilities; using Artemis.Utilities;
using Artemis.ViewModels; using Artemis.ViewModels;
using Artemis.ViewModels.Profiles;
namespace Artemis.Profiles.Layers.Types.Mousemat namespace Artemis.Profiles.Layers.Types.Mousemat
{ {
@ -18,7 +17,7 @@ namespace Artemis.Profiles.Layers.Types.Mousemat
public string Name => "Mousemat"; public string Name => "Mousemat";
public bool ShowInEdtor => false; public bool ShowInEdtor => false;
public DrawType DrawType => DrawType.Mousemat; public DrawType DrawType => DrawType.Mousemat;
public int DrawScale => 1; public int DrawScale => 2;
public ImageSource DrawThumbnail(LayerModel layer) public ImageSource DrawThumbnail(LayerModel layer)
{ {
@ -41,7 +40,7 @@ namespace Artemis.Profiles.Layers.Types.Mousemat
} }
// Otherwise draw the rectangle with its applied dimensions and brush // Otherwise draw the rectangle with its applied dimensions and brush
var rect = layerModel.LayerRect(1); var rect = layerModel.LayerRect(DrawScale);
// Can't meddle with the original brush because it's frozen. // Can't meddle with the original brush because it's frozen.
var brush = layerModel.Brush.Clone(); var brush = layerModel.Brush.Clone();

View File

@ -8,6 +8,7 @@ using System.Windows.Media;
using Artemis.DeviceProviders; using Artemis.DeviceProviders;
using Artemis.Events; using Artemis.Events;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Models;
using Artemis.Modules.Abstract; using Artemis.Modules.Abstract;
using Artemis.Profiles.Layers.Interfaces; using Artemis.Profiles.Layers.Interfaces;
using Artemis.Profiles.Layers.Models; using Artemis.Profiles.Layers.Models;
@ -98,44 +99,36 @@ namespace Artemis.Profiles
/// <summary> /// <summary>
/// Draw all the given layers on the given rect /// Draw all the given layers on the given rect
/// </summary> /// </summary>
/// <param name="g">The graphics to draw on</param> /// <param name="deviceVisualModel"></param>
/// <param name="renderLayers">The layers to render</param> /// <param name="renderLayers">The layers to render</param>
/// <param name="drawType">The type of device to draw for</param>
/// <param name="dataModel">The data model to base the layer's properties on</param> /// <param name="dataModel">The data model to base the layer's properties on</param>
/// <param name="rect">A rectangle matching the current keyboard's size on a scale of 4, used for clipping</param>
/// <param name="preview">Indicates wheter the layer is drawn as a preview, ignoring dynamic properties</param> /// <param name="preview">Indicates wheter the layer is drawn as a preview, ignoring dynamic properties</param>
internal void DrawLayers(Graphics g, List<LayerModel> renderLayers, DrawType drawType, ModuleDataModel dataModel, internal void DrawLayers(DeviceVisualModel deviceVisualModel, List<LayerModel> renderLayers,
Rect rect, bool preview) ModuleDataModel dataModel, bool preview)
{ {
renderLayers = renderLayers.Where(rl => rl.LayerType.DrawType == drawType).ToList(); renderLayers = renderLayers.Where(rl => rl.LayerType.DrawType == deviceVisualModel.DrawType).ToList();
if (!renderLayers.Any()) if (!renderLayers.Any())
return; return;
var visual = new DrawingVisual(); // Setup the DrawingVisual's size
using (var c = visual.RenderOpen()) using (var c = deviceVisualModel.RenderOpen())
{ {
// Setup the DrawingVisual's size c.PushClip(new RectangleGeometry(deviceVisualModel.Rect));
c.PushClip(new RectangleGeometry(rect)); c.DrawRectangle(new SolidColorBrush(Color.FromArgb(0, 0, 0, 0)), null, deviceVisualModel.Rect);
c.DrawRectangle(new SolidColorBrush(Color.FromArgb(0, 0, 0, 0)), null, rect);
// Update the layers // Update the layers
foreach (var layerModel in renderLayers) foreach (var layerModel in renderLayers)
layerModel.Update(dataModel, preview, true); layerModel.Update(dataModel, preview, true);
RaiseDeviceUpdatedEvent(new ProfileDeviceEventsArg(drawType, dataModel, preview, null)); RaiseDeviceUpdatedEvent(new ProfileDeviceEventsArg(deviceVisualModel.DrawType, dataModel, preview, null));
// Draw the layers // Draw the layers
foreach (var layerModel in renderLayers) foreach (var layerModel in renderLayers)
layerModel.Draw(dataModel, c, preview, true); layerModel.Draw(dataModel, c, preview, true);
RaiseDeviceDrawnEvent(new ProfileDeviceEventsArg(drawType, dataModel, preview, c)); RaiseDeviceDrawnEvent(new ProfileDeviceEventsArg(deviceVisualModel.DrawType, dataModel, preview, c));
// Remove the clip // Remove the clip
c.Pop(); c.Pop();
} }
using (var bmp = ImageUtilities.DrawingVisualToBitmap(visual, rect))
{
g.DrawImage(bmp, new PointF(0, 0));
}
} }
private void RaiseDeviceUpdatedEvent(ProfileDeviceEventsArg e) private void RaiseDeviceUpdatedEvent(ProfileDeviceEventsArg e)

View File

@ -1,4 +1,5 @@
using System.Drawing; using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging; using System.Drawing.Imaging;
using System.IO; using System.IO;
using System.Windows; using System.Windows;
@ -66,8 +67,9 @@ namespace Artemis.Utilities
// RenderTargetBitmap construction is expensive, only do it when needed // RenderTargetBitmap construction is expensive, only do it when needed
if (_rBmp?.PixelHeight != height || _rBmp?.PixelWidth != width) if (_rBmp?.PixelHeight != height || _rBmp?.PixelWidth != width)
_rBmp = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32); _rBmp = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32);
else
_rBmp.Clear();
_rBmp.Clear();
_rBmp.Render(visual); _rBmp.Render(visual);
return GetBitmap(_rBmp); return GetBitmap(_rBmp);
} }

View File

@ -4,6 +4,7 @@ using System.Linq;
using System.Windows; using System.Windows;
using System.Windows.Media; using System.Windows.Media;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Models;
using Artemis.Utilities; using Artemis.Utilities;
using Caliburn.Micro; using Caliburn.Micro;
@ -123,7 +124,7 @@ namespace Artemis.ViewModels
RazerDisplay = drawnDisplay; RazerDisplay = drawnDisplay;
} }
public void DrawFrame(RenderFrame frame) public void DrawFrame(FrameModel frameModel)
{ {
// No point updating the display if the view isn't visible // No point updating the display if the view isn't visible
if (!IsActive) if (!IsActive)
@ -133,17 +134,17 @@ namespace Artemis.ViewModels
if (_deviceManager.ActiveKeyboard != null) if (_deviceManager.ActiveKeyboard != null)
{ {
var rect = _deviceManager.ActiveKeyboard.KeyboardRectangle(1); var rect = _deviceManager.ActiveKeyboard.KeyboardRectangle(1);
Keyboard = ImageUtilities.BitmapToDrawingImage(frame.KeyboardBitmap, rect); Keyboard = ImageUtilities.BitmapToDrawingImage(frameModel.KeyboardBitmap, rect);
} }
if (frame.MouseBitmap != null) if (frameModel.MouseBitmap != null)
Mouse = ImageUtilities.BitmapToDrawingImage(frame.MouseBitmap, new Rect(0, 0, 10, 10)); Mouse = ImageUtilities.BitmapToDrawingImage(frameModel.MouseBitmap, new Rect(0, 0, 10, 10));
if (frame.HeadsetBitmap != null) if (frameModel.HeadsetBitmap != null)
Headset = ImageUtilities.BitmapToDrawingImage(frame.HeadsetBitmap, new Rect(0, 0, 10, 10)); Headset = ImageUtilities.BitmapToDrawingImage(frameModel.HeadsetBitmap, new Rect(0, 0, 10, 10));
if (frame.MousematBitmap != null) if (frameModel.MousematBitmap != null)
Mousemat = ImageUtilities.BitmapToDrawingImage(frame.MousematBitmap, new Rect(0, 0, 10, 10)); Mousemat = ImageUtilities.BitmapToDrawingImage(frameModel.MousematBitmap, new Rect(0, 0, 10, 10));
if (frame.GenericBitmap != null) if (frameModel.GenericBitmap != null)
Generic = ImageUtilities.BitmapToDrawingImage(frame.GenericBitmap, new Rect(0, 0, 10, 10)); Generic = ImageUtilities.BitmapToDrawingImage(frameModel.GenericBitmap, new Rect(0, 0, 10, 10));
} }
} }
} }

View File

@ -14,15 +14,15 @@
<converters:LayerOrderConverter x:Key="LayerOrderConverter" /> <converters:LayerOrderConverter x:Key="LayerOrderConverter" />
<Storyboard x:Key="Pulse" RepeatBehavior="Forever"> <Storyboard x:Key="Pulse" RepeatBehavior="Forever">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="BlurRadius" Storyboard.TargetName="ShadowEffect"> <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="BlurRadius" Storyboard.TargetName="ShadowEffect">
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="25"/> <EasingDoubleKeyFrame KeyTime="0:0:0" Value="25" />
<EasingDoubleKeyFrame KeyTime="0:0:2" Value="10"/> <EasingDoubleKeyFrame KeyTime="0:0:2" Value="10" />
<EasingDoubleKeyFrame KeyTime="0:0:4" Value="25"/> <EasingDoubleKeyFrame KeyTime="0:0:4" Value="25" />
</DoubleAnimationUsingKeyFrames> </DoubleAnimationUsingKeyFrames>
</Storyboard> </Storyboard>
</UserControl.Resources> </UserControl.Resources>
<UserControl.Triggers> <UserControl.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded"> <EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard Storyboard="{StaticResource Pulse}"/> <BeginStoryboard Storyboard="{StaticResource Pulse}" />
</EventTrigger> </EventTrigger>
</UserControl.Triggers> </UserControl.Triggers>
<Grid Width="Auto" Height="Auto"> <Grid Width="Auto" Height="Auto">
@ -43,7 +43,8 @@
BorderThickness="3" Width="800" Height="400"> BorderThickness="3" Width="800" Height="400">
<Border> <Border>
<Border.Effect> <Border.Effect>
<DropShadowEffect x:Name="ShadowEffect" ShadowDepth="0" Color="{DynamicResource HighlightColor}" Opacity="1" /> <DropShadowEffect x:Name="ShadowEffect" ShadowDepth="0" Color="{DynamicResource HighlightColor}"
Opacity="1" />
</Border.Effect> </Border.Effect>
<Grid> <Grid>
<Image Grid.Column="0" Grid.Row="0" Source="{Binding Path=KeyboardImage}" <Image Grid.Column="0" Grid.Row="0" Source="{Binding Path=KeyboardImage}"
@ -125,7 +126,7 @@
<StackPanel Grid.Column="0" Grid.Row="2" Orientation="Horizontal" Margin="0,5,0,0" HorizontalAlignment="Right"> <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}" <Button x:Name="ImportProfile" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}"
Height="26" HorizontalAlignment="Right" ToolTip="Import profile"> Height="26" HorizontalAlignment="Right">
<Button.Content> <Button.Content>
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<Rectangle <Rectangle
@ -154,9 +155,8 @@
</StackPanel> </StackPanel>
</Button.Content> </Button.Content>
</Button> </Button>
<Button x:Name="EditLua" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}" <Button x:Name="EditLua" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}" Height="26"
Height="26" HorizontalAlignment="Right" Margin="10,0,0,0" ToolTip="Import profile" HorizontalAlignment="Right" Margin="10,0,0,0" IsEnabled="{Binding Path=EditorEnabled, Mode=OneWay}"
IsEnabled="{Binding Path=EditorEnabled, Mode=OneWay}"
Visibility="{Binding Path=LuaButtonVisible, Converter={StaticResource BoolToVis} }"> Visibility="{Binding Path=LuaButtonVisible, Converter={StaticResource BoolToVis} }">
<Button.Content> <Button.Content>
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">