Exemple #1
0
    Material getTexture(Weland.ShapeDescriptor texture)
    {
        int retval = 0;

        for (int i = 0; i < texture.Collection; i++)
        {
            retval += collectionMapping[i];
        }
        retval += texture.Bitmap;

        if (materials.Count > retval && retval >= 0)
        {
            if (GlobalData.landscapeCollections.Contains(texture.Collection))
            {
                RenderSettings.skybox.mainTexture = materials[retval].mainTexture;
                return(Resources.Load <Material>("Materials/transparent"));
            }
            else
            {
                return(materials[retval]);
            }
        }
        else
        {
            //return new Material(Shader.Find("Custom/StandardClippableV2"));
            return(null);
        }
    }
Exemple #2
0
 public System.Drawing.Bitmap GetBitmap(ShapeDescriptor d)
 {
     if (!cache.ContainsKey((ushort)d))
     {
         cache.Add((ushort)d, Weland.Shapes.GetShape(d));
     }
     return(cache[(ushort)d]);
 }
Exemple #3
0
        public override void TexturePolygon(ShapeDescriptor d, List <Point> points)
        {
            System.Drawing.PointF[] pointArray = new System.Drawing.PointF[points.Count];
            for (int i = 0; i < points.Count; ++i)
            {
                pointArray[i].X = (float)points[i].X;
                pointArray[i].Y = (float)points[i].Y;
            }

            graphics.FillPolygon(new TextureBrush(cache.GetBitmap(d)), pointArray);
        }
Exemple #4
0
        public override void TexturePolygon(ShapeDescriptor d, List <Point> points)
        {
            context.Save();

            OutlinePolygon(points);
            using (SurfacePattern pattern = new SurfacePattern(cache.GetSurface(d))) {
                pattern.Extend = Cairo.Extend.Repeat;
                context.SetSource(pattern);
                context.Fill();
            }
            context.Restore();
        }
Exemple #5
0
        // sets up texture palette for this collection
        void UpdateCollection(int collectionIndex)
        {
            bool landscape = collectionIndex >= 27;

            textureStore.Clear();
            Collection      coll = Weland.Shapes.GetCollection(collectionIndex);
            ShapeDescriptor d    = new ShapeDescriptor();

            d.CLUT       = 0;
            d.Collection = (byte)collectionIndex;
            int textureSize = 64;

            for (byte i = 0; i < coll.BitmapCount; ++i)
            {
                d.Bitmap = i;
                System.Drawing.Bitmap bitmap = Weland.Shapes.GetShape(d);
                if (landscape)
                {
                    int W = 192;
                    int H = (int)Math.Round((double)bitmap.Height * W / bitmap.Width);
                    bitmap = ImageUtilities.ResizeImage(bitmap, W, H);
                }
                else
                {
                    bitmap.RotateFlip(System.Drawing.RotateFlipType.Rotate90FlipNone);
                    bitmap = ImageUtilities.ResizeImage(bitmap, textureSize, textureSize);
                }
                textureStore.AppendValues(ImageUtilities.ImageToPixbuf(bitmap));
            }

            textureIcons.PixbufColumn  = 0;
            textureIcons.Columns       = landscape ? 1 : 3;
            textureIcons.RowSpacing    = 0;
            textureIcons.ColumnSpacing = 0;
            textureIcons.Model         = textureStore;

            if (!landscape)
            {
                if (textureTransferMode.Active == 4)
                {
                    textureTransferMode.Active = 0;
                }
                textureTransferMode.Sensitive = true;
            }
            else
            {
                textureTransferMode.Active    = 4;
                textureTransferMode.Sensitive = false;
            }
        }
Exemple #6
0
            public Gdk.Pixmap GetPixmap(ShapeDescriptor d)
            {
                if (!cache.ContainsKey((ushort)d))
                {
                    System.Drawing.Bitmap bitmap = Weland.Shapes.GetShape(d);
                    Gdk.Pixbuf            pixbuf = ImageUtilities.ImageToPixbuf(bitmap);
                    Gdk.Pixmap            pixmap;
                    Gdk.Pixmap            mask;
                    pixbuf.RenderPixmapAndMask(out pixmap, out mask, 0);
                    cache.Add((ushort)d, pixmap);
                }

                return(cache[(ushort)d]);
            }
Exemple #7
0
        public override void TexturePolygon(ShapeDescriptor d, List <Point> points)
        {
            Gdk.Point[] pointArray = new Gdk.Point[points.Count];
            for (int i = 0; i < points.Count; ++i)
            {
                pointArray[i].X = (int)points[i].X;
                pointArray[i].Y = (int)points[i].Y;
            }

            Gdk.GC g = new Gdk.GC(window);
            g.Tile = cache.GetPixmap(d);
            g.Fill = Gdk.Fill.Tiled;
            window.DrawPolygon(g, true, pointArray);
        }
Exemple #8
0
    GameObject createMapItemFromSpriteSequence(int collectionID, int sequenceID, Weland.ShapesFile shapes, string objectName)
    {
        GameObject item   = Instantiate(Resources.Load <GameObject>(objectName));
        GameObject sprite = Instantiate(Resources.Load <GameObject>("spriteObject"));

        sprite.name             = "sprite";
        sprite.transform.parent = item.transform;
        spriteController sc = sprite.GetComponent <spriteController>();

        sc.parent = item;
        sc.type   = GlobalData.spriteType;

        // Debug.Log(sequenceID);
        Collection coll = shapes.GetCollection(collectionID);

        if (sequenceID > coll.sequences.Count)
        {
            sequenceID = coll.sequences.Count - 1;
        }
        Collection.ShapeSequence sequence = coll.sequences[sequenceID];

        float scale = sequence.PixelsToWorld;

        if (scale == 0)
        {
            scale = coll.pixelsToWorld;
        }
        sc.scale = scale;
        // Debug.Log(coll.frames[0].OriginX);
        sc.sideCount = sequence.getRealViewCount(sequence.NoOfViews);
        List <Material> frames = new List <Material>();

        Weland.ShapeDescriptor tex = new Weland.ShapeDescriptor();

        for (int i = 0; i < sequence.FrameIndexes.Count; i++)
        {
            tex.Collection = (byte)collectionID;
            tex.Bitmap     = (byte)coll.frames[sequence.FrameIndexes[i]].BitmapIndex;
            frames.Add(getTexture(tex));
        }

        sc.frames = frames;


        return(item);
    }
Exemple #9
0
        public System.Drawing.Bitmap GetShape(ShapeDescriptor d)
        {
            Collection coll = collections[d.Collection];

            if (d.Bitmap < coll.BitmapCount && d.CLUT < coll.ColorTableCount)
            {
                return(coll.GetShape(d.CLUT, d.Bitmap));
            }
            else
            {
                System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(128, 128);
                using (System.Drawing.Graphics graphics = System.Drawing.Graphics.FromImage(bitmap)) {
                    System.Drawing.Rectangle rect = new System.Drawing.Rectangle(0, 0, 128, 128);
                    graphics.FillRectangle(new System.Drawing.SolidBrush(System.Drawing.Color.FromArgb(127, 127, 127)), rect);
                }

                return(bitmap);
            }
        }
Exemple #10
0
        // This is how Weland does it, the unity version is below
        ////public System.Drawing.Bitmap GetShape(ShapeDescriptor d)
        ////{
        ////    Collection coll = collections[d.Collection];
        ////    if (d.Bitmap < coll.BitmapCount && d.CLUT < coll.ColorTableCount)
        ////    {
        ////        return coll.GetShape(d.CLUT, d.Bitmap);
        ////    }
        ////    else
        ////    {
        ////        System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(128, 128);
        ////        using (System.Drawing.Graphics graphics = System.Drawing.Graphics.FromImage(bitmap))
        ////        {
        ////            System.Drawing.Rectangle rect = new System.Drawing.Rectangle(0, 0, 128, 128);
        ////            graphics.FillRectangle(new System.Drawing.SolidBrush(System.Drawing.Color.FromArgb(127, 127, 127)), rect);
        ////        }

        ////        return bitmap;
        ////    }
        ////}

        public Texture2D GetShape(ShapeDescriptor d)
        {
            Collection coll = collections[d.Collection];

            if (d.Bitmap < coll.BitmapCount && d.CLUT < coll.ColorTableCount)
            {
                var shape = coll.GetShape(d.CLUT, d.Bitmap);
                shape.name = $"CLUT({d.CLUT}) Bitmap({d.Bitmap}) Collection({d.Collection})";
                return(shape);
            }
            else
            {
                // TODO: Generate a uniquely identifiable texture here
                //       like a unique color from a gradient, with
                //       a number for the index in the middle.
                ////Texture2D shape = new Texture2D(128, 128);
                ////shape.name = $"CLUT({d.CLUT}) Bitmap({d.Bitmap})";

                ////Debug.LogWarning($"Generating texture for missing shape! CLUT({d.CLUT}) Bitmap({d.Bitmap})");

                ////return shape;
                return(null);
            }
        }
Exemple #11
0
            public ImageSurface GetSurface(ShapeDescriptor d)
            {
                if (!cache.ContainsKey((ushort)d))
                {
                    System.Drawing.Bitmap bitmap = Weland.Shapes.GetShape(d);
                    byte[] bytes = new byte[bitmap.Width * bitmap.Height * 4];
                    for (int x = 0; x < bitmap.Width; ++x)
                    {
                        for (int y = 0; y < bitmap.Height; ++y)
                        {
                            System.Drawing.Color c = bitmap.GetPixel(x, y);
                            int offset             = (y * bitmap.Width + x) * 4;
                            bytes[offset]     = c.B;
                            bytes[offset + 1] = c.G;
                            bytes[offset + 2] = c.R;
                            bytes[offset + 3] = c.A;
                        }
                    }

                    bcache.Add((ushort)d, bytes);
                    cache.Add((ushort)d, new ImageSurface(bytes, Format.ARGB32, bitmap.Width, bitmap.Height, bitmap.Width * 4));
                }
                return(cache[(ushort)d]);
            }
Exemple #12
0
 public void Load(BinaryReaderBE reader)
 {
     X       = reader.ReadInt16();
     Y       = reader.ReadInt16();
     Texture = (ShapeDescriptor)reader.ReadUInt16();
 }
Exemple #13
0
 public abstract void TexturePolygon(ShapeDescriptor d, List <Point> points);
Exemple #14
0
        public void Load(BinaryReaderBE reader)
        {
            Type        = (PolygonType)reader.ReadInt16();
            Flags       = reader.ReadUInt16();
            Permutation = reader.ReadInt16();
            VertexCount = reader.ReadUInt16();
            for (int i = 0; i < MaxVertexCount; ++i)
            {
                EndpointIndexes[i] = reader.ReadInt16();
            }

            for (int i = 0; i < MaxVertexCount; ++i)
            {
                LineIndexes[i] = reader.ReadInt16();
            }

            FloorTexture   = (ShapeDescriptor)reader.ReadUInt16();
            CeilingTexture = (ShapeDescriptor)reader.ReadUInt16();
            FloorHeight    = reader.ReadInt16();
            CeilingHeight  = reader.ReadInt16();
            FloorLight     = reader.ReadInt16();
            CeilingLight   = reader.ReadInt16();

            reader.ReadInt32(); // area
            FirstObjectIndex = reader.ReadInt16();

            reader.ReadInt16(); // first_exclusion_zone_index
            reader.ReadInt16(); // line_exclusion_zone_count
            reader.ReadInt16(); // point_exclusion_zone_count
            FloorTransferMode   = reader.ReadInt16();
            CeilingTransferMode = reader.ReadInt16();

            for (int i = 0; i < MaxVertexCount; ++i)
            {
                AdjacentPolygonIndexes[i] = reader.ReadInt16();
            }

            reader.ReadInt16(); // first_neighbor_index
            reader.ReadInt16(); // neighbor_count

            reader.ReadInt16(); // center.x
            reader.ReadInt16(); // center.y

            for (int i = 0; i < SideIndexes.Length; ++i)
            {
                SideIndexes[i] = reader.ReadInt16();
            }

            FloorOrigin.Load(reader);
            CeilingOrigin.Load(reader);

            MediaIndex = reader.ReadInt16();
            MediaLight = reader.ReadInt16();

            reader.ReadInt16(); // sound_source_indexes

            AmbientSound = reader.ReadInt16();
            RandomSound  = reader.ReadInt16();

            reader.BaseStream.Seek(2, SeekOrigin.Current);
        }
Exemple #15
0
    IEnumerator makeWorldFromMarathonMap(Weland.Level Level)
    {
        string load = loadingText;

        //marathon maps have y +/- directions swapped so fix that
        for (int i = 0; i < Level.Endpoints.Count; i++)
        {
            Level.Endpoints[i] = new Point(Level.Endpoints[i].X, (short)(0 - Level.Endpoints[i].Y));
        }
        //now we can generate mapsegment objects from each map polygon
        for (int p = 0; p < Level.Polygons.Count; p++)
        {
            GameObject pol = Instantiate(polygon);
            pol.name = "Polygon" + p;
            pol.tag  = "polygon";
            MapSegment seg = pol.GetComponent <MapSegment>();
            segments.Add(seg);
            seg.height = new Vector3(0, (float)(Level.Polygons[p].CeilingHeight - Level.Polygons[p].FloorHeight) / 1024f, 0);
            if (Level.Polygons[p].Type == Weland.PolygonType.Platform)
            {
                foreach (Weland.Platform pl in Level.Platforms)
                {
                    if (pl.PolygonIndex == p)
                    {
                        seg.platform = new PlatformObject();
                        seg.platform.comesFromCeiling         = pl.ComesFromCeiling;
                        seg.platform.comesFromFloor           = pl.ComesFromFloor;
                        seg.platform.initiallyExtended        = pl.InitiallyExtended;
                        seg.platform.maximumHeight            = (float)pl.MaximumHeight / 1024f;
                        seg.platform.minimumHeight            = (float)pl.MinimumHeight / 1024f;
                        seg.platform.speed                    = (float)pl.Speed / 64f;
                        seg.platform.usesNativePolygonHeights = pl.UsesNativePolygonHeights;
                        seg.platform.door            = pl.IsDoor;
                        seg.platform.initiallyActive = pl.InitiallyActive;
                        seg.platform.parent          = seg;
                        seg.platform.activatesAdjacantPlatformsAtEachLevel      = pl.ActivatesAdjacantPlatformsAtEachLevel;
                        seg.platform.activatesAdjacentPlatformsWhenActivating   = pl.ActivatesAdjacentPlatformsWhenActivating;
                        seg.platform.activatesAdjacentPlatformsWhenDeactivating = pl.ActivatesAdjacentPlatformsWhenDeactivating;
                        seg.platform.activatesLight                = pl.ActivatesLight;
                        seg.platform.activatesOnlyOnce             = pl.ActivatesOnlyOnce;
                        seg.platform.cannotBeExternallyDeactivated = pl.CannotBeExternallyDeactivated;
                        seg.platform.causesDamage    = pl.CausesDamage;
                        seg.platform.contractsSlower = pl.ContractsSlower;
                        seg.platform.deactivatesAdjacentPlatformsWhenActivating   = pl.DeactivatesAdjacentPlatformsWhenActivating;
                        seg.platform.deactivatesAdjacentPlatformsWhenDeactivating = pl.DeactivatesAdjacentPlatformsWhenDeactivating;
                        seg.platform.deactivatesAtEachLevel    = pl.DeactivatesAtEachLevel;
                        seg.platform.deactivatesAtInitialLevel = pl.DeactivatesAtInitialLevel;
                        seg.platform.deactivatesLight          = pl.DeactivatesLight;
                        seg.platform.delay = pl.Delay / 30f;
                        seg.platform.delaysBeforeActivation = pl.DelaysBeforeActivation;
                        seg.platform.doesNotActivateParent  = pl.DoesNotActivateParent;
                        seg.platform.extendsFloorToCeiling  = pl.ExtendsFloorToCeiling;
                        seg.platform.isMonsterControllable  = pl.IsMonsterControllable;
                        seg.platform.isPlayerControllable   = pl.IsPlayerControllable;
                        seg.platform.locked = pl.IsLocked;
                        seg.platform.reversesDirectionWhenObstructed = pl.ReversesDirectionWhenObstructed;
                        seg.platform.secret = pl.IsSecret;
                        seg.platform.mapTag = pl.Tag;
                        seg.platform.usesNativePolygonHeights = pl.UsesNativePolygonHeights;
                    }
                }
            }


            if (Level.Polygons[p].MediaIndex >= 0)
            {
                seg.liquid = new Liquid();

                Media media = Level.Medias[Level.Polygons[p].MediaIndex];
                seg.liquid.currentSpeed      = (float)media.CurrentMagnitude / 1024f;
                seg.liquid.currentDirectioin = Quaternion.Euler(0, (float)media.Direction + 90, 0);
                seg.liquid.high       = (float)media.High / 1024f;
                seg.liquid.low        = (float)media.Low / 1024f;
                seg.liquid.mediaLight = lights[media.LightIndex];
                //?? where is the liquid data stored???
                // Material mat = new Material(Shader.Find("Custom/StandardClippableV2"));

                Weland.ShapeDescriptor tex = new Weland.ShapeDescriptor();

                switch (media.Type)
                {
                case MediaType.Water:
                    tex.Collection     = (byte)GlobalData.mediaCollections[0];
                    tex.Bitmap         = (byte)GlobalData.mediaBitmaps[0];
                    seg.liquid.surface = getTexture(tex);
                    seg.liquid.colour  = GlobalData.mediaColours[0];
                    seg.liquid.density = GlobalData.mediaDensities[0];
                    break;

                case MediaType.Lava:
                    tex.Collection     = (byte)GlobalData.mediaCollections[1];
                    tex.Bitmap         = (byte)GlobalData.mediaBitmaps[1];
                    seg.liquid.surface = getTexture(tex);
                    seg.liquid.colour  = GlobalData.mediaColours[1];
                    seg.liquid.density = GlobalData.mediaDensities[1];
                    break;

                case MediaType.Goo:
                    tex.Collection     = (byte)GlobalData.mediaCollections[2];
                    tex.Bitmap         = (byte)GlobalData.mediaBitmaps[2];
                    seg.liquid.surface = getTexture(tex);
                    seg.liquid.colour  = GlobalData.mediaColours[2];
                    seg.liquid.density = GlobalData.mediaDensities[2];
                    break;

                case MediaType.Sewage:
                    tex.Collection     = (byte)GlobalData.mediaCollections[3];
                    tex.Bitmap         = (byte)GlobalData.mediaBitmaps[3];
                    seg.liquid.surface = getTexture(tex);
                    seg.liquid.colour  = GlobalData.mediaColours[3];
                    seg.liquid.density = GlobalData.mediaDensities[3];
                    break;

                case MediaType.Jjaro:
                    tex.Collection     = (byte)GlobalData.mediaCollections[4];
                    tex.Bitmap         = (byte)GlobalData.mediaBitmaps[4];
                    seg.liquid.surface = getTexture(tex);
                    seg.liquid.colour  = GlobalData.mediaColours[4];
                    seg.liquid.density = GlobalData.mediaDensities[4];
                    break;

                default:
                    tex.Collection     = (byte)GlobalData.mediaCollections[0];
                    tex.Bitmap         = (byte)GlobalData.mediaBitmaps[0];
                    seg.liquid.surface = getTexture(tex);
                    seg.liquid.colour  = GlobalData.mediaColours[0];
                    seg.liquid.density = GlobalData.mediaDensities[0];
                    break;
                }

                seg.liquid.parent = seg;
            }

            switch (Level.Polygons[p].Type)
            {
            case Weland.PolygonType.AutomaticExit:
                seg.automaticExit = Level.Polygons[p].Permutation;
                break;

            case Weland.PolygonType.Base:
                seg.mapBase = Level.Polygons[p].Permutation;
                break;

            case Weland.PolygonType.DualMonsterTrigger:
                seg.dualMonsterTrigger = true;
                break;

            case Weland.PolygonType.Glue:
                seg.glue = true;
                break;

            case Weland.PolygonType.GlueTrigger:
                seg.glueTrigger = true;
                break;

            case Weland.PolygonType.Goal:
                seg.goal = true;
                break;

            case Weland.PolygonType.Hill:
                seg.hill = true;
                break;

            case Weland.PolygonType.InvisibleMonsterTrigger:
                seg.invisibleMonsterTrigger = true;
                break;

            case Weland.PolygonType.ItemImpassable:
                seg.itemImpassable = true;
                break;

            case Weland.PolygonType.ItemTrigger:
                seg.itemTrigger = true;
                break;

            case Weland.PolygonType.LightOffTrigger:
                seg.lightOffTrigger = Level.Polygons[p].Permutation;
                break;

            case Weland.PolygonType.LightOnTrigger:
                seg.lightOnTrigger = Level.Polygons[p].Permutation;
                break;

            case Weland.PolygonType.MajorOuch:
                seg.damage = 7;
                break;

            case Weland.PolygonType.MinorOuch:
                seg.damage = 3;
                break;

            case Weland.PolygonType.MonsterImpassable:
                seg.monsterImpassable = true;
                break;

            case Weland.PolygonType.MustBeExplored:
                seg.mustBeExplored = true;
                break;

            case Weland.PolygonType.PlatformOffTrigger:
                seg.platformOffTrigger = Level.Polygons[p].Permutation;
                break;

            case Weland.PolygonType.PlatformOnTrigger:
                seg.platformOnTrigger = Level.Polygons[p].Permutation;
                break;

            case Weland.PolygonType.Superglue:
                seg.superglue = true;
                break;

            case Weland.PolygonType.Teleporter:
                seg.teleporter = Level.Polygons[p].Permutation;
                break;

            case Weland.PolygonType.VisibleMonsterTrigger:
                seg.visibleMonsterTrigger = true;
                break;

            case Weland.PolygonType.ZoneBorder:
                seg.zoneBorder = true;
                break;
            }

            //get the map points that make up the polygon
            List <Vector3> points = new List <Vector3>();
            //find the top most point so we can sort them clockwise to make
            int zPt = 0;
            int xPt = 0;
            for (int ep = 0; ep < Level.Polygons[p].VertexCount; ep++)
            {
                int x = Level.Endpoints[Level.Polygons[p].EndpointIndexes[ep]].X;
                int z = Level.Endpoints[Level.Polygons[p].EndpointIndexes[ep]].Y;

                if (z > Level.Endpoints[Level.Polygons[p].EndpointIndexes[zPt]].Y ||
                    (z == Level.Endpoints[Level.Polygons[p].EndpointIndexes[zPt]].Y && x > Level.Endpoints[Level.Polygons[p].EndpointIndexes[zPt]].X))
                {
                    zPt = ep;
                }
                if (x < Level.Endpoints[Level.Polygons[p].EndpointIndexes[xPt]].X ||
                    (x == Level.Endpoints[Level.Polygons[p].EndpointIndexes[xPt]].X && z > Level.Endpoints[Level.Polygons[p].EndpointIndexes[xPt]].Y))
                {
                    xPt = ep;
                }
            }

            //add the lines and sides for the polygon
            List <Weland.Line> Line  = new List <Weland.Line>();
            List <Weland.Side> Sides = new List <Weland.Side>();
            int currentLine          = -1;
            for (int ln = 0; ln < Level.Polygons[p].VertexCount; ln++)
            {
                Line.Add(Level.Lines[Level.Polygons[p].LineIndexes[ln]]);
                if (Level.Polygons[p].SideIndexes[ln] >= 0)
                {
                    Sides.Add(Level.Sides[Level.Polygons[p].SideIndexes[ln]]);
                }
                //which lines are attached to the vertex
                int ep = -1;
                if (Line[Line.Count - 1].EndpointIndexes[0] == Level.Polygons[p].EndpointIndexes[zPt])
                {
                    ep = 0;
                }
                if (Line[Line.Count - 1].EndpointIndexes[1] == Level.Polygons[p].EndpointIndexes[zPt])
                {
                    ep = 1;
                }
                if (ep >= 0)
                {
                    if (currentLine < 0)
                    {
                        currentLine = ln;
                    }
                    else
                    {
                        int lep = 0;
                        if (Line[currentLine].EndpointIndexes[1] == Line[Line.Count - 1].EndpointIndexes[0] ||
                            Line[currentLine].EndpointIndexes[1] == Line[Line.Count - 1].EndpointIndexes[1])
                        {
                            lep = 1;
                        }
                        Point   point = Level.Endpoints[Line[currentLine].EndpointIndexes[lep]];
                        Vector2 a     = new Vector2(point.X, point.Y);

                        ep  = Line[Line.Count - 1].EndpointIndexes[Mathf.Abs(ep - 1)];
                        lep = Line[currentLine].EndpointIndexes[Mathf.Abs(lep - 1)];
                        //make sure we are going clockwise
                        Vector2 b = new Vector2(Level.Endpoints[lep].X, Level.Endpoints[lep].Y);
                        Vector2 c = new Vector2(Level.Endpoints[ep].X, Level.Endpoints[ep].Y);
                        if (Mathf.Atan2(b.y - a.y, b.x - a.x) < Mathf.Atan2(c.y - a.y, c.x - a.x))
                        {
                            currentLine = ln;
                        }
                    }
                }
            }

            int lastPt = -1;
            while (Line.Count > 0)
            {
                //get the correct point for each line
                int   pt = 0;
                int[] ei = { Line[currentLine].EndpointIndexes[0], Line[currentLine].EndpointIndexes[1] };
                if (lastPt == -1)
                {
                    if (Level.Endpoints[ei[1]].Y > Level.Endpoints[ei[0]].Y)
                    {
                        pt = 1;
                    }
                    if (Level.Endpoints[ei[1]].Y == Level.Endpoints[ei[0]].Y)
                    {
                        if (Level.Endpoints[ei[1]].X < Level.Endpoints[ei[0]].X)
                        {
                            pt = 1;
                        }
                    }
                }
                if (ei[1] == lastPt)
                {
                    pt = 1;
                }
                // map segment vertices must be in clockwise order
                points.Add(new Vector3(
                               (float)Level.Endpoints[ei[pt]].X / 1024f,
                               0,
                               (float)Level.Endpoints[ei[pt]].Y / 1024f)
                           );

                MapSegmentSide mss = new MapSegmentSide();
                mss.transparent = Line[currentLine].Transparent;
                mss.solid       = Line[currentLine].Solid;
                Side side = new Side();
                //get texture + lighting information for side
                if ((Line[currentLine].ClockwisePolygonSideIndex >= 0 && Line[currentLine].ClockwisePolygonOwner == p) ||
                    (Level.Polygons[p].Type == PolygonType.Platform && Line[currentLine].ClockwisePolygonSideIndex >= 0))
                {
                    side = Level.Sides[Line[currentLine].ClockwisePolygonSideIndex];
                }
                else if ((Line[currentLine].CounterclockwisePolygonSideIndex >= 0 && Line[currentLine].CounterclockwisePolygonOwner == p) ||
                         (Level.Polygons[p].Type == PolygonType.Platform && Line[currentLine].CounterclockwisePolygonSideIndex >= 0))
                {
                    side = Level.Sides[Line[currentLine].CounterclockwisePolygonSideIndex];
                }
                mss.upperMaterial = getTexture(side.Primary.Texture);
                mss.lowerMaterial = getTexture(side.Secondary.Texture);
                mss.middeMaterial = getTexture(side.Transparent.Texture);

                mss.upperOffset  = new Vector2((float)side.Primary.X / 1024f, (float)side.Primary.Y / 1024f);
                mss.middleOffset = new Vector2((float)side.Transparent.X / 1024f, (float)side.Transparent.Y / 1024f);
                mss.lowerOffset  = new Vector2((float)side.Secondary.X / 1024f, (float)side.Secondary.Y / 1024f);

                mss.upperLight  = lights[side.PrimaryLightsourceIndex];
                mss.lowerLight  = lights[side.SecondaryLightsourceIndex];
                mss.middleLight = lights[side.TransparentLightsourceIndex];


                if (mss.lowerMaterial == null)
                {
                    mss.lowerMaterial = mss.upperMaterial;
                    mss.lowerOffset   = mss.upperOffset;
                    mss.lowerLight    = mss.upperLight;
                }

                //get control panel information if needed
                if (side != null && (side.IsControlPanel || side.IsPlatformSwitch() || side.IsTagSwitch() || side.IsLightSwitch()))
                {
                    mss.controlPanel              = new ControlPanel();
                    mss.controlPanel.permutation  = side.ControlPanelPermutation;
                    mss.controlPanel.type         = side.ControlPanelType;
                    mss.controlPanel.controlPanel = side.IsControlPanel;
                    if (side.IsPlatformSwitch())
                    {
                        mss.controlPanel.platformSwitch = side.ControlPanelPermutation;
                    }
                    if (side.IsTagSwitch())
                    {
                        mss.controlPanel.tagSwitch = side.ControlPanelPermutation;
                    }
                    if (side.IsLightSwitch())
                    {
                        mss.controlPanel.lightSwitch = side.ControlPanelPermutation;
                    }
                    mss.controlPanel.inactiveMat = mss.upperMaterial;
                    for (int t = 0; t < materials.Count; t++)
                    {
                        if (materials[t] == mss.controlPanel.inactiveMat)
                        {
                            mss.controlPanel.activeMat = materials[t - 1];
                        }
                    }

                    switch (side.Flags)
                    {
                    // case SideFlags.None:
                    //  break;
                    case SideFlags.ControlPanelStatus:
                        mss.controlPanel.controlPanelStatus = 1;                                //?? what is this for?
                        break;

                    case SideFlags.Dirty:
                        mss.controlPanel.dirty = true;
                        break;

                    case SideFlags.IsDestructiveSwitch:
                        mss.controlPanel.destructiveSwitch = true;
                        break;

                    // case SideFlags.IsLightedSwitch:
                    //  mss.controlPanel.active = true;
                    //  break;
                    case SideFlags.IsRepairSwitch:
                        mss.controlPanel.repairSwitch = true;
                        break;

                    case SideFlags.IsControlPanel:
                        //mss.controlPanel.controlPanel = true;
                        break;

                    case SideFlags.SwitchCanBeDestroyed:
                        mss.controlPanel.canBeDestroyed = true;
                        break;

                    case SideFlags.SwitchCanOnlyBeHitByProjectiles:
                        mss.controlPanel.canOnlyBeHitByProjectiles = true;
                        break;
                    }
                }

                //connedtion information is used for occlusion culling
                seg.sides.Add(mss);
                if (Line[currentLine].ClockwisePolygonOwner == p)
                {
                    mss.connectionID = Line[currentLine].CounterclockwisePolygonOwner;
                }
                else
                {
                    mss.connectionID = Line[currentLine].ClockwisePolygonOwner;
                }
                pt     = Mathf.Abs(pt - 1);
                lastPt = ei[pt];

                //find next line that connects to the endpoint of this one to make the next side
                Line.RemoveAt(currentLine);
                for (int i = 0; i < Line.Count; i++)
                {
                    if (Line[i].EndpointIndexes[0] == ei[pt] || Line[i].EndpointIndexes[1] == ei[pt])
                    {
                        currentLine = i;
                    }
                }
            }

            //get floor and ceiling texture data
            seg.ceiling.upperMaterial = getTexture(Level.Polygons[p].CeilingTexture);
            seg.floor.upperMaterial   = getTexture(Level.Polygons[p].FloorTexture);

            seg.ceiling.upperOffset = new Vector2((float)Level.Polygons[p].CeilingOrigin.X / 1024f, (float)Level.Polygons[p].CeilingOrigin.Y / 1024f);
            seg.floor.upperOffset   = new Vector2((float)Level.Polygons[p].FloorOrigin.X / 1024f, (float)Level.Polygons[p].FloorOrigin.Y / 1024f);

            seg.ceiling.lightID = Level.Polygons[p].CeilingLight;
            seg.ceiling.light   = lights[Level.Polygons[p].CeilingLight];
            seg.floor.lightID   = Level.Polygons[p].FloorLight;
            seg.floor.light     = lights[Level.Polygons[p].FloorLight];
            seg.vertices        = points;
            seg.centerPoint     = new Vector3(0, (float)Level.Polygons[p].FloorHeight / 1024f, 0);
            seg.id = p;

            //convert points to be relative to the polygon average point
            seg.calculatePoints();

            if (p % 77 == 0)
            {
                loadingText = load + "\nGenerating Polygons " + p + "/" + Level.Polygons.Count;
                yield return(null);
            }
        }
        load = load + "\nGenerating Polygons " + Level.Polygons.Count + "/" + Level.Polygons.Count;

        //if a polygon is a platform we need to change its floor/ceiling heights to actually be
        //the volume that the platform would be moving up and down in if it were an actual
        //object - which it will be.
        int count = 0;

        foreach (Weland.Platform pl in Level.Platforms)
        {
            count++;
            segments[pl.PolygonIndex].recalculatePlatformVolume();
            if (count % 7 == 0)
            {
                loadingText = load + "\nRecalculate Platform Volumes " + count + "/" + Level.Platforms.Count;
                yield return(null);
            }
        }
        load  = load + "\nRecalculate Platform Volumes " + count + "/" + Level.Platforms.Count;
        count = 0;

        foreach (MapSegment s in segments)
        {
            count++;
            s.generateMeshes();
            if (count % 77 == 0)
            {
                loadingText = load + "\nGenerating Meshes " + count + "/" + segments.Count;
                yield return(null);
            }
        }
        load  = load + "\nGenerating Meshes " + count + "/" + segments.Count;
        count = 0;

        foreach (MapSegment s in segments)
        {
            count++;
            s.checkIfImpossible();
            if (count % 77 == 0)
            {
                loadingText = load + "\nFinding Impossible Space " + count + "/" + segments.Count;
                yield return(null);
            }
        }
        load  = load + "\nFinding Impossible Space " + count + "/" + segments.Count;
        count = 0;



        string mapHash = CalculateMD5(GlobalData.mapsFilePath);

        mapHash = Application.persistentDataPath + "/" + mapHash + "-" + mapNo + ".cache";
        if (!File.Exists(mapHash))
        {
            activePolygonList apl = new activePolygonList();
            apl.activePolygons = new List <bool[]>();
            for (int i = 0; i < segments.Count; i++)
            {
                count++;
                segments[i].calculateVisibility();

                apl.activePolygons.Add(segments[i].activePolygons);

                if (!GlobalData.skipOcclusion && count % 7 == 0)
                {
                    loadingText = load + "\nOcclusion Culling " + count + "/" + segments.Count;
                    yield return(null);
                }
            }
            BinaryFormatter bf = new BinaryFormatter();
            FileStream      fs = File.Open(mapHash, FileMode.Create);
            bf.Serialize(fs, apl);
            fs.Close();
        }
        else
        {
            FileStream        fs  = File.Open(mapHash, FileMode.Open);
            BinaryFormatter   bf  = new BinaryFormatter();
            activePolygonList apl = (activePolygonList)bf.Deserialize(fs);
            fs.Close();

            for (int i = 0; i < apl.activePolygons.Count; i++)
            {
                if (segments.Count > i)
                {
                    segments[i].activePolygons = apl.activePolygons[i];
                }
            }
        }
        load  = load + "\nOcclusion Culling " + count + "/" + segments.Count;
        count = 0;

        foreach (Weland.Platform pl in Level.Platforms)
        {
            count++;
            segments[pl.PolygonIndex].showHide(true);
            segments[pl.PolygonIndex].makePlatformObjects();
            if (count % 27 == 0)
            {
                loadingText = load + "\nMaking Platforms " + count + "/" + Level.Platforms.Count;
                yield return(null);
            }
        }

        foreach (Weland.Platform pl in Level.Platforms)
        {
            if (segments[pl.PolygonIndex].platform.initiallyActive)
            {
                segments[pl.PolygonIndex].platform.activate();
            }
        }
    }