// Rotates object facing and wall attached to
    public LevelWall Rotate(LevelTile tile)
    {
        if (mFacing == LookingDirection.North)
        {
            // object is placed at wallSouth
            mFacing         = LookingDirection.East;
            mWallAttachedTo = tile.WallWest;
        }
        else if (mFacing == LookingDirection.East)
        {
            // object is placed at wallWest
            mFacing         = LookingDirection.South;
            mWallAttachedTo = tile.WallNorth;
        }
        else if (mFacing == LookingDirection.South)
        {
            // object is placed at wallSouth
            mFacing         = LookingDirection.West;
            mWallAttachedTo = tile.WallEast;
        }
        else if (mFacing == LookingDirection.West)
        {
            // object is placed at wallSouth
            mFacing         = LookingDirection.North;
            mWallAttachedTo = tile.WallSouth;
        }

        return(mWallAttachedTo);
    }
Beispiel #2
0
    // Use this for initialization
    void Start()
    {
        AttachedToWall obj = gameObject.GetComponent <AttachedToWall>();

        mWallAttachedTo = obj.mWallAttachedTo;

        GetComponent <Triggerable>().mReceiverState = mState;
    }
Beispiel #3
0
 void Awake()
 {
     mWallNorth = transform.FindChild("WallNorth").GetComponent <LevelWall>();
     mWallSouth = transform.FindChild("WallSouth").GetComponent <LevelWall>();
     mWallWest  = transform.FindChild("WallWest").GetComponent <LevelWall>();
     mWallEast  = transform.FindChild("WallEast").GetComponent <LevelWall>();
     mFloor     = transform.FindChild("Floor").GetComponent <LevelWall>();
     mCeiling   = transform.FindChild("Ceiling").GetComponent <LevelWall>();
 }
Beispiel #4
0
    private void CreateWall(LevelCell cell, LevelCell otherCell, LevelDirection direction, Canvas twoDMap)
    {
        LevelWall wall = Instantiate(wallPrefab) as LevelWall;

        wall.Initialize(cell, otherCell, direction);
        if (otherCell != null)
        {
            wall = Instantiate(wallPrefab) as LevelWall;
            wall.Initialize(otherCell, cell, direction.GetOpposite());
        }
        CreateTwoDWall(cell, twoDMap, direction);
    }
Beispiel #5
0
    // Use this for initialization
    void Start()
    {
        wallAttachObject = gameObject.GetComponent <AttachedToWall>();
        mWallAttachedTo  = wallAttachObject.mWallAttachedTo;

        if (mWallAttachedTo)
        {
            mWallAttachedTo.SetPassabble(mOpen);
        }

        if (mMatOpen == null)
        {
            SetMaterials("Wall_Stone_Door");
        }

        GetComponent <Triggerable>().mReceiverState = mOpen;
    }
Beispiel #6
0
    private LevelVertex GetVertex(float x, float y, LevelWall wall)
    {
        for (int i = 0; i < Vertices.Count; i++)
        {
            if (Vertices[i].X == x &&
                Vertices[i].Y == y)
            {
                Vertices[i].Walls.Add(wall);
                return(Vertices[i]);
            }
        }

        LevelVertex nv = new LevelVertex();

        nv.X = x;
        nv.Y = y;
        nv.Walls.Add(wall);
        Vertices.Add(nv);
        return(nv);
    }
Beispiel #7
0
 public static (Vector2 pointA, Vector2 pointB) ToVector2(this LevelWall wall)
 => (wall.Points.pointA, wall.Points.pointB);
Beispiel #8
0
 //  Returns Point of intersection if do intersect otherwise default Point (null)
 public static Vector2?FindIntersection(this LevelWall wallA, LevelWall wallB, bool checkIsInLine = false, bool excludeLinePoints = false)
 => wallA.ToVector2().FindIntersection(wallB.ToVector2(), checkIsInLine, excludeLinePoints);
Beispiel #9
0
    void SetMesh()
    {
        if (Filter.mesh)
        {
            Destroy(Filter.mesh);
        }

        List <Material>     materials = new List <Material>();
        List <MeshTopology> topos     = new List <MeshTopology>();

        materials.Add(new Material(MainCamera.MainShader)); // this is for outlines
        topos.Add(MeshTopology.Lines);
        //Renderer.materials = new Material[] { new Material(MainCamera.MainShader), new Material(MainCamera.MainShader) };

        Utils.MeshBuilder mb = new Utils.MeshBuilder();
        for (int i = 0; i < CurrentLevel.Sectors.Count; i++)
        {
            LevelSector sec = CurrentLevel.Sectors[i];

            if (drawAfter >= 0 && i < drawAfter)
            {
                continue;
            }

            int planemesh = mb.CurrentMesh + 1;
            mb.CurrentMesh = 0;
            //if (sec.Walls.Count > 1) Debug.LogFormat("sector {0} has walls", i);
            for (int j = 0; j < sec.Walls.Count; j++)
            {
                LevelWall wall = sec.Walls[j];

                //if (j != 0) continue;

                if (wall.V1.X < 0 || wall.V1.Y < 0 ||
                    wall.V2.X < 0 || wall.V2.Y < 0)
                {
                    continue;
                }

                Color color = new Color(1, 0, 0, 1);
                if (wall.Back != null)
                {
                    color.r = 0;
                    color.g = 1f;
                }

                //if (i == 0) color.g = color.b = 0;
                //else if (i == 10) color.g = color.r = 0;

                // sector 0 = 0
                // sector 10 = +8 (-8) floor height

                float TopFZ1 = wall.Front.Sector.Floor.ZatPoint(wall.V1.X, wall.V1.Y);
                if (wall.Back != null)
                {
                    TopFZ1 = Mathf.Max(TopFZ1, wall.Back.Sector.Floor.ZatPoint(wall.V1.X, wall.V1.Y)); // top point at v1
                }
                float BottomFZ1 = wall.Front.Sector.Floor.ZatPoint(wall.V1.X, wall.V1.Y);
                if (wall.Back != null)
                {
                    BottomFZ1 = Mathf.Min(BottomFZ1, wall.Back.Sector.Floor.ZatPoint(wall.V1.X, wall.V1.Y));
                }
                float TopFZ2 = wall.Front.Sector.Floor.ZatPoint(wall.V2.X, wall.V2.Y);
                if (wall.Back != null)
                {
                    TopFZ2 = Mathf.Max(TopFZ2, wall.Back.Sector.Floor.ZatPoint(wall.V2.X, wall.V2.Y)); // top point at v2
                }
                float BottomFZ2 = wall.Front.Sector.Floor.ZatPoint(wall.V2.X, wall.V2.Y);
                if (wall.Back != null)
                {
                    BottomFZ2 = Mathf.Min(BottomFZ2, wall.Back.Sector.Floor.ZatPoint(wall.V2.X, wall.V2.Y));
                }

                float TopCZ1 = wall.Front.Sector.Ceiling.ZatPoint(wall.V1.X, wall.V1.Y);
                if (wall.Back != null)
                {
                    TopCZ1 = Mathf.Max(TopCZ1, wall.Back.Sector.Ceiling.ZatPoint(wall.V1.X, wall.V1.Y)); // top point at v1
                }
                float BottomCZ1 = wall.Front.Sector.Ceiling.ZatPoint(wall.V1.X, wall.V1.Y);
                if (wall.Back != null)
                {
                    BottomCZ1 = Mathf.Min(BottomCZ1, wall.Back.Sector.Ceiling.ZatPoint(wall.V1.X, wall.V1.Y));
                }
                float TopCZ2 = wall.Front.Sector.Ceiling.ZatPoint(wall.V2.X, wall.V2.Y);
                if (wall.Back != null)
                {
                    TopCZ2 = Mathf.Max(TopCZ2, wall.Back.Sector.Ceiling.ZatPoint(wall.V2.X, wall.V2.Y)); // top point at v2
                }
                float BottomCZ2 = wall.Front.Sector.Ceiling.ZatPoint(wall.V2.X, wall.V2.Y);
                if (wall.Back != null)
                {
                    BottomCZ2 = Mathf.Min(BottomCZ2, wall.Back.Sector.Ceiling.ZatPoint(wall.V2.X, wall.V2.Y));
                }

                if (wall.Back != null)
                {
                    mb.CurrentColor    = color;
                    mb.CurrentPosition = new Vector3(wall.V1.X, wall.V1.Y, TopFZ1);
                    mb.NextVertex();
                    mb.CurrentColor    = color;
                    mb.CurrentPosition = new Vector3(wall.V2.X, wall.V2.Y, TopFZ2);
                    mb.NextVertex();

                    mb.CurrentColor    = color;
                    mb.CurrentPosition = new Vector3(wall.V1.X, wall.V1.Y, TopCZ1);
                    mb.NextVertex();
                    mb.CurrentColor    = color;
                    mb.CurrentPosition = new Vector3(wall.V2.X, wall.V2.Y, TopCZ2);
                    mb.NextVertex();

                    mb.CurrentColor    = color;
                    mb.CurrentPosition = new Vector3(wall.V1.X, wall.V1.Y, BottomFZ1);
                    mb.NextVertex();
                    mb.CurrentColor    = color;
                    mb.CurrentPosition = new Vector3(wall.V2.X, wall.V2.Y, BottomFZ2);
                    mb.NextVertex();

                    mb.CurrentColor    = color;
                    mb.CurrentPosition = new Vector3(wall.V1.X, wall.V1.Y, BottomCZ1);
                    mb.NextVertex();
                    mb.CurrentColor    = color;
                    mb.CurrentPosition = new Vector3(wall.V2.X, wall.V2.Y, BottomCZ2);
                    mb.NextVertex();
                }
                else
                {
                    mb.CurrentColor    = color;
                    mb.CurrentPosition = new Vector3(wall.V1.X, wall.V1.Y, TopFZ1);
                    mb.NextVertex();
                    mb.CurrentColor    = color;
                    mb.CurrentPosition = new Vector3(wall.V2.X, wall.V2.Y, TopFZ2);
                    mb.NextVertex();

                    mb.CurrentColor    = color;
                    mb.CurrentPosition = new Vector3(wall.V1.X, wall.V1.Y, TopCZ1);
                    mb.NextVertex();
                    mb.CurrentColor    = color;
                    mb.CurrentPosition = new Vector3(wall.V2.X, wall.V2.Y, TopCZ2);
                    mb.NextVertex();
                }

                // vertical lines
                if (wall.Back != null)
                {
                    mb.CurrentColor    = color;
                    mb.CurrentPosition = new Vector3(wall.V1.X, wall.V1.Y, TopFZ1);
                    mb.NextVertex();
                    mb.CurrentColor    = color;
                    mb.CurrentPosition = new Vector3(wall.V1.X, wall.V1.Y, BottomFZ1);
                    mb.NextVertex();

                    mb.CurrentColor    = color;
                    mb.CurrentPosition = new Vector3(wall.V2.X, wall.V2.Y, TopFZ2);
                    mb.NextVertex();
                    mb.CurrentColor    = color;
                    mb.CurrentPosition = new Vector3(wall.V2.X, wall.V2.Y, BottomFZ2);
                    mb.NextVertex();

                    mb.CurrentColor    = color;
                    mb.CurrentPosition = new Vector3(wall.V1.X, wall.V1.Y, TopCZ1);
                    mb.NextVertex();
                    mb.CurrentColor    = color;
                    mb.CurrentPosition = new Vector3(wall.V1.X, wall.V1.Y, BottomCZ1);
                    mb.NextVertex();

                    mb.CurrentColor    = color;
                    mb.CurrentPosition = new Vector3(wall.V2.X, wall.V2.Y, TopCZ2);
                    mb.NextVertex();
                    mb.CurrentColor    = color;
                    mb.CurrentPosition = new Vector3(wall.V2.X, wall.V2.Y, BottomCZ2);
                    mb.NextVertex();
                }
                else
                {
                    mb.CurrentColor    = color;
                    mb.CurrentPosition = new Vector3(wall.V1.X, wall.V1.Y, TopFZ1);
                    mb.NextVertex();
                    mb.CurrentColor    = color;
                    mb.CurrentPosition = new Vector3(wall.V1.X, wall.V1.Y, BottomCZ1);
                    mb.NextVertex();

                    mb.CurrentColor    = color;
                    mb.CurrentPosition = new Vector3(wall.V2.X, wall.V2.Y, TopFZ2);
                    mb.NextVertex();
                    mb.CurrentColor    = color;
                    mb.CurrentPosition = new Vector3(wall.V2.X, wall.V2.Y, BottomCZ2);
                    mb.NextVertex();
                }
            }

            // draw floor
            Material    texfloor    = new Material(MainCamera.MainShader);
            RadixBitmap bitmapfloor = TextureManager.GetTextureById(sec.Floor.Texture);
            Vector2     texmul      = new Vector2(bitmapfloor.Width, bitmapfloor.Height);
            if (bitmapfloor != null)
            {
                texfloor.mainTexture = bitmapfloor.Texture;
            }

            Material    texceiling    = new Material(MainCamera.MainShader);
            RadixBitmap bitmapceiling = TextureManager.GetTextureById(sec.Ceiling.Texture);
            Vector2     texmul2       = new Vector2(bitmapceiling.Width, bitmapceiling.Height);
            if (bitmapceiling != null)
            {
                texceiling.mainTexture = bitmapceiling.Texture;
            }

            materials.Add(texfloor);
            materials.Add(texceiling);
            topos.Add(MeshTopology.Triangles);
            topos.Add(MeshTopology.Triangles);

            for (int p = 0; p < 2; p++)
            {
                mb.CurrentMesh = planemesh + p;
                LevelSector.Plane plane = p == 0 ? sec.Floor : sec.Ceiling;
                for (int j = 0; j < sec.Triangles.Count; j++)
                {
                    LevelSector.Triangle tri = sec.Triangles[j];

                    Color color = new Color(0.5f, 0.5f, 0.5f, 1);

                    if (tri.Points.Count != 3)
                    {
                        // now, we know that this mesh is NOT actual triangle list, it consists of points around the sector.
                        Vector2 center = tri.Center;

                        for (int k = 0; k < tri.Points.Count; k++)
                        {
                            // add center point
                            mb.CurrentColor    = color;
                            mb.CurrentPosition = new Vector3(center.x, center.y, plane.ZatPoint(center.x, center.y));
                            mb.CurrentUV1      = new Vector2(center.x / texmul.x, center.y / texmul.y);
                            mb.NextVertex();

                            // add current point
                            int cIndex = k % tri.Points.Count;
                            mb.CurrentColor    = color;
                            mb.CurrentPosition = new Vector3(tri.Points[cIndex].x, tri.Points[cIndex].y, plane.ZatPoint(tri.Points[cIndex].x, tri.Points[cIndex].y));
                            mb.CurrentUV1      = new Vector2(tri.Points[cIndex].x / texmul.x, tri.Points[cIndex].y / texmul.y);
                            mb.NextVertex();

                            // add next point
                            int nIndex = (k + 1) % tri.Points.Count;
                            mb.CurrentColor    = color;
                            mb.CurrentPosition = new Vector3(tri.Points[nIndex].x, tri.Points[nIndex].y, plane.ZatPoint(tri.Points[nIndex].x, tri.Points[nIndex].y));
                            mb.CurrentUV1      = new Vector2(tri.Points[nIndex].x / texmul.x, tri.Points[nIndex].y / texmul.y);
                            mb.NextVertex();
                        }
                    }
                    else // it's a legit triangle, don't overcomplicate
                    {
                        for (int k = 0; k < 3; k++)
                        {
                            mb.CurrentColor    = color;
                            mb.CurrentPosition = new Vector3(tri.Points[k].x, tri.Points[k].y, plane.ZatPoint(tri.Points[k].x, tri.Points[k].y));
                            mb.CurrentUV1      = new Vector2(tri.Points[k].x / texmul.x, tri.Points[k].y / texmul.y);
                            mb.NextVertex();
                        }
                    }
                }
            }

            if (drawAfter >= 0 && i >= drawAfter && sec.Walls.Count > 0)
            {
                Debug.LogFormat("stopped rendering at {0}", i);
                break;
            }
        }

        Filter.mesh        = mb.ToMesh(topos.ToArray());
        Renderer.materials = materials.ToArray();
    }
Beispiel #10
0
    // has parts of Level
    public static List <List <Vector2> > GetLineLoops(LevelSector sec)
    {
        List <List <Vector2> > output = new List <List <Vector2> >();

        HashSet <LevelWall> checkedwalls = new HashSet <LevelWall>();

        while (true)
        {
            List <Vector2> poly      = new List <Vector2>();
            LevelWall      firstwall = null;
            for (int j = 0; j < sec.Walls.Count; j++)
            {
                if (checkedwalls.Contains(sec.Walls[j]))
                {
                    continue;
                }
                firstwall = sec.Walls[j];
                break;
            }

            if (firstwall == null)
            {
                break;
            }

            // take next line loop (polygon)

            LevelWall curwall = firstwall;
            do
            {
                checkedwalls.Add(curwall);

                LevelWall nextwall = null;
                for (int j = 0; j < sec.Walls.Count; j++)
                {
                    LevelWall checkwall = sec.Walls[j];
                    if (checkwall.GetV1(sec) == curwall.GetV2(sec))
                    {
                        nextwall = checkwall;
                        break;
                    }
                }

                poly.Add(new Vector2(curwall.GetV1(sec).X, curwall.GetV1(sec).Y));
                curwall = nextwall;
            }while (curwall != firstwall && curwall != null);
            output.Add(poly);
        }

        if (output[output.Count - 1].Count <= 0)
        {
            output.RemoveAt(output.Count - 1);
        }

        // sort loops
        output = output.OrderBy(o => GetLineLoopArea(o)).Reverse().ToList();

        for (int i = 0; i < output.Count; i++)
        {
            //Debug.LogFormat("loop {0}, lines = {1}, len = {2}, area = {3}", i, output[i].Count, GetLineLoopLength(output[i]), GetLineLoopArea(output[i]));
        }

        return(output);
    }
Beispiel #11
0
    public Level(string filename)
    {
        // 0..0x48 = header
        // 0x49.. = data
        using (MemoryStream ms = ResourceManager.OpenRead(filename))
            using (BinaryReader br = new BinaryReader(ms))
            {
                ms.Position = 0;
                uint level_magic = br.ReadUInt32();
                if (level_magic != 0xFFFFFEE7)
                {
                    throw new LevelException("Invalid level header");
                }

                ms.Position = 0x1D;
                int level_numwalls   = br.ReadInt32();
                int level_numsectors = br.ReadInt32();

                Debug.LogFormat("numwalls = {0}, numsectors = {1}, level = {2}", level_numwalls, level_numsectors, filename);

                Dictionary <int, int> sectorRemap = new Dictionary <int, int>();
                Dictionary <LevelSector, LevelSector> sectorRemapRef = new Dictionary <LevelSector, LevelSector>();

                ms.Position = 0x49;
                for (int i = 0; i < level_numsectors; i++)
                {
                    // sector size = 0x8E
                    long curPos  = ms.Position;
                    long nextPos = ms.Position + 0x8E;

                    LevelSector sec = new LevelSector();

                    ms.Position = curPos + 2;
                    sec.Tag     = Utils.GetNullTermString(br.ReadBytes(0x1A));
                    // for now ignore everything else
                    int sec_texfloor   = br.ReadInt16();
                    int sec_texceiling = br.ReadInt16();
                    sec.Floor.Z         = br.ReadInt16();
                    sec.Ceiling.Z       = br.ReadInt16();
                    sec.Floor.Texture   = sec_texfloor;
                    sec.Ceiling.Texture = sec_texceiling;

                    // 00: ?? ??
                    // 02: name (0x1A long), also known as tag (used in scripting?)
                    // 1C: ## ## (floor texture)
                    // 1E: ## ## (ceiling texture)
                    // // what the f**k is so important in sector structure that it takes 0x6E bytes to store?
                    ms.Position = curPos + 0x25;
                    byte   sec_flags = br.ReadByte();
                    string flagsstr  = "";
                    for (int j = 0; j < 8; j++)
                    {
                        if ((sec_flags & (byte)(1 << j)) != 0)
                        {
                            if (flagsstr != "")
                            {
                                flagsstr += ", ";
                            }
                            if (((1 << j) & 4) != 0)
                            {
                                flagsstr += string.Format("floorslope");
                            }
                            else if (((1 << j) & 8) != 0)
                            {
                                flagsstr += string.Format("ceilingslope");
                            }
                            else
                            {
                                flagsstr += string.Format("unknown:{0:X2}", (byte)(1 << j));
                            }
                        }
                    }
                    if (flagsstr != "")
                    {
                        flagsstr = " (" + flagsstr + ")";
                    }
                    Debug.LogFormat("sector {0}, flags {1}{2}", sec.Tag, sec_flags, flagsstr);

                    if ((sec_flags & 4) != 0) // floor slope
                    {
                        //
                        ReadSlope(ms, br, curPos + 0x26, sec.Floor);
                    }

                    if ((sec_flags & 8) != 0) // ceiling slope
                    {
                        //
                        ReadSlope(ms, br, curPos + 0x36, sec.Ceiling);
                    }

                    // check if such sector already exists
                    sectorRemap[i]      = i;
                    sectorRemapRef[sec] = sec;
                    for (int j = 0; j < Sectors.Count; j++)
                    {
                        LevelSector other = Sectors[j];
                        if (other.Floor.Z == sec.Floor.Z &&
                            other.Ceiling.Z == sec.Ceiling.Z)
                        {
                            sectorRemap[i]      = j;
                            sectorRemapRef[sec] = other;
                            break;
                        }
                    }

                    Sectors.Add(sec);

                    ms.Position = nextPos;
                }

                for (int i = 0; i < level_numwalls; i++)
                {
                    // wall size = 0x56
                    long curPos  = ms.Position;
                    long nextPos = ms.Position + 0x56;

                    LevelWall wall = new LevelWall();

                    ms.Position = curPos + 0x0A;

                    wall.V1 = GetVertex(br.ReadInt32(), br.ReadInt32(), wall);
                    wall.V2 = GetVertex(br.ReadInt32(), br.ReadInt32(), wall);

                    ms.Position = curPos + 0x1A;
                    short wall_ofront = br.ReadInt16();
                    short wall_oback  = br.ReadInt16();
                    short wall_front  = wall_ofront;
                    short wall_back   = wall_oback;

                    if (wall_front < 0)
                    {
                        wall.Front = null;
                    }
                    else
                    {
                        wall.Front        = new LevelWallSide();
                        wall.Front.Wall   = wall;
                        wall.Front.V1     = wall.V1;
                        wall.Front.V2     = wall.V2;
                        wall.Front.Sector = Sectors[wall_front];
                        wall.Front.Sector.Walls.Add(wall);
                    }

                    if (wall_back < 0)
                    {
                        wall.Back = null;
                    }
                    else
                    {
                        wall.Back        = new LevelWallSide();
                        wall.Back.Wall   = wall;
                        wall.Back.V1     = wall.V2;
                        wall.Back.V2     = wall.V1;
                        wall.Back.Sector = Sectors[wall_back];
                        wall.Back.Sector.Walls.Add(wall);
                    }

                    ms.Position = curPos + 0x4E;
                    int wall_texfront = br.ReadInt16(); // this is offset into wall textures, to be changed to a pointer later
                    int wall_texback  = br.ReadInt16();

                    ms.Position = curPos + 0x48;
                    wall.Flags  = (LevelWallFlags)br.ReadUInt32();
                    // for now ignore everything else
                    Walls.Add(wall);

                    //Debug.LogFormat("Wall  Front = {0},  Back = {1},  TextureFront = {2},  TextureBack = {3},  Flags = {4}\nV1 = {5},{6}  V2 = {7},{8}", wall_front, wall_back, wall_texfront, wall_texback, wall.Flags.ToString(), wall.V1.X, wall.V1.Y, wall.V2.X, wall.V2.Y);

                    ms.Position = nextPos;
                }

                // handle unclosed sectors
                // if sector is not closed, we have to find a wall that references a similar sector (using sectorRemap) and remap.
                for (int i = 0; i < Sectors.Count; i++)
                {
                    LevelSector sec = Sectors[i];
                    if (sec.Walls.Count <= 0)
                    {
                        continue;
                    }

                    bool isclosed    = true;
                    int  closedloops = 0;
                    HashSet <LevelWall> checkedwalls = new HashSet <LevelWall>();
                    while (true)
                    {
                        LevelWall firstwall = null;
                        for (int j = 0; j < sec.Walls.Count; j++)
                        {
                            if (checkedwalls.Contains(sec.Walls[j]))
                            {
                                continue;
                            }
                            firstwall = sec.Walls[j];
                            break;
                        }

                        if (firstwall == null)
                        {
                            break;
                        }

                        // take next line loop (polygon)

                        LevelWall curwall = firstwall;
                        do
                        {
                            checkedwalls.Add(curwall);

                            LevelWall nextwall = null;
                            for (int j = 0; j < sec.Walls.Count; j++)
                            {
                                LevelWall checkwall = sec.Walls[j];
                                if (checkwall.GetV1(sec) == curwall.GetV2(sec))
                                {
                                    nextwall = checkwall;
                                    break;
                                }
                            }

                            if (nextwall == null) // sector is not closed. try to find a remapped wall here
                            {
                                for (int j = 0; j < Walls.Count; j++)
                                {
                                    LevelWall rwall = Walls[j];
                                    if (checkedwalls.Contains(rwall) || sec.Walls.Contains(rwall))
                                    {
                                        continue;
                                    }
                                    LevelSector remappedFront = rwall.Front != null ? sectorRemapRef[rwall.Front.Sector] : null;
                                    LevelSector remappedBack  = rwall.Back != null ? sectorRemapRef[rwall.Back.Sector] : null;
                                    LevelSector remappedSelf  = sectorRemapRef[sec];
                                    if ((remappedFront == remappedSelf && rwall.V1 == curwall.GetV2(sec)) ||
                                        (remappedBack == remappedSelf && rwall.V2 == curwall.GetV2(sec)))
                                    {
                                        // add this wall to sector walls
                                        if (remappedFront == remappedSelf)
                                        {
                                            rwall.Front.Sector.Walls.Remove(rwall);
                                            rwall.Front.Sector = sec;
                                            sec.Walls.Add(rwall);
                                        }
                                        else
                                        {
                                            rwall.Back.Sector.Walls.Remove(rwall);
                                            rwall.Back.Sector = sec;
                                            sec.Walls.Add(rwall);
                                        }
                                        nextwall = rwall;
                                    }
                                }
                            }

                            curwall = nextwall;
                        }while (curwall != firstwall && curwall != null);

                        if (curwall == null)
                        {
                            //Debug.LogFormat("sector {0} is not closed", i);
                            isclosed = false;
                        }
                        else
                        {
                            closedloops++;
                        }
                    }
                    if (!isclosed)
                    {
                        //Debug.LogFormat("but has {0} closed loops", closedloops);
                    }
                }

                // based on lines and sectors, build GL nodes like structure
                for (int i = 0; i < Sectors.Count; i++)
                {
                    LevelSector sec = Sectors[i];

                    if (sec.Walls.Count <= 0)
                    {
                        continue;
                    }

                    //if (i != 56)
                    //    continue;

                    //BayazitDecomposer
                    //List<List<Vector2>> polygons = TriangulatorHelper.GetLineLoops(sec);
                    try
                    {
                        List <List <Vector2> > polygons = TriangulatorHelper.MakeTriangles(TriangulatorHelper.GetLineLoops(sec));

                        //Triangulation triangulation = Triangulation.Create(sec);

                        // these polygons should be convex

                        /*for (int j = 0; j < triangulation.Vertices.Count; j += 3)
                         * {
                         *  LevelSector.Triangle tri = new LevelSector.Triangle();
                         *  tri.Points.Add(new Vector2(triangulation.Vertices[j].x, triangulation.Vertices[j].y));
                         *  tri.Points.Add(new Vector2(triangulation.Vertices[j+1].x, triangulation.Vertices[j+1].y));
                         *  tri.Points.Add(new Vector2(triangulation.Vertices[j+2].x, triangulation.Vertices[j+2].y));
                         *  sec.Triangles.Add(tri);
                         * }*/
                        for (int j = 0; j < polygons.Count; j++)
                        {
                            LevelSector.Triangle tri = new LevelSector.Triangle();
                            tri.Points.AddRange(polygons[j]);
                            sec.Triangles.Add(tri);
                        }
                    }
                    catch (NotSupportedException e)
                    {
                        /* ... */
                        sec.Triangles.Clear();
                    }
                }
            }
    }
 public void AddWall(LevelWall newWall)
 {
     AddWalls(new List <LevelWall> {
         newWall
     });
 }