void DisplayMaterialSections(MegaLoftLayerMultiMat layer)
    {
        if (GUILayout.Button("Add Material"))
        {
            MegaMaterialSection ms = new MegaMaterialSection();
            layer.sections.Add(ms);
            EditorUtility.SetDirty(target);
        }

        for (int i = 0; i < layer.sections.Count; i++)
        {
            MegaMaterialSection ms = layer.sections[i];


            string name = "Mat " + ms.id;
            if (ms.mat)
            {
                name += " " + ms.mat.name;
            }

            EditorGUILayout.BeginVertical("box");
            ms.show = EditorGUILayout.Foldout(ms.show, name);
            if (ms.show)
            {
                ms.Enabled      = EditorGUILayout.BeginToggleGroup("Enabled", ms.Enabled);
                ms.id           = EditorGUILayout.IntField("ID", ms.id);
                ms.mat          = (Material)EditorGUILayout.ObjectField("Material", ms.mat, typeof(Material), true);
                ms.cdist        = EditorGUILayout.Slider(MegaToolTip.CrossDist, ms.cdist, cdl, cdh);            //0.025f, 1.0f);
                ms.includeknots = EditorGUILayout.Toggle("Include Knots", ms.includeknots);

                //ms.vertscale = EditorGUILayout.FloatField("Vert Scale", ms.vertscale);
                ms.UVOffset = EditorGUILayout.Vector2Field("UV Offset", ms.UVOffset);
                ms.UVScale  = EditorGUILayout.Vector2Field("UV Scale", ms.UVScale);
                ms.swapuv   = EditorGUILayout.Toggle(MegaToolTip.SwapUV, ms.swapuv);
                ms.physuv   = EditorGUILayout.Toggle(MegaToolTip.PhysicalUV, ms.physuv);
                ms.uvcalcy  = EditorGUILayout.Toggle("Calc Y", ms.uvcalcy);

                ms.colmode   = (MegaLoftColMode)EditorGUILayout.EnumPopup("Color Mode", ms.colmode);
                ms.coloffset = EditorGUILayout.FloatField("Offset", ms.coloffset);
                ms.color     = EditorGUILayout.ColorField("Color", ms.color);
                ms.colR      = EditorGUILayout.CurveField("Red", ms.colR);
                ms.colG      = EditorGUILayout.CurveField("Green", ms.colG);
                ms.colB      = EditorGUILayout.CurveField("Blue", ms.colB);
                ms.colA      = EditorGUILayout.CurveField("Alpha", ms.colA);

                EditorGUILayout.EndToggleGroup();

                if (i > 0)
                {
                    if (GUILayout.Button("Delete"))
                    {
                        layer.sections.RemoveAt(i);
                        EditorUtility.SetDirty(target);
                    }
                }
            }
            EditorGUILayout.EndVertical();
        }
    }
Exemple #2
0
    // Have cdist per material
    // Best way is to treat each material section like a layer
    public override bool PrepareLoft(MegaShapeLoft loft, int sc)
    {
        MegaShape section = layerSection;

        // Look at section and find out how many changes in material there are, ie matid
        // That will be the number of materials
        // Each change will have its own cdist, uv mapping, material

        // We seem to do this below as well
        FindSections(section.splines[crosscurve]);

        Matrix4x4 tm1 = Matrix4x4.identity;

        MegaMatrix.Translate(ref tm1, pivot);
        MegaMatrix.Rotate(ref tm1, new Vector3(Mathf.Deg2Rad * crossRot.x, Mathf.Deg2Rad * crossRot.y, Mathf.Deg2Rad * crossRot.z));

        // Build the cross for each section
        if (enabled)
        {
            float dst = crossDist;

            if (dst < 0.01f)
            {
                dst = 0.01f;
            }

            int k  = -1;
            int lk = -1;

            svert = verts.Count;
            Vector2 uv = Vector2.zero;

            float alpha = crossStart;
            float cend  = crossStart + crossEnd;

            if (alpha < 0.0f)
            {
                alpha = 0.0f;
            }

            if (cend > 1.0f)
            {
                cend = 1.0f;
            }

            MegaSpline cspl = section.splines[crosscurve];

            if (cspl.closed)
            {
                if (alpha < 0.0f)
                {
                    alpha += 1.0f;
                }
            }

            Vector3 off = Vector3.zero;
            if (snap)
            {
                off = cspl.knots[0].p - cspl.knots[0].p;
            }

            if (cspl.closed)
            {
                alpha = Mathf.Repeat(alpha, 1.0f);
            }

            meshsections.Clear();

            Vector3 pos = tm1.MultiplyPoint3x4(cspl.InterpCurve3D(alpha, section.normalizedInterp, ref lk) + off);

            int             currentid = cspl.knots[lk].id;
            MegaMeshSection msect     = new MegaMeshSection();

            msect.castart = 0.0f;
            float uvalpha = crossStart;
            uv.y = uvalpha;             //crossStart;

            msect.vertstart = 0;
            msect.mat       = FindMaterial(currentid);
            meshsections.Add(msect);

            // Method to get cdist
            MegaMaterialSection ms = sections[msect.mat];

            msect.cverts.Add(pos);

            bool loop = true;
            //float lastalpha = alpha;
            while (alpha <= cend)
            {
                if (loop)
                {
                    alpha += ms.cdist;
                    loop   = false;
                }
                if (alpha > cend)
                {
                    alpha = cend;
                }

                pos = tm1.MultiplyPoint3x4(cspl.InterpCurve3D(alpha, section.normalizedInterp, ref k) + off);

                if (k != lk)
                {
                    while (lk != k)
                    {
                        //bool looped = false;
                        lk++;
                        int lk1 = lk % cspl.knots.Count;
                        lk = lk1;

                        if (cspl.knots[lk].id != currentid)
                        {
                            msect.cverts.Add(tm1.MultiplyPoint3x4(cspl.knots[lk].p + off));
                            float caend = ((cspl.knots[lk].length / cspl.length) - crossStart) / (crossEnd - crossStart);
                            msect.caend = caend;

                            // New material
                            msect         = new MegaMeshSection();
                            msect.castart = caend;

                            pos = tm1.MultiplyPoint3x4(cspl.knots[lk].p + off);

                            msect.vertstart = 0;
                            currentid       = cspl.knots[lk].id;
                            msect.mat       = FindMaterial(currentid);
                            meshsections.Add(msect);
                            ms = sections[msect.mat];

                            msect.cverts.Add(pos);
                            lk1 = lk - 1;
                            if (lk1 < 0)
                            {
                                lk1 = cspl.knots.Count - 1;
                            }

                            alpha = (cspl.knots[lk1].length / cspl.length);                             // + crossStart;

                            break;
                        }
                        else
                        {
                            if (ms.includeknots)
                            {
                                msect.cverts.Add(tm1.MultiplyPoint3x4(cspl.knots[lk].p + off));
                            }
                            else
                            {
                                if (cspl.knots[k].id != currentid)
                                {
                                    int kk = lk;
                                    while (cspl.knots[kk].id == currentid && kk < cspl.knots.Count)
                                    {
                                        kk++;
                                    }
                                    if (kk >= cspl.knots.Count)
                                    {
                                        kk = cspl.knots.Count - 1;
                                    }

                                    msect.cverts.Add(tm1.MultiplyPoint3x4(cspl.knots[kk].p + off));
                                    break;
                                }
                                else
                                {
                                    msect.cverts.Add(pos);
                                }
                            }
                        }
                    }
                }
                else
                {
                    msect.cverts.Add(pos);
                }

                if (alpha == cend)
                {
                    if (msect.cverts[msect.cverts.Count - 1] != pos)
                    {
                        msect.cverts.Add(pos);
                    }

                    break;
                }

                alpha += ms.cdist;
                if (alpha > cend)
                {
                    alpha = cend;
                }
            }

            msect.caend = 1.0f;

            // Do uv and col now
            for (int i = 0; i < meshsections.Count; i++)
            {
                MegaMeshSection ms1 = meshsections[i];

                Vector2 uv1 = Vector2.zero;
                ms1.cuvs.Add(uv1);
                ms1.ccols.Add(Color.white);

                for (int v = 1; v < ms1.cverts.Count; v++)
                {
                    uv1.y += Vector3.Distance(ms1.cverts[v], ms1.cverts[v - 1]);
                    ms1.cuvs.Add(uv1);
                    ms1.ccols.Add(Color.white);
                }
            }

            // Add end point
            if (section.splines[crosscurve].closed)
            {
                alpha = Mathf.Repeat(cend, 1.0f);
            }
        }

        // Calc normals
        Vector3 up = Vector3.zero;
        Vector3 n1 = Vector3.zero;

        for (int i = 0; i < meshsections.Count; i++)
        {
            MegaMeshSection ms1 = meshsections[i];

            if (ms1.cverts.Count > 1)
            {
                for (int v = 0; v < ms1.cverts.Count; v++)
                {
                    if (v < ms1.cverts.Count - 1)
                    {
                        n1 = (ms1.cverts[v + 1] - ms1.cverts[v]);
                    }
                    else
                    {
                        n1 = (ms1.cverts[v] - ms1.cverts[v - 1]);
                    }

                    up.x = -n1.y;
                    up.y = n1.x;
                    up.z = 0.0f;
                    ms1.cnorms.Add(up);
                }
            }
        }

        Prepare(loft);

        return(true);
    }
Exemple #3
0
    public override int BuildMesh(MegaShapeLoft loft, int triindex)
    {
        trisstart = triindex;

        if (Lock)
        {
            return(triindex + ((crosses - 2) * (evert - svert)));
        }

        if (layerPath == null || layerSection == null)
        {
            return(triindex);
        }

        MegaSpline pathspline    = layerPath.splines[curve];
        MegaSpline sectionspline = layerSection.splines[crosscurve];

        // so for each loft section run through
        int     vi  = 0;
        Vector2 uv  = Vector2.zero;
        Vector3 p   = Vector3.zero;
        Vector3 scl = Vector3.one;

        float scalemultx = 1.0f;
        float scalemulty = 1.0f;

        Vector3 cmax = crossmax;

        cmax.x = 0.0f;
        cmax.z = 0.0f;

        Vector3 cmin = crossmin;

        cmin.x = 0.0f;
        cmin.z = 0.0f;

        Vector3 totaloff = Vector3.zero;

        float uvstart = pathStart;

        if (UVOrigin == MegaLoftUVOrigin.SplineStart)
        {
            uvstart = 0.0f;
        }

        Matrix4x4 twisttm = Matrix4x4.identity;

        Color col1 = color;

        Matrix4x4 tm;
        Vector3   lastup = loft.up;

        float calpha = 0.0f;

        for (int cr = 0; cr < crosses; cr++)
        {
            float a     = ((float)cr / (float)(crosses - 1));
            float alpha = pathStart + (pathLength * a);

            totaloff = offset;

            if (useOffsetX)
            {
                totaloff.x += offsetCrvX.Evaluate(alpha);
            }

            if (useOffsetY)
            {
                totaloff.y += offsetCrvY.Evaluate(alpha);
            }

            if (useOffsetZ)
            {
                totaloff.z += offsetCrvZ.Evaluate(alpha);
            }

            // get the point on the spline
            if (frameMethod == MegaFrameMethod.New)
            {
                tm = loft.GetDeformMatNewMethod(pathspline, alpha, true, alignCross, ref lastup);
            }
            else
            {
                tm = loft.GetDeformMatNew(pathspline, alpha, true, alignCross);
            }

            if (useTwistCrv)
            {
                float twist = twistCrv.Evaluate(alpha) * twistAmt;

                float tw1 = pathspline.GetTwist(alpha);
                MegaShapeUtils.RotateZ(ref twisttm, Mathf.Deg2Rad * (twist - tw1));
                tm = tm * twisttm;
            }

            if (useCrossScaleCrv)
            {
                float sa = Mathf.Repeat(a + scaleoff, 1.0f);
                scalemultx = crossScaleCrv.Evaluate(sa);
            }

            if (!sepscale)
            {
                scalemulty = scalemultx;
            }
            else
            {
                if (useCrossScaleCrvY)
                {
                    float sa = Mathf.Repeat(a + scaleoffY, 1.0f);
                    scalemulty = crossScaleCrvY.Evaluate(sa);
                }
            }

            scl.x = crossScale.x * scalemultx;                  // Use plus here and have curve as 0010
            scl.y = crossScale.y * scalemulty;

            Vector3 crrot = cmax;
            crrot.y *= scl.y;

            Vector3 cminrot = cmin;
            cminrot.y *= scl.y;

            // Now need to loop through all the meshsections
            for (int m = 0; m < meshsections.Count; m++)
            {
                MegaMeshSection     ms   = meshsections[m];
                MegaMaterialSection mats = sections[ms.mat];

                if (mats.Enabled)
                {
                    if (loft.useColors)
                    {
                        if (mats.colmode == MegaLoftColMode.Loft)
                        {
                            calpha = a;
                        }
                        else
                        {
                            calpha = alpha;
                        }

                        calpha = Mathf.Repeat(calpha + mats.coloffset, 1.0f);
                        col1.r = mats.colR.Evaluate(calpha);
                        col1.g = mats.colG.Evaluate(calpha);
                        col1.b = mats.colB.Evaluate(calpha);
                        col1.a = mats.colA.Evaluate(calpha);
                    }

                    for (int v = 0; v < ms.cverts.Count; v++)
                    {
                        p.x = ms.cverts[v].x * scl.x;
                        p.y = ms.cverts[v].y * scl.y;                           // Curve for this value
                        p.z = ms.cverts[v].z * scl.z;

                        p = tm.MultiplyPoint3x4(p);

                        uv.x = alpha - uvstart;                         //pathStart;
                        uv.y = ms.cuvs[v].y;                            // - crossStart;	// again not sure here start;

                        if (mats.physuv)
                        {
                            uv.x *= pathspline.length;
                            uv.y *= sectionspline.length;
                        }
                        else
                        {
                            if (mats.uvcalcy)
                            {
                                //uv.x = ((a * LoftLength) / sectionspline.length) - uvstart;
                                uv.x = ((alpha * pathspline.length) / sectionspline.length) - uvstart;
                            }
                        }

                        if (conform)
                        {
                            ms.verts1.Add(p + totaloff);
                        }
                        else
                        {
                            ms.verts.Add(p + totaloff);
                        }

                        if (mats.swapuv)
                        {
                            float ux = uv.x;
                            uv.x = uv.y;
                            uv.y = ux;
                        }

                        uv.x *= mats.UVScale.x;
                        uv.y *= mats.UVScale.y;

                        uv.x += mats.UVOffset.x;
                        uv.y += mats.UVOffset.y;

                        ms.uvs.Add(uv);                         //[vi] = uv;

                        if (loft.useColors)
                        {
                            ms.cols.Add(col1);
                        }

                        vi++;
                    }
                }
            }
        }

        //OptmizeMesh();
        // Faces
        int index = triindex;
        int fi    = 0;          // Calc this

        if (enabled)
        {
            if (flip)
            {
                for (int m = 0; m < meshsections.Count; m++)
                {
                    MegaMeshSection     ms   = meshsections[m];
                    MegaMaterialSection mats = sections[ms.mat];

                    if (mats.Enabled)
                    {
                        for (int cr = 0; cr < crosses - 1; cr++)
                        {
                            for (int f = 0; f < ms.cverts.Count - 1; f++)
                            {
                                ms.tris.Add(index + f);
                                ms.tris.Add(index + f + 1);
                                ms.tris.Add(index + f + 1 + ms.cverts.Count);

                                ms.tris.Add(index + f);
                                ms.tris.Add(index + f + 1 + ms.cverts.Count);
                                ms.tris.Add(index + f + ms.cverts.Count);

                                fi += 6;
                            }

                            index += ms.cverts.Count;
                        }
                        index += ms.cverts.Count;
                    }
                }
            }
            else
            {
                for (int m = 0; m < meshsections.Count; m++)
                {
                    MegaMeshSection     ms   = meshsections[m];
                    MegaMaterialSection mats = sections[ms.mat];

                    if (mats.Enabled)
                    {
                        for (int cr = 0; cr < crosses - 1; cr++)
                        {
                            for (int f = 0; f < ms.cverts.Count - 1; f++)
                            {
                                ms.tris.Add(index + f + 1 + ms.cverts.Count);
                                ms.tris.Add(index + f + 1);
                                ms.tris.Add(index + f);

                                ms.tris.Add(index + f + ms.cverts.Count);
                                ms.tris.Add(index + f + 1 + ms.cverts.Count);
                                ms.tris.Add(index + f);

                                fi += 6;
                            }

                            index += ms.cverts.Count;
                        }

                        index += ms.cverts.Count;
                    }
                }
            }
        }

        if (conform)
        {
            CalcBounds();
            DoConform(loft);
        }

        return(triindex + fi);          //triindex;
    }
Exemple #4
0
    void BuildPolyShape(MegaLoftSection lsection, int steps, Vector3 off1, float width)
    {
        int       curve = lsection.curve;
        int       lk    = -1;
        Matrix4x4 tm1   = Matrix4x4.identity;
        MegaShape shape = lsection.shape;

        //verts.Clear();
        //uvs.Clear();
        //norms.Clear();

        MegaMatrix.Translate(ref tm1, pivot);
        Vector3 rot = crossRot + lsection.rot;

        MegaMatrix.Rotate(ref tm1, new Vector3(Mathf.Deg2Rad * rot.x, Mathf.Deg2Rad * rot.y, Mathf.Deg2Rad * rot.z));

        svert = verts.Count;

        {
            float dst = crossDist;

            if (dst < 0.01f)
            {
                dst = 0.01f;
            }

            svert = verts.Count;

            float alpha = crossStart;
            float cend  = crossStart + crossEnd;

            if (alpha < 0.0f)
            {
                alpha = 0.0f;
            }

            if (cend > 1.0f)
            {
                cend = 1.0f;
            }

            MegaSpline cspl = shape.splines[curve];

            if (cspl.closed)
            {
                if (alpha < 0.0f)
                {
                    alpha += 1.0f;
                }
            }

            Vector3 off = off1;                 //Vector3.zero;
            if (snap)
            {
                off = cspl.knots[0].p - cspl.knots[0].p;
            }

            if (cspl.closed)
            {
                alpha = Mathf.Repeat(alpha, 1.0f);
            }

            lsection.meshsections.Clear();
            FindSections(lsection, cspl);

            Vector3 pos = tm1.MultiplyPoint3x4(cspl.InterpCurve3D(alpha, shape.normalizedInterp, ref lk) + off);

            //Debug.Log("MeshSections " + lsection.meshsections.Count);

            for (int i = 0; i < lsection.meshsections.Count; i++)
            {
                MegaMeshSection     ms = lsection.meshsections[i];              //new MegaMeshSection();
                MegaMaterialSection s  = sections[ms.mat];

                int   k1 = ms.firstknot;
                int   k2 = ms.lastknot;
                float l1 = 0.0f;
                float l2 = 0.0f;

                //Debug.Log("k1 " + k1 + " k2 " + k2);
                if (k1 > 0)
                {
                    l1 = cspl.knots[k1 - 1].length;
                }
                else
                {
                    l1 = 0.0f;
                }

                if (k2 < cspl.knots.Count - 1)
                {
                    l2 = cspl.knots[k2 - 1].length;
                }
                else
                {
                    l2 = cspl.length;
                }

                //float slen = l2 - l1;
                //Debug.Log("l1 " + l1 + " l2 " + l2);

                float a1 = l1 / cspl.length;
                float a2 = l2 / cspl.length;
                ms.castart = a1;
                ms.caend   = a2;

                for (int kn = k1; kn < k2; kn++)
                {
                    pos = cspl.knots[kn].Interpolate(0.0f, cspl.knots[kn + 1]) + lsection.offset;

                    pos.x *= lsection.scale.x;
                    pos.y *= lsection.scale.y;
                    pos.z *= lsection.scale.z;

                    pos = tm1.MultiplyPoint3x4(pos + off);
                    ms.cverts.Add(pos);

                    for (int j = 1; j < s.steps; j++)
                    {
                        float ka = (float)j / (float)s.steps;
                        pos = cspl.knots[kn].Interpolate(ka, cspl.knots[kn + 1]) + lsection.offset;

                        pos.x *= lsection.scale.x;
                        pos.y *= lsection.scale.y;
                        pos.z *= lsection.scale.z;

                        pos = tm1.MultiplyPoint3x4(pos + off);
                        ms.cverts.Add(pos);
                    }
                }

                pos = cspl.knots[k2 - 1].Interpolate(1.0f, cspl.knots[k2]) + lsection.offset;

                pos.x *= lsection.scale.x;
                pos.y *= lsection.scale.y;
                pos.z *= lsection.scale.z;

                pos = tm1.MultiplyPoint3x4(pos + off);
                ms.cverts.Add(pos);
                //pos = tm1.MultiplyPoint3x4(cspl.knots[k2].p + off);
                //ms.cverts.Add(pos);
            }

            // Do uv and col now
            for (int i = 0; i < lsection.meshsections.Count; i++)
            {
                MegaMeshSection ms1 = lsection.meshsections[i];

                ms1.len = 0.0f;
                //int k1 = ms1.firstknot;
                //int k2 = ms1.lastknot;

                //Debug.Log("k1 " + k1 + " k2 " + k2);
                //float l1 = cspl.knots[k2].length - cspl.knots[k1].length;

                Vector2 uv1 = Vector2.zero;
                ms1.cuvs.Add(uv1);
                ms1.ccols.Add(Color.white);

                for (int v = 1; v < ms1.cverts.Count; v++)
                {
                    ms1.len += Vector3.Distance(ms1.cverts[v], ms1.cverts[v - 1]);
                }

                for (int v = 1; v < ms1.cverts.Count; v++)
                {
                    uv1.y += Vector3.Distance(ms1.cverts[v], ms1.cverts[v - 1]) / ms1.len;
                    //uv1.y /= len;	//Vector3.Distance(ms1.cverts[v], ms1.cverts[v - 1]);
                    ms1.cuvs.Add(uv1);
                    ms1.ccols.Add(Color.white);
                }
            }

            // Add end point
            if (cspl.closed)
            {
                alpha = Mathf.Repeat(cend, 1.0f);
            }
        }

        // Calc normals
        Vector3 up = Vector3.zero;
        Vector3 n1 = Vector3.zero;

        for (int i = 0; i < lsection.meshsections.Count; i++)
        {
            MegaMeshSection ms1 = lsection.meshsections[i];

            if (ms1.cverts.Count > 1)
            {
                for (int v = 0; v < ms1.cverts.Count; v++)
                {
                    if (v < ms1.cverts.Count - 1)
                    {
                        n1 = (ms1.cverts[v + 1] - ms1.cverts[v]);
                    }
                    else
                    {
                        n1 = (ms1.cverts[v] - ms1.cverts[v - 1]);
                    }

                    up.x = -n1.y;
                    up.y = n1.x;
                    up.z = 0.0f;
                    ms1.cnorms.Add(up);
                }
            }
        }
    }
Exemple #5
0
    public override int BuildMesh(MegaShapeLoft loft, int triindex)
    {
        if (Lock)
        {
            return(triindex);
        }

        if (layerPath == null || layerPath.splines == null || layerPath.splines.Count == 0)
        {
            return(triindex);
        }

        if (loftsections.Count < 2)             //== 0 )
        {
            return(triindex);
        }

        Vector2 uv = Vector2.zero;
        Vector3 p  = Vector3.zero;

        //int wc = 1;	//ActualCrossVerts;
        float lerp = 0.0f;

        Matrix4x4 pathtm = Matrix4x4.identity;

        //if ( SnapToPath )
        //	pathtm = layerPath.transform.localToWorldMatrix;

        Matrix4x4 twisttm = Matrix4x4.identity;

        //Vector3 sclc = Vector2.one;
        Matrix4x4 tm;

        float offx = 0.0f;
        float offy = 0.0f;
        float offz = 0.0f;

        MegaSpline pathspline = layerPath.splines[curve];

        //bool clsd = layerPath.splines[curve].closed;

        float uvstart = pathStart;

        if (UVOrigin == MegaLoftUVOrigin.SplineStart)
        {
            uvstart = 0.0f;
        }

        Vector3 lastup = locup;

        Color col1 = color;

        float calpha = 0.0f;

        //float uvalpha = 0.0f;

        for (int pi = 0; pi < crosses; pi++)
        {
            float alpha     = (float)pi / (float)(crosses - 1);         //PathSteps;
            float pathalpha = pathStart + (pathLength * alpha);

            //uvalpha = pathalpha;
            //if ( clsd )
            //	pathalpha = Mathf.Repeat(pathalpha, 1.0f);

            //if ( useScaleXCrv )
            //	sclc.x = scaleCrvX.Evaluate(pathalpha);

            //if ( useScaleYCrv )
            //	sclc.y = scaleCrvY.Evaluate(pathalpha);

            if (useTwistCrv)
            {
                float twist = twistCrv.Evaluate(pathalpha);
                float tw1   = layerPath.splines[curve].GetTwist(pathalpha);
                MegaShapeUtils.RotateZ(ref twisttm, Mathf.Deg2Rad * (twist - tw1));
                if (frameMethod == MegaFrameMethod.Old)
                {
                    tm = pathtm * GetDeformMat(layerPath.splines[curve], pathalpha, layerPath.normalizedInterp) * twisttm;
                }
                else
                {
                    tm = pathtm * GetDeformMatNewMethod(layerPath.splines[curve], pathalpha, layerPath.normalizedInterp, ref lastup) * twisttm;
                }
            }
            else
            {
                if (frameMethod == MegaFrameMethod.Old)
                {
                    tm = pathtm * GetDeformMat(layerPath.splines[curve], pathalpha, layerPath.normalizedInterp);
                }
                else
                {
                    tm = pathtm * GetDeformMatNewMethod(layerPath.splines[curve], pathalpha, layerPath.normalizedInterp, ref lastup);
                }
            }
            // Need to get the crosssection for the given alpha and the lerp value
            int csect = GetSection(pathalpha, out lerp);

            lerp = ease.easing(0.0f, 1.0f, lerp);

            MegaLoftSection cs1 = loftsections[csect];
            MegaLoftSection cs2 = loftsections[csect + 1];

            //MegaSpline sectionspline = cs1.shape.splines[cs1.curve];

            if (useOffsetX)
            {
                offx = offsetCrvX.Evaluate(pathalpha);
            }

            if (useOffsetY)
            {
                offy = offsetCrvY.Evaluate(pathalpha);
            }

            if (useOffsetZ)
            {
                offz = offsetCrvZ.Evaluate(pathalpha);
            }

            for (int i = 0; i < cs1.meshsections.Count; i++)
            {
                MegaMeshSection ms0 = loftsections[0].meshsections[i];

                //float slen = sectionspline.knots[ms0.lastknot].length - sectionspline.knots[ms0.firstknot].length;

                MegaMaterialSection mats = sections[ms0.mat];

                if (mats.Enabled)
                {
                    MegaMeshSection ms1 = cs1.meshsections[i];
                    MegaMeshSection ms2 = cs2.meshsections[i];

                    if (loft.useColors)
                    {
                        if (mats.colmode == MegaLoftColMode.Loft)
                        {
                            calpha = alpha;
                        }
                        else
                        {
                            calpha = pathalpha;
                        }

                        calpha = Mathf.Repeat(calpha + mats.coloffset, 1.0f);
                        col1.r = mats.colR.Evaluate(calpha);
                        col1.g = mats.colG.Evaluate(calpha);
                        col1.b = mats.colB.Evaluate(calpha);
                        col1.a = mats.colA.Evaluate(calpha);
                    }

                    for (int v = 0; v < ms1.cverts.Count; v++)
                    {
                        p = Vector3.Lerp(ms1.cverts[v], ms2.cverts[v], lerp);                           // Easing here?
                        //if ( useScaleXCrv )
                        //	p.x *= sclc.x;

                        //if ( useScaleYCrv )
                        //	p.y *= sclc.y;

                        p.x += offx;
                        p.y += offy;
                        p.z += offz;

                        p = tm.MultiplyPoint3x4(p);

                        p += offset;

                        //int ix = (pi * wc) + v;
                        if (conform)
                        {
                            ms0.verts1.Add(p);
                        }
                        else
                        {
                            ms0.verts.Add(p);
                        }

                        uv.y = Mathf.Lerp(ms1.cuvs[v].y, ms2.cuvs[v].y, lerp);

                        uv.x = alpha - uvstart;                         //pathStart;
                        //uv.y = ms.cuvs[v].y;	// - crossStart;	// again not sure here start;

                        if (mats.physuv)
                        {
                            uv.x *= pathspline.length;
                            uv.y *= ms0.len;                                    //sectionspline.length;
                        }
                        else
                        {
                            if (mats.uvcalcy)
                            {
                                //uv.x = ((alpha * LoftLength) / sectionspline.length) - uvstart;
                                uv.x = ((alpha * pathspline.length) / ms0.len) - uvstart;
                            }
                        }

                        if (mats.swapuv)
                        {
                            float ux = uv.x;
                            uv.x = uv.y;
                            uv.y = ux;
                        }

                        uv.x *= mats.UVScale.x;
                        uv.y *= mats.UVScale.y;

                        uv.x += mats.UVOffset.x;
                        uv.y += mats.UVOffset.y;

                        ms0.uvs.Add(uv);                                //[vi] = uv;

                        if (loft.useColors)
                        {
                            ms0.cols.Add(col1);
                        }

#if false
                        uv.y = uvstart + alpha;

                        uv.x *= UVScale.x;
                        uv.y *= UVScale.y;

                        uv.x += UVOffset.x;
                        uv.y += UVOffset.y;
#endif
                        //ms0.uvs.Add(uv);
                    }
                }
            }
        }

        int index = triindex;
        int fi    = 0;          // Calc this

        if (enabled)
        {
            if (flip)
            {
                for (int m = 0; m < loftsections[0].meshsections.Count; m++)
                {
                    MegaMeshSection     ms   = loftsections[0].meshsections[m];
                    MegaMaterialSection mats = sections[ms.mat];

                    if (mats.Enabled)
                    {
                        for (int cr = 0; cr < crosses - 1; cr++)
                        {
                            for (int f = 0; f < ms.cverts.Count - 1; f++)
                            {
                                ms.tris.Add(index + f);
                                ms.tris.Add(index + f + 1);
                                ms.tris.Add(index + f + 1 + ms.cverts.Count);

                                ms.tris.Add(index + f);
                                ms.tris.Add(index + f + 1 + ms.cverts.Count);
                                ms.tris.Add(index + f + ms.cverts.Count);

                                fi += 6;
                            }

                            index += ms.cverts.Count;
                        }
                        index += ms.cverts.Count;
                    }
                }
            }
            else
            {
                for (int m = 0; m < loftsections[0].meshsections.Count; m++)
                {
                    MegaMeshSection     ms   = loftsections[0].meshsections[m];
                    MegaMaterialSection mats = sections[ms.mat];

                    if (mats.Enabled)
                    {
                        for (int cr = 0; cr < crosses - 1; cr++)
                        {
                            for (int f = 0; f < ms.cverts.Count - 1; f++)
                            {
                                ms.tris.Add(index + f + 1 + ms.cverts.Count);
                                ms.tris.Add(index + f + 1);
                                ms.tris.Add(index + f);

                                ms.tris.Add(index + f + ms.cverts.Count);
                                ms.tris.Add(index + f + 1 + ms.cverts.Count);
                                ms.tris.Add(index + f);

                                fi += 6;
                            }

                            index += ms.cverts.Count;
                        }

                        index += ms.cverts.Count;
                    }
                }
            }
        }

        if (conform)
        {
            CalcBounds();
            DoConform(loft);
        }

        return(triindex + fi);          //triindex;
    }
    void OnGUI()
    {
        if (Selection.activeGameObject == null)
        {
            return;
        }

        MegaShapeLoft loft = Selection.activeGameObject.GetComponent <MegaShapeLoft>();

        if (loft == null)
        {
            return;
        }

        lofttype  = (MegaLoftType)EditorGUILayout.EnumPopup("Type", lofttype);
        LayerName = EditorGUILayout.TextField("Name", LayerName);
        start     = EditorGUILayout.FloatField("Start", start);
        length    = EditorGUILayout.FloatField("Length", length);
        paramCol  = EditorGUILayout.ColorField("Param Col", paramCol);

        EditorStyles.textField.wordWrap = true;

        switch (lofttype)
        {
        case MegaLoftType.Simple:
            EditorGUILayout.TextArea("Basic Loft layer that uses a single spline for the path and another spline for the cross section", GUILayout.Height(50.0f));
            path     = (MegaShape)EditorGUILayout.ObjectField("Path", path, typeof(MegaShape), true);
            section  = (MegaShape)EditorGUILayout.ObjectField("Section", section, typeof(MegaShape), true);
            material = (Material)EditorGUILayout.ObjectField("Material", material, typeof(Material), true);
            break;

        //case MegaLoftType.Collider:
        //	colliderwidth = EditorGUILayout.FloatField("Collider Width", colliderwidth);
        //	break;

        case MegaLoftType.CloneSimple:
            EditorGUILayout.TextArea("Clone a mesh onto a surface with options for start, end and main meshes", GUILayout.Height(50.0f));
            startObjMesh = (Mesh)EditorGUILayout.ObjectField("Start Obj", startObjMesh, typeof(Mesh), true);
            mainObjMesh  = (Mesh)EditorGUILayout.ObjectField("Main Obj", mainObjMesh, typeof(Mesh), true);
            endObjMesh   = (Mesh)EditorGUILayout.ObjectField("End Obj", endObjMesh, typeof(Mesh), true);
            surfaceLoft  = (MegaShapeLoft)EditorGUILayout.ObjectField("Surface", surfaceLoft, typeof(MegaShapeLoft), true);
            surfaceLayer = EditorGUILayout.Popup("Layer", surfaceLayer + 1, MegaShapeUtils.GetLayers(surfaceLoft)) - 1;
            material     = (Material)EditorGUILayout.ObjectField("Material", material, typeof(Material), true);
            break;

        case MegaLoftType.ScatterSimple:
            EditorGUILayout.TextArea("Scatters a choosen mesh and material over a surface", GUILayout.Height(50.0f));
            mainObjMesh  = (Mesh)EditorGUILayout.ObjectField("Obj", mainObjMesh, typeof(Mesh), true);
            surfaceLoft  = (MegaShapeLoft)EditorGUILayout.ObjectField("Surface", surfaceLoft, typeof(MegaShapeLoft), true);
            surfaceLayer = EditorGUILayout.Popup("Layer", surfaceLayer + 1, MegaShapeUtils.GetLayers(surfaceLoft)) - 1;
            material     = (Material)EditorGUILayout.ObjectField("Material", material, typeof(Material), true);
            break;

        case MegaLoftType.Scatter:
            EditorGUILayout.TextArea("Builds a mesh layer by scattering a choosen object over a surface", GUILayout.Height(50.0f));
            mainObj      = (GameObject)EditorGUILayout.ObjectField("Obj", mainObj, typeof(Mesh), true);
            mainObj      = MegaMeshCheck.ValidateObj(mainObj);
            surfaceLoft  = (MegaShapeLoft)EditorGUILayout.ObjectField("Surface", surfaceLoft, typeof(MegaShapeLoft), true);
            surfaceLayer = EditorGUILayout.Popup("Layer", surfaceLayer + 1, MegaShapeUtils.GetLayers(surfaceLoft)) - 1;
            break;

        case MegaLoftType.ScatterSpline:
            EditorGUILayout.TextArea("Build a mesh by scattering a choosen mesh and material along a spline", GUILayout.Height(50.0f));
            path        = (MegaShape)EditorGUILayout.ObjectField("Path", path, typeof(MegaShape), true);
            mainObjMesh = (Mesh)EditorGUILayout.ObjectField("Obj", mainObjMesh, typeof(Mesh), true);
            material    = (Material)EditorGUILayout.ObjectField("Material", material, typeof(Material), true);
            break;

        case MegaLoftType.Complex:
            EditorGUILayout.TextArea("Advanced lofter that uses a spline for the path and any number of cross section splines to define the loft", GUILayout.Height(50.0f));
            path     = (MegaShape)EditorGUILayout.ObjectField("Path", path, typeof(MegaShape), true);
            section  = (MegaShape)EditorGUILayout.ObjectField("Section", section, typeof(MegaShape), true);
            material = (Material)EditorGUILayout.ObjectField("Material", material, typeof(Material), true);
            break;

        case MegaLoftType.CloneSplineSimple:
            EditorGUILayout.TextArea("Clone a mesh along a spline with options for start, end and main meshes", GUILayout.Height(50.0f));
            path         = (MegaShape)EditorGUILayout.ObjectField("Path", path, typeof(MegaShape), true);
            startObjMesh = (Mesh)EditorGUILayout.ObjectField("Start Obj", startObjMesh, typeof(Mesh), true);
            //startObj = MegaMeshCheck.ValidateObj(startObj);
            mainObjMesh = (Mesh)EditorGUILayout.ObjectField("Main Obj", mainObjMesh, typeof(Mesh), true);
            //mainObj = MegaMeshCheck.ValidateObj(mainObj);
            endObjMesh = (Mesh)EditorGUILayout.ObjectField("End Obj", endObjMesh, typeof(Mesh), true);
            //endObj = MegaMeshCheck.ValidateObj(endObj);
            material = (Material)EditorGUILayout.ObjectField("Material", material, typeof(Material), true);
            break;

        case MegaLoftType.Clone:
            EditorGUILayout.TextArea("Clone a mesh onto a surface with options for start, end and main meshes", GUILayout.Height(50.0f));
            startObj     = (GameObject)EditorGUILayout.ObjectField("Start Obj", startObj, typeof(GameObject), true);
            startObj     = MegaMeshCheck.ValidateObj(startObj);
            mainObj      = (GameObject)EditorGUILayout.ObjectField("Main Obj", mainObj, typeof(GameObject), true);
            mainObj      = MegaMeshCheck.ValidateObj(mainObj);
            endObj       = (GameObject)EditorGUILayout.ObjectField("End Obj", endObj, typeof(GameObject), true);
            endObj       = MegaMeshCheck.ValidateObj(endObj);
            surfaceLoft  = (MegaShapeLoft)EditorGUILayout.ObjectField("Surface", surfaceLoft, typeof(MegaShapeLoft), true);
            surfaceLayer = EditorGUILayout.Popup("Layer", surfaceLayer + 1, MegaShapeUtils.GetLayers(surfaceLoft)) - 1;
            material     = (Material)EditorGUILayout.ObjectField("Material", material, typeof(Material), true);

            break;

        case MegaLoftType.CloneSpline:
            EditorGUILayout.TextArea("Build a mesh layer by cloning objects along a spline with options for start, end and main objects", GUILayout.Height(50.0f));
            path     = (MegaShape)EditorGUILayout.ObjectField("Path", path, typeof(MegaShape), true);
            startObj = (GameObject)EditorGUILayout.ObjectField("Start Obj", startObj, typeof(GameObject), true);
            startObj = MegaMeshCheck.ValidateObj(startObj);
            mainObj  = (GameObject)EditorGUILayout.ObjectField("Main Obj", mainObj, typeof(GameObject), true);
            mainObj  = MegaMeshCheck.ValidateObj(mainObj);
            endObj   = (GameObject)EditorGUILayout.ObjectField("End Obj", endObj, typeof(GameObject), true);
            endObj   = MegaMeshCheck.ValidateObj(endObj);
            break;

        case MegaLoftType.CloneRules:
            EditorGUILayout.TextArea("Rule based clone onto a surface", GUILayout.Height(50.0f));
            //path = (MegaShape)EditorGUILayout.ObjectField("Path", path, typeof(MegaShape), true);
            surfaceLoft  = (MegaShapeLoft)EditorGUILayout.ObjectField("Surface", surfaceLoft, typeof(MegaShapeLoft), true);
            surfaceLayer = EditorGUILayout.Popup("Layer", surfaceLayer + 1, MegaShapeUtils.GetLayers(surfaceLoft)) - 1;
            break;

        case MegaLoftType.CloneSplineRules:
            EditorGUILayout.TextArea("Rule based clone along a spline", GUILayout.Height(50.0f));
            path         = (MegaShape)EditorGUILayout.ObjectField("Path", path, typeof(MegaShape), true);
            surfaceLoft  = (MegaShapeLoft)EditorGUILayout.ObjectField("Surface", surfaceLoft, typeof(MegaShapeLoft), true);
            surfaceLayer = EditorGUILayout.Popup("Layer", surfaceLayer + 1, MegaShapeUtils.GetLayers(surfaceLoft)) - 1;
            break;

#if true
        case MegaLoftType.MultiMaterial:
            EditorGUILayout.TextArea("Will create a loft using multiple materials based on material ids in the spline knots. It uses a single spline for the path and another spline for the cross section", GUILayout.Height(50.0f));
            path     = (MegaShape)EditorGUILayout.ObjectField("Path", path, typeof(MegaShape), true);
            section  = (MegaShape)EditorGUILayout.ObjectField("Section", section, typeof(MegaShape), true);
            material = (Material)EditorGUILayout.ObjectField("Material", material, typeof(Material), true);
            break;

        case MegaLoftType.MultiMaterialComplex:
            EditorGUILayout.TextArea("Will create a complex loft using multiple materials based on material ids in the spline knots. It uses a single spline for the path and another spline for the cross section", GUILayout.Height(50.0f));
            path     = (MegaShape)EditorGUILayout.ObjectField("Path", path, typeof(MegaShape), true);
            section  = (MegaShape)EditorGUILayout.ObjectField("Section", section, typeof(MegaShape), true);
            material = (Material)EditorGUILayout.ObjectField("Material", material, typeof(Material), true);
            break;
#endif
        }

        EditorStyles.textField.wordWrap = false;

        EditorGUILayout.BeginHorizontal();
        if (GUILayout.Button("Create"))
        {
            MegaLoftLayerBase laybase = null;

            switch (lofttype)
            {
            case MegaLoftType.Simple:
            {
                MegaLoftLayerSimple layer = Selection.activeGameObject.AddComponent <MegaLoftLayerSimple>();
                layer.pathStart    = start;
                layer.pathLength   = length;
                layer.layerPath    = path;
                layer.layerSection = section;
                laybase            = layer;
            }
            break;

            case MegaLoftType.CloneSimple:
            {
                MegaLoftLayerCloneSimple layer = Selection.activeGameObject.AddComponent <MegaLoftLayerCloneSimple>();
                layer.startObj     = startObjMesh;
                layer.mainObj      = mainObjMesh;
                layer.endObj       = endObjMesh;
                layer.surfaceLoft  = surfaceLoft;
                layer.surfaceLayer = surfaceLayer;
                laybase            = layer;
            }
            break;

            case MegaLoftType.ScatterSimple:
            {
                MegaLoftLayerScatterSimple layer = Selection.activeGameObject.AddComponent <MegaLoftLayerScatterSimple>();
                layer.scatterMesh  = mainObjMesh;
                layer.surfaceLoft  = surfaceLoft;
                layer.surfaceLayer = surfaceLayer;
                laybase            = layer;
            }
            break;

            case MegaLoftType.Scatter:
            {
                MegaLoftLayerScatter layer = Selection.activeGameObject.AddComponent <MegaLoftLayerScatter>();
                layer.mainObj      = mainObj;
                layer.surfaceLoft  = surfaceLoft;
                layer.surfaceLayer = surfaceLayer;
                laybase            = layer;
            }
            break;

            case MegaLoftType.ScatterSpline:
            {
                MegaLoftLayerScatterSpline layer = Selection.activeGameObject.AddComponent <MegaLoftLayerScatterSpline>();
                layer.scatterMesh = mainObjMesh;
                layer.layerPath   = path;
                laybase           = layer;
            }
            break;

            case MegaLoftType.Complex:
            {
                MegaLoftLayerComplex layer = Selection.activeGameObject.AddComponent <MegaLoftLayerComplex>();
                layer.layerPath    = path;
                layer.layerSection = section;
                laybase            = layer;
            }
            break;

            case MegaLoftType.CloneSplineSimple:
            {
                MegaLoftLayerCloneSplineSimple layer = Selection.activeGameObject.AddComponent <MegaLoftLayerCloneSplineSimple>();
                layer.layerPath = path;
                layer.startObj  = startObjMesh;
                layer.mainObj   = mainObjMesh;
                layer.endObj    = endObjMesh;
                laybase         = layer;
            }
            break;

            case MegaLoftType.CloneSpline:
            {
                MegaLoftLayerCloneSpline layer = Selection.activeGameObject.AddComponent <MegaLoftLayerCloneSpline>();
                layer.layerPath = path;
                layer.startObj  = startObj;
                layer.mainObj   = mainObj;
                layer.endObj    = endObj;
                laybase         = layer;
            }
            break;

            case MegaLoftType.Clone:
            {
                MegaLoftLayerClone layer = Selection.activeGameObject.AddComponent <MegaLoftLayerClone>();
                layer.surfaceLoft  = surfaceLoft;
                layer.surfaceLayer = surfaceLayer;
                layer.startObj     = startObj;
                layer.mainObj      = mainObj;
                layer.endObj       = endObj;
                laybase            = layer;
            }
            break;

            case MegaLoftType.CloneRules:
            {
                MegaLoftLayerCloneRules layer = Selection.activeGameObject.AddComponent <MegaLoftLayerCloneRules>();
                layer.surfaceLoft  = surfaceLoft;
                layer.surfaceLayer = surfaceLayer;
                //layer.layerPath = path;
                //layer.layerSection = section;
                laybase = layer;
            }
            break;

            case MegaLoftType.CloneSplineRules:
            {
                MegaLoftLayerCloneSplineRules layer = Selection.activeGameObject.AddComponent <MegaLoftLayerCloneSplineRules>();
                layer.layerPath = path;
                laybase         = layer;
            }
            break;

#if true
            case MegaLoftType.MultiMaterial:
            {
                MegaLoftLayerMultiMat layer = Selection.activeGameObject.AddComponent <MegaLoftLayerMultiMat>();
                layer.pathStart    = start;
                layer.pathLength   = length;
                layer.layerPath    = path;
                layer.layerSection = section;
                MegaMaterialSection ms = new MegaMaterialSection();
                ms.mat = material;
                layer.sections.Add(ms);
                laybase = layer;
            }
            break;

            // We should add two loft sections
            // if cross has multiple splines add them all equally spaced?
            case MegaLoftType.MultiMaterialComplex:
            {
                MegaLoftLayerMultiMatComplex layer = Selection.activeGameObject.AddComponent <MegaLoftLayerMultiMatComplex>();
                layer.pathStart    = start;
                layer.pathLength   = length;
                layer.layerPath    = path;
                layer.layerSection = section;
                MegaMaterialSection ms = new MegaMaterialSection();
                ms.mat = material;
                layer.sections.Add(ms);
                laybase = layer;
            }
            break;
#endif
            default:
                EditorUtility.DisplayDialog("Layer Not Supported", "Currently this layer type is not not supported", "OK");
                break;
            }

            // Common params
            if (laybase)
            {
                laybase.paramcol  = paramCol;
                laybase.LayerName = LayerName;
                laybase.LayerName = LayerName;
                laybase.material  = material;
            }
            this.Close();
        }

        if (GUILayout.Button("Cancel"))
        {
            this.Close();
        }
        EditorGUILayout.EndHorizontal();
    }
    void OnGUI()
    {
        if ( Selection.activeGameObject == null )
            return;

        MegaShapeLoft loft = Selection.activeGameObject.GetComponent<MegaShapeLoft>();
        if ( loft == null )
            return;

        lofttype	= (MegaLoftType)EditorGUILayout.EnumPopup("Type", lofttype);
        LayerName	= EditorGUILayout.TextField("Name", LayerName);
        start		= EditorGUILayout.FloatField("Start", start);
        length		= EditorGUILayout.FloatField("Length", length);
        paramCol	= EditorGUILayout.ColorField("Param Col", paramCol);

        EditorStyles.textField.wordWrap = true;

        switch ( lofttype )
        {
            case MegaLoftType.Simple:
                EditorGUILayout.TextArea("Basic Loft layer that uses a single spline for the path and another spline for the cross section", GUILayout.Height(50.0f));
                path		= (MegaShape)EditorGUILayout.ObjectField("Path", path, typeof(MegaShape), true);
                section		= (MegaShape)EditorGUILayout.ObjectField("Section", section, typeof(MegaShape), true);
                material	= (Material)EditorGUILayout.ObjectField("Material", material, typeof(Material), true);
                break;

            //case MegaLoftType.Collider:
            //	colliderwidth = EditorGUILayout.FloatField("Collider Width", colliderwidth);
            //	break;

            case MegaLoftType.CloneSimple:
                EditorGUILayout.TextArea("Clone a mesh onto a surface with options for start, end and main meshes", GUILayout.Height(50.0f));
                startObjMesh = (Mesh)EditorGUILayout.ObjectField("Start Obj", startObjMesh, typeof(Mesh), true);
                mainObjMesh		= (Mesh)EditorGUILayout.ObjectField("Main Obj", mainObjMesh, typeof(Mesh), true);
                endObjMesh		= (Mesh)EditorGUILayout.ObjectField("End Obj", endObjMesh, typeof(Mesh), true);
                surfaceLoft	= (MegaShapeLoft)EditorGUILayout.ObjectField("Surface", surfaceLoft, typeof(MegaShapeLoft), true);
                surfaceLayer = EditorGUILayout.Popup("Layer", surfaceLayer + 1, MegaShapeUtils.GetLayers(surfaceLoft)) - 1;
                material = (Material)EditorGUILayout.ObjectField("Material", material, typeof(Material), true);
                break;

            case MegaLoftType.ScatterSimple:
                EditorGUILayout.TextArea("Scatters a choosen mesh and material over a surface", GUILayout.Height(50.0f));
                mainObjMesh = (Mesh)EditorGUILayout.ObjectField("Obj", mainObjMesh, typeof(Mesh), true);
                surfaceLoft		= (MegaShapeLoft)EditorGUILayout.ObjectField("Surface", surfaceLoft, typeof(MegaShapeLoft), true);
                surfaceLayer	= EditorGUILayout.Popup("Layer", surfaceLayer + 1, MegaShapeUtils.GetLayers(surfaceLoft)) - 1;
                material = (Material)EditorGUILayout.ObjectField("Material", material, typeof(Material), true);
                break;

            case MegaLoftType.Scatter:
                EditorGUILayout.TextArea("Builds a mesh layer by scattering a choosen object over a surface", GUILayout.Height(50.0f));
                mainObj = (GameObject)EditorGUILayout.ObjectField("Obj", mainObj, typeof(Mesh), true);
                mainObj = MegaMeshCheck.ValidateObj(mainObj);
                surfaceLoft = (MegaShapeLoft)EditorGUILayout.ObjectField("Surface", surfaceLoft, typeof(MegaShapeLoft), true);
                surfaceLayer = EditorGUILayout.Popup("Layer", surfaceLayer + 1, MegaShapeUtils.GetLayers(surfaceLoft)) - 1;
                break;

            case MegaLoftType.ScatterSpline:
                EditorGUILayout.TextArea("Build a mesh by scattering a choosen mesh and material along a spline", GUILayout.Height(50.0f));
                path = (MegaShape)EditorGUILayout.ObjectField("Path", path, typeof(MegaShape), true);
                mainObjMesh = (Mesh)EditorGUILayout.ObjectField("Obj", mainObjMesh, typeof(Mesh), true);
                material = (Material)EditorGUILayout.ObjectField("Material", material, typeof(Material), true);
                break;

            case MegaLoftType.Complex:
                EditorGUILayout.TextArea("Advanced lofter that uses a spline for the path and any number of cross section splines to define the loft", GUILayout.Height(50.0f));
                path		= (MegaShape)EditorGUILayout.ObjectField("Path", path, typeof(MegaShape), true);
                section		= (MegaShape)EditorGUILayout.ObjectField("Section", section, typeof(MegaShape), true);
                material	= (Material)EditorGUILayout.ObjectField("Material", material, typeof(Material), true);
                break;

            case MegaLoftType.CloneSplineSimple:
                EditorGUILayout.TextArea("Clone a mesh along a spline with options for start, end and main meshes", GUILayout.Height(50.0f));
                path = (MegaShape)EditorGUILayout.ObjectField("Path", path, typeof(MegaShape), true);
                startObjMesh = (Mesh)EditorGUILayout.ObjectField("Start Obj", startObjMesh, typeof(Mesh), true);
                //startObj = MegaMeshCheck.ValidateObj(startObj);
                mainObjMesh = (Mesh)EditorGUILayout.ObjectField("Main Obj", mainObjMesh, typeof(Mesh), true);
                //mainObj = MegaMeshCheck.ValidateObj(mainObj);
                endObjMesh = (Mesh)EditorGUILayout.ObjectField("End Obj", endObjMesh, typeof(Mesh), true);
                //endObj = MegaMeshCheck.ValidateObj(endObj);
                material = (Material)EditorGUILayout.ObjectField("Material", material, typeof(Material), true);
                break;

            case MegaLoftType.Clone:
                EditorGUILayout.TextArea("Clone a mesh onto a surface with options for start, end and main meshes", GUILayout.Height(50.0f));
                startObj = (GameObject)EditorGUILayout.ObjectField("Start Obj", startObj, typeof(GameObject), true);
                startObj = MegaMeshCheck.ValidateObj(startObj);
                mainObj = (GameObject)EditorGUILayout.ObjectField("Main Obj", mainObj, typeof(GameObject), true);
                mainObj = MegaMeshCheck.ValidateObj(mainObj);
                endObj = (GameObject)EditorGUILayout.ObjectField("End Obj", endObj, typeof(GameObject), true);
                endObj = MegaMeshCheck.ValidateObj(endObj);
                surfaceLoft = (MegaShapeLoft)EditorGUILayout.ObjectField("Surface", surfaceLoft, typeof(MegaShapeLoft), true);
                surfaceLayer = EditorGUILayout.Popup("Layer", surfaceLayer + 1, MegaShapeUtils.GetLayers(surfaceLoft)) - 1;
                material = (Material)EditorGUILayout.ObjectField("Material", material, typeof(Material), true);

                break;

            case MegaLoftType.CloneSpline:
                EditorGUILayout.TextArea("Build a mesh layer by cloning objects along a spline with options for start, end and main objects", GUILayout.Height(50.0f));
                path = (MegaShape)EditorGUILayout.ObjectField("Path", path, typeof(MegaShape), true);
                startObj = (GameObject)EditorGUILayout.ObjectField("Start Obj", startObj, typeof(GameObject), true);
                startObj = MegaMeshCheck.ValidateObj(startObj);
                mainObj = (GameObject)EditorGUILayout.ObjectField("Main Obj", mainObj, typeof(GameObject), true);
                mainObj = MegaMeshCheck.ValidateObj(mainObj);
                endObj = (GameObject)EditorGUILayout.ObjectField("End Obj", endObj, typeof(GameObject), true);
                endObj = MegaMeshCheck.ValidateObj(endObj);
                break;

            case MegaLoftType.CloneRules:
                EditorGUILayout.TextArea("Rule based clone onto a surface", GUILayout.Height(50.0f));
                //path = (MegaShape)EditorGUILayout.ObjectField("Path", path, typeof(MegaShape), true);
                surfaceLoft = (MegaShapeLoft)EditorGUILayout.ObjectField("Surface", surfaceLoft, typeof(MegaShapeLoft), true);
                surfaceLayer = EditorGUILayout.Popup("Layer", surfaceLayer + 1, MegaShapeUtils.GetLayers(surfaceLoft)) - 1;
                break;

            case MegaLoftType.CloneSplineRules:
                EditorGUILayout.TextArea("Rule based clone along a spline", GUILayout.Height(50.0f));
                path = (MegaShape)EditorGUILayout.ObjectField("Path", path, typeof(MegaShape), true);
                surfaceLoft = (MegaShapeLoft)EditorGUILayout.ObjectField("Surface", surfaceLoft, typeof(MegaShapeLoft), true);
                surfaceLayer = EditorGUILayout.Popup("Layer", surfaceLayer + 1, MegaShapeUtils.GetLayers(surfaceLoft)) - 1;
                break;

        #if true
            case MegaLoftType.MultiMaterial:
                EditorGUILayout.TextArea("Will create a loft using multiple materials based on material ids in the spline knots. It uses a single spline for the path and another spline for the cross section", GUILayout.Height(50.0f));
                path = (MegaShape)EditorGUILayout.ObjectField("Path", path, typeof(MegaShape), true);
                section = (MegaShape)EditorGUILayout.ObjectField("Section", section, typeof(MegaShape), true);
                material = (Material)EditorGUILayout.ObjectField("Material", material, typeof(Material), true);
                break;

            case MegaLoftType.MultiMaterialComplex:
                EditorGUILayout.TextArea("Will create a complex loft using multiple materials based on material ids in the spline knots. It uses a single spline for the path and another spline for the cross section", GUILayout.Height(50.0f));
                path = (MegaShape)EditorGUILayout.ObjectField("Path", path, typeof(MegaShape), true);
                section = (MegaShape)EditorGUILayout.ObjectField("Section", section, typeof(MegaShape), true);
                material = (Material)EditorGUILayout.ObjectField("Material", material, typeof(Material), true);
                break;
        #endif
        }

        EditorStyles.textField.wordWrap = false;

        EditorGUILayout.BeginHorizontal();
        if ( GUILayout.Button("Create") )
        {
            MegaLoftLayerBase laybase = null;

            switch ( lofttype )
            {
                case MegaLoftType.Simple:
                    {
                        MegaLoftLayerSimple layer = Selection.activeGameObject.AddComponent<MegaLoftLayerSimple>();
                        layer.pathStart		= start;
                        layer.pathLength	= length;
                        layer.layerPath		= path;
                        layer.layerSection	= section;
                        laybase = layer;
                    }
                    break;

                case MegaLoftType.CloneSimple:
                    {
                        MegaLoftLayerCloneSimple layer = Selection.activeGameObject.AddComponent<MegaLoftLayerCloneSimple>();
                        layer.startObj		= startObjMesh;
                        layer.mainObj		= mainObjMesh;
                        layer.endObj		= endObjMesh;
                        layer.surfaceLoft	= surfaceLoft;
                        layer.surfaceLayer	= surfaceLayer;
                        laybase = layer;
                    }
                    break;

                case MegaLoftType.ScatterSimple:
                    {
                        MegaLoftLayerScatterSimple layer = Selection.activeGameObject.AddComponent<MegaLoftLayerScatterSimple>();
                        layer.scatterMesh	= mainObjMesh;
                        layer.surfaceLoft	= surfaceLoft;
                        layer.surfaceLayer	= surfaceLayer;
                        laybase = layer;
                    }
                    break;

                case MegaLoftType.Scatter:
                    {
                        MegaLoftLayerScatter layer = Selection.activeGameObject.AddComponent<MegaLoftLayerScatter>();
                        layer.mainObj		= mainObj;
                        layer.surfaceLoft	= surfaceLoft;
                        layer.surfaceLayer	= surfaceLayer;
                        laybase = layer;
                    }
                    break;

                case MegaLoftType.ScatterSpline:
                    {
                        MegaLoftLayerScatterSpline layer = Selection.activeGameObject.AddComponent<MegaLoftLayerScatterSpline>();
                        layer.scatterMesh	= mainObjMesh;
                        layer.layerPath		= path;
                        laybase = layer;
                    }
                    break;

                case MegaLoftType.Complex:
                    {
                        MegaLoftLayerComplex layer = Selection.activeGameObject.AddComponent<MegaLoftLayerComplex>();
                        layer.layerPath		= path;
                        layer.layerSection	= section;
                        laybase = layer;
                    }
                    break;

                case MegaLoftType.CloneSplineSimple:
                    {
                        MegaLoftLayerCloneSplineSimple layer = Selection.activeGameObject.AddComponent<MegaLoftLayerCloneSplineSimple>();
                        layer.layerPath	= path;
                        layer.startObj	= startObjMesh;
                        layer.mainObj	= mainObjMesh;
                        layer.endObj	= endObjMesh;
                        laybase = layer;
                    }
                    break;

                case MegaLoftType.CloneSpline:
                    {
                        MegaLoftLayerCloneSpline layer = Selection.activeGameObject.AddComponent<MegaLoftLayerCloneSpline>();
                        layer.layerPath	= path;
                        layer.startObj	= startObj;
                        layer.mainObj	= mainObj;
                        layer.endObj	= endObj;
                        laybase = layer;
                    }
                    break;

                case MegaLoftType.Clone:
                    {
                        MegaLoftLayerClone layer = Selection.activeGameObject.AddComponent<MegaLoftLayerClone>();
                        layer.surfaceLoft = surfaceLoft;
                        layer.surfaceLayer = surfaceLayer;
                        layer.startObj = startObj;
                        layer.mainObj = mainObj;
                        layer.endObj = endObj;
                        laybase = layer;
                    }
                    break;

                case MegaLoftType.CloneRules:
                    {
                        MegaLoftLayerCloneRules layer = Selection.activeGameObject.AddComponent<MegaLoftLayerCloneRules>();
                        layer.surfaceLoft = surfaceLoft;
                        layer.surfaceLayer = surfaceLayer;
                        //layer.layerPath = path;
                        //layer.layerSection = section;
                        laybase = layer;
                    }
                    break;

                case MegaLoftType.CloneSplineRules:
                    {
                        MegaLoftLayerCloneSplineRules layer = Selection.activeGameObject.AddComponent<MegaLoftLayerCloneSplineRules>();
                        layer.layerPath = path;
                        laybase = layer;
                    }
                    break;
        #if true
                case MegaLoftType.MultiMaterial:
                    {
                        MegaLoftLayerMultiMat layer = Selection.activeGameObject.AddComponent<MegaLoftLayerMultiMat>();
                        layer.pathStart = start;
                        layer.pathLength = length;
                        layer.layerPath = path;
                        layer.layerSection = section;
                        MegaMaterialSection ms = new MegaMaterialSection();
                        ms.mat = material;
                        layer.sections.Add(ms);
                        laybase = layer;
                    }
                    break;

                    // We should add two loft sections
                    // if cross has multiple splines add them all equally spaced?
                case MegaLoftType.MultiMaterialComplex:
                    {
                        MegaLoftLayerMultiMatComplex layer = Selection.activeGameObject.AddComponent<MegaLoftLayerMultiMatComplex>();
                        layer.pathStart = start;
                        layer.pathLength = length;
                        layer.layerPath = path;
                        layer.layerSection = section;
                        MegaMaterialSection ms = new MegaMaterialSection();
                        ms.mat = material;
                        layer.sections.Add(ms);
                        laybase = layer;
                    }
                    break;
        #endif
                default:
                    EditorUtility.DisplayDialog("Layer Not Supported", "Currently this layer type is not not supported", "OK");
                    break;
            }

            // Common params
            if ( laybase )
            {
                laybase.paramcol	= paramCol;
                laybase.LayerName	= LayerName;
                laybase.LayerName	= LayerName;
                laybase.material	= material;
            }
            this.Close();
        }

        if ( GUILayout.Button("Cancel") )
        {
            this.Close();
        }
        EditorGUILayout.EndHorizontal();
    }
	void DisplayMaterialSections(MegaLoftLayerMultiMatComplex layer)
	{
		if ( GUILayout.Button("Add Material") )
		{
			MegaMaterialSection ms = new MegaMaterialSection();
			layer.sections.Add(ms);
			EditorUtility.SetDirty(target);
		}

		for ( int i = 0; i < layer.sections.Count; i++ )
		{
			MegaMaterialSection ms = layer.sections[i];

			string name = "Mat " + ms.id;
			if ( ms.mat )
			{
				name += " " + ms.mat.name;
			}

			EditorGUILayout.BeginVertical("box");
			ms.show = EditorGUILayout.Foldout(ms.show, name);
			if ( ms.show )
			{
				ms.Enabled = EditorGUILayout.BeginToggleGroup("Enabled", ms.Enabled);
				ms.id = EditorGUILayout.IntField("ID", ms.id);
				ms.mat = (Material)EditorGUILayout.ObjectField("Material", ms.mat, typeof(Material), true);
				//ms.cdist = EditorGUILayout.Slider(MegaToolTip.CrossDist, ms.cdist, cdl, cdh);	//0.025f, 1.0f);
				ms.steps = EditorGUILayout.IntSlider("Divs", ms.steps, 1, 4);	//0.025f, 1.0f);

				ms.UVOffset = EditorGUILayout.Vector2Field("UV Offset", ms.UVOffset);
				ms.UVScale = EditorGUILayout.Vector2Field("UV Scale", ms.UVScale);
				ms.swapuv = EditorGUILayout.Toggle(MegaToolTip.SwapUV, ms.swapuv);
				ms.physuv = EditorGUILayout.Toggle(MegaToolTip.PhysicalUV, ms.physuv);
				ms.uvcalcy = EditorGUILayout.Toggle("Calc Y", ms.uvcalcy);

				ms.colmode = (MegaLoftColMode)EditorGUILayout.EnumPopup("Color Mode", ms.colmode);
				ms.coloffset = EditorGUILayout.FloatField("Offset", ms.coloffset);
				ms.color = EditorGUILayout.ColorField("Color", ms.color);
				ms.colR = EditorGUILayout.CurveField("Red", ms.colR);
				ms.colG = EditorGUILayout.CurveField("Green", ms.colG);
				ms.colB = EditorGUILayout.CurveField("Blue", ms.colB);
				ms.colA = EditorGUILayout.CurveField("Alpha", ms.colA);

				EditorGUILayout.EndToggleGroup();

				if ( i > 0 )
				{
					if ( GUILayout.Button("Delete") )
					{
						layer.sections.RemoveAt(i);
						EditorUtility.SetDirty(target);
					}
				}
			}
			EditorGUILayout.EndVertical();
		}
	}