mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
commit
80cd620247
@ -56,6 +56,7 @@
|
|||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<Prefer32Bit>false</Prefer32Bit>
|
<Prefer32Bit>false</Prefer32Bit>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
@ -65,6 +66,7 @@
|
|||||||
<DefineConstants>TRACE</DefineConstants>
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<ManifestCertificateThumbprint>EAC088BE27A2DE790AE6F37A020409F4A1B5EC0E</ManifestCertificateThumbprint>
|
<ManifestCertificateThumbprint>EAC088BE27A2DE790AE6F37A020409F4A1B5EC0E</ManifestCertificateThumbprint>
|
||||||
@ -491,6 +493,13 @@
|
|||||||
<Compile Include="Profiles\Layers\Types\AmbientLight\ScreenCapturing\DX9ScreenCapture.cs" />
|
<Compile Include="Profiles\Layers\Types\AmbientLight\ScreenCapturing\DX9ScreenCapture.cs" />
|
||||||
<Compile Include="Profiles\Layers\Types\AmbientLight\ScreenCapturing\IScreenCapture.cs" />
|
<Compile Include="Profiles\Layers\Types\AmbientLight\ScreenCapturing\IScreenCapture.cs" />
|
||||||
<Compile Include="Profiles\Layers\Types\AmbientLight\ScreenCapturing\ScreenCaptureManager.cs" />
|
<Compile Include="Profiles\Layers\Types\AmbientLight\ScreenCapturing\ScreenCaptureManager.cs" />
|
||||||
|
<Compile Include="Profiles\Layers\Types\AngularBrush\AngularBrushPropertiesModel.cs" />
|
||||||
|
<Compile Include="Profiles\Layers\Types\AngularBrush\AngularBrushPropertiesView.xaml.cs">
|
||||||
|
<DependentUpon>AngularBrushPropertiesView.xaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Profiles\Layers\Types\AngularBrush\AngularBrushPropertiesViewModel.cs" />
|
||||||
|
<Compile Include="Profiles\Layers\Types\AngularBrush\AngularBrushType.cs" />
|
||||||
|
<Compile Include="Profiles\Layers\Types\AngularBrush\Drawing\GradientDrawer.cs" />
|
||||||
<Compile Include="Profiles\Layers\Types\Audio\AudioCapturing\AudioCapture.cs" />
|
<Compile Include="Profiles\Layers\Types\Audio\AudioCapturing\AudioCapture.cs" />
|
||||||
<Compile Include="Profiles\Layers\Types\Audio\AudioCapturing\AudioCaptureManager.cs" />
|
<Compile Include="Profiles\Layers\Types\Audio\AudioCapturing\AudioCaptureManager.cs" />
|
||||||
<Compile Include="Events\AudioDeviceChangedEventArgs.cs" />
|
<Compile Include="Events\AudioDeviceChangedEventArgs.cs" />
|
||||||
@ -862,6 +871,10 @@
|
|||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</Page>
|
</Page>
|
||||||
|
<Page Include="Profiles\Layers\Types\AngularBrush\AngularBrushPropertiesView.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
</Page>
|
||||||
<Page Include="Profiles\Layers\Types\Audio\AudioPropertiesView.xaml">
|
<Page Include="Profiles\Layers\Types\Audio\AudioPropertiesView.xaml">
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
|
|||||||
@ -3,13 +3,10 @@ using System.Drawing;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Timers;
|
|
||||||
using System.Windows.Media;
|
|
||||||
using Artemis.DeviceProviders;
|
using Artemis.DeviceProviders;
|
||||||
using Artemis.ViewModels;
|
using Artemis.ViewModels;
|
||||||
using Ninject.Extensions.Logging;
|
using Ninject.Extensions.Logging;
|
||||||
using Color = System.Drawing.Color;
|
using Color = System.Drawing.Color;
|
||||||
using Timer = System.Timers.Timer;
|
|
||||||
|
|
||||||
namespace Artemis.Managers
|
namespace Artemis.Managers
|
||||||
{
|
{
|
||||||
@ -21,7 +18,8 @@ namespace Artemis.Managers
|
|||||||
private readonly DebugViewModel _debugViewModel;
|
private readonly DebugViewModel _debugViewModel;
|
||||||
private readonly DeviceManager _deviceManager;
|
private readonly DeviceManager _deviceManager;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private readonly Timer _loopTimer;
|
//private readonly Timer _loopTimer;
|
||||||
|
private readonly Task _loopTask;
|
||||||
private readonly ModuleManager _moduleManager;
|
private readonly ModuleManager _moduleManager;
|
||||||
|
|
||||||
public LoopManager(ILogger logger, ModuleManager moduleManager, DeviceManager deviceManager,
|
public LoopManager(ILogger logger, ModuleManager moduleManager, DeviceManager deviceManager,
|
||||||
@ -33,10 +31,10 @@ namespace Artemis.Managers
|
|||||||
_debugViewModel = debugViewModel;
|
_debugViewModel = debugViewModel;
|
||||||
|
|
||||||
// Setup timers
|
// Setup timers
|
||||||
_loopTimer = new Timer(40);
|
//_loopTimer = new Timer(40);
|
||||||
_loopTimer.Elapsed += LoopTimerOnElapsed;
|
//_loopTimer.Elapsed += LoopTimerOnElapsed;
|
||||||
_loopTimer.Start();
|
//_loopTimer.Start();
|
||||||
|
_loopTask = Task.Factory.StartNew(ProcessLoop);
|
||||||
_logger.Info("Intialized LoopManager");
|
_logger.Info("Intialized LoopManager");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,22 +47,45 @@ namespace Artemis.Managers
|
|||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_loopTimer.Stop();
|
_loopTask.Dispose();
|
||||||
_loopTimer.Dispose();
|
//_loopTimer.Stop();
|
||||||
|
//_loopTimer.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LoopTimerOnElapsed(object sender, ElapsedEventArgs elapsedEventArgs)
|
private void ProcessLoop()
|
||||||
{
|
{
|
||||||
try
|
//TODO DarthAffe 14.01.2017: A stop-condition and a real cleanup instead of just aborting might be better
|
||||||
|
while (true)
|
||||||
{
|
{
|
||||||
Render();
|
try
|
||||||
}
|
{
|
||||||
catch (Exception e)
|
long preUpdateTicks = DateTime.Now.Ticks;
|
||||||
{
|
|
||||||
_logger.Warn(e, "Exception in render loop");
|
Render();
|
||||||
|
|
||||||
|
int sleep = (int)(40f - ((DateTime.Now.Ticks - preUpdateTicks) / 10000f));
|
||||||
|
if (sleep > 0)
|
||||||
|
Thread.Sleep(sleep);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_logger.Warn(e, "Exception in render loop");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//private void LoopTimerOnElapsed(object sender, ElapsedEventArgs elapsedEventArgs)
|
||||||
|
//{
|
||||||
|
// try
|
||||||
|
// {
|
||||||
|
// Render();
|
||||||
|
// }
|
||||||
|
// catch (Exception e)
|
||||||
|
// {
|
||||||
|
// _logger.Warn(e, "Exception in render loop");
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
public Task StartAsync()
|
public Task StartAsync()
|
||||||
{
|
{
|
||||||
return Task.Run(() => Start());
|
return Task.Run(() => Start());
|
||||||
|
|||||||
@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using Artemis.Profiles.Layers.Models;
|
||||||
|
|
||||||
|
namespace Artemis.Profiles.Layers.Types.AngularBrush
|
||||||
|
{
|
||||||
|
public class AngularBrushPropertiesModel : LayerPropertiesModel
|
||||||
|
{
|
||||||
|
#region Properties & Fields
|
||||||
|
|
||||||
|
public IList<Tuple<double, Color>> GradientStops { get; set; }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
|
||||||
|
public AngularBrushPropertiesModel(LayerPropertiesModel properties = null)
|
||||||
|
: base(properties)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,80 @@
|
|||||||
|
<UserControl x:Class="Artemis.Profiles.Layers.Types.AngularBrush.AngularBrushPropertiesView"
|
||||||
|
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:controls="http://metro.mahapps.com/winfx/xaml/controls"
|
||||||
|
xmlns:ncore="http://schemas.ncore.com/wpf/xaml/colorbox"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
d:DesignHeight="300" d:DesignWidth="300">
|
||||||
|
<Grid>
|
||||||
|
<!-- Colors -->
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition />
|
||||||
|
<ColumnDefinition />
|
||||||
|
<ColumnDefinition />
|
||||||
|
<ColumnDefinition />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<!-- Animation -->
|
||||||
|
<TextBlock Grid.Row="0" Grid.Column="0" Margin="10" FontSize="13.333" Text="Animation:"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Height="18" />
|
||||||
|
<ComboBox Grid.Row="0" Grid.Column="1" Margin="10,10,10,0" x:Name="LayerAnimations" VerticalAlignment="Top"
|
||||||
|
Height="22">
|
||||||
|
<ComboBox.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<TextBlock Text="{Binding Path=Name, Mode=OneWay}" />
|
||||||
|
</DataTemplate>
|
||||||
|
</ComboBox.ItemTemplate>
|
||||||
|
</ComboBox>
|
||||||
|
|
||||||
|
<!-- Animation Speed -->
|
||||||
|
<TextBlock Grid.Row="0" Grid.Column="2" Margin="10" FontSize="13.333" Text="Animation speed:"
|
||||||
|
VerticalAlignment="Center" Height="18" />
|
||||||
|
<Slider x:Name="RotationSpeed" Grid.Row="0" Grid.Column="3" VerticalAlignment="Center"
|
||||||
|
TickPlacement="None" TickFrequency="0.05"
|
||||||
|
Value="{Binding Path=LayerModel.Properties.AnimationSpeed, Mode=TwoWay}" Minimum="0.05" Maximum="3"
|
||||||
|
SmallChange="0" IsSnapToTickEnabled="True" Margin="10,12,10,2" Height="24" />
|
||||||
|
|
||||||
|
<!-- 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=LayerModel.Properties.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="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}"
|
||||||
|
BorderThickness="1" SnapsToDevicePixels="True" ToolTip="Click to edit">
|
||||||
|
<ncore:ColorBox Brush="{Binding Brush, Mode=TwoWay}" ShowNone="False" Height="24" Width="134"
|
||||||
|
VerticalAlignment="Top" ShowLinear="True" ShowRadial="False" ShowSolid="False" />
|
||||||
|
</Border>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<!-- Dynamic -->
|
||||||
|
<Label Grid.Row="3" Grid.Column="0" FontSize="20" HorizontalAlignment="Left"
|
||||||
|
Content="Dynamic" Width="97" VerticalAlignment="Bottom" />
|
||||||
|
|
||||||
|
<!-- Dynamic property views -->
|
||||||
|
<ContentControl Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="4" x:Name="HeightProperties" />
|
||||||
|
<ContentControl Grid.Row="5" Grid.Column="0" Grid.ColumnSpan="4" x:Name="WidthProperties" />
|
||||||
|
<ContentControl Grid.Row="6" Grid.Column="0" Grid.ColumnSpan="4" x:Name="OpacityProperties" />
|
||||||
|
|
||||||
|
<ContentControl Grid.Row="7" Grid.Column="0" Grid.ColumnSpan="4" x:Name="LayerTweenViewModel" />
|
||||||
|
</Grid>
|
||||||
|
</UserControl>
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
using System.Windows.Controls;
|
||||||
|
|
||||||
|
namespace Artemis.Profiles.Layers.Types.AngularBrush
|
||||||
|
{
|
||||||
|
public partial class AngularBrushPropertiesView : UserControl
|
||||||
|
{
|
||||||
|
public AngularBrushPropertiesView()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,72 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using Artemis.Profiles.Layers.Abstract;
|
||||||
|
using Artemis.Profiles.Layers.Interfaces;
|
||||||
|
using Artemis.Utilities;
|
||||||
|
using Artemis.ViewModels;
|
||||||
|
using Artemis.ViewModels.Profiles;
|
||||||
|
using Caliburn.Micro;
|
||||||
|
|
||||||
|
namespace Artemis.Profiles.Layers.Types.AngularBrush
|
||||||
|
{
|
||||||
|
public class AngularBrushPropertiesViewModel : LayerPropertiesViewModel
|
||||||
|
{
|
||||||
|
#region Properties & Fields
|
||||||
|
|
||||||
|
private ILayerAnimation _selectedLayerAnimation;
|
||||||
|
|
||||||
|
public BindableCollection<GeneralHelpers.PropertyCollection> DataModelProps { get; set; }
|
||||||
|
public BindableCollection<ILayerAnimation> LayerAnimations { get; set; }
|
||||||
|
public LayerDynamicPropertiesViewModel HeightProperties { get; set; }
|
||||||
|
public LayerDynamicPropertiesViewModel WidthProperties { get; set; }
|
||||||
|
public LayerDynamicPropertiesViewModel OpacityProperties { get; set; }
|
||||||
|
public LayerTweenViewModel LayerTweenViewModel { get; set; }
|
||||||
|
|
||||||
|
public ILayerAnimation SelectedLayerAnimation
|
||||||
|
{
|
||||||
|
get { return _selectedLayerAnimation; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (Equals(value, _selectedLayerAnimation)) return;
|
||||||
|
_selectedLayerAnimation = value;
|
||||||
|
NotifyOfPropertyChange(() => SelectedLayerAnimation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
|
||||||
|
public AngularBrushPropertiesViewModel(LayerEditorViewModel editorVm)
|
||||||
|
: base(editorVm)
|
||||||
|
{
|
||||||
|
LayerAnimations = new BindableCollection<ILayerAnimation>(editorVm.LayerAnimations);
|
||||||
|
|
||||||
|
HeightProperties = new LayerDynamicPropertiesViewModel("Height", editorVm);
|
||||||
|
WidthProperties = new LayerDynamicPropertiesViewModel("Width", editorVm);
|
||||||
|
OpacityProperties = new LayerDynamicPropertiesViewModel("Opacity", editorVm);
|
||||||
|
LayerTweenViewModel = new LayerTweenViewModel(editorVm);
|
||||||
|
|
||||||
|
SelectedLayerAnimation =
|
||||||
|
LayerAnimations.FirstOrDefault(l => l.Name == editorVm.ProposedLayer.LayerAnimation?.Name) ??
|
||||||
|
LayerAnimations.First(l => l.Name == "None");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
|
||||||
|
public override void ApplyProperties()
|
||||||
|
{
|
||||||
|
HeightProperties.Apply(LayerModel);
|
||||||
|
WidthProperties.Apply(LayerModel);
|
||||||
|
OpacityProperties.Apply(LayerModel);
|
||||||
|
|
||||||
|
LayerModel.Properties.Brush = Brush;
|
||||||
|
LayerModel.LayerAnimation = SelectedLayerAnimation;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,130 @@
|
|||||||
|
using System;
|
||||||
|
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.Interfaces;
|
||||||
|
using Artemis.Profiles.Layers.Models;
|
||||||
|
using Artemis.Profiles.Layers.Types.AngularBrush.Drawing;
|
||||||
|
using Artemis.ViewModels;
|
||||||
|
|
||||||
|
namespace Artemis.Profiles.Layers.Types.AngularBrush
|
||||||
|
{
|
||||||
|
public class AngularBrushType : ILayerType
|
||||||
|
{
|
||||||
|
#region Properties & Fields
|
||||||
|
|
||||||
|
private GradientDrawer _gradientDrawer;
|
||||||
|
|
||||||
|
public string Name => "Angular Brush";
|
||||||
|
public bool ShowInEdtor => true;
|
||||||
|
public DrawType DrawType => DrawType.Keyboard;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public AngularBrushType()
|
||||||
|
{
|
||||||
|
_gradientDrawer = new GradientDrawer();
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
|
||||||
|
public ImageSource DrawThumbnail(LayerModel layer)
|
||||||
|
{
|
||||||
|
//TODO DarthAffe 14.01.2017: This could be replaced with the real brush but it complaints about the thread too
|
||||||
|
Rect thumbnailRect = new Rect(0, 0, 18, 18);
|
||||||
|
DrawingVisual visual = new DrawingVisual();
|
||||||
|
using (DrawingContext c = visual.RenderOpen())
|
||||||
|
if (layer.Properties.Brush != null)
|
||||||
|
c.DrawRectangle(layer.Properties.Brush,
|
||||||
|
new Pen(new SolidColorBrush(Colors.White), 1),
|
||||||
|
thumbnailRect);
|
||||||
|
|
||||||
|
DrawingImage image = new DrawingImage(visual.Drawing);
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Draw(LayerModel layerModel, DrawingContext c)
|
||||||
|
{
|
||||||
|
AngularBrushPropertiesModel properties = layerModel.Properties as AngularBrushPropertiesModel;
|
||||||
|
if (properties == null) return;
|
||||||
|
|
||||||
|
Brush origBrush = layerModel.Brush;
|
||||||
|
|
||||||
|
//TODO DarthAffe 14.01.2017: Check if an update is needed
|
||||||
|
_gradientDrawer.GradientStops = GetGradientStops(layerModel.Brush).Select(x => new Tuple<double, Color>(x.Offset, x.Color)).ToList();
|
||||||
|
_gradientDrawer.Update();
|
||||||
|
layerModel.Brush = _gradientDrawer.Brush.Clone();
|
||||||
|
|
||||||
|
// If an animation is present, let it handle the drawing
|
||||||
|
if (layerModel.LayerAnimation != null && !(layerModel.LayerAnimation is NoneAnimation))
|
||||||
|
{
|
||||||
|
layerModel.LayerAnimation.Draw(layerModel, c);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise draw the rectangle with its layer.AppliedProperties dimensions and brush
|
||||||
|
Rect rect = layerModel.Properties.Contain
|
||||||
|
? layerModel.LayerRect()
|
||||||
|
: new Rect(layerModel.Properties.X * 4, layerModel.Properties.Y * 4,
|
||||||
|
layerModel.Properties.Width * 4, layerModel.Properties.Height * 4);
|
||||||
|
|
||||||
|
Rect clip = layerModel.LayerRect();
|
||||||
|
|
||||||
|
// Can't meddle with the original brush because it's frozen.
|
||||||
|
Brush brush = layerModel.Brush.Clone();
|
||||||
|
brush.Opacity = layerModel.Opacity;
|
||||||
|
|
||||||
|
c.PushClip(new RectangleGeometry(clip));
|
||||||
|
c.DrawRectangle(brush, null, rect);
|
||||||
|
c.Pop();
|
||||||
|
|
||||||
|
layerModel.Brush = origBrush;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update(LayerModel layerModel, ModuleDataModel dataModel, bool isPreview = false)
|
||||||
|
{
|
||||||
|
layerModel.ApplyProperties(true);
|
||||||
|
if (isPreview || dataModel == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// If not previewing, apply dynamic properties according to datamodel
|
||||||
|
foreach (DynamicPropertiesModel dynamicProperty in layerModel.Properties.DynamicProperties)
|
||||||
|
dynamicProperty.ApplyProperty(dataModel, layerModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetupProperties(LayerModel layerModel)
|
||||||
|
{
|
||||||
|
if (layerModel.Properties is AngularBrushPropertiesModel)
|
||||||
|
return;
|
||||||
|
|
||||||
|
layerModel.Properties = new AngularBrushPropertiesModel(layerModel.Properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LayerPropertiesViewModel SetupViewModel(LayerEditorViewModel layerEditorViewModel, LayerPropertiesViewModel layerPropertiesViewModel)
|
||||||
|
{
|
||||||
|
return (layerPropertiesViewModel as AngularBrushPropertiesViewModel) ?? new AngularBrushPropertiesViewModel(layerEditorViewModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
private GradientStopCollection GetGradientStops(Brush brush)
|
||||||
|
{
|
||||||
|
LinearGradientBrush linearBrush = brush as LinearGradientBrush;
|
||||||
|
if (linearBrush != null)
|
||||||
|
return linearBrush.GradientStops;
|
||||||
|
|
||||||
|
RadialGradientBrush radialBrush = brush as RadialGradientBrush;
|
||||||
|
if (radialBrush != null)
|
||||||
|
return radialBrush.GradientStops;
|
||||||
|
|
||||||
|
SolidColorBrush solidBrush = brush as SolidColorBrush;
|
||||||
|
if (solidBrush != null)
|
||||||
|
return new GradientStopCollection(new[] { new GradientStop(solidBrush.Color, 0), new GradientStop(solidBrush.Color, 1) });
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,149 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using System.Windows.Media.Imaging;
|
||||||
|
|
||||||
|
namespace Artemis.Profiles.Layers.Types.AngularBrush.Drawing
|
||||||
|
{
|
||||||
|
public class GradientDrawer
|
||||||
|
{
|
||||||
|
#region Constants
|
||||||
|
|
||||||
|
private static readonly double ORIGIN = Math.Atan2(-1, 0);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Properties & Fields
|
||||||
|
|
||||||
|
private WriteableBitmap _bitmap;
|
||||||
|
|
||||||
|
private IList<Tuple<double, Color>> _gradientStops;
|
||||||
|
public IList<Tuple<double, Color>> GradientStops
|
||||||
|
{
|
||||||
|
set { _gradientStops = FixGradientStops(value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Brush Brush { get; private set; }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
|
||||||
|
public void Update()
|
||||||
|
{
|
||||||
|
if (_bitmap == null)
|
||||||
|
CreateBrush();
|
||||||
|
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
_bitmap.Lock();
|
||||||
|
byte* buffer = (byte*)_bitmap.BackBuffer.ToPointer();
|
||||||
|
|
||||||
|
int width = _bitmap.PixelWidth;
|
||||||
|
double widthHalf = width / 2.0;
|
||||||
|
|
||||||
|
int height = _bitmap.PixelHeight;
|
||||||
|
double heightHalf = height / 2.0;
|
||||||
|
|
||||||
|
for (int y = 0; y < height; y++)
|
||||||
|
for (int x = 0; x < width; x++)
|
||||||
|
{
|
||||||
|
int offset = (((y * width) + x) * 4);
|
||||||
|
|
||||||
|
double gradientOffset = CalculateGradientOffset(x, y, widthHalf, heightHalf);
|
||||||
|
GetColor(_gradientStops, gradientOffset,
|
||||||
|
ref buffer[offset + 3], ref buffer[offset + 2],
|
||||||
|
ref buffer[offset + 1], ref buffer[offset]);
|
||||||
|
}
|
||||||
|
|
||||||
|
_bitmap.AddDirtyRect(new Int32Rect(0, 0, width, height));
|
||||||
|
_bitmap.Unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateBrush()
|
||||||
|
{
|
||||||
|
_bitmap = new WriteableBitmap(100, 100, 96, 96, PixelFormats.Bgra32, null);
|
||||||
|
Brush = new ImageBrush(_bitmap) { Stretch = Stretch.UniformToFill };
|
||||||
|
}
|
||||||
|
|
||||||
|
private double CalculateGradientOffset(double x, double y, double centerX, double centerY)
|
||||||
|
{
|
||||||
|
double angle = Math.Atan2(y - centerY, x - centerX) - ORIGIN;
|
||||||
|
if (angle < 0) angle += Math.PI * 2;
|
||||||
|
return angle / (Math.PI * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GetColor(IList<Tuple<double, Color>> gradientStops, double offset, ref byte colA, ref byte colR, ref byte colG, ref byte colB)
|
||||||
|
{
|
||||||
|
if (gradientStops.Count == 0)
|
||||||
|
{
|
||||||
|
colA = 0;
|
||||||
|
colR = 0;
|
||||||
|
colG = 0;
|
||||||
|
colB = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (gradientStops.Count == 1)
|
||||||
|
{
|
||||||
|
Color color = gradientStops.First().Item2;
|
||||||
|
colA = color.A;
|
||||||
|
colR = color.R;
|
||||||
|
colG = color.G;
|
||||||
|
colB = color.B;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Tuple<double, Color> beforeStop = null;
|
||||||
|
double afterOffset = -1;
|
||||||
|
Color afterColor = default(Color);
|
||||||
|
|
||||||
|
for (int i = 0; i < gradientStops.Count; i++)
|
||||||
|
{
|
||||||
|
Tuple<double, Color> gradientStop = gradientStops[i];
|
||||||
|
double o = gradientStop.Item1;
|
||||||
|
if (o <= offset)
|
||||||
|
beforeStop = gradientStop;
|
||||||
|
|
||||||
|
if (o >= offset)
|
||||||
|
{
|
||||||
|
afterOffset = gradientStop.Item1;
|
||||||
|
afterColor = gradientStop.Item2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
double beforeOffset = beforeStop.Item1;
|
||||||
|
Color beforeColor = beforeStop.Item2;
|
||||||
|
|
||||||
|
double blendFactor = 0f;
|
||||||
|
if (beforeOffset != afterOffset)
|
||||||
|
blendFactor = ((offset - beforeOffset) / (afterOffset - beforeOffset));
|
||||||
|
|
||||||
|
colA = (byte)((afterColor.A - beforeColor.A) * blendFactor + beforeColor.A);
|
||||||
|
colR = (byte)((afterColor.R - beforeColor.R) * blendFactor + beforeColor.R);
|
||||||
|
colG = (byte)((afterColor.G - beforeColor.G) * blendFactor + beforeColor.G);
|
||||||
|
colB = (byte)((afterColor.B - beforeColor.B) * blendFactor + beforeColor.B);
|
||||||
|
}
|
||||||
|
|
||||||
|
private IList<Tuple<double, Color>> FixGradientStops(IList<Tuple<double, Color>> gradientStops)
|
||||||
|
{
|
||||||
|
if (gradientStops == null) return new List<Tuple<double, Color>>();
|
||||||
|
|
||||||
|
List<Tuple<double, Color>> stops = gradientStops.OrderBy(x => x.Item1).ToList();
|
||||||
|
|
||||||
|
Tuple<double, Color> firstStop = stops.First();
|
||||||
|
if (firstStop.Item1 > 0)
|
||||||
|
stops.Insert(0, new Tuple<double, Color>(0, firstStop.Item2));
|
||||||
|
|
||||||
|
Tuple<double, Color> lastStop = stops.Last();
|
||||||
|
if (lastStop.Item1 < 1)
|
||||||
|
stops.Add(new Tuple<double, Color>(1, lastStop.Item2));
|
||||||
|
|
||||||
|
return stops;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user