Пример #1
0
 private void RenderSectorFilled(Sector s, int color)
 {
     // Render the geometry
     FlatVertex[] verts = new FlatVertex[s.FlatVertices.Length];
     s.FlatVertices.CopyTo(verts, 0);
     for (int i = 0; i < verts.Length; i++)
     {
         verts[i].c = color;
     }
     renderer.RenderGeometry(verts, null, true);
 }
Пример #2
0
        // This renders the associated things with the indication color
        public static void RenderAssociations(IRenderer2D renderer, Association asso, List <Line3D> eventlines)
        {
            // Tag must be above zero
            if (General.GetByIndex(asso.Tags, 0) < 1)
            {
                return;
            }

            // Things?
            switch (asso.Type)
            {
            case UniversalType.ThingTag:
                foreach (Thing t in General.Map.Map.Things)
                {
                    if (!asso.Tags.Contains(t.Tag))
                    {
                        continue;
                    }

                    //Do not draw the association if the user is hovering over a child link
                    ThingTypeInfo ti = General.Map.Data.GetThingInfoEx(t.Type);
                    if (ti != null && ti.ThingLink < 0)
                    {
                        continue;
                    }

                    renderer.RenderThing(t, General.Colors.Indication, General.Settings.ActiveThingsAlpha);
                    if (General.Settings.GZShowEventLines)
                    {
                        eventlines.Add(new Line3D(asso.Center, t.Position));                                                               //mxd
                    }
                }
                break;

            case UniversalType.SectorTag:
                foreach (Sector s in General.Map.Map.Sectors)
                {
                    if (!asso.Tags.Overlaps(s.Tags))
                    {
                        continue;
                    }
                    int          highlightedColor = General.Colors.Highlight.WithAlpha(128).ToInt();
                    FlatVertex[] verts            = new FlatVertex[s.FlatVertices.Length];
                    s.FlatVertices.CopyTo(verts, 0);
                    for (int i = 0; i < verts.Length; i++)
                    {
                        verts[i].c = highlightedColor;
                    }
                    renderer.RenderGeometry(verts, null, true);
                }
                break;
            }
        }
Пример #3
0
        // This updates the overlay
        private void UpdateOverlay()
        {
            if (renderer.StartOverlay(true))
            {
                // Editing a selection?
                if (mode == ModifyMode.Adjusting)
                {
                    // Go for all sectors that are being edited
                    ICollection <Sector> orderedselection = General.Map.Map.GetSelectedSectors(true);
                    foreach (Sector s in orderedselection)
                    {
                        // We use the overlay to dim the brightness of the sectors
                        PixelColor c = PixelColor.FromInt(General.Map.Renderer2D.CalculateBrightness(s.Brightness));
                        PixelColor brightnesscolor = new PixelColor((byte)(255 - c.r), 0, 0, 0);
                        int        brightnessint   = brightnesscolor.ToInt();

                        // Render the geometry
                        FlatVertex[] verts = new FlatVertex[s.FlatVertices.Length];
                        s.FlatVertices.CopyTo(verts, 0);
                        for (int i = 0; i < verts.Length; i++)
                        {
                            verts[i].c = brightnessint;
                        }
                        renderer.RenderGeometry(verts, null, true);
                    }
                }

                if (BuilderPlug.Me.ViewSelectionNumbers)
                {
                    // Go for all sectors
                    ICollection <Sector> orderedselection = General.Map.Map.GetSelectedSectors(true);
                    foreach (Sector s in orderedselection)
                    {
                        // Render labels
                        TextLabel[] labelarray = labels[s];
                        for (int i = 0; i < s.Labels.Count; i++)
                        {
                            TextLabel l = labelarray[i];

                            // Render only when enough space for the label to see
                            float requiredsize = (l.TextSize.Height / 2) / renderer.Scale;
                            if (requiredsize < s.Labels[i].radius)
                            {
                                renderer.RenderText(l);
                            }
                        }
                    }
                }

                renderer.Finish();
            }
        }
Пример #4
0
        // This updates the ceiling surface
        public void UpdateCeilingSurface()
        {
            if (flatvertices == null)
            {
                return;
            }

            // Create ceiling vertices
            FlatVertex[] ceilvertices = new FlatVertex[flatvertices.Length];
            flatvertices.CopyTo(ceilvertices, 0);
            General.Plugins.OnSectorCeilingSurfaceUpdate(this, ref ceilvertices);
            surfaceentry.ceilvertices = ceilvertices;
            surfaceentry.ceiltexture  = longceiltexname;
            if (surfaceentry.floorvertices == null)
            {
                surfaceentry.floorvertices = ceilvertices;
            }

            // Update entry
            surfaceentry = General.Map.CRenderer2D.Surfaces.UpdateSurfaces(surfaceentry);
            General.Map.CRenderer2D.Surfaces.UnlockBuffers();
        }
Пример #5
0
        // For rendering
        private void DrawSubsectorArea(FlatVertex[] vertices, PixelColor color)
        {
            if (vertices == null)
            {
                return;
            }
            if (vertices.Length < 3)
            {
                return;
            }

            // Copy array and change color
            FlatVertex[] poly = new FlatVertex[vertices.Length];
            vertices.CopyTo(poly, 0);
            int intcolor = color.WithAlpha(100).ToInt();

            for (int i = 0; i < poly.Length; i++)
            {
                poly[i].c = intcolor;
            }

            // Draw
            renderer.RenderGeometry(poly, null, true);
        }
Пример #6
0
        /// <summary>
        /// Renders associated things and sectors in the indication color.
        /// Also renders event lines, if that option is enabled
        /// </summary>
        public void Render()
        {
            bool showlabels = BuilderPlug.Me.EventLineLabelVisibility > 0;             // Show labels at all?

            foreach (Thing t in things)
            {
                renderer.RenderThing(t, General.Colors.Indication, General.Settings.ActiveThingsAlpha);
            }

            // There must be a better way to do this
            foreach (Sector s in sectors)
            {
                int          highlightedColor = General.Colors.Highlight.WithAlpha(128).ToInt();
                FlatVertex[] verts            = new FlatVertex[s.FlatVertices.Length];
                s.FlatVertices.CopyTo(verts, 0);
                for (int i = 0; i < verts.Length; i++)
                {
                    verts[i].c = highlightedColor;
                }
                renderer.RenderGeometry(verts, null, true);
            }

            if (General.Settings.GZShowEventLines)
            {
                List <Line3D>     lines  = new List <Line3D>(eventlines.Count);
                List <ITextLabel> labels = new List <ITextLabel>(eventlines.Count);

                foreach (KeyValuePair <string, List <Line3D> > kvp in eventlines)
                {
                    bool            emptylabel   = string.IsNullOrEmpty(kvp.Key);        // Can be true if only either forward or reverse labels are shown
                    List <Vector2D> allpositions = new List <Vector2D>(kvp.Value.Count);

                    foreach (Line3D line in kvp.Value)
                    {
                        if (showlabels && !emptylabel)
                        {
                            allpositions.Add(GetLabelPosition(line.Start, line.End));
                        }

                        lines.Add(line);
                    }

                    if (showlabels && !emptylabel)
                    {
                        List <Vector2D> positions    = MergePositions(allpositions, textwidths[kvp.Key]);
                        int             labelcounter = 0;

                        // Set the position of the pre-generated labels. Only add the labels that are needed
                        foreach (Vector2D pos in positions)
                        {
                            textlabels[kvp.Key][labelcounter].Location = pos;
                            labels.Add(textlabels[kvp.Key][labelcounter]);
                            labelcounter++;
                        }
                    }
                }

                renderer.RenderArrows(lines);

                if (showlabels)
                {
                    renderer.RenderText(labels);
                }
            }
        }
Пример #7
0
        // For rendering
        private void DrawSplitArea(RectangleF bbox, int nodeindex, bool left, PixelColor color)
        {
            Node node = nodes[nodeindex];

            // Begin with a square bounding box polygon
            List <Vector2D> poly = new List <Vector2D>(16);

            poly.Add(new Vector2D(bbox.Left, bbox.Top));
            poly.Add(new Vector2D(bbox.Right, bbox.Top));
            poly.Add(new Vector2D(bbox.Right, bbox.Bottom));
            poly.Add(new Vector2D(bbox.Left, bbox.Bottom));

            // Remove everything behind the split from the area
            if (left)
            {
                CropPolygon(poly, new Split(node.linestart, -node.linedelta));
            }
            else
            {
                CropPolygon(poly, new Split(node.linestart, node.linedelta));
            }

            // Remove everything behind parent splits from the area
            int prevnode   = nodeindex;
            int parentnode = node.parent;

            while (parentnode > -1)
            {
                Node pn = nodes[parentnode];
                if (!pn.leftsubsector && (pn.leftchild == prevnode))
                {
                    CropPolygon(poly, new Split(pn.linestart, -pn.linedelta));
                }
                else if (!pn.rightsubsector && (pn.rightchild == prevnode))
                {
                    CropPolygon(poly, new Split(pn.linestart, pn.linedelta));
                }
                prevnode   = parentnode;
                parentnode = pn.parent;
            }

            if (poly.Count >= 3)
            {
                // Create render vertices
                FlatVertex[] fverts   = new FlatVertex[(poly.Count - 2) * 3];
                int          intcolor = color.ToInt();
                int          pi       = 0;
                for (int t = 0; t < (poly.Count - 2); t++)
                {
                    fverts[pi].x     = poly[0].x;
                    fverts[pi].y     = poly[0].y;
                    fverts[pi].c     = intcolor;
                    fverts[pi + 1].x = poly[t + 1].x;
                    fverts[pi + 1].y = poly[t + 1].y;
                    fverts[pi + 1].c = intcolor;
                    fverts[pi + 2].x = poly[t + 2].x;
                    fverts[pi + 2].y = poly[t + 2].y;
                    fverts[pi + 2].c = intcolor;
                    pi += 3;
                }

                // Draw
                renderer.RenderGeometry(fverts, null, true);
            }
        }
Пример #8
0
        /// <summary>
        /// Build the polygon for a specific subsector
        /// </summary>
        private void BuildSubsectorPoly(int ss, IEnumerable <Split> nodesplits)
        {
            // Begin with a giant square polygon that covers the entire map
            List <Vector2D> poly = new List <Vector2D>(16);

            poly.Add(new Vector2D(-General.Map.FormatInterface.MaxCoordinate, General.Map.FormatInterface.MaxCoordinate));
            poly.Add(new Vector2D(General.Map.FormatInterface.MaxCoordinate, General.Map.FormatInterface.MaxCoordinate));
            poly.Add(new Vector2D(General.Map.FormatInterface.MaxCoordinate, -General.Map.FormatInterface.MaxCoordinate));
            poly.Add(new Vector2D(-General.Map.FormatInterface.MaxCoordinate, -General.Map.FormatInterface.MaxCoordinate));

            // Crop the polygon by the node tree splits
            foreach (Split s in nodesplits)
            {
                CropPolygon(poly, s);
            }

            // Crop the polygon by the subsector segs
            for (int i = 0; i < ssectors[ss].numsegs; i++)
            {
                Split s;
                Seg   sg = segs[ssectors[ss].firstseg + i];

                //mxd. Sanity check, because some segs in Doom maps refer to non-existing verts.
                if (sg.startvertex > verts.Length - 1 || sg.endvertex > verts.Length - 1)
                {
                    continue;
                }

                s.pos   = verts[sg.startvertex];
                s.delta = verts[sg.endvertex] - verts[sg.startvertex];
                CropPolygon(poly, s);
            }

            if (poly.Count > 1)
            {
                // Remove any zero-length lines
                Vector2D prevpoint = poly[0];
                for (int i = poly.Count - 1; i >= 0; i--)
                {
                    if (Vector2D.DistanceSq(poly[i], prevpoint) < 0.001f)
                    {
                        poly.RemoveAt(i);
                    }
                    else
                    {
                        prevpoint = poly[i];
                    }
                }
            }

            ssectors[ss].points = poly.ToArray();

            // Setup vertices for rendering
            if (poly.Count >= 3)
            {
                FlatVertex[] fverts   = new FlatVertex[(poly.Count - 2) * 3];
                int          intcolor = PixelColor.FromColor(Color.Gray).WithAlpha(100).ToInt();
                int          pi       = 0;
                for (int t = 0; t < (poly.Count - 2); t++)
                {
                    fverts[pi].x     = poly[0].x;
                    fverts[pi].y     = poly[0].y;
                    fverts[pi].c     = intcolor;
                    fverts[pi + 1].x = poly[t + 1].x;
                    fverts[pi + 1].y = poly[t + 1].y;
                    fverts[pi + 1].c = intcolor;
                    fverts[pi + 2].x = poly[t + 2].x;
                    fverts[pi + 2].y = poly[t + 2].y;
                    fverts[pi + 2].c = intcolor;
                    pi += 3;
                }
                ssectors[ss].vertices = fverts;
            }
        }
Пример #9
0
        // This updates the selection rectangle components
        private void UpdateRectangleComponents()
        {
            float      gripsize  = GRIP_SIZE / renderer.Scale;
            PixelColor rectcolor = General.Colors.Highlight.WithAlpha(RECTANGLE_ALPHA);

            // Corners in world space
            corners[0] = TexToWorld(selectionoffset + new Vector2D(0f, 0f));
            corners[1] = TexToWorld(selectionoffset + new Vector2D(texture.ScaledWidth, 0f));
            corners[2] = TexToWorld(selectionoffset + new Vector2D(texture.ScaledWidth, -texture.ScaledHeight));
            corners[3] = TexToWorld(selectionoffset + new Vector2D(0f, -texture.ScaledHeight));

            // Vertices
            cornerverts = new FlatVertex[6];
            for (int i = 0; i < 6; i++)
            {
                cornerverts[i]   = new FlatVertex();
                cornerverts[i].z = 1.0f;
                cornerverts[i].c = rectcolor.ToInt();
            }
            cornerverts[0].x = corners[0].x;
            cornerverts[0].y = corners[0].y;
            cornerverts[1].x = corners[1].x;
            cornerverts[1].y = corners[1].y;
            cornerverts[2].x = corners[2].x;
            cornerverts[2].y = corners[2].y;
            cornerverts[3].x = corners[0].x;
            cornerverts[3].y = corners[0].y;
            cornerverts[4].x = corners[2].x;
            cornerverts[4].y = corners[2].y;
            cornerverts[5].x = corners[3].x;
            cornerverts[5].y = corners[3].y;

            // Extended points for rotation corners
            extends[0] = TexToWorld(selectionoffset + new Vector2D(texture.ScaledWidth + (20f * Math.Sign(scale.x * sectorinfo[0].scale.x)) / renderer.Scale * (scale.x * sectorinfo[0].scale.x), 0f));
            extends[1] = TexToWorld(selectionoffset + new Vector2D(0f, -texture.ScaledHeight + (-20f * Math.Sign(scale.y * sectorinfo[0].scale.y)) / renderer.Scale * (scale.y * sectorinfo[0].scale.y)));

            // Middle points between corners
            Vector2D middle12 = corners[1] + (corners[2] - corners[1]) * 0.5f;
            Vector2D middle23 = corners[2] + (corners[3] - corners[2]) * 0.5f;

            // Resize grips
            resizegrips[0] = new RectangleF(middle12.x - gripsize * 0.5f,
                                            middle12.y - gripsize * 0.5f,
                                            gripsize, gripsize);
            resizegrips[1] = new RectangleF(middle23.x - gripsize * 0.5f,
                                            middle23.y - gripsize * 0.5f,
                                            gripsize, gripsize);

            // Rotate grips
            rotategrips[0] = new RectangleF(extends[0].x - gripsize * 0.5f,
                                            extends[0].y - gripsize * 0.5f,
                                            gripsize, gripsize);
            rotategrips[1] = new RectangleF(extends[1].x - gripsize * 0.5f,
                                            extends[1].y - gripsize * 0.5f,
                                            gripsize, gripsize);

            if (showalignoffset)
            {
                Vector2D worldalignoffset = TexToWorld(selectionoffset + alignoffset);
                alignrect = new RectangleF(worldalignoffset.x - gripsize * 0.5f,
                                           worldalignoffset.y - gripsize * 0.5f,
                                           gripsize, gripsize);
            }
        }
Пример #10
0
        public void UpdateSoundEnvironments(object sender, DoWorkEventArgs e)
        {
            List <Sector>     sectorstocheck        = new List <Sector>();
            List <Sector>     checkedsectors        = new List <Sector>();
            List <Sector>     allsectors            = new List <Sector>();
            BackgroundWorker  worker                = sender as BackgroundWorker;
            List <FlatVertex> vertsList             = new List <FlatVertex>();
            Dictionary <Thing, PixelColor> secolor  = new Dictionary <Thing, PixelColor>();
            Dictionary <Thing, int>        senumber = new Dictionary <Thing, int>();

            soundenvironments.Clear();
            blockinglinedefs.Clear();
            SoundEnvironmentMode.SoundEnvironmentPanel.BeginUpdate();             //mxd

            // Keep track of all the sectors in the map. Sectors that belong to a sound environment
            // will be removed from the list, so in the end only sectors that don't belong to any
            // sound environment will be in this list
            foreach (Sector s in General.Map.Map.Sectors)
            {
                allsectors.Add(s);
            }

            List <Thing> soundenvironmenthings = GetSoundEnvironmentThings(General.Map.Map.Sectors.ToList());
            int          numthings             = soundenvironmenthings.Count;

            // Assign each thing a color and a number, so each sound environment will always have the same color
            // and id, no matter in what order they are discovered
            for (int i = 0; i < soundenvironmenthings.Count; i++)
            {
                //mxd. Make sure same environments use the same color
                int seid = (soundenvironmenthings[i].Args[0] << 8) + soundenvironmenthings[i].Args[1];
                secolor[soundenvironmenthings[i]] = distinctcolors[seid % distinctcolors.Count];
                senumber.Add(soundenvironmenthings[i], i + 1);
            }

            while (soundenvironmenthings.Count > 0 && !worker.CancellationPending)
            {
                // Sort things by distance to center of the screen, so that sound environments the user want to look at will (hopefully) be discovered first
                Vector2D center = General.Map.Renderer2D.DisplayToMap(new Vector2D(General.Interface.Display.Width / 2f, General.Interface.Display.Height / 2f));
                soundenvironmenthings = soundenvironmenthings.OrderBy(o => Math.Abs(Vector2D.Distance(center, o.Position))).ToList();

                Thing thing = soundenvironmenthings[0];
                if (thing.Sector == null)
                {
                    thing.DetermineSector();
                }

                // Ignore things that are outside the map
                if (thing.Sector == null)
                {
                    soundenvironmenthings.Remove(thing);
                    continue;
                }

                SoundEnvironment environment = new SoundEnvironment();

                // Add initial sector. Additional adjacant sectors will be added later
                // as they are discovered
                sectorstocheck.Add(thing.Sector);

                while (sectorstocheck.Count > 0)
                {
                    Sector sector = sectorstocheck[0];

                    if (!environment.Sectors.Contains(sector))
                    {
                        environment.Sectors.Add(sector);
                    }
                    if (!checkedsectors.Contains(sector))
                    {
                        checkedsectors.Add(sector);
                    }

                    sectorstocheck.Remove(sector);
                    allsectors.Remove(sector);

                    // Find adjacant sectors and add them to the list of sectors to check if necessary
                    foreach (Sidedef sd in sector.Sidedefs)
                    {
                        if (LinedefBlocksSoundEnvironment(sd.Line))
                        {
                            if (!environment.Linedefs.Contains(sd.Line))
                            {
                                environment.Linedefs.Add(sd.Line);
                            }
                            continue;
                        }

                        if (sd.Other == null)
                        {
                            continue;
                        }

                        Sector oppositesector = (sd.Line.Front.Sector == sector ? sd.Line.Back.Sector : sd.Line.Front.Sector);

                        if (!sectorstocheck.Contains(oppositesector) && !checkedsectors.Contains(oppositesector))
                        {
                            sectorstocheck.Add(oppositesector);
                        }
                    }
                }

                // Get all things that are in the current sound environment...
                environment.Things = GetSoundEnvironmentThings(environment.Sectors);

                // ... and remove them from the list of sound environment things to check, because we know that
                // they already belong to a sound environment
                foreach (Thing t in environment.Things)
                {
                    if (soundenvironmenthings.Contains(t))
                    {
                        soundenvironmenthings.Remove(t);
                    }
                }

                // Set color and id of the sound environment
                environment.Color = secolor[environment.Things[0]];
                environment.ID    = senumber[environment.Things[0]];

                // Create the data for the overlay geometry
                List <FlatVertex> severtslist = new List <FlatVertex>(environment.Sectors.Count * 3);               //mxd
                foreach (Sector s in environment.Sectors)
                {
                    FlatVertex[] fv = new FlatVertex[s.FlatVertices.Length];
                    s.FlatVertices.CopyTo(fv, 0);
                    for (int j = 0; j < fv.Length; j++)
                    {
                        fv[j].c = environment.Color.WithAlpha(128).ToInt();
                    }

                    vertsList.AddRange(fv);
                    severtslist.AddRange(fv);                     //mxd

                    // Get all Linedefs that will block sound environments
                    foreach (Sidedef sd in s.Sidedefs)
                    {
                        if (!LinedefBlocksSoundEnvironment(sd.Line))
                        {
                            continue;
                        }
                        lock (blockinglinedefs)
                        {
                            blockinglinedefs.Add(sd.Line);
                        }
                    }
                }

                //mxd. Store sector environment verts
                environment.SectorsGeometry = severtslist.ToArray();

                // Update the overlay geometry with the newly added sectors
                if (overlayGeometry == null)
                {
                    overlayGeometry = vertsList.ToArray();
                }
                else
                {
                    lock (overlayGeometry)
                    {
                        overlayGeometry = vertsList.ToArray();
                    }
                }

                environment.Things   = environment.Things.OrderBy(o => o.Index).ToList();
                environment.Linedefs = environment.Linedefs.OrderBy(o => o.Index).ToList();

                //mxd. Find the first non-dormant thing
                Thing activeenv = null;
                foreach (Thing t in environment.Things)
                {
                    if (!ThingDormant(t))
                    {
                        activeenv = t;
                        break;
                    }
                }

                //mxd. Update environment name
                if (activeenv != null)
                {
                    foreach (KeyValuePair <string, KeyValuePair <int, int> > group in General.Map.Data.Reverbs)
                    {
                        if (group.Value.Key == activeenv.Args[0] && group.Value.Value == activeenv.Args[1])
                        {
                            environment.Name = group.Key + " (" + activeenv.Args[0] + " " + activeenv.Args[1] + ")";
                            break;
                        }
                    }

                    //mxd. No suitable name found?..
                    if (environment.Name == SoundEnvironment.DEFAULT_NAME)
                    {
                        environment.Name += " (" + activeenv.Args[0] + " " + activeenv.Args[1] + ")";
                    }
                }

                //mxd. Still no suitable name?..
                if (environment.Name == SoundEnvironment.DEFAULT_NAME)
                {
                    environment.Name += " " + environment.ID;
                }

                lock (soundenvironments)
                {
                    soundenvironments.Add(environment);
                }

                // Tell the worker that discovering a sound environment is finished. This will update the tree view, and also
                // redraw the interface, so the sectors of this sound environment are colored
                worker.ReportProgress((int)((1.0f - (soundenvironmenthings.Count / (float)numthings)) * 100), environment);
            }

            // Create overlay geometry for sectors that don't belong to a sound environment
            foreach (Sector s in allsectors)
            {
                FlatVertex[] fv = new FlatVertex[s.FlatVertices.Length];
                s.FlatVertices.CopyTo(fv, 0);
                for (int j = 0; j < fv.Length; j++)
                {
                    fv[j].c = NoSoundColor.WithAlpha(128).ToInt();
                }
                vertsList.AddRange(fv);
            }

            if (overlayGeometry == null)
            {
                overlayGeometry = vertsList.ToArray();
            }
            else
            {
                lock (overlayGeometry)
                {
                    overlayGeometry = vertsList.ToArray();
                }
            }

            soundenvironmentisupdated = true;
            SoundEnvironmentMode.SoundEnvironmentPanel.EndUpdate();             //mxd
        }
Пример #11
0
        // This makes new vertices as well as floor and ceiling surfaces
        internal void CreateSurfaces()
        {
            if (updateneeded)
            {
                // Brightness color
                int brightint = General.Map.Renderer2D.CalculateBrightness(brightness);

                // villsa
                switch (General.Map.Renderer2D.ViewMode)
                {
                case ViewMode.FloorColor:
                    brightint = this.flrColor.color.ToInt();
                    break;

                case ViewMode.CeilingColor:
                    brightint = this.ceilColor.color.ToInt();
                    break;

                case ViewMode.ThingColor:
                    brightint = this.thingColor.color.ToInt();
                    break;

                default:
                    break;
                }

                // Make vertices
                flatvertices = new FlatVertex[triangles.Vertices.Count];
                for (int i = 0; i < triangles.Vertices.Count; i++)
                {
                    flatvertices[i].x = triangles.Vertices[i].x;
                    flatvertices[i].y = triangles.Vertices[i].y;
                    flatvertices[i].z = 1.0f;
                    flatvertices[i].c = brightint;
                    flatvertices[i].u = triangles.Vertices[i].x;
                    flatvertices[i].v = triangles.Vertices[i].y;
                }

                // Create bounding box
                bbox = CreateBBox();

                // Make a dummy entry if we don't have one yet
                if (surfaceentry == null)
                {
                    surfaceentry = new SurfaceEntry(-1, -1, -1);
                }

                // Create floor vertices
                FlatVertex[] floorvertices = new FlatVertex[flatvertices.Length];
                flatvertices.CopyTo(floorvertices, 0);
                General.Plugins.OnSectorFloorSurfaceUpdate(this, ref floorvertices);
                surfaceentry.floorvertices = floorvertices;
                surfaceentry.floortexture  = longfloortexname;

                // Create ceiling vertices
                FlatVertex[] ceilvertices = new FlatVertex[flatvertices.Length];
                flatvertices.CopyTo(ceilvertices, 0);
                General.Plugins.OnSectorCeilingSurfaceUpdate(this, ref ceilvertices);
                surfaceentry.ceilvertices = ceilvertices;
                surfaceentry.ceiltexture  = longceiltexname;

                // Update entry
                surfaceentry = General.Map.CRenderer2D.Surfaces.UpdateSurfaces(surfaceentry);

                // Updated
                updateneeded = false;
            }
        }
		// Redrawing display
		public override void OnRedrawDisplay()
		{
			if (!stairsectorbuilderform.FullyLoaded) return;

			base.OnRedrawDisplay();

			renderer.RedrawSurface();

			// Render lines
			if (renderer.StartPlotter(true))
			{
				renderer.PlotLinedefSet(General.Map.Map.Linedefs);
				renderer.PlotVerticesSet(General.Map.Map.Vertices);
				renderer.Finish();
			}

			// Render things
			if (renderer.StartThings(true))
			{
				renderer.RenderThingSet(General.Map.Map.Things, 1.0f);
				renderer.Finish();
			}

			// Render overlay
			if (renderer.StartOverlay(true))
			{
				if (stairsectorbuilderform.NumberOfSectors > 0)
				{
					if (stairsectorbuilderform.Tabs.SelectedIndex == 2 && numcontrolpoints != stairsectorbuilderform.NumControlPoints)
					{
						ModifyControlpointNumber(stairsectorbuilderform.NumControlPoints);
						numcontrolpoints = stairsectorbuilderform.NumControlPoints;
					}

					// Create sector info based on the settings...
					UpdateVertexData();

					// Render the control points if the Catmull Rom spline tab is selected
					if (stairsectorbuilderform.Tabs.SelectedIndex == 2)
					{
						foreach (List<Vector2D> lv in exactsplines)
						{
							for (int i = 0; i < lv.Count - 1; i++)
							{
								renderer.RenderLine(lv[i], lv[i + 1], LINE_THICKNESS, new PixelColor(255, 128, 128, 128), true);
							}
						}

						foreach (CatmullRomSplineGroup crsg in catmullromsplinegroups)
						{
							CatmullRomSplineData[] crsd = new CatmullRomSplineData[2] { crsg.splines[INNER_SPLINE], crsg.splines[OUTER_SPLINE] };

							foreach (CatmullRomSplineData c in crsd)
							{
								for (int i = 0; i < c.controlpoints.Count; i++)
								{
									RectangleF rect = new RectangleF(c.controlpoints[i].x - CONTROLPOINT_SIZE / 2, c.controlpoints[i].y - CONTROLPOINT_SIZE / 2, 10.0f, 10.0f);

									if (i == 0) renderer.RenderRectangle(rect, 2, new PixelColor(128, 255, 0, 0), true);
									else if (i == c.controlpoints.Count - 1) renderer.RenderRectangle(rect, 2, new PixelColor(128, 0, 255, 0), true);
									else renderer.RenderRectangle(rect, 2, General.Colors.Indication, true);
									//renderer.RenderLine(c.controlpoints[i], c.controlpoints[i] + c.tangents[i], LINE_THICKNESS, new PixelColor(255, 128, 128, 128), true);
								}
							}
						}
					}

					// ... and draw the preview
					foreach (StairInfo si in stairsectors)
					{
						foreach (List<Vector2D> lv in si.sectors)
						{
							FlatVertex[] fvl = new FlatVertex[lv.Count];

							for (int i = 0; i < lv.Count - 1; i++)
							{
								FlatVertex fv = new FlatVertex();

								renderer.RenderLine(lv[i], lv[i + 1], LINE_THICKNESS, General.Colors.Highlight, true);

								fvl[lv.Count - 1 - i].x = fv.u = lv[i].x;
								fvl[lv.Count - 1 - i].y = fv.v = lv[i].y;
								fvl[lv.Count - 1 - i].z = 1;
								fvl[lv.Count - 1 - i].c = 1056964608;

								RectangleF rect = new RectangleF(lv[i].x - CONTROLPOINT_SIZE / 2, lv[i].y - CONTROLPOINT_SIZE / 2, 10.0f, 10.0f);
								renderer.RenderRectangle(rect, 2, new PixelColor(128, 255, 0, 0), true);
							}

							fvl[0] = fvl[lv.Count - 1];

							// renderer.RenderGeometry(fvl, null, true);
						}
					}
				}

				renderer.Finish();
			}
			renderer.Present();
		}