// Mouse leaves public override void OnMouseLeave(EventArgs e) { base.OnMouseLeave(e); // Highlight nothing highlightedslope = null; }
/// <summary>This finds the slope vertex closest to the specified position.</summary> public SlopeVertex NearestSlopeVertexSquareRange(ICollection <SlopeVertex> selection, Vector2D pos, float maxrange) { RectangleF range = RectangleF.FromLTRB(pos.x - maxrange, pos.y - maxrange, pos.x + maxrange, pos.y + maxrange); SlopeVertex closest = null; float distance = float.MaxValue; // Go for all vertices in selection foreach (SlopeVertex v in selection) { float px = v.Pos.x; float py = v.Pos.y; //mxd. Within range? if ((v.Pos.x < range.Left) || (v.Pos.x > range.Right) || (v.Pos.y < range.Top) || (v.Pos.y > range.Bottom)) { continue; } // Close than previous find? float d = Math.Abs(px - pos.x) + Math.Abs(py - pos.y); if (d < distance) { // This one is closer closest = v; distance = d; } } // Return result return(closest); }
// Done editing protected override void OnEditEnd() { base.OnEditEnd(); if (dragging) { return; } if (highlightedslope != null) { SlopeVertex sv = highlightedslope; List <SlopeVertex> vertices = GetSelectedSlopeVertices(); if (!vertices.Contains(highlightedslope)) { vertices.Add(highlightedslope); } SlopeVertexEditForm svef = new SlopeVertexEditForm(); svef.Setup(vertices); DialogResult result = svef.ShowDialog((Form)General.Interface); if (result == DialogResult.OK) { General.Map.IsChanged = true; BuilderPlug.Me.UpdateSlopes(); } highlightedslope = null; } else if (highlightedsector != null) { if (General.Map.Map.SelectedSectorsCount == 0) { BuilderPlug.Me.MenusForm.AddSectorsContextMenu.Tag = new List <Sector>() { highlightedsector }; } else { BuilderPlug.Me.MenusForm.AddSectorsContextMenu.Tag = General.Map.Map.GetSelectedSectors(true).ToList(); } BuilderPlug.Me.MenusForm.AddSectorsContextMenu.Show(Cursor.Position); } updateOverlaySurfaces(); UpdateOverlay(); General.Interface.RedrawDisplay(); }
// This sets up new labels /* * private void SetupLabels() * { * if (labels != null) * { * // Dispose old labels * foreach (KeyValuePair<Sector, TextLabel[]> lbl in labels) * foreach (TextLabel l in lbl.Value) l.Dispose(); * } * * // Make text labels for sectors * labels = new Dictionary<Sector, TextLabel[]>(General.Map.Map.Sectors.Count); * foreach (Sector s in General.Map.Map.Sectors) * { * // Setup labels * TextLabel[] labelarray = new TextLabel[s.Labels.Count]; * for (int i = 0; i < s.Labels.Count; i++) * { * Vector2D v = s.Labels[i].position; * labelarray[i] = new TextLabel(20); * labelarray[i].TransformCoords = true; * labelarray[i].Rectangle = new RectangleF(v.x, v.y, 0.0f, 0.0f); * labelarray[i].AlignX = TextAlignmentX.Center; * labelarray[i].AlignY = TextAlignmentY.Middle; * labelarray[i].Scale = 14f; * labelarray[i].Color = General.Colors.Highlight.WithAlpha(255); * labelarray[i].Backcolor = General.Colors.Background.WithAlpha(255); * } * labels.Add(s, labelarray); * } * } */ private void SetupLabels() { labels = new List <TextLabel>(); PixelColor white = new PixelColor(255, 255, 255, 255); foreach (SlopeVertexGroup svg in BuilderPlug.Me.SlopeVertexGroups) { for (int i = 0; i < svg.Vertices.Count; i++) { if (BuilderPlug.Me.SlopeVertexLabelDisplayOption == LabelDisplayOption.Always || General.Interface.AltState == true) { SlopeVertex sv = svg.Vertices[i]; double scale = 1 / renderer.Scale; double x = sv.Pos.x; double y = sv.Pos.y - 14 * scale; string value = String.Format("Z: {0}", sv.Z); bool showlabel = true; // Rearrange labels if they'd be (exactly) on each other foreach (TextLabel l in labels) { if (l.Location.x == x && l.Location.y == y) { // Reduce visual clutter by de-duping stacked labels, when "show all labels" is enabled if (l.Text == value) { showlabel = false; //dedupe } else { // Adjust the label position down one line y -= l.TextSize.Height * scale; } } } // Only proceed if the label was not deduped if (showlabel) { TextLabel label = new TextLabel(); label.TransformCoords = true; label.Location = new Vector2D(x, y); label.AlignX = TextAlignmentX.Center; label.AlignY = TextAlignmentY.Middle; label.BackColor = General.Colors.Background.WithAlpha(128); label.Text = value; label.Color = white; labels.Add(label); } } } } }
public SlopeVertexGroup GetSlopeVertexGroup(SlopeVertex sv) { foreach (SlopeVertexGroup svg in slopevertexgroups) { if (svg.Vertices.Contains(sv)) { return(svg); } } return(null); }
// This sets up new labels /* * private void SetupLabels() * { * if (labels != null) * { * // Dispose old labels * foreach (KeyValuePair<Sector, TextLabel[]> lbl in labels) * foreach (TextLabel l in lbl.Value) l.Dispose(); * } * * // Make text labels for sectors * labels = new Dictionary<Sector, TextLabel[]>(General.Map.Map.Sectors.Count); * foreach (Sector s in General.Map.Map.Sectors) * { * // Setup labels * TextLabel[] labelarray = new TextLabel[s.Labels.Count]; * for (int i = 0; i < s.Labels.Count; i++) * { * Vector2D v = s.Labels[i].position; * labelarray[i] = new TextLabel(20); * labelarray[i].TransformCoords = true; * labelarray[i].Rectangle = new RectangleF(v.x, v.y, 0.0f, 0.0f); * labelarray[i].AlignX = TextAlignmentX.Center; * labelarray[i].AlignY = TextAlignmentY.Middle; * labelarray[i].Scale = 14f; * labelarray[i].Color = General.Colors.Highlight.WithAlpha(255); * labelarray[i].Backcolor = General.Colors.Background.WithAlpha(255); * } * labels.Add(s, labelarray); * } * } */ private void SetupLabels() { labels = new List <TextLabel>(); PixelColor white = new PixelColor(255, 255, 255, 255); foreach (SlopeVertexGroup svg in BuilderPlug.Me.SlopeVertexGroups) { for (int i = 0; i < svg.Vertices.Count; i++) { SlopeVertex sv = svg.Vertices[i]; float x = sv.Pos.x; float y = sv.Pos.y - 14 * (1 / renderer.Scale); TextLabel label = new TextLabel(); label.TransformCoords = true; label.Location = new Vector2D(x, y); label.AlignX = TextAlignmentX.Center; label.AlignY = TextAlignmentY.Middle; label.BackColor = General.Colors.Background.WithAlpha(255); label.Text = ""; // Rearrange labels if they'd be (exactly) on each other // TODO: do something like that also for overlapping labels foreach (TextLabel l in labels) { if (l.Location.x == label.Location.x && l.Location.y == label.Location.y) { label.Location = new Vector2D(x, l.Location.y - 14.0f * (1 / renderer.Scale)); } } label.Color = white; label.Text += String.Format("Z: {0}", sv.Z); labels.Add(label); } } }
public void Setup(List <SlopeVertex> vertices) { this.vertices = vertices; SlopeVertex fv = vertices[0]; SlopeVertexGroup fsvg = BuilderPlug.Me.GetSlopeVertexGroup(fv); sectors = new List <Sector>(); undodescription = "Edit slope vertex"; if (vertices.Count > 1) { undodescription = "Edit " + vertices.Count + " slope vertices"; } positionx.Text = fv.Pos.x.ToString(); positiony.Text = fv.Pos.y.ToString(); positionz.Text = fv.Z.ToString(); foreach (Sector s in fsvg.Sectors) { if (!sectors.Contains(s)) { sectors.Add(s); } } reposition.Checked = fsvg.Reposition; spline.Checked = fsvg.Spline; canaddsectors = true; canremovesectors = true; if (vertices.Count > 1) { List <SlopeVertexGroup> listsvgs = new List <SlopeVertexGroup>(); this.Text = "Edit slope vertices (" + vertices.Count.ToString() + ")"; foreach (SlopeVertex sv in vertices) { SlopeVertexGroup svg = BuilderPlug.Me.GetSlopeVertexGroup(sv); if (!listsvgs.Contains(svg)) { listsvgs.Add(svg); } if (sv.Pos.x.ToString() != positionx.Text) { positionx.Text = ""; } if (sv.Pos.y.ToString() != positiony.Text) { positiony.Text = ""; } if (sv.Z.ToString() != positionz.Text) { positionz.Text = ""; } if (svg.Reposition != reposition.Checked) { reposition.CheckState = CheckState.Indeterminate; } if (svg.Spline) { spline.Enabled = true; } if (svg.Spline != spline.Checked) { spline.CheckState = CheckState.Indeterminate; } foreach (Sector s in svg.Sectors) { if (!sectors.Contains(s)) { sectors.Add(s); } } } if (listsvgs.Count > 2) { canaddsectors = false; canremovesectors = false; } } foreach (Sector s in sectors.OrderBy(x => x.Index)) { checkedListBoxSectors.Items.Add(s); } if (General.Map.Map.SelectedSectorsCount == 0) { addselectedsectorsceiling.Enabled = false; removeselectedsectorsceiling.Enabled = false; addselectedsectorsfloor.Enabled = false; removeselectedsectorsfloor.Enabled = false; } else { addselectedsectorsceiling.Enabled = canaddsectors; removeselectedsectorsceiling.Enabled = canremovesectors; addselectedsectorsfloor.Enabled = canaddsectors; removeselectedsectorsfloor.Enabled = canremovesectors; } }
//retrieves the current mouse position on the grid, snapped as necessary private Vector2D SnapToNearest(Vector2D vm) { float vrange = 20f / renderer.Scale; bool snaptogrid = General.Interface.ShiftState ^ General.Interface.SnapToGrid; //allow temporary disable of snap by holding shift if (General.Interface.AutoMerge) //only snap to geometry if the option is enabled { // Try the nearest slope vertex SlopeVertex nh = NearestSlopeVertexSquareRange(vm, vrange); if (nh != null) { return(nh.Pos); } // Try the nearest map vertex Vertex nv = General.Map.Map.NearestVertexSquareRange(vm, vrange); if (nv != null) { return(nv.Position); } // Try the nearest linedef Linedef nl = General.Map.Map.NearestLinedefRange(vm, vrange); if (nl != null) { // Snap to grid? if (snaptogrid) { // Get grid intersection coordinates List <Vector2D> coords = nl.GetGridIntersections(); // Find nearest grid intersection bool found = false; float found_distance = float.MaxValue; Vector2D found_coord = new Vector2D(); foreach (Vector2D v in coords) { Vector2D delta = vm - v; if (delta.GetLengthSq() < found_distance) { found_distance = delta.GetLengthSq(); found_coord = v; found = true; } } if (found) { return(found_coord); } } else { return(nl.NearestOnLine(vm)); } } } //Just get the current mouse location instead if (snaptogrid) { return(General.Map.Grid.SnappedToGrid(vm)); } return(vm); }
// Mouse moves public override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); if (selectpressed && !editpressed && !selecting) { // Check if moved enough pixels for multiselect Vector2D delta = mousedownpos - mousepos; if ((Math.Abs(delta.x) > 2) || (Math.Abs(delta.y) > 2)) { // Start multiselecting StartMultiSelection(); } } else if (e.Button == MouseButtons.None) { SlopeVertex oldhighlight = highlightedslope; Sector oldhighlightedsector = highlightedsector; float distance = float.MaxValue; float d; highlightedslope = null; foreach (SlopeVertexGroup svg in BuilderPlug.Me.SlopeVertexGroups) { foreach (SlopeVertex sv in svg.Vertices) { d = Vector2D.Distance(sv.Pos, mousemappos); if (d <= BuilderModes.BuilderPlug.Me.HighlightRange / renderer.Scale && d < distance) { distance = d; highlightedslope = sv; } } } // If no slope vertex is highlighted, check if a sector should be if (highlightedslope == null) { // Find the nearest linedef within highlight range Linedef l = General.Map.Map.NearestLinedef(mousemappos); if (l != null) { // Check on which side of the linedef the mouse is float side = l.SideOfLine(mousemappos); if (side > 0) { // Is there a sidedef here? if (l.Back != null) { // Highlight if not the same if (l.Back.Sector != highlightedsector) { HighlightSector(l.Back.Sector); } } else { // Highlight nothing if (highlightedsector != null) { HighlightSector(null); } } } else { // Is there a sidedef here? if (l.Front != null) { // Highlight if not the same if (l.Front.Sector != highlightedsector) { HighlightSector(l.Front.Sector); } } else { // Highlight nothing if (highlightedsector != null) { HighlightSector(null); } } } } } else { HighlightSector(null); } if (highlightedslope != oldhighlight) { updateOverlaySurfaces(); UpdateOverlay(); General.Interface.RedrawDisplay(); } } else if (dragging && highlightedslope != null) { Vector2D newpos = SnapToNearest(mousemappos); Vector2D offset = highlightedslope.Pos - newpos; foreach (SlopeVertex sl in GetSelectedSlopeVertices()) { sl.Pos -= offset; } highlightedslope.Pos = newpos; General.Map.IsChanged = true; updateOverlaySurfaces(); UpdateOverlay(); General.Interface.RedrawDisplay(); } else if (selecting) { UpdateOverlay(); General.Interface.RedrawDisplay(); } }
private void SetupLabels() { Dictionary <Sector, List <TextLabel> > sectorlabels = new Dictionary <Sector, List <TextLabel> >(); PixelColor white = new PixelColor(255, 255, 255, 255); Dictionary <Sector, Dictionary <PlaneType, SlopeVertexGroup> > requiredlabels = new Dictionary <Sector, Dictionary <PlaneType, SlopeVertexGroup> >(); if (labels != null) { // Dispose old labels foreach (TextLabel l in labels) { l.Dispose(); } } labels = new List <TextLabel>(); // Go through all sectors that belong to a SVG and set which SVG their floor and // ceiling belongs to foreach (SlopeVertexGroup svg in BuilderPlug.Me.SlopeVertexGroups) { foreach (Sector s in svg.Sectors) { if (!requiredlabels.ContainsKey(s)) { requiredlabels.Add(s, new Dictionary <PlaneType, SlopeVertexGroup>()); requiredlabels[s][PlaneType.Floor] = null; requiredlabels[s][PlaneType.Ceiling] = null; } if ((svg.SectorPlanes[s] & PlaneType.Floor) == PlaneType.Floor) { requiredlabels[s][PlaneType.Floor] = svg; } if ((svg.SectorPlanes[s] & PlaneType.Ceiling) == PlaneType.Ceiling) { requiredlabels[s][PlaneType.Ceiling] = svg; } } } foreach (KeyValuePair <Sector, Dictionary <PlaneType, SlopeVertexGroup> > element in requiredlabels) { int numlabels = 0; int counter = 0; Sector sector = element.Key; Dictionary <PlaneType, SlopeVertexGroup> dict = element.Value; // How many planes of this sector have a SVG? if (dict[PlaneType.Floor] != null) { numlabels++; } if (dict[PlaneType.Ceiling] != null) { numlabels++; } TextLabel[] labelarray = new TextLabel[sector.Labels.Count * numlabels]; foreach (PlaneType pt in Enum.GetValues(typeof(PlaneType))) { if (dict[pt] == null) { continue; } // If we're in the second iteration of the loop both the ceiling and // floor of the sector have a SVG, so change to alignment of the // existing labels from center to left if (counter == 1) { for (int i = 0; i < sector.Labels.Count; i++) { labelarray[i].AlignX = TextAlignmentX.Left; } } for (int i = 0; i < sector.Labels.Count; i++) { int apos = sector.Labels.Count * counter + i; Vector2D v = sector.Labels[i].position; labelarray[apos] = new TextLabel(); labelarray[apos].TransformCoords = true; labelarray[apos].AlignY = TextAlignmentY.Middle; labelarray[apos].BackColor = General.Colors.Background.WithAlpha(255); labelarray[apos].Location = sector.Labels[i].position; if (dict[pt].Vertices.Contains(highlightedslope)) { labelarray[apos].Color = General.Colors.Highlight.WithAlpha(255); } else { labelarray[apos].Color = white; } if (pt == PlaneType.Floor) { labelarray[apos].Text = "F"; } else { labelarray[apos].Text = "C"; } // First iteration of loop -> may be the only label needed, so // set it to be in the center if (counter == 0) { labelarray[apos].AlignX = TextAlignmentX.Center; } // Second iteration of the loop so set it to be aligned at the right else if (counter == 1) { labelarray[apos].AlignX = TextAlignmentX.Right; } } counter++; } labels.AddRange(labelarray); } foreach (SlopeVertexGroup svg in BuilderPlug.Me.SlopeVertexGroups) { for (int i = 0; i < svg.Vertices.Count; i++) { SlopeVertex sv = svg.Vertices[i]; float x = sv.Pos.x; float y = sv.Pos.y - 14 * (1 / renderer.Scale); TextLabel label = new TextLabel(); label.TransformCoords = true; label.Location = new Vector2D(x, y); label.AlignX = TextAlignmentX.Center; label.AlignY = TextAlignmentY.Middle; label.BackColor = General.Colors.Background.WithAlpha(255); label.Text = ""; // Rearrange labels if they'd be (exactly) on each other // TODO: do something like that also for overlapping labels foreach (TextLabel l in labels) { if (l.Location.x == label.Location.x && l.Location.y == label.Location.y) { label.Location = new Vector2D(x, l.Location.y - l.TextSize.Height * (1 / renderer.Scale)); } } if (svg.Vertices.Contains(highlightedslope)) { label.Color = General.Colors.Highlight.WithAlpha(255); } else if (sv.Selected) { label.Color = General.Colors.Selection.WithAlpha(255); } else { label.Color = white; } label.Text += String.Format("Z: {0}", sv.Z); labels.Add(label); } } }
public TextLabel[] CreateLabels(Sector sector, SlopeVertex slopevertex, float scale) { int numlabels = 0; int loopcounter = 0; PixelColor white = new PixelColor(255, 255, 255, 255); // Count how many actual labels we have to create at each label position foreach (PlaneType pt in Enum.GetValues(typeof(PlaneType))) { if ((planetypes & pt) == pt) { numlabels++; } } // Split sectors can have multiple label positions, so we have to create // numlabels labels for each position TextLabel[] labels = new TextLabel[sector.Labels.Count * numlabels]; foreach (PlaneType pt in Enum.GetValues(typeof(PlaneType))) { if ((planetypes & pt) != pt) { continue; } bool highlighted = false; foreach (SlopeVertexGroup svg in slopevertexgroups[pt]) { if (svg.Vertices.Contains(slopevertex)) { highlighted = true; } } for (int i = 0; i < sector.Labels.Count; i++) { int apos = sector.Labels.Count * loopcounter + i; Vector2D location = sector.Labels[i].position; location.x += ((-6 * (numlabels - 1)) + (loopcounter * 12)) * (1 / scale); labels[apos] = new TextLabel(); labels[apos].TransformCoords = true; labels[apos].AlignX = TextAlignmentX.Center; labels[apos].AlignY = TextAlignmentY.Middle; labels[apos].BackColor = General.Colors.Background.WithAlpha(128); labels[apos].Location = location; if (highlighted) { labels[apos].Color = General.Colors.Highlight.WithAlpha(255); } else { labels[apos].Color = white; } if (pt == PlaneType.Floor) { labels[apos].Text = "F"; } else if (pt == PlaneType.Ceiling) { labels[apos].Text = "C"; } else if (pt == PlaneType.Bottom) { labels[apos].Text = "B"; } else if (pt == PlaneType.Top) { labels[apos].Text = "T"; } } loopcounter++; } return(labels); }