// This updates the selection private void Update() { // Not in any modifying mode? if (mode == ModifyMode.None) { Vector2D prevdragoffset = alignoffset; alignoffset = new Vector2D(float.MinValue, float.MinValue); showalignoffset = false; // Check what grip the mouse is over // and change cursor accordingly Grip mousegrip = CheckMouseGrip(); switch (mousegrip) { case Grip.Main: int closestcorner = -1; float cornerdist = float.MaxValue; for (int i = 0; i < 4; i++) { Vector2D delta = corners[i] - mousemappos; float d = delta.GetLengthSq(); if (d < cornerdist) { closestcorner = i; cornerdist = d; } } switch (closestcorner) { // TODO: case 0: alignoffset = new Vector2D(0f, 0f); break; case 1: alignoffset = new Vector2D(texture.ScaledWidth, 0f); break; case 2: alignoffset = new Vector2D(texture.ScaledWidth, -texture.ScaledHeight); break; case 3: alignoffset = new Vector2D(0f, -texture.ScaledHeight); break; } showalignoffset = true; General.Interface.SetCursor(Cursors.Hand); break; case Grip.RotateLB: case Grip.RotateRT: alignoffset = new Vector2D(0f, 0f); showalignoffset = true; General.Interface.SetCursor(Cursors.Cross); break; case Grip.SizeH: case Grip.SizeV: alignoffset = new Vector2D(0f, 0f); showalignoffset = true; // Pick the best matching cursor depending on rotation and side float resizeangle = -(rotation + sectorinfo[0].rotation); if (mousegrip == Grip.SizeH) { resizeangle += Angle2D.PIHALF; } resizeangle = Angle2D.Normalized(resizeangle); if (resizeangle > Angle2D.PI) { resizeangle -= Angle2D.PI; } resizeangle = Math.Abs(resizeangle + Angle2D.PI / 8.000001f); int cursorindex = (int)Math.Floor((resizeangle / Angle2D.PI) * 4.0f) % 4; General.Interface.SetCursor(RESIZE_CURSORS[cursorindex]); break; default: General.Interface.SetCursor(Cursors.Default); break; } if (prevdragoffset != alignoffset) { General.Interface.RedrawDisplay(); } } else { Vector2D snappedmappos = mousemappos; bool dosnaptogrid = snaptogrid; // Options snaptogrid = General.Interface.ShiftState ^ General.Interface.SnapToGrid; snaptonearest = General.Interface.CtrlState ^ General.Interface.AutoMerge; // Change to crosshair cursor so we can clearly see around the mouse cursor General.Interface.SetCursor(Cursors.Cross); // Check what modifying mode we are in switch (mode) { case ModifyMode.Dragging: offset = -mousemappos - dragoffset; Vector2D transformedpos = TexToWorld(alignoffset); // Snap to nearest vertex? if (snaptonearest) { float vrange = BuilderPlug.Me.StitchRange / renderer.Scale; // Try the nearest vertex Vertex nv = MapSet.NearestVertexSquareRange(General.Map.Map.Vertices, transformedpos, vrange); if (nv != null) { // Change offset to snap to target offset -= nv.Position - transformedpos; dosnaptogrid = false; } else { // Find the nearest line within range Linedef nl = MapSet.NearestLinedefRange(General.Map.Map.Linedefs, transformedpos, vrange); if (nl != null) { // Snap to grid? if (dosnaptogrid) { // Get grid intersection coordinates List <Vector2D> coords = nl.GetGridIntersections(); // Find nearest grid intersection float found_distance = float.MaxValue; Vector2D found_pos = new Vector2D(float.NaN, float.NaN); foreach (Vector2D v in coords) { Vector2D dist = transformedpos - v; if (dist.GetLengthSq() < found_distance) { // Found a better match found_distance = dist.GetLengthSq(); found_pos = v; // Do not snap to grid anymore dosnaptogrid = false; } } // Found something? if (!float.IsNaN(found_pos.x)) { // Change offset to snap to target offset -= found_pos - transformedpos; } } else { // Change offset to snap onto the line offset -= nl.NearestOnLine(transformedpos) - transformedpos; } } } } // Snap to grid? if (dosnaptogrid) { // Change offset to align to grid offset -= General.Map.Grid.SnappedToGrid(transformedpos) - transformedpos; } break; case ModifyMode.Resizing: // Snap to nearest vertex? if (snaptonearest) { float vrange = BuilderPlug.Me.StitchRange / renderer.Scale; // Try the nearest vertex Vertex nv = MapSet.NearestVertexSquareRange(General.Map.Map.Vertices, snappedmappos, vrange); if (nv != null) { snappedmappos = nv.Position; dosnaptogrid = false; } } // Snap to grid? if (dosnaptogrid) { // Aligned to grid snappedmappos = General.Map.Grid.SnappedToGrid(snappedmappos); } float newscale = 1f / resizeaxis.GetNearestOnLine(snappedmappos); if (float.IsInfinity(newscale) || float.IsNaN(newscale)) { newscale = 99999f; } scale = (newscale * resizefilter) + scale * (1.0f - resizefilter); if (float.IsInfinity(scale.x) || float.IsNaN(scale.x)) { scale.x = 99999f; } if (float.IsInfinity(scale.y) || float.IsNaN(scale.y)) { scale.y = 99999f; } // Show the extension line so that the user knows what it is aligning to UpdateRectangleComponents(); Line2D edgeline; if (resizefilter.x > resizefilter.y) { edgeline = new Line2D(corners[1], corners[2]); } else { edgeline = new Line2D(corners[3], corners[2]); } float nearestonedge = edgeline.GetNearestOnLine(snappedmappos); if (nearestonedge > 0.5f) { extensionline = new Line2D(edgeline.v1, snappedmappos); } else { extensionline = new Line2D(edgeline.v2, snappedmappos); } break; case ModifyMode.Rotating: // Snap to nearest vertex? extensionline = new Line2D(); if (snaptonearest) { float vrange = BuilderPlug.Me.StitchRange / renderer.Scale; // Try the nearest vertex Vertex nv = MapSet.NearestVertexSquareRange(General.Map.Map.Vertices, snappedmappos, vrange); if (nv != null) { snappedmappos = nv.Position; dosnaptogrid = false; // Show the extension line so that the user knows what it is aligning to extensionline = new Line2D(corners[0], snappedmappos); } } Vector2D delta = snappedmappos - rotationcenter; float deltaangle = -delta.GetAngle(); // Snap to grid? if (dosnaptogrid) { // We make 8 vectors that the rotation can snap to float founddistance = float.MaxValue; float foundrotation = rotation; for (int i = 0; i < 8; i++) { // Make the vectors float angle = (float)i * Angle2D.PI * 0.25f; Vector2D gridvec = Vector2D.FromAngle(angle); Vector3D rotvec = Vector2D.FromAngle(deltaangle + rotationoffset); // Check distance float dist = 2.0f - Vector2D.DotProduct(gridvec, rotvec); if (dist < founddistance) { foundrotation = angle; founddistance = dist; } } // Keep rotation rotation = foundrotation - sectorinfo[0].rotation; } else { rotation = deltaangle + rotationoffset - sectorinfo[0].rotation; } break; } UpdateSectors(); General.Interface.RedrawDisplay(); } }
// 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(); // 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.FormatInterface.LeftBoundary) { offset.x = General.Map.FormatInterface.LeftBoundary - tl.x; } if (offset.x + br.x > General.Map.FormatInterface.RightBoundary) { offset.x = General.Map.FormatInterface.RightBoundary - br.x; } if (offset.y + tl.y > General.Map.FormatInterface.TopBoundary) { offset.y = General.Map.FormatInterface.TopBoundary - tl.y; } if (offset.y + br.y < General.Map.FormatInterface.BottomBoundary) { offset.y = General.Map.FormatInterface.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); } }
// 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) { double 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(), General.Map.Grid.GridRotate, General.Map.Grid.GridOriginX, General.Map.Grid.GridOriginY); // mxd. Do the rest only if we actually have some coordinates if (coords.Count > 0) { // Find nearest grid intersection double found_distance = double.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); }