void ShowDirection(IFerr2DTMaterial aMat, int aDir)
    {
        Ferr2DT_SegmentDescription desc = aMat.GetDescriptor((Ferr2DT_TerrainDirection)aDir);

        settingsScroll = EditorGUILayout.BeginScrollView(settingsScroll);
        EditorGUILayout.LabelField("Edge Placement", EditorStyles.boldLabel);
        EditorGUI.indentLevel = 1;
        desc.zOffset          = EditorGUILayout.IntField("Draw Order", Mathf.RoundToInt(desc.zOffset * 1000)) / 1000f;
        desc.YOffsetPercent   = EditorGUILayout.Slider("Y Offset", desc.YOffsetPercent, -.5f, .5f);
        desc.yOffset          = EditorGUILayout.FloatField("[Legacy] Y Offset", desc.yOffset);
        desc.capOffset        = EditorGUILayout.FloatField("[Legacy] Cap Offset", desc.capOffset);
        EditorGUI.indentLevel = 0;

        Ferr2DT_TerrainMaterialUtility.EditColliders(desc);

        EditorGUILayout.Space();
        EditorGUILayout.LabelField("Edge Segments", EditorStyles.boldLabel);
        simpleUVs = EditorGUILayout.Toggle("Simple Mode", simpleUVs);
        if (simpleUVs)
        {
            Ferr2DT_TerrainMaterialUtility.EditUVsSimple(aMat, desc);
        }
        else
        {
            Ferr2DT_TerrainMaterialUtility.EditUVsComplex(aMat, desc, width, ref currBody);
        }
        EditorGUILayout.EndScrollView();
    }
Example #2
0
    public Ferr2DT_Material CreateNewFormatMaterial()
    {
        Ferr2DT_Material result = ScriptableObject.CreateInstance <Ferr2DT_Material>();

        result.edgeMaterial = _edgeMaterial;
        result.fillMaterial = _fillMaterial;

        for (int i = 0; i < 4; i += 1)
        {
            Ferr2DT_TerrainDirection dir = (Ferr2DT_TerrainDirection)i;
            if (!Has(dir))
            {
                continue;
            }
            result.Set(dir, true);
            Ferr2DT_SegmentDescription dest = result.GetDescriptor(dir);
            Ferr2DT_SegmentDescription src  = GetDescriptor(dir);
            dest.applyTo       = src.applyTo;
            dest.body          = src.body;
            dest.capOffset     = src.capOffset;
            dest.innerLeftCap  = src.innerLeftCap;
            dest.innerRightCap = src.innerRightCap;
            dest.leftCap       = src.leftCap;
            dest.rightCap      = src.rightCap;
            dest.yOffset       = src.yOffset;
            dest.zOffset       = src.zOffset;
        }

        return(result);
    }
Example #3
0
 public Ferr2DT_TerrainMaterial()
 {
     for (int i = 0; i < descriptors.Length; i++)
     {
         descriptors[i] = new Ferr2DT_SegmentDescription();
     }
 }
    private Rect LegacyGetRandomBodyRect(Vector2 aInitialPos, Ferr2DT_SegmentDescription aDesc)
    {
#if UNITY_5_4_OR_NEWER
        UnityEngine.Random.State tSeed = default(UnityEngine.Random.State);
#else
        int tSeed = 0;
#endif
        if (randomByWorldCoordinates)
        {
#if UNITY_5_4_OR_NEWER
            tSeed = UnityEngine.Random.state;
            UnityEngine.Random.InitState((int)(aInitialPos.x + aInitialPos.y));
#else
            tSeed = UnityEngine.Random.seed;
            UnityEngine.Random.seed = (int)(aInitialPos.x + aInitialPos.y);
#endif
        }

        Rect body = TerrainMaterial.ToUV(aDesc.body[UnityEngine.Random.Range(0, aDesc.body.Length)]);
        if (randomByWorldCoordinates)
        {
#if UNITY_5_4_OR_NEWER
            UnityEngine.Random.state = tSeed;
#else
            UnityEngine.Random.seed = tSeed;
#endif
        }
        return(body);
    }
Example #5
0
    public static void CreateAsset()
    {
        Ferr2DT_Material mat = (Ferr2DT_Material)Ferr.SOUtil.CreateAsset(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType, editorMenuName);

        // top
        mat.Set(Ferr2DT_TerrainDirection.Top, true);
        Ferr2DT_SegmentDescription curr = mat._descriptors[0];

        curr.SingleColliderCapType = Ferr2D_CapColliderType.Connected;

        // left
        mat.Set(Ferr2DT_TerrainDirection.Left, true);
        curr         = mat._descriptors[1];
        curr.ZOffset = 2f / 1000f;
        curr.SingleColliderCapType = Ferr2D_CapColliderType.Rectangle;

        // right
        mat.Set(Ferr2DT_TerrainDirection.Right, true);
        curr         = mat._descriptors[2];
        curr.ZOffset = 2f / 1000f;
        curr.SingleColliderCapType = Ferr2D_CapColliderType.Rectangle;

        // right
        mat.Set(Ferr2DT_TerrainDirection.Bottom, true);
        curr         = mat._descriptors[3];
        curr.ZOffset = 1f / 1000f;
        curr.SingleColliderCapType = Ferr2D_CapColliderType.Connected;
    }
Example #6
0
    private void AddSegment(List <Vector2> aSegment, bool aClosed, Ferr2DT_TerrainDirection aDir = Ferr2DT_TerrainDirection.None)
    {
        Ferr2DT_SegmentDescription desc = GetDescription(aSegment);

        if (aDir != Ferr2DT_TerrainDirection.None)
        {
            desc = terrainMaterial.GetDescriptor(aDir);
        }
        int   bodyID    = UnityEngine.Random.Range(0, desc.body.Length);
        Rect  body      = terrainMaterial.ToUV(desc.body[bodyID]);
        float bodyWidth = body.width * unitsPerUV.x;

        int tSeed = UnityEngine.Random.seed;

        Vector2 capLeftSlideDir  = (aSegment[1] - aSegment[0]);
        Vector2 capRightSlideDir = (aSegment[aSegment.Count - 2] - aSegment[aSegment.Count - 1]);

        capLeftSlideDir.Normalize();
        capRightSlideDir.Normalize();
        aSegment[0] -= capLeftSlideDir * desc.capOffset;
        aSegment[aSegment.Count - 1] -= capRightSlideDir * desc.capOffset;

        for (int i = 0; i < aSegment.Count - 1; i++)
        {
            Vector2 norm1   = Vector2.zero;
            Vector2 norm2   = Vector2.zero;
            float   length  = Vector2.Distance(aSegment[i + 1], aSegment[i]);
            int     repeats = Mathf.Max(1, Mathf.FloorToInt(length / bodyWidth + stretchThreshold));

            norm1 = Ferr2D_Path.GetNormal(aSegment, i, aClosed);
            norm2 = Ferr2D_Path.GetNormal(aSegment, i + 1, aClosed);

            for (int t = 1; t < repeats + 1; t++)
            {
                UnityEngine.Random.seed = (int)(transform.position.x * 100000 + transform.position.y * 10000 + i * 100 + t);
                body = terrainMaterial.ToUV(desc.body[UnityEngine.Random.Range(0, desc.body.Length)]);
                Vector2 pos1, pos2, n1, n2;

                pos1 = Vector2.Lerp(aSegment[i], aSegment[i + 1], (float)(t - 1) / repeats);
                pos2 = Vector2.Lerp(aSegment[i], aSegment[i + 1], (float)t / repeats);
                n1   = Vector2.Lerp(norm1, norm2, (float)(t - 1) / repeats);
                n2   = Vector2.Lerp(norm1, norm2, (float)t / repeats);

                float d    = (body.height / 2) * unitsPerUV.y;
                float yOff = fill == Ferr2DT_FillMode.InvertedClosed ? -desc.yOffset : desc.yOffset;
                int   v1   = dMesh.AddVertex(pos1.x + n1.x * (d + yOff), pos1.y + n1.y * (d + yOff), desc.zOffset, body.x, fill == Ferr2DT_FillMode.InvertedClosed ? body.yMax : body.y);
                int   v2   = dMesh.AddVertex(pos1.x - n1.x * (d - yOff), pos1.y - n1.y * (d - yOff), desc.zOffset, body.x, fill == Ferr2DT_FillMode.InvertedClosed ? body.y    : body.yMax);
                int   v3   = dMesh.AddVertex(pos2.x + n2.x * (d + yOff), pos2.y + n2.y * (d + yOff), desc.zOffset, body.xMax, fill == Ferr2DT_FillMode.InvertedClosed ? body.yMax : body.y);
                int   v4   = dMesh.AddVertex(pos2.x - n2.x * (d - yOff), pos2.y - n2.y * (d - yOff), desc.zOffset, body.xMax, fill == Ferr2DT_FillMode.InvertedClosed ? body.y    : body.yMax);
                dMesh.AddFace(v1, v3, v4, v2);
            }
        }
        if (!aClosed)
        {
            AddCap(aSegment, desc, -1);
            AddCap(aSegment, desc, 1);
        }
        UnityEngine.Random.seed = tSeed;
    }
Example #7
0
    public void Add()
    {
        Array.Resize(ref descriptors, descriptors.Length + 1);
        var newSegment = new Ferr2DT_SegmentDescription();

        newSegment.applyTo = (Ferr2DT_TerrainDirection)descriptors.Length - 1;
        descriptors[descriptors.Length - 1] = newSegment;
    }
    public static void EditUVsComplex(Ferr2DT_TerrainMaterial    aMat, Ferr2DT_SegmentDescription desc, float aWidth, ref int aCurrBody)
    {
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Body", GUILayout.Width(40f));

        int bodyID = Mathf.Clamp(aCurrBody, 0, desc.body.Length);
        if (GUILayout.Button("<", GUILayout.Width(20f))) aCurrBody = Mathf.Clamp(aCurrBody - 1, 0, desc.body.Length - 1);
        EditorGUILayout.LabelField("" + (bodyID + 1), GUILayout.Width(12f));
        if (GUILayout.Button(">", GUILayout.Width(20f))) aCurrBody = Mathf.Clamp(aCurrBody + 1, 0, desc.body.Length - 1);
        bodyID = Mathf.Clamp(aCurrBody, 0, desc.body.Length - 1);
        int length = Math.Max(1, EditorGUILayout.IntField(desc.body.Length, GUILayout.Width(32f)));
        EditorGUILayout.LabelField("Total", GUILayout.Width(40f));
        if (length != desc.body.Length) Array.Resize<Rect>(ref desc.body, length);

        EditorGUILayout.EndHorizontal();

        EditorGUILayout.Space();
        desc.body[bodyID] = AtlasField(aMat, desc.body[bodyID], aMat.edgeMaterial != null ? aMat.edgeMaterial.mainTexture : EditorGUIUtility.whiteTexture);
        if (desc.leftCap.width == 0 && desc.leftCap.height == 0)
        {
            if (EditorGUILayout.Toggle("Left Cap", false))
            {
                desc.leftCap = new Rect(0, 0, 30, 30);
            }
        }
        else
        {
            if (EditorGUILayout.Toggle("Left Cap", true))
            {
                desc.leftCap = AtlasField(aMat, desc.leftCap, aMat.edgeMaterial != null ? aMat.edgeMaterial.mainTexture : EditorGUIUtility.whiteTexture);
            }
            else
            {
                desc.leftCap = new Rect(0, 0, 0, 0);
            }

        }
        if (desc.rightCap.width == 0 && desc.rightCap.height == 0)
        {
            if (EditorGUILayout.Toggle("Right Cap", false))
            {
                desc.rightCap = new Rect(0, 0, 30, 30);
            }
        }
        else
        {
            if (EditorGUILayout.Toggle("Right Cap", true))
            {
                desc.rightCap = AtlasField(aMat, desc.rightCap, aMat.edgeMaterial != null ? aMat.edgeMaterial.mainTexture : EditorGUIUtility.whiteTexture);
            }
            else
            {
                desc.rightCap = new Rect(0, 0, 0, 0);
            }
        }
    }
    /// <summary>
    /// Creates a TerrainMaterial from a JSON object, does -not- link edgeMaterial or fillMaterial, you'll have to do that yourself!
    /// </summary>
    /// <param name="aJSON">A parsed JSON value</param>
    public void           FromJSON(Ferr_JSONValue aJSON)
    {
        Ferr_JSONValue descArr = aJSON["descriptors"];

        for (int i = 0; i < descArr.Length; i++)
        {
            descriptors[i] = new Ferr2DT_SegmentDescription();
            descriptors[i].FromJSON(descArr[i]);
        }
    }
    public static void EditColliders(Ferr2DT_SegmentDescription desc)
    {
        EditorGUILayout.LabelField("Colliders", EditorStyles.boldLabel);
        EditorGUI.indentLevel = 1;

        desc.ColliderOffset    = EditorGUILayout.Slider("Vertical Offset", desc.ColliderOffset, -1, 1);
        desc.ColliderThickness = EditorGUILayout.Slider("Thickness", desc.ColliderThickness, 0, 2);
        desc.PhysicsMaterial2D = (PhysicsMaterial2D)EditorGUILayout.ObjectField("Physics Material 2D", desc.PhysicsMaterial2D, typeof(PhysicsMaterial2D), false);
        desc.PhysicsMaterial3D = (PhysicMaterial   )EditorGUILayout.ObjectField("Physics Material 3D", desc.PhysicsMaterial3D, typeof(PhysicMaterial), false);

        EditorGUI.indentLevel = 0;
    }
    public static void EditUVsSimple(Ferr2DT_TerrainMaterial aMat, Ferr2DT_SegmentDescription desc)
    {
        Rect cap  = aMat.ToPixels(desc.leftCap);
        Rect body = aMat.ToPixels(desc.body[0]);

        float   height    = body.height;
        float   capWidth  = cap.width;
        float   bodyWidth = body.width;
        int     bodyCount = desc.body.Length;
        Vector2 pos       = new Vector2(cap.x, cap.y);

        if (cap.width == 0 && cap.height == 0)
        {
            pos = new Vector2(body.x, body.y);
        }

        pos       = EditorGUILayout.Vector2Field("Position", pos);
        height    = EditorGUILayout.FloatField("Height", height);
        capWidth  = EditorGUILayout.FloatField("Cap Width", capWidth);
        bodyWidth = EditorGUILayout.FloatField("Body Width", bodyWidth);
        bodyCount = Mathf.Max(1, EditorGUILayout.IntField("Body slices", bodyCount));

        if (bodyCount != desc.body.Length)
        {
            Array.Resize <Rect>(ref desc.body, bodyCount);
        }

        float currX = pos.x;

        desc.leftCap.x      = currX;
        desc.leftCap.y      = pos.y;
        desc.leftCap.width  = capWidth;
        desc.leftCap.height = capWidth == 0 ? 0 : height;
        desc.leftCap        = aMat.ToNative(desc.leftCap);
        currX += capWidth;

        for (int i = 0; i < desc.body.Length; i++)
        {
            desc.body[i].x      = currX;
            desc.body[i].y      = pos.y;
            desc.body[i].width  = bodyWidth;
            desc.body[i].height = height;
            desc.body[i]        = aMat.ToNative(desc.body[i]);
            currX += bodyWidth;
        }

        desc.rightCap.x      = currX;
        desc.rightCap.y      = pos.y;
        desc.rightCap.width  = capWidth;
        desc.rightCap.height = capWidth == 0 ? 0 : height;
        desc.rightCap        = aMat.ToNative(desc.rightCap);
    }
    public static float MaxHeight(Ferr2DT_SegmentDescription aDesc)
    {
        float sourceHeight = Mathf.Max(aDesc.leftCap.height, aDesc.rightCap.height);
        float max          = 0;

        for (int i = 0; i < aDesc.body.Length; i++)
        {
            if (aDesc.body[i].height > max)
            {
                max = aDesc.body[i].height;
            }
        }
        return(Mathf.Max(max, sourceHeight));
    }
    private void LegacyCreateBody(Ferr2DT_SegmentDescription aDesc, List <Vector2> aSegment, List <float> aSegmentScale, List <CutOverrides> aCutOverrides, float aBodyWidth, int aTextureSlices, bool aClosed)
    {
        float distance    = Ferr2D_Path.GetSegmentLength(aSegment);
        int   textureCuts = Mathf.Max(1, Mathf.FloorToInt(distance / aBodyWidth + 0.5f));

        Ferr2D_DynamicMesh mesh = DMesh;

        Rect  body = LegacyPickBody(aDesc, aCutOverrides, aSegment[0], 0, 0);
        float d    = (body.height / 2) * unitsPerUV.y;
        float yOff = fill == Ferr2DT_FillMode.InvertedClosed ? -aDesc.yOffset : aDesc.yOffset;

        int p1 = 0, p2 = 0, p3 = 0;
        int pIndex   = 0;
        int cutIndex = 0;

        // loop for each instance of the texture
        for (int t = 0; t < textureCuts; t++)
        {
            float texPercent     = (t / (float)(textureCuts));
            float texPercentStep = (1f / (float)(textureCuts));

            // slice each texture chunk a number of times
            for (int i = 0; i < aTextureSlices; i++)
            {
                float slicePercent = (i / (float)(aTextureSlices - 1));
                float totalPercent = texPercent + slicePercent * texPercentStep;

                int   ptLocal  = 0;
                float pctLocal = 0;
                Ferr2D_Path.PathGlobalPercentToLocal(aSegment, totalPercent, out ptLocal, out pctLocal, distance, aClosed);

                // if we skip over path points, we need to add slices at each path point to prevent the mesh from bypassing it.
                for (int extra = 0; extra < ptLocal - pIndex; extra++)
                {
                    float traveledDist = Ferr2D_Path.GetSegmentLengthToIndex(aSegment, pIndex + extra + 1);
                    float v            = (traveledDist / distance) * textureCuts;
                    v = v - (int)v;
                    LegacyAddVertexColumn(aDesc, aSegment, aSegmentScale, aClosed, mesh, body, d, yOff, i != 0, v, pIndex + extra + 1, 0, ref p1, ref p2, ref p3);
                    cutIndex = -1;
                }
                pIndex = ptLocal;

                LegacyAddVertexColumn(aDesc, aSegment, aSegmentScale, aClosed, mesh, body, d, yOff, i != 0, slicePercent, ptLocal, pctLocal, ref p1, ref p2, ref p3);
            }

            cutIndex += 1;
            body      = LegacyPickBody(aDesc, aCutOverrides, mesh.GetVert(p2), pIndex, cutIndex);
        }
    }
Example #14
0
 /// <summary>
 /// Sets a particular direction as having a valid descriptor. Or not. That's a bool.
 /// </summary>
 /// <param name="aDirection">The direction!</param>
 /// <param name="aActive">To active, or not to active? That is the question!</param>
 public void                       Set(Ferr2DT_TerrainDirection aDirection, bool aActive)
 {
     if (aActive)
     {
         if (descriptors[(int)aDirection].applyTo != aDirection)
         {
             descriptors[(int)aDirection]         = new Ferr2DT_SegmentDescription();
             descriptors[(int)aDirection].applyTo = aDirection;
         }
     }
     else if (descriptors[(int)aDirection].applyTo != Ferr2DT_TerrainDirection.Top)
     {
         descriptors[(int)aDirection] = new Ferr2DT_SegmentDescription();
     }
 }
    private float TexDistAtSegment(Ferr2DT_PathTerrain.EdgeSegment aSegment, Ferr2DT_SegmentDescription edgeData, List <int> aTexSegments, int aSegmentId)
    {
        float currLength = 0;

        for (int i = 0; i < aTexSegments.Count && i <= aSegmentId; i++)
        {
            float segLength = terrain.TerrainMaterial.ToUV(edgeData.GetBody(aTexSegments[i])).width *terrain.UnitsPerUV.x;

            if (i == aSegmentId)
            {
                return(currLength + segLength / 2);
            }
            currLength += terrain.TerrainMaterial.ToUV(edgeData.GetBody(aTexSegments[i])).width *terrain.UnitsPerUV.x;
        }
        return(-1);
    }
Example #16
0
    private void AddCap(List <Vector2> aSegment, Ferr2DT_SegmentDescription aDesc, float aDir)
    {
        int     index = 0;
        Vector2 dir   = Vector2.zero;

        if (aDir < 0)
        {
            index = 0;
            dir   = aSegment[0] - aSegment[1];
        }
        else
        {
            index = aSegment.Count - 1;
            dir   = aSegment[aSegment.Count - 1] - aSegment[aSegment.Count - 2];
        }
        dir.Normalize();
        Vector2 norm = Ferr2D_Path.GetNormal(aSegment, index, false);
        Vector2 pos  = aSegment[index];
        Rect    lCap = fill == Ferr2DT_FillMode.InvertedClosed ? terrainMaterial.ToUV(aDesc.rightCap) : terrainMaterial.ToUV(aDesc.leftCap);
        Rect    rCap = fill == Ferr2DT_FillMode.InvertedClosed ? terrainMaterial.ToUV(aDesc.leftCap) : terrainMaterial.ToUV(aDesc.rightCap);
        float   yOff = fill == Ferr2DT_FillMode.InvertedClosed ? -aDesc.yOffset : aDesc.yOffset;

        if (aDir < 0)
        {
            float width = lCap.width * unitsPerUV.x;
            float scale = (lCap.height / 2) * unitsPerUV.y;

            int v1 = dMesh.AddVertex(pos + dir * width + norm * (scale + yOff), aDesc.zOffset, new Vector2(fill == Ferr2DT_FillMode.InvertedClosed? lCap.xMax : lCap.x, fill == Ferr2DT_FillMode.InvertedClosed ? lCap.yMax : lCap.y));
            int v2 = dMesh.AddVertex(pos + norm * (scale + yOff), aDesc.zOffset, new Vector2(fill == Ferr2DT_FillMode.InvertedClosed ? lCap.x : lCap.xMax, fill == Ferr2DT_FillMode.InvertedClosed ? lCap.yMax : lCap.y));

            int v3 = dMesh.AddVertex(pos - norm * (scale - yOff), aDesc.zOffset, new Vector2(fill == Ferr2DT_FillMode.InvertedClosed ? lCap.x : lCap.xMax, fill == Ferr2DT_FillMode.InvertedClosed ? lCap.y : lCap.yMax));
            int v4 = dMesh.AddVertex(pos + dir * width - norm * (scale - yOff), aDesc.zOffset, new Vector2(fill == Ferr2DT_FillMode.InvertedClosed ? lCap.xMax : lCap.x, fill == Ferr2DT_FillMode.InvertedClosed ? lCap.y : lCap.yMax));
            dMesh.AddFace(v1, v2, v3, v4);
        }
        else
        {
            float width = rCap.width * unitsPerUV.x;
            float scale = (rCap.height / 2) * unitsPerUV.y;

            int v1 = dMesh.AddVertex(pos + dir * width + norm * (scale + yOff), aDesc.zOffset, new Vector2(fill == Ferr2DT_FillMode.InvertedClosed ? rCap.x : rCap.xMax, fill == Ferr2DT_FillMode.InvertedClosed ? rCap.yMax : rCap.y));
            int v2 = dMesh.AddVertex(pos + norm * (scale + yOff), aDesc.zOffset, new Vector2(fill == Ferr2DT_FillMode.InvertedClosed ? rCap.xMax : rCap.x, fill == Ferr2DT_FillMode.InvertedClosed ? rCap.yMax : rCap.y));

            int v3 = dMesh.AddVertex(pos - norm * (scale - yOff), aDesc.zOffset, new Vector2(fill == Ferr2DT_FillMode.InvertedClosed ? rCap.xMax : rCap.x, fill == Ferr2DT_FillMode.InvertedClosed ? rCap.y : rCap.yMax));
            int v4 = dMesh.AddVertex(pos + dir * width - norm * (scale - yOff), aDesc.zOffset, new Vector2(fill == Ferr2DT_FillMode.InvertedClosed ? rCap.x : rCap.xMax, fill == Ferr2DT_FillMode.InvertedClosed ? rCap.y : rCap.yMax));
            dMesh.AddFace(v4, v3, v2, v1);
        }
    }
    void ShowDirection(Ferr2DT_TerrainMaterial aMat, Ferr2DT_TerrainDirection aDir)
    {
        Ferr2DT_SegmentDescription desc = aMat.GetDescriptor(aDir);

        desc.zOffset   = EditorGUILayout.FloatField("Z Offset", desc.zOffset);
        desc.yOffset   = EditorGUILayout.FloatField("Y Offset", desc.yOffset);
        desc.capOffset = EditorGUILayout.FloatField("Cap Offset", desc.capOffset);

        simpleUVs = EditorGUILayout.Toggle("Simple", simpleUVs);
        if (simpleUVs)
        {
            Ferr2DT_TerrainMaterialUtility.EditUVsSimple(aMat, desc);
        }
        else
        {
            Ferr2DT_TerrainMaterialUtility.EditUVsComplex(aMat, desc, width, ref currBody);
        }
    }
Example #18
0
    public static bool IsSimple(Ferr2DT_SegmentDescription aDesc)
    {
        float height = aDesc.leftCap.height;
        bool  noCaps = aDesc.leftCap.width == 0 && aDesc.rightCap.width == 0;

        bool heightSame = noCaps ?
                          aDesc.body[0].height == aDesc.body[aDesc.body.Length - 1].height :
                          aDesc.rightCap.height == height && aDesc.body[0].height == height;
        bool capSame = aDesc.leftCap.width == aDesc.rightCap.width;
        bool ySame   = noCaps ?
                       aDesc.body[0].y == aDesc.body[aDesc.body.Length - 1].y :
                       aDesc.leftCap.y == aDesc.rightCap.y && aDesc.leftCap.y == aDesc.body[0].y && aDesc.leftCap.y == aDesc.body[aDesc.body.Length - 1].y;
        bool xSpaced = noCaps ?
                       (aDesc.body[0].x - aDesc.body[aDesc.body.Length - 1].x) % aDesc.body[0].width == 0:
                       aDesc.leftCap.xMax == aDesc.body[0].x && aDesc.rightCap.x == aDesc.body[aDesc.body.Length - 1].xMax;

        return(heightSame && capSame && ySame && xSpaced);
    }
    public static bool IsSimple(Ferr2DT_SegmentDescription aDesc)
    {
        float y       = aDesc.body[0].y;
        bool  hasCaps = aDesc.leftCap.width != 0 || aDesc.rightCap.width != 0;
        float height  = aDesc.body[0].height;

        if (hasCaps && (aDesc.leftCap.y != y || aDesc.rightCap.y != y))
        {
            return(false);
        }
        if (hasCaps && aDesc.leftCap.xMax != aDesc.body[0].x)
        {
            return(false);
        }
        if (hasCaps && aDesc.rightCap.x != aDesc.body[aDesc.body.Length - 1].xMax)
        {
            return(false);
        }
        if (hasCaps && (aDesc.leftCap.height != height || aDesc.rightCap.height != height))
        {
            return(false);
        }

        for (int i = 0; i < aDesc.body.Length; i++)
        {
            if (aDesc.body[i].y != aDesc.leftCap.y)
            {
                return(false);
            }
            if (aDesc.body[i].height != height)
            {
                return(false);
            }
            if (i + 1 < aDesc.body.Length && aDesc.body[i].xMax != aDesc.body[i + 1].x)
            {
                return(false);
            }
        }
        return(true);
    }
    private Rect LegacyPickBody(Ferr2DT_SegmentDescription aDesc, List <CutOverrides> aCutOverrides, Vector2 aStartPos, int aCurrIndex, int aCurrCut)
    {
        int  cutOverride = -1;
        Rect result      = default(Rect);

        if (aCutOverrides[aCurrIndex].data != null && aCurrCut < aCutOverrides[aCurrIndex].data.Count)
        {
            cutOverride = aCutOverrides[aCurrIndex].data[aCurrCut] - 1;
        }

        if (cutOverride == -1 || cutOverride >= aDesc.body.Length)
        {
            result = LegacyGetRandomBodyRect(aStartPos, aDesc);
        }
        else
        {
            // trigger this so a random number is consumed
            LegacyGetRandomBodyRect(aStartPos, aDesc);
            result = TerrainMaterial.ToUV(aDesc.body[cutOverride]);
        }
        return(result);
    }
    public static void ShowSample(IFerr2DTMaterial aMat, Ferr2DT_TerrainDirection aDir, float aWidth)
    {
        if (aMat.edgeMaterial == null || aMat.edgeMaterial.mainTexture == null)
        {
            return;
        }

        Ferr2DT_SegmentDescription desc = aMat.GetDescriptor(aDir);
        float   totalWidth   = desc.leftCap.width + desc.rightCap.width + (Mathf.Max(0, desc.body[0].width) * 3);
        float   sourceHeight = MaxHeight(desc);
        Texture tex          = aMat.edgeMaterial != null ? aMat.edgeMaterial.mainTexture : EditorGUIUtility.whiteTexture;

        float scale  = Mathf.Min(aWidth / totalWidth, 64 / sourceHeight);
        float aspect = tex.height / tex.width;

        GUILayout.Space(sourceHeight * scale * aspect);
        float x = GUILayoutUtility.GetLastRect().x;
        float y = GUILayoutUtility.GetLastRect().y;

        if (desc.leftCap.width != 0)
        {
            float yOff = ((sourceHeight - desc.leftCap.height) / 2) * scale;
            GUI.DrawTextureWithTexCoords(new Rect(x, y + yOff, desc.leftCap.width * scale, desc.leftCap.height * scale * aspect), tex, aMat.ToUV(desc.leftCap));
            x += desc.leftCap.width * scale;
        }
        for (int i = 0; i < 3; i++)
        {
            int   id   = (2 - i) % desc.body.Length;
            float yOff = ((sourceHeight - desc.body[id].height) / 2) * scale;
            GUI.DrawTextureWithTexCoords(new Rect(x, y + yOff, desc.body[id].width * scale, desc.body[id].height * scale * aspect), tex, aMat.ToUV(desc.body[id]));
            x += desc.body[id].width * scale;
        }
        if (desc.leftCap.width != 0)
        {
            float yOff = ((sourceHeight - desc.rightCap.height) / 2) * scale;
            GUI.DrawTextureWithTexCoords(new Rect(x, y + yOff, desc.rightCap.width * scale, desc.rightCap.height * scale * aspect), tex, aMat.ToUV(desc.rightCap));
        }
    }
    private void LegacyAddVertexColumn(Ferr2DT_SegmentDescription aDesc, List <Vector2> aSegment, List <float> aSegmentScale, bool aClosed, Ferr2D_DynamicMesh mesh, Rect body, float d, float yOff, bool aConnectFace, float slicePercent, int ptLocal, float pctLocal, ref int p1, ref int p2, ref int p3)
    {
        Vector2 pos1 = smoothPath ? Ferr2D_Path.HermiteGetPt(aSegment, ptLocal, pctLocal, aClosed) : Ferr2D_Path.LinearGetPt(aSegment, ptLocal, pctLocal, aClosed);
        Vector2 n1   = smoothPath ? Ferr2D_Path.HermiteGetNormal(aSegment, ptLocal, pctLocal, aClosed) : Ferr2D_Path.LinearGetNormal(aSegment, ptLocal, pctLocal, aClosed);
        float   s    = aClosed    ? Mathf.Lerp(aSegmentScale[ptLocal], aSegmentScale[(ptLocal + 1) % aSegmentScale.Count], pctLocal) : Mathf.Lerp(aSegmentScale[ptLocal], aSegmentScale[Mathf.Min(ptLocal + 1, aSegmentScale.Count - 1)], pctLocal);

        // this compensates for scale distortion when corners are very sharp, but the normals are not long enough to keep the edge the appropriate width
        // not actually a problem for smooth paths
        if (!smoothPath)
        {
            n1.Normalize();
            float rootScale = 1f / Mathf.Abs(Mathf.Cos(Vector2.Angle(Ferr2D_Path.GetSegmentNormal(ptLocal, aSegment, aClosed), n1) * Mathf.Deg2Rad));
            s = s * rootScale;
        }

        int v1 = mesh.AddVertex(pos1.x + n1.x * (d * s + yOff), pos1.y + n1.y * (d * s + yOff), -slantAmount + aDesc.zOffset, Mathf.Lerp(body.x, body.xMax, slicePercent), fill == Ferr2DT_FillMode.InvertedClosed ? body.yMax : body.y);
        int v2 = mesh.AddVertex(pos1.x - n1.x * (d * s - yOff), pos1.y - n1.y * (d * s - yOff), slantAmount + aDesc.zOffset, Mathf.Lerp(body.x, body.xMax, slicePercent), fill == Ferr2DT_FillMode.InvertedClosed ? body.y : body.yMax);
        int v3 = splitMiddle ? mesh.AddVertex(pos1.x + n1.x * yOff, pos1.y + n1.y * yOff, aDesc.zOffset, Mathf.Lerp(body.x, body.xMax, slicePercent), Mathf.Lerp(body.y, body.yMax, 0.5f)) : -1;

        if (aConnectFace)
        {
            if (!splitMiddle)
            {
                mesh.AddFace(v2, p2, p1, v1);
            }
            else
            {
                mesh.AddFace(v2, p2, p3, v3);
                mesh.AddFace(v3, p3, p1, v1);
            }
        }

        p1 = v1;
        p2 = v2;
        p3 = v3;
    }
 public static float MaxHeight(Ferr2DT_SegmentDescription aDesc)
 {
     float sourceHeight = Mathf.Max( aDesc.leftCap.height, aDesc.rightCap.height );
     float max          = 0;
     for (int i = 0; i < aDesc.body.Length; i++)
     {
         if (aDesc.body[i].height > max) max = aDesc.body[i].height;
     }
     return Mathf.Max(max, sourceHeight);
 }
    public static void EditUVsSimple(Ferr2DT_SegmentDescription desc)
    {
        float   height    = MaxHeight(desc);
        float   capWidth  = Mathf.Max(desc.leftCap.width, desc.rightCap.width);
        float   bodyWidth = desc.body[0].width;
        int     bodyCount = desc.body.Length;
        Vector2 pos       = new Vector2(desc.leftCap.x, desc.leftCap.y);
        if (desc.leftCap.width == 0 && desc.leftCap.height == 0) pos = new Vector2(desc.body[0].x, desc.body[0].y);

        pos       = EditorGUILayout.Vector2Field("Position",    pos      );
        height    = EditorGUILayout.FloatField  ("Height",      height   );
        capWidth  = EditorGUILayout.FloatField  ("Cap Width",   capWidth );
        bodyWidth = EditorGUILayout.FloatField  ("Body Width",  bodyWidth);
        bodyCount = Mathf.Max(1, EditorGUILayout.IntField    ("Body slices", bodyCount));

        if (bodyCount != desc.body.Length) {
            Array.Resize<Rect>(ref desc.body, bodyCount);
        }

        float currX = pos.x;
        desc.leftCap.x      = currX;
        desc.leftCap.y      = pos.y;
        desc.leftCap.width  = capWidth;
        desc.leftCap.height = capWidth == 0 ? 0 : height;
        currX += capWidth;

        for (int i = 0; i < desc.body.Length; i++)
        {
            desc.body[i].x      = currX;
            desc.body[i].y      = pos.y;
            desc.body[i].width  = bodyWidth;
            desc.body[i].height = height;
            currX += bodyWidth;
        }

        desc.rightCap.x      = currX;
        desc.rightCap.y      = pos.y;
        desc.rightCap.width  = capWidth;
        desc.rightCap.height = capWidth == 0 ? 0 : height;
    }
    public static bool IsSimple(Ferr2DT_SegmentDescription aDesc)
    {
        float height = aDesc.leftCap.height;
        bool noCaps = aDesc.leftCap.width == 0 && aDesc.rightCap.width == 0;

        bool heightSame = noCaps ?
            aDesc.body[0] .height == aDesc.body[aDesc.body.Length-1].height :
            aDesc.rightCap.height == height && aDesc.body[0].height == height;
        bool capSame    = aDesc.leftCap.width   == aDesc.rightCap.width;
        bool ySame      = noCaps ?
            aDesc.body[0].y == aDesc.body[aDesc.body.Length-1].y :
            aDesc.leftCap.y == aDesc.rightCap.y && aDesc.leftCap.y == aDesc.body[0].y && aDesc.leftCap.y == aDesc.body[aDesc.body.Length-1].y;
        bool xSpaced    = noCaps ?
            (aDesc.body[0].x - aDesc.body[aDesc.body.Length-1].x) % aDesc.body[0].width == 0:
            aDesc.leftCap.xMax == aDesc.body[0].x  && aDesc.rightCap.x == aDesc.body[aDesc.body.Length-1].xMax;

        return heightSame && capSame && ySame && xSpaced;
    }
 /// <summary>
 /// Creates a TerrainMaterial from a JSON object, does -not- link edgeMaterial or fillMaterial, you'll have to do that yourself!
 /// </summary>
 /// <param name="aJSON">A parsed JSON value</param>
 public void FromJSON(Ferr_JSONValue aJSON)
 {
     Ferr_JSONValue descArr = aJSON["descriptors"];
     for (int i = 0; i < descArr.Length; i++) {
         descriptors[i] = new Ferr2DT_SegmentDescription();
         descriptors[i].FromJSON(descArr[i]);
     }
 }
 /// <summary>
 /// Sets a particular direction as having a valid descriptor. Or not. That's a bool.
 /// </summary>
 /// <param name="aDirection">The direction!</param>
 /// <param name="aActive">To active, or not to active? That is the question!</param>
 public void Set(Ferr2DT_TerrainDirection aDirection, bool aActive)
 {
     if (aActive) {
         if (descriptors[(int)aDirection].applyTo != aDirection) {
             descriptors[(int)aDirection] = new Ferr2DT_SegmentDescription();
             descriptors[(int)aDirection].applyTo = aDirection;
         }
     } else if (descriptors[(int)aDirection].applyTo != Ferr2DT_TerrainDirection.Top) {
         descriptors[(int)aDirection] = new Ferr2DT_SegmentDescription();
     }
 }
Example #28
0
    private void DoCutOverrideModeHandles(Ferr2D_Path path, Ferr2DT_PathTerrain terrain, Matrix4x4 mat, Transform camTransform)
    {
        List <List <int>               > segments = new List <List <int>               >();
        List <Ferr2DT_TerrainDirection>  dirs     = new List <Ferr2DT_TerrainDirection>();
        List <Vector2> rawVerts = path.GetVertsRaw();

        // cut the terrain into segments, we need segment info to draw these points
        segments = terrain.GetSegments(rawVerts, out dirs);

        for (int s = 0; s < segments.Count; s++)
        {
            List <int>     currSeg   = segments[s];
            List <Vector2> currVerts = Ferr2D_Path.IndicesToList(rawVerts, currSeg);
            List <Ferr2DT_PathTerrain.CutOverrides> overrides = Ferr2D_Path.IndicesToList(terrain.cutOverrides, currSeg);

            // find information about this segment
            Ferr2DT_TerrainDirection   currDir = dirs[s];
            Ferr2DT_SegmentDescription desc    = default(Ferr2DT_SegmentDescription);

            if (currDir != Ferr2DT_TerrainDirection.None)
            {
                desc = terrain.TerrainMaterial.GetDescriptor(currDir);
            }
            else
            {
                desc = terrain.GetDescription(currSeg);
            }

            // if there's no body segment choices, don't bother with the rest of this
            if (desc.body.Length < 2)
            {
                continue;
            }

            Vector2 capLeftSlideDir  = (currVerts[1] - currVerts[0]);
            Vector2 capRightSlideDir = (currVerts[currVerts.Count - 2] - currVerts[currVerts.Count - 1]);
            capLeftSlideDir.Normalize();
            capRightSlideDir.Normalize();
            currVerts[0] -= capLeftSlideDir * desc.capOffset;
            currVerts[currVerts.Count - 1] -= capRightSlideDir * desc.capOffset;

            float distance = Ferr2D_Path.GetSegmentLength(currVerts);

            // how many texture cuts are there on the segment
            float bodyWidth   = desc.body[0].width * (terrain.TerrainMaterial.edgeMaterial.mainTexture.width / terrain.pixelsPerUnit);
            int   textureCuts = Mathf.Max(1, Mathf.FloorToInt(distance / bodyWidth + 0.5f));

            // data is attached to the points still, check if we've switched to a new point
            int activePt       = -1;
            int activeLocalCut = -1;
            for (int c = 0; c < textureCuts; c++)
            {
                float pctGlobal = c / (float)textureCuts;

                int   ptLocal  = 0;
                float pctLocal = 0;
                Ferr2D_Path.PathGlobalPercentToLocal(currVerts, pctGlobal, out ptLocal, out pctLocal, distance, false);

                if (ptLocal != activePt)
                {
                    // if they size down, we need to shorten the data too
                    if (activePt != -1)
                    {
                        CapListSize <int>(ref overrides[activePt].data, activeLocalCut + 3);
                    }
                    activePt       = ptLocal;
                    activeLocalCut = 0;

                    if (overrides[activePt].data == null)
                    {
                        overrides[activePt].data = new List <int>();
                    }
                }

                while (activeLocalCut >= overrides[activePt].data.Count)
                {
                    overrides[activePt].data.Add(0);
                }

                CapFunction cap            = CapDotAuto;
                int         activeOverride = overrides[activePt].data[activeLocalCut];
                if (activeOverride != 0)
                {
                    if (activeOverride == 1)
                    {
                        cap = CapDot1;
                    }
                    else if (activeOverride == 2)
                    {
                        cap = CapDot2;
                    }
                    else if (activeOverride == 3)
                    {
                        cap = CapDot3;
                    }
                    else if (activeOverride == 4)
                    {
                        cap = CapDot4;
                    }
                    else if (activeOverride == 5)
                    {
                        cap = CapDot5;
                    }
                    else if (activeOverride >= 6)
                    {
                        cap = CapDotN;
                    }
                }
                if (Event.current.alt)
                {
                    cap = CapDotReset;
                }

                int   ptShow  = 0;
                float pctShow = 0;
                Ferr2D_Path.PathGlobalPercentToLocal(currVerts, pctGlobal + (1f / textureCuts) * 0.5f, out ptShow, out pctShow, distance, false);

                Vector2 pt  = Ferr2D_Path.LinearGetPt(currVerts, ptShow, pctShow, false);
                Vector3 pos = mat.MultiplyPoint3x4(pt);
                float   sc  = HandleScale(pos) * 0.5f;
                if (Handles.Button(pos, camTransform.rotation, sc, sc, cap))
                {
                    Undo.RecordObject(terrain, "Lock Texture Segment");

                    overrides[activePt].data[activeLocalCut] = Event.current.alt ? 0 : (activeOverride + 1) % (desc.body.Length + 1);
                    EditorUtility.SetDirty(terrain);
                    GUI.changed = true;
                }

                activeLocalCut += 1;
            }
            if (activePt != -1)
            {
                CapListSize <int>(ref overrides[activePt].data, activeLocalCut + 3);
            }
        }
    }
 public Ferr2DT_TerrainMaterial()
 {
     for (int i = 0; i < descriptors.Length; i++) {
         descriptors[i] = new Ferr2DT_SegmentDescription();
     }
 }
    public static void EditUVsSimple(IFerr2DTMaterial aMat, Ferr2DT_SegmentDescription desc)
    {
        Rect cap  = aMat.ToPixels(desc.leftCap);
        Rect body = aMat.ToPixels(desc.body[0]);

        float   height    = body.height;
        float   capWidth  = cap.width;
        float   bodyWidth = body.width;
        int     bodyCount = desc.body.Length;
        Vector2 pos       = new Vector2(cap.x, cap.y);

        if (cap.width == 0 && cap.height == 0)
        {
            pos = new Vector2(body.x, body.y);
        }

        Ferr.EditorTools.Box(2, () => {
            pos      = EditorGUILayout.Vector2Field("Position", pos);
            height   = EditorGUILayout.FloatField("Height", height);
            capWidth = EditorGUILayout.FloatField("Cap Width", capWidth);
            desc.SingleColliderCapOffset = EditorGUILayout.Slider("Cap Offset", desc.SingleColliderCapOffset, -1, 1);
            bodyWidth = Mathf.Max(1, EditorGUILayout.FloatField("Body Width", bodyWidth));
            bodyCount = Mathf.Max(1, EditorGUILayout.IntField("Body slices", bodyCount));

            EditorGUILayout.Space();
            EditorGUILayout.LabelField("Colliders", EditorStyles.boldLabel);

            desc.SingleColliderCapType = (Ferr2D_CapColliderType)EditorGUILayout.EnumPopup("Collider Type", desc.SingleColliderCapType);
            desc.SingleColliderCapSize = EditorGUILayout.Slider("Collider Size", desc.SingleColliderCapSize, -1, 2);

            if (bodyCount != desc.body.Length)
            {
                Rect[] bodies = desc.body;
                Array.Resize <Rect>(ref bodies, bodyCount);
                desc.body = bodies;
            }

            float currX    = pos.x;
            Rect leftCap   = desc.leftCap;
            leftCap.x      = currX;
            leftCap.y      = pos.y;
            leftCap.width  = capWidth;
            leftCap.height = capWidth == 0 ? 0 : height;
            desc.leftCap   = aMat.ToNative(leftCap);
            currX         += capWidth;

            for (int i = 0; i < desc.body.Length; i++)
            {
                desc.body[i].x      = currX;
                desc.body[i].y      = pos.y;
                desc.body[i].width  = bodyWidth;
                desc.body[i].height = height;
                desc.body[i]        = aMat.ToNative(desc.body[i]);
                currX += bodyWidth;
            }

            Rect rightCap   = desc.rightCap;
            rightCap.x      = currX;
            rightCap.y      = pos.y;
            rightCap.width  = capWidth;
            rightCap.height = capWidth == 0 ? 0 : height;
            desc.rightCap   = aMat.ToNative(rightCap);
        });
    }
Example #31
0
	private void AddCap    (List<Vector2> aSegment, Ferr2DT_SegmentDescription aDesc, bool aInner, float aDir, float aScale, bool aSmooth) {
		int     index = 0;
		Vector2 dir   = Vector2.zero;
		if (aDir < 0) {
			index = 0;
			dir   = aSegment[0] - aSegment[1];
		} else {
			index = aSegment.Count-1;
			dir   = aSegment[aSegment.Count-1] - aSegment[aSegment.Count-2];
		}
		dir.Normalize();
        Vector2 norm = aSmooth ? Ferr2D_Path.HermiteGetNormal(aSegment, index, 0, false): Ferr2D_Path.GetNormal(aSegment, index, false);
		Vector2 pos  = aSegment[index];
        float   yOff = fill == Ferr2DT_FillMode.InvertedClosed ? -aDesc.yOffset : aDesc.yOffset;
        Rect cap;
		if (aDir < 0) {
			if (fill == Ferr2DT_FillMode.InvertedClosed) cap = (!aInner && aDesc.innerRightCap.width > 0) ? terrainMaterial.ToUV(aDesc.innerRightCap) : terrainMaterial.ToUV(aDesc.rightCap);
			else                                         cap = ( aInner && aDesc.innerLeftCap .width > 0) ? terrainMaterial.ToUV(aDesc.innerLeftCap ) : terrainMaterial.ToUV(aDesc.leftCap );
		} else        {
			if (fill == Ferr2DT_FillMode.InvertedClosed) cap = (!aInner && aDesc.innerLeftCap .width > 0) ? terrainMaterial.ToUV(aDesc.innerLeftCap ) : terrainMaterial.ToUV(aDesc.leftCap );
			else                                         cap = ( aInner && aDesc.innerRightCap.width > 0) ? terrainMaterial.ToUV(aDesc.innerRightCap) : terrainMaterial.ToUV(aDesc.rightCap);
		}
        
		float width =  cap.width     * unitsPerUV.x;
		float scale = (cap.height/2) * unitsPerUV.y * aScale;

        float minU = fill == Ferr2DT_FillMode.InvertedClosed ? cap.xMax : cap.x;
        float maxU = fill == Ferr2DT_FillMode.InvertedClosed ? cap.x    : cap.xMax;
        float minV = fill == Ferr2DT_FillMode.InvertedClosed ? cap.yMax : cap.y;
        float maxV = fill == Ferr2DT_FillMode.InvertedClosed ? cap.y    : cap.yMax;

        if (aDir >= 0) {
            float t = minU;
            minU = maxU;
            maxU = t;
        }

        int v1  =           DMesh.AddVertex(pos + dir * width + norm * (scale + yOff), -slantAmount + aDesc.zOffset, new Vector2(minU, minV));
        int v2  =           DMesh.AddVertex(pos +               norm * (scale + yOff), -slantAmount + aDesc.zOffset, new Vector2(maxU, minV));

        int v15 = splitMiddle ? DMesh.AddVertex(pos + dir * width +        (norm  * yOff),  aDesc.zOffset,           new Vector2(minU, cap.y + (cap.height / 2))) : -1;
        int v25 = splitMiddle ? DMesh.AddVertex(pos               +        (norm  * yOff),  aDesc.zOffset,           new Vector2(maxU, cap.y + (cap.height / 2))) : -1;

        int v3  =           DMesh.AddVertex(pos -               norm * (scale - yOff),  slantAmount + aDesc.zOffset, new Vector2(maxU, maxV));
        int v4  =           DMesh.AddVertex(pos + dir * width - norm * (scale - yOff),  slantAmount + aDesc.zOffset, new Vector2(minU, maxV));

        if (splitMiddle && aDir < 0) {
            DMesh.AddFace(v1,  v2,  v25, v15);
            DMesh.AddFace(v15, v25, v3,  v4 );
        } else if (splitMiddle && aDir >= 0) {
            DMesh.AddFace(v2,  v1,  v15, v25);
            DMesh.AddFace(v25, v15, v4,  v3 );
        } else if (aDir < 0){
            DMesh.AddFace(v1, v2, v3, v4);
        } else {
            DMesh.AddFace(v2, v1, v4, v3);
        }
	}
    public static void EditUVsComplex(IFerr2DTMaterial aMat, Ferr2DT_SegmentDescription desc, float aWidth, ref int aCurrBody)
    {
        int currBody = aCurrBody;
        int bodyID   = 0;

        Ferr.EditorTools.Box(2, () => {
            if (desc.leftCap.width == 0 && desc.leftCap.height == 0 &&
                desc.rightCap.width == 0 && desc.rightCap.height == 0)
            {
                desc.EditorLeftCapOffset  = EditorGUILayout.Slider("Left Offset", desc.EditorLeftCapOffset, -1, 1);
                desc.EditorRightCapOffset = EditorGUILayout.Slider("Right Offset", desc.EditorRightCapOffset, -1, 1);
            }

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Body", GUILayout.Width(40f));

            bodyID = Mathf.Clamp(currBody, 0, desc.body.Length);
            if (GUILayout.Button("<", GUILayout.Width(20f)))
            {
                currBody = Mathf.Clamp(currBody - 1, 0, desc.body.Length - 1);
            }
            EditorGUILayout.LabelField("" + (bodyID + 1), GUILayout.Width(12f));
            if (GUILayout.Button(">", GUILayout.Width(20f)))
            {
                currBody = Mathf.Clamp(currBody + 1, 0, desc.body.Length - 1);
            }
            bodyID     = Mathf.Clamp(currBody, 0, desc.body.Length - 1);
            int length = Math.Max(1, EditorGUILayout.IntField(desc.body.Length, GUILayout.Width(32f)));
            EditorGUILayout.LabelField("Total", GUILayout.Width(40f));
            if (length != desc.body.Length)
            {
                Rect[] bodies = desc.body;
                Array.Resize <Rect>(ref bodies, length);
                desc.body = bodies;
            }

            EditorGUILayout.EndHorizontal();
            EditorGUILayout.Space();
            desc.body[bodyID] = AtlasField(aMat, desc.body[bodyID], aMat.edgeMaterial != null ? aMat.edgeMaterial.mainTexture : EditorGUIUtility.whiteTexture);

            float pixelWidth = aMat.edgeMaterial == null || aMat.edgeMaterial.mainTexture == null ? 1f / 256 : 1f / aMat.edgeMaterial.mainTexture.width;
            if (desc.body[bodyID].width < pixelWidth)
            {
                desc.body[bodyID].width = pixelWidth;
            }
        });
        aCurrBody = currBody;

        EditorGUILayout.Space();
        Ferr.EditorTools.Box(2, () => {
            if (desc.leftCap.width == 0 && desc.leftCap.height == 0)
            {
                if (EditorGUILayout.Toggle("Left Cap", false))
                {
                    desc.leftCap = aMat.ToNative(new Rect(0, 0, 50, 50));
                }
            }
            else
            {
                if (EditorGUILayout.Toggle("Left Cap", true))
                {
                    desc.EditorLeftCapOffset = EditorGUILayout.Slider("Cap Offset", desc.EditorLeftCapOffset, -1, 1);
                    desc.leftCap             = AtlasField(aMat, desc.leftCap, aMat.edgeMaterial != null ? aMat.edgeMaterial.mainTexture : EditorGUIUtility.whiteTexture);
                }
                else
                {
                    desc.leftCap = new Rect(0, 0, 0, 0);
                }
            }
            EditorGUI.indentLevel         += 1;
            desc.EditorLeftCapType         = Convert.ToInt32(EditorGUILayout.EnumPopup("Collider Type", (Ferr2D_CapColliderType)desc.EditorLeftCapType));
            desc.EditorLeftCapColliderSize = EditorGUILayout.Slider("Collider Size", desc.EditorLeftCapColliderSize, -1, 2);
            EditorGUI.indentLevel         -= 1;
        });

        EditorGUILayout.Space();
        Ferr.EditorTools.Box(2, () => {
            if (desc.innerLeftCap.width == 0 && desc.innerLeftCap.height == 0)
            {
                if (EditorGUILayout.Toggle("Inner Left Cap", false))
                {
                    desc.innerLeftCap = aMat.ToNative(new Rect(0, 0, 50, 50));
                }
            }
            else
            {
                if (EditorGUILayout.Toggle("Inner Left Cap", true))
                {
                    Ferr.EditorTools.Box(2, () => {
                        desc.EditorInnerLeftCapOffset = EditorGUILayout.Slider("Cap Offset", desc.EditorInnerLeftCapOffset, -1, 1);
                        desc.innerLeftCap             = AtlasField(aMat, desc.innerLeftCap, aMat.edgeMaterial != null ? aMat.edgeMaterial.mainTexture : EditorGUIUtility.whiteTexture);
                    });
                }
                else
                {
                    desc.innerLeftCap = new Rect(0, 0, 0, 0);
                }
            }
            EditorGUI.indentLevel              += 1;
            desc.EditorInnerLeftCapType         = Convert.ToInt32(EditorGUILayout.EnumPopup("Collider Type", (Ferr2D_CapColliderType)desc.EditorInnerLeftCapType));
            desc.EditorInnerLeftCapColliderSize = EditorGUILayout.Slider("Collider Size", desc.EditorInnerLeftCapColliderSize, -1, 2);
            EditorGUI.indentLevel              -= 1;
        });

        EditorGUILayout.Space();
        Ferr.EditorTools.Box(2, () => {
            if (desc.rightCap.width == 0 && desc.rightCap.height == 0)
            {
                if (EditorGUILayout.Toggle("Right Cap", false))
                {
                    desc.rightCap = aMat.ToNative(new Rect(0, 0, 50, 50));
                }
            }
            else
            {
                if (EditorGUILayout.Toggle("Right Cap", true))
                {
                    Ferr.EditorTools.Box(2, () => {
                        desc.EditorRightCapOffset = EditorGUILayout.Slider("Cap Offset", desc.EditorRightCapOffset, -1, 1);
                        desc.rightCap             = AtlasField(aMat, desc.rightCap, aMat.edgeMaterial != null ? aMat.edgeMaterial.mainTexture : EditorGUIUtility.whiteTexture);
                    });
                }
                else
                {
                    desc.rightCap = new Rect(0, 0, 0, 0);
                }
            }
            EditorGUI.indentLevel          += 1;
            desc.EditorRightCapType         = Convert.ToInt32(EditorGUILayout.EnumPopup("Collider Type", (Ferr2D_CapColliderType)desc.EditorRightCapType));
            desc.EditorRightCapColliderSize = EditorGUILayout.Slider("Collider Size", desc.EditorRightCapColliderSize, -1, 2);
            EditorGUI.indentLevel          -= 1;
        });

        EditorGUILayout.Space();
        Ferr.EditorTools.Box(2, () => {
            if (desc.innerRightCap.width == 0 && desc.innerRightCap.height == 0)
            {
                if (EditorGUILayout.Toggle("Inner Right Cap", false))
                {
                    desc.innerRightCap = aMat.ToNative(new Rect(0, 0, 50, 50));
                }
            }
            else
            {
                if (EditorGUILayout.Toggle("Inner Right Cap", true))
                {
                    Ferr.EditorTools.Box(2, () => {
                        desc.EditorInnerRightCapOffset = EditorGUILayout.Slider("Cap Offset", desc.EditorInnerRightCapOffset, -1, 1);
                        desc.innerRightCap             = AtlasField(aMat, desc.innerRightCap, aMat.edgeMaterial != null ? aMat.edgeMaterial.mainTexture : EditorGUIUtility.whiteTexture);
                    });
                }
                else
                {
                    desc.innerRightCap = new Rect(0, 0, 0, 0);
                }
            }
            EditorGUI.indentLevel               += 1;
            desc.EditorInnerRightCapType         = Convert.ToInt32(EditorGUILayout.EnumPopup("Collider Type", (Ferr2D_CapColliderType)desc.EditorInnerRightCapType));
            desc.EditorInnerRightCapColliderSize = EditorGUILayout.Slider("Collider Size", desc.EditorInnerRightCapColliderSize, -1, 2);
            EditorGUI.indentLevel               -= 1;
        });
    }
Example #33
0
    private void SlicedQuad(List <Vector2> aSegment, int aVert, float aStart, float aEnd, int aCuts, bool aSmoothed, bool aClosed, Ferr2DT_SegmentDescription aDesc, float aStartScale, float aEndScale)
    {
        Vector2[] pos    = new Vector2[aCuts];
        Vector2[] norm   = new Vector2[aCuts];
        float  [] scales = new float  [aCuts];
        Vector3   tn1    = Ferr2D_Path.GetNormal(aSegment, aVert, aClosed);
        Vector3   tn2    = Ferr2D_Path.GetNormal(aSegment, aVert + 1, aClosed);

        // get the data needed to make the quad
        for (int i = 0; i < aCuts; i++)
        {
            float percent = aStart + (i / (float)(aCuts - 1)) * (aEnd - aStart);
            if (aSmoothed)
            {
                pos [i] = Ferr2D_Path.HermiteGetPt(aSegment, aVert, percent, aClosed);
                norm[i] = Ferr2D_Path.HermiteGetNormal(aSegment, aVert, percent, aClosed);
            }
            else
            {
                pos [i] = Vector2.Lerp(aSegment[aVert], aSegment[aVert + 1], percent);
                norm[i] = Vector2.Lerp(tn1, tn2, percent);
            }
            scales[i] = Mathf.Lerp(aStartScale, aEndScale, (i / (float)(aCuts - 1)));
        }

        int tSeed = 0;

        if (randomByWorldCoordinates)
        {
            tSeed = UnityEngine.Random.seed;
            UnityEngine.Random.seed = (int)(pos[0].x * 700000 + pos[0].y * 30000);
        }

        Rect  body = terrainMaterial.ToUV(aDesc.body[UnityEngine.Random.Range(0, aDesc.body.Length)]);
        float d    = (body.height / 2) * unitsPerUV.y;
        float yOff = fill == Ferr2DT_FillMode.InvertedClosed ? -aDesc.yOffset : aDesc.yOffset;

        if (randomByWorldCoordinates)
        {
            UnityEngine.Random.seed = tSeed;
        }

        // put the data together into a mesh
        int p1 = 0, p2 = 0, p3 = 0;

        for (int i = 0; i < aCuts; i++)
        {
            float percent = (i / (float)(aCuts - 1));

            Vector3 pos1 = pos [i];
            Vector3 n1   = norm[i];
            int     v1   = DMesh.AddVertex(pos1.x + n1.x * (d * scales[i] + yOff), pos1.y + n1.y * (d * scales[i] + yOff), -slantAmount + aDesc.zOffset, Mathf.Lerp(body.x, body.xMax, percent), fill == Ferr2DT_FillMode.InvertedClosed ? body.yMax : body.y);
            int     v2   = DMesh.AddVertex(pos1.x - n1.x * (d * scales[i] - yOff), pos1.y - n1.y * (d * scales[i] - yOff), slantAmount + aDesc.zOffset, Mathf.Lerp(body.x, body.xMax, percent), fill == Ferr2DT_FillMode.InvertedClosed ? body.y    : body.yMax);
            int     v3   = splitMiddle ? DMesh.AddVertex(pos1.x + n1.x * yOff, pos1.y + n1.y * yOff, aDesc.zOffset, Mathf.Lerp(body.x, body.xMax, percent), Mathf.Lerp(body.y, body.yMax, 0.5f)) : -1;

            if (i != 0)
            {
                if (!splitMiddle)
                {
                    DMesh.AddFace(v2, p2, p1, v1);
                }
                else
                {
                    DMesh.AddFace(v2, p2, p3, v3);
                    DMesh.AddFace(v3, p3, p1, v1);
                }
            }

            p1 = v1;
            p2 = v2;
            p3 = v3;
        }
    }
Example #34
0
    private void AddCap(List <Vector2> aSegment, Ferr2DT_SegmentDescription aDesc, bool aInner, float aDir, float aScale, bool aSmooth)
    {
        int     index = 0;
        Vector2 dir   = Vector2.zero;

        if (aDir < 0)
        {
            index = 0;
            dir   = aSegment[0] - aSegment[1];
        }
        else
        {
            index = aSegment.Count - 1;
            dir   = aSegment[aSegment.Count - 1] - aSegment[aSegment.Count - 2];
        }
        dir.Normalize();
        Vector2 norm = aSmooth ? Ferr2D_Path.HermiteGetNormal(aSegment, index, 0, false): Ferr2D_Path.GetNormal(aSegment, index, false);
        Vector2 pos  = aSegment[index];
        float   yOff = fill == Ferr2DT_FillMode.InvertedClosed ? -aDesc.yOffset : aDesc.yOffset;
        Rect    cap;

        if (aDir < 0)
        {
            if (fill == Ferr2DT_FillMode.InvertedClosed)
            {
                cap = (!aInner && aDesc.innerRightCap.width > 0) ? terrainMaterial.ToUV(aDesc.innerRightCap) : terrainMaterial.ToUV(aDesc.rightCap);
            }
            else
            {
                cap = (aInner && aDesc.innerLeftCap.width > 0) ? terrainMaterial.ToUV(aDesc.innerLeftCap) : terrainMaterial.ToUV(aDesc.leftCap);
            }
        }
        else
        {
            if (fill == Ferr2DT_FillMode.InvertedClosed)
            {
                cap = (!aInner && aDesc.innerLeftCap.width > 0) ? terrainMaterial.ToUV(aDesc.innerLeftCap) : terrainMaterial.ToUV(aDesc.leftCap);
            }
            else
            {
                cap = (aInner && aDesc.innerRightCap.width > 0) ? terrainMaterial.ToUV(aDesc.innerRightCap) : terrainMaterial.ToUV(aDesc.rightCap);
            }
        }

        float width = cap.width * unitsPerUV.x;
        float scale = (cap.height / 2) * unitsPerUV.y * aScale;

        float minU = fill == Ferr2DT_FillMode.InvertedClosed ? cap.xMax : cap.x;
        float maxU = fill == Ferr2DT_FillMode.InvertedClosed ? cap.x    : cap.xMax;
        float minV = fill == Ferr2DT_FillMode.InvertedClosed ? cap.yMax : cap.y;
        float maxV = fill == Ferr2DT_FillMode.InvertedClosed ? cap.y    : cap.yMax;

        if (aDir >= 0)
        {
            float t = minU;
            minU = maxU;
            maxU = t;
        }

        int v1 = DMesh.AddVertex(pos + dir * width + norm * (scale + yOff), -slantAmount + aDesc.zOffset, new Vector2(minU, minV));
        int v2 = DMesh.AddVertex(pos + norm * (scale + yOff), -slantAmount + aDesc.zOffset, new Vector2(maxU, minV));

        int v15 = splitMiddle ? DMesh.AddVertex(pos + dir * width + (norm * yOff), aDesc.zOffset, new Vector2(minU, cap.y + (cap.height / 2))) : -1;
        int v25 = splitMiddle ? DMesh.AddVertex(pos + (norm * yOff), aDesc.zOffset, new Vector2(maxU, cap.y + (cap.height / 2))) : -1;

        int v3 = DMesh.AddVertex(pos - norm * (scale - yOff), slantAmount + aDesc.zOffset, new Vector2(maxU, maxV));
        int v4 = DMesh.AddVertex(pos + dir * width - norm * (scale - yOff), slantAmount + aDesc.zOffset, new Vector2(minU, maxV));

        if (splitMiddle && aDir < 0)
        {
            DMesh.AddFace(v1, v2, v25, v15);
            DMesh.AddFace(v15, v25, v3, v4);
        }
        else if (splitMiddle && aDir >= 0)
        {
            DMesh.AddFace(v2, v1, v15, v25);
            DMesh.AddFace(v25, v15, v4, v3);
        }
        else if (aDir < 0)
        {
            DMesh.AddFace(v1, v2, v3, v4);
        }
        else
        {
            DMesh.AddFace(v2, v1, v4, v3);
        }
    }
    public static bool IsSimple(Ferr2DT_SegmentDescription aDesc)
    {
        float y       = aDesc.body[0].y;
        bool  hasCaps = aDesc.leftCap.width != 0 || aDesc.rightCap.width != 0;
        float height  = aDesc.body[0].height;

        if (hasCaps && (aDesc.leftCap.y      != y      || aDesc.rightCap.y != y))           return false;
        if (hasCaps &&  aDesc.leftCap.xMax   != aDesc.body[0].x)                            return false;
        if (hasCaps &&  aDesc.rightCap.x     != aDesc.body[aDesc.body.Length - 1].xMax)     return false;
        if (hasCaps && (aDesc.leftCap.height != height || aDesc.rightCap.height != height)) return false;

        for (int i = 0; i < aDesc.body.Length; i++) {
            if (aDesc.body[i].y      != aDesc.leftCap.y)                                return false;
            if (aDesc.body[i].height != height)                                         return false;
            if (i + 1 < aDesc.body.Length && aDesc.body[i].xMax != aDesc.body[i + 1].x) return false;
        }
        return true;
    }
Example #36
0
	private void SlicedQuad(List<Vector2> aSegment, int aVert, float aStart, float aEnd, int aCuts, bool aSmoothed, bool aClosed, Ferr2DT_SegmentDescription aDesc, float aStartScale, float aEndScale) {
        Vector2[] pos    = new Vector2[aCuts];
		Vector2[] norm   = new Vector2[aCuts];
        float  [] scales = new float  [aCuts];
		Vector3   tn1  = Ferr2D_Path.GetNormal(aSegment, aVert,   aClosed);
		Vector3   tn2  = Ferr2D_Path.GetNormal(aSegment, aVert+1, aClosed);

        // get the data needed to make the quad
        for (int i = 0; i < aCuts; i++) {
            float percent = aStart + (i / (float)(aCuts - 1)) * (aEnd - aStart);
            if (aSmoothed) {
                pos [i] = Ferr2D_Path.HermiteGetPt    (aSegment, aVert, percent, aClosed);
                norm[i] = Ferr2D_Path.HermiteGetNormal(aSegment, aVert, percent, aClosed);
            } else {
                pos [i] = Vector2.Lerp(aSegment[aVert], aSegment[aVert + 1], percent);
                norm[i] = Vector2.Lerp(tn1,             tn2,                 percent);
            }
            scales[i] = Mathf.Lerp(aStartScale, aEndScale, (i / (float)(aCuts - 1)));
        }

        int tSeed = 0;
        if (randomByWorldCoordinates) {
            tSeed = UnityEngine.Random.seed;
            UnityEngine.Random.seed = (int)(pos[0].x * 700000 + pos[0].y * 30000);
        }

        Rect  body  = terrainMaterial.ToUV(aDesc.body[UnityEngine.Random.Range(0, aDesc.body.Length)]);
		float d     = (body.height / 2) * unitsPerUV.y;
		float yOff  = fill == Ferr2DT_FillMode.InvertedClosed ? -aDesc.yOffset : aDesc.yOffset;
        if (randomByWorldCoordinates) {
            UnityEngine.Random.seed = tSeed;
        }

        // put the data together into a mesh
		int p1=0, p2=0, p3=0;
		for (int i = 0; i < aCuts; i++) {
			float percent = (i/(float)(aCuts-1));

			Vector3 pos1 = pos [i  ];
			Vector3 n1   = norm[i  ];
			int   v1 = DMesh.AddVertex(pos1.x + n1.x * (d*scales[i] + yOff), pos1.y + n1.y * (d*scales[i] + yOff), -slantAmount + aDesc.zOffset, Mathf.Lerp(body.x, body.xMax, percent), fill == Ferr2DT_FillMode.InvertedClosed ? body.yMax : body.y   );
			int   v2 = DMesh.AddVertex(pos1.x - n1.x * (d*scales[i] - yOff), pos1.y - n1.y * (d*scales[i] - yOff),  slantAmount + aDesc.zOffset, Mathf.Lerp(body.x, body.xMax, percent), fill == Ferr2DT_FillMode.InvertedClosed ? body.y    : body.yMax);
			int   v3 = splitMiddle ? DMesh.AddVertex(pos1.x + n1.x * yOff, pos1.y + n1.y * yOff, aDesc.zOffset, Mathf.Lerp(body.x, body.xMax, percent), Mathf.Lerp(body.y,body.yMax,0.5f)) : -1;

			if (i != 0) {
				if (!splitMiddle) {
					DMesh.AddFace(v2, p2, p1, v1);
				} else {
					DMesh.AddFace(v2, p2, p3, v3);
					DMesh.AddFace(v3, p3, p1, v1);
				}
			}

			p1 = v1;
			p2 = v2;
			p3 = v3;
		}
	}
    public static void EditUVsComplex(Ferr2DT_TerrainMaterial aMat, Ferr2DT_SegmentDescription desc, float aWidth, ref int aCurrBody)
    {
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Body", GUILayout.Width(40f));

        int bodyID = Mathf.Clamp(aCurrBody, 0, desc.body.Length);

        if (GUILayout.Button("<", GUILayout.Width(20f)))
        {
            aCurrBody = Mathf.Clamp(aCurrBody - 1, 0, desc.body.Length - 1);
        }
        EditorGUILayout.LabelField("" + (bodyID + 1), GUILayout.Width(12f));
        if (GUILayout.Button(">", GUILayout.Width(20f)))
        {
            aCurrBody = Mathf.Clamp(aCurrBody + 1, 0, desc.body.Length - 1);
        }
        bodyID = Mathf.Clamp(aCurrBody, 0, desc.body.Length - 1);
        int length = Math.Max(1, EditorGUILayout.IntField(desc.body.Length, GUILayout.Width(32f)));

        EditorGUILayout.LabelField("Total", GUILayout.Width(40f));
        if (length != desc.body.Length)
        {
            Array.Resize <Rect>(ref desc.body, length);
        }

        EditorGUILayout.EndHorizontal();

        EditorGUILayout.Space();
        desc.body[bodyID] = AtlasField(aMat, desc.body[bodyID], aMat.edgeMaterial != null ? aMat.edgeMaterial.mainTexture : EditorGUIUtility.whiteTexture);
        if (desc.leftCap.width == 0 && desc.leftCap.height == 0)
        {
            if (EditorGUILayout.Toggle("Left Cap", false))
            {
                desc.leftCap = new Rect(0, 0, 30, 30);
            }
        }
        else
        {
            if (EditorGUILayout.Toggle("Left Cap", true))
            {
                desc.leftCap = AtlasField(aMat, desc.leftCap, aMat.edgeMaterial != null ? aMat.edgeMaterial.mainTexture : EditorGUIUtility.whiteTexture);
            }
            else
            {
                desc.leftCap = new Rect(0, 0, 0, 0);
            }
        }
        if (desc.innerLeftCap.width == 0 && desc.innerLeftCap.height == 0)
        {
            if (EditorGUILayout.Toggle("Inner Left Cap", false))
            {
                desc.innerLeftCap = new Rect(0, 0, 30, 30);
            }
        }
        else
        {
            if (EditorGUILayout.Toggle("Inner Left Cap", true))
            {
                desc.innerLeftCap = AtlasField(aMat, desc.innerLeftCap, aMat.edgeMaterial != null ? aMat.edgeMaterial.mainTexture : EditorGUIUtility.whiteTexture);
            }
            else
            {
                desc.innerLeftCap = new Rect(0, 0, 0, 0);
            }
        }

        if (desc.rightCap.width == 0 && desc.rightCap.height == 0)
        {
            if (EditorGUILayout.Toggle("Right Cap", false))
            {
                desc.rightCap = new Rect(0, 0, 30, 30);
            }
        }
        else
        {
            if (EditorGUILayout.Toggle("Right Cap", true))
            {
                desc.rightCap = AtlasField(aMat, desc.rightCap, aMat.edgeMaterial != null ? aMat.edgeMaterial.mainTexture : EditorGUIUtility.whiteTexture);
            }
            else
            {
                desc.rightCap = new Rect(0, 0, 0, 0);
            }
        }
        if (desc.innerRightCap.width == 0 && desc.innerRightCap.height == 0)
        {
            if (EditorGUILayout.Toggle("Inner Right Cap", false))
            {
                desc.innerRightCap = new Rect(0, 0, 30, 30);
            }
        }
        else
        {
            if (EditorGUILayout.Toggle("Inner Right Cap", true))
            {
                desc.innerRightCap = AtlasField(aMat, desc.innerRightCap, aMat.edgeMaterial != null ? aMat.edgeMaterial.mainTexture : EditorGUIUtility.whiteTexture);
            }
            else
            {
                desc.innerRightCap = new Rect(0, 0, 0, 0);
            }
        }
    }
    public static void ShowPreviewDirection(Ferr2DT_TerrainMaterial aMat, Ferr2DT_TerrainDirection aDir, Rect aBounds, bool aSimpleUVs, bool aEditable)
    {
        Ferr2DT_SegmentDescription desc = aMat.GetDescriptor(aDir);

        if (!aMat.Has(aDir))
        {
            return;
        }

        if (!aEditable)
        {
            for (int i = 0; i < desc.body.Length; i++)
            {
                Ferr.EditorTools.DrawRect(aMat.ToScreen(desc.body[i]), aBounds);
            }
            Ferr.EditorTools.DrawRect(aMat.ToScreen(desc.leftCap), aBounds);
            Ferr.EditorTools.DrawRect(aMat.ToScreen(desc.rightCap), aBounds);
            Ferr.EditorTools.DrawRect(aMat.ToScreen(desc.innerLeftCap), aBounds);
            Ferr.EditorTools.DrawRect(aMat.ToScreen(desc.innerRightCap), aBounds);
        }
        else if (aSimpleUVs)
        {
            float   height    = MaxHeight(desc);
            float   capWidth  = Mathf.Max(desc.leftCap.width, desc.rightCap.width);
            float   bodyWidth = desc.body[0].width;
            int     bodyCount = desc.body.Length;
            float   texWidth  = aMat.edgeMaterial.mainTexture != null ? aMat.edgeMaterial.mainTexture.width  : 1;
            float   texHeight = aMat.edgeMaterial.mainTexture != null ? aMat.edgeMaterial.mainTexture.height : 1;
            Vector2 pos       = new Vector2(desc.leftCap.x, desc.leftCap.y);
            if (desc.leftCap.width == 0 && desc.leftCap.height == 0)
            {
                pos = new Vector2(desc.body[0].x, desc.body[0].y);
            }

            Rect bounds = new Rect(pos.x, pos.y, capWidth * 2 + bodyWidth * bodyCount, height);
            bounds = aMat.ToNative(Ferr.EditorTools.UVRegionRect(aMat.ToPixels(bounds), aBounds));
            bounds = ClampRect(bounds, (Texture2D)aMat.edgeMaterial.mainTexture);

            Ferr.EditorTools.DrawVLine(new Vector2((pos.x + capWidth) * texWidth + aBounds.x, (pos.y * texHeight) + 2), height * texHeight);
            for (int i = 1; i <= desc.body.Length; i++)
            {
                Ferr.EditorTools.DrawVLine(new Vector2((pos.x + capWidth + bodyWidth * i) * texWidth + aBounds.x, (pos.y * texHeight) + 2), height * texHeight);
            }

            height    = bounds.height;
            bodyWidth = (bounds.width - capWidth * 2) / bodyCount;
            pos.x     = bounds.x;
            pos.y     = bounds.y;

            float currX = pos.x;
            desc.leftCap.x      = currX;
            desc.leftCap.y      = pos.y;
            desc.leftCap.width  = capWidth;
            desc.leftCap.height = capWidth == 0 ? 0 : height;
            currX += capWidth;

            for (int i = 0; i < desc.body.Length; i++)
            {
                desc.body[i].x      = currX;
                desc.body[i].y      = pos.y;
                desc.body[i].width  = bodyWidth;
                desc.body[i].height = height;
                currX += bodyWidth;
            }

            desc.rightCap.x      = currX;
            desc.rightCap.y      = pos.y;
            desc.rightCap.width  = capWidth;
            desc.rightCap.height = capWidth == 0 ? 0 : height;
        }
        else
        {
            for (int i = 0; i < desc.body.Length; i++)
            {
                desc.body[i] = ClampRect(aMat.ToNative(Ferr.EditorTools.UVRegionRect(aMat.ToPixels(desc.body[i]), aBounds)), (Texture2D)aMat.edgeMaterial.mainTexture);
            }
            if (desc.leftCap.width != 0 && desc.leftCap.height != 0)
            {
                desc.leftCap = ClampRect(aMat.ToNative(Ferr.EditorTools.UVRegionRect(aMat.ToPixels(desc.leftCap), aBounds)), (Texture2D)aMat.edgeMaterial.mainTexture);
            }
            if (desc.rightCap.width != 0 && desc.rightCap.height != 0)
            {
                desc.rightCap = ClampRect(aMat.ToNative(Ferr.EditorTools.UVRegionRect(aMat.ToPixels(desc.rightCap), aBounds)), (Texture2D)aMat.edgeMaterial.mainTexture);
            }

            if (desc.innerLeftCap.width != 0 && desc.innerLeftCap.height != 0)
            {
                desc.innerLeftCap = ClampRect(aMat.ToNative(Ferr.EditorTools.UVRegionRect(aMat.ToPixels(desc.innerLeftCap), aBounds)), (Texture2D)aMat.edgeMaterial.mainTexture);
            }
            if (desc.innerRightCap.width != 0 && desc.innerRightCap.height != 0)
            {
                desc.innerRightCap = ClampRect(aMat.ToNative(Ferr.EditorTools.UVRegionRect(aMat.ToPixels(desc.innerRightCap), aBounds)), (Texture2D)aMat.edgeMaterial.mainTexture);
            }
        }
    }