diff --git a/Source/BuilderModes/BuilderModes.csproj b/Source/BuilderModes/BuilderModes.csproj
index c3639f42..9796c004 100644
--- a/Source/BuilderModes/BuilderModes.csproj
+++ b/Source/BuilderModes/BuilderModes.csproj
@@ -38,6 +38,7 @@
+
diff --git a/Source/BuilderModes/LinedefsMode/DragLinedefsMode.cs b/Source/BuilderModes/LinedefsMode/DragLinedefsMode.cs
index a7fe5b84..6085b719 100644
--- a/Source/BuilderModes/LinedefsMode/DragLinedefsMode.cs
+++ b/Source/BuilderModes/LinedefsMode/DragLinedefsMode.cs
@@ -62,7 +62,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
#region ================== Constructor / Disposer
// Constructor to start dragging immediately
- public DragLinedefsMode(EditMode basemode, Linedef dragitem, Vector2D dragstartmappos)
+ public DragLinedefsMode(EditMode basemode, Vector2D dragstartmappos)
{
// Get the nearest vertex for snapping
Vertex nearest = MapSet.NearestVertex(General.Map.Map.GetVerticesFromLinesSelection(true), dragstartmappos);
diff --git a/Source/BuilderModes/LinedefsMode/LinedefsMode.cs b/Source/BuilderModes/LinedefsMode/LinedefsMode.cs
index 93fa6097..f0470696 100644
--- a/Source/BuilderModes/LinedefsMode/LinedefsMode.cs
+++ b/Source/BuilderModes/LinedefsMode/LinedefsMode.cs
@@ -323,7 +323,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
}
// Start dragging the selection
- General.Map.ChangeMode(new DragLinedefsMode(new LinedefsMode(), highlighted, mousedownmappos));
+ General.Map.ChangeMode(new DragLinedefsMode(new LinedefsMode(), mousedownmappos));
}
}
}
diff --git a/Source/BuilderModes/SectorsMode/DragSectorsMode.cs b/Source/BuilderModes/SectorsMode/DragSectorsMode.cs
index b01a064d..637a3ae1 100644
--- a/Source/BuilderModes/SectorsMode/DragSectorsMode.cs
+++ b/Source/BuilderModes/SectorsMode/DragSectorsMode.cs
@@ -63,7 +63,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
#region ================== Constructor / Disposer
// Constructor to start dragging immediately
- public DragSectorsMode(EditMode basemode, Sector dragitem, Vector2D dragstartmappos)
+ public DragSectorsMode(EditMode basemode, Vector2D dragstartmappos)
{
// Get the nearest vertex for snapping
Vertex nearest = MapSet.NearestVertex(General.Map.Map.GetVerticesFromLinesSelection(true), dragstartmappos);
diff --git a/Source/BuilderModes/SectorsMode/SectorsMode.cs b/Source/BuilderModes/SectorsMode/SectorsMode.cs
index 72dc39ca..5901d99b 100644
--- a/Source/BuilderModes/SectorsMode/SectorsMode.cs
+++ b/Source/BuilderModes/SectorsMode/SectorsMode.cs
@@ -368,7 +368,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
}
// Start dragging the selection
- General.Map.ChangeMode(new DragSectorsMode(new SectorsMode(), highlighted, mousedownmappos));
+ General.Map.ChangeMode(new DragSectorsMode(new SectorsMode(), mousedownmappos));
}
}
}
diff --git a/Source/BuilderModes/Shared/DragGeometryMode.cs b/Source/BuilderModes/Shared/DragGeometryMode.cs
index b4b269db..5e89c651 100644
--- a/Source/BuilderModes/Shared/DragGeometryMode.cs
+++ b/Source/BuilderModes/Shared/DragGeometryMode.cs
@@ -241,7 +241,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
MoveGeometryRelative(new Vector2D(0f, 0f), false, false);
// Make undo for the dragging
- General.Map.UndoRedo.CreateUndo("drag vertices", UndoGroup.None, 0, false);
+ General.Map.UndoRedo.CreateUndo("drag vertices", UndoGroup.None, 0);
// Move selected geometry to final position
MoveGeometryRelative(mousemappos - dragstartmappos, snaptogrid, snaptonearest);
diff --git a/Source/BuilderModes/ThingsMode/DragThingsMode.cs b/Source/BuilderModes/ThingsMode/DragThingsMode.cs
new file mode 100644
index 00000000..c2fdeb01
--- /dev/null
+++ b/Source/BuilderModes/ThingsMode/DragThingsMode.cs
@@ -0,0 +1,369 @@
+
+#region ================== Copyright (c) 2007 Pascal vd Heiden
+
+/*
+ * Copyright (c) 2007 Pascal vd Heiden, www.codeimp.com
+ * This program is released under GNU General Public License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#endregion
+
+#region ================== Namespaces
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Text;
+using System.Windows.Forms;
+using System.IO;
+using System.Reflection;
+using CodeImp.DoomBuilder.Interface;
+using CodeImp.DoomBuilder.IO;
+using CodeImp.DoomBuilder.Map;
+using CodeImp.DoomBuilder.Rendering;
+using CodeImp.DoomBuilder.Geometry;
+using System.Drawing;
+using CodeImp.DoomBuilder.Editing;
+
+#endregion
+
+namespace CodeImp.DoomBuilder.BuilderModes.Editing
+{
+ // No action or button for this mode, it is automatic.
+ // The EditMode attribute does not have to be specified unless the
+ // mode must be activated by class name rather than direct instance.
+ // In that case, just specifying the attribute like this is enough:
+ [EditMode]
+
+ public sealed class DragThingsMode : ClassicMode
+ {
+ #region ================== Constants
+
+ #endregion
+
+ #region ================== Variables
+
+ // Mode to return to
+ private EditMode basemode;
+
+ // Mouse position on map where dragging started
+ private Vector2D dragstartmappos;
+
+ // Item used as reference for snapping to the grid
+ protected Thing dragitem;
+ private Vector2D dragitemposition;
+
+ // List of old thing positions
+ private List oldpositions;
+
+ // List of selected items
+ private ICollection selectedthings;
+
+ // List of non-selected items
+ private ICollection unselectedthings;
+
+ // Keep track of view changes
+ private float lastoffsetx;
+ private float lastoffsety;
+ private float lastscale;
+
+ // Options
+ private bool snaptogrid; // SHIFT to toggle
+ private bool snaptonearest; // CTRL to enable
+
+ #endregion
+
+ #region ================== Properties
+
+ // Just keep the base mode button checked
+ public override string EditModeButtonName { get { return basemode.GetType().Name; } }
+
+ #endregion
+
+ #region ================== Constructor / Disposer
+
+ // Constructor to start dragging immediately
+ public DragThingsMode(EditMode basemode, Vector2D dragstartmappos)
+ {
+ // Initialize
+ this.dragstartmappos = dragstartmappos;
+ this.basemode = basemode;
+
+ Cursor.Current = Cursors.AppStarting;
+
+ // Get the nearest thing for snapping
+ dragitem = MapSet.NearestThing(General.Map.Map.GetThingsSelection(true), dragstartmappos);
+
+ // Get selected things
+ selectedthings = General.Map.Map.GetThingsSelection(true);
+ unselectedthings = General.Map.Map.GetThingsSelection(false);
+
+ // Make old positions list
+ // We will use this as reference to move the vertices, or to move them back on cancel
+ oldpositions = new List(selectedthings.Count);
+ foreach(Thing t in selectedthings) oldpositions.Add(t.Position);
+
+ // Also keep old position of the dragged item
+ dragitemposition = dragitem.Position;
+
+ // Keep view information
+ lastoffsetx = renderer.OffsetX;
+ lastoffsety = renderer.OffsetY;
+ lastscale = renderer.Scale;
+
+ Cursor.Current = Cursors.Default;
+
+ // We have no destructor
+ GC.SuppressFinalize(this);
+ }
+
+ // Disposer
+ public override void Dispose()
+ {
+ // Not already disposed?
+ if(!isdisposed)
+ {
+ // Clean up
+
+ // Done
+ base.Dispose();
+ }
+ }
+
+ #endregion
+
+ #region ================== Methods
+
+ // This moves the selected things relatively
+ // Returns true when things has actually moved
+ private bool MoveThingsRelative(Vector2D offset, bool snapgrid, bool snapnearest)
+ {
+ Vector2D oldpos = dragitem.Position;
+ Thing nearest;
+ int i = 0;
+
+ // Snap to nearest?
+ if(snapnearest)
+ {
+ // Find nearest unselected item within selection range
+ nearest = MapSet.NearestThingSquareRange(unselectedthings, mousemappos, ThingsMode.THING_HIGHLIGHT_RANGE / renderer.Scale);
+ if(nearest != null)
+ {
+ // Move the dragged item
+ dragitem.Move((Vector2D)nearest.Position);
+
+ // Adjust the offset
+ offset = (Vector2D)nearest.Position - dragitemposition;
+
+ // Do not snap to grid!
+ snapgrid = false;
+ }
+ }
+
+ // Snap to grid?
+ if(snapgrid)
+ {
+ // Move the dragged item
+ dragitem.Move(dragitemposition + offset);
+
+ // Snap item to grid
+ dragitem.SnapToGrid();
+
+ // Adjust the offset
+ offset += (Vector2D)dragitem.Position - (dragitemposition + offset);
+ }
+
+ // Drag item moved?
+ if(!snapgrid || ((Vector2D)dragitem.Position != oldpos))
+ {
+ // Move selected geometry
+ foreach(Thing t in selectedthings)
+ {
+ // Move vertex from old position relative to the
+ // mouse position change since drag start
+ t.Move(oldpositions[i] + offset);
+
+ // Next
+ i++;
+ }
+
+ // Moved
+ return true;
+ }
+ else
+ {
+ // No changes
+ return false;
+ }
+ }
+
+ // This redraws the display
+ public unsafe override void RedrawDisplay()
+ {
+ bool viewchanged = CheckViewChanged();
+
+ // Start with a clear display
+ if(renderer.Start(viewchanged, true))
+ {
+ if(viewchanged)
+ {
+ // Render lines and vertices
+ renderer.RenderLinedefSet(General.Map.Map.Linedefs);
+ renderer.RenderVerticesSet(General.Map.Map.Vertices);
+ }
+
+ // Render things
+ renderer.SetThingsRenderOrder(true);
+ renderer.RenderThingSet(unselectedthings);
+ renderer.RenderThingSet(selectedthings);
+
+ // Draw the dragged item highlighted
+ // This is important to know, because this item is used
+ // for snapping to the grid and snapping to nearest items
+ renderer.RenderThing(dragitem, General.Colors.Highlight);
+
+ // Done
+ renderer.Finish();
+ }
+ }
+
+ // Cancelled
+ public override void Cancel()
+ {
+ // Move geometry back to original position
+ MoveThingsRelative(new Vector2D(0f, 0f), false, false);
+
+ // If only a single vertex was selected, deselect it now
+ if(selectedthings.Count == 1) General.Map.Map.ClearSelectedThings();
+
+ // Update cached values
+ General.Map.Map.Update();
+
+ // Cancel base class
+ base.Cancel();
+
+ // Return to vertices mode
+ General.Map.ChangeMode(basemode);
+ }
+
+ // Mode engages
+ public override void Engage()
+ {
+ base.Engage();
+ }
+
+ // Disenagaging
+ public override void Disengage()
+ {
+ base.Disengage();
+ Cursor.Current = Cursors.AppStarting;
+
+ // When not cancelled
+ if(!cancelled)
+ {
+ // Move geometry back to original position
+ MoveThingsRelative(new Vector2D(0f, 0f), false, false);
+
+ // Make undo for the dragging
+ General.Map.UndoRedo.CreateUndo("drag things", UndoGroup.None, 0);
+
+ // Move selected geometry to final position
+ MoveThingsRelative(mousemappos - dragstartmappos, snaptogrid, snaptonearest);
+
+ // Update cached values
+ General.Map.Map.Update();
+
+ // Map is changed
+ General.Map.IsChanged = true;
+ }
+
+ // Hide highlight info
+ General.Interface.HideInfo();
+
+ // Done
+ Cursor.Current = Cursors.Default;
+ }
+
+ // This checks if the view offset/zoom changed and updates the check
+ protected bool CheckViewChanged()
+ {
+ bool viewchanged = false;
+
+ // View changed?
+ if(renderer.OffsetX != lastoffsetx) viewchanged = true;
+ if(renderer.OffsetY != lastoffsety) viewchanged = true;
+ if(renderer.Scale != lastscale) viewchanged = true;
+
+ // Keep view information
+ lastoffsetx = renderer.OffsetX;
+ lastoffsety = renderer.OffsetY;
+ lastscale = renderer.Scale;
+
+ // Return result
+ return viewchanged;
+ }
+
+ // This updates the dragging
+ private void Update()
+ {
+ snaptogrid = General.Interface.ShiftState ^ General.Interface.SnapToGrid;
+ snaptonearest = General.Interface.CtrlState;
+
+ // Move selected geometry
+ if(MoveThingsRelative(mousemappos - dragstartmappos, snaptogrid, snaptonearest))
+ {
+ // Update cached values
+ //General.Map.Map.Update(true, false);
+ General.Map.Map.Update();
+
+ // Redraw
+ General.Interface.RedrawDisplay();
+ }
+ }
+
+ // Mouse moving
+ public override void MouseMove(MouseEventArgs e)
+ {
+ base.MouseMove(e);
+ Update();
+ }
+
+ // Mouse button released
+ public override void MouseUp(MouseEventArgs e)
+ {
+ base.MouseUp(e);
+
+ // Is the editing button released?
+ if(e.Button == EditMode.EDIT_BUTTON)
+ {
+ // Just return to vertices mode, geometry will be merged on disengage.
+ General.Map.ChangeMode(basemode);
+ }
+ }
+
+ // When a key is released
+ public override void KeyUp(KeyEventArgs e)
+ {
+ base.KeyUp(e);
+ if(snaptogrid != General.Interface.ShiftState ^ General.Interface.SnapToGrid) Update();
+ if(snaptonearest != General.Interface.CtrlState) Update();
+ }
+
+ // When a key is pressed
+ public override void KeyDown(KeyEventArgs e)
+ {
+ base.KeyDown(e);
+ if(snaptogrid != General.Interface.ShiftState ^ General.Interface.SnapToGrid) Update();
+ if(snaptonearest != General.Interface.CtrlState) Update();
+ }
+
+ #endregion
+ }
+}
diff --git a/Source/BuilderModes/ThingsMode/ThingsMode.cs b/Source/BuilderModes/ThingsMode/ThingsMode.cs
index 710c0b1a..88a8cfdd 100644
--- a/Source/BuilderModes/ThingsMode/ThingsMode.cs
+++ b/Source/BuilderModes/ThingsMode/ThingsMode.cs
@@ -44,7 +44,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
{
#region ================== Constants
- protected const float THING_HIGHLIGHT_RANGE = 10f;
+ public const float THING_HIGHLIGHT_RANGE = 10f;
#endregion
@@ -254,6 +254,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
if(selected.Count > 0)
{
// Show thing edit dialog
+ // TODO
// When a single thing was selected, deselect it now
if(selected.Count == 1) General.Map.Map.ClearSelectedThings();
@@ -264,6 +265,36 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
}
}
}
+
+ // Mouse wants to drag
+ protected override void DragStart(MouseEventArgs e)
+ {
+ base.DragStart(e);
+
+ // Which button is used?
+ if(e.Button == EditMode.SELECT_BUTTON)
+ {
+ // Make selection
+
+ }
+ else if(e.Button == EditMode.EDIT_BUTTON)
+ {
+ // Anything highlighted?
+ if((highlighted != null) && !highlighted.IsDisposed)
+ {
+ // Highlighted item not selected?
+ if(!highlighted.Selected)
+ {
+ // Select only this sector for dragging
+ General.Map.Map.ClearSelectedThings();
+ highlighted.Selected = true;
+ }
+
+ // Start dragging the selection
+ General.Map.ChangeMode(new DragThingsMode(new ThingsMode(), mousedownmappos));
+ }
+ }
+ }
#endregion
}
diff --git a/Source/Editing/UndoManager.cs b/Source/Editing/UndoManager.cs
index ea50cde3..5daac5d0 100644
--- a/Source/Editing/UndoManager.cs
+++ b/Source/Editing/UndoManager.cs
@@ -142,7 +142,7 @@ namespace CodeImp.DoomBuilder.Editing
#region ================== Public Methods
// This makes an undo and returns the unique ticket id
- public int CreateUndo(string description, UndoGroup group, int grouptag, bool allow3dchange)
+ public int CreateUndo(string description, UndoGroup group, int grouptag)
{
UndoSnapshot u;
@@ -155,7 +155,7 @@ namespace CodeImp.DoomBuilder.Editing
if(++ticketid == int.MaxValue) ticketid = 1;
// Make a snapshot
- u = new UndoSnapshot(description, allow3dchange, General.Map.Map.Clone(), ticketid);
+ u = new UndoSnapshot(description, General.Map.Map.Clone(), ticketid);
// Put it on the stack
undos.Insert(0, u);
diff --git a/Source/Editing/UndoSnapshot.cs b/Source/Editing/UndoSnapshot.cs
index 8e3c87e4..3682539a 100644
--- a/Source/Editing/UndoSnapshot.cs
+++ b/Source/Editing/UndoSnapshot.cs
@@ -39,15 +39,13 @@ namespace CodeImp.DoomBuilder.Editing
{
public MapSet map;
public string description;
- public bool allow3dchange; // True when allowed to change in 3D mode
public int ticketid; // For safe withdrawing
// Constructor
- public UndoSnapshot(string description, bool allow3dchange, MapSet map, int ticketid)
+ public UndoSnapshot(string description, MapSet map, int ticketid)
{
this.ticketid = ticketid;
this.description = description;
- this.allow3dchange = allow3dchange;
this.map = map;
}
@@ -56,7 +54,6 @@ namespace CodeImp.DoomBuilder.Editing
{
this.ticketid = info.ticketid;
this.description = info.description;
- this.allow3dchange = info.allow3dchange;
this.map = map;
}
}
diff --git a/Source/Interface/LinedefEditForm.cs b/Source/Interface/LinedefEditForm.cs
index 1a45d5e9..990f0605 100644
--- a/Source/Interface/LinedefEditForm.cs
+++ b/Source/Interface/LinedefEditForm.cs
@@ -237,7 +237,7 @@ namespace CodeImp.DoomBuilder.Interface
// Make undo
if(lines.Count > 1) undodesc = lines.Count + " linedefs";
- General.Map.UndoRedo.CreateUndo("edit " + undodesc, UndoGroup.None, 0, false);
+ General.Map.UndoRedo.CreateUndo("edit " + undodesc, UndoGroup.None, 0);
// Go for all the lines
foreach(Linedef l in lines)
diff --git a/Source/Interface/MainForm.cs b/Source/Interface/MainForm.cs
index 9f4a6e38..50b45b25 100644
--- a/Source/Interface/MainForm.cs
+++ b/Source/Interface/MainForm.cs
@@ -314,8 +314,6 @@ namespace CodeImp.DoomBuilder.Interface
// This updates the status icon
internal void UpdateStatusIcon()
{
- if(IsDisposed) return;
-
// From another thread?
if(statusbar.InvokeRequired)
{
diff --git a/Source/Interface/SectorEditForm.cs b/Source/Interface/SectorEditForm.cs
index 9e1e1143..914e2ede 100644
--- a/Source/Interface/SectorEditForm.cs
+++ b/Source/Interface/SectorEditForm.cs
@@ -113,7 +113,7 @@ namespace CodeImp.DoomBuilder.Interface
// Make undo
if(sectors.Count > 1) undodesc = sectors.Count + " sectors";
- General.Map.UndoRedo.CreateUndo("edit " + undodesc, UndoGroup.None, 0, false);
+ General.Map.UndoRedo.CreateUndo("edit " + undodesc, UndoGroup.None, 0);
// Go for all sectors
foreach(Sector s in sectors)
diff --git a/Source/Map/MapSet.cs b/Source/Map/MapSet.cs
index 684c4475..64b9b295 100644
--- a/Source/Map/MapSet.cs
+++ b/Source/Map/MapSet.cs
@@ -619,7 +619,7 @@ namespace CodeImp.DoomBuilder.Map
if(General.MainWindow.AutoMerge)
{
// Make undo for the stitching
- stitchundo = General.Map.UndoRedo.CreateUndo("stitch geometry", UndoGroup.None, 0, false);
+ stitchundo = General.Map.UndoRedo.CreateUndo("stitch geometry", UndoGroup.None, 0);
// Find lines that moved during the drag
movinglines = LinedefsFromSelectedVertices(false, true, true);
@@ -968,6 +968,30 @@ namespace CodeImp.DoomBuilder.Map
return closest;
}
+ // This finds the thing closest to the specified position
+ public static Thing NearestThing(ICollection selection, Vector2D pos)
+ {
+ Thing closest = null;
+ float distance = float.MaxValue;
+ float d;
+
+ // Go for all things in selection
+ foreach(Thing t in selection)
+ {
+ // Calculate distance and check if closer than previous find
+ d = t.DistanceToSq(pos);
+ if(d < distance)
+ {
+ // This one is closer
+ closest = t;
+ distance = d;
+ }
+ }
+
+ // Return result
+ return closest;
+ }
+
// This finds the vertex closest to the specified position
public static Vertex NearestVertexSquareRange(ICollection selection, Vector2D pos, float maxrange)
{
diff --git a/Source/Map/Thing.cs b/Source/Map/Thing.cs
index c6076e4b..fa25b873 100644
--- a/Source/Map/Thing.cs
+++ b/Source/Map/Thing.cs
@@ -224,6 +224,16 @@ namespace CodeImp.DoomBuilder.Map
#region ================== Changes
+ // This moves the thing
+ // NOTE: This does not update sector! (call DetermineSector)
+ public void Move(Vector2D newpos)
+ {
+ // Change position
+ this.x = (int)newpos.x;
+ this.y = (int)newpos.y;
+ this.pos = new Vector3D(newpos.x, newpos.y, zoffset);
+ }
+
// This moves the thing
// NOTE: This does not update sector! (call DetermineSector)
public void Move(int x, int y, int zoffset)
@@ -289,6 +299,13 @@ namespace CodeImp.DoomBuilder.Map
#region ================== Methods
+ // This snaps the vertex to the grid
+ public void SnapToGrid()
+ {
+ // Calculate nearest grid coordinates
+ this.Move(General.Map.Grid.SnappedToGrid((Vector2D)pos));
+ }
+
// This returns the distance from given coordinates
public float DistanceToSq(Vector2D p)
{