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); }
// 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; } }
// 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(); } }
// 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(); }
// 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); }
/// <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); } } }
// 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); } }
/// <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; } }
// 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); } }
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 }
// 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(); }