/// <summary> /// Creates an instance of CompositionEffectFactory. /// </summary> /// <param name="compositor">Compositor</param> /// <param name="graphicsEffect">The type of effect to create.</param> /// <param name="animatablePropertyExpressions">List of Expression each specifying /// an animatable property</param> /// <returns>The created CompositionEffectFactory object.</returns> public static CompositionEffectFactory CreateEffectFactory(this Compositor compositor, IGraphicsEffect graphicsEffect, params Expression <Func <object> >[] animatablePropertyExpressions) { var animatableProperties = animatablePropertyExpressions.Select(CompositionExpressionEngine.ParseExpression).ToArray(); return(compositor.CreateEffectFactory(graphicsEffect, animatableProperties)); }
public void ReflectOverAllEffects() { var assembly = typeof(GaussianBlurEffect).GetTypeInfo().Assembly; var effectTypes = from type in assembly.DefinedTypes where type.ImplementedInterfaces.Contains(typeof(IGraphicsEffect)) where type.AsType() != typeof(PixelShaderEffect) select type; var device = new CanvasDevice(); var device2 = new CanvasDevice(); foreach (var effectType in effectTypes) { IGraphicsEffect effect = (IGraphicsEffect)Activator.CreateInstance(effectType.AsType()); // Test an un-realized effect instance. TestEffectSources(effectType, effect, null); TestEffectProperties(effectType, effect); // Realize the effect (creating a backing D2D effect instance), then test it again. var initialSourceImage = RealizeEffect(device, effectType, effect); TestEffectSources(effectType, effect, initialSourceImage); TestEffectProperties(effectType, effect); // Test that interop can successfully transfer property values in both directions. TestEffectInterop(device, device2, effectType, effect); } }
static void TestEffectInterop(CanvasDevice device, CanvasDevice device2, TypeInfo effectType, IGraphicsEffect realizedEffect) { // One Win2D effect is backed by a realized ID2D1Effect instance, the other is not. // Their property values should be the same either way. IGraphicsEffect unrealizedEffect = (IGraphicsEffect)Activator.CreateInstance(effectType.AsType()); PropertyValuesShouldMatch(effectType, realizedEffect, unrealizedEffect); // Create a new ID2D1Effect instance, then wrap a Win2D effect around it. // We should get the same default property values either way. IGraphicsEffect wrappedEffect = EffectAccessor.CreateThenWrapNewEffectOfSameType(device, realizedEffect); // Special case: Win2D intentionally defaults to a different DpiCompensationEffect.BorderMode vs. D2D. if (wrappedEffect is DpiCompensationEffect) { var dpiCompensationEffect = wrappedEffect as DpiCompensationEffect; Assert.AreEqual(EffectBorderMode.Soft, dpiCompensationEffect.BorderMode); dpiCompensationEffect.BorderMode = EffectBorderMode.Hard; } PropertyValuesShouldMatch(effectType, unrealizedEffect, wrappedEffect); // Re-realize the new effect onto a second device. // All property values should be successfully transferred across. RealizeEffect(device2, effectType, wrappedEffect); PropertyValuesShouldMatch(effectType, unrealizedEffect, wrappedEffect); }
private static void GetActiveEffects(IGraphicsEffectSource effectSource, List <Type> typesSeen) { // Record this node if it is an IGraphicsEffect. IGraphicsEffect effect = effectSource as IGraphicsEffect; if (effect != null) { typesSeen.Add(effect.GetType()); foreach (var property in effect.GetType().GetRuntimeProperties()) { if (property.PropertyType == typeof(IGraphicsEffectSource)) { // Recurse into any source properties that could themselves be effects. var source = (IGraphicsEffectSource)property.GetValue(effect); GetActiveEffects(source, typesSeen); } else if (property.PropertyType == typeof(IList <IGraphicsEffectSource>)) { // Recurse into any array source properties. var sources = (IList <IGraphicsEffectSource>)property.GetValue(effect); foreach (var source in sources) { GetActiveEffects(source, typesSeen); } } } } }
private async void ViewEffectGraph_Click(object sender, RoutedEventArgs e) { if (!_inDialog) { _inDialog = true; IGraphicsEffect effect = Material.Effect; if (effect != null) { StringBuilder sb = new StringBuilder(1024); EffectToString(sb, 0, effect, (CompositionEffectBrush)Material.Brush); ViewEffectDialog viewEffectDialog = new ViewEffectDialog() { Title = "View Effect Graph", PrimaryButtonText = "OK", HorizontalContentAlignment = HorizontalAlignment.Center, IsSecondaryButtonEnabled = false, }; viewEffectDialog.EffectText = sb.ToString(); await viewEffectDialog.ShowAsync(); } _inDialog = false; } }
public static async Task <AttachedAnimatableCompositionEffect <T> > AttachCompositionAnimatableInAppCustomAcrylicEffectAsync <TSource, T>( [NotNull] this TSource element, [NotNull] T target, float on, float off, bool initiallyVisible, Color color, float colorMix, [CanBeNull] CanvasControl canvas, [NotNull] Uri uri, int timeThreshold = 1000, bool reload = false, bool disposeOnUnload = false) where TSource : FrameworkElement where T : FrameworkElement { // Get the compositor Visual visual = await DispatcherHelper.GetFromUIThreadAsync(element.GetVisual); Compositor compositor = visual.Compositor; // Create the blur effect and the effect factory CompositionBackdropBrush backdropBrush = compositor.CreateBackdropBrush(); GaussianBlurEffect blurEffect = new GaussianBlurEffect { Name = "Blur", BlurAmount = 0f, BorderMode = EffectBorderMode.Hard, Optimization = EffectOptimization.Balanced, Source = new CompositionEffectSourceParameter(nameof(backdropBrush)) }; const String animationPropertyName = "Blur.BlurAmount"; // Prepare the dictionary with the parameters to add IDictionary <String, CompositionBrush> sourceParameters = new Dictionary <String, CompositionBrush> { { nameof(backdropBrush), backdropBrush } }; // Get the noise brush using Win2D IGraphicsEffect source = await AcrylicEffectHelper.ConcatenateEffectWithTintAndBorderAsync(compositor, blurEffect, sourceParameters, color, colorMix, canvas, uri, timeThreshold, reload); // Make sure the Win2D brush was loaded correctly CompositionEffectFactory effectFactory = compositor.CreateEffectFactory(source, new[] { animationPropertyName }); // Create the effect factory and apply the final effect CompositionEffectBrush effectBrush = effectFactory.CreateBrush(); foreach (KeyValuePair <String, CompositionBrush> pair in sourceParameters) { effectBrush.SetSourceParameter(pair.Key, pair.Value); } // Assign the effect to a brush and display it SpriteVisual sprite = compositor.CreateSpriteVisual(); sprite.Brush = effectBrush; await AddToTreeAndBindSizeAsync(target.GetVisual(), target, sprite); if (initiallyVisible) { await DispatcherHelper.RunOnUIThreadAsync(() => element.Opacity = 1); } return(new AttachedAnimatableCompositionEffect <T>(target, sprite, new CompositionAnimationParameters(animationPropertyName, on, off), disposeOnUnload)); }
static void TestEffectProperties(TypeInfo effectType, IGraphicsEffect effect) { var properties = (from property in effectType.DeclaredProperties where property.Name != "Name" where property.Name != "Sources" where property.PropertyType != typeof(IGraphicsEffectSource) select property).ToList(); IList <object> effectProperties = new ViewIndexerAsList <object>(() => EffectAccessor.GetPropertyCount(effect), i => EffectAccessor.GetProperty(effect, i)); FilterOutCustomizedEffectProperties(effectType.AsType(), ref properties, ref effectProperties); // Should have the same number of strongly typed properties as elements in the properties collection. Assert.AreEqual(properties.Count, effectProperties.Count); // Store the initial property values. var initialValues = effectProperties.ToList(); var whichIndexIsProperty = new List <int>(); // Changing strongly typed properties should change the properties collection. for (int i = 0; i < effectProperties.Count; i++) { object testValue1 = GetArbitraryTestValue(properties[i].PropertyType, true); object testValue2 = GetArbitraryTestValue(properties[i].PropertyType, false); // Change a property value, and see which collection properties match the result. properties[i].SetValue(effect, testValue1); var matches1 = (from j in Enumerable.Range(0, effectProperties.Count) where BoxedValuesAreEqual(effectProperties[j], Box(testValue1, properties[i]), properties[i]) select j).ToList(); // Change the same property to a different value, and see which collection properties match now. properties[i].SetValue(effect, testValue2); var matches2 = (from j in Enumerable.Range(0, effectProperties.Count) where BoxedValuesAreEqual(effectProperties[j], Box(testValue2, properties[i]), properties[i]) select j).ToList(); // There should be one and only one property that matched both times. If not, // either we don't have 1 <-> 1 mapping between strongly typed properties and // collection indices, or something went wrong during the boxing type conversions. var intersection = matches1.Intersect(matches2); Assert.AreEqual(1, intersection.Count()); int whichIndexIsThis = intersection.Single(); whichIndexIsProperty.Add(whichIndexIsThis); // Change the property value back to its initial state. properties[i].SetValue(effect, Unbox(initialValues[whichIndexIsThis], properties[i])); Assert.IsTrue(BoxedValuesAreEqual(initialValues[whichIndexIsThis], effectProperties[whichIndexIsThis], properties[i])); } // Should not have any duplicate property mappings. Assert.AreEqual(whichIndexIsProperty.Count, whichIndexIsProperty.Distinct().Count()); }
public Form1() : base() { InitializeComponent(); // Get graphics device. canvasDevice = CanvasDevice.GetSharedDevice(); // Create effect graph. acrylicEffect = CreateAcrylicEffectGraph(); }
static void PropertyValuesShouldMatch(TypeInfo effectType, IGraphicsEffect effect1, IGraphicsEffect effect2) { foreach (var property in GetEffectProperties(effectType)) { object value1 = property.GetValue(effect1); object value2 = property.GetValue(effect2); AssertPropertyValuesAreEqual(value1, value2); } }
public void LinkLayerEffects(Layer nextLayer) { IGraphicsEffect source = _inputEffect; _chainedEffect = null; // Link the effect chain foreach (var effect in Effects) { if (effect.Enabled) { effect.GraphicsEffect.GetType().GetProperties().FirstOrDefault(x => x.Name == "Source").SetValue(effect.GraphicsEffect, source); source = effect.GraphicsEffect; _chainedEffect = effect.GraphicsEffect; } } if (nextLayer != null) { IGraphicsEffect layerEffect = EffectRoot; IGraphicsEffect blendEffect; blendEffect = Helpers.GetEffectFromBlendMode(_blendMode); if (blendEffect is BlendEffect) { BlendEffect blend = (BlendEffect)blendEffect; blend.Foreground = nextLayer.GenerateEffectGraph(false); blend.Background = layerEffect; _blendEffect = blend; } else if (blendEffect is CompositeEffect) { CompositeEffect composite = (CompositeEffect)blendEffect; composite.Sources.Add(nextLayer.GenerateEffectGraph(false)); composite.Sources.Add(layerEffect); _blendEffect = composite; } else if (blendEffect is ArithmeticCompositeEffect) { ArithmeticCompositeEffect arith = (ArithmeticCompositeEffect)blendEffect; arith.Source1 = layerEffect; arith.Source2 = nextLayer.GenerateEffectGraph(false); _blendEffect = arith; } else { Debug.Assert(false); } } else { _blendEffect = null; } }
static void TestEffectSources(TypeInfo effectType, IGraphicsEffect effect) { var sourceProperties = (from property in effectType.DeclaredProperties where property.PropertyType == typeof(IGraphicsEffectSource) select property).ToList(); // Should have the same number of strongly typed properties as the effect has sources. Assert.AreEqual(sourceProperties.Count, EffectAccessor.GetSourceCount(effect)); // Initial source values should all be null. for (int i = 0; i < EffectAccessor.GetSourceCount(effect); i++) { Assert.IsNull(EffectAccessor.GetSource(effect, i)); Assert.IsNull(sourceProperties[i].GetValue(effect)); } var testValue1 = new GaussianBlurEffect(); var testValue2 = new ShadowEffect(); var whichIndexIsProperty = new List <int>(); // Changing strongly typed properties should change the sources reported by IGraphicsEffectD2D1Interop. for (int i = 0; i < EffectAccessor.GetSourceCount(effect); i++) { // Change a property value, and see which source changes. sourceProperties[i].SetValue(effect, testValue1); int whichIndexIsThis = 0; while (EffectAccessor.GetSource(effect, whichIndexIsThis) != testValue1) { whichIndexIsThis++; Assert.IsTrue(whichIndexIsThis < EffectAccessor.GetSourceCount(effect)); } whichIndexIsProperty.Add(whichIndexIsThis); // Change the same property value again, and make sure the same source changes. sourceProperties[i].SetValue(effect, testValue2); Assert.AreSame(testValue2, EffectAccessor.GetSource(effect, whichIndexIsThis)); // Change the property value to null. sourceProperties[i].SetValue(effect, null); Assert.IsNull(EffectAccessor.GetSource(effect, whichIndexIsThis)); } // Should not have any duplicate property mappings. Assert.AreEqual(whichIndexIsProperty.Count, whichIndexIsProperty.Distinct().Count()); }
public void ReflectOverAllEffects() { var assembly = typeof(GaussianBlurEffect).GetTypeInfo().Assembly; var effectTypes = from type in assembly.DefinedTypes where type.ImplementedInterfaces.Contains(typeof(IGraphicsEffect)) select type; foreach (var effectType in effectTypes) { IGraphicsEffect effect = (IGraphicsEffect)Activator.CreateInstance(effectType.AsType()); TestEffectSources(effectType, effect); TestEffectProperties(effectType, effect); } }
private void OnLayerChanged(object sender, string property) { try { IGraphicsEffect effectGraph = Layer.GenerateEffectGraph(true); CompositionEffectFactory effectFactory = _previewSprite.Compositor.CreateEffectFactory(effectGraph, null); _previewSprite.Brush = effectFactory.CreateBrush(); Layer.UpdateResourceBindings((CompositionEffectBrush)_previewSprite.Brush); } catch { _previewSprite.Brush = null; } LayerDescription.Text = Layer.Description; }
private async void UpdateBrush() { if (_layerInvalidated) { // Clear the old brush _effectBrush = null; IGraphicsEffect effecGraph = _groupLayer.GenerateEffectGraph(false); if (effecGraph != null) { try { CompositionEffectFactory effectFactory = _compositor.CreateEffectFactory(effecGraph, null); _effectBrush = effectFactory.CreateBrush(); foreach (Layer layer in _groupLayer.Layers) { if (layer.Enabled) { layer.UpdateResourceBindings(_effectBrush); } } } catch (Exception e) { ContentDialog dialog = new ContentDialog() { Title = "Failed to create effect", Content = String.Format("The effect creation failed with the following error. Please simplify your material.\r\n\r\n\"{0}\"", e.Message.ToString().Replace("\r\n", " ")), PrimaryButtonText = "OK", IsSecondaryButtonEnabled = false, }; await dialog.ShowAsync(); // Clear out the old effect _effectBrush = null; } // Clear the flag _layerInvalidated = false; } _brushChangedHandler(this); } }
public CompositionHostControl() { InitializeComponent(); // 手动高亮,下面代码用于创建 Win2d 的渲染设备 _canvasDevice = CanvasDevice.GetSharedDevice(); // Create host and attach root container for hosted tree. _compositionHost = new CompositionHost(); CompositionHostElement.Child = _compositionHost; _compositionHost.RegisterForDispose(this); _compositor = _compositionHost.Compositor; _containerVisual = _compositor.CreateContainerVisual(); // Create effect graph. _acrylicEffect = CreateAcrylicEffectGraph(); }
public CompositionEffectBrush CreateEffectBrush( EffectType effectType, string effectName, float propertyValue, IEnumerable <string> properties) { IGraphicsEffect effectDesc = null; switch (effectType) { case EffectType.Saturation: effectDesc = new SaturationEffect() { Name = effectName, Saturation = propertyValue, Source = new CompositionEffectSourceParameter("source") }; break; case EffectType.HueRotation: effectDesc = new HueRotationEffect() { Name = effectName, Angle = propertyValue, Source = new CompositionEffectSourceParameter("source") }; break; case EffectType.Sepia: effectDesc = new SepiaEffect() { Name = effectName, Intensity = propertyValue, Source = new CompositionEffectSourceParameter("source") }; break; } CompositionEffectFactory effectFactory = _compositor.CreateEffectFactory(effectDesc, properties); CompositionEffectBrush effectBrush = effectFactory.CreateBrush(); return(effectBrush); }
protected T StartEffectAnimation <T>( FrameworkElement element, IGraphicsEffect effect, Func <double, T> animationSetupFunc, Action <CompositionEffectBrush> brushSetupAction) where T : KeyFrameAnimation { var duration = Initialize(element); // Call a Func that will be used to setup the animation and create the keyframes, delay, etc. var animation = animationSetupFunc(duration); var effectFactory = Window.Current.Compositor.CreateEffectFactory(effect, new[] { TargetProperty }); var brush = effectFactory.CreateBrush(); // Call an Action that will be used to setup the CompositionEffectBrush object brushSetupAction(brush); brush.StartAnimation(TargetProperty, animation); return(animation); }
static ICanvasImage RealizeEffect(CanvasDevice device, TypeInfo effectType, IGraphicsEffect effect) { var dummySourceImage = new CanvasCommandList(device); // We can't realize an effect with invalid inputs, so must first set them all to something reasonable. foreach (var sourceProperty in effectType.DeclaredProperties.Where(p => p.PropertyType == typeof(IGraphicsEffectSource))) { sourceProperty.SetValue(effect, dummySourceImage); } // Add one image to any variable size Sources collection properties. foreach (var sourcesProperty in effectType.DeclaredProperties.Where(p => p.Name == "Sources")) { var sources = sourcesProperty.GetValue(effect) as IList <IGraphicsEffectSource>; sources.Clear(); sources.Add(dummySourceImage); } EffectAccessor.RealizeEffect(device, effect); return(dummySourceImage); }
private void InitializeBrush(IGraphicsEffect effect, String uri) { Brush = Compositor.CreateEffectFactory(effect, new[] { "effect.Source1Amount", "effect.Source2Amount", } ).CreateBrush(); SetForeground(uri); }
public static async Task <AttachedStaticCompositionEffect <T> > AttachCompositionCustomAcrylicEffectAsync <T>( [NotNull] this T element, Color color, float colorMix, [CanBeNull] CanvasControl canvas, [NotNull] Uri uri, int timeThreshold = 1000, bool reload = false, bool disposeOnUnload = false) where T : FrameworkElement { // Percentage check if (colorMix <= 0 || colorMix >= 1) { throw new ArgumentOutOfRangeException("The mix factors must be in the [0,1] range"); } if (timeThreshold <= 0) { throw new ArgumentOutOfRangeException("The time threshold must be a positive number"); } // Setup the compositor Visual visual = ElementCompositionPreview.GetElementVisual(element); Compositor compositor = visual.Compositor; // Prepare a luminosity to alpha effect to adjust the background contrast CompositionBackdropBrush hostBackdropBrush = compositor.CreateHostBackdropBrush(); CompositionEffectSourceParameter backgroundParameter = new CompositionEffectSourceParameter(nameof(hostBackdropBrush)); LuminanceToAlphaEffect alphaEffect = new LuminanceToAlphaEffect { Source = backgroundParameter }; OpacityEffect opacityEffect = new OpacityEffect { Source = alphaEffect, Opacity = 0.4f // Reduce the amount of the effect to avoid making bright areas completely black }; // Layer [0,1,3] - Desktop background with blur and tint overlay BlendEffect alphaBlend = new BlendEffect { Background = backgroundParameter, Foreground = opacityEffect, Mode = BlendEffectMode.Overlay }; IDictionary <String, CompositionBrush> sourceParameters = new Dictionary <String, CompositionBrush> { { nameof(hostBackdropBrush), hostBackdropBrush } }; // Get the noise brush using Win2D IGraphicsEffect source = await AcrylicEffectHelper.ConcatenateEffectWithTintAndBorderAsync(compositor, alphaBlend, sourceParameters, color, colorMix, canvas, uri, timeThreshold, reload); // Make sure the Win2D brush was loaded correctly CompositionEffectFactory factory = compositor.CreateEffectFactory(source); // Create the effect factory and apply the final effect CompositionEffectBrush effectBrush = factory.CreateBrush(); foreach (KeyValuePair <String, CompositionBrush> pair in sourceParameters) { effectBrush.SetSourceParameter(pair.Key, pair.Value); } // Create the sprite to display and add it to the visual tree SpriteVisual sprite = compositor.CreateSpriteVisual(); sprite.Brush = effectBrush; await AddToTreeAndBindSizeAsync(visual, element, sprite); return(new AttachedStaticCompositionEffect <T>(element, sprite, disposeOnUnload)); }
public static async Task <AttachedStaticCompositionEffect <T> > AttachCompositionInAppCustomAcrylicEffectAsync <TSource, T>( [NotNull] this TSource element, [NotNull] T target, float blur, int ms, Color color, float colorMix, float?saturation, [CanBeNull] CanvasControl canvas, [NotNull] Uri uri, int timeThreshold = 1000, bool reload = false, bool fadeIn = false, bool disposeOnUnload = false) where TSource : FrameworkElement where T : FrameworkElement { // Percentage check if (saturation < 0 || saturation > 1) { throw new ArgumentOutOfRangeException("The input saturation value must be in the [0,1] range"); } if (colorMix <= 0 || colorMix >= 1) { throw new ArgumentOutOfRangeException("The mix factors must be in the [0,1] range"); } if (timeThreshold <= 0) { throw new ArgumentOutOfRangeException("The time threshold must be a positive number"); } // Setup the compositor Visual visual = ElementCompositionPreview.GetElementVisual(element); Compositor compositor = visual.Compositor; // Prepare a luminosity to alpha effect to adjust the background contrast CompositionBackdropBrush backdropBrush = compositor.CreateBackdropBrush(); const String blurName = "Blur", blurParameterName = "Blur.BlurAmount"; GaussianBlurEffect blurEffect = new GaussianBlurEffect { Name = blurName, BlurAmount = 0f, BorderMode = EffectBorderMode.Hard, Optimization = EffectOptimization.Balanced, Source = new CompositionEffectSourceParameter(nameof(backdropBrush)) }; // Background with blur and tint overlay IDictionary <String, CompositionBrush> sourceParameters = new Dictionary <String, CompositionBrush> { { nameof(backdropBrush), backdropBrush } }; // Get the noise brush using Win2D IGraphicsEffect source = await AcrylicEffectHelper.ConcatenateEffectWithTintAndBorderAsync(compositor, blurEffect, sourceParameters, color, colorMix, canvas, uri, timeThreshold, reload); // Add the final saturation effect if needed if (saturation != null) { SaturationEffect saturationEffect = new SaturationEffect { Saturation = saturation.Value, Source = source }; source = saturationEffect; } // Make sure the Win2D brush was loaded correctly CompositionEffectFactory factory = compositor.CreateEffectFactory(source, new[] { blurParameterName }); // Create the effect factory and apply the final effect CompositionEffectBrush effectBrush = factory.CreateBrush(); foreach (KeyValuePair <String, CompositionBrush> pair in sourceParameters) { effectBrush.SetSourceParameter(pair.Key, pair.Value); } // Create the sprite to display and add it to the visual tree SpriteVisual sprite = compositor.CreateSpriteVisual(); sprite.Brush = effectBrush; // Assign the visual if (fadeIn) { sprite.StopAnimation("Opacity"); sprite.Opacity = 0; } await AddToTreeAndBindSizeAsync(target.GetVisual(), target, sprite); if (fadeIn) { // Fade the effect in ScalarKeyFrameAnimation opacityAnimation = sprite.Compositor.CreateScalarKeyFrameAnimation(1, 0, TimeSpan.FromMilliseconds(ms), null, sprite.GetEasingFunction(EasingFunctionNames.Linear)); sprite.StartAnimation("Opacity", opacityAnimation); } // Animate the blur and return the result effectBrush.StartAnimationAsync(blurParameterName, blur, TimeSpan.FromMilliseconds(ms)).Forget(); return(new AttachedStaticCompositionEffect <T>(target, sprite, disposeOnUnload)); }
public SaturationEffect(IGraphicsEffect source) : base(source) { }
private void MainPage_Loaded(object sender, RoutedEventArgs e) { // Initialize Composition UI infrastructure. _leftRoot = LeftContainer.GetVisual(); _middleRoot = MiddleContainer.GetVisual(); _rightRoot = RightContainer.GetVisual(); _compositor = _leftRoot.Compositor; _imageFactory = CompositionImageFactory.CreateCompositionImageFactory(_compositor); // Hook the sprite visuals into the XAML visual tree. _leftSpriteVisual = _compositor.CreateSpriteVisual(); var side = (float)Math.Min(LeftPresenter.ActualWidth, LeftPresenter.ActualHeight); _leftSpriteVisual.Size = new Vector2(side, side); _leftRoot.Children.InsertAtTop(_leftSpriteVisual); _middleSpriteVisual = _compositor.CreateSpriteVisual(); side = (float)Math.Min(MiddlePresenter.ActualWidth, MiddlePresenter.ActualHeight); _middleSpriteVisual.Size = new Vector2(side, side); _middleRoot.Children.InsertAtTop(_middleSpriteVisual); _rightSpriteVisual = _compositor.CreateSpriteVisual(); side = (float)Math.Min(RightPresenter.ActualWidth, RightPresenter.ActualHeight); _rightSpriteVisual.Size = new Vector2(side, side); _rightRoot.Children.InsertAtTop(_rightSpriteVisual); // Create CompositionSurfaceBrush _imageBrush = _compositor.CreateSurfaceBrush(); // Create an image source to load var imageSource = _imageFactory.CreateImageFromUri(new Uri("ms-appx:///Assets/flowers.jpg")); _imageBrush.Surface = imageSource.Surface; // Create and apply the first effect. _firstEffect = new SaturationEffect { Name = "firstEffect", Source = new CompositionEffectSourceParameter("source") }; var firstEffectFactory = _compositor.CreateEffectFactory(_firstEffect, new[] { "firstEffect.Saturation" }); _effectBrush1 = firstEffectFactory.CreateBrush(); _leftSpriteVisual.Brush = _effectBrush1; // Create and apply the second effect. var secondEffect = new InvertEffect { Name = "secondEffect", Source = new CompositionEffectSourceParameter("source") }; var secondEffectFactory = _compositor.CreateEffectFactory(secondEffect); _effectBrush2 = secondEffectFactory.CreateBrush(); _middleSpriteVisual.Brush = _effectBrush2; // Create and apply the combined effect. _combinedEffect = new InvertEffect { Name = "chained", Source = _firstEffect }; var combinedEffectFactory = _compositor.CreateEffectFactory(_combinedEffect, new[] { "firstEffect.Saturation" }); _combinedBrush = combinedEffectFactory.CreateBrush(); _rightSpriteVisual.Brush = _combinedBrush; // Chain the brushes _effectBrush1.SetSourceParameter("source", _imageBrush); _effectBrush2.SetSourceParameter("source", _imageBrush); _combinedBrush.SetSourceParameter("source", _imageBrush); }
static void TestEffectProperties(TypeInfo effectType, IGraphicsEffect effect) { var properties = GetEffectProperties(effectType).ToList(); IList <object> effectProperties = new ViewIndexerAsList <object>(() => EffectAccessor.GetPropertyCount(effect), i => EffectAccessor.GetProperty(effect, i)); FilterOutCustomizedEffectProperties(effectType.AsType(), ref properties, ref effectProperties); // Should have the same number of strongly typed properties as elements in the properties collection. Assert.AreEqual(properties.Count, effectProperties.Count); // Store the initial property values. var initialValues = effectProperties.ToList(); var whichIndexIsProperty = new List <int>(); // Changing strongly typed properties should change the properties collection. for (int i = 0; i < effectProperties.Count; i++) { object testValue1 = GetArbitraryTestValue(properties[i].PropertyType, true); object testValue2 = GetArbitraryTestValue(properties[i].PropertyType, false); // Change a property value, and see which collection properties match the result. properties[i].SetValue(effect, testValue1); AssertPropertyValuesAreEqual(testValue1, properties[i].GetValue(effect)); var matches1 = (from j in Enumerable.Range(0, effectProperties.Count) where BoxedValuesAreEqual(effectProperties[j], Box(testValue1, properties[i]), properties[i]) select j).ToList(); // Change the same property to a different value, and see which collection properties match now. properties[i].SetValue(effect, testValue2); AssertPropertyValuesAreEqual(testValue2, properties[i].GetValue(effect)); var matches2 = (from j in Enumerable.Range(0, effectProperties.Count) where BoxedValuesAreEqual(effectProperties[j], Box(testValue2, properties[i]), properties[i]) select j).ToList(); // There should be one and only one property that matched both times. If not, // either we don't have 1 <-> 1 mapping between strongly typed properties and // collection indices, or something went wrong during the boxing type conversions. var intersection = matches1.Intersect(matches2); Assert.AreEqual(1, intersection.Count()); int whichIndexIsThis = intersection.Single(); whichIndexIsProperty.Add(whichIndexIsThis); // Change the property value back to its initial state. var unboxedValue = Unbox(initialValues[whichIndexIsThis], properties[i]); properties[i].SetValue(effect, unboxedValue); AssertPropertyValuesAreEqual(unboxedValue, properties[i].GetValue(effect)); Assert.IsTrue(BoxedValuesAreEqual(initialValues[whichIndexIsThis], effectProperties[whichIndexIsThis], properties[i])); // Validate that IGraphicsEffectD2D1Interop agrees with what we think the type and index of this property is. int mappingIndex; EffectPropertyMapping mapping; EffectAccessor.GetNamedPropertyMapping(effect, properties[i].Name, out mappingIndex, out mapping); int expectedMappingIndex = whichIndexIsThis; if (effectProperties is FilteredViewOfList <object> ) { expectedMappingIndex = ((FilteredViewOfList <object>)effectProperties).GetOriginalIndex(expectedMappingIndex); } Assert.AreEqual(expectedMappingIndex, mappingIndex); var expectedMapping = GetExpectedPropertyMapping(properties[i], effectProperties[whichIndexIsThis]); Assert.AreEqual(expectedMapping, mapping); } // Should not have any duplicate property mappings. Assert.AreEqual(whichIndexIsProperty.Count, whichIndexIsProperty.Distinct().Count()); }
private async void UpdateEffect() { if (_compositor != null) { ComboBoxItem item = EffectSelection.SelectedValue as ComboBoxItem; IGraphicsEffect graphicsEffect = null; CompositionBrush secondaryBrush = null; string[] animatableProperties = null; // // Create the appropriate effect graph and resources // switch ((EffectTypes)item.Tag) { case EffectTypes.Desaturation: { graphicsEffect = new SaturationEffect() { Saturation = 0.0f, Source = new CompositionEffectSourceParameter("ImageSource") }; } break; case EffectTypes.Hue: { graphicsEffect = new HueRotationEffect() { Name = "Hue", Angle = 3.14f, Source = new CompositionEffectSourceParameter("ImageSource") }; animatableProperties = new[] { "Hue.Angle" }; } break; case EffectTypes.VividLight: { graphicsEffect = new BlendEffect() { Mode = BlendEffectMode.VividLight, Foreground = new ColorSourceEffect() { Name = "Base", Color = Color.FromArgb(255, 80, 40, 40) }, Background = new CompositionEffectSourceParameter("ImageSource"), }; animatableProperties = new[] { "Base.Color" }; } break; case EffectTypes.Mask: { graphicsEffect = new CompositeEffect() { Mode = CanvasComposite.DestinationOver, Sources = { new CompositeEffect() { Mode = CanvasComposite.DestinationIn, Sources = { new CompositionEffectSourceParameter("ImageSource"), new CompositionEffectSourceParameter("SecondSource") } }, new ColorSourceEffect() { Color = Color.FromArgb(200, 255, 255, 255) }, } }; CompositionDrawingSurface backgroundSurface = await SurfaceLoader.LoadFromUri(new Uri("ms-appx:///Samples/SDK 14393/ForegroundFocusEffects/mask.png")); CompositionSurfaceBrush maskBrush = _compositor.CreateSurfaceBrush(backgroundSurface); maskBrush.Stretch = CompositionStretch.UniformToFill; maskBrush.CenterPoint = _destinationSprite.Size * .5f; secondaryBrush = maskBrush; } break; case EffectTypes.Blur: { graphicsEffect = new GaussianBlurEffect() { BlurAmount = 20, Source = new CompositionEffectSourceParameter("ImageSource"), Optimization = EffectOptimization.Balanced, BorderMode = EffectBorderMode.Hard, }; } break; case EffectTypes.LightenBlur: { graphicsEffect = new ArithmeticCompositeEffect() { Source1Amount = .4f, Source2Amount = .6f, MultiplyAmount = 0, Source1 = new ColorSourceEffect() { Name = "Base", Color = Color.FromArgb(255, 255, 255, 255), }, Source2 = new GaussianBlurEffect() { BlurAmount = 20, Source = new CompositionEffectSourceParameter("ImageSource"), Optimization = EffectOptimization.Balanced, BorderMode = EffectBorderMode.Hard, } }; } break; case EffectTypes.DarkenBlur: { graphicsEffect = new ArithmeticCompositeEffect() { Source1Amount = .4f, Source2Amount = .6f, MultiplyAmount = 0, Source1 = new ColorSourceEffect() { Name = "Base", Color = Color.FromArgb(255, 0, 0, 0), }, Source2 = new GaussianBlurEffect() { BlurAmount = 20, Source = new CompositionEffectSourceParameter("ImageSource"), Optimization = EffectOptimization.Balanced, BorderMode = EffectBorderMode.Hard, } }; } break; case EffectTypes.RainbowBlur: { graphicsEffect = new ArithmeticCompositeEffect() { Source1Amount = .3f, Source2Amount = .7f, MultiplyAmount = 0, Source1 = new ColorSourceEffect() { Name = "Base", Color = Color.FromArgb(255, 0, 0, 0), }, Source2 = new GaussianBlurEffect() { BlurAmount = 20, Source = new CompositionEffectSourceParameter("ImageSource"), Optimization = EffectOptimization.Balanced, BorderMode = EffectBorderMode.Hard, } }; animatableProperties = new[] { "Base.Color" }; } break; default: break; } // Create the effect factory and instantiate a brush CompositionEffectFactory _effectFactory = _compositor.CreateEffectFactory(graphicsEffect, animatableProperties); CompositionEffectBrush brush = _effectFactory.CreateBrush(); // Set the destination brush as the source of the image content brush.SetSourceParameter("ImageSource", _compositor.CreateBackdropBrush()); // If his effect uses a secondary brush, set it now if (secondaryBrush != null) { brush.SetSourceParameter("SecondSource", secondaryBrush); } // Update the destination layer with the fully configured brush _destinationSprite.Brush = brush; } }
private void EffectToString(StringBuilder sb, int indent, IGraphicsEffect effect, CompositionEffectBrush brush) { const int indentIncrement = 4; Type type = effect.GetType(); sb.AppendFormat("{0}{1}\r\n{0}{{\r\n", Indent(indent), type.Name); Dictionary <string, object> expandedProperties = new Dictionary <string, object>(); indent += indentIncrement; foreach (PropertyInfo info in effect.GetType().GetProperties()) { string propertyName = info.Name.ToLower(); if (propertyName == "cacheoutput" || propertyName == "bufferprecision" || propertyName == "colorhdr" || propertyName == "issupported" || propertyName == "clampoutput" || propertyName == "name" || propertyName == "alphamode") { continue; } object obj = info.GetValue(effect); if (obj != null) { if (obj is IGraphicsEffect || obj is IList <IGraphicsEffectSource> ) { expandedProperties.Add(info.Name, obj); } else { if (obj is CompositionEffectSourceParameter) { CompositionEffectSourceParameter param = (CompositionEffectSourceParameter)obj; CompositionBrush sourceBrush = brush.GetSourceParameter(param.Name); string s = String.Format("{0}{1} :\r\n{0}{{\r\n", Indent(indent), info.Name); sb.Append(s); BrushToString(sb, indent + indentIncrement, sourceBrush); sb.AppendFormat("{0}}}\r\n", Indent(indent)); } else { sb.AppendFormat("{0}{1} : {2}\r\n", Indent(indent), info.Name, Helpers.ToString(obj)); } } } } // Moved all of the nested source properties to the end of the list foreach (KeyValuePair <string, object> entry in expandedProperties) { string name = entry.Key; object obj = entry.Value; if (obj is IGraphicsEffect) { string s = String.Format("{0}{1} :\r\n{0}{{\r\n", Indent(indent), name); sb.Append(s); EffectToString(sb, indent + indentIncrement, (IGraphicsEffect)obj, brush); sb.AppendFormat("{0}}}\r\n", Indent(indent)); } else if (obj is IList <IGraphicsEffectSource> ) { IList <IGraphicsEffectSource> list = (IList <IGraphicsEffectSource>)obj; sb.AppendFormat("{0}{1} :\r\n{0}[\r\n", Indent(indent), name); foreach (IGraphicsEffectSource source in list) { EffectToString(sb, indent + indentIncrement, (IGraphicsEffect)source, brush); } sb.AppendFormat("{0}]\r\n", Indent(indent)); } } indent -= indentIncrement; sb.AppendFormat("{0}}}\r\n", Indent(indent)); }