public override bool Equals(object obj)
        {
            var param = obj as ProcedualModelParameter;

            if (param == null)
            {
                return(false);
            }

            if (Type.Value != param.Type.Value)
            {
                return(false);
            }

            if (Type.Value == ProcedualModelType.Mesh)
            {
                if (!AngleBeginEnd.ValueEquals(param.AngleBeginEnd))
                {
                    return(false);
                }
                if (!Divisions.ValueEquals(param.Divisions))
                {
                    return(false);
                }
            }
            else if (Type.Value == ProcedualModelType.Ribbon)
            {
                if (CrossSection.Value != param.CrossSection.Value)
                {
                    return(false);
                }
                if (Rotate.Value != param.Rotate.Value)
                {
                    return(false);
                }
                if (Vertices.Value != param.Vertices.Value)
                {
                    return(false);
                }
                if (!RibbonScales.ValueEquals(param.RibbonScales))
                {
                    return(false);
                }
                if (!RibbonAngles.ValueEquals(param.RibbonAngles))
                {
                    return(false);
                }
                if (!RibbonNoises.ValueEquals(param.RibbonNoises))
                {
                    return(false);
                }
                if (Count.Value != param.Count.Value)
                {
                    return(false);
                }
            }
            else
            {
                throw new Exception();
            }


            if (PrimitiveType.Value != param.PrimitiveType.Value)
            {
                return(false);
            }

            if (PrimitiveType.Value == ProcedualModelPrimitiveType.Sphere)
            {
                if (Radius.Value != param.Radius.Value)
                {
                    return(false);
                }
                if (DepthMin.Value != param.DepthMin.Value)
                {
                    return(false);
                }
                if (DepthMax.Value != param.DepthMax.Value)
                {
                    return(false);
                }
            }
            else if (PrimitiveType.Value == ProcedualModelPrimitiveType.Cone)
            {
                if (Radius.Value != param.Radius.Value)
                {
                    return(false);
                }
                if (Depth.Value != param.Depth.Value)
                {
                    return(false);
                }
            }
            else if (PrimitiveType.Value == ProcedualModelPrimitiveType.Cylinder)
            {
                if (Radius.Value != param.Radius.Value)
                {
                    return(false);
                }
                if (Radius2.Value != param.Radius2.Value)
                {
                    return(false);
                }
                if (Depth.Value != param.Depth.Value)
                {
                    return(false);
                }
            }
            else if (PrimitiveType.Value == ProcedualModelPrimitiveType.Spline4)
            {
                if (!Point1.ValueEquals(param.Point1))
                {
                    return(false);
                }
                if (!Point2.ValueEquals(param.Point2))
                {
                    return(false);
                }
                if (!Point3.ValueEquals(param.Point3))
                {
                    return(false);
                }
                if (!Point4.ValueEquals(param.Point4))
                {
                    return(false);
                }
            }
            else
            {
                throw new Exception();
            }

            if (AxisType.Value != param.AxisType.Value)
            {
                return(false);
            }

            if (!TiltNoiseFrequency.ValueEquals(param.TiltNoiseFrequency))
            {
                return(false);
            }
            if (!TiltNoiseOffset.ValueEquals(param.TiltNoiseOffset))
            {
                return(false);
            }
            if (!TiltNoisePower.ValueEquals(param.TiltNoisePower))
            {
                return(false);
            }

            if (!WaveNoiseFrequency.ValueEquals(param.WaveNoiseFrequency))
            {
                return(false);
            }
            if (!WaveNoiseOffset.ValueEquals(param.WaveNoiseOffset))
            {
                return(false);
            }
            if (!WaveNoisePower.ValueEquals(param.WaveNoisePower))
            {
                return(false);
            }

            if (!CurlNoiseFrequency.ValueEquals(param.CurlNoiseFrequency))
            {
                return(false);
            }
            if (!CurlNoiseOffset.ValueEquals(param.CurlNoiseOffset))
            {
                return(false);
            }
            if (!CurlNoisePower.ValueEquals(param.CurlNoisePower))
            {
                return(false);
            }

            if (!ColorLeft.ValueEquals(param.ColorLeft))
            {
                return(false);
            }
            if (!ColorCenter.ValueEquals(param.ColorCenter))
            {
                return(false);
            }
            if (!ColorRight.ValueEquals(param.ColorRight))
            {
                return(false);
            }
            if (!ColorLeftMiddle.ValueEquals(param.ColorLeftMiddle))
            {
                return(false);
            }
            if (!ColorCenterMiddle.ValueEquals(param.ColorCenterMiddle))
            {
                return(false);
            }
            if (!ColorRightMiddle.ValueEquals(param.ColorRightMiddle))
            {
                return(false);
            }

            if (!ColorCenterArea.ValueEquals(param.ColorCenterArea))
            {
                return(false);
            }

            return(true);
        }