private static void PropertyChanged(object sender, object args)
        {
            PropertyData data = null;

            if (sender.GetType() == typeof(ColorPicker))
            {
                ColorPicker mixer = (ColorPicker)sender;
                data = (PropertyData)mixer.Tag;
                string name = (string)data.Key;

                MethodInfo method = data.Target.GetType().GetMethod("SetProperty");
                object     result = method.Invoke(data.Target, new object[] { name, mixer.Color });
            }
            else if (sender.GetType() == typeof(ComboBox))
            {
                ComboBox box = (ComboBox)sender;
                data = (PropertyData)box.Tag;
                PropertyData itemData = (PropertyData)((ComboBoxItem)box.SelectedItem).Tag;
                string       name     = (string)data.Key;

                MethodInfo method = data.Target.GetType().GetMethod("SetProperty");
                object     result = method.Invoke(data.Target, new object[] { name, itemData.Key });
            }
            else if (sender.GetType() == typeof(TextBox))
            {
                TextBox box = (TextBox)sender;
                data = (PropertyData)box.Tag;
                string name = (string)data.Key;

                if (box.Text.Length > 0)
                {
                    try
                    {
                        MethodInfo method = data.Target.GetType().GetMethod("SetProperty");
                        object     result = method.Invoke(data.Target, new object[] { name, Convert.ToSingle(box.Text) });
                    }
                    catch
                    {
                        // Ignore, invalid conversion or property range
                    }
                }
            }
            else if (sender.GetType() == typeof(Matrix5x4Control))
            {
                Matrix5x4Control mat = (Matrix5x4Control)sender;
                data = (PropertyData)mat.Tag;
                string name = (string)data.Key;

                MethodInfo method = data.Target.GetType().GetMethod("SetProperty");
                object     result = method.Invoke(data.Target, new object[] { name, mat.Matrix });
            }
            else if (sender.GetType() == typeof(VectorControl))
            {
                VectorControl vec = (VectorControl)sender;
                data = (PropertyData)vec.Tag;
                string name = (string)data.Key;

                MethodInfo method = data.Target.GetType().GetMethod("SetProperty");
                switch (vec.Components)
                {
                case 2:
                    method.Invoke(data.Target, new object[] { name, vec.Vector2 });
                    break;

                case 3:
                    method.Invoke(data.Target, new object[] { name, vec.Vector3 });
                    break;

                case 4:
                    method.Invoke(data.Target, new object[] { name, vec.Vector4 });
                    break;
                }
            }
            else
            {
                Debug.Assert(false);
            }
        }
        static public void AddPropertyToPanel(object propertyObject, object targetObject, StackPanel panel, PropertyInfo info)
        {
            TextBlock textName = new TextBlock();

            textName.Text   = info.Name;
            textName.Margin = textName.Margin = new Thickness(0, 20, 0, 5);
            panel.Children.Add(textName);

            FrameworkElement element;

            if (info.PropertyType == typeof(float))
            {
                TextBox box = new TextBox();
                box.Text         = ((float)info.GetValue(propertyObject)).ToString();
                box.Tag          = new PropertyData(info.Name, propertyObject, targetObject);
                box.TextChanged += PropertyChanged;
                element          = box;
            }
            else if (info.PropertyType == typeof(bool))
            {
                ComboBox box = new ComboBox();
                box.Tag = new PropertyData(info.Name, propertyObject, targetObject);
                box.SelectionChanged += PropertyChanged;
                box.SelectedValuePath = "Content";

                ComboBoxItem item = new ComboBoxItem();
                item.Content = "True";
                item.Tag     = new PropertyData(true, propertyObject, targetObject);
                box.Items.Add(item);

                item         = new ComboBoxItem();
                item.Content = "False";
                item.Tag     = new PropertyData(false, propertyObject, targetObject);
                box.Items.Add(item);

                box.SelectedValue = ((bool)info.GetValue(propertyObject)).ToString();
                element           = box;
            }
            else if (typeof(Enum).IsAssignableFrom(info.PropertyType))
            {
                ComboBox box = new ComboBox();
                box.Tag = new PropertyData(info.Name, propertyObject, targetObject);
                box.SelectionChanged += PropertyChanged;
                box.SelectedValuePath = "Content";

                foreach (object o in Enum.GetValues(info.PropertyType))
                {
                    ComboBoxItem item = new ComboBoxItem();
                    item.Content = o.ToString();
                    item.Tag     = new PropertyData(o, propertyObject, targetObject);;
                    box.Items.Add(item);
                }

                box.SelectedValue = info.GetValue(propertyObject).ToString();
                element           = box;
            }
            else if (info.PropertyType == typeof(Color))
            {
                ColorPicker mixer = new ColorPicker();
                mixer.ColorChanged += PropertyChanged;
                mixer.Tag           = new PropertyData(info.Name, propertyObject, targetObject);
                mixer.Color         = (Color)info.GetValue(propertyObject);
                element             = mixer;
            }
            else if (info.PropertyType == typeof(Matrix5x4))
            {
                Matrix5x4Control mat = new Matrix5x4Control();
                mat.MatrixChanged += PropertyChanged;
                mat.Tag            = new PropertyData(info.Name, propertyObject, targetObject);
                mat.Matrix         = (Matrix5x4)info.GetValue(propertyObject);
                element            = mat;
            }
            else if (info.PropertyType == typeof(Vector2))
            {
                VectorControl vec = new VectorControl(2);
                vec.VectorChanged += PropertyChanged;
                vec.Tag            = new PropertyData(info.Name, propertyObject, targetObject);
                vec.Vector2        = (Vector2)info.GetValue(propertyObject);
                element            = vec;
            }
            else if (info.PropertyType == typeof(Vector3))
            {
                VectorControl vec = new VectorControl(3);
                vec.VectorChanged += PropertyChanged;
                vec.Tag            = new PropertyData(info.Name, propertyObject, targetObject);
                vec.Vector3        = (Vector3)info.GetValue(propertyObject);
                element            = vec;
            }
            else if (info.PropertyType == typeof(Vector4))
            {
                VectorControl vec = new VectorControl(4);
                vec.VectorChanged += PropertyChanged;
                vec.Tag            = new PropertyData(info.Name, propertyObject, targetObject);
                vec.Vector4        = (Vector4)info.GetValue(propertyObject);
                element            = vec;
            }
            else
            {
                textName = new TextBlock();
                object value = info.GetValue(propertyObject);
                textName.Text = value == null ? "" : value.ToString();
                element       = textName;
            }

            panel.Children.Add(element);
        }