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

Profile preview rewrite

This commit is contained in:
SpoinkyNL 2017-01-05 16:01:34 +01:00
parent fdcb3568d9
commit 9ddde37333
16 changed files with 938 additions and 892 deletions

View File

@ -336,6 +336,7 @@
<Compile Include="Events\ModuleChangedEventArgs.cs" />
<Compile Include="Events\EnabledChangedEventArgs.cs" />
<Compile Include="Events\KeyboardChangedEventArgs.cs" />
<Compile Include="Events\ProfileChangedEventArgs.cs" />
<Compile Include="Events\ProfileDeviceEventsArg.cs" />
<Compile Include="Events\RazerColorArrayChanged.cs" />
<Compile Include="Events\RazerColorsChangedEventArgs.cs" />

View File

@ -0,0 +1,15 @@
using System;
using Artemis.Profiles;
namespace Artemis.Events
{
public class ProfileChangedEventArgs : EventArgs
{
public ProfileChangedEventArgs(ProfileModel profileModel)
{
ProfileModel = profileModel;
}
public ProfileModel ProfileModel { get; }
}
}

View File

@ -137,6 +137,10 @@ namespace Artemis.Managers
var processes = System.Diagnostics.Process.GetProcesses();
var module = ModuleManager.ActiveModule;
// If the current active module is in preview-mode, leave it alone
if (module?.PreviewLayers != null)
return;
// If the active module is a process bound module, make sure it should still be enabled
if (module != null && module.IsBoundToProcess)
{

View File

@ -72,7 +72,8 @@ namespace Artemis.Managers
/// </summary>
/// <param name="moduleModel">The module to activate</param>
/// <param name="loopManager">Optionally pass the LoopManager to automatically start it, if it's not running.</param>
public void ChangeActiveModule(ModuleModel moduleModel, LoopManager loopManager = null)
/// <param name="storeAsLast">Whether or not to store this effect as the last effect</param>
public void ChangeActiveModule(ModuleModel moduleModel, LoopManager loopManager = null, bool storeAsLast = true)
{
if (_waitEffect != null)
{
@ -82,8 +83,6 @@ namespace Artemis.Managers
if (moduleModel == null)
throw new ArgumentNullException(nameof(moduleModel));
if (moduleModel.IsOverlay)
throw new ArgumentException("Can't set an General module as the active module");
if (_deviceManager.ActiveKeyboard == null)
{
@ -102,7 +101,6 @@ namespace Artemis.Managers
return;
}
var wasNull = false;
if (ActiveModule == null)
{
@ -135,9 +133,8 @@ namespace Artemis.Managers
_logger.Debug("Changed active module to: {0}", moduleModel.Name);
if (ActiveModule.IsBoundToProcess || ActiveModule.IsOverlay || ActiveModule.Name == "Profile preview")
if (ActiveModule.IsBoundToProcess || ActiveModule.IsOverlay || !storeAsLast)
return;
// Regular modules are stored as the last active module
_generalSettings.LastModule = ActiveModule?.Name;
_generalSettings.Save();
@ -156,7 +153,6 @@ namespace Artemis.Managers
ChangeActiveModule(module, loopManager);
}
/// <summary>
/// Clears the current module
/// </summary>

View File

@ -4,18 +4,17 @@ using System.Timers;
using Artemis.DAL;
using Artemis.Modules.Abstract;
using Artemis.Settings;
using Ninject;
using Ninject.Extensions.Logging;
namespace Artemis.Managers
{
public class ProfileManager
{
private readonly ILogger _logger;
private readonly ModuleManager _moduleManager;
private readonly DeviceManager _deviceManager;
private readonly LoopManager _loopManager;
private readonly GeneralSettings _generalSettings;
private readonly ILogger _logger;
private readonly LoopManager _loopManager;
private readonly ModuleManager _moduleManager;
public ProfileManager(ILogger logger, ModuleManager moduleManager, DeviceManager deviceManager,
LoopManager loopManager)
@ -44,39 +43,41 @@ namespace Artemis.Managers
/// <param name="e"></param>
private void SetupProfilePreview(object sender, ElapsedEventArgs e)
{
// if (string.IsNullOrEmpty(_generalSettings.LastKeyboard) || _deviceManager.ChangingKeyboard)
// return;
//
// var activePreview = PreviewViewModules.FirstOrDefault(vm => vm.IsActive);
// if (activePreview == null)
// {
// // Should not be active if no selected profile is set
// if (_moduleManager.ActiveModule != _profilePreviewModel)
// return;
//
// _logger.Debug("Loading last module after profile preview");
// var lastModule = _moduleManager.GetLastModule();
// if (lastModule != null)
// _moduleManager.ChangeActiveModule(lastModule);
// else
// _moduleManager.ClearActiveModule();
// }
// else
// {
// if (_moduleManager.ActiveModule != null && _moduleManager.ActiveModule != _profilePreviewModel &&
// _moduleManager.ActiveModule != activePreview.ModuleModel)
// {
// _logger.Debug("Activate profile preview");
// _moduleManager.ChangeActiveModule(_profilePreviewModel);
// }
//
// // LoopManager might be running, this method won't do any harm in that case.
// _loopManager.StartAsync();
//
// // Can safely spam this, it won't do anything if they are equal
// _profilePreviewModel.ProfileViewModel = activePreview.ProfileEditor.ProfileViewModel;
// _profilePreviewModel.ChangeProfile(activePreview.ModuleModel.ProfileModel);
// }
if (string.IsNullOrEmpty(_generalSettings.LastKeyboard) || _deviceManager.ChangingKeyboard)
return;
var activePreview = PreviewViewModules.FirstOrDefault(vm => vm.IsActive && vm.UsesProfileEditor);
if (activePreview != null)
EnsurePreviewActive(activePreview);
else
EnsurePreviewInactive();
}
private void EnsurePreviewActive(ModuleViewModel toBeActive)
{
// If the current module is the same as what should be active, don't do anything
if (_moduleManager.ActiveModule != null && _moduleManager.ActiveModule == toBeActive.ModuleModel)
return;
_logger.Debug("Activate profile preview");
_moduleManager.ChangeActiveModule(toBeActive.ModuleModel, null, false);
// LoopManager might be running, this method won't do any harm in that case.
_loopManager.StartAsync();
}
private void EnsurePreviewInactive()
{
// Check if the active module is being previewed, if so, that should no longer be happening
if (_moduleManager.ActiveModule?.PreviewLayers == null)
return;
_logger.Debug("Deactivate profile preview");
var lastModule = _moduleManager.GetLastModule();
if (lastModule != null)
_moduleManager.ChangeActiveModule(lastModule);
else
_moduleManager.ClearActiveModule();
}
}
}

View File

@ -2,6 +2,5 @@
{
public abstract class ModuleDataModel
{
public ModuleDataModel ParentDataModel { get; set; }
}
}

View File

@ -23,13 +23,17 @@ namespace Artemis.Modules.Abstract
public ModuleModel(DeviceManager deviceManager, LuaManager luaManager)
{
_luaManager = luaManager;
DeviceManager = deviceManager;
PreviewLayers = new List<LayerModel>();
DeviceManager.OnKeyboardChanged += OnKeyboardChanged;
}
#region Events
public event EventHandler<ProfileChangedEventArgs> ProfileChanged;
#endregion
#region Abstract properties
/// <summary>
@ -95,6 +99,8 @@ namespace Artemis.Modules.Abstract
ProfileModel = profileModel;
ProfileModel?.Activate(_luaManager);
RaiseProfileChangedEvent(new ProfileChangedEventArgs(ProfileModel));
}
public virtual void Enable()
@ -107,7 +113,7 @@ namespace Artemis.Modules.Abstract
{
IsInitialized = false;
PreviewLayers.Clear();
PreviewLayers = null;
ProfileModel?.Deactivate(_luaManager);
ProfileModel = null;
}
@ -123,6 +129,12 @@ namespace Artemis.Modules.Abstract
ChangeProfile(ProfileProvider.GetProfile(DeviceManager.ActiveKeyboard, this, profileName));
}
protected virtual void RaiseProfileChangedEvent(ProfileChangedEventArgs e)
{
var handler = ProfileChanged;
handler?.Invoke(this, e);
}
public abstract void Update();
public virtual void Render(RenderFrame frame, bool keyboardOnly)
@ -134,35 +146,36 @@ namespace Artemis.Modules.Abstract
{
lock (ProfileModel)
{
// Get all enabled layers who's conditions are met
var layers = GetRenderLayers(keyboardOnly);
// Use the preview layers if they are present, else get all layers who's conditions are met
var layers = PreviewLayers ?? GetRenderLayers(keyboardOnly);
var preview = PreviewLayers != null;
// Render the keyboard layer-by-layer
var keyboardRect = DeviceManager.ActiveKeyboard.KeyboardRectangle();
using (var g = Graphics.FromImage(frame.KeyboardBitmap))
{
ProfileModel?.DrawLayers(g, layers, DrawType.Keyboard, DataModel, keyboardRect, false, true);
ProfileModel?.DrawLayers(g, layers, DrawType.Keyboard, DataModel, keyboardRect, preview);
}
// Render mice layer-by-layer
var devRec = new Rect(0, 0, 40, 40);
using (var g = Graphics.FromImage(frame.MouseBitmap))
{
ProfileModel?.DrawLayers(g, layers, DrawType.Mouse, DataModel, devRec, false, true);
ProfileModel?.DrawLayers(g, layers, DrawType.Mouse, DataModel, devRec, preview);
}
// Render headsets layer-by-layer
using (var g = Graphics.FromImage(frame.HeadsetBitmap))
{
ProfileModel?.DrawLayers(g, layers, DrawType.Headset, DataModel, devRec, false, true);
ProfileModel?.DrawLayers(g, layers, DrawType.Headset, DataModel, devRec, preview);
}
// Render generic devices layer-by-layer
using (var g = Graphics.FromImage(frame.GenericBitmap))
{
ProfileModel?.DrawLayers(g, layers, DrawType.Generic, DataModel, devRec, false, true);
ProfileModel?.DrawLayers(g, layers, DrawType.Generic, DataModel, devRec, preview);
}
// Render mousemats layer-by-layer
using (var g = Graphics.FromImage(frame.MousematBitmap))
{
ProfileModel?.DrawLayers(g, layers, DrawType.Mousemat, DataModel, devRec, false, true);
ProfileModel?.DrawLayers(g, layers, DrawType.Mousemat, DataModel, devRec, preview);
}
// Trace debugging

View File

@ -13,22 +13,16 @@ namespace Artemis.Modules.Abstract
{
private readonly ModuleManager _moduleManager;
private readonly MainManager _mainManager;
private readonly IKernel _kernel;
private ModuleSettings _settings;
public ModuleViewModel(MainManager mainManager, ModuleModel moduleModel, IKernel kernel)
{
_mainManager = mainManager;
_kernel = kernel;
_moduleManager = mainManager.ModuleManager;
ModuleModel = moduleModel;
Settings = moduleModel.Settings;
IParameter[] args =
{
new ConstructorArgument("mainManager", _mainManager),
new ConstructorArgument("moduleModel", ModuleModel),
new ConstructorArgument("lastProfile", Settings.LastProfile)
};
ProfileEditor = kernel.Get<ProfileEditorViewModel>(args);
_mainManager.EnabledChanged += MainManagerOnEnabledChanged;
_moduleManager.EffectChanged += ModuleManagerOnModuleChanged;
@ -125,13 +119,24 @@ namespace Artemis.Modules.Abstract
protected override void OnActivate()
{
base.OnActivate();
ProfileEditor.Activate();
if (!UsesProfileEditor)
return;
IParameter[] args =
{
new ConstructorArgument("mainManager", _mainManager),
new ConstructorArgument("moduleModel", ModuleModel),
new ConstructorArgument("lastProfile", Settings.LastProfile)
};
ProfileEditor = _kernel.Get<ProfileEditorViewModel>(args);
}
protected override void OnDeactivate(bool close)
{
base.OnDeactivate(close);
ProfileEditor.Deactivate();
ProfileEditor?.Dispose();
ProfileEditor = null;
}
}
}

View File

@ -1,4 +1,5 @@
using Artemis.Modules.Abstract;
using Artemis.Modules.General.GeneralProfile;
using MoonSharp.Interpreter;
namespace Artemis.Modules.Games.Dota2
@ -14,9 +15,7 @@ namespace Artemis.Modules.Games.Dota2
public Items items { get; set; }
public Previously previously { get; set; }
}
[MoonSharpUserData]
public class Provider
{

View File

@ -29,7 +29,7 @@
</Label>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Label Content="Enable module" Margin="0 3 0 0" HorizontalAlignment="Right" />
<ToggleButton Margin="0 3 0 0" Width="25" Height="25"
<ToggleButton Margin="0 3 0 0" Width="25" Height="25"
Style="{DynamicResource MetroCircleToggleButtonStyle}"
ToolTip="Note: You can't enable an module when Artemis is disabled"
IsChecked="{Binding Path=Settings.Enabled, Mode=OneWay}"
@ -41,10 +41,9 @@
<ContentControl Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" x:Name="ProfileEditor" Margin="0,0,-30,0" />
<TextBlock x:Name="VersionText" Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="2" VerticalAlignment="Center"
Margin="0,8"
TextWrapping="Wrap" HorizontalAlignment="Left" FontFamily="Segoe UI Semibold"
Foreground="{DynamicResource HighlightBrush}" MaxWidth="510" TextAlignment="Justify" />
Margin="0,8" TextWrapping="Wrap" HorizontalAlignment="Left"
Foreground="{DynamicResource HighlightBrush}" />
<!-- Buttons -->
<StackPanel Grid.Column="0" Grid.Row="5" Orientation="Horizontal" VerticalAlignment="Bottom">
<Button x:Name="ResetSettings" Content="Reset effect" VerticalAlignment="Top" Width="100"

View File

@ -7,7 +7,9 @@ namespace Artemis.Modules.Overlays.OverlayProfile
{
public OverlayProfileDataModel()
{
ParentDataModel = new GeneralProfileDataModel();
GeneralDataModel = new GeneralProfileDataModel();
}
public GeneralProfileDataModel GeneralDataModel { get; set; }
}
}

View File

@ -25,7 +25,8 @@ namespace Artemis.Modules.Overlays.OverlayProfile
public override void Update()
{
// TODO: Find a clean way to update the parent profile model
DataModel.ParentDataModel = _generalProfileModel.DataModel;
((OverlayProfileDataModel) DataModel).GeneralDataModel =
(GeneralProfileDataModel) _generalProfileModel.DataModel;
}
}
}

View File

@ -104,9 +104,8 @@ namespace Artemis.Profiles
/// <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="updateAnimations">Wheter or not to update the layer's animations</param>
internal void DrawLayers(Graphics g, List<LayerModel> renderLayers, DrawType drawType, ModuleDataModel dataModel,
Rect rect, bool preview, bool updateAnimations)
Rect rect, bool preview)
{
renderLayers = renderLayers.Where(rl => rl.LayerType.DrawType == drawType).ToList();
var visual = new DrawingVisual();
@ -119,12 +118,12 @@ namespace Artemis.Profiles
// Update the layers
foreach (var layerModel in layerModels)
layerModel.Update(dataModel, preview, updateAnimations);
layerModel.Update(dataModel, preview, true);
RaiseDeviceUpdatedEvent(new ProfileDeviceEventsArg(drawType, dataModel, preview, null));
// Draw the layers
foreach (var layerModel in layerModels)
layerModel.Draw(dataModel, c, preview, updateAnimations);
layerModel.Draw(dataModel, c, preview, true);
RaiseDeviceDrawnEvent(new ProfileDeviceEventsArg(drawType, dataModel, preview, c));
// Remove the clip

View File

@ -35,7 +35,7 @@ namespace Artemis.Utilities
return null;
var value = prop.GetValue(o, null);
if ((propertyNames.Length == 1) || (value == null))
if (propertyNames.Length == 1 || value == null)
return value;
return GetPropertyValue(value, path.Replace(propertyNames[0] + ".", ""));
}
@ -46,31 +46,31 @@ namespace Artemis.Utilities
string path = "")
{
var list = new List<PropertyCollection>();
foreach (var propertyInfo in getProperties)
foreach (var propInfo in getProperties)
{
var friendlyName = Empty;
if (propertyInfo.PropertyType.Name == "Int32")
if (propInfo.PropertyType.Name == "Int32")
friendlyName = "(Number)";
else if (propertyInfo.PropertyType.Name == "Single")
else if (propInfo.PropertyType.Name == "Single")
friendlyName = "(Decimal)";
else if (propertyInfo.PropertyType.Name == "String")
else if (propInfo.PropertyType.Name == "String")
friendlyName = "(Text)";
else if (propertyInfo.PropertyType.Name == "Boolean")
else if (propInfo.PropertyType.Name == "Boolean")
friendlyName = "(Yes/no)";
if (propertyInfo.PropertyType.BaseType?.Name == "Enum")
if (propInfo.PropertyType.BaseType?.Name == "Enum")
friendlyName = "(Choice)";
var parent = new PropertyCollection
{
Type = propertyInfo.PropertyType.Name,
Type = propInfo.PropertyType.Name,
DisplayType = friendlyName,
Display = $"{path.Replace(".", " ")}{propertyInfo.Name}",
Path = $"{path}{propertyInfo.Name}"
Display = $"{path.Replace(".", " ")}{propInfo.Name}",
Path = $"{path}{propInfo.Name}"
};
if (propertyInfo.PropertyType.BaseType?.Name == "Enum")
if (propInfo.PropertyType.BaseType?.Name == "Enum")
{
parent.EnumValues = Enum.GetNames(propertyInfo.PropertyType);
parent.EnumValues = Enum.GetNames(propInfo.PropertyType);
parent.Type = "Enum";
}
@ -78,13 +78,10 @@ namespace Artemis.Utilities
list.Add(parent);
// Don't go into Strings, DateTimes or anything with JsonIgnore on it
if (propertyInfo.PropertyType.Name != "String" &&
propertyInfo.PropertyType.Name != "DateTime" &&
propertyInfo.CustomAttributes.All(a => a.AttributeType != typeof(JsonIgnoreAttribute)))
{
list.AddRange(GenerateTypeMap(propertyInfo.PropertyType.GetProperties(),
path + $"{propertyInfo.Name}."));
}
if (propInfo.PropertyType.Name != "String" &&
propInfo.PropertyType.Name != "DateTime" &&
propInfo.CustomAttributes.All(a => a.AttributeType != typeof(JsonIgnoreAttribute)))
list.AddRange(GenerateTypeMap(propInfo.PropertyType.GetProperties(), path + $"{propInfo.Name}."));
}
return list;
}

File diff suppressed because it is too large Load Diff

View File

@ -7,6 +7,7 @@ using System.Windows.Input;
using System.Windows.Media;
using Artemis.Events;
using Artemis.Managers;
using Artemis.Modules.Abstract;
using Artemis.Profiles;
using Artemis.Profiles.Layers.Interfaces;
using Artemis.Profiles.Layers.Models;
@ -43,7 +44,8 @@ namespace Artemis.ViewModels.Profiles
deviceManager.OnKeyboardChanged += DeviceManagerOnOnKeyboardChanged;
}
public ProfileModel SelectedProfile { get; set; }
public ModuleModel ModuleModel { get; set; }
public ProfileModel SelectedProfile => ModuleModel?.ProfileModel;
public LayerModel SelectedLayer
{
@ -99,6 +101,7 @@ namespace Artemis.ViewModels.Profiles
if (!Activated)
return;
// Update the glowing effect around the keyboard
if (_blurProgress > 2)
_blurProgress = 0;
_blurProgress = _blurProgress + 0.025;
@ -110,10 +113,17 @@ namespace Artemis.ViewModels.Profiles
{
var preview = new DrawingImage();
preview.Freeze();
KeyboardPreview = preview;
KeyboardPreview = preview;
// Setup layers for the next frame
if (ModuleModel.IsInitialized)
ModuleModel.PreviewLayers = new List<LayerModel>();
return;
}
var renderLayers = GetRenderLayers();
// Draw the current frame to the preview
var keyboardRect = _deviceManager.ActiveKeyboard.KeyboardRectangle(4);
var visual = new DrawingVisual();
using (var drawingContext = visual.RenderOpen())
@ -122,11 +132,8 @@ namespace Artemis.ViewModels.Profiles
drawingContext.PushClip(new RectangleGeometry(keyboardRect));
drawingContext.DrawRectangle(new SolidColorBrush(Color.FromArgb(0, 0, 0, 0)), null, keyboardRect);
// Get the layers that must be drawn
var drawLayers = GetRenderLayers();
// Draw the layers
foreach (var layer in drawLayers)
foreach (var layer in renderLayers)
{
layer.Update(null, true, false);
if (layer.LayerType.ShowInEdtor)
@ -166,16 +173,18 @@ namespace Artemis.ViewModels.Profiles
new Point(layerRect.BottomRight.X - 0.7, layerRect.BottomRight.Y - 0.7));
}
SelectedProfile.RaiseDeviceDrawnEvent(new ProfileDeviceEventsArg(DrawType.Preview, null, true,
drawingContext));
SelectedProfile.RaiseDeviceDrawnEvent(new ProfileDeviceEventsArg(DrawType.Preview, null, true, drawingContext));
// Remove the clip
drawingContext.Pop();
}
var drawnPreview = new DrawingImage(visual.Drawing);
drawnPreview.Freeze();
KeyboardPreview = drawnPreview;
// Setup layers for the next frame
if (ModuleModel.IsInitialized)
ModuleModel.PreviewLayers = renderLayers;
}
private void DeviceManagerOnOnKeyboardChanged(object sender, KeyboardChangedEventArgs e)