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

Profiles refactor

This commit is contained in:
SpoinkyNL 2016-05-16 20:32:21 +02:00
parent bbbbad7504
commit 9d451094cc
34 changed files with 677 additions and 614 deletions

View File

@ -306,9 +306,11 @@
<Compile Include="Models\OverlaySettings.cs" />
<Compile Include="Models\Profiles\LayerConditionModel.cs" />
<Compile Include="Models\Profiles\LayerModel.cs" />
<Compile Include="Models\Profiles\LayerDynamicPropertiesModel.cs" />
<Compile Include="Models\Profiles\LayerPropertiesModel.cs" />
<Compile Include="Models\Profiles\ProfileModel.cs" />
<Compile Include="Models\Profiles\Properties\DynamicPropertiesModel.cs" />
<Compile Include="Models\Profiles\Properties\KeyboardPropertiesModel.cs" />
<Compile Include="Models\Profiles\Properties\LayerPropertiesModel.cs" />
<Compile Include="Models\Profiles\Properties\MousePropertiesModel.cs" />
<Compile Include="Modules\Effects\AmbientLightning\AmbientLightningEffectModel.cs" />
<Compile Include="Modules\Effects\AmbientLightning\AmbientLightningEffectSettings.cs" />
<Compile Include="Modules\Effects\AmbientLightning\AmbientLightningEffectView.xaml.cs">
@ -420,7 +422,8 @@
<Compile Include="Utilities\GifImage.cs" />
<Compile Include="Utilities\ImageUtilities.cs" />
<Compile Include="Utilities\Keyboard\KeyboardHook.cs" />
<Compile Include="Utilities\LayerDrawer.cs" />
<Compile Include="Utilities\Layers\AnimationUpdater.cs" />
<Compile Include="Utilities\Layers\Drawer.cs" />
<Compile Include="Utilities\LogitechDll\DllManager.cs" />
<Compile Include="Utilities\LogitechDll\NamedPipeServer.cs" />
<Compile Include="Utilities\LogitechDll\PipeServer.cs" />
@ -451,10 +454,12 @@
<Compile Include="Modules\Games\Dota2\Dota2ViewModel.cs" />
<Compile Include="Modules\Games\RocketLeague\RocketLeagueViewModel.cs" />
<Compile Include="Modules\Games\Witcher3\Witcher3ViewModel.cs" />
<Compile Include="ViewModels\LayerEditor\LayerKeyboardViewModel.cs" />
<Compile Include="ViewModels\LayerEditor\KeyboardPropertiesViewModel.cs" />
<Compile Include="ViewModels\LayerEditor\LayerConditionViewModel.cs" />
<Compile Include="ViewModels\LayerEditor\LayerDynamicPropertiesViewModel.cs" />
<Compile Include="ViewModels\LayerEditor\LayerEditorViewModel.cs" />
<Compile Include="ViewModels\LayerEditor\LayerPropertiesViewModel.cs" />
<Compile Include="ViewModels\LayerEditor\MousePropertiesViewModel.cs" />
<Compile Include="ViewModels\OverlaysViewModel.cs" />
<Compile Include="Modules\Overlays\VolumeDisplay\VolumeDisplayViewModel.cs" />
<Compile Include="ViewModels\ProfileEditorViewModel.cs" />
@ -491,8 +496,8 @@
<Compile Include="Modules\Games\Witcher3\Witcher3View.xaml.cs">
<DependentUpon>Witcher3View.xaml</DependentUpon>
</Compile>
<Compile Include="Views\LayerEditor\LayerKeyboardView.xaml.cs">
<DependentUpon>LayerKeyboardView.xaml</DependentUpon>
<Compile Include="Views\LayerEditor\KeyboardPropertiesView.xaml.cs">
<DependentUpon>KeyboardPropertiesView.xaml</DependentUpon>
</Compile>
<Compile Include="Views\LayerEditor\LayerConditionView.xaml.cs">
<DependentUpon>LayerConditionView.xaml</DependentUpon>
@ -503,8 +508,8 @@
<Compile Include="Views\LayerEditor\LayerEditorView.xaml.cs">
<DependentUpon>LayerEditorView.xaml</DependentUpon>
</Compile>
<Compile Include="Views\LayerEditor\LayerMouseView.xaml.cs">
<DependentUpon>LayerMouseView.xaml</DependentUpon>
<Compile Include="Views\LayerEditor\MousePropertiesView.xaml.cs">
<DependentUpon>MousePropertiesView.xaml</DependentUpon>
</Compile>
<Compile Include="Views\OverlaysView.xaml.cs">
<DependentUpon>OverlaysView.xaml</DependentUpon>
@ -673,7 +678,7 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\LayerEditor\LayerKeyboardView.xaml">
<Page Include="Views\LayerEditor\KeyboardPropertiesView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
@ -689,7 +694,7 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\LayerEditor\LayerMouseView.xaml">
<Page Include="Views\LayerEditor\MousePropertiesView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>

View File

@ -114,7 +114,7 @@ namespace Artemis.Managers
if (renderEffect.Initialized == false)
return;
// Update the current effect
// ApplyProperties the current effect
if (renderEffect.Initialized)
renderEffect.Update();

View File

@ -83,7 +83,6 @@ namespace Artemis.Managers
_logger.Debug("Shutting down MainManager");
LoopManager.Stop();
ProcessWorker.CancelAsync();
ProcessWorker.CancelAsync();
GameStateWebServer.Stop();
PipeServer.Stop();
}

View File

@ -1,79 +0,0 @@
using System.ComponentModel;
using Artemis.Models.Interfaces;
using Artemis.Utilities;
using static System.Decimal;
namespace Artemis.Models.Profiles
{
public class LayerDynamicPropertiesModel
{
/// <summary>
/// Property this dynamic property applies on
/// </summary>
public string LayerProperty { get; set; }
/// <summary>
/// Property to base the percentage upon
/// </summary>
public string GameProperty { get; set; }
/// <summary>
/// Percentage source, the number that defines 100%
/// </summary>
public string PercentageSource { get; set; }
/// <summary>
/// Type of property
/// </summary>
public LayerPropertyType LayerPropertyType { get; set; }
internal void ApplyProperty(IGameDataModel data, LayerPropertiesModel userProps, LayerPropertiesModel props)
{
if (LayerPropertyType == LayerPropertyType.PercentageOf)
Apply(props, userProps, data, int.Parse(PercentageSource));
if (LayerPropertyType == LayerPropertyType.PercentageOfProperty)
ApplyProp(props, userProps, data);
}
private void Apply(LayerPropertiesModel props, LayerPropertiesModel userProps, IGameDataModel data,
int percentageSource)
{
// Property to apply on
var layerProp = props.GetType().GetProperty(LayerProperty);
// User's settings
var userProp = userProps.GetType().GetProperty(LayerProperty);
// Property to base the percentage upon
var gameProperty = data.GetPropValue<int>(GameProperty);
if (layerProp == null || userProp == null)
return;
var percentage = ToDouble(gameProperty)/percentageSource;
// Opacity requires some special treatment as it causes an exception if it's < 0.0 or > 1.0
if (LayerProperty == "Opacity")
{
var opacity = percentage*(double) userProp.GetValue(userProps, null);
if (opacity < 0.0)
opacity = 0.0;
if (opacity > 1.0)
opacity = 1.0;
layerProp.SetValue(props, opacity);
}
else
layerProp.SetValue(props, percentage*(double) userProp.GetValue(userProps, null));
}
private void ApplyProp(LayerPropertiesModel props, LayerPropertiesModel userProps, IGameDataModel data)
{
var value = data.GetPropValue<int>(PercentageSource);
Apply(props, userProps, data, value);
}
}
public enum LayerPropertyType
{
[Description("None")] None,
[Description("% of")] PercentageOf,
[Description("% of property")] PercentageOfProperty
}
}

View File

@ -1,106 +1,87 @@
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel;
using System.Linq;
using System.Windows.Media;
using System.Xml.Serialization;
using Artemis.Models.Interfaces;
using Artemis.Models.Profiles.Properties;
using Artemis.Utilities;
using Artemis.Utilities.Layers;
using Artemis.Utilities.ParentChild;
namespace Artemis.Models.Profiles
{
public class LayerModel : IChildItem<LayerModel>, IChildItem<ProfileModel>
{
[XmlIgnore] private readonly LayerDrawer _drawer;
[XmlIgnore] private bool _mustDraw;
public LayerModel()
{
UserProps = new LayerPropertiesModel();
CalcProps = new LayerPropertiesModel();
Children = new ChildItemCollection<LayerModel, LayerModel>(this);
LayerConditions = new List<LayerConditionModel>();
LayerProperties = new List<LayerDynamicPropertiesModel>();
_mustDraw = true;
_drawer = new LayerDrawer(this, 4);
}
public string Name { get; set; }
public LayerType LayerType { get; set; }
public string GifFile { get; set; }
public bool Enabled { get; set; }
public int Order { get; set; }
public LayerPropertiesModel UserProps { get; set; }
public LayerPropertiesModel Properties { get; set; }
public ChildItemCollection<LayerModel, LayerModel> Children { get; }
public List<LayerConditionModel> LayerConditions { get; set; }
public List<LayerDynamicPropertiesModel> LayerProperties { get; set; }
[XmlIgnore]
public LayerPropertiesModel CalcProps { get; set; }
public ImageSource LayerImage => GetThumbnail();
[XmlIgnore]
public ImageSource LayerImage => _drawer.GetThumbnail();
public LayerModel Parent { get; internal set; }
[XmlIgnore]
public LayerModel ParentLayer { get; internal set; }
public ProfileModel Profile { get; internal set; }
[XmlIgnore]
public ProfileModel ParentProfile { get; internal set; }
public GifImage GifImage { get; set; }
public bool ConditionsMet<T>(IGameDataModel dataModel)
{
return Enabled && LayerConditions.All(cm => cm.ConditionMet<T>(dataModel));
}
public void DrawPreview(DrawingContext c)
{
GeneralHelpers.CopyProperties(CalcProps, UserProps);
if (LayerType == LayerType.Keyboard || LayerType == LayerType.Keyboard)
_drawer.Draw(c, _mustDraw);
else if (LayerType == LayerType.KeyboardGif)
_drawer.DrawGif(c, _mustDraw);
_mustDraw = false;
return Enabled && Properties.Conditions.All(cm => cm.ConditionMet<T>(dataModel));
}
public void Draw<T>(IGameDataModel dataModel, DrawingContext c, bool preview = false)
{
// Conditions aren't checked during a preview because there is no game data to base them on
// Don't draw when the layer is disabled
if (!Enabled)
return;
// Preview simply shows the properties as they are. When not previewing they are applied
LayerPropertiesModel properties;
if (!preview)
{
if (!ConditionsMet<T>(dataModel))
return;
return; // Don't draw the layer when not previewing and the conditions arent met
properties = Properties.GetAppliedProperties(dataModel);
}
else
properties = GeneralHelpers.Clone(Properties);
if (LayerType == LayerType.Folder)
foreach (var layerModel in Children.OrderByDescending(l => l.Order))
layerModel.Draw<T>(dataModel, c);
else if (LayerType == LayerType.Keyboard || LayerType == LayerType.Keyboard)
_drawer.Draw(c);
else if (LayerType == LayerType.KeyboardGif)
_drawer.DrawGif(c);
else if (LayerType == LayerType.Mouse)
_drawer.UpdateMouse();
else if (LayerType == LayerType.Headset)
_drawer.UpdateHeadset();
}
// Update animations on layer types that support them
if (LayerType == LayerType.Keyboard || LayerType == LayerType.KeyboardGif)
AnimationUpdater.UpdateAnimation((KeyboardPropertiesModel) properties);
public void Update<T>(IGameDataModel dataModel, bool preview = false)
{
// Folders are drawn recursively
if (LayerType == LayerType.Folder)
{
foreach (var layerModel in Children)
layerModel.Update<T>(dataModel);
return;
foreach (var layerModel in Children.OrderByDescending(l => l.Order))
layerModel.Draw<T>(dataModel, c);
}
// All other types are handles by the Drawer helper
else if (LayerType == LayerType.Keyboard)
Drawer.Draw(c, (KeyboardPropertiesModel) properties);
else if (LayerType == LayerType.KeyboardGif)
Drawer.DrawGif(c, (KeyboardPropertiesModel) properties, GifImage);
else if (LayerType == LayerType.Mouse)
Drawer.UpdateMouse(properties);
else if (LayerType == LayerType.Headset)
Drawer.UpdateHeadset(properties);
}
GeneralHelpers.CopyProperties(CalcProps, UserProps);
// Dynamic properties aren't applied during preview because there is no game data to base them on
if (preview)
return;
foreach (var dynamicProperty in LayerProperties)
dynamicProperty.ApplyProperty(dataModel, UserProps, CalcProps);
private ImageSource GetThumbnail()
{
// TODO
return null;
}
public void Reorder(LayerModel selectedLayer, bool moveUp)
@ -133,14 +114,14 @@ namespace Artemis.Models.Profiles
LayerModel IChildItem<LayerModel>.Parent
{
get { return ParentLayer; }
set { ParentLayer = value; }
get { return Parent; }
set { Parent = value; }
}
ProfileModel IChildItem<ProfileModel>.Parent
{
get { return ParentProfile; }
set { ParentProfile = value; }
get { return Profile; }
set { Profile = value; }
}
#endregion

View File

@ -1,41 +0,0 @@
using System.ComponentModel;
using System.Windows;
using System.Windows.Media;
using System.Xml.Serialization;
namespace Artemis.Models.Profiles
{
[XmlInclude(typeof(SolidColorBrush))]
[XmlInclude(typeof(LinearGradientBrush))]
[XmlInclude(typeof(RadialGradientBrush))]
[XmlInclude(typeof(MatrixTransform))]
public class LayerPropertiesModel
{
public double X { get; set; }
public double Y { get; set; }
public double Width { get; set; }
public double Height { get; set; }
public double Opacity { get; set; }
public bool ContainedBrush { get; set; }
public LayerAnimation Animation { get; set; }
public double AnimationSpeed { get; set; }
public Brush Brush { get; set; }
public Rect GetRect(int scale = 4)
{
return new Rect(X*scale, Y*scale, Width*scale, Height*scale);
}
}
public enum LayerAnimation
{
[Description("None")] None,
[Description("Slide left")] SlideLeft,
[Description("Slide right")] SlideRight,
[Description("Slide up")] SlideUp,
[Description("Slide down")] SlideDown,
[Description("Grow")] Grow,
[Description("Pulse")] Pulse
}
}

View File

@ -2,7 +2,9 @@
using System.Linq;
using System.Windows;
using System.Windows.Media;
using System.Xml.Serialization;
using Artemis.Models.Interfaces;
using Artemis.Models.Profiles.Properties;
using Artemis.Utilities;
using Artemis.Utilities.ParentChild;
using Color = System.Windows.Media.Color;
@ -22,12 +24,14 @@ namespace Artemis.Models.Profiles
public string Name { get; set; }
public string KeyboardName { get; set; }
public string GameName { get; set; }
[XmlIgnore]
public DrawingVisual DrawingVisual { get; set; }
protected bool Equals(ProfileModel other)
{
return string.Equals(Name, other.Name) && string.Equals(KeyboardName, other.KeyboardName) &&
return string.Equals(Name, other.Name) &&
string.Equals(KeyboardName, other.KeyboardName) &&
string.Equals(GameName, other.GameName);
}
@ -62,7 +66,7 @@ namespace Artemis.Models.Profiles
Enabled = true,
Order = -1,
LayerType = LayerType.Keyboard,
UserProps = new LayerPropertiesModel
Properties = new KeyboardPropertiesModel
{
Brush = new SolidColorBrush(ColorHelpers.GetRandomRainbowMediaColor()),
Animation = LayerAnimation.None,

View File

@ -0,0 +1,85 @@
using System.ComponentModel;
using Artemis.Models.Interfaces;
using Artemis.Utilities;
using static System.Decimal;
namespace Artemis.Models.Profiles.Properties
{
public class DynamicPropertiesModel
{
/// <summary>
/// Property this dynamic property applies on
/// </summary>
public string LayerProperty { get; set; }
/// <summary>
/// Property to base the percentage upon
/// </summary>
public string GameProperty { get; set; }
/// <summary>
/// Percentage source, the number that defines 100%
/// </summary>
public double PercentageSource { get; set; }
/// <summary>
/// Percentage source property, the property that defines 100%
/// </summary>
public string PercentageProperty { get; set; }
/// <summary>
/// Type of property
/// </summary>
public LayerPropertyType LayerPropertyType { get; set; }
internal void ApplyProperty(IGameDataModel dataModel, KeyboardPropertiesModel properties)
{
if (LayerPropertyType == LayerPropertyType.PercentageOf)
ApplyPercentageOf(dataModel, properties, PercentageSource);
if (LayerPropertyType == LayerPropertyType.PercentageOfProperty)
ApplyPercentageOfProperty(dataModel, properties);
}
private void ApplyPercentageOf(IGameDataModel dataModel, KeyboardPropertiesModel properties,
double percentageSource)
{
// Property to apply on
var layerProp = properties.GetType().GetProperty(LayerProperty);
// Property to base the percentage upon
var gameProperty = dataModel.GetPropValue<int>(GameProperty);
if (layerProp == null)
return;
var percentage = ToDouble(gameProperty)/percentageSource;
var appliedValue = percentage*(double) layerProp.GetValue(layerProp, null);
// Opacity requires some special treatment as it causes an exception if it's < 0.0 or > 1.0
if (LayerProperty == "Opacity")
{
if (appliedValue < 0.0)
appliedValue = 0.0;
if (appliedValue > 1.0)
appliedValue = 1.0;
}
layerProp.SetValue(layerProp, appliedValue);
}
private void ApplyPercentageOfProperty(IGameDataModel dataModel, KeyboardPropertiesModel properties)
{
var value = dataModel.GetPropValue<double>(PercentageProperty);
ApplyPercentageOf(dataModel, properties, value);
}
}
public enum LayerPropertyType
{
[Description("None")] None,
[Description("% of")] PercentageOf,
[Description("% of property")] PercentageOfProperty
}
}

View File

@ -0,0 +1,58 @@
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;
using System.Xml.Serialization;
using Artemis.Models.Interfaces;
using Artemis.Utilities;
namespace Artemis.Models.Profiles.Properties
{
public class KeyboardPropertiesModel : LayerPropertiesModel
{
public KeyboardPropertiesModel()
{
DynamicProperties = new List<DynamicPropertiesModel>();
}
public double X { get; set; }
public double Y { get; set; }
public double Width { get; set; }
public double Height { get; set; }
public double Opacity { get; set; }
public bool Contain { get; set; }
public LayerAnimation Animation { get; set; }
public double AnimationSpeed { get; set; }
public string GifFile { get; set; }
public List<DynamicPropertiesModel> DynamicProperties { get; set; }
[XmlIgnore]
public int AnimationProgress { get; set; }
public Rect GetRect(int scale = 4)
{
return new Rect(X*scale, Y*scale, Width*scale, Height*scale);
}
public override LayerPropertiesModel GetAppliedProperties(IGameDataModel dataModel)
{
var properties = GeneralHelpers.Clone(this);
foreach (var dynamicProperty in properties.DynamicProperties)
dynamicProperty.ApplyProperty(dataModel, properties);
properties.Brush.Opacity = Opacity;
return properties;
}
}
public enum LayerAnimation
{
[Description("None")] None,
[Description("Slide left")] SlideLeft,
[Description("Slide right")] SlideRight,
[Description("Slide up")] SlideUp,
[Description("Slide down")] SlideDown,
[Description("Grow")] Grow,
[Description("Pulse")] Pulse
}
}

View File

@ -0,0 +1,26 @@
using System.Collections.Generic;
using System.Windows.Media;
using System.Xml.Serialization;
using Artemis.Models.Interfaces;
namespace Artemis.Models.Profiles.Properties
{
[XmlInclude(typeof(SolidColorBrush))]
[XmlInclude(typeof(LinearGradientBrush))]
[XmlInclude(typeof(RadialGradientBrush))]
[XmlInclude(typeof(MatrixTransform))]
[XmlInclude(typeof(KeyboardPropertiesModel))]
[XmlInclude(typeof(MousePropertiesModel))]
public abstract class LayerPropertiesModel
{
protected LayerPropertiesModel()
{
Conditions = new List<LayerConditionModel>();
}
public abstract LayerPropertiesModel GetAppliedProperties(IGameDataModel dataModel);
public List<LayerConditionModel> Conditions { get; set; }
public Brush Brush { get; set; }
}
}

View File

@ -0,0 +1,14 @@
using Artemis.Models.Interfaces;
using Artemis.Utilities;
namespace Artemis.Models.Profiles.Properties
{
public class MousePropertiesModel : LayerPropertiesModel
{
public override LayerPropertiesModel GetAppliedProperties(IGameDataModel dataModel)
{
// TODO: Apply any properties, if applicable to mice in the first place.
return GeneralHelpers.Clone(this);
}
}
}

View File

@ -31,11 +31,6 @@ namespace Artemis.Modules.Effects.ProfilePreview
public override void Update()
{
if (SelectedProfile == null)
return;
foreach (var layerModel in SelectedProfile.Layers)
layerModel.Update<ProfilePreviewDataModel>(_previewDataModel, true);
}
public override Bitmap GenerateBitmap()

View File

@ -39,11 +39,7 @@ namespace Artemis.Modules.Games.CounterStrike
public override void Update()
{
if (Profile == null || GameDataModel == null)
return;
foreach (var layerModel in Profile.Layers)
layerModel.Update<CounterStrikeDataModel>(GameDataModel);
// TODO: Set up active weapon in the datamodel
}
public override Bitmap GenerateBitmap()

View File

@ -62,9 +62,6 @@ namespace Artemis.Modules.Games.RocketLeague
((RocketLeagueDataModel) GameDataModel).Boost = 0;
if (((RocketLeagueDataModel) GameDataModel).Boost > 100)
((RocketLeagueDataModel) GameDataModel).Boost = 100;
foreach (var layerModel in Profile.Layers)
layerModel.Update<RocketLeagueDataModel>(GameDataModel);
}
public override Bitmap GenerateBitmap()

View File

@ -25,7 +25,7 @@ using System.Windows;
//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
//inside a <PropertyGroup>. For example, if you are using US english
//in your source files, set the <UICulture> to en-US. Then uncomment
//the NeutralResourceLanguage attribute below. Update the "en-US" in
//the NeutralResourceLanguage attribute below. ApplyProperties the "en-US" in
//the line below to match the UICulture setting in the project file.
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]

View File

@ -446,11 +446,6 @@
<nc:GradientStopAdder Height="20" Focusable="False"
IsTabStop="False" FocusVisualStyle="{x:Null}"
ColorBox="{Binding RelativeSource={RelativeSource TemplatedParent}}">
<nc:GradientStopAdder.Background>
<LinearGradientBrush
GradientStops="{Binding Brush.GradientStops, RelativeSource={RelativeSource TemplatedParent}}"
StartPoint="0, .5" EndPoint="1, .5" />
</nc:GradientStopAdder.Background>
<Button.Style>
<Style TargetType="Button">
<Setter Property="Template">

View File

@ -21,10 +21,14 @@ namespace Artemis.Utilities
_dimension = new FrameDimension(_gifImage.FrameDimensionsList[0]); //gets the GUID
_frameCount = _gifImage.GetFrameCount(_dimension); //total frames in the animation
Source = path;
var item = _gifImage.GetPropertyItem(0x5100); // FrameDelay in libgdiplus
_delay = (item.Value[0] + item.Value[1]*256)*10; // Time is in 1/100th of a second
}
public string Source { get; set; }
/// <summary>
/// Whether the gif should play backwards when it reaches the end
/// </summary>

View File

@ -1,203 +0,0 @@
using System;
using System.Drawing;
using System.IO;
using System.Windows;
using System.Windows.Media;
using Artemis.Models.Profiles;
using Artemis.Properties;
using Pen = System.Windows.Media.Pen;
using Point = System.Windows.Point;
using Size = System.Windows.Size;
namespace Artemis.Utilities
{
internal class LayerDrawer
{
private readonly LayerModel _layerModel;
private double _animationProgress;
private Rect _firstRect;
private GifImage _gifImage;
private string _gifSource;
private Rect _rectangle;
private Rect _secondRect;
public LayerDrawer(LayerModel layerModel, int scale)
{
Scale = scale;
_layerModel = layerModel;
_animationProgress = 0;
}
public int Scale { get; set; }
public void Draw(DrawingContext c, bool update = true)
{
if (_layerModel.CalcProps.Brush == null || !_layerModel.Enabled)
return;
if (!update)
_layerModel.CalcProps.Animation = LayerAnimation.None;
UpdateAnimation();
// Set up variables for this frame
_rectangle = new Rect(_layerModel.CalcProps.X*Scale,
_layerModel.CalcProps.Y*Scale, _layerModel.CalcProps.Width*Scale,
_layerModel.CalcProps.Height*Scale);
if (_layerModel.LayerType == LayerType.Keyboard)
_layerModel.CalcProps.Brush.Dispatcher.Invoke(() => DrawRectangle(c));
}
private void UpdateAnimation()
{
if (!_layerModel.Enabled)
return;
// Slide right animation
if (_layerModel.CalcProps.Animation == LayerAnimation.SlideRight)
{
_firstRect = new Rect(new Point(_rectangle.X + _animationProgress, _rectangle.Y),
new Size(_rectangle.Width, _rectangle.Height));
_secondRect = new Rect(new Point(_firstRect.X - _rectangle.Width, _rectangle.Y),
new Size(_rectangle.Width + 1, _rectangle.Height));
if (_animationProgress > _layerModel.CalcProps.Width*4)
_animationProgress = 0;
}
// Slide left animation
if (_layerModel.CalcProps.Animation == LayerAnimation.SlideLeft)
{
_firstRect = new Rect(new Point(_rectangle.X - _animationProgress, _rectangle.Y),
new Size(_rectangle.Width + 1, _rectangle.Height));
_secondRect = new Rect(new Point(_firstRect.X + _rectangle.Width, _rectangle.Y),
new Size(_rectangle.Width, _rectangle.Height));
if (_animationProgress > _layerModel.CalcProps.Width*4)
_animationProgress = 0;
}
// Slide down animation
if (_layerModel.CalcProps.Animation == LayerAnimation.SlideDown)
{
_firstRect = new Rect(new Point(_rectangle.X, _rectangle.Y + _animationProgress),
new Size(_rectangle.Width, _rectangle.Height));
_secondRect = new Rect(new Point(_firstRect.X, _firstRect.Y - _rectangle.Height),
new Size(_rectangle.Width, _rectangle.Height));
if (_animationProgress > _layerModel.CalcProps.Height*4)
_animationProgress = 0;
}
// Slide up animation
if (_layerModel.CalcProps.Animation == LayerAnimation.SlideUp)
{
_firstRect = new Rect(new Point(_rectangle.X, _rectangle.Y - _animationProgress),
new Size(_rectangle.Width, _rectangle.Height));
_secondRect = new Rect(new Point(_firstRect.X, _firstRect.Y + _rectangle.Height),
new Size(_rectangle.Width, _rectangle.Height));
if (_animationProgress > _layerModel.CalcProps.Height*4)
_animationProgress = 0;
}
// Pulse animation
if (_layerModel.CalcProps.Animation == LayerAnimation.Pulse)
{
var opac = (Math.Sin(_animationProgress*Math.PI) + 1)*(_layerModel.UserProps.Opacity/2);
_layerModel.CalcProps.Opacity = opac;
if (_animationProgress > 2)
_animationProgress = 0;
_animationProgress = _animationProgress + _layerModel.CalcProps.AnimationSpeed/2;
}
else
{
// Update the animation progress
_animationProgress = _animationProgress + _layerModel.CalcProps.AnimationSpeed;
}
}
public DrawingImage GetThumbnail()
{
var thumbnailRect = new Rect(0, 0, 18, 18);
var visual = new DrawingVisual();
using (var c = visual.RenderOpen())
{
// Draw the appropiate icon or draw the brush
if (_layerModel.LayerType == LayerType.Folder)
c.DrawImage(ImageUtilities.BitmapToBitmapImage(Resources.folder), thumbnailRect);
else if (_layerModel.LayerType == LayerType.Headset)
c.DrawImage(ImageUtilities.BitmapToBitmapImage(Resources.headset), thumbnailRect);
else if (_layerModel.LayerType == LayerType.Mouse)
c.DrawImage(ImageUtilities.BitmapToBitmapImage(Resources.mouse), thumbnailRect);
else if (_layerModel.LayerType == LayerType.KeyboardGif)
c.DrawImage(ImageUtilities.BitmapToBitmapImage(Resources.gif), thumbnailRect);
else if (_layerModel.LayerType == LayerType.Keyboard && _layerModel.UserProps.Brush != null)
c.DrawRectangle(_layerModel.UserProps.Brush, new Pen(new SolidColorBrush(Colors.White), 1),
thumbnailRect);
}
var image = new DrawingImage(visual.Drawing);
return image;
}
public void DrawRectangle(DrawingContext c)
{
var brush = _layerModel.CalcProps.Brush.CloneCurrentValue();
brush.Opacity = _layerModel.CalcProps.Opacity;
if (_layerModel.CalcProps.Animation == LayerAnimation.SlideDown ||
_layerModel.CalcProps.Animation == LayerAnimation.SlideLeft ||
_layerModel.CalcProps.Animation == LayerAnimation.SlideRight ||
_layerModel.CalcProps.Animation == LayerAnimation.SlideUp)
{
// TODO: if (_layerModel.CalcProps.ContainedBrush)
c.PushClip(new RectangleGeometry(_rectangle));
c.DrawRectangle(brush, null, _firstRect);
c.DrawRectangle(brush, null, _secondRect);
c.Pop();
}
else
{
c.DrawRectangle(brush, null, _rectangle);
}
}
public void DrawEllipse(DrawingContext c)
{
c.DrawEllipse(_layerModel.CalcProps.Brush, null,
new Point(_rectangle.Width/2, _rectangle.Height/2), _rectangle.Width, _rectangle.Height);
}
public void DrawGif(DrawingContext c, bool update = true)
{
if (string.IsNullOrEmpty(_layerModel.GifFile))
return;
if (!File.Exists(_layerModel.GifFile))
return;
if (_layerModel.GifFile != _gifSource || _gifSource == null)
{
_gifImage = new GifImage(_layerModel.GifFile);
_gifSource = _layerModel.GifFile;
}
var gifRect = new Rect(_layerModel.CalcProps.X*Scale,
_layerModel.CalcProps.Y*Scale, _layerModel.CalcProps.Width*Scale,
_layerModel.CalcProps.Height*Scale);
var draw = update ? _gifImage.GetNextFrame() : _gifImage.GetFrame(0);
c.DrawImage(ImageUtilities.BitmapToBitmapImage(new Bitmap(draw)), gifRect);
}
public void UpdateMouse()
{
}
public void UpdateHeadset()
{
}
}
}

View File

@ -0,0 +1,43 @@
using System;
using Artemis.Models.Profiles.Properties;
namespace Artemis.Utilities.Layers
{
public static class AnimationUpdater
{
public static void UpdateAnimation(KeyboardPropertiesModel properties)
{
const int scale = 4;
// Horizontal sliding
if (properties.Animation == LayerAnimation.SlideRight || properties.Animation == LayerAnimation.SlideLeft)
{
if (properties.AnimationProgress > properties.Width*scale)
properties.AnimationProgress = 0;
}
// Vertical sliding
if (properties.Animation == LayerAnimation.SlideDown || properties.Animation == LayerAnimation.SlideUp)
{
if (properties.AnimationProgress > properties.Height*scale)
properties.AnimationProgress = 0;
}
// Pulse animation
if (properties.Animation == LayerAnimation.Pulse)
{
var opac = (Math.Sin(properties.AnimationProgress*Math.PI) + 1)*(properties.Opacity/2);
properties.Opacity = opac;
if (properties.AnimationProgress > 2)
properties.AnimationProgress = 0;
properties.AnimationProgress = (int) (properties.AnimationProgress + properties.AnimationSpeed/2);
}
else
{
// ApplyProperties the animation progress
properties.AnimationProgress = (int) (properties.AnimationProgress + properties.AnimationSpeed);
}
}
}
}

View File

@ -0,0 +1,128 @@
using System.Drawing;
using System.IO;
using System.Windows;
using System.Windows.Media;
using Artemis.Models.Profiles;
using Artemis.Models.Profiles.Properties;
using Artemis.Properties;
using Pen = System.Windows.Media.Pen;
using Point = System.Windows.Point;
using Size = System.Windows.Size;
namespace Artemis.Utilities.Layers
{
public static class Drawer
{
public static void Draw(DrawingContext c, KeyboardPropertiesModel props)
{
if (props.Brush == null)
return;
const int scale = 4;
// Set up variables for this frame
var rect = new Rect(props.X*scale, props.Y*scale, props.Width*scale, props.Height*scale);
var s1 = new Rect();
var s2 = new Rect();
if (props.Animation == LayerAnimation.SlideRight)
{
s1 = new Rect(new Point(rect.X + props.AnimationProgress, rect.Y), new Size(rect.Width, rect.Height));
s2 = new Rect(new Point(s1.X - rect.Width, rect.Y), new Size(rect.Width + 1, rect.Height));
}
if (props.Animation == LayerAnimation.SlideLeft)
{
s1 = new Rect(new Point(rect.X - props.AnimationProgress, rect.Y), new Size(rect.Width + 1, rect.Height));
s2 = new Rect(new Point(s1.X + rect.Width, rect.Y), new Size(rect.Width, rect.Height));
}
if (props.Animation == LayerAnimation.SlideDown)
{
s1 = new Rect(new Point(rect.X, rect.Y + props.AnimationProgress), new Size(rect.Width, rect.Height));
s2 = new Rect(new Point(s1.X, s1.Y - rect.Height), new Size(rect.Width, rect.Height));
}
if (props.Animation == LayerAnimation.SlideUp)
{
s1 = new Rect(new Point(rect.X, rect.Y - props.AnimationProgress), new Size(rect.Width, rect.Height));
s2 = new Rect(new Point(s1.X, s1.Y + rect.Height), new Size(rect.Width, rect.Height));
}
props.Brush.Dispatcher.Invoke(() => DrawRectangle(c, props, rect, s1, s2));
}
private static void DrawRectangle(DrawingContext c, KeyboardPropertiesModel properties, Rect rectangle,
Rect slide1, Rect slide2)
{
// TODO: Implement clipping modes
// Most animation types can be drawn regularly
if (properties.Animation == LayerAnimation.None ||
properties.Animation == LayerAnimation.Grow ||
properties.Animation == LayerAnimation.Pulse)
{
c.DrawRectangle(properties.Brush, null, rectangle);
}
// Sliding animations however, require offsetting two rects
else
{
c.PushClip(new RectangleGeometry(rectangle));
c.DrawRectangle(properties.Brush, null, slide1);
c.DrawRectangle(properties.Brush, null, slide2);
c.Pop();
}
}
public static void DrawGif(DrawingContext c, KeyboardPropertiesModel properties, GifImage gifImage,
bool update = true)
{
if (string.IsNullOrEmpty(properties.GifFile))
return;
if (!File.Exists(properties.GifFile))
return;
const int scale = 4;
// Only reconstruct GifImage if the underlying source has changed
if (gifImage == null)
gifImage = new GifImage(properties.GifFile);
if (gifImage.Source != properties.GifFile)
gifImage = new GifImage(properties.GifFile);
var gifRect = new Rect(properties.X*scale, properties.Y*scale, properties.Width*scale,
properties.Height*scale);
var draw = update ? gifImage.GetNextFrame() : gifImage.GetFrame(0);
c.DrawImage(ImageUtilities.BitmapToBitmapImage(new Bitmap(draw)), gifRect);
}
public static void UpdateMouse(LayerPropertiesModel properties)
{
}
public static void UpdateHeadset(LayerPropertiesModel properties)
{
}
public static DrawingImage GetThumbnail(LayerModel layerModel)
{
var thumbnailRect = new Rect(0, 0, 18, 18);
var visual = new DrawingVisual();
using (var c = visual.RenderOpen())
{
// Draw the appropiate icon or draw the brush
if (layerModel.LayerType == LayerType.Folder)
c.DrawImage(ImageUtilities.BitmapToBitmapImage(Resources.folder), thumbnailRect);
else if (layerModel.LayerType == LayerType.Headset)
c.DrawImage(ImageUtilities.BitmapToBitmapImage(Resources.headset), thumbnailRect);
else if (layerModel.LayerType == LayerType.Mouse)
c.DrawImage(ImageUtilities.BitmapToBitmapImage(Resources.mouse), thumbnailRect);
else if (layerModel.LayerType == LayerType.KeyboardGif)
c.DrawImage(ImageUtilities.BitmapToBitmapImage(Resources.gif), thumbnailRect);
else if (layerModel.LayerType == LayerType.Keyboard && layerModel.Properties.Brush != null)
c.DrawRectangle(layerModel.Properties.Brush, new Pen(new SolidColorBrush(Colors.White), 1),
thumbnailRect);
}
var image = new DrawingImage(visual.Drawing);
return image;
}
}
}

View File

@ -26,7 +26,7 @@ namespace Artemis.Utilities
return null;
var viewUpdate = await
dialogService.ShowQuestionMessageBox("Update available",
dialogService.ShowQuestionMessageBox("ApplyProperties available",
$"A new version of Artemis is available, version {newRelease["tag_name"].Value<string>()}.\n" +
"Do you wish to view the update on GitHub now?\n\n" +
"Note: You can disable update notifications in the settings menu");

View File

@ -0,0 +1,67 @@
using Artemis.Models.Interfaces;
using Artemis.Models.Profiles.Properties;
using Artemis.Utilities;
using Caliburn.Micro;
namespace Artemis.ViewModels.LayerEditor
{
public class KeyboardPropertiesViewModel : LayerPropertiesViewModel
{
private bool _isGif;
private KeyboardPropertiesModel _proposedProperties;
public KeyboardPropertiesViewModel(IGameDataModel gameDataModel, LayerPropertiesModel properties)
: base(gameDataModel)
{
var keyboardProperties = (KeyboardPropertiesModel) properties;
ProposedProperties = GeneralHelpers.Clone(keyboardProperties);
DataModelProps = new BindableCollection<GeneralHelpers.PropertyCollection>();
DataModelProps.AddRange(GeneralHelpers.GenerateTypeMap(gameDataModel));
HeightProperties = new LayerDynamicPropertiesViewModel("Height", DataModelProps, keyboardProperties);
WidthProperties = new LayerDynamicPropertiesViewModel("Width", DataModelProps, keyboardProperties);
OpacityProperties = new LayerDynamicPropertiesViewModel("Opacity", DataModelProps, keyboardProperties);
}
public bool IsGif
{
get { return _isGif; }
set
{
_isGif = value;
NotifyOfPropertyChange(() => ShowGif);
NotifyOfPropertyChange(() => ShowBrush);
}
}
public bool ShowGif => IsGif;
public bool ShowBrush => !IsGif;
public BindableCollection<GeneralHelpers.PropertyCollection> DataModelProps { get; set; }
public LayerDynamicPropertiesViewModel HeightProperties { get; set; }
public LayerDynamicPropertiesViewModel WidthProperties { get; set; }
public LayerDynamicPropertiesViewModel OpacityProperties { get; set; }
public KeyboardPropertiesModel ProposedProperties
{
get { return _proposedProperties; }
set
{
if (Equals(value, _proposedProperties)) return;
_proposedProperties = value;
NotifyOfPropertyChange(() => ProposedProperties);
}
}
public override LayerPropertiesModel GetAppliedProperties()
{
HeightProperties.Apply();
WidthProperties.Apply();
OpacityProperties.Apply();
return GeneralHelpers.Clone(ProposedProperties);
}
}
}

View File

@ -1,16 +1,16 @@
using System.ComponentModel;
using System.Linq;
using Artemis.Models.Profiles;
using Artemis.Models.Profiles.Properties;
using Artemis.Utilities;
using Caliburn.Micro;
namespace Artemis.ViewModels.LayerEditor
{
public class LayerDynamicPropertiesViewModel : PropertyChangedBase
public sealed class LayerDynamicPropertiesViewModel : PropertyChangedBase
{
private readonly LayerModel _layer;
private readonly KeyboardPropertiesModel _keyboardProperties;
private readonly string _property;
private LayerDynamicPropertiesModel _layerDynamicPropertiesModelProposed;
private DynamicPropertiesModel _proposed;
private LayerPropertyType _layerPropertyType;
private string _name;
private GeneralHelpers.PropertyCollection _selectedSource;
@ -18,24 +18,21 @@ namespace Artemis.ViewModels.LayerEditor
private bool _sourcesIsVisible;
private bool _userSourceIsVisible;
public LayerDynamicPropertiesViewModel(string property,
BindableCollection<GeneralHelpers.PropertyCollection> dataModelProps, LayerModel layer)
public LayerDynamicPropertiesViewModel(string property, BindableCollection<GeneralHelpers.PropertyCollection> dataModelProps, KeyboardPropertiesModel keyboardProperties)
{
_property = property;
_layer = layer;
_keyboardProperties = keyboardProperties;
// Look for the existing property model
LayerDynamicPropertiesModelProposed = new LayerDynamicPropertiesModel();
var original = _layer.LayerProperties.FirstOrDefault(lp => lp.LayerProperty == _property);
Proposed = new DynamicPropertiesModel();
var original = _keyboardProperties.DynamicProperties.FirstOrDefault(lp => lp.LayerProperty == _property);
if (original == null)
{
LayerDynamicPropertiesModelProposed.LayerProperty = property;
LayerDynamicPropertiesModelProposed.LayerPropertyType = LayerPropertyType.None;
Proposed.LayerProperty = property;
Proposed.LayerPropertyType = LayerPropertyType.None;
}
else
{
GeneralHelpers.CopyProperties(LayerDynamicPropertiesModelProposed, original);
}
GeneralHelpers.CopyProperties(Proposed, original);
Name = property + ":";
Targets = new BindableCollection<GeneralHelpers.PropertyCollection>();
@ -45,11 +42,9 @@ namespace Artemis.ViewModels.LayerEditor
PropertyChanged += OnPropertyChanged;
SelectedTarget =
dataModelProps.FirstOrDefault(p => p.Path == LayerDynamicPropertiesModelProposed.GameProperty);
SelectedSource =
dataModelProps.FirstOrDefault(p => p.Path == LayerDynamicPropertiesModelProposed.PercentageSource);
LayerPropertyType = LayerDynamicPropertiesModelProposed.LayerPropertyType;
SelectedTarget = dataModelProps.FirstOrDefault(p => p.Path == Proposed.GameProperty);
SelectedSource = dataModelProps.FirstOrDefault(p => p.Path == Proposed.PercentageProperty);
LayerPropertyType = Proposed.LayerPropertyType;
}
public LayerPropertyType LayerPropertyType
@ -74,19 +69,17 @@ namespace Artemis.ViewModels.LayerEditor
}
}
public LayerDynamicPropertiesModel LayerDynamicPropertiesModelProposed
public DynamicPropertiesModel Proposed
{
get { return _layerDynamicPropertiesModelProposed; }
get { return _proposed; }
set
{
if (Equals(value, _layerDynamicPropertiesModelProposed)) return;
_layerDynamicPropertiesModelProposed = value;
NotifyOfPropertyChange(() => LayerDynamicPropertiesModelProposed);
if (Equals(value, _proposed)) return;
_proposed = value;
NotifyOfPropertyChange(() => Proposed);
}
}
public BindableCollection<GeneralHelpers.PropertyCollection> Targets { get; set; }
public GeneralHelpers.PropertyCollection SelectedTarget
{
get { return _selectedTarget; }
@ -98,8 +91,6 @@ namespace Artemis.ViewModels.LayerEditor
}
}
public BindableCollection<GeneralHelpers.PropertyCollection> Sources { get; set; }
public GeneralHelpers.PropertyCollection SelectedSource
{
get { return _selectedSource; }
@ -133,15 +124,19 @@ namespace Artemis.ViewModels.LayerEditor
}
}
public BindableCollection<GeneralHelpers.PropertyCollection> Targets { get; set; }
public BindableCollection<GeneralHelpers.PropertyCollection> Sources { get; set; }
private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "SelectedTarget")
LayerDynamicPropertiesModelProposed.GameProperty = SelectedTarget.Path;
Proposed.GameProperty = SelectedTarget.Path;
if (e.PropertyName == "SelectedSource")
LayerDynamicPropertiesModelProposed.PercentageSource = SelectedSource.Path;
Proposed.PercentageProperty = SelectedSource.Path;
if (e.PropertyName == "LayerPropertyType")
{
LayerDynamicPropertiesModelProposed.LayerPropertyType = LayerPropertyType;
Proposed.LayerPropertyType = LayerPropertyType;
UserSourceIsVisible = LayerPropertyType == LayerPropertyType.PercentageOf;
SourcesIsVisible = LayerPropertyType == LayerPropertyType.PercentageOfProperty;
}
@ -149,11 +144,11 @@ namespace Artemis.ViewModels.LayerEditor
public void Apply()
{
var original = _layer.LayerProperties.FirstOrDefault(lp => lp.LayerProperty == _property);
var original = _keyboardProperties.DynamicProperties.FirstOrDefault(lp => lp.LayerProperty == _property);
if (original == null)
_layer.LayerProperties.Add(LayerDynamicPropertiesModelProposed);
_keyboardProperties.DynamicProperties.Add(Proposed);
else
GeneralHelpers.CopyProperties(original, LayerDynamicPropertiesModelProposed);
GeneralHelpers.CopyProperties(original, Proposed);
}
}
}

View File

@ -2,13 +2,10 @@
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Threading;
using System.Windows.Forms;
using System.Windows.Media;
using Artemis.KeyboardProviders;
using Artemis.Models;
using Artemis.Models.Interfaces;
using Artemis.Models.Profiles;
using Artemis.Models.Profiles.Properties;
using Artemis.Services;
using Artemis.Utilities;
using Caliburn.Micro;
@ -19,49 +16,34 @@ namespace Artemis.ViewModels.LayerEditor
{
public sealed class LayerEditorViewModel : Screen
{
private readonly KeyboardProvider _activeKeyboard;
private readonly BackgroundWorker _previewWorker;
private readonly IGameDataModel _gameDataModel;
private readonly bool _wasEnabled;
private LayerModel _layer;
private LayerPropertiesViewModel _layerPropertiesViewModel;
private LayerType _layerType;
private LayerModel _proposedLayer;
private LayerPropertiesModel _proposedProperties;
private LayerKeyboardViewModel _layerKeyboardViewModel;
public LayerEditorViewModel(IGameDataModel gameDataModel, KeyboardProvider activeKeyboard, LayerModel layer)
public LayerEditorViewModel(IGameDataModel gameDataModel, LayerModel layer)
{
_activeKeyboard = activeKeyboard;
_gameDataModel = gameDataModel;
_wasEnabled = layer.Enabled;
Layer = layer;
ProposedLayer = new LayerModel();
GeneralHelpers.CopyProperties(ProposedLayer, Layer);
Layer.Enabled = false;
DataModelProps = new BindableCollection<GeneralHelpers.PropertyCollection>();
ProposedProperties = new LayerPropertiesModel();
DataModelProps.AddRange(GeneralHelpers.GenerateTypeMap(gameDataModel));
LayerConditionVms =
new BindableCollection<LayerConditionViewModel>(
layer.LayerConditions.Select(c => new LayerConditionViewModel(this, c, DataModelProps)));
HeightProperties = new LayerDynamicPropertiesViewModel("Height", DataModelProps, layer);
WidthProperties = new LayerDynamicPropertiesViewModel("Width", DataModelProps, layer);
OpacityProperties = new LayerDynamicPropertiesViewModel("Opacity", DataModelProps, layer);
LayerConditionVms = new BindableCollection<LayerConditionViewModel>(layer.Properties.Conditions
.Select(c => new LayerConditionViewModel(this, c, DataModelProps)));
_previewWorker = new BackgroundWorker {WorkerSupportsCancellation = true};
_previewWorker.DoWork += PreviewWorkerOnDoWork;
_previewWorker.RunWorkerAsync();
PropertyChanged += GridDisplayHandler;
PropertyChanged += PropertiesViewModelHandler;
PreSelect();
}
[Inject]
public MetroDialogService DialogService { get; set; }
public LayerDynamicPropertiesViewModel OpacityProperties { get; set; }
public LayerDynamicPropertiesViewModel WidthProperties { get; set; }
public LayerDynamicPropertiesViewModel HeightProperties { get; set; }
public BindableCollection<GeneralHelpers.PropertyCollection> DataModelProps { get; set; }
@ -102,34 +84,6 @@ namespace Artemis.ViewModels.LayerEditor
}
}
public bool KeyboardGridIsVisible => Layer.LayerType == LayerType.Keyboard;
public bool GifGridIsVisible => Layer.LayerType == LayerType.KeyboardGif;
public ImageSource LayerImage
{
get
{
var keyboardRect = _activeKeyboard.KeyboardRectangle(4);
var visual = new DrawingVisual();
using (var drawingContext = visual.RenderOpen())
{
// Setup the DrawingVisual's size
drawingContext.PushClip(new RectangleGeometry(keyboardRect));
drawingContext.DrawRectangle(new SolidColorBrush(Color.FromArgb(0, 0, 0, 0)), null, keyboardRect);
// Draw the layer
_layer.DrawPreview(drawingContext);
// Remove the clip
drawingContext.Pop();
}
var image = new DrawingImage(visual.Drawing);
return image;
}
}
public LayerType LayerType
{
get { return _layerType; }
@ -141,63 +95,67 @@ namespace Artemis.ViewModels.LayerEditor
}
}
private void PreviewWorkerOnDoWork(object sender, DoWorkEventArgs doWorkEventArgs)
public LayerPropertiesViewModel LayerPropertiesViewModel
{
while (!_previewWorker.CancellationPending)
get { return _layerPropertiesViewModel; }
set
{
NotifyOfPropertyChange(() => LayerImage);
Thread.Sleep(1000/25);
if (Equals(value, _layerPropertiesViewModel)) return;
_layerPropertiesViewModel = value;
NotifyOfPropertyChange(() => LayerPropertiesViewModel);
}
}
public bool KeyboardGridIsVisible => Layer.LayerType == LayerType.Keyboard;
public bool GifGridIsVisible => Layer.LayerType == LayerType.KeyboardGif;
public void PreSelect()
{
GeneralHelpers.CopyProperties(ProposedProperties, Layer.UserProps);
LayerType = Layer.LayerType;
GeneralHelpers.CopyProperties(ProposedProperties, Layer.Properties);
}
private void GridDisplayHandler(object sender, PropertyChangedEventArgs e)
private void PropertiesViewModelHandler(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName != "LayerType")
return;
Layer.LayerType = LayerType;
if (LayerType != LayerType.Keyboard && LayerType != LayerType.KeyboardGif)
LayerKeyboardViewModel = null;
if ((LayerType == LayerType.Keyboard || LayerType == LayerType.KeyboardGif) && LayerKeyboardViewModel == null)
LayerKeyboardViewModel = new LayerKeyboardViewModel();
// Update the KeyboardPropertiesViewModel if it's being used
var model = LayerPropertiesViewModel as KeyboardPropertiesViewModel;
if (model != null)
model.IsGif = LayerType == LayerType.KeyboardGif;
NotifyOfPropertyChange(() => KeyboardGridIsVisible);
NotifyOfPropertyChange(() => GifGridIsVisible);
}
public LayerKeyboardViewModel LayerKeyboardViewModel
{
get { return _layerKeyboardViewModel; }
set
// Apply the proper PropertiesViewModel
if ((LayerType == LayerType.Keyboard || LayerType == LayerType.KeyboardGif) &&
!(LayerPropertiesViewModel is KeyboardPropertiesViewModel))
{
if (Equals(value, _layerKeyboardViewModel)) return;
_layerKeyboardViewModel = value;
NotifyOfPropertyChange(() => LayerKeyboardViewModel);
LayerPropertiesViewModel = new KeyboardPropertiesViewModel(_gameDataModel, Layer.Properties)
{
IsGif = LayerType == LayerType.KeyboardGif
};
}
else if (LayerType == LayerType.Mouse && !(LayerPropertiesViewModel is MousePropertiesViewModel))
LayerPropertiesViewModel = new MousePropertiesViewModel(_gameDataModel);
NotifyOfPropertyChange(() => LayerPropertiesViewModel);
}
public void AddCondition()
{
var condition = new LayerConditionModel();
Layer.LayerConditions.Add(condition);
Layer.Properties.Conditions.Add(condition);
LayerConditionVms.Add(new LayerConditionViewModel(this, condition, DataModelProps));
}
public void Apply()
{
GeneralHelpers.CopyProperties(Layer.UserProps, ProposedProperties);
HeightProperties.Apply();
WidthProperties.Apply();
OpacityProperties.Apply();
Layer.Properties = LayerPropertiesViewModel.GetAppliedProperties();
if (!File.Exists(Layer.GifFile) && Layer.LayerType == LayerType.KeyboardGif)
if (Layer.LayerType != LayerType.KeyboardGif)
return; // Don't bother checking for a GIF path unless the type is GIF
if (!File.Exists(((KeyboardPropertiesModel) Layer.Properties).GifFile))
DialogService.ShowErrorMessageBox("Couldn't find or access the provided GIF file.");
}
@ -205,20 +163,21 @@ namespace Artemis.ViewModels.LayerEditor
LayerConditionModel layerConditionModel)
{
LayerConditionVms.Remove(layerConditionViewModel);
Layer.LayerConditions.Remove(layerConditionModel);
Layer.Properties.Conditions.Remove(layerConditionModel);
}
public void BrowseGif()
{
if (Layer.LayerType != LayerType.KeyboardGif)
return;
var dialog = new OpenFileDialog {Filter = "Animated image file (*.gif)|*.gif"};
var result = dialog.ShowDialog();
if (result == DialogResult.OK)
Layer.GifFile = dialog.FileName;
((KeyboardPropertiesModel) Layer.Properties).GifFile = dialog.FileName;
}
public override void CanClose(Action<bool> callback)
{
_previewWorker.CancelAsync();
_layer.Enabled = _wasEnabled;
base.CanClose(callback);
}

View File

@ -1,8 +0,0 @@
using Caliburn.Micro;
namespace Artemis.ViewModels.LayerEditor
{
public class LayerKeyboardViewModel : PropertyChangedBase
{
}
}

View File

@ -0,0 +1,18 @@
using Artemis.Models.Interfaces;
using Artemis.Models.Profiles.Properties;
using Caliburn.Micro;
namespace Artemis.ViewModels.LayerEditor
{
public abstract class LayerPropertiesViewModel : PropertyChangedBase
{
public IGameDataModel GameDataModel { get; set; }
protected LayerPropertiesViewModel(IGameDataModel gameDataModel)
{
GameDataModel = gameDataModel;
}
public abstract LayerPropertiesModel GetAppliedProperties();
}
}

View File

@ -0,0 +1,17 @@
using Artemis.Models.Interfaces;
using Artemis.Models.Profiles.Properties;
namespace Artemis.ViewModels.LayerEditor
{
public class MousePropertiesViewModel : LayerPropertiesViewModel
{
public MousePropertiesViewModel(IGameDataModel gameDataModel) : base(gameDataModel)
{
}
public override LayerPropertiesModel GetAppliedProperties()
{
return null;
}
}
}

View File

@ -12,6 +12,7 @@ using Artemis.KeyboardProviders;
using Artemis.Managers;
using Artemis.Models;
using Artemis.Models.Profiles;
using Artemis.Models.Profiles.Properties;
using Artemis.Services;
using Artemis.Utilities;
using Artemis.ViewModels.LayerEditor;
@ -51,6 +52,7 @@ namespace Artemis.ViewModels
[Inject]
public MetroDialogService DialogService { get; set; }
public BindableCollection<ProfileModel> Profiles
{
get { return _profiles; }
@ -130,11 +132,13 @@ namespace Artemis.ViewModels
drawingContext.DrawRectangle(new SolidColorBrush(Color.FromArgb(0, 0, 0, 0)), null, keyboardRect);
// Draw the layers
foreach (
var layerModel in
_selectedProfile.Layers.OrderByDescending(l => l.Order)
.Where(l => l.LayerType == LayerType.Keyboard || l.LayerType == LayerType.KeyboardGif))
layerModel.DrawPreview(drawingContext);
foreach (var layerModel in _selectedProfile.Layers
.OrderByDescending(l => l.Order)
.Where(l => l.LayerType == LayerType.Keyboard ||
l.LayerType == LayerType.KeyboardGif))
{
layerModel.Draw<object>(null, drawingContext, true);
}
// Get the selection color
var color = (Color) ThemeManager.DetectAppStyle(Application.Current).Item2.Resources["AccentColor"];
@ -143,7 +147,7 @@ namespace Artemis.ViewModels
// Draw the selection outline and resize indicator
if (SelectedLayer != null && ShouldDrawLayer(SelectedLayer))
{
var layerRect = SelectedLayer.UserProps.GetRect();
var layerRect = ((KeyboardPropertiesModel) SelectedLayer.Properties).GetRect();
// Deflate the rect so that the border is drawn on the inside
layerRect.Inflate(-0.2, -0.2);
@ -226,6 +230,11 @@ namespace Artemis.ViewModels
{
var name = await DialogService.ShowInputDialog("Add new profile",
"Please provide a profile name unique to this game and keyboard.");
// Null when the user cancelled
if (name == null)
return;
if (name.Length < 1)
{
DialogService.ShowMessageBox("Invalid profile name", "Please provide a valid profile name");
@ -265,7 +274,7 @@ namespace Artemis.ViewModels
public void LayerEditor(LayerModel layer)
{
IWindowManager manager = new WindowManager();
_editorVm = new LayerEditorViewModel(_gameModel.GameDataModel, ActiveKeyboard, layer);
_editorVm = new LayerEditorViewModel(_gameModel.GameDataModel, layer);
dynamic settings = new ExpandoObject();
settings.Title = "Artemis | Edit " + layer.Name;
@ -340,10 +349,10 @@ namespace Artemis.ViewModels
var reorderLayer = SelectedLayer;
if (SelectedLayer.ParentLayer != null)
SelectedLayer.ParentLayer.Reorder(SelectedLayer, true);
if (SelectedLayer.Parent != null)
SelectedLayer.Parent.Reorder(SelectedLayer, true);
else
SelectedLayer.ParentProfile.Reorder(SelectedLayer, true);
SelectedLayer.Profile.Reorder(SelectedLayer, true);
NotifyOfPropertyChange(() => Layers);
SelectedLayer = reorderLayer;
@ -359,10 +368,10 @@ namespace Artemis.ViewModels
var reorderLayer = SelectedLayer;
if (SelectedLayer.ParentLayer != null)
SelectedLayer.ParentLayer.Reorder(SelectedLayer, false);
if (SelectedLayer.Parent != null)
SelectedLayer.Parent.Reorder(SelectedLayer, false);
else
SelectedLayer.ParentProfile.Reorder(SelectedLayer, false);
SelectedLayer.Profile.Reorder(SelectedLayer, false);
NotifyOfPropertyChange(() => Layers);
SelectedLayer = reorderLayer;
@ -394,7 +403,7 @@ namespace Artemis.ViewModels
var y = pos.Y/((double) ActiveKeyboard.PreviewSettings.Height/ActiveKeyboard.Height);
var hoverLayer = SelectedProfile.Layers.OrderBy(l => l.Order).Where(ShouldDrawLayer)
.FirstOrDefault(l => l.UserProps.GetRect(1).Contains(x, y));
.FirstOrDefault(l => ((KeyboardPropertiesModel) l.Properties).GetRect(1).Contains(x, y));
SelectedLayer = hoverLayer;
}
@ -408,7 +417,7 @@ namespace Artemis.ViewModels
var x = pos.X/((double) ActiveKeyboard.PreviewSettings.Width/ActiveKeyboard.Width);
var y = pos.Y/((double) ActiveKeyboard.PreviewSettings.Height/ActiveKeyboard.Height);
var hoverLayer = SelectedProfile.Layers.OrderBy(l => l.Order).Where(ShouldDrawLayer)
.FirstOrDefault(l => l.UserProps.GetRect(1).Contains(x, y));
.FirstOrDefault(l => ((KeyboardPropertiesModel) l.Properties).GetRect(1).Contains(x, y));
HandleDragging(e, x, y, hoverLayer);
@ -422,7 +431,7 @@ namespace Artemis.ViewModels
// Turn the mouse pointer into a hand if hovering over an active layer
if (hoverLayer == SelectedLayer)
{
var rect = hoverLayer.UserProps.GetRect(1);
var rect = ((KeyboardPropertiesModel) hoverLayer.Properties).GetRect(1);
KeyboardPreviewCursor =
Math.Sqrt(Math.Pow(x - rect.BottomRight.X, 2) + Math.Pow(y - rect.BottomRight.Y, 2)) < 0.6
? Cursors.SizeNWSE
@ -456,8 +465,10 @@ namespace Artemis.ViewModels
// Setup the dragging state on mouse press
if (_draggingLayerOffset == null && hoverLayer != null && e.LeftButton == MouseButtonState.Pressed)
{
var layerRect = hoverLayer.UserProps.GetRect(1);
_draggingLayerOffset = new Point(x - SelectedLayer.UserProps.X, y - SelectedLayer.UserProps.Y);
var layerRect = ((KeyboardPropertiesModel) hoverLayer.Properties).GetRect(1);
var selectedProps = (KeyboardPropertiesModel) SelectedLayer.Properties;
_draggingLayerOffset = new Point(x - selectedProps.X, y - selectedProps.Y);
_draggingLayer = hoverLayer;
if (Math.Sqrt(Math.Pow(x - layerRect.BottomRight.X, 2) + Math.Pow(y - layerRect.BottomRight.Y, 2)) < 0.6)
_resizing = true;
@ -468,20 +479,22 @@ namespace Artemis.ViewModels
if (_draggingLayerOffset == null || _draggingLayer == null || (_draggingLayer != SelectedLayer))
return;
var draggingProps = (KeyboardPropertiesModel) _draggingLayer?.Properties;
// If no setup or reset was done, handle the actual dragging action
if (_resizing)
{
_draggingLayer.UserProps.Width = (int) Math.Round(x - _draggingLayer.UserProps.X);
_draggingLayer.UserProps.Height = (int) Math.Round(y - _draggingLayer.UserProps.Y);
if (_draggingLayer.UserProps.Width < 1)
_draggingLayer.UserProps.Width = 1;
if (_draggingLayer.UserProps.Height < 1)
_draggingLayer.UserProps.Height = 1;
draggingProps.Width = (int) Math.Round(x - draggingProps.X);
draggingProps.Height = (int) Math.Round(y - draggingProps.Y);
if (draggingProps.Width < 1)
draggingProps.Width = 1;
if (draggingProps.Height < 1)
draggingProps.Height = 1;
}
else
{
_draggingLayer.UserProps.X = (int) Math.Round(x - _draggingLayerOffset.Value.X);
_draggingLayer.UserProps.Y = (int) Math.Round(y - _draggingLayerOffset.Value.Y);
draggingProps.X = (int) Math.Round(x - _draggingLayerOffset.Value.X);
draggingProps.Y = (int) Math.Round(y - _draggingLayerOffset.Value.Y);
}
NotifyOfPropertyChange(() => KeyboardPreview);
}

View File

@ -1,12 +1,25 @@
<UserControl x:Class="Artemis.Views.LayerEditor.LayerKeyboardView"
<UserControl x:Class="Artemis.Views.LayerEditor.KeyboardPropertiesView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
xmlns:ncore="http://schemas.ncore.com/wpf/xaml/colorbox"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:properties="clr-namespace:Artemis.Models.Profiles.Properties"
xmlns:utilities="clr-namespace:Artemis.Utilities"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
<utilities:EnumDescriptionConverter x:Key="HEnumDescriptionConverter" />
<ObjectDataProvider MethodName="GetValues"
ObjectType="{x:Type sys:Enum}"
x:Key="AnimationEnumValues">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="properties:LayerAnimation" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</UserControl.Resources>
<Grid>
<!-- Colors -->
<Grid.ColumnDefinitions>
@ -49,14 +62,14 @@
<!-- ClippingType -->
<TextBlock Grid.Row="1" Grid.Column="0" Margin="10, 13, 10, 10" FontSize="13.333" Text="Clipping type:"
VerticalAlignment="Center" Height="23"/>
<controls:ToggleSwitch IsChecked="{Binding Path=ProposedProperties.ContainedBrush, Mode=TwoWay}"
<controls:ToggleSwitch IsChecked="{Binding Path=ProposedProperties.Contain, Mode=TwoWay}"
Grid.Row="1"
Grid.Column="1" OnLabel="Contain" OffLabel="Cut-off" Margin="10,1,5,1"
VerticalAlignment="Center"
Height="36" />
<!-- Colors -->
<StackPanel Grid.Row="1" Grid.Column="2" Grid.ColumnSpan="2" Orientation="Horizontal" x:Name="KeyboardGridIsVisible">
<StackPanel Grid.Row="1" Grid.Column="2" Grid.ColumnSpan="2" Orientation="Horizontal" x:Name="ShowBrush">
<TextBlock Margin="10,13,10,0" FontSize="13.333" Text="Color(s):"
VerticalAlignment="Top" Height="18" Width="130" />
<Border Margin="10" BorderBrush="{StaticResource ControlBorderBrush}"
@ -66,7 +79,7 @@
</StackPanel>
<!-- GIF settings -->
<Grid Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="4" x:Name="GifGridIsVisible">
<Grid Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="4" x:Name="ShowGif">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
@ -81,7 +94,7 @@
VerticalAlignment="Top" Height="18" />
<Grid Grid.Row="0" Grid.Column="1" ColumnSpan="3" Margin="5,2,10,0" VerticalAlignment="Top">
<TextBox Height="23" TextWrapping="Wrap" Margin="5,0,30,0"
Text="{Binding Path=Layer.GifFile, Mode=TwoWay}" />
Text="{Binding Path=ProposedProperties.GifFile, Mode=TwoWay}" />
<Button x:Name="BrowseGif" Content="..." RenderTransformOrigin="-0.039,-0.944"
HorizontalAlignment="Right" Width="25" Style="{DynamicResource SquareButtonStyle}" Height="25" />
</Grid>

View File

@ -16,11 +16,11 @@ using System.Windows.Shapes;
namespace Artemis.Views.LayerEditor
{
/// <summary>
/// Interaction logic for LayerMouseView.xaml
/// Interaction logic for KeyboardPropertiesView.xaml
/// </summary>
public partial class LayerMouseView : UserControl
public partial class KeyboardPropertiesView : UserControl
{
public LayerMouseView()
public KeyboardPropertiesView()
{
InitializeComponent();
}

View File

@ -3,11 +3,10 @@
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.Views.LayerEditor"
xmlns:utilities="clr-namespace:Artemis.Utilities"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:profileEnumerations="clr-namespace:Artemis.Models.Profiles"
xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
xmlns:properties="clr-namespace:Artemis.Models.Profiles.Properties"
mc:Ignorable="d"
d:DesignHeight="40" d:DesignWidth="500">
@ -17,7 +16,7 @@
ObjectType="{x:Type sys:Enum}"
x:Key="DynamicPropertyValues">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="profileEnumerations:LayerPropertyType" />
<x:Type TypeName="properties:LayerPropertyType" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</UserControl.Resources>
@ -81,8 +80,7 @@
<!-- PercentageOf -->
<StackPanel Grid.Column="3" x:Name="UserSourceIsVisible" VerticalAlignment="Center">
<controls:NumericUpDown Margin="10,0" Height="22"
Value="{Binding Path=LayerDynamicPropertiesModelProposed.PercentageSource, Mode=TwoWay}" />
<controls:NumericUpDown Margin="10,0" Height="22" Value="{Binding Path=Proposed.PercentageSource, Mode=TwoWay}" />
</StackPanel>
</Grid>
</UserControl>

View File

@ -10,6 +10,7 @@
Title="Artemis | Edit Layer" Height="750" Width="630"
xmlns:profileEnumerations="clr-namespace:Artemis.Models.Profiles"
xmlns:ncore="http://schemas.ncore.com/wpf/xaml/colorbox"
xmlns:properties="clr-namespace:Artemis.Models.Profiles.Properties"
GlowBrush="{DynamicResource AccentColorBrush}" Icon="../../Resources/bow.png"
ResizeMode="NoResize">
<controls:MetroWindow.Resources>
@ -21,20 +22,6 @@
<x:Type TypeName="profileEnumerations:LayerType" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<ObjectDataProvider MethodName="GetValues"
ObjectType="{x:Type sys:Enum}"
x:Key="AnimationEnumValues">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="profileEnumerations:LayerAnimation" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<ObjectDataProvider MethodName="GetValues"
ObjectType="{x:Type sys:Enum}"
x:Key="DynamicPropertyValues">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="profileEnumerations:LayerPropertyType" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</controls:MetroWindow.Resources>
<Grid Margin="10,0">
@ -97,12 +84,9 @@
<Label Grid.Row="4" Grid.Column="0" FontSize="20" HorizontalAlignment="Left"
Content="Advanced" Width="97" VerticalAlignment="Bottom" />
<!-- Advanced settings - Keyboard -->
<ContentControl Grid.Row="5" Grid.ColumnSpan="4" Grid.Column="0" x:Name="LayerAdvancedKeyboardViewModel" />
<!-- Advanced settings -->
<ContentControl Grid.Row="5" Grid.ColumnSpan="4" Grid.Column="0" x:Name="LayerPropertiesViewModel" />
<!-- Advanced settings - Mouse -->
<ContentControl Grid.Row="5" Grid.ColumnSpan="4" Grid.Column="0" x:Name="MouseProperties" />
<Button Grid.Row="6" Grid.Column="0" x:Name="Apply" Content="Apply" VerticalAlignment="Bottom"
Style="{DynamicResource SquareButtonStyle}" Width="95" HorizontalAlignment="Left" Margin="10,0,0,20"
Height="30" />

View File

@ -1,4 +1,4 @@
<UserControl x:Class="Artemis.Views.LayerEditor.LayerMouseView"
<UserControl x:Class="Artemis.Views.LayerEditor.MousePropertiesView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
@ -7,6 +7,6 @@
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<TextBlock>NYI</TextBlock>
</Grid>
</UserControl>

View File

@ -16,11 +16,11 @@ using System.Windows.Shapes;
namespace Artemis.Views.LayerEditor
{
/// <summary>
/// Interaction logic for LayerKeyboardView.xaml
/// Interaction logic for MousePropertiesView.xaml
/// </summary>
public partial class LayerKeyboardView : UserControl
public partial class MousePropertiesView : UserControl
{
public LayerKeyboardView()
public MousePropertiesView()
{
InitializeComponent();
}