add BlendEffectBox

This commit is contained in:
NaBian committed 2020-02-24 19:16:31 +08:00
1 parent f6da5e1101
commit 6530a711ee
17 files changed
+195 -500

No files matched your search

@@ -68,8 +68,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Media\Animation\LinearGeometryKeyFrame.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Media\Animation\ResolvedKeyFrameEntry.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Media\Animation\SplineGeometryKeyFrame.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Media\Effects\BlendEffect.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Media\Effects\BlendEffectMode.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Media\Effects\BlendEffectBox.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Media\Effects\BrightnessEffect.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Media\Effects\ColorComplementEffect.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Media\Effects\ColorMatrixEffect.cs" />
@@ -404,6 +403,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="$(MSBuildThisFileDirectory)Themes\Styles\BlendEffectBox.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="$(MSBuildThisFileDirectory)Themes\Styles\Base\FrameBaseStyle.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
@@ -1,61 +0,0 @@
//reference doc : https://docs.microsoft.com/en-us/windows/win32/direct2d/blend#blending-examples
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Effects;
namespace HandyControl.Media.Effects
{
public class BlendEffect : ShaderEffect
{
private static readonly Dictionary<BlendEffectMode, PixelShader> ShaderDic;
public static readonly DependencyProperty BackgroundProperty = RegisterPixelShaderSamplerProperty("Background", typeof(BlendEffect), 0);
public static readonly DependencyProperty ForegroundProperty = RegisterPixelShaderSamplerProperty("Foreground", typeof(BlendEffect), 1);
static BlendEffect()
{
ShaderDic = new Dictionary<BlendEffectMode, PixelShader>();
}
public BlendEffect()
{
if (!ShaderDic.ContainsKey(Mode))
{
ShaderDic[Mode] = new PixelShader
{
UriSource = new Uri($"pack://application:,,,/HandyControl;component/Resources/Effects/{Mode.ToString()}BlendEffect.ps")
};
}
PixelShader = ShaderDic[Mode];
UpdateShaderValue(BackgroundProperty);
UpdateShaderValue(ForegroundProperty);
}
public Brush Background
{
get => (Brush)GetValue(BackgroundProperty);
set => SetValue(BackgroundProperty, value);
}
public Brush Foreground
{
get => (Brush)GetValue(ForegroundProperty);
set => SetValue(ForegroundProperty, value);
}
public static readonly DependencyProperty ModeProperty = DependencyProperty.Register(
"Mode", typeof(BlendEffectMode), typeof(BlendEffect), new PropertyMetadata(default(BlendEffectMode), PixelShaderConstantCallback(0)));
public BlendEffectMode Mode
{
get => (BlendEffectMode) GetValue(ModeProperty);
set => SetValue(ModeProperty, value);
}
}
}
@@ -0,0 +1,116 @@
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Markup;
using System.Windows.Media.Effects;
namespace HandyControl.Media.Effects
{
[DefaultProperty("Content")]
[ContentProperty("Content")]
public class BlendEffectBox : Control
{
private readonly ContentPresenter _effectBottomPresenter;
private readonly ContentPresenter _effectTopPresenter;
private bool _isInternalAction;
public BlendEffectBox()
{
_effectTopPresenter = new ContentPresenter();
ActualContent = _effectTopPresenter;
_effectBottomPresenter = new ContentPresenter();
_effectBottomPresenter.SetBinding(ContentPresenter.ContentProperty, new Binding(ContentProperty.Name)
{
Source = this
});
var effects = new ObservableCollection<Effect>();
effects.CollectionChanged += OnEffectsChanged;
Effects = effects;
}
private void OnEffectsChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (Effects == null || Effects.Count == 0)
{
ClearEffect(_effectTopPresenter);
return;
}
if (_isInternalAction) return;
_isInternalAction = true;
AddEffect(_effectTopPresenter, Effects.Count);
_isInternalAction = false;
}
private void ClearEffect(ContentPresenter presenter)
{
if (presenter == null) return;
if (ReferenceEquals(_effectBottomPresenter, presenter))
{
_effectBottomPresenter.SetCurrentValue(EffectProperty, null);
return;
}
presenter.SetCurrentValue(EffectProperty, null);
ClearEffect(presenter.Content as ContentPresenter);
}
private void AddEffect(ContentPresenter presenter, int count)
{
var newCount = --count;
if (newCount >= 0)
{
presenter.Effect = Effects[newCount];
var nextCount = --count;
if (nextCount >= 1)
{
var content = new ContentPresenter();
presenter.Content = content;
AddEffect(content, newCount);
}
else if (nextCount >= 0)
{
_effectBottomPresenter.Effect = Effects[0];
presenter.Content = _effectBottomPresenter;
}
else
{
presenter.Content = _effectBottomPresenter;
}
}
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
[Bindable(true)]
public Collection<Effect> Effects { get; }
public static readonly DependencyProperty ContentProperty = DependencyProperty.Register(
"Content", typeof(FrameworkElement), typeof(BlendEffectBox), new PropertyMetadata(default(FrameworkElement)));
public FrameworkElement Content
{
get => (FrameworkElement)GetValue(ContentProperty);
set => SetValue(ContentProperty, value);
}
internal static readonly DependencyProperty ActualContentProperty = DependencyProperty.Register(
"ActualContent", typeof(FrameworkElement), typeof(BlendEffectBox), new PropertyMetadata(default(FrameworkElement)));
internal FrameworkElement ActualContent
{
get => (FrameworkElement) GetValue(ActualContentProperty);
set => SetValue(ActualContentProperty, value);
}
}
}
@@ -1,32 +0,0 @@
namespace HandyControl.Media.Effects
{
public enum BlendEffectMode
{
Multiply,
Screen,
Darken,
Lighten,
Dissolve,
ColorBurn,
LinearBurn,
DarkerColor,
LighterColor,
ColorDodge,
LinearDodge,
Overlay,
SoftLight,
HardLight,
VividLight,
LinearLight,
PinLight,
HardMix,
Difference,
Exclusion,
Hue,
Saturation,
Color,
Luminosity,
Subtract,
Division
}
}
@@ -1,15 +0,0 @@
sampler2D background : register(s0);
sampler2D foreground : register(s1);
float4 main(float2 uv : TEXCOORD) : COLOR
{
float4 b = tex2D(background, uv);
float4 f = tex2D(foreground, uv);
float4 o = b;
f.rgb *= f.a;
b.rgb *= b.a;
o.rgb = f.rgb * b.rgb + f.rgb * (1 - b.a) + b.rgb * (1 - f.a);
return o;
}
@@ -0,0 +1,14 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:effects="clr-namespace:HandyControl.Media.Effects">
<Style TargetType="effects:BlendEffectBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="effects:BlendEffectBox">
<ContentPresenter ContentSource="ActualContent"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
@@ -84,6 +84,7 @@
<ResourceDictionary Source="FlowDocument.xaml"/>
<ResourceDictionary Source="NavigationWindow.xaml"/>
<ResourceDictionary Source="Frame.xaml"/>
<ResourceDictionary Source="BlendEffectBox.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>