views:

749

answers:

3

I have two brushes. I don't know wath type of brushes they are. They can be ImageBrushes, SolidBrushes or VisualBrushes. I have each in a variable of the "Brush" type.

I need to combine two brushes. How do I do it?

I tried this. But It didn't work. Here are Back and Front the brushes that need to me combined.

        Border Bd = new Border();
        Border Bdr = new Border();

        Bd.Width = 1.0;
        Bd.Height = 1.0;

        Bd.Background = Back;
        Bdr.Background = Front;

        Bd.Child = Bdr;

        Brush VB = new VisualBrush(Bd);

I need this because I am making a custom animation class to animate brushes. After making some test's I concluded that the error is in the combining of the brushes and not elsewhere in the class.

The resulting brush is completely transparent.

[EDIT]=========================================================================[EDIT]

Here is the complete BrushAnimation Class.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Media.Animation;
using System.Windows;
using System.Windows.Media;
using System.Windows.Controls;

namespace WPFSoPaTest
{
    class BrushAnimation : AnimationTimeline
    {
                protected override Freezable CreateInstanceCore()
        {
            return new BrushAnimation();
        }
        public override Type TargetPropertyType
        {
            get { return typeof(Brush); }
        }
        static BrushAnimation()
        {
            FromProperty = DependencyProperty.Register("From", typeof(Brush),
                typeof(BrushAnimation));

            ToProperty = DependencyProperty.Register("To", typeof(Brush),
                typeof(BrushAnimation));
        }
        public static readonly DependencyProperty FromProperty;
        public Brush From
        {
            get
            {
                return (Brush)GetValue(BrushAnimation.FromProperty);
            }
            set
            {
                SetValue(BrushAnimation.FromProperty, value);
            }
        }
        public static readonly DependencyProperty ToProperty;
        public Brush To
        {
            get
            {
                return (Brush)GetValue(BrushAnimation.ToProperty);
            }
            set
            {
                SetValue(BrushAnimation.ToProperty, value);
            }
        }
        public override object GetCurrentValue(object defaultOriginValue,
        object defaultDestinationValue, AnimationClock animationClock)
        {
            Brush fromVal = ((Brush)GetValue(BrushAnimation.FromProperty)).CloneCurrentValue();
            Brush toVal = ((Brush)GetValue(BrushAnimation.ToProperty)).CloneCurrentValue();

            if ((double)animationClock.CurrentProgress == 0.0)
                return fromVal; //Here it workes fine.

            if ((double)animationClock.CurrentProgress == 1.0)
                return toVal;   //It workes also here fine.

            toVal.Opacity = (double)animationClock.CurrentProgress;


            Border Bd = new Border();
            Border Bdr = new Border();

            Bd.Width = 1.0;
            Bd.Height = 1.0;

            Bd.Background = fromVal;
            Bdr.Background = toVal;

            Bd.Visibility = Visibility.Visible;
            Bdr.Visibility = Visibility.Visible;
            Bd.Child = Bdr;

            Brush VB = new VisualBrush(Bd);
            return VB; //But here it return's a transparent brush.

            //If I return the 'toVal' variable here it animates correctly the opacity.
        }
    }
}

A: 

The above approach should work as long as you have transparent pixels in the front brush. If not the front brush would just overlay the back brush. You should provide a more complete example to see what is actually going on.

bitbonk
Oops I forgot to mention. To do the animation I am changing regularly the opacity of the front brush. It will be 0 at the beginning of the animation and it will end at 1. So at the end it will overlay the back brush.The problem with it is that the resulting brush is completely transparent.
Aaron de Windt
Maybe you accidentally set the transparency of the VisualBrush "VB". Its really hard to tell what#s going wrong with an incomplete example.
bitbonk
I added the complete class. Look at it again.
Aaron de Windt
btw: toVal.GetType() == typeof(SpecularMaterial) no need to create an instance just to compare the types
bitbonk
I don't get it. It seems that your anmation does nothing but animating the opacity of a material. You don't have to write a extra class to achieve this in XAML. You can animate material properties in XAML (or C#) very easily. For Material.Opacity you just use a DoubleAnimation
bitbonk
I am using it to do a transition from one material to an other. I could use a double animation to animate Material.Brush.Opacity (There is no Material.Opacity), but I thought that if I made a Animation class for the transition the code could be a bit more organized. I need to use this a couple of times.This class could help some people, but it isn't useful for everybody.
Aaron de Windt
A: 

The reason I need to animate a brush is to animate the brush in a material that I am using in a 3d object. I thought it would be easier to animate the brush than the material.

I have already used the method above to combinate brushes, but it didn't work here.

After thinking a little bit I decided to animate the Material and not the brush. It resulted to be easier than animating a brush.

[NOTE]
This animation class is adapted for my needs. It only animates the brush in the material. I am using this class to replace the brush of a material for an other.

[NOTE]
The 'to material' will at the end replace completely the 'from material', it will not end with a MaterialGroup.

Here is the MaterialAnimation Class for who needs it. I also have a Point3DCollectionAnimation Class. It can be used to animate 3D meshes. It's very useful. You can find it below this one.

MaterialAnimation

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Media.Animation;
using System.Windows;
using System.Windows.Media;
using System.Windows.Controls;
using System.Windows.Media.Media3D;

namespace System.Windows.Media.Animation
{
    class MaterialAnimation : AnimationTimeline
    {
                protected override Freezable CreateInstanceCore()
        {
            return new MaterialAnimation();

        }
        public override Type TargetPropertyType
        {
            get { return typeof(Material); }
        }
        static MaterialAnimation()
        {
            FromProperty = DependencyProperty.Register("From", typeof(Material),
                typeof(MaterialAnimation));

            ToProperty = DependencyProperty.Register("To", typeof(Material),
                typeof(MaterialAnimation));
        }
        public static readonly DependencyProperty FromProperty;
        public Material From
        {
            get
            {
                return (Material)GetValue(MaterialAnimation.FromProperty);
            }
            set
            {
                SetValue(MaterialAnimation.FromProperty, value);
            }
        }
        public static readonly DependencyProperty ToProperty;
        public Material To
        {
            get
            {
                return (Material)GetValue(MaterialAnimation.ToProperty);
            }
            set
            {
                SetValue(MaterialAnimation.ToProperty, value);
            }
        }
        public override object GetCurrentValue(object defaultOriginValue,
        object defaultDestinationValue, AnimationClock animationClock)
        {
            Material fromVal = ((Material)GetValue(MaterialAnimation.FromProperty)).CloneCurrentValue();
            Material toVal = ((Material)GetValue(MaterialAnimation.ToProperty)).CloneCurrentValue();

            if ((double)animationClock.CurrentProgress == 0.0)
                return fromVal; //Here it workes fine.

            if ((double)animationClock.CurrentProgress == 1.0)
                return toVal;   //It workes also here fine.            

            if (toVal.GetType() == (new DiffuseMaterial()).GetType())
                ((DiffuseMaterial)toVal).Brush.Opacity = (double)animationClock.CurrentProgress;
            else
                if (toVal.GetType() == (new SpecularMaterial()).GetType())
                    ((SpecularMaterial)toVal).Brush.Opacity = (double)animationClock.CurrentProgress;
                else
                    ((EmissiveMaterial)toVal).Brush.Opacity = (double)animationClock.CurrentProgress;


            MaterialGroup MG = new MaterialGroup();

            MG.Children.Add(fromVal);
            MG.Children.Add(toVal);            

            return MG; 
        }
    }
}


Here is the Point3DCollectionAnimation Class.

Point3DCollectionAnimation

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Media.Animation;
using System.Windows;
using System.Windows.Media.Media3D;

namespace System.Windows.Media.Animation
{
    public class Point3DCollectionAnimation : AnimationTimeline
    {
        protected override Freezable CreateInstanceCore()
        {
            return new Point3DCollectionAnimation();
        }
        public override Type TargetPropertyType
        {
            get { return typeof(Point3DCollection); }
        }
        static Point3DCollectionAnimation()
        {
            FromProperty = DependencyProperty.Register("From", typeof(Point3DCollection),
                typeof(Point3DCollectionAnimation));

            ToProperty = DependencyProperty.Register("To", typeof(Point3DCollection),
                typeof(Point3DCollectionAnimation));
        }
        public static readonly DependencyProperty FromProperty;
        public Point3DCollection From
        {
            get
            {
                return (Point3DCollection)GetValue(Point3DCollectionAnimation.FromProperty);
            }
            set
            {
                SetValue(Point3DCollectionAnimation.FromProperty, value);
            }
        }
        public static readonly DependencyProperty ToProperty;
        public Point3DCollection To
        {
            get
            {
                return (Point3DCollection)GetValue(Point3DCollectionAnimation.ToProperty);
            }
            set
            {
                SetValue(Point3DCollectionAnimation.ToProperty, value);
            }
        }
        public override object GetCurrentValue(object defaultOriginValue,
        object defaultDestinationValue, AnimationClock animationClock)
        {
            Point3DCollection fromVal = ((Point3DCollection)GetValue(Point3DCollectionAnimation.FromProperty));
            Point3DCollection toVal = ((Point3DCollection)GetValue(Point3DCollectionAnimation.ToProperty));

            Point3DCollection ret;

            int t = 0;
            if (fromVal.Count > toVal.Count)
            {
                ret = fromVal.Clone();
                foreach (Point3D tov in toVal)
                {
                    Point3D frov = fromVal[t];
                    Point3D newv = new Point3D();

                    newv.X = (double)animationClock.CurrentProgress * (tov.X - frov.X) + frov.X;
                    newv.Y = (double)animationClock.CurrentProgress * (tov.Y - frov.Y) + frov.Y;
                    newv.Z = (double)animationClock.CurrentProgress * (tov.Z - frov.Z) + frov.Z;
                    ret[t] = newv;
                    t++;
                }
            }
            else
            {
                ret = toVal.Clone();
                foreach (Point3D frov in fromVal)
                {
                    Point3D tov = toVal[t];
                    Point3D newv = new Point3D();

                    newv.X = (double)animationClock.CurrentProgress * (tov.X - frov.X) + frov.X;
                    newv.Y = (double)animationClock.CurrentProgress * (tov.Y - frov.Y) + frov.Y;
                    newv.Z = (double)animationClock.CurrentProgress * (tov.Z - frov.Z) + frov.Z;
                    ret[t] = newv;
                    t++;
                }
            }

            return ret;
        }
    }
}

I hope these classes are usefull for who needs them. I searched for them allot on the internet, but didn't find them. I'm sure that there are more people who needs these classes.

Please leave comments.

Aaron de Windt
A: 

I discovered the problem. Visual Brushes are not freezable. To the code to work I will need to find a way to freeze the brush.

Aaron de Windt