Added selection feature in Visual Mode (click left mouse button to select)

This commit is contained in:
codeimp 2009-05-03 19:22:32 +00:00
parent fd9308d74f
commit 634efc6ee4
10 changed files with 462 additions and 253 deletions

View file

@ -19,7 +19,7 @@
<div id="contents">
<p>
The Visual Mode is different from the other modes. In this mode you can walk and fly through your map in 3D and see it as it would look like in game. With the crosshair you can aim at objects (floors, ceilings, walls and things) and edit them instantly.
The Visual Mode is different from the other modes. In this mode you can walk and fly through your map in 3D and see it as it would look like in game. With the crosshair you can aim at objects (floors, ceilings, walls and things) and edit them instantly. You can also select objects and perform actions on all objects together. Note that not all actions apply to an entire selection.
<h2>Default Controls</h2>
<table border="0" cellspacing="6" width="90%">
@ -45,7 +45,11 @@
</tr>
<tr>
<td valign="top"><b title="Shift + Middle Mouse Button">Shift+MMB</b></td>
<td>Flood-fills with the copied texture image or flat image onto the target. This fills all adjacent textures or flats that are identical to the original.</td>
<td>Flood-fills with the copied texture image or flat image onto the target. This fills all adjacent textures or flats that are identical to the original. Note that this action is only applied to the targeted object and does not work for a selection.</td>
</tr>
<tr>
<td valign="top"><b>C</b></td>
<td>Clears the selection.</td>
</tr>
<tr>
<td valign="top"><b>E</b></td>
@ -85,23 +89,23 @@
</tr>
<tr>
<td valign="top"><b>A</b></td>
<td>Auto-aligns the neighbouring textures horizontally, until a wall is encountered that has different textures.</td>
<td>Auto-aligns the neighbouring textures horizontally, until a wall is encountered that has different textures. Note that this action is only applied to the targeted object and does not work for a selection.</td>
</tr>
<tr>
<td valign="top"><b>Shift+A</b></td>
<td>Auto-aligns the neighbouring textures vertically, until a wall is encountered that has different textures. The vertical alignment takes the ceiling height differences between sidedefs into account.</td>
<td>Auto-aligns the neighbouring textures vertically, until a wall is encountered that has different textures. The vertical alignment takes the ceiling height differences between sidedefs into account. Note that this action is only applied to the targeted object and does not work for a selection.</td>
</tr>
<tr>
<td valign="top"><b>Shift+C</b></td>
<td>Copies the targeted texture offsets for pasting.</td>
<td>Copies the targeted texture offsets for pasting. Note that this works only for the targeted object, the selection is ignored.</td>
</tr>
<tr>
<td valign="top"><b>Control+C</b></td>
<td>Copies the targeted texture image or flat image for pasting.</td>
<td>Copies the targeted texture image or flat image for pasting. Note that this works only for the targeted object, the selection is ignored.</td>
</tr>
<tr>
<td valign="top"><b>Control+Shift+C</b></td>
<td>Copies the targeted object properties for pasting.</td>
<td>Copies the targeted object properties for pasting. Note that this works only for the targeted object, the selection is ignored.</td>
</tr>
<tr>
<td valign="top"><b>Shift+V</b></td>

View file

@ -1057,6 +1057,7 @@ namespace CodeImp.DoomBuilder
// Make selection
map.AddSelectionToGroup(0x01 << groupindex);
General.Interface.DisplayStatus(StatusType.Action, "Assigned selection to group " + groupindex);
General.Interface.SetCursor(Cursors.Default);
}
@ -1071,6 +1072,7 @@ namespace CodeImp.DoomBuilder
map.SelectThingsByGroup(groupmask);
// Redraw to show selection
General.Interface.DisplayStatus(StatusType.Action, "Selected group " + groupindex);
General.Interface.RedrawDisplay();
}

View file

@ -133,6 +133,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
public virtual void OnInsert() { }
public virtual void OnDelete() { }
protected virtual void SetTexture(string texturename) { }
public virtual void ApplyUpperUnpegged(bool set) { }
public virtual void ApplyLowerUnpegged(bool set) { }
// Select or deselect
public virtual void OnSelectEnd()
@ -177,12 +179,12 @@ namespace CodeImp.DoomBuilder.BuilderModes
if(fillceilings)
{
mode.CreateSingleUndo("Flood-fill ceilings with " + newtexture);
mode.CreateUndo("Flood-fill ceilings with " + newtexture);
mode.SetActionResult("Flood-filled ceilings with " + newtexture + ".");
}
else
{
mode.CreateSingleUndo("Flood-fill floors with " + newtexture);
mode.CreateUndo("Flood-fill floors with " + newtexture);
mode.SetActionResult("Flood-filled floors with " + newtexture + ".");
}
@ -227,7 +229,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
if(BuilderPlug.Me.CopiedSectorProps != null)
{
mode.CreateSingleUndo("Paste sector properties");
mode.CreateUndo("Paste sector properties");
mode.SetActionResult("Pasted sector properties.");
BuilderPlug.Me.CopiedSectorProps.Apply(Sector.Sector);
UpdateSectorGeometry(true);
@ -244,11 +246,17 @@ namespace CodeImp.DoomBuilder.BuilderModes
string newtexture = General.Interface.BrowseFlat(General.Interface, oldtexture);
if(newtexture != oldtexture)
{
mode.CreateSingleUndo("Change flat " + newtexture);
SetTexture(newtexture);
mode.ApplySelectTexture(newtexture, true);
}
}
}
// Apply Texture
public virtual void ApplyTexture(string texture)
{
mode.CreateUndo("Change flat " + texture);
SetTexture(texture);
}
// Copy texture
public virtual void OnCopyTexture()
@ -271,13 +279,17 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
if(General.Interface.IsActiveWindow)
{
List<Sector> sectors = new List<Sector>();
sectors.Add(this.Sector.Sector);
List<Sector> sectors = mode.GetSelectedSectors();
DialogResult result = General.Interface.ShowEditSectors(sectors);
if(result == DialogResult.OK)
{
// Rebuild sector
UpdateSectorGeometry(true);
foreach(Sector s in sectors)
{
VisualSector vs = mode.GetVisualSector(s);
if(vs != null)
(vs as BaseVisualSector).Changed = true;
}
}
}
}
@ -286,6 +298,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Sector height change
public virtual void OnChangeTargetHeight(int amount)
{
changed = true;
ChangeHeight(amount);
// Rebuild sector
@ -295,7 +309,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Sector brightness change
public virtual void OnChangeTargetBrightness(bool up)
{
mode.CreateSingleUndo("Change sector brightness", UndoGroup.SectorBrightnessChange, Sector.Sector.FixedIndex);
mode.CreateUndo("Change sector brightness", UndoGroup.SectorBrightnessChange, Sector.Sector.FixedIndex);
if(up)
Sector.Sector.Brightness = General.Map.Config.BrightnessLevels.GetNextHigher(Sector.Sector.Brightness);

View file

@ -63,7 +63,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
private int startoffsetx;
private int startoffsety;
protected bool uvdragging;
private int prevoffsetx; // We have to provide delta offsets, but I don't
private int prevoffsety; // want to calculate with delta offsets to prevent
// inaccuracy in the dragging.
// Undo/redo
private int undoticket;
@ -123,7 +125,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
if(!Sidedef.MiddleRequired() && (string.IsNullOrEmpty(Sidedef.MiddleTexture) || (Sidedef.MiddleTexture[0] == '-')))
{
// Make it now
mode.CreateSingleUndo("Create middle texture");
mode.CreateUndo("Create middle texture");
mode.SetActionResult("Created middle texture.");
General.Settings.FindDefaultDrawSettings();
Sidedef.SetTextureMid(General.Settings.DefaultTexture);
@ -147,7 +149,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
public virtual void OnDelete()
{
// Remove texture
mode.CreateSingleUndo("Delete texture");
mode.CreateUndo("Delete texture");
mode.SetActionResult("Deleted a texture.");
SetTexture("-");
@ -180,12 +182,14 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
// Change ceiling
case 1:
this.Sector.Ceiling.OnChangeTargetHeight(amount);
if(!this.Sector.Ceiling.Changed)
this.Sector.Ceiling.OnChangeTargetHeight(amount);
break;
// Change floor
case 2:
this.Sector.Floor.OnChangeTargetHeight(amount);
if(!this.Sector.Floor.Changed)
this.Sector.Floor.OnChangeTargetHeight(amount);
break;
}
}
@ -193,7 +197,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Reset texture offsets
public virtual void OnResetTextureOffset()
{
mode.CreateSingleUndo("Reset texture offsets");
mode.CreateUndo("Reset texture offsets");
mode.SetActionResult("Texture offsets reset.");
// Apply offsets
@ -202,10 +206,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Update sidedef geometry
VisualSidedefParts parts = Sector.GetSidedefParts(Sidedef);
if(parts.lower != null) parts.lower.Setup();
if(parts.middledouble != null) parts.middledouble.Setup();
if(parts.middlesingle != null) parts.middlesingle.Setup();
if(parts.upper != null) parts.upper.Setup();
parts.SetupAllParts();
}
// Toggle upper-unpegged
@ -215,34 +216,12 @@ namespace CodeImp.DoomBuilder.BuilderModes
this.Sidedef.Line.Flags[General.Map.Config.UpperUnpeggedFlag])
{
// Remove flag
mode.CreateSingleUndo("Remove upper-unpegged setting");
mode.SetActionResult("Removed upper-unpegged setting.");
this.Sidedef.Line.Flags[General.Map.Config.UpperUnpeggedFlag] = false;
mode.ApplyUpperUnpegged(false);
}
else
{
// Add flag
mode.CreateSingleUndo("Set upper-unpegged setting");
mode.SetActionResult("Set upper-unpegged setting.");
this.Sidedef.Line.Flags[General.Map.Config.UpperUnpeggedFlag] = true;
}
// Update sidedef geometry
VisualSidedefParts parts = Sector.GetSidedefParts(Sidedef);
if(parts.lower != null) parts.lower.Setup();
if(parts.middledouble != null) parts.middledouble.Setup();
if(parts.middlesingle != null) parts.middlesingle.Setup();
if(parts.upper != null) parts.upper.Setup();
// Update other sidedef geometry
if(Sidedef.Other != null)
{
BaseVisualSector othersector = (BaseVisualSector)mode.GetVisualSector(Sidedef.Other.Sector);
parts = othersector.GetSidedefParts(Sidedef.Other);
if(parts.lower != null) parts.lower.Setup();
if(parts.middledouble != null) parts.middledouble.Setup();
if(parts.middlesingle != null) parts.middlesingle.Setup();
if(parts.upper != null) parts.upper.Setup();
mode.ApplyUpperUnpegged(true);
}
}
@ -253,37 +232,80 @@ namespace CodeImp.DoomBuilder.BuilderModes
this.Sidedef.Line.Flags[General.Map.Config.LowerUnpeggedFlag])
{
// Remove flag
mode.CreateSingleUndo("Remove lower-unpegged setting");
mode.ApplyLowerUnpegged(false);
}
else
{
// Add flag
mode.ApplyLowerUnpegged(true);
}
}
// This sets the Upper Unpegged flag
public virtual void ApplyUpperUnpegged(bool set)
{
if(!set)
{
// Remove flag
mode.CreateUndo("Remove upper-unpegged setting");
mode.SetActionResult("Removed upper-unpegged setting.");
this.Sidedef.Line.Flags[General.Map.Config.UpperUnpeggedFlag] = false;
}
else
{
// Add flag
mode.CreateUndo("Set upper-unpegged setting");
mode.SetActionResult("Set upper-unpegged setting.");
this.Sidedef.Line.Flags[General.Map.Config.UpperUnpeggedFlag] = true;
}
// Update sidedef geometry
VisualSidedefParts parts = Sector.GetSidedefParts(Sidedef);
parts.SetupAllParts();
// Update other sidedef geometry
if(Sidedef.Other != null)
{
BaseVisualSector othersector = (BaseVisualSector)mode.GetVisualSector(Sidedef.Other.Sector);
parts = othersector.GetSidedefParts(Sidedef.Other);
parts.SetupAllParts();
}
}
// This sets the Lower Unpegged flag
public virtual void ApplyLowerUnpegged(bool set)
{
if(!set)
{
// Remove flag
mode.CreateUndo("Remove lower-unpegged setting");
mode.SetActionResult("Removed lower-unpegged setting.");
this.Sidedef.Line.Flags[General.Map.Config.LowerUnpeggedFlag] = false;
}
else
{
// Add flag
mode.CreateSingleUndo("Set lower-unpegged setting");
mode.CreateUndo("Set lower-unpegged setting");
mode.SetActionResult("Set lower-unpegged setting.");
this.Sidedef.Line.Flags[General.Map.Config.LowerUnpeggedFlag] = true;
}
// Update sidedef geometry
VisualSidedefParts parts = Sector.GetSidedefParts(Sidedef);
if(parts.lower != null) parts.lower.Setup();
if(parts.middledouble != null) parts.middledouble.Setup();
if(parts.middlesingle != null) parts.middlesingle.Setup();
if(parts.upper != null) parts.upper.Setup();
parts.SetupAllParts();
// Update other sidedef geometry
if(Sidedef.Other != null)
{
BaseVisualSector othersector = (BaseVisualSector)mode.GetVisualSector(Sidedef.Other.Sector);
parts = othersector.GetSidedefParts(Sidedef.Other);
if(parts.lower != null) parts.lower.Setup();
if(parts.middledouble != null) parts.middledouble.Setup();
if(parts.middlesingle != null) parts.middlesingle.Setup();
if(parts.upper != null) parts.upper.Setup();
parts.SetupAllParts();
}
}
// Flood-fill textures
public virtual void OnTextureFloodfill()
{
@ -294,7 +316,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
string newtexture = BuilderPlug.Me.CopiedTexture;
if(newtexture != oldtexture)
{
mode.CreateSingleUndo("Flood-fill textures with " + newtexture);
mode.CreateUndo("Flood-fill textures with " + newtexture);
mode.SetActionResult("Flood-filled textures with " + newtexture + ".");
mode.Renderer.SetCrosshairBusy(true);
@ -316,10 +338,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
BaseVisualSector vs = (mode.GetVisualSector(sd.Sector) as BaseVisualSector);
VisualSidedefParts parts = vs.GetSidedefParts(sd);
if(parts.lower != null) parts.lower.Setup();
if(parts.middledouble != null) parts.middledouble.Setup();
if(parts.middlesingle != null) parts.middlesingle.Setup();
if(parts.upper != null) parts.upper.Setup();
parts.SetupAllParts();
}
}
@ -334,7 +353,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Auto-align texture X offsets
public virtual void OnTextureAlign(bool alignx, bool aligny)
{
mode.CreateSingleUndo("Auto-align textures");
mode.CreateUndo("Auto-align textures");
mode.SetActionResult("Auto-aligned textures.");
// Make sure the texture is loaded (we need the texture size)
@ -352,10 +371,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
BaseVisualSector vs = (mode.GetVisualSector(sd.Sector) as BaseVisualSector);
VisualSidedefParts parts = vs.GetSidedefParts(sd);
if(parts.lower != null) parts.lower.Setup();
if(parts.middledouble != null) parts.middledouble.Setup();
if(parts.middlesingle != null) parts.middlesingle.Setup();
if(parts.upper != null) parts.upper.Setup();
parts.SetupAllParts();
}
}
}
@ -369,18 +385,24 @@ namespace CodeImp.DoomBuilder.BuilderModes
string newtexture = General.Interface.BrowseTexture(General.Interface, oldtexture);
if(newtexture != oldtexture)
{
mode.CreateSingleUndo("Change texture " + newtexture);
SetTexture(newtexture);
mode.ApplySelectTexture(newtexture, false);
}
}
}
// Apply Texture
public virtual void ApplyTexture(string texture)
{
mode.CreateUndo("Change texture " + texture);
SetTexture(texture);
}
// Paste texture
public virtual void OnPasteTexture()
{
if(BuilderPlug.Me.CopiedTexture != null)
{
mode.CreateSingleUndo("Paste texture " + BuilderPlug.Me.CopiedTexture);
mode.CreateUndo("Paste texture " + BuilderPlug.Me.CopiedTexture);
mode.SetActionResult("Pasted texture " + BuilderPlug.Me.CopiedTexture + ".");
SetTexture(BuilderPlug.Me.CopiedTexture);
}
@ -389,17 +411,14 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Paste texture offsets
public virtual void OnPasteTextureOffsets()
{
mode.CreateSingleUndo("Paste texture offsets");
mode.CreateUndo("Paste texture offsets");
Sidedef.OffsetX = BuilderPlug.Me.CopiedOffsets.X;
Sidedef.OffsetY = BuilderPlug.Me.CopiedOffsets.Y;
mode.SetActionResult("Pasted texture offsets " + Sidedef.OffsetX + ", " + Sidedef.OffsetY + ".");
// Update sidedef geometry
VisualSidedefParts parts = Sector.GetSidedefParts(Sidedef);
if(parts.lower != null) parts.lower.Setup();
if(parts.middledouble != null) parts.middledouble.Setup();
if(parts.middlesingle != null) parts.middlesingle.Setup();
if(parts.upper != null) parts.upper.Setup();
parts.SetupAllParts();
}
// Copy texture
@ -429,7 +448,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
if(BuilderPlug.Me.CopiedSidedefProps != null)
{
mode.CreateSingleUndo("Paste sidedef properties");
mode.CreateUndo("Paste sidedef properties");
mode.SetActionResult("Pasted sidedef properties.");
BuilderPlug.Me.CopiedSidedefProps.Apply(Sidedef);
@ -456,6 +475,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
dragorigin = pickintersect;
startoffsetx = Sidedef.OffsetX;
startoffsety = Sidedef.OffsetY;
prevoffsetx = Sidedef.OffsetX;
prevoffsety = Sidedef.OffsetY;
}
// Select button released
@ -484,10 +505,27 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
if(General.Interface.IsActiveWindow)
{
List<Linedef> lines = new List<Linedef>();
lines.Add(this.Sidedef.Line);
DialogResult result = General.Interface.ShowEditLinedefs(lines);
if(result == DialogResult.OK) (this.Sector as BaseVisualSector).Changed = true;
List<Linedef> linedefs = mode.GetSelectedLinedefs();
DialogResult result = General.Interface.ShowEditLinedefs(linedefs);
if(result == DialogResult.OK)
{
foreach(Linedef l in linedefs)
{
if(l.Front != null)
{
VisualSector vs = mode.GetVisualSector(l.Front.Sector);
if(vs != null)
(vs as BaseVisualSector).Changed = true;
}
if(l.Back != null)
{
VisualSector vs = mode.GetVisualSector(l.Back.Sector);
if(vs != null)
(vs as BaseVisualSector).Changed = true;
}
}
}
}
}
}
@ -510,7 +548,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
float deltaz = General.Map.VisualCamera.AngleZ - dragstartanglez;
if((Math.Abs(deltaxy) + Math.Abs(deltaz)) > DRAG_ANGLE_TOLERANCE)
{
mode.CreateSingleUndo("Change texture offsets");
mode.CreateUndo("Change texture offsets");
// Start drag now
uvdragging = true;
@ -541,46 +579,46 @@ namespace CodeImp.DoomBuilder.BuilderModes
if((Math.Sign(dragdeltaz.x) < 0) || (Math.Sign(dragdeltaz.y) < 0) || (Math.Sign(dragdeltaz.z) < 0)) offsety = -offsety;
// Apply offsets
Sidedef.OffsetX = startoffsetx - (int)Math.Round(offsetx);
Sidedef.OffsetY = startoffsety + (int)Math.Round(offsety);
int newoffsetx = startoffsetx - (int)Math.Round(offsetx);
int newoffsety = startoffsety + (int)Math.Round(offsety);
mode.ApplyTextureOffsetChange(prevoffsetx - newoffsetx, prevoffsety - newoffsety);
prevoffsetx = newoffsetx;
prevoffsety = newoffsety;
// Update sidedef geometry
VisualSidedefParts parts = Sector.GetSidedefParts(Sidedef);
if(parts.lower != null) parts.lower.Setup();
if(parts.middledouble != null) parts.middledouble.Setup();
if(parts.middlesingle != null) parts.middlesingle.Setup();
if(parts.upper != null) parts.upper.Setup();
mode.ShowTargetInfo();
}
// Sector brightness change
public virtual void OnChangeTargetBrightness(bool up)
{
// Change brightness
mode.CreateSingleUndo("Change sector brightness", UndoGroup.SectorBrightnessChange, Sector.Sector.FixedIndex);
if(up)
Sector.Sector.Brightness = General.Map.Config.BrightnessLevels.GetNextHigher(Sector.Sector.Brightness);
else
Sector.Sector.Brightness = General.Map.Config.BrightnessLevels.GetNextLower(Sector.Sector.Brightness);
mode.SetActionResult("Changed sector brightness to " + Sector.Sector.Brightness + ".");
Sector.Sector.UpdateCache();
// Rebuild sector
Sector.Changed = true;
// Go for all things in this sector
foreach(Thing t in General.Map.Map.Things)
if(!Sector.Changed)
{
if(t.Sector == Sector.Sector)
// Change brightness
mode.CreateUndo("Change sector brightness", UndoGroup.SectorBrightnessChange, Sector.Sector.FixedIndex);
if(up)
Sector.Sector.Brightness = General.Map.Config.BrightnessLevels.GetNextHigher(Sector.Sector.Brightness);
else
Sector.Sector.Brightness = General.Map.Config.BrightnessLevels.GetNextLower(Sector.Sector.Brightness);
mode.SetActionResult("Changed sector brightness to " + Sector.Sector.Brightness + ".");
Sector.Sector.UpdateCache();
// Rebuild sector
Sector.Changed = true;
// Go for all things in this sector
foreach(Thing t in General.Map.Map.Things)
{
if(mode.VisualThingExists(t))
if(t.Sector == Sector.Sector)
{
// Update thing
BaseVisualThing vt = (mode.GetVisualThing(t) as BaseVisualThing);
vt.Changed = true;
if(mode.VisualThingExists(t))
{
// Update thing
BaseVisualThing vt = (mode.GetVisualThing(t) as BaseVisualThing);
vt.Changed = true;
}
}
}
}
@ -590,7 +628,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
public virtual void OnChangeTextureOffset(int horizontal, int vertical)
{
if((General.Map.UndoRedo.NextUndo == null) || (General.Map.UndoRedo.NextUndo.TicketID != undoticket))
undoticket = mode.CreateSingleUndo("Change texture offsets");
undoticket = mode.CreateUndo("Change texture offsets");
// Apply offsets
Sidedef.OffsetX -= horizontal;
@ -600,10 +638,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Update sidedef geometry
VisualSidedefParts parts = Sector.GetSidedefParts(Sidedef);
if(parts.lower != null) parts.lower.Setup();
if(parts.middledouble != null) parts.middledouble.Setup();
if(parts.middlesingle != null) parts.middlesingle.Setup();
if(parts.upper != null) parts.upper.Setup();
parts.SetupAllParts();
}
#endregion

View file

@ -77,9 +77,13 @@ namespace CodeImp.DoomBuilder.BuilderModes
// We keep these to determine if we need to make a new undo level
private bool selectionchanged;
private Action lastaction;
private Actions.Action lastaction;
private VisualActionResult actionresult;
private bool undocreated;
// List of selected objects when an action is performed
private List<IVisualEventReceiver> selectedobjects;
#endregion
#region ================== Properties
@ -121,32 +125,51 @@ namespace CodeImp.DoomBuilder.BuilderModes
#region ================== Methods
// This is called before an action is performed
private void PreAction(string multiundodescription, bool multiseparateundo, UndoGroup singleundogroup)
private void PreAction(bool groupmultiselectionundo)
{
int undogrouptag = 0;
actionresult = new VisualActionResult();
PickTargetUnlocked();
// If the action is not performed on a selected object, clear the
// current selection and make a temporary selection for the target.
if(!target.picked.Selected)
if((target.picked != null) && !target.picked.Selected)
{
// Single object, no selection
singleselection = true;
ClearSelection();
target.picked.Selected = true;
undocreated = false;
}
else
{
singleselection = false;
// Check if we should make a new undo level
// We don't want to do this if this is the same action with the same
// selection and the action wants to group the undo levels
if((lastaction != General.Actions.Current) || selectionchanged || multiseparateundo)
if((lastaction != General.Actions.Current) || selectionchanged || !groupmultiselectionundo)
{
General.Map.UndoRedo.CreateUndo(multiundodescription, UndoGroup.None, 0);
// We want to create a new undo level, but not just yet
undocreated = false;
}
else
{
// We don't want to make a new undo level (changes will be combined)
undocreated = true;
}
}
MakeSelectedObjectsList();
}
// Called before an action is performed. This does not make an undo level or change selection.
private void PreActionNoChange()
{
actionresult = new VisualActionResult();
singleselection = false;
undocreated = false;
MakeSelectedObjectsList();
}
// This is called after an action is performed
@ -158,6 +181,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
lastaction = General.Actions.Current;
selectionchanged = false;
if(singleselection)
ClearSelection();
UpdateChangedObjects();
ShowTargetInfo();
}
@ -177,22 +203,55 @@ namespace CodeImp.DoomBuilder.BuilderModes
// This creates an undo, when only a single selection is made
// When a multi-selection is made, the undo is created by the PreAction function
public int CreateSingleUndo(string description, UndoGroup group, int grouptag)
public int CreateUndo(string description, UndoGroup group, int grouptag)
{
if(singleselection)
return General.Map.UndoRedo.CreateUndo(description, group, grouptag);
if(!undocreated)
{
undocreated = true;
if(singleselection)
return General.Map.UndoRedo.CreateUndo(description, group, grouptag);
else
return General.Map.UndoRedo.CreateUndo(description, UndoGroup.None, 0);
}
else
{
return 0;
}
}
// This creates an undo, when only a single selection is made
// When a multi-selection is made, the undo is created by the PreAction function
public int CreateSingleUndo(string description)
public int CreateUndo(string description)
{
if(singleselection)
return General.Map.UndoRedo.CreateUndo(description);
else
return 0;
return CreateUndo(description, UndoGroup.None, 0);
}
// This makes a list of the selected object
private void MakeSelectedObjectsList()
{
// Make list of selected objects
selectedobjects = new List<IVisualEventReceiver>();
foreach(KeyValuePair<Sector, VisualSector> vs in allsectors)
{
BaseVisualSector bvs = (BaseVisualSector)vs.Value;
if((bvs.Floor != null) && bvs.Floor.Selected) selectedobjects.Add(bvs.Floor);
if((bvs.Ceiling != null) && bvs.Ceiling.Selected) selectedobjects.Add(bvs.Ceiling);
foreach(Sidedef sd in vs.Key.Sidedefs)
{
List<VisualGeometry> sidedefgeos = bvs.GetSidedefGeometry(sd);
foreach(VisualGeometry sdg in sidedefgeos)
{
if(sdg.Selected) selectedobjects.Add((sdg as IVisualEventReceiver));
}
}
}
foreach(KeyValuePair<Thing, VisualThing> vt in allthings)
{
BaseVisualThing bvt = (BaseVisualThing)vt.Value;
if(bvt.Selected) selectedobjects.Add(bvt);
}
}
// This creates a visual sector
@ -424,11 +483,106 @@ namespace CodeImp.DoomBuilder.BuilderModes
#endregion
#region ================== Action Assist
// Because some actions can only be called on a single (the targeted) object because
// they show a dialog window or something, these functions help applying the result
// to all compatible selected objects.
// Apply texture offsets
public void ApplyTextureOffsetChange(int dx, int dy)
{
foreach(IVisualEventReceiver i in selectedobjects)
{
i.OnChangeTextureOffset(dx, dy);
}
}
// Apply upper unpegged flag
public void ApplyUpperUnpegged(bool set)
{
foreach(IVisualEventReceiver i in selectedobjects)
{
i.ApplyUpperUnpegged(set);
}
}
// Apply lower unpegged flag
public void ApplyLowerUnpegged(bool set)
{
foreach(IVisualEventReceiver i in selectedobjects)
{
i.ApplyLowerUnpegged(set);
}
}
// Apply texture change
public void ApplySelectTexture(string texture, bool flat)
{
if(General.Map.Config.MixTexturesFlats)
{
// Apply on all compatible types
foreach(IVisualEventReceiver i in selectedobjects)
{
i.ApplyTexture(texture);
}
}
else
{
// We don't want to mix textures and flats, so apply only on the same type
foreach(IVisualEventReceiver i in selectedobjects)
{
if(((i is BaseVisualGeometrySector) && flat) ||
((i is BaseVisualGeometrySidedef) && !flat))
{
i.ApplyTexture(texture);
}
}
}
}
// This returns all selected sectors
public List<Sector> GetSelectedSectors()
{
List<Sector> sectors = new List<Sector>();
foreach(IVisualEventReceiver i in selectedobjects)
{
if(i is BaseVisualGeometrySector) sectors.Add((i as BaseVisualGeometrySector).Sector.Sector);
}
return sectors;
}
// This returns all selected linedefs
public List<Linedef> GetSelectedLinedefs()
{
List<Linedef> linedefs = new List<Linedef>();
foreach(IVisualEventReceiver i in selectedobjects)
{
if(i is BaseVisualGeometrySidedef) linedefs.Add((i as BaseVisualGeometrySidedef).Sidedef.Line);
}
return linedefs;
}
// This returns all selected things
public List<Thing> GetSelectedThings()
{
List<Thing> things = new List<Thing>();
foreach(IVisualEventReceiver i in selectedobjects)
{
if(i is BaseVisualThing) things.Add((i as BaseVisualThing).Thing);
}
return things;
}
#endregion
#region ================== Actions
[BeginAction("clearselection", BaseAction = true)]
public void ClearSelection()
{
selectedobjects = new List<IVisualEventReceiver>();
foreach(KeyValuePair<Sector, VisualSector> vs in allsectors)
{
BaseVisualSector bvs = (BaseVisualSector)vs.Value;
@ -454,68 +608,66 @@ namespace CodeImp.DoomBuilder.BuilderModes
[BeginAction("visualselect", BaseAction = true)]
public void BeginSelect()
{
PreActionNoChange();
PickTargetUnlocked();
if(target.picked != null) (target.picked as IVisualEventReceiver).OnSelectBegin();
UpdateChangedObjects();
PostAction();
}
[EndAction("visualselect", BaseAction = true)]
public void EndSelect()
{
PreActionNoChange();
if(target.picked != null) (target.picked as IVisualEventReceiver).OnSelectEnd();
UpdateChangedObjects();
PostAction();
}
[BeginAction("visualedit", BaseAction = true)]
public void BeginEdit()
{
PickTargetUnlocked();
PreAction(false);
if(target.picked != null) (target.picked as IVisualEventReceiver).OnEditBegin();
UpdateChangedObjects();
PostAction();
}
[EndAction("visualedit", BaseAction = true)]
public void EndEdit()
{
PreAction(false);
if(target.picked != null) (target.picked as IVisualEventReceiver).OnEditEnd();
UpdateChangedObjects();
ShowTargetInfo();
PostAction();
}
[BeginAction("raisesector8")]
public void RaiseSector8()
{
PickTargetUnlocked();
if(target.picked != null) (target.picked as IVisualEventReceiver).OnChangeTargetHeight(8);
UpdateChangedObjects();
ShowTargetInfo();
PreAction(true);
foreach(IVisualEventReceiver i in selectedobjects) i.OnChangeTargetHeight(8);
PostAction();
}
[BeginAction("lowersector8")]
public void LowerSector8()
{
PickTargetUnlocked();
if(target.picked != null) (target.picked as IVisualEventReceiver).OnChangeTargetHeight(-8);
UpdateChangedObjects();
ShowTargetInfo();
PreAction(true);
foreach(IVisualEventReceiver i in selectedobjects) i.OnChangeTargetHeight(-8);
PostAction();
}
[BeginAction("raisesector1")]
public void RaiseSector1()
{
PickTargetUnlocked();
if(target.picked != null) (target.picked as IVisualEventReceiver).OnChangeTargetHeight(1);
UpdateChangedObjects();
ShowTargetInfo();
PreAction(true);
foreach(IVisualEventReceiver i in selectedobjects) i.OnChangeTargetHeight(1);
PostAction();
}
[BeginAction("lowersector1")]
public void LowerSector1()
{
PickTargetUnlocked();
if(target.picked != null) (target.picked as IVisualEventReceiver).OnChangeTargetHeight(-1);
UpdateChangedObjects();
ShowTargetInfo();
PreAction(true);
foreach(IVisualEventReceiver i in selectedobjects) i.OnChangeTargetHeight(-1);
PostAction();
}
[BeginAction("showvisualthings")]
@ -528,163 +680,149 @@ namespace CodeImp.DoomBuilder.BuilderModes
[BeginAction("raisebrightness8")]
public void RaiseBrightness8()
{
PickTargetUnlocked();
if(target.picked != null) (target.picked as IVisualEventReceiver).OnChangeTargetBrightness(true);
UpdateChangedObjects();
ShowTargetInfo();
PreAction(true);
foreach(IVisualEventReceiver i in selectedobjects) i.OnChangeTargetBrightness(true);
PostAction();
}
[BeginAction("lowerbrightness8")]
public void LowerBrightness8()
{
PickTargetUnlocked();
if(target.picked != null) (target.picked as IVisualEventReceiver).OnChangeTargetBrightness(false);
UpdateChangedObjects();
ShowTargetInfo();
PreAction(true);
foreach(IVisualEventReceiver i in selectedobjects) i.OnChangeTargetBrightness(false);
PostAction();
}
[BeginAction("movetextureleft")]
public void MoveTextureLeft1()
{
PickTargetUnlocked();
if(target.picked != null) (target.picked as IVisualEventReceiver).OnChangeTextureOffset(-1, 0);
UpdateChangedObjects();
ShowTargetInfo();
PreAction(true);
foreach(IVisualEventReceiver i in selectedobjects) i.OnChangeTextureOffset(-1, 0);
PostAction();
}
[BeginAction("movetextureright")]
public void MoveTextureRight1()
{
PickTargetUnlocked();
if(target.picked != null) (target.picked as IVisualEventReceiver).OnChangeTextureOffset(1, 0);
UpdateChangedObjects();
ShowTargetInfo();
PreAction(true);
foreach(IVisualEventReceiver i in selectedobjects) i.OnChangeTextureOffset(1, 0);
PostAction();
}
[BeginAction("movetextureup")]
public void MoveTextureUp1()
{
PickTargetUnlocked();
if(target.picked != null) (target.picked as IVisualEventReceiver).OnChangeTextureOffset(0, -1);
UpdateChangedObjects();
ShowTargetInfo();
PreAction(true);
foreach(IVisualEventReceiver i in selectedobjects) i.OnChangeTextureOffset(0, -1);
PostAction();
}
[BeginAction("movetexturedown")]
public void MoveTextureDown1()
{
PickTargetUnlocked();
if(target.picked != null) (target.picked as IVisualEventReceiver).OnChangeTextureOffset(0, 1);
UpdateChangedObjects();
ShowTargetInfo();
PreAction(true);
foreach(IVisualEventReceiver i in selectedobjects) i.OnChangeTextureOffset(0, 1);
PostAction();
}
[BeginAction("movetextureleft8")]
public void MoveTextureLeft8()
{
PickTargetUnlocked();
if(target.picked != null) (target.picked as IVisualEventReceiver).OnChangeTextureOffset(-8, 0);
UpdateChangedObjects();
ShowTargetInfo();
PreAction(true);
foreach(IVisualEventReceiver i in selectedobjects) i.OnChangeTextureOffset(-8, 0);
PostAction();
}
[BeginAction("movetextureright8")]
public void MoveTextureRight8()
{
PickTargetUnlocked();
if(target.picked != null) (target.picked as IVisualEventReceiver).OnChangeTextureOffset(8, 0);
UpdateChangedObjects();
ShowTargetInfo();
PreAction(true);
foreach(IVisualEventReceiver i in selectedobjects) i.OnChangeTextureOffset(8, 0);
PostAction();
}
[BeginAction("movetextureup8")]
public void MoveTextureUp8()
{
PickTargetUnlocked();
if(target.picked != null) (target.picked as IVisualEventReceiver).OnChangeTextureOffset(0, -8);
UpdateChangedObjects();
ShowTargetInfo();
PreAction(true);
foreach(IVisualEventReceiver i in selectedobjects) i.OnChangeTextureOffset(0, -8);
PostAction();
}
[BeginAction("movetexturedown8")]
public void MoveTextureDown8()
{
PickTargetUnlocked();
if(target.picked != null) (target.picked as IVisualEventReceiver).OnChangeTextureOffset(0, 8);
UpdateChangedObjects();
ShowTargetInfo();
PreAction(true);
foreach(IVisualEventReceiver i in selectedobjects) i.OnChangeTextureOffset(0, 8);
PostAction();
}
[BeginAction("textureselect")]
public void TextureSelect()
{
PickTargetUnlocked();
PreAction(false);
renderer.SetCrosshairBusy(true);
General.Interface.RedrawDisplay();
if(target.picked != null) (target.picked as IVisualEventReceiver).OnSelectTexture();
UpdateChangedObjects();
renderer.SetCrosshairBusy(false);
ShowTargetInfo();
PostAction();
}
[BeginAction("texturecopy")]
public void TextureCopy()
{
PickTargetUnlocked();
PreActionNoChange();
if(target.picked != null) (target.picked as IVisualEventReceiver).OnCopyTexture();
UpdateChangedObjects();
ShowTargetInfo();
PostAction();
}
[BeginAction("texturepaste")]
public void TexturePaste()
{
PickTargetUnlocked();
if(target.picked != null) (target.picked as IVisualEventReceiver).OnPasteTexture();
UpdateChangedObjects();
ShowTargetInfo();
PreAction(false);
foreach(IVisualEventReceiver i in selectedobjects) i.OnPasteTexture();
PostAction();
}
[BeginAction("visualautoalignx")]
public void TextureAutoAlignX()
{
PickTargetUnlocked();
PreAction(false);
renderer.SetCrosshairBusy(true);
General.Interface.RedrawDisplay();
if(target.picked != null) (target.picked as IVisualEventReceiver).OnTextureAlign(true, false);
UpdateChangedObjects();
renderer.SetCrosshairBusy(false);
ShowTargetInfo();
PostAction();
}
[BeginAction("visualautoaligny")]
public void TextureAutoAlignY()
{
PickTargetUnlocked();
PreAction(false);
renderer.SetCrosshairBusy(true);
General.Interface.RedrawDisplay();
if(target.picked != null) (target.picked as IVisualEventReceiver).OnTextureAlign(false, true);
UpdateChangedObjects();
renderer.SetCrosshairBusy(false);
ShowTargetInfo();
PostAction();
}
[BeginAction("toggleupperunpegged")]
public void ToggleUpperUnpegged()
{
PickTargetUnlocked();
PreAction(false);
if(target.picked != null) (target.picked as IVisualEventReceiver).OnToggleUpperUnpegged();
UpdateChangedObjects();
ShowTargetInfo();
PostAction();
}
[BeginAction("togglelowerunpegged")]
public void ToggleLowerUnpegged()
{
PickTargetUnlocked();
PreAction(false);
if(target.picked != null) (target.picked as IVisualEventReceiver).OnToggleLowerUnpegged();
UpdateChangedObjects();
ShowTargetInfo();
PostAction();
}
[BeginAction("togglegravity")]
@ -706,73 +844,65 @@ namespace CodeImp.DoomBuilder.BuilderModes
[BeginAction("resettexture")]
public void ResetTexture()
{
PickTargetUnlocked();
if(target.picked != null) (target.picked as IVisualEventReceiver).OnResetTextureOffset();
UpdateChangedObjects();
ShowTargetInfo();
PreAction(true);
foreach(IVisualEventReceiver i in selectedobjects) i.OnResetTextureOffset();
PostAction();
}
[BeginAction("floodfilltextures")]
public void FloodfillTextures()
{
PickTargetUnlocked();
PreAction(false);
if(target.picked != null) (target.picked as IVisualEventReceiver).OnTextureFloodfill();
UpdateChangedObjects();
ShowTargetInfo();
PostAction();
}
[BeginAction("texturecopyoffsets")]
public void TextureCopyOffsets()
{
PickTargetUnlocked();
PreActionNoChange();
if(target.picked != null) (target.picked as IVisualEventReceiver).OnCopyTextureOffsets();
UpdateChangedObjects();
ShowTargetInfo();
PostAction();
}
[BeginAction("texturepasteoffsets")]
public void TexturePasteOffsets()
{
PickTargetUnlocked();
if(target.picked != null) (target.picked as IVisualEventReceiver).OnPasteTextureOffsets();
UpdateChangedObjects();
ShowTargetInfo();
PreAction(false);
foreach(IVisualEventReceiver i in selectedobjects) i.OnPasteTextureOffsets();
PostAction();
}
[BeginAction("copyproperties")]
public void CopyProperties()
{
PickTargetUnlocked();
PreActionNoChange();
if(target.picked != null) (target.picked as IVisualEventReceiver).OnCopyProperties();
UpdateChangedObjects();
ShowTargetInfo();
PostAction();
}
[BeginAction("pasteproperties")]
public void PasteProperties()
{
PickTargetUnlocked();
if(target.picked != null) (target.picked as IVisualEventReceiver).OnPasteProperties();
UpdateChangedObjects();
ShowTargetInfo();
PreAction(false);
foreach(IVisualEventReceiver i in selectedobjects) i.OnPasteProperties();
PostAction();
}
[BeginAction("insertitem", BaseAction = true)]
public void Insert()
{
PickTargetUnlocked();
if(target.picked != null) (target.picked as IVisualEventReceiver).OnInsert();
UpdateChangedObjects();
ShowTargetInfo();
PreAction(false);
foreach(IVisualEventReceiver i in selectedobjects) i.OnInsert();
PostAction();
}
[BeginAction("deleteitem", BaseAction = true)]
public void Delete()
{
PickTargetUnlocked();
if(target.picked != null) (target.picked as IVisualEventReceiver).OnDelete();
UpdateChangedObjects();
ShowTargetInfo();
PreAction(false);
foreach(IVisualEventReceiver i in selectedobjects) i.OnDelete();
PostAction();
}
#endregion

View file

@ -371,6 +371,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
public virtual void OnTextureFloodfill() { }
public virtual void OnInsert() { }
public virtual void OnDelete() { }
public virtual void ApplyTexture(string texture) { }
public virtual void ApplyUpperUnpegged(bool set) { }
public virtual void ApplyLowerUnpegged(bool set) { }
// Return texture name
public virtual string GetTextureName() { return ""; }
@ -394,7 +397,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
if(BuilderPlug.Me.CopiedThingProps != null)
{
mode.CreateSingleUndo("Paste thing properties");
mode.CreateUndo("Paste thing properties");
mode.SetActionResult("Pasted thing properties.");
BuilderPlug.Me.CopiedThingProps.Apply(Thing);
Thing.UpdateConfiguration();
@ -411,10 +414,17 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
if(General.Interface.IsActiveWindow)
{
List<Thing> things = new List<Thing>();
things.Add(this.Thing);
List<Thing> things = mode.GetSelectedThings();
DialogResult result = General.Interface.ShowEditThings(things);
if(result == DialogResult.OK) this.Rebuild();
if(result == DialogResult.OK)
{
foreach(Thing t in things)
{
VisualThing vt = mode.GetVisualThing(t);
if(vt != null)
(vt as BaseVisualThing).Changed = true;
}
}
}
}
}
@ -425,7 +435,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
if(General.Map.FormatInterface.HasThingHeight)
{
if((General.Map.UndoRedo.NextUndo == null) || (General.Map.UndoRedo.NextUndo.TicketID != undoticket))
undoticket = mode.CreateSingleUndo("Change thing height");
undoticket = mode.CreateUndo("Change thing height");
Thing.Move(Thing.Position + new Vector3D(0.0f, 0.0f, (float)amount));

View file

@ -62,6 +62,11 @@ namespace CodeImp.DoomBuilder.BuilderModes
void OnProcess(double deltatime);
void OnInsert();
void OnDelete();
// Assist functions
void ApplyTexture(string texture);
void ApplyUpperUnpegged(bool set);
void ApplyLowerUnpegged(bool set);
// Other methods
string GetTextureName();

View file

@ -137,7 +137,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
if(BuilderPlug.Me.CopiedFlat != null)
{
mode.CreateSingleUndo("Paste ceiling " + BuilderPlug.Me.CopiedFlat);
mode.CreateUndo("Paste ceiling " + BuilderPlug.Me.CopiedFlat);
mode.SetActionResult("Pasted flat " + BuilderPlug.Me.CopiedFlat + " on ceiling.");
SetTexture(BuilderPlug.Me.CopiedFlat);
this.Setup();
@ -147,7 +147,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
// This changes the height
protected override void ChangeHeight(int amount)
{
mode.CreateSingleUndo("Change ceiling height", UndoGroup.CeilingHeightChange, this.Sector.Sector.FixedIndex);
mode.CreateUndo("Change ceiling height", UndoGroup.CeilingHeightChange, this.Sector.Sector.FixedIndex);
this.Sector.Sector.CeilHeight += amount;
mode.SetActionResult("Changed ceiling height to " + Sector.Sector.CeilHeight + ".");
}

View file

@ -124,7 +124,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
if(BuilderPlug.Me.CopiedFlat != null)
{
mode.CreateSingleUndo("Paste floor " + BuilderPlug.Me.CopiedFlat);
mode.CreateUndo("Paste floor " + BuilderPlug.Me.CopiedFlat);
mode.SetActionResult("Pasted flat " + BuilderPlug.Me.CopiedFlat + " on floor.");
SetTexture(BuilderPlug.Me.CopiedFlat);
this.Setup();
@ -134,7 +134,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
// This changes the height
protected override void ChangeHeight(int amount)
{
mode.CreateSingleUndo("Change floor height", UndoGroup.FloorHeightChange, this.Sector.Sector.FixedIndex);
mode.CreateUndo("Change floor height", UndoGroup.FloorHeightChange, this.Sector.Sector.FixedIndex);
this.Sector.Sector.FloorHeight += amount;
mode.SetActionResult("Changed floor height to " + Sector.Sector.FloorHeight + ".");
}

View file

@ -61,5 +61,14 @@ namespace CodeImp.DoomBuilder.BuilderModes
this.middledouble = null;
this.middlesingle = m;
}
// This calls Setup() on all parts
public void SetupAllParts()
{
if(lower != null) lower.Setup();
if(middledouble != null) middledouble.Setup();
if(middlesingle != null) middlesingle.Setup();
if(upper != null) upper.Setup();
}
}
}