// This moves the selected geometry relatively // Returns true when geometry has actually moved private bool MoveGeometryRelative(Vector2D offset, bool snapgrid, bool snapnearest) { Vector2D oldpos = dragitem.Position; Vector2D anchorpos = dragitemposition + offset; Vector2D tl, br; // don't move if the offset contains invalid data if (!offset.IsFinite()) { return(false); } // Find the outmost vertices tl = br = oldpositions[0]; for (int i = 0; i < oldpositions.Count; i++) { if (oldpositions[i].x < tl.x) { tl.x = (int)oldpositions[i].x; } if (oldpositions[i].x > br.x) { br.x = (int)oldpositions[i].x; } if (oldpositions[i].y > tl.y) { tl.y = (int)oldpositions[i].y; } if (oldpositions[i].y < br.y) { br.y = (int)oldpositions[i].y; } } // Snap to nearest? if (snapnearest) { // Find nearest unselected vertex within range Vertex nv = MapSet.NearestVertexSquareRange(unselectedverts, anchorpos, BuilderPlug.Me.StitchRange / renderer.Scale); if (nv != null) { // Move the dragged item dragitem.Move(nv.Position); // Adjust the offset offset = nv.Position - dragitemposition; // Do not snap to grid! snapgrid = false; } else { // Find the nearest unselected line within range Linedef nl = MapSet.NearestLinedefRange(snaptolines, anchorpos, BuilderPlug.Me.StitchRange / renderer.Scale); if (nl != null) { // Snap to grid? if (snaptogrid) { // Get grid intersection coordinates List <Vector2D> coords = nl.GetGridIntersections(new Vector2D(0.0f, 0.0f), General.Map.Grid.GridRotate, General.Map.Grid.GridOriginX, General.Map.Grid.GridOriginY); // Find nearest grid intersection float found_distance = float.MaxValue; Vector2D found_coord = new Vector2D(); foreach (Vector2D v in coords) { Vector2D delta = anchorpos - v; if (delta.GetLengthSq() < found_distance) { found_distance = delta.GetLengthSq(); found_coord = v; } } // Move the dragged item dragitem.Move(found_coord); // Align to line here offset = found_coord - dragitemposition; // Do not snap to grid anymore snapgrid = false; } else { // Move the dragged item dragitem.Move(nl.NearestOnLine(anchorpos)); // Align to line here offset = nl.NearestOnLine(anchorpos) - dragitemposition; } } } } // Snap to grid? if (snapgrid) { // Move the dragged item dragitem.Move(anchorpos); // Snap item to grid dragitem.SnapToGrid(); // Adjust the offset offset += dragitem.Position - anchorpos; } // Make sure the offset is inside the map boundaries if (offset.x + tl.x < General.Map.Config.LeftBoundary) { offset.x = General.Map.Config.LeftBoundary - tl.x; } if (offset.x + br.x > General.Map.Config.RightBoundary) { offset.x = General.Map.Config.RightBoundary - br.x; } if (offset.y + tl.y > General.Map.Config.TopBoundary) { offset.y = General.Map.Config.TopBoundary - tl.y; } if (offset.y + br.y < General.Map.Config.BottomBoundary) { offset.y = General.Map.Config.BottomBoundary - br.y; } // Drag item moved? if (!snapgrid || (dragitem.Position != oldpos)) { int i = 0; // Move selected geometry foreach (Vertex v in selectedverts) { // Move vertex from old position relative to the // mouse position change since drag start v.Move(oldpositions[i] + offset); // Next i++; } // Update labels int index = 0; foreach (Linedef l in unstablelines) { labels[index++].Move(l.Start.Position, l.End.Position); } // Moved return(true); } else { // No changes return(false); } }
public static void CreateInvisibleBlocker(Linedef l, float min, float max, string objname, Transform holder) { if (max - min <= 0) { return; } if (l.start == l.end) { return; } GameObject blocker = new GameObject(objname); blocker.transform.SetParent(holder); blocker.layer = 9; Mesh mesh = new Mesh { name = objname + "_mesh" }; Vector3[] vertices = new Vector3[8]; Vector3[] normals = new Vector3[8]; int[] indices = new int[12]; vertices[0] = new Vector3(l.start.Position.x, min, l.start.Position.y); vertices[1] = new Vector3(l.end.Position.x, min, l.end.Position.y); vertices[2] = new Vector3(l.start.Position.x, max, l.start.Position.y); vertices[3] = new Vector3(l.end.Position.x, max, l.end.Position.y); vertices[4] = vertices[0]; vertices[5] = vertices[1]; vertices[6] = vertices[2]; vertices[7] = vertices[3]; indices[0] = 0; indices[1] = 1; indices[2] = 2; indices[3] = 2; indices[4] = 1; indices[5] = 3; indices[6] = 2; indices[7] = 1; indices[8] = 0; indices[9] = 3; indices[10] = 1; indices[11] = 2; Vector3 normal = (vertices[0] - vertices[1]).normalized; float z = normal.z; float x = normal.x; normal.x = -z; normal.z = x; for (int i = 0; i < 4; i++) { normals[i] = -normal; } for (int i = 4; i < 8; i++) { normals[i] = normal; } mesh.vertices = vertices; mesh.triangles = indices; mesh.normals = normals; mesh.RecalculateBounds(); MeshCollider mc = blocker.AddComponent <MeshCollider>(); mc.sharedMesh = mesh; }
public void BindTag(int tag, LinedefProperties ldprops) { Linedef line = null; // try to find an line without an action foreach (Sidedef sd in sector.Sidedefs) { if (sd.Line.Action == 0 && sd.Line.Tag == 0 && line == null) { line = sd.Line; } // if a line of the control sector already has the tag // nothing has to be done if (sd.Line.Args[0] == tag) { return; } } // no lines without an action, so a line has to get split // find the longest line to split if (line == null) { line = sector.Sidedefs.First().Line; foreach (Sidedef sd in sector.Sidedefs) { if (sd.Line.Length > line.Length) { line = sd.Line; } } // Lines may not have a length of less than 1 after splitting if (line.Length / 2 < 1) { throw new Exception("Can't split more lines in Sector " + line.Front.Sector.Index.ToString() + "."); } Vertex v = General.Map.Map.CreateVertex(line.Line.GetCoordinatesAt(0.5f)); v.SnapToAccuracy(); line = line.Split(v); General.Map.Map.Update(); General.Interface.RedrawDisplay(); } if (ldprops != null) { ldprops.Apply(new List <Linedef>() { line }, false); } line.Action = 160; line.Args[0] = tag; line.Args[1] = type; line.Args[2] = flags; line.Args[3] = alpha; }
//mxd. Constructor public Line2D(Linedef line) { this.v1 = line.Start.Position; this.v2 = line.End.Position; }
// This shows the info public void ShowInfo(Linedef l) { TypeHandler th; bool upperunpegged, lowerunpegged; string peggedness; //double starttime = General.stopwatch.Elapsed.TotalMilliseconds; SuspendLayout(); // Show/hide stuff depending on format if (!General.Map.FormatInterface.HasActionArgs) { if (bUsingArgsAlready || bNeedSetup) { arglbl1.Visible = false; arglbl2.Visible = false; arglbl3.Visible = false; arglbl4.Visible = false; arglbl5.Visible = false; arg1.Visible = false; arg2.Visible = false; arg3.Visible = false; arg4.Visible = false; arg5.Visible = false; tableLayoutPanel1.ColumnStyles[1].Width = 0f; infopanel.Width = doomformatwidth; bUsingArgsAlready = false; } } else { if (!bUsingArgsAlready || bNeedSetup) { arglbl1.Visible = true; arglbl2.Visible = true; arglbl3.Visible = true; arglbl4.Visible = true; arglbl5.Visible = true; arg1.Visible = true; arg2.Visible = true; arg3.Visible = true; arg4.Visible = true; arg5.Visible = true; tableLayoutPanel1.ColumnStyles[1].Width = 37.5f; infopanel.Width = hexenformatwidth; bUsingArgsAlready = true; } } // Move panels frontpanel.Left = infopanel.Left + infopanel.Width + infopanel.Margin.Right + frontpanel.Margin.Left; backpanel.Left = frontpanel.Left + frontpanel.Width + frontpanel.Margin.Right + backpanel.Margin.Left; // Get line action information LinedefActionInfo act = General.Map.Config.GetLinedefActionInfo(l.Action); // Determine peggedness upperunpegged = l.IsFlagSet(General.Map.Config.UpperUnpeggedFlag); lowerunpegged = l.IsFlagSet(General.Map.Config.LowerUnpeggedFlag); if (upperunpegged && lowerunpegged) { peggedness = "Upper/Lower"; } else if (upperunpegged) { peggedness = "Upper"; } else if (lowerunpegged) { peggedness = "Lower"; } else { peggedness = "None"; } // Linedef info sb.Length = 0; sb.Append(" Linedef "); sb.Append(l.Index); sb.Append(" "); infopanel.Text = sb.ToString(); sb.Length = 0; action.Text = act.ToString(); length.Text = l.Length.ToString("0.##"); sb.Append(l.AngleDeg.ToString()); sb.Append("\u00B0"); angle.Text = sb.ToString(); sb.Length = 0; tag.Text = l.Tag.ToString(); unpegged.Text = peggedness; if (bUsingArgsAlready) { // Arguments sb.Append(act.Args[0].Title); sb.Append(':'); arglbl1.Text = sb.ToString(); sb.Length = 0; sb.Append(act.Args[1].Title); sb.Append(':'); arglbl2.Text = sb.ToString(); sb.Length = 0; sb.Append(act.Args[2].Title); sb.Append(':'); arglbl3.Text = sb.ToString(); sb.Length = 0; sb.Append(act.Args[3].Title); sb.Append(':'); arglbl4.Text = sb.ToString(); sb.Length = 0; sb.Append(act.Args[4].Title); sb.Append(':'); arglbl5.Text = sb.ToString(); sb.Length = 0; arglbl1.Enabled = act.Args[0].Used; arglbl2.Enabled = act.Args[1].Used; arglbl3.Enabled = act.Args[2].Used; arglbl4.Enabled = act.Args[3].Used; arglbl5.Enabled = act.Args[4].Used; arg1.Enabled = act.Args[0].Used; arg2.Enabled = act.Args[1].Used; arg3.Enabled = act.Args[2].Used; arg4.Enabled = act.Args[3].Used; arg5.Enabled = act.Args[4].Used; th = General.Types.GetArgumentHandler(act.Args[0]); th.SetValue(l.Args[0]); arg1.Text = th.GetStringValue(); th = General.Types.GetArgumentHandler(act.Args[1]); th.SetValue(l.Args[1]); arg2.Text = th.GetStringValue(); th = General.Types.GetArgumentHandler(act.Args[2]); th.SetValue(l.Args[2]); arg3.Text = th.GetStringValue(); th = General.Types.GetArgumentHandler(act.Args[3]); th.SetValue(l.Args[3]); arg4.Text = th.GetStringValue(); th = General.Types.GetArgumentHandler(act.Args[4]); th.SetValue(l.Args[4]); arg5.Text = th.GetStringValue(); } // Front side available? if (l.Front != null) { // Show sidedef info sb.Append(" Front Sidedef "); sb.Append(l.Front.Index); sb.Append(' '); frontpanel.Text = sb.ToString(); sb.Length = 0; sb.Append(" Sector "); sb.Append(l.Front.Sector.Index); frontsector.Text = sb.ToString(); sb.Length = 0; frontsector.Visible = true; sb.Append(l.Front.OffsetX); sb.Append(", "); sb.Append(l.Front.OffsetY); frontoffset.Text = sb.ToString(); sb.Length = 0; fronthighname.Text = l.Front.HighTexture; frontmidname.Text = l.Front.MiddleTexture; frontlowname.Text = l.Front.LowTexture; DisplaySidedefTexture(fronthightex, l.Front.HighTexture, l.Front.HighRequired()); DisplaySidedefTexture(frontmidtex, l.Front.MiddleTexture, l.Front.MiddleRequired()); DisplaySidedefTexture(frontlowtex, l.Front.LowTexture, l.Front.LowRequired()); frontoffsetlabel.Enabled = true; frontoffset.Enabled = true; frontpanel.Enabled = true; } else { // Show no info frontpanel.Text = " Front Sidedef "; frontsector.Text = ""; frontsector.Visible = false; frontoffsetlabel.Enabled = false; frontoffset.Enabled = false; frontpanel.Enabled = false; frontoffset.Text = "--, --"; fronthighname.Text = ""; frontmidname.Text = ""; frontlowname.Text = ""; fronthightex.BackgroundImage = null; frontmidtex.BackgroundImage = null; frontlowtex.BackgroundImage = null; } // Back size available? if (l.Back != null) { // Show sidedef info sb.Append(" Back Sidedef "); sb.Append(l.Back.Index); sb.Append(' '); backpanel.Text = sb.ToString(); sb.Length = 0; sb.Append(" Sector "); sb.Append(l.Back.Sector.Index); backsector.Text = sb.ToString(); sb.Length = 0; backsector.Visible = true; sb.Append(l.Back.OffsetX); sb.Append(", "); sb.Append(l.Back.OffsetY); backoffset.Text = sb.ToString(); sb.Length = 0; backhighname.Text = l.Back.HighTexture; backmidname.Text = l.Back.MiddleTexture; backlowname.Text = l.Back.LowTexture; DisplaySidedefTexture(backhightex, l.Back.HighTexture, l.Back.HighRequired()); DisplaySidedefTexture(backmidtex, l.Back.MiddleTexture, l.Back.MiddleRequired()); DisplaySidedefTexture(backlowtex, l.Back.LowTexture, l.Back.LowRequired()); backoffsetlabel.Enabled = true; backoffset.Enabled = true; backpanel.Enabled = true; } else { // Show no info backpanel.Text = " Back Sidedef "; backsector.Text = ""; backsector.Visible = false; backoffsetlabel.Enabled = false; backoffset.Enabled = false; backpanel.Enabled = false; backoffset.Text = "--, --"; backhighname.Text = ""; backmidname.Text = ""; backlowname.Text = ""; backhightex.BackgroundImage = null; backmidtex.BackgroundImage = null; backlowtex.BackgroundImage = null; } // Position labels frontsector.Left = frontlowtex.Right - frontsector.Width; backsector.Left = backlowtex.Right - backsector.Width; ResumeLayout(); // Show the whole thing this.Show(); this.Invalidate(); //this.Update(); // ano - don't think this is needed, and is slow bNeedSetup = false; //Logger.WriteLogLine((General.stopwatch.Elapsed.TotalMilliseconds - starttime) + " milliseconds for linedefinfopanel.showinfo"); }
// This puts a single linedef in all blocks it crosses public void AddLinedef(Linedef line) { // Get coordinates Vector2D v1 = line.Start.Position; Vector2D v2 = line.End.Position; // Find start and end block Point pos = GetBlockCoordinates(v1); Point end = GetBlockCoordinates(v2); // Horizontal straight line? if (pos.Y == end.Y) { // Simple loop int dirx = Math.Sign(v2.x - v1.x); for (int x = pos.X; x != end.X; x += dirx) { GetBlock(new Point(x, pos.Y)).Lines.Add(line); } GetBlock(end).Lines.Add(line); } // Vertical straight line? else if (pos.X == end.X) { // Simple loop int diry = Math.Sign(v2.y - v1.y); for (int y = pos.Y; y != end.Y; y += diry) { GetBlock(new Point(pos.X, y)).Lines.Add(line); } GetBlock(end).Lines.Add(line); } else { // Add lines to this block GetBlock(pos).Lines.Add(line); // Moving outside the block? if (pos != end) { // Calculate current block edges float cl = pos.X * BLOCK_SIZE; float cr = (pos.X + 1) * BLOCK_SIZE; float ct = pos.Y * BLOCK_SIZE; float cb = (pos.Y + 1) * BLOCK_SIZE; // Line directions int dirx = Math.Sign(v2.x - v1.x); int diry = Math.Sign(v2.y - v1.y); // Calculate offset and delta movement over x float deltax; float posx; if (dirx == 0) { posx = float.MaxValue; deltax = float.MaxValue; } else if (dirx > 0) { posx = (cr - v1.x) / (v2.x - v1.x); deltax = BLOCK_SIZE / (v2.x - v1.x); } else { // Calculate offset and delta movement over x posx = (v1.x - cl) / (v1.x - v2.x); deltax = BLOCK_SIZE / (v1.x - v2.x); } // Calculate offset and delta movement over y float deltay; float posy; if (diry == 0) { posy = float.MaxValue; deltay = float.MaxValue; } else if (diry > 0) { posy = (cb - v1.y) / (v2.y - v1.y); deltay = BLOCK_SIZE / (v2.y - v1.y); } else { posy = (v1.y - ct) / (v1.y - v2.y); deltay = BLOCK_SIZE / (v1.y - v2.y); } // Continue while not reached the end while (pos != end) { // Check in which direction to move if (posx < posy) { // Move horizontally posx += deltax; if (pos.X != end.X) { pos.X += dirx; } } else { // Move vertically posy += deltay; if (pos.Y != end.Y) { pos.Y += diry; } } // Add lines to this block GetBlock(pos).Lines.Add(line); } } } }
// Constructor public ResultLineMissingSides(Linedef l) { // Initialize line = l; viewobjects.Add(l); hidden = l.IgnoredErrorChecks.Contains(this.GetType()); //mxd description = "This linedef is missing front and back sidedefs." + "A line must have at least a front side and optionally a back side!"; buttons = 0; // Check if we can join a sector on the front side bool fixable = false; List <LinedefSide> sides = Tools.FindPotentialSectorAt(l, true); if (sides != null) { foreach (LinedefSide sd in sides) { // If any of the sides lies along a sidedef, then we can copy // that sidedef to fix the missing sidedef on this line. if (sd.Front && (sd.Line.Front != null)) { copysidedeffront = sd.Line.Front; fixable = true; break; } if (!sd.Front && (sd.Line.Back != null)) { copysidedeffront = sd.Line.Back; fixable = true; break; } } } // Fixable? if (fixable) { buttons++; } // Check if we can join a sector on the back side fixable = false; sides = Tools.FindPotentialSectorAt(l, false); if (sides != null) { foreach (LinedefSide sd in sides) { // If any of the sides lies along a sidedef, then we can copy // that sidedef to fix the missing sidedef on this line. if (sd.Front && (sd.Line.Front != null)) { copysidedefback = sd.Line.Front; fixable = true; break; } if (!sd.Front && (sd.Line.Back != null)) { copysidedefback = sd.Line.Back; fixable = true; break; } } } // Fixable? if (fixable) { buttons++; } // Now make a fine description switch (buttons) { case 0: description += " Doom Builder could not find a solution to fix this line."; break; case 1: description += " Click Create One Side to rebuild a single sidedef, making this line single-sided."; break; case 2: description += " Click Create Both Side to rebuild both sides of the line, making this line double-sided."; break; } }
private void GetSetBaseHeights(Linedef ld) { if (baseheightset) return; baseheightset = true; if (stairsectorbuilderform.SideFront) { if (ld.Back == null && ld.Front != null) { stairsectorbuilderform.CeilingBase = ld.Front.Sector.CeilHeight; stairsectorbuilderform.FloorBase = ld.Front.Sector.FloorHeight; stairsectorbuilderform.LightingBase = ld.Front.Sector.Brightness == 255 ? 256 : ld.Front.Sector.Brightness; } else if(ld.Front == null && ld.Back != null) { stairsectorbuilderform.CeilingBase = ld.Back.Sector.CeilHeight; stairsectorbuilderform.FloorBase = ld.Back.Sector.FloorHeight; stairsectorbuilderform.LightingBase = ld.Back.Sector.Brightness == 255 ? 256 : ld.Back.Sector.Brightness; } else { stairsectorbuilderform.CeilingBase = 128; stairsectorbuilderform.FloorBase = 0; stairsectorbuilderform.LightingBase = 192; } } else { stairsectorbuilderform.CeilingBase = ld.Front.Sector.CeilHeight; stairsectorbuilderform.FloorBase = ld.Front.Sector.FloorHeight; stairsectorbuilderform.LightingBase = ld.Front.Sector.Brightness == 255 ? 256 : ld.Front.Sector.Brightness; } }
private void InsertVertex() { bool snaptogrid = General.Interface.ShiftState ^ General.Interface.SnapToGrid; bool snaptonearest = General.Interface.CtrlState ^ General.Interface.AutoMerge; // Mouse in window? if (General.Interface.MouseInDisplay) { Vector2D insertpos; // Create undo General.Map.UndoRedo.CreateUndo("Insert vertex"); // Snap to geometry? Linedef l = General.Map.Map.NearestLinedefRange(mousemappos, BuilderPlug.Me.SplitLinedefsRange / renderer.Scale); if (snaptonearest && (l != null)) { // Snip to grid also? if (snaptogrid) { // Find all points where the grid intersects the line List <Vector2D> points = l.GetGridIntersections(General.Map.Grid.GridRotate, General.Map.Grid.GridOriginX, General.Map.Grid.GridOriginY); if (points.Count == 0) { //mxd. Just use the nearest point on line insertpos = l.NearestOnLine(mousemappos); } else { insertpos = mousemappos; double distance = double.MaxValue; foreach (Vector2D p in points) { double pdist = Vector2D.DistanceSq(p, mousemappos); if (pdist < distance) { insertpos = p; distance = pdist; } } } } else { // Just use the nearest point on line insertpos = l.NearestOnLine(mousemappos); } } // Snap to grid? else if (snaptogrid) { // Snap to grid insertpos = General.Map.Grid.SnappedToGrid(mousemappos); } else { // Just insert here, don't snap to anything insertpos = mousemappos; } // Make the vertex Vertex v = General.Map.Map.CreateVertex(insertpos); if (v == null) { General.Map.UndoRedo.WithdrawUndo(); return; } // Snap to map format accuracy v.SnapToAccuracy(); // Split the line with this vertex if (snaptonearest) { //mxd. Check if snapped vertex is still on top of a linedef l = General.Map.Map.NearestLinedefRange(v.Position, BuilderPlug.Me.SplitLinedefsRange / renderer.Scale); if (l != null) { //mxd if (v.Position == l.Start.Position || v.Position == l.End.Position) { General.Interface.DisplayStatus(StatusType.Info, "There's already a vertex here."); General.Map.UndoRedo.WithdrawUndo(); return; } General.Interface.DisplayStatus(StatusType.Action, "Split a linedef."); Linedef sld = l.Split(v); if (sld == null) { General.Map.UndoRedo.WithdrawUndo(); return; } //BuilderPlug.Me.AdjustSplitCoordinates(l, sld); } } else { General.Interface.DisplayStatus(StatusType.Action, "Inserted a vertex."); } // Update General.Map.Map.Update(); // Redraw screen General.Interface.RedrawDisplay(); } }
// This runs the check public override void Run() { BlockMap <BlockEntry> blockmap = BuilderPlug.Me.ErrorCheckForm.BlockMap; int progress = 0; int stepprogress = 0; float maxradius = 0; Dictionary <int, HashSet <int> > processedthingpairs = new Dictionary <int, HashSet <int> >(); //mxd foreach (ThingTypeInfo tti in General.Map.Data.ThingTypes) { if (tti.Radius > maxradius) { maxradius = tti.Radius; } } // Go for all the things foreach (Thing t in General.Map.Map.Things) { ThingTypeInfo info = General.Map.Data.GetThingInfo(t.Type); bool stuck = false; // Check this thing for getting stuck? if ((info.ErrorCheck == ThingTypeInfo.THING_ERROR_INSIDE_STUCK) && (info.Blocking > ThingTypeInfo.THING_BLOCKING_NONE)) { // Make square coordinates from thing float blockingsize = t.Size - ALLOWED_STUCK_DISTANCE; Vector2D lt = new Vector2D(t.Position.x - blockingsize, t.Position.y - blockingsize); Vector2D rb = new Vector2D(t.Position.x + blockingsize, t.Position.y + blockingsize); Vector2D bmlt = new Vector2D(t.Position.x - maxradius, t.Position.y - maxradius); Vector2D bmrb = new Vector2D(t.Position.x + maxradius, t.Position.y + maxradius); // Go for all the lines to see if this thing is stuck List <BlockEntry> blocks = blockmap.GetSquareRange(new RectangleF((float)bmlt.x, (float)bmlt.y, (float)(bmrb.x - bmlt.x), (float)(bmrb.y - bmlt.y))); Dictionary <Linedef, Linedef> doneblocklines = new Dictionary <Linedef, Linedef>(blocks.Count * 3); foreach (BlockEntry b in blocks) { foreach (Linedef l in b.Lines) { // Only test when sinlge-sided, two-sided + impassable and not already checked if (((l.Back == null) || l.IsFlagSet(General.Map.Config.ImpassableFlag)) && !doneblocklines.ContainsKey(l)) { // Test if line ends are inside the thing if (PointInRect(lt, rb, l.Start.Position) || PointInRect(lt, rb, l.End.Position)) { // Thing stuck in line! stuck = true; SubmitResult(new ResultStuckThingInLine(t, l)); } // Test if the line intersects the square else if (Line2D.GetIntersection(l.Start.Position, l.End.Position, lt.x, lt.y, rb.x, lt.y) || Line2D.GetIntersection(l.Start.Position, l.End.Position, rb.x, lt.y, rb.x, rb.y) || Line2D.GetIntersection(l.Start.Position, l.End.Position, rb.x, rb.y, lt.x, rb.y) || Line2D.GetIntersection(l.Start.Position, l.End.Position, lt.x, rb.y, lt.x, lt.y)) { // Thing stuck in line! stuck = true; SubmitResult(new ResultStuckThingInLine(t, l)); } // Checked doneblocklines.Add(l, l); } } // Check if thing is stuck in other things if (info.Blocking != ThingTypeInfo.THING_BLOCKING_NONE) { foreach (Thing ot in b.Things) { // Don't compare the thing with itself if (t.Index == ot.Index) { continue; } // mxd. Don't compare already processed stuff if (processedthingpairs.ContainsKey(t.Index) && processedthingpairs[t.Index].Contains(ot.Index)) { continue; } // Only check of items that can block if (General.Map.Data.GetThingInfo(ot.Type).Blocking == ThingTypeInfo.THING_BLOCKING_NONE) { continue; } // need to compare the flags if (FlagsOverlap(t, ot) && ThingsOverlap(t, ot)) { stuck = true; SubmitResult(new ResultStuckThingInThing(t, ot)); } //mxd. Prepare collections if (!processedthingpairs.ContainsKey(t.Index)) { processedthingpairs.Add(t.Index, new HashSet <int>()); } if (!processedthingpairs.ContainsKey(ot.Index)) { processedthingpairs.Add(ot.Index, new HashSet <int>()); } //mxd. Add both ways processedthingpairs[t.Index].Add(ot.Index); processedthingpairs[ot.Index].Add(t.Index); } } } } // Check this thing for being outside the map? if (!stuck && info.ErrorCheck >= ThingTypeInfo.THING_ERROR_INSIDE) { // Get the nearest line to see if the thing is outside the map bool outside; Linedef l = General.Map.Map.NearestLinedef(t.Position); if (l.SideOfLine(t.Position) <= 0) { outside = (l.Front == null); } else { outside = (l.Back == null); } // Outside the map? if (outside) { // Make result SubmitResult(new ResultThingOutside(t)); } } // Handle thread interruption try { Thread.Sleep(0); } catch (ThreadInterruptedException) { return; } // We are making progress! if ((++progress / PROGRESS_STEP) > stepprogress) { stepprogress = (progress / PROGRESS_STEP); AddProgress(1); } } }
// Mouse moves public override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); if (panning) { return; //mxd. Skip all this jazz while panning } //mxd if (selectpressed && !editpressed && !selecting) { // Check if moved enough pixels for multiselect Vector2D delta = mousedownpos - mousepos; if ((Math.Abs(delta.x) > BuilderPlug.Me.MouseSelectionThreshold) || (Math.Abs(delta.y) > BuilderPlug.Me.MouseSelectionThreshold)) { // Start multiselecting StartMultiSelection(); } } else if (paintselectpressed && !editpressed && !selecting) //mxd. Drag-select { // Find the nearest thing within highlight range Vertex v = General.Map.Map.NearestVertexSquareRange(mousemappos, BuilderPlug.Me.HighlightRange / renderer.Scale); if (v != null) { if (v != highlighted) { //toggle selected state if (General.Interface.ShiftState ^ BuilderPlug.Me.AdditivePaintSelect) { v.Selected = true; } else if (General.Interface.CtrlState) { v.Selected = false; } else { v.Selected = !v.Selected; } highlighted = v; UpdateSelectionInfo(); //mxd // Update entire display General.Interface.RedrawDisplay(); } } else if (highlighted != null) { highlighted = null; Highlight(null); // Update entire display General.Interface.RedrawDisplay(); } } else if (e.Button == MouseButtons.None) // Not holding any buttons? { //mxd. Render insert vertex preview Linedef l = General.Map.Map.NearestLinedefRange(mousemappos, BuilderPlug.Me.SplitLinedefsRange / renderer.Scale); if (l != null) { // Snip to grid? if (General.Interface.ShiftState ^ General.Interface.SnapToGrid) { // Find all points where the grid intersects the line List <Vector2D> points = l.GetGridIntersections(General.Map.Grid.GridRotate, General.Map.Grid.GridOriginX, General.Map.Grid.GridOriginY); if (points.Count == 0) { insertpreview = l.NearestOnLine(mousemappos); } else { insertpreview = mousemappos; double distance = double.MaxValue; foreach (Vector2D p in points) { double pdist = Vector2D.DistanceSq(p, mousemappos); if (pdist < distance) { insertpreview = p; distance = pdist; } } } } else { // Just use the nearest point on line insertpreview = l.NearestOnLine(mousemappos); } //render preview if (renderer.StartOverlay(true)) { double dist = Math.Min(Vector2D.Distance(mousemappos, insertpreview), BuilderPlug.Me.SplitLinedefsRange); byte alpha = (byte)(255 - (dist / BuilderPlug.Me.SplitLinedefsRange) * 128); float vsize = (renderer.VertexSize + 1.0f) / renderer.Scale; renderer.RenderRectangleFilled(new RectangleF((float)(insertpreview.x - vsize), (float)(insertpreview.y - vsize), vsize * 2.0f, vsize * 2.0f), General.Colors.InfoLine.WithAlpha(alpha), true); renderer.Finish(); renderer.Present(); } } else if (insertpreview.IsFinite()) { insertpreview.x = float.NaN; //undraw preveiw if (renderer.StartOverlay(true)) { renderer.Finish(); renderer.Present(); } } // Find the nearest vertex within highlight range Vertex v = General.Map.Map.NearestVertexSquareRange(mousemappos, BuilderPlug.Me.HighlightRange / renderer.Scale); // Highlight if not the same if (v != highlighted) { Highlight(v); } } }
private bool GetLinedefPair(SectorGroup sga, SectorGroup sgb, out Linedef la, out Linedef lb) { Vector2D offset = sgb.BBAnchor - sga.BBAnchor; List<Sidedef> sidedefs = new List<Sidedef>(); la = lb = null; foreach (Sector s in sga.Sectors) { foreach (Sidedef sd in s.Sidedefs.Where(sdx => sdx.Line.Action == 0 && sdx.Line.Tag == 0).OrderByDescending(sdx => sdx.Line.Length)) if (!sidedefs.Contains(sd)) sidedefs.Add(sd); } // Get all sidedefs of sector a without action and tag, ordered by their length foreach (Sidedef sda in sidedefs) { foreach (Sector s in sgb.Sectors) { try { // Sidedef sdb = s.Sidedefs.Where(sd => (sd.Line.Start.Position == sda.Line.Start.Position + offset && sd.Line.End.Position == sda.Line.End.Position + offset) || (sd.Line.Start.Position == sda.Line.End.Position + offset && sd.Line.End.Position == sda.Line.Start.Position + offset)).First(); var x = s.Sidedefs.Where(sd => (sd.Line.Start.Position == sda.Line.Start.Position + offset && sd.Line.End.Position == sda.Line.End.Position + offset) || (sd.Line.Start.Position == sda.Line.End.Position + offset && sd.Line.End.Position == sda.Line.Start.Position + offset)); Sidedef sdb = x.First(); if (sdb.Line.Action == 0 && sdb.Line.Tag == 0) { la = sda.Line; lb = sdb.Line; return true; } } catch (Exception e) { } } } return false; }
private bool CreateWallPortalGeometry(Linedef ld) { Vector2D p = ld.Line.GetPerpendicular().GetNormal(); List<DrawnVertex> dv = new List<DrawnVertex>(); dv.Add(SectorVertex(ld.Line.v2)); dv.Add(SectorVertex(ld.Line.v1)); dv.Add(SectorVertex(ld.Line.v1 + p * wallgeometrydepth)); dv.Add(SectorVertex(ld.Line.v2 + p * wallgeometrydepth)); dv.Add(SectorVertex(ld.Line.v2)); return Tools.DrawLines(dv); }
// This shows the info public void ShowInfo(Linedef l, Sidedef highlightside) { string peggedness; // Show/hide stuff depending on format if (!General.Map.FormatInterface.HasActionArgs) { arglbl1.Visible = false; arglbl2.Visible = false; arglbl3.Visible = false; arglbl4.Visible = false; arglbl5.Visible = false; arg1.Visible = false; arg2.Visible = false; arg3.Visible = false; arg4.Visible = false; arg5.Visible = false; infopanel.Width = doomformatwidth; } else { arglbl1.Visible = true; arglbl2.Visible = true; arglbl3.Visible = true; arglbl4.Visible = true; arglbl5.Visible = true; arg1.Visible = true; arg2.Visible = true; arg3.Visible = true; arg4.Visible = true; arg5.Visible = true; infopanel.Width = hexenformatwidth; } //mxd. Hide activation or tag and rearrange labels if (!General.Map.FormatInterface.HasBuiltInActivations && General.Map.FormatInterface.HasNumericLinedefActivations) //Hexen map format? { activation.Visible = true; activationlabel.Text = "Activation:"; activationlabel.Visible = true; taglabel.Visible = false; tag.Visible = false; //set activation foreach (LinedefActivateInfo ai in General.Map.Config.LinedefActivates) { if (l.Activate == ai.Index) { activation.Text = ai.Title; break; } } activation.Enabled = (l.Activate != 0 || l.Action != 0); //mxd activationlabel.Enabled = (l.Activate != 0 || l.Action != 0); //mxd } else { if (General.Map.UDMF) { // Hijack activation labels to show lock numer... activationlabel.Text = "Lock:"; activationlabel.Visible = true; activation.Visible = true; int locknum = l.Fields.GetValue("locknumber", 0); if (locknum != 0) { activationlabel.Enabled = true; activation.Enabled = true; if (General.Map.Config.Enums.ContainsKey("keys")) { foreach (EnumItem item in General.Map.Config.Enums["keys"]) { if (item.GetIntValue() == locknum) { activation.Text = locknum + " - " + item.Title; break; } } } else { activation.Text = locknum.ToString(); } } else { activationlabel.Enabled = false; activation.Enabled = false; activation.Text = "None"; } } else { // Should be Doom map format activationlabel.Visible = false; activation.Visible = false; } taglabel.Visible = true; tag.Visible = true; //mxd. Set tag(s) if (l.Tags.Count > 1) { string[] tags = new string[l.Tags.Count]; for (int i = 0; i < l.Tags.Count; i++) { tags[i] = l.Tags[i].ToString(); } tag.Text = string.Join(", ", tags); tag.Enabled = true; taglabel.Enabled = true; taglabel.Text = "Tags:"; } else { tag.Text = l.Tag + (General.Map.Options.TagLabels.ContainsKey(l.Tag) ? " - " + General.Map.Options.TagLabels[l.Tag] : string.Empty); tag.Enabled = (l.Tag != 0); taglabel.Enabled = (l.Tag != 0); taglabel.Text = "Tag:"; } } // Get line action information LinedefActionInfo act = General.Map.Config.GetLinedefActionInfo(l.Action); // Determine peggedness bool upperunpegged = l.IsFlagSet(General.Map.Config.UpperUnpeggedFlag); bool lowerunpegged = l.IsFlagSet(General.Map.Config.LowerUnpeggedFlag); if (upperunpegged && lowerunpegged) { peggedness = "Upper & Lower"; } else if (upperunpegged) { peggedness = "Upper"; } else if (lowerunpegged) { peggedness = "Lower"; } else { peggedness = "None"; } // Linedef info #if DEBUG infopanel.Text = " Linedef " + l.Index + " (vert. " + l.Start.Index + " - vert. " + l.End.Index + ") "; #else infopanel.Text = " Linedef " + l.Index + " "; #endif action.Text = act.ToString(); length.Text = l.Length.ToString("0.##"); angle.Text = l.AngleDeg + "\u00B0"; unpegged.Text = peggedness; unpegged.Enabled = (peggedness != "None"); //mxd peglabel.Enabled = (peggedness != "None"); //mxd action.Enabled = (act.Index != 0); actionlabel.Enabled = (act.Index != 0); //mxd. ACS script argument names bool isacsscript = (Array.IndexOf(GZGeneral.ACS_SPECIALS, l.Action) != -1); bool isnamedacsscript = (isacsscript && General.Map.UDMF && l.Fields.ContainsKey("arg0str")); string scriptname = (isnamedacsscript ? l.Fields.GetValue("arg0str", string.Empty) : string.Empty); ScriptItem scriptitem = null; //mxd. Set default label colors arg1.ForeColor = SystemColors.ControlText; arglbl1.ForeColor = SystemColors.ControlText; // Named script? if (isnamedacsscript && General.Map.NamedScripts.ContainsKey(scriptname.ToLowerInvariant())) { scriptitem = General.Map.NamedScripts[scriptname.ToLowerInvariant()]; } // Script number? else if (isacsscript && General.Map.NumberedScripts.ContainsKey(l.Args[0])) { scriptitem = General.Map.NumberedScripts[l.Args[0]]; scriptname = (scriptitem.HasCustomName ? scriptitem.Name : scriptitem.Index.ToString()); } // Apply script args? Label[] arglabels = { arglbl1, arglbl2, arglbl3, arglbl4, arglbl5 }; Label[] args = { arg1, arg2, arg3, arg4, arg5 }; if (scriptitem != null) { string[] argnames = scriptitem.GetArgumentsDescriptions(l.Action); for (int i = 0; i < argnames.Length; i++) { if (!string.IsNullOrEmpty(argnames[i])) { arglabels[i].Text = argnames[i] + ":"; arglabels[i].Enabled = true; args[i].Enabled = true; } else { arglabels[i].Text = act.Args[i].Title + ":"; arglabels[i].Enabled = act.Args[i].Used; args[i].Enabled = act.Args[i].Used; } } } else { for (int i = 0; i < act.Args.Length; i++) { arglabels[i].Text = act.Args[i].Title + ":"; arglabels[i].Enabled = act.Args[i].Used; args[i].Enabled = act.Args[i].Used; } // Special cases: unknown script name/index if (isacsscript || isnamedacsscript) { arglbl1.Text = "Unknown script " + (isnamedacsscript ? "name" : "number") + ":"; arg1.ForeColor = Color.DarkRed; arglbl1.ForeColor = Color.DarkRed; } } //mxd. Set argument value and label if (!string.IsNullOrEmpty(scriptname)) { arg1.Text = scriptname; } else { SetArgumentText(act.Args[0], arg1, l.Args[0]); } SetArgumentText(act.Args[1], arg2, l.Args[1]); SetArgumentText(act.Args[2], arg3, l.Args[2]); SetArgumentText(act.Args[3], arg4, l.Args[3]); SetArgumentText(act.Args[4], arg5, l.Args[4]); // Front side available? if (l.Front != null) { //mxd. Extended info shown? bool hasTopFields = false; bool hasMiddleFields = false; bool hasBottomFields = false; //mxd. Highlight this side? bool highlight = (l.Front == highlightside); frontpanel.ForeColor = (highlight ? SystemColors.HotTrack : SystemColors.WindowText); //mxd // Show sidedef info frontpanel.Visible = true; //mxd frontpanel.Text = " Front Sidedef " + l.Front.Index; //mxd if (General.Map.UDMF) { //light frontoffsetlabel.Text = "Front light:"; SetUDMFLight(l.Front, frontoffsetlabel, frontoffset, highlight); //global offset, sector index frontpanel.Text += ". Offset " + l.Front.OffsetX + ", " + l.Front.OffsetY + ". Sector " + l.Front.Sector.Index + " "; //sidedef top hasTopFields = SetPairedUDMFFieldsLabel(l.Front.Fields, "offsetx_top", "offsety_top", 0.0f, frontTopUDMFOffsetLabel, frontTopUDMFOffset, highlight); hasTopFields |= SetPairedUDMFFieldsLabel(l.Front.Fields, "scalex_top", "scaley_top", 1.0f, frontTopUDMFScaleLabel, frontTopUDMFScale, highlight); //sidedef middle hasMiddleFields = SetPairedUDMFFieldsLabel(l.Front.Fields, "offsetx_mid", "offsety_mid", 0.0f, frontMidUDMFOffsetLabel, frontMidUDMFOffset, highlight); hasMiddleFields |= SetPairedUDMFFieldsLabel(l.Front.Fields, "scalex_mid", "scaley_mid", 1.0f, frontMidUDMFScaleLabel, frontMidUDMFScale, highlight); //sidedef bottom hasBottomFields = SetPairedUDMFFieldsLabel(l.Front.Fields, "offsetx_bottom", "offsety_bottom", 0.0f, frontBottomUDMFOffsetLabel, frontBottomUDMFOffset, highlight); hasBottomFields |= SetPairedUDMFFieldsLabel(l.Front.Fields, "scalex_bottom", "scaley_bottom", 1.0f, frontBottomUDMFScaleLabel, frontBottomUDMFScale, highlight); //visibility frontTopUDMFOffset.Visible = hasTopFields; frontTopUDMFOffsetLabel.Visible = hasTopFields; frontTopUDMFScale.Visible = hasTopFields; frontTopUDMFScaleLabel.Visible = hasTopFields; frontMidUDMFOffset.Visible = hasMiddleFields; frontMidUDMFOffsetLabel.Visible = hasMiddleFields; frontMidUDMFScale.Visible = hasMiddleFields; frontMidUDMFScaleLabel.Visible = hasMiddleFields; frontBottomUDMFOffset.Visible = hasBottomFields; frontBottomUDMFOffsetLabel.Visible = hasBottomFields; frontBottomUDMFScale.Visible = hasBottomFields; frontBottomUDMFScaleLabel.Visible = hasBottomFields; } else { frontoffsetlabel.Text = "Front offset:"; if (l.Front.OffsetX != 0 || l.Front.OffsetY != 0) { frontoffset.Text = l.Front.OffsetX + ", " + l.Front.OffsetY; frontoffsetlabel.Enabled = true; frontoffset.Enabled = true; frontoffset.ForeColor = (highlight ? SystemColors.HotTrack : SystemColors.WindowText); frontoffsetlabel.ForeColor = frontoffset.ForeColor; } else { frontoffset.Text = "--, --"; frontoffsetlabel.Enabled = false; frontoffset.Enabled = false; } //mxd. Sector index frontpanel.Text += ". Sector " + l.Front.Sector.Index + " "; //visibility frontTopUDMFOffsetLabel.Visible = false; frontTopUDMFScaleLabel.Visible = false; frontMidUDMFOffsetLabel.Visible = false; frontMidUDMFScaleLabel.Visible = false; frontBottomUDMFOffsetLabel.Visible = false; frontBottomUDMFScaleLabel.Visible = false; } //mxd. Set texture names, update panel sizes UpdateTexturePanel(panelFrontTop, l.Front.HighTexture, fronthighname, labelTextureFrontTop, Math.Max(frontTopUDMFOffset.Right, frontTopUDMFScale.Right) + 4, fronthightex, frontTopUDMFOffsetLabel.Left, hasTopFields, l.Front.HighRequired()); UpdateTexturePanel(panelFrontMid, l.Front.MiddleTexture, frontmidname, labelTextureFrontMid, Math.Max(frontMidUDMFOffset.Right, frontMidUDMFScale.Right) + 4, frontmidtex, frontMidUDMFOffsetLabel.Left, hasMiddleFields, l.Front.MiddleRequired()); UpdateTexturePanel(panelFrontLow, l.Front.LowTexture, frontlowname, labelTextureFrontBottom, Math.Max(frontBottomUDMFOffset.Right, frontBottomUDMFScale.Right) + 4, frontlowtex, frontBottomUDMFOffsetLabel.Left, hasBottomFields, l.Front.LowRequired()); //mxd. Resize panel flowLayoutPanelFront.Width = panelFrontLow.Right; frontpanel.Width = flowLayoutPanelFront.Width + flowLayoutPanelFront.Left * 2 - 4; } else { // Show no info if (General.Map.UDMF) //mxd { frontoffsetlabel.Text = "Front light:"; frontoffset.Text = "--"; } else { frontoffsetlabel.Text = "Front offset:"; frontoffset.Text = "--, --"; } frontoffsetlabel.Enabled = false; frontoffset.Enabled = false; fronthightex.BackgroundImage = null; frontmidtex.BackgroundImage = null; frontlowtex.BackgroundImage = null; frontpanel.Visible = false; //mxd } // Back size available? if (l.Back != null) { //mxd. Extended info shown? bool hasTopFields = false; bool hasMiddleFields = false; bool hasBottomFields = false; //mxd. Highlight this side? bool highlight = l.Back == highlightside; backpanel.ForeColor = (highlight ? SystemColors.HotTrack : SystemColors.WindowText); //mxd // Show sidedef info backpanel.Visible = true; //mxd backpanel.Text = " Back Sidedef " + l.Back.Index; //mxd if (General.Map.UDMF) { //light backoffsetlabel.Text = "Back light:"; SetUDMFLight(l.Back, backoffsetlabel, backoffset, highlight); //global offset, sector index backpanel.Text += ". Offset " + l.Back.OffsetX + ", " + l.Back.OffsetY + ". Sector " + l.Back.Sector.Index + " "; //sidedef top hasTopFields = SetPairedUDMFFieldsLabel(l.Back.Fields, "offsetx_top", "offsety_top", 0f, backTopUDMFOffsetLabel, backTopUDMFOffset, highlight); hasTopFields |= SetPairedUDMFFieldsLabel(l.Back.Fields, "scalex_top", "scaley_top", 1.0f, backTopUDMFScaleLabel, backTopUDMFScale, highlight); //sidedef middle hasMiddleFields = SetPairedUDMFFieldsLabel(l.Back.Fields, "offsetx_mid", "offsety_mid", 0f, backMidUDMFOffsetLabel, backMidUDMFOffset, highlight); hasMiddleFields |= SetPairedUDMFFieldsLabel(l.Back.Fields, "scalex_mid", "scaley_mid", 1.0f, backMidUDMFScaleLabel, backMidUDMFScale, highlight); //sidedef bottom hasBottomFields = SetPairedUDMFFieldsLabel(l.Back.Fields, "offsetx_bottom", "offsety_bottom", 0f, backBottomUDMFOffsetLabel, backBottomUDMFOffset, highlight); hasBottomFields |= SetPairedUDMFFieldsLabel(l.Back.Fields, "scalex_bottom", "scaley_bottom", 1.0f, backBottomUDMFScaleLabel, backBottomUDMFScale, highlight); //visibility backTopUDMFOffset.Visible = hasTopFields; backTopUDMFOffsetLabel.Visible = hasTopFields; backTopUDMFScale.Visible = hasTopFields; backTopUDMFScaleLabel.Visible = hasTopFields; backMidUDMFOffset.Visible = hasMiddleFields; backMidUDMFOffsetLabel.Visible = hasMiddleFields; backMidUDMFScale.Visible = hasMiddleFields; backMidUDMFScaleLabel.Visible = hasMiddleFields; backBottomUDMFOffset.Visible = hasBottomFields; backBottomUDMFOffsetLabel.Visible = hasBottomFields; backBottomUDMFScale.Visible = hasBottomFields; backBottomUDMFScaleLabel.Visible = hasBottomFields; } else { backoffsetlabel.Text = "Back offset:"; if (l.Back.OffsetX != 0 || l.Back.OffsetY != 0) { backoffset.Text = l.Back.OffsetX + ", " + l.Back.OffsetY; backoffsetlabel.Enabled = true; backoffset.Enabled = true; backoffset.ForeColor = (highlight ? SystemColors.HotTrack : SystemColors.WindowText); backoffsetlabel.ForeColor = backoffset.ForeColor; } else { backoffset.Text = "--, --"; backoffsetlabel.Enabled = false; backoffset.Enabled = false; } // Sector index backpanel.Text += ". Sector " + l.Back.Sector.Index + " "; } //mxd. Set texture names, update panel sizes UpdateTexturePanel(panelBackTop, l.Back.HighTexture, backhighname, labelTextureBackTop, Math.Max(backTopUDMFOffset.Right, backTopUDMFScale.Right) + 4, backhightex, backTopUDMFOffsetLabel.Left, hasTopFields, l.Back.HighRequired()); UpdateTexturePanel(panelBackMid, l.Back.MiddleTexture, backmidname, labelTextureBackMid, Math.Max(backMidUDMFOffset.Right, backMidUDMFScale.Right) + 4, backmidtex, backMidUDMFOffsetLabel.Left, hasMiddleFields, l.Back.MiddleRequired()); UpdateTexturePanel(panelBackLow, l.Back.LowTexture, backlowname, labelTextureBackBottom, Math.Max(backBottomUDMFOffset.Right, backBottomUDMFScale.Right) + 4, backlowtex, backBottomUDMFOffsetLabel.Left, hasBottomFields, l.Back.LowRequired()); //mxd. Resize panel flowLayoutPanelBack.Width = panelBackLow.Right; backpanel.Width = flowLayoutPanelBack.Width + flowLayoutPanelBack.Left * 2 - 4; } else { // Show no info if (General.Map.UDMF) //mxd { backoffsetlabel.Text = "Back light:"; backoffset.Text = "--"; } else { backoffsetlabel.Text = "Back offset:"; backoffset.Text = "--, --"; } backoffsetlabel.Enabled = false; backoffset.Enabled = false; backhightex.BackgroundImage = null; backmidtex.BackgroundImage = null; backlowtex.BackgroundImage = null; backpanel.Visible = false; //mxd } //mxd. Flags and activations flags.Items.Clear(); // Add activations foreach (LinedefActivateInfo ai in General.Map.Config.LinedefActivates) { if (l.Flags.ContainsKey(ai.Key) && l.Flags[ai.Key]) { flags.Items.Add(new ListViewItem(ai.Title) { Checked = true, ForeColor = SystemColors.HotTrack }); } } // And flags foreach (KeyValuePair <string, string> group in General.Map.Config.LinedefFlags) { if (l.Flags.ContainsKey(group.Key) && l.Flags[group.Key]) { flags.Items.Add(new ListViewItem(group.Value) { Checked = true }); } } // And front flags if (l.Front != null) { foreach (KeyValuePair <string, string> group in General.Map.Config.SidedefFlags) { if (l.Front.Flags.ContainsKey(group.Key) && l.Front.Flags[group.Key]) { flags.Items.Add(new ListViewItem("Front: " + group.Value) { Checked = true }); } } } // And back flags if (l.Back != null) { foreach (KeyValuePair <string, string> group in General.Map.Config.SidedefFlags) { if (l.Back.Flags.ContainsKey(group.Key) && l.Back.Flags[group.Key]) { flags.Items.Add(new ListViewItem("Back: " + group.Value) { Checked = true }); } } } //mxd. Flags panel visibility and size flagsPanel.Visible = (flags.Items.Count > 0); if (flags.Items.Count > 0) { Rectangle rect = flags.GetItemRect(0); int itemspercolumn = 1; // Check how many items per column we have... for (int i = 1; i < flags.Items.Count; i++) { if (flags.GetItemRect(i).X != rect.X) { break; } itemspercolumn++; } flags.Width = rect.Width * (int)Math.Ceiling(flags.Items.Count / (float)itemspercolumn); flagsPanel.Width = flags.Width + flags.Left * 2; } // Show the whole thing this.Show(); this.Update(); }
// ano - based on CodeImp's SectorsMode.JoinMergeSectors public static LuaSector MergeSectors(Table table) { if (table == null || table.Length <= 0) { // ano - should we error or warn here? return null; } HashSet<Sector> sectors = UniqueSectorsFromTable(table); // ano - bit of a hacky mess to retrieve only element of 1-sized hashset if (sectors.Count == 1) { foreach (Sector s in sectors) { if (s.IsDisposed) { return null; } return new LuaSector(s); } } // ano - for merge we need to remove linedefs // let's get count instances of the unique lines from the sectors Dictionary<Linedef, int> linedefs = new Dictionary<Linedef, int>(); foreach (Sector s in sectors) { if (s.IsDisposed) { continue; } foreach (Sidedef side in s.Sidedefs) { Linedef line = side.Line; if (linedefs.ContainsKey(line)) { linedefs[line]++; } else if ( line.Front != null && line.Back != null && line.Front.Sector != line.Back.Sector) { linedefs.Add(line, 1); } } } foreach (KeyValuePair<Linedef, int> pair in linedefs) { if (pair.Value > 1) { pair.Key.Dispose(); } } return JoinUniqueSectors(sectors); }
// ano - negative stitchrange defaults to builderplug.me.stitchrange which comes from config file // most of this is codeimps code public DrawnVertex GetVertexAt( Vector2D mappos, bool snaptonearest, bool snaptogrid, float stitchrange, bool scaletorenderer, List <DrawnVertex> points = null) { DrawnVertex p = new DrawnVertex(); Vector2D vm = mappos; float vrange = stitchrange; if (scaletorenderer) { vrange = stitchrange / renderer.Scale; } //float vrange = stitchrange; // Snap to nearest? if (snaptonearest) { if (points != null) { // Go for all drawn points foreach (DrawnVertex v in points) { if (Vector2D.DistanceSq(mappos, v.pos) < (vrange * vrange)) { p.pos = v.pos; p.stitch = true; p.stitchline = true; //Logger.WriteLogLine("a");//debugcrap return(p); } } } // Try the nearest vertex Vertex nv = General.Map.Map.NearestVertexSquareRange(mappos, vrange); if (nv != null) { p.pos = nv.Position; p.stitch = true; p.stitchline = true; //Logger.WriteLogLine("b");//debugcrap return(p); } // Try the nearest linedef Linedef nl = General.Map.Map.NearestLinedefRange(mappos, 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 = mappos - v; if (delta.GetLengthSq() < found_distance) { found_distance = delta.GetLengthSq(); found_coord = v; found = true; } } if (found) { // Align to the closest grid intersection p.pos = found_coord; p.stitch = true; p.stitchline = true; //Logger.WriteLogLine("c");//debugcrap return(p); } } else { // Aligned to line p.pos = nl.NearestOnLine(mappos); p.stitch = true; p.stitchline = true; //Logger.WriteLogLine("d");//debugcrap return(p); } } } else { // Always snap to the first drawn vertex so that the user can finish a complete sector without stitching if (points != null && points.Count > 0) { if (Vector2D.DistanceSq(mappos, points[0].pos) < (vrange * vrange)) { p.pos = points[0].pos; p.stitch = true; p.stitchline = false; //Logger.WriteLogLine("e");//debugcrap return(p); } } } // if the mouse cursor is outside the map bondaries check if the line between the last set point and the // mouse cursor intersect any of the boundary lines. If it does, set the position to this intersection if (points != null && points.Count > 0 && (mappos.x < General.Map.Config.LeftBoundary || mappos.x > General.Map.Config.RightBoundary || mappos.y > General.Map.Config.TopBoundary || mappos.y < General.Map.Config.BottomBoundary)) { Line2D dline = new Line2D(mappos, points[points.Count - 1].pos); bool foundintersection = false; float u = 0.0f; List <Line2D> blines = new List <Line2D>(); // lines for left, top, right and bottom bondaries blines.Add(new Line2D(General.Map.Config.LeftBoundary, General.Map.Config.BottomBoundary, General.Map.Config.LeftBoundary, General.Map.Config.TopBoundary)); blines.Add(new Line2D(General.Map.Config.LeftBoundary, General.Map.Config.TopBoundary, General.Map.Config.RightBoundary, General.Map.Config.TopBoundary)); blines.Add(new Line2D(General.Map.Config.RightBoundary, General.Map.Config.TopBoundary, General.Map.Config.RightBoundary, General.Map.Config.BottomBoundary)); blines.Add(new Line2D(General.Map.Config.RightBoundary, General.Map.Config.BottomBoundary, General.Map.Config.LeftBoundary, General.Map.Config.BottomBoundary)); // check for intersections with boundaries for (int i = 0; i < blines.Count; i++) { if (!foundintersection) { // only check for intersection if the last set point is not on the // line we are checking against if (blines[i].GetSideOfLine(points[points.Count - 1].pos) != 0.0f) { foundintersection = blines[i].GetIntersection(dline, out u); } } } // if there was no intersection set the position to the last set point if (!foundintersection) { vm = points[points.Count - 1].pos; } else { vm = dline.GetCoordinatesAt(u); } } // Snap to grid? if (snaptogrid) { // Aligned to grid p.pos = General.Map.Grid.SnappedToGrid(vm); // special handling if (p.pos.x > General.Map.Config.RightBoundary) { p.pos.x = General.Map.Config.RightBoundary; } if (p.pos.y < General.Map.Config.BottomBoundary) { p.pos.y = General.Map.Config.BottomBoundary; } p.stitch = snaptonearest; p.stitchline = snaptonearest; //Logger.WriteLogLine("f");//debugcrap return(p); } else { // Normal position p.pos = vm; p.stitch = snaptonearest; p.stitchline = snaptonearest; //Logger.WriteLogLine("g");//debugcrap return(p); } } // getcurrentposition
// This moves the selected geometry relatively // Returns true when geometry has actually moved private bool MoveGeometryRelative(Vector2D offset, bool snapgrid, bool snapgridincrement, bool snapnearest, bool snapcardinal) { //mxd. If snap to cardinal directions is enabled, modify the offset if (snapcardinal) { float angle = Angle2D.DegToRad((General.ClampAngle((int)Angle2D.RadToDeg(offset.GetAngle()) + 44)) / 90 * 90); offset = new Vector2D(0, -offset.GetLength()).GetRotated(angle); snapgridincrement = true; // We don't want to move the geometry away from the cardinal directions } Vector2D oldpos = dragitem.Position; Vector2D anchorpos = dragitemposition + offset; Vector2D tl, br; // don't move if the offset contains invalid data if (!offset.IsFinite()) { return(false); } // Find the outmost vertices tl = br = oldpositions[0]; for (int i = 0; i < oldpositions.Count; i++) { if (oldpositions[i].x < tl.x) { tl.x = (int)oldpositions[i].x; } if (oldpositions[i].x > br.x) { br.x = (int)oldpositions[i].x; } if (oldpositions[i].y > tl.y) { tl.y = (int)oldpositions[i].y; } if (oldpositions[i].y < br.y) { br.y = (int)oldpositions[i].y; } } // Snap to nearest? if (snapnearest) { // Find nearest unselected vertex within range Vertex nv = MapSet.NearestVertexSquareRange(unselectedverts, anchorpos, BuilderPlug.Me.StitchRange / renderer.Scale); if (nv != null) { // Move the dragged item dragitem.Move(nv.Position); // Adjust the offset offset = nv.Position - dragitemposition; // Do not snap to grid! snapgrid = false; snaptogridincrement = false; //mxd } else { // Find the nearest unselected line within range Linedef nl = MapSet.NearestLinedefRange(snaptolines, anchorpos, BuilderPlug.Me.StitchRange / renderer.Scale); if (nl != null) { // Snap to grid? if (snapgrid || snapgridincrement) { // Get grid intersection coordinates List <Vector2D> coords = nl.GetGridIntersections(snapgridincrement ? dragstartoffset : new Vector2D()); // mxd. Do the rest only if we actually have some coordinates if (coords.Count > 0) { // Find nearest grid intersection float found_distance = float.MaxValue; Vector2D found_coord = new Vector2D(); foreach (Vector2D v in coords) { Vector2D delta = anchorpos - v; if (delta.GetLengthSq() < found_distance) { found_distance = delta.GetLengthSq(); found_coord = v; } } // Move the dragged item dragitem.Move(found_coord); // Align to line here offset = found_coord - dragitemposition; // Do not snap to grid anymore snapgrid = false; snapgridincrement = false; //mxd } } else { // Move the dragged item dragitem.Move(nl.NearestOnLine(anchorpos)); // Align to line here offset = nl.NearestOnLine(anchorpos) - dragitemposition; } } } } // Snap to grid or grid increment? if (snapgrid || snapgridincrement) { // Move the dragged item dragitem.Move(anchorpos); // Snap item to grid increment if (snapgridincrement) //mxd { dragitem.Move(General.Map.Grid.SnappedToGrid(dragitem.Position) - dragstartoffset); } else // Or to the grid itself { dragitem.SnapToGrid(); } // Adjust the offset offset += dragitem.Position - anchorpos; } // Make sure the offset is inside the map boundaries if (offset.x + tl.x < General.Map.Config.LeftBoundary) { offset.x = General.Map.Config.LeftBoundary - tl.x; } if (offset.x + br.x > General.Map.Config.RightBoundary) { offset.x = General.Map.Config.RightBoundary - br.x; } if (offset.y + tl.y > General.Map.Config.TopBoundary) { offset.y = General.Map.Config.TopBoundary - tl.y; } if (offset.y + br.y < General.Map.Config.BottomBoundary) { offset.y = General.Map.Config.BottomBoundary - br.y; } // Drag item moved? if ((!snapgrid && !snapgridincrement) || (dragitem.Position != oldpos)) { int i = 0; // Move selected geometry foreach (Vertex v in selectedverts) { // Move vertex from old position relative to the mouse position change since drag start v.Move(oldpositions[i++] + offset); } //mxd. Move selected things i = 0; foreach (Thing t in thingstodrag) { t.Move(oldthingpositions[i++] + offset); } // Update labels int index = 0; foreach (Linedef l in unstablelines) { labels[index++].Move(l.Start.Position, l.End.Position); } // Moved return(true); } // No changes return(false); }
public void DeleteItem() { // Make list of selected vertices ICollection <Vertex> selected = General.Map.Map.GetSelectedVertices(true); if ((selected.Count == 0) && (highlighted != null) && !highlighted.IsDisposed) { selected.Add(highlighted); } // Anything to do? if (selected.Count > 0) { // Make undo if (selected.Count > 1) { General.Map.UndoRedo.CreateUndo("Delete " + selected.Count + " vertices"); General.Interface.DisplayStatus(StatusType.Action, "Deleted " + selected.Count + " vertices."); } else { General.Map.UndoRedo.CreateUndo("Delete vertex"); General.Interface.DisplayStatus(StatusType.Action, "Deleted a vertex."); } // Go for all vertices that need to be removed foreach (Vertex v in selected) { // Not already removed automatically? if (!v.IsDisposed) { // If the vertex only has 2 linedefs attached, then merge the linedefs if (v.Linedefs.Count == 2) { Linedef ld1 = General.GetByIndex(v.Linedefs, 0); Linedef ld2 = General.GetByIndex(v.Linedefs, 1); //Vertex v1 = (ld1.Start == v) ? ld1.End : ld1.Start; Vertex v2 = (ld2.Start == v) ? ld2.End : ld2.Start; if (ld1.Start == v) { ld1.SetStartVertex(v2); } else { ld1.SetEndVertex(v2); } //if(ld2.Start == v) ld2.SetStartVertex(v1); else ld2.SetEndVertex(v1); //ld1.Join(ld2); ld2.Dispose(); } // Trash vertex v.Dispose(); } } // Update cache values General.Map.IsChanged = true; General.Map.Map.Update(); // Invoke a new mousemove so that the highlighted item updates MouseEventArgs e = new MouseEventArgs(MouseButtons.None, 0, (int)mousepos.x, (int)mousepos.y, 0); OnMouseMove(e); // Redraw screen General.Interface.RedrawDisplay(); } }
// Mode is engaged public override void OnEngage() { base.OnEngage(); // Update projection (mxd) General.Map.CRenderer3D.CreateProjection(); // Update the used textures General.Map.Data.UpdateUsedTextures(); // Fill the blockmap FillBlockMap(); //mxd. Synch camera position to cursor position or center of the screen in 2d-mode if (General.Settings.GZSynchCameras) { // Keep previous camera position if Control is held and camera was previously moved in Visual mode if (!General.Interface.CtrlState || General.Map.VisualCamera.Position.GetLengthSq() == 0) { //If initial position is inside or nearby a sector - adjust camera.z accordingly float posz = General.Map.VisualCamera.Position.z; Sector nearestsector = General.Map.Map.GetSectorByCoordinates(initialcameraposition, blockmap); if (nearestsector == null) { Linedef nearestline = MapSet.NearestLinedef(General.Map.Map.Linedefs, initialcameraposition); if (nearestline != null) { float side = nearestline.SideOfLine(initialcameraposition); Sidedef nearestside = (side < 0.0f ? nearestline.Front : nearestline.Back) ?? (side < 0.0f ? nearestline.Back : nearestline.Front); if (nearestside != null) { nearestsector = nearestside.Sector; } } } if (nearestsector != null) { int sectorheight = nearestsector.CeilHeight - nearestsector.FloorHeight; if (sectorheight < 41) { posz = nearestsector.FloorHeight + Math.Max(16, sectorheight / 2); } else if (General.Map.VisualCamera.Position.z < nearestsector.FloorHeight + 41) { posz = nearestsector.FloorHeight + 41; // same as in doom } else if (General.Map.VisualCamera.Position.z > nearestsector.CeilHeight) { posz = nearestsector.CeilHeight - 4; } } General.Map.VisualCamera.Position = new Vector3D(initialcameraposition.x, initialcameraposition.y, posz); } } else { General.Map.VisualCamera.PositionAtThing(); } // Start special input mode General.Interface.EnableProcessing(); General.Interface.StartExclusiveMouseInput(); }
// Mode starts public override void OnEngage() { Cursor.Current = Cursors.WaitCursor; base.OnEngage(); General.Interface.DisplayStatus(StatusType.Busy, "Setting up test environment..."); CleanUp(); BuilderPlug.InterfaceForm.AddToInterface(); lastviewstats = BuilderPlug.InterfaceForm.ViewStats; // Export the current map to a temporary WAD file tempfile = BuilderPlug.MakeTempFilename(".wad"); General.Map.ExportToFile(tempfile); // Load the map in VPO_DLL BuilderPlug.VPO.Start(tempfile, General.Map.Options.LevelName); // Determine map boundary mapbounds = Rectangle.Round(MapSet.CreateArea(General.Map.Map.Vertices)); // Create tiles for all points inside the map Point lt = TileForPoint(mapbounds.Left - Tile.TILE_SIZE, mapbounds.Top - Tile.TILE_SIZE); Point rb = TileForPoint(mapbounds.Right + Tile.TILE_SIZE, mapbounds.Bottom + Tile.TILE_SIZE); Rectangle tilesrect = new Rectangle(lt.X, lt.Y, rb.X - lt.X, rb.Y - lt.Y); NearestLineBlockmap blockmap = new NearestLineBlockmap(tilesrect); for (int x = tilesrect.X; x <= tilesrect.Right; x += Tile.TILE_SIZE) { for (int y = tilesrect.Y; y <= tilesrect.Bottom; y += Tile.TILE_SIZE) { // If the tile is obviously outside the map, don't create it Vector2D pc = new Vector2D(x + (Tile.TILE_SIZE >> 1), y + (Tile.TILE_SIZE >> 1)); Linedef ld = MapSet.NearestLinedef(blockmap.GetBlockAt(pc).Lines, pc); float distancesq = ld.DistanceToSq(pc, true); if (distancesq > (Tile.TILE_SIZE * Tile.TILE_SIZE)) { float side = ld.SideOfLine(pc); if ((side > 0.0f) && (ld.Back == null)) { continue; } } Point tp = new Point(x, y); tiles.Add(tp, new Tile(tp)); } } QueuePoints(0); // Make an image to draw on. // The BitmapImage for Doom Builder's resources must be Format32bppArgb and NOT using color correction, // otherwise DB will make a copy of the bitmap when LoadImage() is called! This is normally not a problem, // but we want to keep drawing to the same bitmap. int width = General.NextPowerOf2(General.Interface.Display.ClientSize.Width); int height = General.NextPowerOf2(General.Interface.Display.ClientSize.Height); canvas = new Bitmap(width, height, PixelFormat.Format32bppArgb); image = new DynamicBitmapImage(canvas, "_CANVAS_"); image.UseColorCorrection = false; image.MipMapLevels = 1; image.LoadImage(); image.CreateTexture(); // Make custom presentation CustomPresentation p = new CustomPresentation(); p.AddLayer(new PresentLayer(RendererLayer.Overlay, BlendingMode.Mask, 1f, false)); p.AddLayer(new PresentLayer(RendererLayer.Grid, BlendingMode.Mask)); p.AddLayer(new PresentLayer(RendererLayer.Geometry, BlendingMode.Alpha, 1f, true)); renderer.SetPresentation(p); // Setup processing nextupdate = DateTime.Now + new TimeSpan(0, 0, 0, 0, 100); General.Interface.EnableProcessing(); processingenabled = true; RedrawAllTiles(); Cursor.Current = Cursors.Default; General.Interface.SetCursor(Cursors.Cross); General.Interface.DisplayReady(); }
// This preforms visibility culling protected void DoCulling() { lastProcessed++; List <Linedef> visiblelines = new List <Linedef>(); Vector2D campos2d = General.Map.VisualCamera.Position; // Make collections visiblesectors = new List <VisualSector>(visiblesectors.Count * 2); visiblegeometry = new List <VisualGeometry>(visiblegeometry.Count * 2); visiblethings = new List <VisualThing>(visiblethings.Count * 2); // Get the blocks within view range visibleblocks = blockmap.GetFrustumRange(renderer.Frustum2D); // Fill collections with geometry and things foreach (VisualBlockEntry block in visibleblocks) { if (processgeometry) { // Lines foreach (Linedef ld in block.Lines) { // Line not already processed? if (ld.LastProcessed != lastProcessed) { // Add line if not added yet ld.LastProcessed = lastProcessed; visiblelines.Add(ld); // Which side of the line is the camera on? if (ld.SideOfLine(campos2d) < 0) { // Do front of line if (ld.Front != null) { ProcessSidedefCulling(ld.Front); } } else { // Do back of line if (ld.Back != null) { ProcessSidedefCulling(ld.Back); } } } } } if (processthings) { // Things foreach (Thing t in block.Things) { if (t.LastProcessed == lastProcessed) { continue; } t.LastProcessed = lastProcessed; // Not filtered out? if (!General.Map.ThingsFilter.IsThingVisible(t)) { continue; } VisualThing vt; if (allthings.ContainsKey(t)) { vt = allthings[t]; } else { // Create new visual thing vt = CreateVisualThing(t); allthings[t] = vt; } if (vt != null) { visiblethings.Add(vt); } } } } if (processgeometry) { // Find camera sector Sector camsector = blockmap.GetSectorAt(campos2d); if (camsector != null) { General.Map.VisualCamera.Sector = camsector; } else { // To do: fix this code. It is retarded. Walking over all visible lines is extremely expensive. Linedef nld = MapSet.NearestLinedef(visiblelines, campos2d); if (nld != null) { General.Map.VisualCamera.Sector = GetCameraSectorFromLinedef(nld); } else { // Exceptional case: no lines found in any nearby blocks! // This could happen in the middle of an extremely large sector and in this case // the above code will not have found any sectors/sidedefs for rendering. // Here we handle this special case with brute-force. Let's find the sector // the camera is in by searching the entire map and render that sector only. nld = General.Map.Map.NearestLinedef(campos2d); if (nld != null) { General.Map.VisualCamera.Sector = GetCameraSectorFromLinedef(nld); if (General.Map.VisualCamera.Sector != null) { foreach (Sidedef sd in General.Map.VisualCamera.Sector.Sidedefs) { float side = sd.Line.SideOfLine(campos2d); if (((side < 0) && sd.IsFront) || ((side > 0) && !sd.IsFront)) { ProcessSidedefCulling(sd); } } } else { // Too far away from the map to see anything General.Map.VisualCamera.Sector = null; } } else { // Map is empty General.Map.VisualCamera.Sector = null; } } } } }
public NodeInfo(Linedef ld) { type = NodeInfoType.LINEDEF; linedef = ld; }
// Brightness level effect public void AddEffectBrightnessLevel(Linedef sourcelinedef) { EffectBrightnessLevel e = new EffectBrightnessLevel(this, sourcelinedef); alleffects.Add(e); }
// Fix by merging with surrounding geometry/removing public override bool Button1Click(bool batchMode) { if (!batchMode) { General.Map.UndoRedo.CreateUndo("Invalid sector correction"); } //collect the lines List <Linedef> lines = new List <Linedef>(); foreach (Sidedef side in sector.Sidedefs) { if (!lines.Contains(side.Line) && !side.Line.IsDisposed) { lines.Add(side.Line); } } //get rid of lines with zero length foreach (Linedef line in lines) { if (line.Length == 0) { line.Dispose(); } } if (lines.Count == 0) { sector.Dispose(); } else if (lines.Count < 3) //merge with surrounding geometry { bool merged = false; foreach (Sidedef side in sector.Sidedefs) { if (side.Other != null && side.Other.Sector != null && sector.Index != side.Other.Sector.Index) { sector.Join(side.Other.Sector); merged = true; break; } } if (!merged) { HashSet <Linedef> sectorlines = new HashSet <Linedef>(); foreach (Sidedef side in sector.Sidedefs) { sectorlines.Add(side.Line); } if (sectorlines.Count > 0) { List <LinedefSide> newlines = new List <LinedefSide>(sectorlines.Count); foreach (Linedef line in sectorlines) { if (line.Front != null) { newlines.Add(new LinedefSide(line, true)); } if (line.Back != null) { newlines.Add(new LinedefSide(line, false)); } } if (newlines.Count > 0) { // If invalid sector is inside another one, join them Vector2D center = new Vector2D(sector.BBox.X + sector.BBox.Width / 2, sector.BBox.Y + sector.BBox.Height / 2); Linedef otherline = General.Map.Map.NearestLinedef(center, sectorlines); Sidedef targetside = (otherline.Front ?? otherline.Back); if (targetside != null && ((otherline.Front != null && otherline.Front.Sector != null && otherline.Front.Sector.BBox.Contains(center.x, center.y)) || otherline.Back != null && otherline.Back.Sector != null && otherline.Back.Sector.BBox.Contains(center.x, center.y))) { Tools.JoinSector(newlines, targetside); merged = true; } } } //oh well, I don't know what else I can do here... if (!merged) { sector.Dispose(); } } } else //redraw the lines { foreach (Linedef line in lines) { if (line.IsDisposed) { continue; } DrawnVertex start = new DrawnVertex { pos = line.Start.Position, stitch = true, stitchline = true }; DrawnVertex end = new DrawnVertex { pos = line.End.Position, stitch = true, stitchline = true }; Tools.DrawLines(new List <DrawnVertex> { start, end }, false, false); } } General.Map.Map.Update(); return(true); }
//mxd. Transfer Floor Brightness effect public void AddEffectTransferCeilingBrightness(Linedef sourcelinedef) { EffectTransferCeilingBrightness e = new EffectTransferCeilingBrightness(this, sourcelinedef); alleffects.Add(e); }
// Mouse moves public override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); // Not holding any buttons? if (e.Button == MouseButtons.None) { General.Interface.SetCursor(Cursors.Default); //mxd. Find the nearest linedef within default highlight range Linedef nl = General.Map.Map.NearestLinedefRange(mousemappos, 20 / renderer.Scale); //mxd. We are not interested in single-sided lines (unless they have "blocksound" flag set)... if (nl != null && (nl.Front == null || nl.Back == null) && !nl.IsFlagSet(BlockSoundFlag)) { nl = null; } //mxd. Set as highlighted bool redrawrequired = (highlightedline != nl); highlightedline = nl; // 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 != highlighted) { Highlight(l.Back.Sector); redrawrequired = true; //mxd } } else if (highlighted != null) { // Highlight nothing Highlight(null); redrawrequired = true; //mxd } } else { // Is there a sidedef here? if (l.Front != null) { // Highlight if not the same if (l.Front.Sector != highlighted) { Highlight(l.Front.Sector); redrawrequired = true; //mxd } } else if (highlighted != null) { // Highlight nothing Highlight(null); redrawrequired = true; //mxd } } } else if (highlighted != null) { // Highlight nothing Highlight(null); redrawrequired = true; //mxd } //mxd if (redrawrequired) { // Show highlight info if (highlightedline != null && !highlightedline.IsDisposed) { General.Interface.ShowLinedefInfo(highlightedline); } else if (highlighted != null && !highlighted.IsDisposed) { General.Interface.ShowSectorInfo(highlighted); } else { General.Interface.HideInfo(); } // Redraw display General.Interface.RedrawDisplay(); } } }
// Line slope effect public void AddEffectLineSlope(Linedef sourcelinedef) { EffectLineSlope e = new EffectLineSlope(this, sourcelinedef); alleffects.Add(e); }
public LuaLinedef(Linedef l) { linedef = l; }
//mxd. Plane copy slope effect public void AddEffectPlaneClopySlope(Linedef sourcelinedef, bool front) { EffectPlaneCopySlope e = new EffectPlaneCopySlope(this, sourcelinedef, front); alleffects.Add(e); }
// This reads the linedefs and sidedefs private static void ReadLinedefs(MapSet map, BinaryReader reader, Dictionary <int, Vertex> vertexlink, Dictionary <int, Sector> sectorlink, Dictionary <int, SidedefData> sidedeflink) { int count = reader.ReadInt32(); // Go for all lines map.SetCapacity(0, map.Linedefs.Count + count, map.Sidedefs.Count + sidedeflink.Count, 0, 0); for (int i = 0; i < count; i++) { int[] args = new int[Linedef.NUM_ARGS]; int v1 = reader.ReadInt32(); int v2 = reader.ReadInt32(); int s1 = reader.ReadInt32(); int s2 = reader.ReadInt32(); int special = reader.ReadInt32(); for (int a = 0; a < Linedef.NUM_ARGS; a++) { args[a] = reader.ReadInt32(); } int numtags = reader.ReadInt32(); //mxd List <int> tags = new List <int>(numtags); //mxd for (int a = 0; a < numtags; a++) { tags.Add(reader.ReadInt32()); //mxd } //flags Dictionary <string, bool> stringflags = new Dictionary <string, bool>(StringComparer.Ordinal); int numFlags = reader.ReadInt32(); for (int f = 0; f < numFlags; f++) { stringflags.Add(ReadString(reader), reader.ReadBoolean()); } //add missing flags foreach (KeyValuePair <string, string> flag in General.Map.Config.LinedefFlags) { if (stringflags.ContainsKey(flag.Key)) { continue; } stringflags.Add(flag.Key, false); } //add missing activations foreach (LinedefActivateInfo activate in General.Map.Config.LinedefActivates) { if (stringflags.ContainsKey(activate.Key)) { continue; } stringflags.Add(activate.Key, false); } // Read custom fields Dictionary <string, UniValue> fields = ReadCustomFields(reader); // Check if not zero-length if (Vector2D.ManhattanDistance(vertexlink[v1].Position, vertexlink[v2].Position) > 0.0001f) { // Create new linedef Linedef l = map.CreateLinedef(vertexlink[v1], vertexlink[v2]); if (l != null) { l.Update(stringflags, 0, tags, special, args); l.UpdateCache(); // Add custom fields l.Fields.BeforeFieldsChange(); foreach (KeyValuePair <string, UniValue> group in fields) { l.Fields.Add(group.Key, group.Value); } // Connect sidedefs to the line if (s1 > -1) { if (s1 < sidedeflink.Count) { AddSidedef(map, sidedeflink[s1], l, true, sectorlink); } else { General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " references invalid front sidedef " + s1 + ". Sidedef has been removed."); } } if (s2 > -1) { if (s2 < sidedeflink.Count) { AddSidedef(map, sidedeflink[s2], l, false, sectorlink); } else { General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " references invalid back sidedef " + s1 + ". Sidedef has been removed."); } } } } else { General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " is zero-length. Linedef has been removed."); } } }
// Start editing protected override void OnEditBegin() { bool snaptogrid = General.Interface.ShiftState ^ General.Interface.SnapToGrid; bool snaptonearest = General.Interface.CtrlState ^ General.Interface.AutoMerge; // Vertex highlighted? if ((highlighted != null) && !highlighted.IsDisposed) { // Edit pressed in this mode editpressed = true; // Highlighted item not selected? if (!highlighted.Selected && (BuilderPlug.Me.AutoClearSelection || (General.Map.Map.SelectedVerticesCount == 0))) { // Make this the only selection General.Map.Map.ClearSelectedVertices(); highlighted.Selected = true; General.Interface.RedrawDisplay(); } // Update display if (renderer.StartPlotter(false)) { // Redraw highlight to show selection renderer.PlotVertex(highlighted, renderer.DetermineVertexColor(highlighted)); renderer.Finish(); renderer.Present(); } } else { // Find the nearest linedef within highlight range Linedef l = General.Map.Map.NearestLinedefRange(mousemappos, BuilderPlug.Me.SplitLinedefsRange / renderer.Scale); if (l != null) { // Create undo General.Map.UndoRedo.CreateUndo("Split line"); Vector2D insertpos; // Snip to grid also? if (snaptogrid) { // Find all points where the grid intersects the line List <Vector2D> points = l.GetGridIntersections(); insertpos = mousemappos; float distance = float.MaxValue; foreach (Vector2D p in points) { float pdist = Vector2D.DistanceSq(p, mousemappos); if (pdist < distance) { insertpos = p; distance = pdist; } } } else { // Just use the nearest point on line insertpos = l.NearestOnLine(mousemappos); } // Make the vertex Vertex v = General.Map.Map.CreateVertex(insertpos); if (v == null) { General.Map.UndoRedo.WithdrawUndo(); return; } // Snap to map format accuracy //v.SnapToAccuracy(); // Split the line with this vertex Linedef sld = l.Split(v); if (sld == null) { General.Map.UndoRedo.WithdrawUndo(); return; } BuilderPlug.Me.AdjustSplitCoordinates(l, sld); // Update General.Map.Map.Update(); // Highlight it Highlight(v); // Redraw display General.Interface.RedrawDisplay(); } else { // Start drawing mode DrawLinesMode drawmode = new DrawLinesMode(); DrawnVertex v = DrawLinesMode.GetCurrentPosition(mousemappos, snaptonearest, snaptogrid, renderer, new List <DrawnVertex>()); if (drawmode.DrawPointAt(v)) { General.Editing.ChangeMode(drawmode); } else { General.Interface.DisplayStatus(StatusType.Warning, "Failed to draw point: outside of map boundaries."); } } } base.OnEditBegin(); }
// This highlights a new region private void Highlight(bool buttonspressed) { // Mouse inside? if (mouseinside) { // Highlighting from a new sidedef? Linedef nl = General.Map.Map.NearestLinedef(mousemappos); if (nl != null) { float side = nl.SideOfLine(mousemappos); LinedefSide newnearest = new LinedefSide(nl, (side <= 0.0f)); if (newnearest != nearestside) { // Only change when buttons are not pressed if (!buttonspressed || (editside == newnearest)) { // Find new sector General.Interface.SetCursor(Cursors.AppStarting); nearestside = newnearest; allsides = Tools.FindPotentialSectorAt(mousemappos); if (allsides != null) { alllines = new List <Linedef>(allsides.Count); foreach (LinedefSide sd in allsides) { alllines.Add(sd.Line); } } else { alllines = null; } General.Interface.SetCursor(Cursors.Default); } else { // Don't highlight this one nearestside = null; allsides = null; alllines = null; } // Redraw overlay DrawGeometry(); DrawOverlay(); //mxd renderer.Present(); } } } else { // No valid region nearestside = null; allsides = null; alllines = null; // Redraw overlay DrawGeometry(); renderer.Present(); } }
public static void InsertVertex(Vector2D mousemappos, float rendererscale) { bool snaptogrid = General.Interface.ShiftState ^ General.Interface.SnapToGrid; bool snaptonearest = General.Interface.CtrlState ^ General.Interface.AutoMerge; // Mouse in window? if (General.Interface.MouseInDisplay) { Vector2D insertpos; // Create undo General.Map.UndoRedo.CreateUndo("Insert vertex"); // Snap to geometry? Linedef l = General.Map.Map.NearestLinedefRange(mousemappos, BuilderPlug.Me.SplitLinedefsRange / rendererscale); if (snaptonearest && (l != null)) { // Snip to grid also? if (snaptogrid) { // Find all points where the grid intersects the line List <Vector2D> points = l.GetGridIntersections(); insertpos = mousemappos; float distance = float.MaxValue; foreach (Vector2D p in points) { float pdist = Vector2D.DistanceSq(p, mousemappos); if (pdist < distance) { insertpos = p; distance = pdist; } } } else { // Just use the nearest point on line insertpos = l.NearestOnLine(mousemappos); } } // Snap to grid? else if (snaptogrid) { // Snap to grid insertpos = General.Map.Grid.SnappedToGrid(mousemappos); } else { // Just insert here, don't snap to anything insertpos = mousemappos; } // Make the vertex Vertex v = General.Map.Map.CreateVertex(insertpos); if (v == null) { General.Map.UndoRedo.WithdrawUndo(); return; } // Snap to map format accuracy //v.SnapToAccuracy(); // Split the line with this vertex if (snaptonearest && (l != null)) { General.Interface.DisplayStatus(StatusType.Action, "Split a line."); Linedef sld = l.Split(v); if (sld == null) { General.Map.UndoRedo.WithdrawUndo(); return; } BuilderPlug.Me.AdjustSplitCoordinates(l, sld); } else { General.Interface.DisplayStatus(StatusType.Action, "Inserted a vertex."); } // Update General.Map.Map.Update(); // Redraw screen General.Interface.RedrawDisplay(); } }
// This reads the linedefs and sidedefs private void ReadLinedefs(MapSet map, UniversalParser textmap, Dictionary <int, Vertex> vertexlink, Dictionary <int, Sector> sectorlink) { // Get list of entries List <UniversalCollection> linescolls = GetNamedCollections(textmap.Root, "linedef"); List <UniversalCollection> sidescolls = GetNamedCollections(textmap.Root, "sidedef"); // Go for all lines map.SetCapacity(0, map.Linedefs.Count + linescolls.Count, map.Sidedefs.Count + sidescolls.Count, 0, 0); char[] splitter = { ' ' }; //mxd for (int i = 0; i < linescolls.Count; i++) { // Read fields UniversalCollection lc = linescolls[i]; int[] args = new int[Linedef.NUM_ARGS]; string where = "linedef " + i; int v1 = GetCollectionEntry(lc, "v1", true, 0, where); int v2 = GetCollectionEntry(lc, "v2", true, 0, where); if (!vertexlink.ContainsKey(v1) || !vertexlink.ContainsKey(v2)) { //mxd General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " references one or more invalid vertices. Linedef has been removed."); continue; } int tag = GetCollectionEntry(lc, "id", false, 0, where); int special = GetCollectionEntry(lc, "special", false, 0, where); args[0] = GetCollectionEntry(lc, "arg0", false, 0, where); args[1] = GetCollectionEntry(lc, "arg1", false, 0, where); args[2] = GetCollectionEntry(lc, "arg2", false, 0, where); args[3] = GetCollectionEntry(lc, "arg3", false, 0, where); args[4] = GetCollectionEntry(lc, "arg4", false, 0, where); int s1 = GetCollectionEntry(lc, "sidefront", false, -1, where); int s2 = GetCollectionEntry(lc, "sideback", false, -1, where); //mxd. MoreIDs List <int> tags = new List <int> { tag }; string moreids = GetCollectionEntry(lc, "moreids", false, string.Empty, where); if (!string.IsNullOrEmpty(moreids)) { string[] moreidscol = moreids.Split(splitter, StringSplitOptions.RemoveEmptyEntries); foreach (string sid in moreidscol) { int id; if (int.TryParse(sid.Trim(), out id) && id != 0 && !tags.Contains(id)) { tags.Add(id); } } } if (tag == 0 && tags.Count > 1) { tags.RemoveAt(0); } // Flags Dictionary <string, bool> stringflags = new Dictionary <string, bool>(StringComparer.Ordinal); foreach (KeyValuePair <string, string> flag in General.Map.Config.LinedefFlags) { stringflags[flag.Key] = GetCollectionEntry(lc, flag.Key, false, false, where); } foreach (FlagTranslation ft in General.Map.Config.LinedefFlagsTranslation) { foreach (string field in ft.Fields) { stringflags[field] = GetCollectionEntry(lc, field, false, false, where); } } // Activations foreach (LinedefActivateInfo activate in General.Map.Config.LinedefActivates) { stringflags[activate.Key] = GetCollectionEntry(lc, activate.Key, false, false, where); } // Check if not zero-length if (Vector2D.ManhattanDistance(vertexlink[v1].Position, vertexlink[v2].Position) > 0.0001f) { // Create new linedef Linedef l = map.CreateLinedef(vertexlink[v1], vertexlink[v2]); if (l != null) { l.Update(stringflags, 0, tags, special, args); l.UpdateCache(); // Custom fields ReadCustomFields(lc, l, "linedef"); // Read sidedefs and connect them to the line if (s1 > -1) { if (s1 < sidescolls.Count) { ReadSidedef(map, sidescolls[s1], l, true, sectorlink, s1); } else { General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " references invalid front sidedef " + s1 + ". Sidedef has been removed."); } } if (s2 > -1) { if (s2 < sidescolls.Count) { ReadSidedef(map, sidescolls[s2], l, false, sectorlink, s2); } else { General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " references invalid back sidedef " + s1 + ". Sidedef has been removed."); } } } } else { General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " is zero-length. Linedef has been removed."); } } }
// Remember info for floor and ceiling height. The info is retrieved // from either front or back of the source line, depending in what // direction the it should build // Also set the upper/lower textures to use if they aren't already private void GetSetTextureAndHeightInfo(Linedef ld, out StairInfo siout) { StairInfo si = new StairInfo(); Sidedef primary; Sidedef secondary; GetSetBaseHeights(ld); if (stairsectorbuilderform.SideFront) { if (ld.Front == null) { primary = ld.Back; secondary = ld.Front; } else { primary = ld.Front; secondary = ld.Back; } } else { if (ld.Back == null) { primary = ld.Front; secondary = ld.Back; } else { primary = ld.Back; secondary = ld.Front; } } si.ceilingheight = (primary != null) ? primary.Sector.CeilHeight : 128; si.floorheight = (primary != null) ? primary.Sector.FloorHeight : 0; if (stairsectorbuilderform.UpperTextureTexture == "") stairsectorbuilderform.UpperTextureTexture = (primary == null) ? General.Settings.DefaultTexture : ((secondary == null) ? primary.MiddleTexture : primary.HighTexture); if (stairsectorbuilderform.LowerTextureTexture == "") stairsectorbuilderform.LowerTextureTexture = (primary == null) ? General.Settings.DefaultTexture : ((secondary == null) ? primary.MiddleTexture : primary.LowTexture); siout = si; }