diff --git a/Artemis/Artemis/ArtemisBootstrapper.cs b/Artemis/Artemis/ArtemisBootstrapper.cs index ddb65e86d..c50498429 100644 --- a/Artemis/Artemis/ArtemisBootstrapper.cs +++ b/Artemis/Artemis/ArtemisBootstrapper.cs @@ -61,7 +61,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,7 +98,7 @@ namespace Artemis logger.Info("Artemis was run using the autorun shortcut, sleeping for 15 sec."); Thread.Sleep(15000); } - InputHook.Start(); + _kernel = new StandardKernel(new BaseModules(), new ManagerModules()); _kernel.Bind().To().InSingletonScope(); @@ -145,6 +145,7 @@ namespace Artemis protected override void OnStartup(object sender, StartupEventArgs e) { DisplayRootViewFor(); + InputHook.Start(); } } } \ No newline at end of file diff --git a/Artemis/Artemis/Profiles/Layers/Models/LayerKeybindModel.cs b/Artemis/Artemis/Profiles/Layers/Models/LayerKeybindModel.cs index 087e506ec..74453a110 100644 --- a/Artemis/Artemis/Profiles/Layers/Models/LayerKeybindModel.cs +++ b/Artemis/Artemis/Profiles/Layers/Models/LayerKeybindModel.cs @@ -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: diff --git a/Artemis/Artemis/Profiles/Layers/Models/LayerModel.cs b/Artemis/Artemis/Profiles/Layers/Models/LayerModel.cs index 8007936f5..25f27bf48 100644 --- a/Artemis/Artemis/Profiles/Layers/Models/LayerModel.cs +++ b/Artemis/Artemis/Profiles/Layers/Models/LayerModel.cs @@ -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, IChildItem - { - public LayerModel() - { - Children = new ChildItemCollection(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; } - - /// - /// Checks whether this layers conditions are met. - /// If they are met and this layer is an event, this also triggers that event. - /// - /// - /// - public bool AreConditionsMet(ModuleDataModel dataModel) - { - // Conditions are not even checked if the layer isn't enabled - return Enabled && LayerCondition.ConditionsMet(this, dataModel); - } - - /// - /// Update the layer - /// - /// - /// - /// - 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; - } - - /// - /// Applies the saved properties to the current properties - /// - /// Include advanced properties (opacity, brush) - 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; - } - - /// - /// Draw the layer using the provided context - /// - /// - /// - /// - /// - public void Draw(ModuleDataModel dataModel, DrawingContext c, bool preview, bool updateAnimations) - { - if (Brush == null || !preview && !RenderAllowed) - return; - - LayerType.Draw(this, c); - } - - /// - /// Tells the current layer type to setup the layer's LayerProperties - /// - 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) - }; - } - - /// - /// Ensures all child layers have a unique order - /// - public void FixOrder() - { - Children.Sort(l => l.Order); - for (var i = 0; i < Children.Count; i++) - Children[i].Order = i; - } - - /// - /// Returns whether the layer meets the requirements to be drawn in the profile editor - /// - /// - 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; - } - - /// - /// Returns every descendant of this layer - /// - /// - public IEnumerable GetLayers() - { - var layers = new List(); - foreach (var layerModel in Children.OrderBy(c => c.Order)) - { - layers.Add(layerModel); - layers.AddRange(layerModel.GetLayers()); - } - - return layers; - } - - /// - /// Creates a new Keyboard layer with default settings - /// - /// - 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" - } - }; - } - - /// - /// Insert this layer before the given layer - /// - /// - public void InsertBefore(LayerModel source) - { - source.Order = Order; - Insert(source); - } - - /// - /// Insert this layer after the given layer - /// - /// - public void InsertAfter(LayerModel source) - { - source.Order = Order + 1; - Insert(source); - } - - /// - /// Insert the layer as a sibling - /// - /// - 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 - /// - /// 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 - /// - /// Instance of said game data model - /// Whether or not to ignore anything but keyboards - /// - /// A flat list containing all layers that must be rendered - public List 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, IChildItem + { + public LayerModel() + { + Children = new ChildItemCollection(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; } + + /// + /// Checks whether this layers conditions are met. + /// If they are met and this layer is an event, this also triggers that event. + /// + /// + /// + public bool AreConditionsMet(ModuleDataModel dataModel) + { + // Conditions are not even checked if the layer isn't enabled + return Enabled && LayerCondition.ConditionsMet(this, dataModel); + } + + /// + /// Update the layer + /// + /// + /// + /// + 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; + } + + /// + /// Applies the saved properties to the current properties + /// + /// Include advanced properties (opacity, brush) + 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; + } + + /// + /// Draw the layer using the provided context + /// + /// + /// + /// + /// + public void Draw(ModuleDataModel dataModel, DrawingContext c, bool preview, bool updateAnimations) + { + if (Brush == null || !preview && !RenderAllowed) + return; + + LayerType.Draw(this, c); + } + + /// + /// Tells the current layer type to setup the layer's LayerProperties + /// + 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) + }; + } + + /// + /// Ensures all child layers have a unique order + /// + public void FixOrder() + { + Children.Sort(l => l.Order); + for (var i = 0; i < Children.Count; i++) + Children[i].Order = i; + } + + /// + /// Returns whether the layer meets the requirements to be drawn in the profile editor + /// + /// + 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; + } + + /// + /// Returns every descendant of this layer + /// + /// + public IEnumerable GetLayers() + { + var layers = new List(); + foreach (var layerModel in Children.OrderBy(c => c.Order)) + { + layers.Add(layerModel); + layers.AddRange(layerModel.GetLayers()); + } + + return layers; + } + + /// + /// Creates a new Keyboard layer with default settings + /// + /// + 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" + } + }; + } + + /// + /// Insert this layer before the given layer + /// + /// + public void InsertBefore(LayerModel source) + { + source.Order = Order; + Insert(source); + } + + /// + /// Insert this layer after the given layer + /// + /// + public void InsertAfter(LayerModel source) + { + source.Order = Order + 1; + Insert(source); + } + + /// + /// Insert the layer as a sibling + /// + /// + 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 + /// + /// 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 + /// + /// Instance of said game data model + /// Whether or not to ignore anything but keyboards + /// + /// A flat list containing all layers that must be rendered + public List GetRenderLayers(ModuleDataModel dataModel, bool keyboardOnly, bool ignoreConditions = false) + { var layers = new List(); 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 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 Members - - LayerModel IChildItem.Parent - { - get { return Parent; } - set { Parent = value; } - } - - ProfileModel IChildItem.Parent - { - get { return Profile; } - set { Profile = value; } - } - - #endregion - - /// - 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 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 Members + + LayerModel IChildItem.Parent + { + get { return Parent; } + set { Parent = value; } + } + + ProfileModel IChildItem.Parent + { + get { return Profile; } + set { Profile = value; } + } + + #endregion + + /// + public override string ToString() + { + return $"{nameof(Name)}: {Name}, {nameof(Order)}: {Order}, {nameof(X)}: {X}, {nameof(Y)}: {Y}, {nameof(Width)}: {Width}, {nameof(Height)}: {Height}"; + } + } +} diff --git a/Artemis/Artemis/Profiles/Layers/Models/LayerPropertiesModel.cs b/Artemis/Artemis/Profiles/Layers/Models/LayerPropertiesModel.cs index c1ec39f17..3fcd8df46 100644 --- a/Artemis/Artemis/Profiles/Layers/Models/LayerPropertiesModel.cs +++ b/Artemis/Artemis/Profiles/Layers/Models/LayerPropertiesModel.cs @@ -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 Conditions { get; set; } = new List(); - public List LayerKeybindModels { get; set; } = new List(); - public List DynamicProperties { get; set; } = new List(); - - [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 LayerKeybindModels { get; set; } = new List(); + public List DynamicProperties { get; set; } = new List(); + + [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 + } } \ No newline at end of file diff --git a/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs b/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs index 9916680fa..d7699475c 100644 --- a/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs +++ b/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs @@ -324,7 +324,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 @@ -333,28 +333,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(data); - if (layerModel == null) - return; - - if (SelectedLayer != null) - SelectedLayer.InsertAfter(layerModel); - else + GeneralHelpers.ExecuteSta(() => { - SelectedProfile.Layers.Add(layerModel); - SelectedProfile.FixOrder(); - } - Execute.OnUIThread(() => UpdateLayerList(layerModel)); - }); + var data = (string) Clipboard.GetData("layer"); + if (data == null) + return; + + var layerModel = JsonConvert.DeserializeObject(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) @@ -665,7 +672,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; @@ -681,7 +688,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); @@ -703,6 +710,8 @@ namespace Artemis.ViewModels KeyboardPreviewCursor = Cursors.Hand; } + + private Point GetScaledPosition(MouseEventArgs e) { var previewSettings = _deviceManager.ActiveKeyboard.PreviewSettings; @@ -723,6 +732,15 @@ namespace Artemis.ViewModels 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; }