实现ShaderEffect.IsEnabled

时间:2014-08-06 15:05:48

标签: c# wpf

我正在尝试创建ShaderEffect(非常成功),但是,我有一个问题是为他们正确实施IsEnabled

我希望让IsEnabled动态启用/关闭效果,而不是更改元素的Effect属性。主要是因为我在动画中绑定有问题(可以解释,如果有人坚持,IsEnabled 错误方式)和可用性(绑定到IsEnabled比设置更容易Effect)。

这是效果

public class SomeEffect : ShaderEffect
{
    public Brush Input
    {
        get { return (Brush)GetValue(InputProperty); }
        set { SetValue(InputProperty, value); }
    }
    public static readonly DependencyProperty InputProperty =
        ShaderEffect.RegisterPixelShaderSamplerProperty("Input", typeof(SomeEffect), 0);

    public bool IsEnabled
    {
        get { return (bool)GetValue(IsEnabledProperty); }
        set { SetValue(IsEnabledProperty, value); }
    }
    public static readonly DependencyProperty IsEnabledProperty =
        DependencyProperty.Register("IsEnabled", typeof(bool), typeof(SomeEffect), new PropertyMetadata(true, OnIsEnabledPropertyChanged));
    private static void OnIsEnabledPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (e.NewValue != e.OldValue)
            (d as SomeEffect).SetValue(IsEnabledPrivateProperty, (bool)e.NewValue ? 1.0 : 0.0);
    }
    private static readonly DependencyProperty IsEnabledPrivateProperty =
        DependencyProperty.Register("IsEnabledPrivate", typeof(double), typeof(SomeEffect), new PropertyMetadata(1.0, OnIsEnabledPrivatePropertyChanged));
    private static void OnIsEnabledPrivatePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (e.NewValue != e.OldValue)
            (d as SomeEffect).SetValue(IsEnabledProperty, (double)e.NewValue != 0);
        PixelShaderConstantCallback(0)(d, e);
    }

    private static PixelShader _shader = new PixelShader() { UriSource = new Uri("...", UriKind.Relative) };

    public SomeEffect()
    {
        PixelShader = _shader;
        UpdateShaderValue(IsEnabledPrivateProperty);
    }
}

这是着色器

sampler2D _input : register(s0);
float _enabled : register(C0);

float4 main(float2 uv : TEXCOORD) : COLOR
{
    float4 color = tex2D(_input, uv);
    if(_enabled == 0)
        return color;

    ...
    return somethingelse;
}

它做得非常愚蠢,总是调用着色器,但如果设置了IsEnabled则不会做任何事情(返回原始颜色)。

bool属性有一个棘手的解决方法,着色器只能有double,所以我实现了另一个依赖属性,然后由ShaderEffect的服务函数使用(即, PixelShaderConstantCallbackUpdateShaderValue)。我可以使用转换器并具有double属性,但最好让bool IsEnabled直接在xaml中使用。

我尝试了什么:

  • 我尝试将PixelShader属性设置为null,这会导致服务功能失败,因为它们会将其初始化为null。如果设置了某些绑定到效果的静态回调属性,而PixelShader == null则会出现异常
  

PresentationCore.dll中出现未处理的“System.InvalidOperationException”类型异常   附加信息:必须在ShaderEffect上设置PixelShader。

  • 我是用上面解释的那种愚蠢的方式做到的。我对着色器知之甚少,但很明显,这种做法是错误的。但它确实有效。

  • 我可以想到可以创建一个自定义控件,它将包含两个内容容器:有效(永远打开)和不带。更改此控件的IsEnabled内容从一个容器移动到另一个容器。但即使没有开始,这看起来相当愚蠢和有限,虽然比以前的解决方案更优化(因为着色器不会被称为零大小或不可见的元素,我认为)。

那么,正确IsEnabled实施ShaderEffect的方式是什么?

0 个答案:

没有答案