mirror of
https://git.do.srb2.org/STJr/ZoneBuilder.git
synced 2024-11-10 06:41:49 +00:00
Added 3 map geometry dragging modes (used when applying Drag Vertices/Linedefs/Sectors modes and Edit Selection mode):
- "Merge Dragged Vertices Only". Only vertex-line intersections will be processed (DB2 mode). - "Merge Dragged Geometry". Geometry merging will be performed. - "Replace with Dragged Geometry". Dragged geometry will replace underlaying geometry. You can switch between these using 3 new actions, top toolbar buttons and Edit menu buttons. Changed: activating the same 2D mode repeatedly now toggles View modes. Renamed "Merge Geometry" action/menu item to "Snap to Geometry". More fixes to vertex/linedef/sector dragging logic. Updated ZDoom_DECORATE.cfg.
This commit is contained in:
parent
14e372cb91
commit
cdfe94bfa4
22 changed files with 575 additions and 114 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -462,3 +462,4 @@
|
|||
/Build/D3DImm.dll
|
||||
/Build/D3D9.dll
|
||||
/Build/D3D8.dll
|
||||
/UpgradeLog.htm
|
||||
|
|
|
@ -75,21 +75,21 @@ keywords
|
|||
A_ClearLastHeard = "A_ClearLastHeard";
|
||||
A_ClearSoundTarget = "A_ClearSoundTarget";
|
||||
A_ClearTarget = "A_ClearTarget";
|
||||
A_DamageChildren = "A_DamageChildren(int amount[, str damagetype = \"None\"[, int flags = 0[, str filter = \"None\"[, str species = \"None\"]]]])\namount: amount of damage to inflict. Use a negative value to heal.\ndamagetype: the type of damage to inflict.\nflags: DMSS flags.\nfilter: the actor class to damage.\nspecies: the actor species to damage.";
|
||||
A_DamageMaster = "A_DamageMaster(int amount[, str damagetype = \"None\"[, int flags = 0[, str filter = \"None\"[, str species = \"None\"]]]])\namount: amount of damage to inflict. Use a negative value to heal.\ndamagetype: the type of damage to inflict.\nflags: DMSS flags.\nfilter: the actor class to damage.\nspecies: the actor species to damage.";
|
||||
A_DamageSelf = "A_DamageSelf(int amount[, str damagetype = \"None\"[, int flags = 0[, str filter = \"None\"[, str species = \"None\"]]]])\namount: amount of damage to inflict. Use a negative value to heal.\ndamagetype: the type of damage to inflict.\nflags: DMSS flags.\nfilter: the actor class to damage.\nspecies: the actor species to damage.";
|
||||
A_DamageSiblings = "A_DamageSiblings(int amount[, str damagetype = \"None\"[, int flags = 0[, str filter = \"None\"[, str species = \"None\"]]]])\namount: amount of damage to inflict. Use a negative value to heal.\ndamagetype: the type of damage to inflict.\nflags: DMSS flags.\nfilter: the actor class to damage.\nspecies: the actor species to damage.";
|
||||
A_DamageTarget = "A_DamageTarget(int amount[, str damagetype = \"None\"[, int flags = 0[, str filter = \"None\"[, str species = \"None\"]]]])\namount: amount of damage to inflict. Use a negative value to heal.\ndamagetype: the type of damage to inflict.\nflags: DMSS flags.\nfilter: the actor class to damage.\nspecies: the actor species to damage.";
|
||||
A_DamageTracer = "A_DamageTracer(int amount[, str damagetype = \"None\"[, int flags = 0[, str filter = \"None\"[, str species = \"None\"]]]])\namount: amount of damage to inflict. Use a negative value to heal.\ndamagetype: the type of damage to inflict.\nflags: DMSS flags.\nfilter: the actor class to damage.\nspecies: the actor species to damage.";
|
||||
A_DamageChildren = "A_DamageChildren(int amount[, str damagetype = \"None\"[, int flags = 0[, str filter = \"None\"[, str species = \"None\"[, int src = AAPTR_DEFAULT[, int inflictor = AAPTR_DEFAULT]]]]]])\namount: amount of damage to inflict. Use a negative value to heal.\ndamagetype: the type of damage to inflict.\nflags: DMSS flags.\nfilter: the actor class to damage.\nspecies: the actor species to damage.";
|
||||
A_DamageMaster = "A_DamageMaster(int amount[, str damagetype = \"None\"[, int flags = 0[, str filter = \"None\"[, str species = \"None\"[, int src = AAPTR_DEFAULT[, int inflictor = AAPTR_DEFAULT]]]]]])\namount: amount of damage to inflict. Use a negative value to heal.\ndamagetype: the type of damage to inflict.\nflags: DMSS flags.\nfilter: the actor class to damage.\nspecies: the actor species to damage.";
|
||||
A_DamageSelf = "A_DamageSelf(int amount[, str damagetype = \"None\"[, int flags = 0[, str filter = \"None\"[, str species = \"None\"[, int src = AAPTR_DEFAULT[, int inflictor = AAPTR_DEFAULT]]]]]])\namount: amount of damage to inflict. Use a negative value to heal.\ndamagetype: the type of damage to inflict.\nflags: DMSS flags.\nfilter: the actor class to damage.\nspecies: the actor species to damage.";
|
||||
A_DamageSiblings = "A_DamageSiblings(int amount[, str damagetype = \"None\"[, int flags = 0[, str filter = \"None\"[, str species = \"None\"[, int src = AAPTR_DEFAULT[, int inflictor = AAPTR_DEFAULT]]]]]])\namount: amount of damage to inflict. Use a negative value to heal.\ndamagetype: the type of damage to inflict.\nflags: DMSS flags.\nfilter: the actor class to damage.\nspecies: the actor species to damage.";
|
||||
A_DamageTarget = "A_DamageTarget(int amount[, str damagetype = \"None\"[, int flags = 0[, str filter = \"None\"[, str species = \"None\"[, int src = AAPTR_DEFAULT[, int inflictor = AAPTR_DEFAULT]]]]]])\namount: amount of damage to inflict. Use a negative value to heal.\ndamagetype: the type of damage to inflict.\nflags: DMSS flags.\nfilter: the actor class to damage.\nspecies: the actor species to damage.";
|
||||
A_DamageTracer = "A_DamageTracer(int amount[, str damagetype = \"None\"[, int flags = 0[, str filter = \"None\"[, str species = \"None\"[, int src = AAPTR_DEFAULT[, int inflictor = AAPTR_DEFAULT]]]]]])\namount: amount of damage to inflict. Use a negative value to heal.\ndamagetype: the type of damage to inflict.\nflags: DMSS flags.\nfilter: the actor class to damage.\nspecies: the actor species to damage.";
|
||||
A_Die = "A_Die[(str damagetype = \"none\")]";
|
||||
A_FaceTarget = "A_FaceTarget[(float angle = 0.0[, float pitch = 270.0])]\nA_FaceTarget([float max_turn = 0.0[, float max_pitch = 270.0[, float ang_offset = 0.0[, float pitch_offset = 0.0[, int flags = 0[, float z_add = 0.0]]]]]])";
|
||||
A_FaceMaster = "A_FaceMaster[(float angle = 0.0[, float pitch = 270.0])]\nA_FaceMaster([float max_turn = 0.0[, float max_pitch = 270.0[, float ang_offset = 0.0[, float pitch_offset = 0.0[, int flags = 0[, float z_add = 0.0]]]]]])";
|
||||
A_FastChase = "A_FastChase";
|
||||
A_KillChildren = "A_KillChildren[(str damagetype = \"None\"[, int flags = 0[, str filter = \"None\[, str species = \"None\]]])]\ndamagetype: if the actor dies, the actor will enter a death state based on damagetype if present (or pain state if using NODAMAGE).\nflags: KILS flags.\nfilter: the actor class to damage.\nspecies: the actor species to damage.";
|
||||
A_KillMaster = "A_KillMaster[(str damagetype = \"None\"[, int flags = 0[, str filter = \"None\"[, str species = \"None\"]]])]\ndamagetype: if the actor dies, the actor will enter a death state based on damagetype if present (or pain state if using NODAMAGE).\nflags: KILS flags.\nfilter: the actor class to damage.\nspecies: the actor species to damage.";
|
||||
A_KillSiblings = "A_KillSiblings[(str damagetype = \"None\"[, int flags = 0[, str filter = \"None\"[, str species = \"None\"]]])]\ndamagetype: if the actor dies, the actor will enter a death state based on damagetype if present (or pain state if using NODAMAGE).\nflags: KILS flags.\nfilter: the actor class to damage.\nspecies: the actor species to damage.";
|
||||
A_KillTarget = "A_KillTarget[(str damagetype = \"None\"[, int flags = 0[, str filter = \"None\"[, str species = \"None\"]]])]\ndamagetype: if the actor dies, the actor will enter a death state based on damagetype if present (or pain state if using NODAMAGE).\nflags: KILS flags.\nfilter: the actor class to damage.\nspecies: the actor species to damage.";
|
||||
A_KillTracer = "A_KillTracer[(str damagetype = \"None\"[, int flags = 0[, str filter = \"None\"[, str species = \"None\"]]])]\ndamagetype: if the actor dies, the actor will enter a death state based on damagetype if present (or pain state if using NODAMAGE).\nflags: KILS flags.\nfilter: the actor class to damage.\nspecies: the actor species to damage.";
|
||||
A_KillChildren = "A_KillChildren[(str damagetype = \"None\"[, int flags = 0[, str filter = \"None\[, str species = \"None\"[, int src = AAPTR_DEFAULT[, int inflictor = AAPTR_DEFAULT]]]]])]\ndamagetype: if the actor dies, the actor will enter a death state based on damagetype if present (or pain state if using NODAMAGE).\nflags: KILS flags.\nfilter: the actor class to damage.\nspecies: the actor species to damage.";
|
||||
A_KillMaster = "A_KillMaster[(str damagetype = \"None\"[, int flags = 0[, str filter = \"None\"[, str species = \"None\"[, int src = AAPTR_DEFAULT[, int inflictor = AAPTR_DEFAULT]]]]])]\ndamagetype: if the actor dies, the actor will enter a death state based on damagetype if present (or pain state if using NODAMAGE).\nflags: KILS flags.\nfilter: the actor class to damage.\nspecies: the actor species to damage.";
|
||||
A_KillSiblings = "A_KillSiblings[(str damagetype = \"None\"[, int flags = 0[, str filter = \"None\"[, str species = \"None\"[, int src = AAPTR_DEFAULT[, int inflictor = AAPTR_DEFAULT]]]]])]\ndamagetype: if the actor dies, the actor will enter a death state based on damagetype if present (or pain state if using NODAMAGE).\nflags: KILS flags.\nfilter: the actor class to damage.\nspecies: the actor species to damage.";
|
||||
A_KillTarget = "A_KillTarget[(str damagetype = \"None\"[, int flags = 0[, str filter = \"None\"[, str species = \"None\"[, int src = AAPTR_DEFAULT[, int inflictor = AAPTR_DEFAULT]]]]])]\ndamagetype: if the actor dies, the actor will enter a death state based on damagetype if present (or pain state if using NODAMAGE).\nflags: KILS flags.\nfilter: the actor class to damage.\nspecies: the actor species to damage.";
|
||||
A_KillTracer = "A_KillTracer[(str damagetype = \"None\"[, int flags = 0[, str filter = \"None\"[, str species = \"None\"[, int src = AAPTR_DEFAULT[, int inflictor = AAPTR_DEFAULT]]]]])]\ndamagetype: if the actor dies, the actor will enter a death state based on damagetype if present (or pain state if using NODAMAGE).\nflags: KILS flags.\nfilter: the actor class to damage.\nspecies: the actor species to damage.";
|
||||
A_Look = "A_Look";
|
||||
A_Look2 = "A_Look2";
|
||||
A_LookEx = "A_LookEx(int flags, float minseedist, float maxseedist, float maxheardist, float fov, state seestate)";
|
||||
|
@ -426,6 +426,7 @@ keywords
|
|||
GetSpawnHealth = "int GetSpawnHealth()";
|
||||
GetZAt = "float GetZAt([float x = 0.0[, float y = 0.0[, float angle = 0.0[, int flags = 0[, int pick_pointer = AAPTR_TARGET]]]]])";
|
||||
GetGibHealth = "int GetGibHealth()";
|
||||
GetCrouchFactor = "float GetCrouchFactor(int ptr = AAPTR_PLAYER1)";
|
||||
}
|
||||
|
||||
properties
|
||||
|
@ -733,7 +734,14 @@ constants
|
|||
AAPTR_TARGET;
|
||||
AAPTR_MASTER;
|
||||
AAPTR_TRACER;
|
||||
AAPTR_PLAYER;
|
||||
AAPTR_PLAYER1;
|
||||
AAPTR_PLAYER2;
|
||||
AAPTR_PLAYER3;
|
||||
AAPTR_PLAYER4;
|
||||
AAPTR_PLAYER5;
|
||||
AAPTR_PLAYER6;
|
||||
AAPTR_PLAYER7;
|
||||
AAPTR_PLAYER8;
|
||||
AAPTR_PLAYER_GETTARGET;
|
||||
AAPTR_PLAYER_GETCONVERSATION;
|
||||
//A_SpawnItemEx flags
|
||||
|
|
|
@ -917,6 +917,7 @@
|
|||
<Compile Include="GZBuilder\Rendering\SizelessVisualThingCage.cs" />
|
||||
<Compile Include="GZBuilder\Rendering\ThingBoundingBox.cs" />
|
||||
<Compile Include="GZBuilder\Data\ThingCopyData.cs" />
|
||||
<Compile Include="Map\MergeGeometryMode.cs" />
|
||||
<Compile Include="Map\SectorBuilder.cs" />
|
||||
<Compile Include="GZBuilder\Rendering\VisualVertexHandle.cs" />
|
||||
<Compile Include="GZBuilder\Geometry\Line3D.cs" />
|
||||
|
@ -1182,6 +1183,9 @@
|
|||
<None Include="Resources\MixedThings.png" />
|
||||
<None Include="Resources\LinedefColorPresets.png" />
|
||||
<EmbeddedResource Include="Resources\MissingSky3D.png" />
|
||||
<None Include="Resources\MergeGeo.png" />
|
||||
<None Include="Resources\MergeGeoClassic.png" />
|
||||
<None Include="Resources\MergeGeoRemoveLines.png" />
|
||||
<Content Include="Resources\Model.png" />
|
||||
<None Include="Resources\ModelDisabled.png" />
|
||||
<None Include="Resources\ModelFiltered.png" />
|
||||
|
|
|
@ -91,6 +91,7 @@ namespace CodeImp.DoomBuilder.Config
|
|||
private bool locatetexturegroup; //mxd
|
||||
private bool keeptexturefilterfocused; //mxd
|
||||
private SplitLineBehavior splitlinebehavior; //mxd
|
||||
private MergeGeometryMode mergegeomode; //mxd
|
||||
private bool usehighlight; //mxd
|
||||
|
||||
//mxd. Script editor settings
|
||||
|
@ -214,6 +215,7 @@ namespace CodeImp.DoomBuilder.Config
|
|||
public bool LocateTextureGroup { get { return locatetexturegroup; } internal set { locatetexturegroup = value; } } //mxd
|
||||
public bool KeepTextureFilterFocused { get { return keeptexturefilterfocused; } internal set { keeptexturefilterfocused = value; } } //mxd
|
||||
public SplitLineBehavior SplitLineBehavior { get { return splitlinebehavior; } set { splitlinebehavior = value; } } //mxd
|
||||
public MergeGeometryMode MergeGeometryMode { get { return mergegeomode; } internal set { mergegeomode = value; } } //mxd
|
||||
|
||||
//mxd. Highlight mode
|
||||
public bool UseHighlight
|
||||
|
@ -369,7 +371,8 @@ namespace CodeImp.DoomBuilder.Config
|
|||
showtexturesizes = cfg.ReadSetting("showtexturesizes", true);
|
||||
locatetexturegroup = cfg.ReadSetting("locatetexturegroup", true); //mxd
|
||||
keeptexturefilterfocused = cfg.ReadSetting("keeptexturefilterfocused", true); //mxd
|
||||
splitlinebehavior = (SplitLineBehavior)General.Clamp(cfg.ReadSetting("splitlinebehavior", 0), 0, 3); //mxd
|
||||
splitlinebehavior = (SplitLineBehavior)General.Clamp(cfg.ReadSetting("splitlinebehavior", 0), 0, Enum.GetValues(typeof(SplitLineBehavior)).Length - 1); //mxd
|
||||
mergegeomode = (MergeGeometryMode)General.Clamp(cfg.ReadSetting("mergegeometrymode", (int)MergeGeometryMode.REPLACE), 0, Enum.GetValues(typeof(MergeGeometryMode)).Length - 1); //mxd
|
||||
usehighlight = cfg.ReadSetting("usehighlight", true); //mxd
|
||||
|
||||
//mxd. Script editor
|
||||
|
@ -494,6 +497,7 @@ namespace CodeImp.DoomBuilder.Config
|
|||
cfg.WriteSetting("locatetexturegroup", locatetexturegroup); //mxd
|
||||
cfg.WriteSetting("keeptexturefilterfocused", keeptexturefilterfocused); //mxd
|
||||
cfg.WriteSetting("splitlinebehavior", (int)splitlinebehavior); //mxd
|
||||
cfg.WriteSetting("mergegeometrymode", (int)mergegeomode); //mxd
|
||||
cfg.WriteSetting("usehighlight", usehighlight); //mxd
|
||||
|
||||
//mxd. Script editor
|
||||
|
|
|
@ -171,14 +171,18 @@ namespace CodeImp.DoomBuilder
|
|||
counter += incrementby;
|
||||
}
|
||||
|
||||
public static void ResetCounter() { ResetCounter(string.Empty); }
|
||||
public static void ResetCounter(string message)
|
||||
{
|
||||
if(message.Contains("%"))
|
||||
message = message.Replace("%", counter.ToString());
|
||||
else
|
||||
message = message.TrimEnd() + ": " + counter;
|
||||
if(!string.IsNullOrEmpty(message))
|
||||
{
|
||||
if(message.Contains("%"))
|
||||
message = message.Replace("%", counter.ToString());
|
||||
else
|
||||
message = message.TrimEnd() + ": " + counter;
|
||||
|
||||
WriteLine(DebugMessageType.SPECIAL, message);
|
||||
WriteLine(DebugMessageType.SPECIAL, message);
|
||||
}
|
||||
|
||||
counter = 0;
|
||||
}
|
||||
|
|
|
@ -633,7 +633,7 @@ namespace CodeImp.DoomBuilder.Editing
|
|||
}
|
||||
|
||||
// This sets the view mode
|
||||
private static void SetViewMode(ViewMode mode)
|
||||
internal static void SetViewMode(ViewMode mode)
|
||||
{
|
||||
General.Map.CRenderer2D.SetViewMode(mode);
|
||||
General.MainWindow.UpdateInterface();
|
||||
|
|
|
@ -17,10 +17,13 @@
|
|||
#region ================== Namespaces
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using CodeImp.DoomBuilder.Actions;
|
||||
using CodeImp.DoomBuilder.Plugins;
|
||||
using CodeImp.DoomBuilder.Rendering;
|
||||
using CodeImp.DoomBuilder.VisualModes;
|
||||
|
||||
#endregion
|
||||
|
@ -160,6 +163,15 @@ namespace CodeImp.DoomBuilder.Editing
|
|||
// Switch back to last classic mode
|
||||
General.Editing.ChangeMode(General.Editing.PreviousClassicMode.Name);
|
||||
}
|
||||
//mxd. The same mode? Switch view modes instead
|
||||
else if(General.Editing.Mode is ClassicMode && General.Editing.Mode.GetType().FullName == type.FullName)
|
||||
{
|
||||
List<ViewMode> vmodes = new List<ViewMode>(Enum.GetValues(typeof(ViewMode)).Cast<ViewMode>());
|
||||
int curmode = vmodes.IndexOf(General.Map.Renderer2D.ViewMode);
|
||||
curmode = (curmode == vmodes.Count - 1 ? 0 : ++curmode);
|
||||
|
||||
ClassicMode.SetViewMode(vmodes[curmode]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create instance
|
||||
|
|
|
@ -1262,8 +1262,8 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
// self intersections for which splits were made above.
|
||||
map.Update(true, false);
|
||||
map.BeginAddRemove();
|
||||
MapSet.SplitLinesByVertices(newlines, intersectverts, MapSet.STITCH_DISTANCE, null, false);
|
||||
MapSet.SplitLinesByVertices(newlines, mergeverts, MapSet.STITCH_DISTANCE, null, false);
|
||||
MapSet.SplitLinesByVertices(newlines, intersectverts, MapSet.STITCH_DISTANCE, null);
|
||||
MapSet.SplitLinesByVertices(newlines, mergeverts, MapSet.STITCH_DISTANCE, null);
|
||||
map.EndAddRemove();
|
||||
|
||||
/***************************************************\
|
||||
|
@ -1330,7 +1330,7 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
// Before this point, the new geometry is not linked with the existing geometry.
|
||||
// Now perform standard geometry stitching to merge the new geometry with the rest
|
||||
// of the map. The marked vertices indicate the new geometry.
|
||||
map.StitchGeometry(false);
|
||||
map.StitchGeometry();
|
||||
map.Update(true, false);
|
||||
|
||||
// Find our new lines again, because they have been merged with the other geometry
|
||||
|
|
|
@ -1989,9 +1989,9 @@ namespace CodeImp.DoomBuilder.Map
|
|||
}
|
||||
|
||||
/// <summary>This filters lines by a rectangular area.</summary>
|
||||
public static List<Linedef> FilterByArea(ICollection<Linedef> lines, ref RectangleF area)
|
||||
public static HashSet<Linedef> FilterByArea(ICollection<Linedef> lines, ref RectangleF area)
|
||||
{
|
||||
List<Linedef> newlines = new List<Linedef>(lines.Count);
|
||||
HashSet<Linedef> newlines = new HashSet<Linedef>();
|
||||
|
||||
// Go for all lines
|
||||
foreach(Linedef l in lines)
|
||||
|
@ -2046,18 +2046,18 @@ namespace CodeImp.DoomBuilder.Map
|
|||
/// <summary>
|
||||
/// Stitches marked geometry with non-marked geometry. Returns false when the operation failed.
|
||||
/// </summary>
|
||||
public bool StitchGeometry() { return StitchGeometry(false); } //mxd. Compatibility
|
||||
public bool StitchGeometry(bool correctsectorrefs)
|
||||
public bool StitchGeometry() { return StitchGeometry(MergeGeometryMode.CLASSIC); } //mxd. Compatibility
|
||||
public bool StitchGeometry(MergeGeometryMode mergemode)
|
||||
{
|
||||
// Find vertices
|
||||
ICollection<Vertex> movingverts = General.Map.Map.GetMarkedVertices(true);
|
||||
ICollection<Vertex> fixedverts = General.Map.Map.GetMarkedVertices(false);
|
||||
HashSet<Vertex> movingverts = new HashSet<Vertex>(General.Map.Map.GetMarkedVertices(true));
|
||||
HashSet<Vertex> fixedverts = new HashSet<Vertex>(General.Map.Map.GetMarkedVertices(false));
|
||||
|
||||
// Find lines that moved during the drag
|
||||
List<Linedef> movinglines = LinedefsFromMarkedVertices(false, true, true);
|
||||
HashSet<Linedef> movinglines = new HashSet<Linedef>(LinedefsFromMarkedVertices(false, true, true));
|
||||
|
||||
// Find all non-moving lines
|
||||
List<Linedef> fixedlines = LinedefsFromMarkedVertices(true, false, false);
|
||||
HashSet<Linedef> fixedlines = new HashSet<Linedef>(LinedefsFromMarkedVertices(true, false, false));
|
||||
|
||||
// Determine area in which we are editing
|
||||
RectangleF editarea = CreateArea(movinglines);
|
||||
|
@ -2076,16 +2076,16 @@ namespace CodeImp.DoomBuilder.Map
|
|||
|
||||
// Split moving lines with unselected vertices
|
||||
ICollection<Vertex> nearbyfixedverts = FilterByArea(fixedverts, ref editarea);
|
||||
if(!SplitLinesByVertices(movinglines, nearbyfixedverts, STITCH_DISTANCE, movinglines, correctsectorrefs))
|
||||
if(!SplitLinesByVertices(movinglines, nearbyfixedverts, STITCH_DISTANCE, movinglines, mergemode))
|
||||
return false;
|
||||
|
||||
// Split non-moving lines with selected vertices
|
||||
fixedlines = FilterByArea(fixedlines, ref editarea);
|
||||
if(!SplitLinesByVertices(fixedlines, movingverts, STITCH_DISTANCE, movinglines, correctsectorrefs))
|
||||
if(!SplitLinesByVertices(fixedlines, movingverts, STITCH_DISTANCE, movinglines, mergemode))
|
||||
return false;
|
||||
|
||||
//mxd. Split moving lines with fixed lines
|
||||
if(!SplitLinesByLines(fixedlines, movinglines, correctsectorrefs)) return false;
|
||||
if(!SplitLinesByLines(fixedlines, movinglines, mergemode)) return false;
|
||||
|
||||
// Remove looped linedefs
|
||||
RemoveLoopedLinedefs(movinglines);
|
||||
|
@ -2093,10 +2093,49 @@ namespace CodeImp.DoomBuilder.Map
|
|||
// Join overlapping lines
|
||||
if(!JoinOverlappingLines(movinglines)) return false;
|
||||
|
||||
//mxd. Remove remaining new verts from dragged shape if possible
|
||||
if(mergemode == MergeGeometryMode.REPLACE)
|
||||
{
|
||||
// Get lines, which belong to dragged sectors
|
||||
HashSet<Sector> draggedsectors = GetSectorsFromLinedefs(movinglines);
|
||||
HashSet<Linedef> sectorlines = new HashSet<Linedef>();
|
||||
foreach(Sector s in draggedsectors)
|
||||
{
|
||||
foreach(Sidedef side in s.Sidedefs)
|
||||
sectorlines.Add(side.Line);
|
||||
}
|
||||
|
||||
HashSet<Vertex> tocheck = new HashSet<Vertex>();
|
||||
|
||||
foreach(Linedef l in sectorlines)
|
||||
{
|
||||
if(l.IsDisposed) continue;
|
||||
if(!movingverts.Contains(l.Start)) tocheck.Add(l.Start);
|
||||
if(!movingverts.Contains(l.End)) tocheck.Add(l.End);
|
||||
}
|
||||
|
||||
// Remove verts, which are not part of initially dragged verts
|
||||
foreach(Vertex v in tocheck)
|
||||
{
|
||||
if(!v.IsDisposed && v.Linedefs.Count == 2)
|
||||
{
|
||||
Linedef ld1 = General.GetByIndex(v.Linedefs, 0);
|
||||
Linedef ld2 = General.GetByIndex(v.Linedefs, 1);
|
||||
|
||||
Vertex v2 = (ld2.Start == v) ? ld2.End : ld2.Start;
|
||||
if(ld1.Start == v) ld1.SetStartVertex(v2); else ld1.SetEndVertex(v2);
|
||||
ld2.Dispose();
|
||||
|
||||
// Trash vertex
|
||||
v.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EndAddRemove();
|
||||
|
||||
//mxd. Correct sector references
|
||||
if(correctsectorrefs)
|
||||
if(mergemode != MergeGeometryMode.CLASSIC)
|
||||
{
|
||||
// Linedefs cache needs to be up to date...
|
||||
Update(true, false);
|
||||
|
@ -2105,6 +2144,11 @@ namespace CodeImp.DoomBuilder.Map
|
|||
List<Linedef> changedlines = LinedefsFromMarkedVertices(false, true, true);
|
||||
CorrectSectorReferences(changedlines, true);
|
||||
CorrectOuterSides(new HashSet<Linedef>(changedlines));
|
||||
|
||||
// Mark only fully selected sectors
|
||||
ClearMarkedSectors(false);
|
||||
HashSet<Sector> changedsectors = GetSectorsFromLinedefs(changedlines);
|
||||
foreach(Sector s in changedsectors) s.Marked = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -2113,6 +2157,9 @@ namespace CodeImp.DoomBuilder.Map
|
|||
//mxd. Shameless SLADEMap::correctSectors ripoff... Corrects/builds sectors for all lines in [lines]
|
||||
private static void CorrectSectorReferences(List<Linedef> lines, bool existing_only)
|
||||
{
|
||||
//DebugConsole.Clear();
|
||||
//DebugConsole.WriteLine("CorrectSectorReferences for " + lines.Count + " lines");
|
||||
|
||||
// Create a list of sidedefs to perform sector creation with
|
||||
List<LinedefSide> edges = new List<LinedefSide>();
|
||||
if(existing_only)
|
||||
|
@ -2152,15 +2199,9 @@ namespace CodeImp.DoomBuilder.Map
|
|||
HashSet<Sector> affectedsectors = new HashSet<Sector>(General.Map.Map.GetSelectedSectors(true));
|
||||
affectedsectors.UnionWith(General.Map.Map.GetUnselectedSectorsFromLinedefs(lines));
|
||||
|
||||
//mxd. Collect their lines
|
||||
HashSet<Linedef> sectorlines = new HashSet<Linedef>();
|
||||
foreach(Sector s in affectedsectors)
|
||||
{
|
||||
foreach(Sidedef side in s.Sidedefs)
|
||||
{
|
||||
if(side.Line != null) sectorlines.Add(side.Line);
|
||||
}
|
||||
}
|
||||
//mxd. Collect their sidedefs
|
||||
HashSet<Sidedef> sectorsides = new HashSet<Sidedef>();
|
||||
foreach(Sector s in affectedsectors) sectorsides.UnionWith(s.Sidedefs);
|
||||
|
||||
// Build sectors
|
||||
SectorBuilder builder = new SectorBuilder();
|
||||
|
@ -2169,6 +2210,7 @@ namespace CodeImp.DoomBuilder.Map
|
|||
foreach(LinedefSide ls in edges)
|
||||
{
|
||||
// Skip if edge is ignored
|
||||
//DebugConsole.WriteLine((ls.Ignore ? "Ignoring line " : "Processing line ") + ls.Line.Index);
|
||||
if(ls.Ignore) continue;
|
||||
|
||||
// Run sector builder on current edge
|
||||
|
@ -2177,13 +2219,15 @@ namespace CodeImp.DoomBuilder.Map
|
|||
// Find any subsequent edges that were part of the sector created
|
||||
bool has_existing_lines = false;
|
||||
bool has_existing_sides = false;
|
||||
bool has_zero_sided_lines = false;
|
||||
bool has_sides_belonging_to_dragged_sectors = false; //mxd
|
||||
//bool has_zero_sided_lines = false;
|
||||
bool has_dragged_sides = false; //mxd
|
||||
List<LinedefSide> edges_in_sector = new List<LinedefSide>();
|
||||
foreach(LinedefSide edge in builder.SectorEdges)
|
||||
{
|
||||
bool line_is_ours = false;
|
||||
if(sectorlines.Contains(edge.Line)) has_sides_belonging_to_dragged_sectors = true; //mxd
|
||||
bool side_exists = (edge.Front ? edge.Line.Front != null : edge.Line.Back != null); //mxd
|
||||
if(side_exists && sectorsides.Contains(edge.Front ? edge.Line.Front : edge.Line.Back))
|
||||
has_dragged_sides = true; //mxd
|
||||
|
||||
foreach(LinedefSide ls2 in edges)
|
||||
{
|
||||
|
@ -2200,14 +2244,13 @@ namespace CodeImp.DoomBuilder.Map
|
|||
|
||||
if(line_is_ours)
|
||||
{
|
||||
if(edge.Line.Front == null && edge.Line.Back == null)
|
||||
has_zero_sided_lines = true;
|
||||
//if(edge.Line.Front == null && edge.Line.Back == null)
|
||||
//has_zero_sided_lines = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
has_existing_lines = true;
|
||||
if(edge.Front ? edge.Line.Front != null : edge.Line.Back != null)
|
||||
has_existing_sides = true;
|
||||
has_existing_sides |= side_exists; //mxd
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2218,7 +2261,8 @@ namespace CodeImp.DoomBuilder.Map
|
|||
// in an enclosed void, and should not be drawn.
|
||||
// However, if existing_only is false, the caller expects us to create
|
||||
// new sides anyway; skip this check.
|
||||
if(existing_only && has_existing_lines && !has_existing_sides && !has_sides_belonging_to_dragged_sectors) continue;
|
||||
if(existing_only && has_existing_lines && !has_existing_sides && !has_dragged_sides)
|
||||
continue;
|
||||
|
||||
// Ignore traced edges when trying to create any further sectors
|
||||
foreach(LinedefSide ls3 in edges_in_sector) ls3.Ignore = true;
|
||||
|
@ -2332,7 +2376,7 @@ namespace CodeImp.DoomBuilder.Map
|
|||
foreach(Sidedef side in newsides)
|
||||
{
|
||||
// Clear any unneeded textures
|
||||
side.RemoveUnneededTextures(side.Other != null);
|
||||
side.RemoveUnneededTextures(side.Other != null, false, true);
|
||||
|
||||
// Set middle texture if needed
|
||||
if(side.MiddleRequired() && side.MiddleTexture == "-")
|
||||
|
@ -2628,8 +2672,8 @@ namespace CodeImp.DoomBuilder.Map
|
|||
// Go for all the lines
|
||||
foreach(Linedef l in lines)
|
||||
{
|
||||
// Check if referencing the same vertex twice
|
||||
if(l.Start == l.End)
|
||||
// Check if referencing the same vertex twice (mxd. Or if both verts are null)
|
||||
if(l.Start == l.End || l.Start.Position == l.End.Position)
|
||||
{
|
||||
// Remove this line
|
||||
while(lines.Remove(l));
|
||||
|
@ -2785,8 +2829,8 @@ namespace CodeImp.DoomBuilder.Map
|
|||
|
||||
/// <summary>This splits the given lines with the given vertices. All affected lines
|
||||
/// will be added to changedlines. Returns false when the operation failed.</summary>
|
||||
public static bool SplitLinesByVertices(ICollection<Linedef> lines, ICollection<Vertex> verts, float splitdist, ICollection<Linedef> changedlines) { return SplitLinesByVertices(lines, verts, splitdist, changedlines, false); }
|
||||
public static bool SplitLinesByVertices(ICollection<Linedef> lines, ICollection<Vertex> verts, float splitdist, ICollection<Linedef> changedlines, bool removeinnerlines)
|
||||
public static bool SplitLinesByVertices(ICollection<Linedef> lines, ICollection<Vertex> verts, float splitdist, ICollection<Linedef> changedlines) { return SplitLinesByVertices(lines, verts, splitdist, changedlines, MergeGeometryMode.CLASSIC); }
|
||||
public static bool SplitLinesByVertices(ICollection<Linedef> lines, ICollection<Vertex> verts, float splitdist, ICollection<Linedef> changedlines, MergeGeometryMode mergemode)
|
||||
{
|
||||
if (verts.Count == 0 || lines.Count == 0) return true; //mxd
|
||||
|
||||
|
@ -2799,6 +2843,9 @@ namespace CodeImp.DoomBuilder.Map
|
|||
blockmap.AddVerticesSet(verts);
|
||||
blockmap.AddLinedefsSet(lines);
|
||||
|
||||
HashSet<Vertex> splitverts = new HashSet<Vertex>();
|
||||
HashSet<Sector> changedsectors = (mergemode == MergeGeometryMode.REPLACE ? General.Map.Map.GetSectorsFromLinedefs(changedlines) : new HashSet<Sector>());
|
||||
|
||||
foreach (Vertex v in verts)
|
||||
{
|
||||
List<BlockEntry> blocks;
|
||||
|
@ -2860,27 +2907,91 @@ namespace CodeImp.DoomBuilder.Map
|
|||
}
|
||||
}
|
||||
|
||||
//mxd. Remove lines, which are inside affected sectors
|
||||
if(mergemode == MergeGeometryMode.REPLACE && changedsectors.Count > 0)
|
||||
{
|
||||
HashSet<Linedef> alllines = new HashSet<Linedef>(lines);
|
||||
if(changedlines != null) alllines.UnionWith(changedlines);
|
||||
|
||||
foreach(Linedef l in alllines) l.UpdateCache();
|
||||
foreach(Sector s in changedsectors) s.UpdateBBox();
|
||||
foreach(Linedef l in alllines)
|
||||
{
|
||||
// Remove line when both it's start and end are inside a changed sector and neither side references it
|
||||
if(l.Start != null && l.End != null &&
|
||||
(l.Front == null || !changedsectors.Contains(l.Front.Sector)) &&
|
||||
(l.Back == null || !changedsectors.Contains(l.Back.Sector)))
|
||||
{
|
||||
foreach(Sector s in changedsectors)
|
||||
{
|
||||
if(s.Intersect(l.Start.Position) && s.Intersect(l.End.Position))
|
||||
{
|
||||
Vertex[] tocheck = { l.Start, l.End };
|
||||
while(lines.Remove(l));
|
||||
if(changedlines != null) while(changedlines.Remove(l));
|
||||
l.Dispose();
|
||||
|
||||
foreach(Vertex v in tocheck)
|
||||
{
|
||||
// If the newly created vertex only has 2 linedefs attached, then merge the linedefs
|
||||
if(!v.IsDisposed && v.Linedefs.Count == 2 && splitverts.Contains(v))
|
||||
{
|
||||
Linedef ld1 = General.GetByIndex(v.Linedefs, 0);
|
||||
Linedef ld2 = General.GetByIndex(v.Linedefs, 1);
|
||||
if(!ld1.Marked && !ld2.Marked)
|
||||
{
|
||||
Vertex v2 = (ld2.Start == v) ? ld2.End : ld2.Start;
|
||||
if(ld1.Start == v) ld1.SetStartVertex(v2); else ld1.SetEndVertex(v2);
|
||||
while(lines.Remove(ld2));
|
||||
if(changedlines != null) while(changedlines.Remove(ld2));
|
||||
ld2.Dispose();
|
||||
|
||||
// Trash vertex
|
||||
v.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>Splits lines by lines. Adds new lines to the second collection. Returns false when the operation failed.</summary>
|
||||
public static bool SplitLinesByLines(IList<Linedef> lines, IList<Linedef> changedlines, bool removeinnerlines) //mxd
|
||||
public static bool SplitLinesByLines(HashSet<Linedef> lines, HashSet<Linedef> changedlines, MergeGeometryMode mergemode) //mxd
|
||||
{
|
||||
if(lines.Count == 0 || changedlines.Count == 0) return true;
|
||||
if(lines.Count == 0 || changedlines.Count == 0 || mergemode == MergeGeometryMode.CLASSIC) return true;
|
||||
|
||||
// Create blockmap
|
||||
HashSet<Vertex> verts = new HashSet<Vertex>(); //mxd
|
||||
foreach(Linedef l in lines)
|
||||
{
|
||||
verts.Add(l.Start);
|
||||
verts.Add(l.End);
|
||||
}
|
||||
foreach(Linedef l in changedlines)
|
||||
{
|
||||
verts.Add(l.Start);
|
||||
verts.Add(l.End);
|
||||
}
|
||||
|
||||
RectangleF area = RectangleF.Union(CreateArea(lines), CreateArea(changedlines));
|
||||
BlockMap<BlockEntry> blockmap = new BlockMap<BlockEntry>(area);
|
||||
blockmap.AddLinedefsSet(lines);
|
||||
blockmap.AddLinedefsSet(changedlines);
|
||||
blockmap.AddVerticesSet(verts); //mxd
|
||||
int bmWidth = blockmap.Size.Width;
|
||||
int bmHeight = blockmap.Size.Height;
|
||||
BlockEntry[,] bmap = blockmap.Map;
|
||||
|
||||
//mxd
|
||||
HashSet<Vertex> splitverts = new HashSet<Vertex>();
|
||||
HashSet<Sector> changedsectors = (removeinnerlines ? General.Map.Map.GetSectorsFromLinedefs(changedlines) : new HashSet<Sector>());
|
||||
HashSet<Linedef> initialchanedlines = new HashSet<Linedef>(changedlines);
|
||||
HashSet<Sector> changedsectors = (mergemode == MergeGeometryMode.REPLACE ? General.Map.Map.GetSectorsFromLinedefs(changedlines) : new HashSet<Sector>());
|
||||
|
||||
// Check for intersections
|
||||
for(int w = 0; w < bmWidth; w++)
|
||||
|
@ -2908,8 +3019,25 @@ namespace CodeImp.DoomBuilder.Map
|
|||
Vector2D intersection = Line2D.GetIntersectionPoint(new Line2D(l1), new Line2D(l2), true);
|
||||
if(!float.IsNaN(intersection.x))
|
||||
{
|
||||
// Create split vertex
|
||||
Vertex splitvertex = General.Map.Map.CreateVertex(intersection);
|
||||
//mxd. Round to map format precision
|
||||
intersection.x = (float)Math.Round(intersection.x, General.Map.FormatInterface.VertexDecimals);
|
||||
intersection.y = (float)Math.Round(intersection.y, General.Map.FormatInterface.VertexDecimals);
|
||||
|
||||
//mxd. Do we already have a vertex here?
|
||||
bool existingvert = false;
|
||||
Vertex splitvertex = null;
|
||||
foreach(Vertex v in block.Vertices)
|
||||
{
|
||||
if(v.Position == intersection)
|
||||
{
|
||||
splitvertex = v;
|
||||
existingvert = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//mxd. Create split vertex?
|
||||
if(splitvertex == null) splitvertex = General.Map.Map.CreateVertex(intersection);
|
||||
if(splitvertex == null) return false;
|
||||
|
||||
// Split both lines
|
||||
|
@ -2919,9 +3047,12 @@ namespace CodeImp.DoomBuilder.Map
|
|||
Linedef nl2 = l2.Split(splitvertex);
|
||||
if(nl2 == null) return false;
|
||||
|
||||
// Mark split vertex
|
||||
splitvertex.Marked = true;
|
||||
splitverts.Add(splitvertex); //mxd
|
||||
// Mark split vertex?
|
||||
if(!existingvert)
|
||||
{
|
||||
splitvertex.Marked = true;
|
||||
splitverts.Add(splitvertex); //mxd
|
||||
}
|
||||
|
||||
// Add to the second collection
|
||||
changedlines.Add(nl1);
|
||||
|
@ -2937,7 +3068,7 @@ namespace CodeImp.DoomBuilder.Map
|
|||
}
|
||||
|
||||
//mxd. Remove lines, which are inside affected sectors
|
||||
if(removeinnerlines)
|
||||
if(mergemode == MergeGeometryMode.REPLACE)
|
||||
{
|
||||
HashSet<Linedef> alllines = new HashSet<Linedef>(lines);
|
||||
alllines.UnionWith(changedlines);
|
||||
|
@ -2947,34 +3078,40 @@ namespace CodeImp.DoomBuilder.Map
|
|||
foreach(Linedef l in alllines)
|
||||
{
|
||||
// Remove line when both it's start and end are inside a changed sector and neither side references it
|
||||
if(l.Start != null && l.End != null && !initialchanedlines.Contains(l) &&
|
||||
(l.Front == null || !changedsectors.Contains(l.Front.Sector)) &&
|
||||
(l.Back == null || !changedsectors.Contains(l.Back.Sector)))
|
||||
if(l.Start != null && l.End != null)
|
||||
{
|
||||
foreach(Sector s in changedsectors)
|
||||
if(l.Front == null && l.Back == null)
|
||||
{
|
||||
if(s.Intersect(l.Start.Position) && s.Intersect(l.End.Position))
|
||||
l.Dispose();
|
||||
}
|
||||
else if((l.Front == null || !changedsectors.Contains(l.Front.Sector)) &&
|
||||
(l.Back == null || !changedsectors.Contains(l.Back.Sector)))
|
||||
{
|
||||
foreach(Sector s in changedsectors)
|
||||
{
|
||||
Vertex[] tocheck = new[] { l.Start, l.End };
|
||||
l.Dispose();
|
||||
|
||||
foreach(Vertex v in tocheck)
|
||||
if(s.Intersect(l.Start.Position) && s.Intersect(l.End.Position))
|
||||
{
|
||||
// If the vertex only has 2 linedefs attached, then merge the linedefs
|
||||
if(!v.IsDisposed && v.Linedefs.Count == 2)
|
||||
Vertex[] tocheck = { l.Start, l.End };
|
||||
l.Dispose();
|
||||
|
||||
foreach(Vertex v in tocheck)
|
||||
{
|
||||
Linedef ld1 = General.GetByIndex(v.Linedefs, 0);
|
||||
Linedef ld2 = General.GetByIndex(v.Linedefs, 1);
|
||||
Vertex v2 = (ld2.Start == v) ? ld2.End : ld2.Start;
|
||||
if(ld1.Start == v) ld1.SetStartVertex(v2); else ld1.SetEndVertex(v2);
|
||||
ld2.Dispose();
|
||||
// If the newly created vertex only has 2 linedefs attached, then merge the linedefs
|
||||
if(!v.IsDisposed && v.Linedefs.Count == 2 && splitverts.Contains(v))
|
||||
{
|
||||
Linedef ld1 = General.GetByIndex(v.Linedefs, 0);
|
||||
Linedef ld2 = General.GetByIndex(v.Linedefs, 1);
|
||||
Vertex v2 = (ld2.Start == v) ? ld2.End : ld2.Start;
|
||||
if(ld1.Start == v) ld1.SetStartVertex(v2); else ld1.SetEndVertex(v2);
|
||||
ld2.Dispose();
|
||||
|
||||
// Trash vertex
|
||||
v.Dispose();
|
||||
// Trash vertex
|
||||
v.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
9
Source/Core/Map/MergeGeometryMode.cs
Normal file
9
Source/Core/Map/MergeGeometryMode.cs
Normal file
|
@ -0,0 +1,9 @@
|
|||
namespace CodeImp.DoomBuilder.Map
|
||||
{
|
||||
public enum MergeGeometryMode //mxd
|
||||
{
|
||||
CLASSIC,
|
||||
MERGE,
|
||||
REPLACE,
|
||||
}
|
||||
}
|
|
@ -64,19 +64,32 @@ namespace CodeImp.DoomBuilder.Map
|
|||
for(int a = 0; a < 10000; a++)
|
||||
{
|
||||
// Trace outline
|
||||
if(!TraceOutline(line, front)) break;
|
||||
if(!TraceOutline(line, front))
|
||||
{
|
||||
//DebugConsole.WriteLine("TraceSector: find outmost outline failed");
|
||||
break;
|
||||
}
|
||||
|
||||
// Discard any vertices outside the traced outline
|
||||
vertex_valid.RemoveWhere(PointOutsideOutline);
|
||||
//DebugConsole.WriteLine("vertex_valid: " + vertex_valid.Count + " verts after RemoveWhere");
|
||||
|
||||
// If it is clockwise, we've found the outmost outline
|
||||
if(o_clockwise) break;
|
||||
if(o_clockwise)
|
||||
{
|
||||
//DebugConsole.WriteLine("TraceSector: found outmost outline");
|
||||
break;
|
||||
}
|
||||
|
||||
// Otherwise, find the next edge outside the outline
|
||||
LinedefSide next = FindOuterEdge();
|
||||
|
||||
// If none was found, we're outside the map
|
||||
if(next == null) return false;
|
||||
if(next == null)
|
||||
{
|
||||
//DebugConsole.WriteLine("TraceSector aborted: no outer edge");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Repeat with this edge
|
||||
line = next.Line;
|
||||
|
@ -93,17 +106,25 @@ namespace CodeImp.DoomBuilder.Map
|
|||
LinedefSide edge = FindInnerEdge();
|
||||
|
||||
// Check if we're done
|
||||
if(edge == null) break;
|
||||
if(edge == null)
|
||||
{
|
||||
//DebugConsole.WriteLine("No inner edge found (no edge)");
|
||||
break;
|
||||
}
|
||||
|
||||
// Trace outline from edge
|
||||
if(!TraceOutline(edge.Line, edge.Front)) break;
|
||||
if(!TraceOutline(edge.Line, edge.Front))
|
||||
{
|
||||
//DebugConsole.WriteLine("No inner edge found (TraceOutline failed)");
|
||||
break;
|
||||
}
|
||||
|
||||
// Discard any vertices outside the traced outline
|
||||
vertex_valid.RemoveWhere(PointOutsideOutline);
|
||||
//DebugConsole.WriteLine("vertex_valid: " + vertex_valid.Count + " verts after RemoveWhere");
|
||||
}
|
||||
|
||||
//DebugConsole.WriteLine("FindInnerEdge: " + o_edges.Count + " lines");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -119,6 +140,7 @@ namespace CodeImp.DoomBuilder.Map
|
|||
|
||||
// Init outline
|
||||
o_edges.Clear();
|
||||
o_bbox = RectangleF.Empty;
|
||||
LinedefSide start = new LinedefSide(line, front);
|
||||
o_edges.Add(start);
|
||||
int edge_sum = 0;
|
||||
|
@ -144,12 +166,14 @@ namespace CodeImp.DoomBuilder.Map
|
|||
// Get next edge. If no valid next edge was found, go back along the current line
|
||||
LinedefSide edge_next = (NextEdge(edge, visited_lines) ?? new LinedefSide(edge.Line, !edge.Front));
|
||||
|
||||
//DebugConsole.WriteLine("Next line " + edge_next.Line.Index + (edge_next.Front ? " (front)" : " (back)"));
|
||||
//DebugConsole.WriteLine("Next line for " + edge.Line.Index + (edge.Front ? " (front)" : " (back)") + ": " + edge_next.Line.Index + (edge_next.Front ? " (front)" : " (back)"));
|
||||
|
||||
// Discard edge vertices
|
||||
vertex_valid.Remove(edge_next.Line.Start);
|
||||
vertex_valid.Remove(edge_next.Line.End);
|
||||
|
||||
//DebugConsole.WriteLine("vertex_valid: " + vertex_valid.Count + " verts after Remove (in TraceOutline)");
|
||||
|
||||
// Check if we're back to the start
|
||||
if(edge_next.Line == start.Line && edge_next.Front == start.Front)
|
||||
break;
|
||||
|
@ -166,12 +190,15 @@ namespace CodeImp.DoomBuilder.Map
|
|||
Math.Max(edge.Line.Start.Position.x, edge.Line.End.Position.x), // right
|
||||
Math.Max(edge.Line.Start.Position.y, edge.Line.End.Position.y)); // bottom
|
||||
|
||||
o_bbox = (o_bbox.IsEmpty ? l_bbox : RectangleF.Union(o_bbox, l_bbox));
|
||||
//mxd. As it turned out, o_bbox.IsEmpty was not what we needed...
|
||||
o_bbox = (o_bbox == RectangleF.Empty ? l_bbox : RectangleF.Union(o_bbox, l_bbox));
|
||||
}
|
||||
|
||||
// Check if outline is clockwise
|
||||
o_clockwise = (edge_sum < 0);
|
||||
|
||||
//DebugConsole.WriteLine("TraceOutline for line " + line.Index + " (" + (front ? "front":"back") + ") found " + o_edges.Count + " edges; o_clockwise=" + o_clockwise);
|
||||
|
||||
// Add outline edges to sector edge list
|
||||
sector_edges.AddRange(o_edges);
|
||||
|
||||
|
@ -230,6 +257,8 @@ namespace CodeImp.DoomBuilder.Map
|
|||
/// <summary>Find the closest edge within the current outline (that isn't part of the current outline)</summary>
|
||||
private LinedefSide FindInnerEdge()
|
||||
{
|
||||
//DebugConsole.WriteLine("FindInnerEdge: processing " + vertex_valid.Count + " verts");
|
||||
|
||||
// Find rightmost non-discarded vertex
|
||||
vertex_right = null;
|
||||
foreach(Vertex v in vertex_valid)
|
||||
|
@ -247,7 +276,11 @@ namespace CodeImp.DoomBuilder.Map
|
|||
}
|
||||
|
||||
// If no vertex was found, we're done
|
||||
if(vertex_right == null) return null;
|
||||
if(vertex_right == null)
|
||||
{
|
||||
//DebugConsole.WriteLine("FindInnerEdge: no vertex_right");
|
||||
return null;
|
||||
}
|
||||
|
||||
// Go through vertex's connected lines, to find
|
||||
// the line with the smallest angle parallel with
|
||||
|
@ -280,6 +313,8 @@ namespace CodeImp.DoomBuilder.Map
|
|||
{
|
||||
// Discard vertex and try again
|
||||
vertex_valid.Remove(vertex_right);
|
||||
//DebugConsole.WriteLine("vertex_valid: " + vertex_valid.Count + " verts after Remove (in FindInnerEdge)");
|
||||
|
||||
return FindInnerEdge();
|
||||
}
|
||||
|
||||
|
@ -384,11 +419,20 @@ namespace CodeImp.DoomBuilder.Map
|
|||
//mxd. The meaning of 0.0 is also inverted!!!
|
||||
|
||||
// Return false if it is on the correct side
|
||||
if(side > 0 && o_edges[nearest].Front) return false;
|
||||
if(side <= 0 && !o_edges[nearest].Front) return false;
|
||||
if(side > 0 && o_edges[nearest].Front)
|
||||
{
|
||||
//DebugConsole.WriteLine("Point " + point + " is within outline (infront of line) " + nearest);
|
||||
return false;
|
||||
}
|
||||
if(side <= 0 && !o_edges[nearest].Front)
|
||||
{
|
||||
//DebugConsole.WriteLine("Point " + point + " is within outline (at the back of line) " + nearest);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Not within the outline
|
||||
//DebugConsole.WriteLine("Point " + point + " is outside outline");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -491,7 +535,10 @@ namespace CodeImp.DoomBuilder.Map
|
|||
if(sector_copy != null) sector_copy.CopyPropertiesTo(sector);
|
||||
}
|
||||
|
||||
//DebugConsole.WriteLine(" ");
|
||||
//DebugConsole.WriteLine("Creating sector " + sector.Index + " from " + sector_edges.Count + " lines");
|
||||
//DebugConsole.WriteLine("*************************************************************");
|
||||
//DebugConsole.WriteLine(" ");
|
||||
|
||||
// Set sides to new sector
|
||||
foreach(LinedefSide edge in sector_edges)
|
||||
|
@ -501,14 +548,26 @@ namespace CodeImp.DoomBuilder.Map
|
|||
{
|
||||
if(target.Sector != sector)
|
||||
{
|
||||
bool targetwas2s = (target.Other != null);
|
||||
target.SetSector(sector); //mxd. Reattach side
|
||||
target.Marked = true; //mxd. Mark it
|
||||
|
||||
//mxd. Mark for texture adjustments if sidedness was changed.
|
||||
//mxd. Also keep existing mark if the side was already marked.
|
||||
target.Marked |= ((targetwas2s && target.Other == null) || (!targetwas2s && target.Other != null));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
target = General.Map.Map.CreateSidedef(edge.Line, edge.Front, sector); //mxd. Create new side
|
||||
target.Marked = true; //mxd. Mark it
|
||||
target.Marked = true; //mxd. Mark it for texture adjustments
|
||||
if(target.Other != null)
|
||||
{
|
||||
//mxd. Better than nothing
|
||||
target.Other.CopyPropertiesTo(target);
|
||||
|
||||
//mxd. Other was singlesided. We'll need to adjust it's textures as well
|
||||
target.Other.Marked = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -330,7 +330,7 @@ namespace CodeImp.DoomBuilder.Map
|
|||
public override string ToString()
|
||||
{
|
||||
#if DEBUG
|
||||
return "Vertex (" + pos + (marked ? "; marked" : "") + ")";
|
||||
return "Vertex " + Index + " (" + pos + (marked ? "; marked" : "") + ")";
|
||||
#else
|
||||
return "Vertex (" + pos + ")";
|
||||
#endif
|
||||
|
|
27
Source/Core/Properties/Resources.Designer.cs
generated
27
Source/Core/Properties/Resources.Designer.cs
generated
|
@ -753,9 +753,20 @@ namespace CodeImp.DoomBuilder.Properties {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap MergeGeo {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("MergeGeo", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
internal static System.Drawing.Bitmap MergeGeoClassic {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("MergeGeoClassic", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
internal static System.Drawing.Bitmap mergegeometry {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("mergegeometry", resourceCulture);
|
||||
|
@ -773,9 +784,13 @@ namespace CodeImp.DoomBuilder.Properties {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap MergeGeoRemoveLines {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("MergeGeoRemoveLines", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
internal static System.Drawing.Bitmap MissingTexture {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("MissingTexture", resourceCulture);
|
||||
|
|
|
@ -598,6 +598,15 @@
|
|||
<data name="Angle7" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\Angle7.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="MergeGeo" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\MergeGeo.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="MergeGeoClassic" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\MergeGeoClassic.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="MergeGeoRemoveLines" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\MergeGeoRemoveLines.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="Snap1mp" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\Snap1mp.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
|
|
|
@ -479,6 +479,36 @@ redo
|
|||
allowscroll = true;
|
||||
}
|
||||
|
||||
geomergeclassic //mxd
|
||||
{
|
||||
title = "Merge Dragged Vertices Only";
|
||||
category = "edit";
|
||||
description = "Only vertex-line intersections will be processed when applying geometry drag or paste actions.";
|
||||
allowkeys = true;
|
||||
allowmouse = true;
|
||||
allowscroll = false;
|
||||
}
|
||||
|
||||
geomerge //mxd
|
||||
{
|
||||
title = "Merge Dragged Geometry";
|
||||
category = "edit";
|
||||
description = "Geometry merging will be performed when applying geometry drag or paste actions.";
|
||||
allowkeys = true;
|
||||
allowmouse = true;
|
||||
allowscroll = false;
|
||||
}
|
||||
|
||||
georeplace //mxd
|
||||
{
|
||||
title = "Replace with Dragged Geometry";
|
||||
category = "edit";
|
||||
description = "Dragged geometry will replace underlaying geometry when applying geometry drag or paste actions.";
|
||||
allowkeys = true;
|
||||
allowmouse = true;
|
||||
allowscroll = false;
|
||||
}
|
||||
|
||||
togglesnap
|
||||
{
|
||||
title = "Snap to Grid";
|
||||
|
@ -491,9 +521,9 @@ togglesnap
|
|||
|
||||
toggleautomerge
|
||||
{
|
||||
title = "Merge Geometry";
|
||||
title = "Snap to Geometry";
|
||||
category = "edit";
|
||||
description = "Toggles automatic merging of geometry for vertices and structures that are being dragged.";
|
||||
description = "Toggles snapping to the nearest vertex or linedef for map elements that are being dragged.";
|
||||
allowkeys = true;
|
||||
allowmouse = true;
|
||||
allowscroll = true;
|
||||
|
|
BIN
Source/Core/Resources/MergeGeo.png
Normal file
BIN
Source/Core/Resources/MergeGeo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
BIN
Source/Core/Resources/MergeGeoClassic.png
Normal file
BIN
Source/Core/Resources/MergeGeoClassic.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
BIN
Source/Core/Resources/MergeGeoRemoveLines.png
Normal file
BIN
Source/Core/Resources/MergeGeoRemoveLines.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
102
Source/Core/Windows/MainForm.Designer.cs
generated
102
Source/Core/Windows/MainForm.Designer.cs
generated
|
@ -97,6 +97,10 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
this.itemviewfloors = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.itemviewceilings = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.seperatorviewviews = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.itemmergegeoclassic = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.itemmergegeo = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.itemreplacegeo = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.separatorgeomerge = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.itemfullbrightness = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.itemtogglegrid = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator();
|
||||
|
@ -180,6 +184,10 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
this.buttonviewbrightness = new System.Windows.Forms.ToolStripButton();
|
||||
this.buttonviewfloors = new System.Windows.Forms.ToolStripButton();
|
||||
this.buttonviewceilings = new System.Windows.Forms.ToolStripButton();
|
||||
this.separatorgeomergemodes = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.buttonmergegeoclassic = new System.Windows.Forms.ToolStripButton();
|
||||
this.buttonmergegeo = new System.Windows.Forms.ToolStripButton();
|
||||
this.buttonplacegeo = new System.Windows.Forms.ToolStripButton();
|
||||
this.seperatorviews = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.buttontogglefixedthingsscale = new System.Windows.Forms.ToolStripButton();
|
||||
this.buttonsnaptogrid = new System.Windows.Forms.ToolStripButton();
|
||||
|
@ -518,6 +526,10 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
this.itempaste,
|
||||
this.itempastespecial,
|
||||
this.seperatoreditcopypaste,
|
||||
this.itemmergegeoclassic,
|
||||
this.itemmergegeo,
|
||||
this.itemreplacegeo,
|
||||
this.separatorgeomerge,
|
||||
this.itemsnaptogrid,
|
||||
this.itemdynamicgridsize,
|
||||
this.itemautomerge,
|
||||
|
@ -632,7 +644,7 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
this.itemautomerge.Name = "itemautomerge";
|
||||
this.itemautomerge.Size = new System.Drawing.Size(224, 22);
|
||||
this.itemautomerge.Tag = "builder_toggleautomerge";
|
||||
this.itemautomerge.Text = "&Merge Geometry";
|
||||
this.itemautomerge.Text = "Snap to &Geometry";
|
||||
this.itemautomerge.Click += new System.EventHandler(this.InvokeTaggedAction);
|
||||
//
|
||||
// itemautoclearsidetextures
|
||||
|
@ -842,6 +854,38 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
this.seperatorviewviews.Name = "seperatorviewviews";
|
||||
this.seperatorviewviews.Size = new System.Drawing.Size(212, 6);
|
||||
//
|
||||
// itemmergegeoclassic
|
||||
//
|
||||
this.itemmergegeoclassic.Image = global::CodeImp.DoomBuilder.Properties.Resources.MergeGeoClassic;
|
||||
this.itemmergegeoclassic.Name = "itemmergegeoclassic";
|
||||
this.itemmergegeoclassic.Size = new System.Drawing.Size(215, 22);
|
||||
this.itemmergegeoclassic.Tag = "builder_geomergeclassic";
|
||||
this.itemmergegeoclassic.Text = "Merge Dragged Vertices Only";
|
||||
this.itemmergegeoclassic.Click += new System.EventHandler(this.InvokeTaggedAction);
|
||||
//
|
||||
// itemmergegeo
|
||||
//
|
||||
this.itemmergegeo.Image = global::CodeImp.DoomBuilder.Properties.Resources.MergeGeo;
|
||||
this.itemmergegeo.Name = "itemmergegeo";
|
||||
this.itemmergegeo.Size = new System.Drawing.Size(215, 22);
|
||||
this.itemmergegeo.Tag = "builder_geomerge";
|
||||
this.itemmergegeo.Text = "Merge Dragged Geometry";
|
||||
this.itemmergegeo.Click += new System.EventHandler(this.InvokeTaggedAction);
|
||||
//
|
||||
// itemreplacegeo
|
||||
//
|
||||
this.itemreplacegeo.Image = global::CodeImp.DoomBuilder.Properties.Resources.MergeGeoRemoveLines;
|
||||
this.itemreplacegeo.Name = "itemreplacegeo";
|
||||
this.itemreplacegeo.Size = new System.Drawing.Size(215, 22);
|
||||
this.itemreplacegeo.Tag = "builder_georeplace";
|
||||
this.itemreplacegeo.Text = "Replace with Dragged Geometry";
|
||||
this.itemreplacegeo.Click += new System.EventHandler(this.InvokeTaggedAction);
|
||||
//
|
||||
// separatorgeomerge
|
||||
//
|
||||
this.separatorgeomerge.Name = "separatorgeomerge";
|
||||
this.separatorgeomerge.Size = new System.Drawing.Size(212, 6);
|
||||
//
|
||||
// itemfullbrightness
|
||||
//
|
||||
this.itemfullbrightness.Checked = true;
|
||||
|
@ -1277,6 +1321,10 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
this.buttonviewbrightness,
|
||||
this.buttonviewfloors,
|
||||
this.buttonviewceilings,
|
||||
this.separatorgeomergemodes,
|
||||
this.buttonmergegeoclassic,
|
||||
this.buttonmergegeo,
|
||||
this.buttonplacegeo,
|
||||
this.seperatorviews,
|
||||
this.buttonsnaptogrid,
|
||||
this.buttontoggledynamicgrid,
|
||||
|
@ -1682,6 +1730,48 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
this.buttonviewceilings.Text = "View Ceiling Textures";
|
||||
this.buttonviewceilings.Click += new System.EventHandler(this.InvokeTaggedAction);
|
||||
//
|
||||
// separatorgeomergemodes
|
||||
//
|
||||
this.separatorgeomergemodes.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0);
|
||||
this.separatorgeomergemodes.Name = "separatorgeomergemodes";
|
||||
this.separatorgeomergemodes.Size = new System.Drawing.Size(6, 25);
|
||||
//
|
||||
// buttonmergegeoclassic
|
||||
//
|
||||
this.buttonmergegeoclassic.CheckOnClick = true;
|
||||
this.buttonmergegeoclassic.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
|
||||
this.buttonmergegeoclassic.Image = global::CodeImp.DoomBuilder.Properties.Resources.MergeGeoClassic;
|
||||
this.buttonmergegeoclassic.ImageTransparentColor = System.Drawing.Color.Magenta;
|
||||
this.buttonmergegeoclassic.Name = "buttonmergegeoclassic";
|
||||
this.buttonmergegeoclassic.Size = new System.Drawing.Size(23, 22);
|
||||
this.buttonmergegeoclassic.Tag = "builder_geomergeclassic";
|
||||
this.buttonmergegeoclassic.Text = "Merge Dragged Vertices Only";
|
||||
this.buttonmergegeoclassic.Click += new System.EventHandler(this.InvokeTaggedAction);
|
||||
//
|
||||
// buttonmergegeoclassic
|
||||
//
|
||||
this.buttonmergegeo.CheckOnClick = true;
|
||||
this.buttonmergegeo.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
|
||||
this.buttonmergegeo.Image = global::CodeImp.DoomBuilder.Properties.Resources.MergeGeo;
|
||||
this.buttonmergegeo.ImageTransparentColor = System.Drawing.Color.Magenta;
|
||||
this.buttonmergegeo.Name = "buttonmergegeo";
|
||||
this.buttonmergegeo.Size = new System.Drawing.Size(23, 22);
|
||||
this.buttonmergegeo.Tag = "builder_geomerge";
|
||||
this.buttonmergegeo.Text = "Merge Dragged Geometry";
|
||||
this.buttonmergegeo.Click += new System.EventHandler(this.InvokeTaggedAction);
|
||||
//
|
||||
// buttonmergegeoclassic
|
||||
//
|
||||
this.buttonplacegeo.CheckOnClick = true;
|
||||
this.buttonplacegeo.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
|
||||
this.buttonplacegeo.Image = global::CodeImp.DoomBuilder.Properties.Resources.MergeGeoRemoveLines;
|
||||
this.buttonplacegeo.ImageTransparentColor = System.Drawing.Color.Magenta;
|
||||
this.buttonplacegeo.Name = "buttonmergegeoclassic";
|
||||
this.buttonplacegeo.Size = new System.Drawing.Size(23, 22);
|
||||
this.buttonplacegeo.Tag = "builder_georeplace";
|
||||
this.buttonplacegeo.Text = "Replace with Dragged Geometry";
|
||||
this.buttonplacegeo.Click += new System.EventHandler(this.InvokeTaggedAction);
|
||||
//
|
||||
// seperatorviews
|
||||
//
|
||||
this.seperatorviews.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0);
|
||||
|
@ -1751,7 +1841,7 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
this.buttonautomerge.Name = "buttonautomerge";
|
||||
this.buttonautomerge.Size = new System.Drawing.Size(23, 22);
|
||||
this.buttonautomerge.Tag = "builder_toggleautomerge";
|
||||
this.buttonautomerge.Text = "Merge Geometry";
|
||||
this.buttonautomerge.Text = "Snap to Geometry";
|
||||
this.buttonautomerge.Click += new System.EventHandler(this.InvokeTaggedAction);
|
||||
//
|
||||
// buttonautoclearsidetextures
|
||||
|
@ -2681,6 +2771,10 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
private System.Windows.Forms.ToolStripButton buttonviewbrightness;
|
||||
private System.Windows.Forms.ToolStripButton buttonviewfloors;
|
||||
private System.Windows.Forms.ToolStripButton buttonviewceilings;
|
||||
private System.Windows.Forms.ToolStripSeparator separatorgeomergemodes;
|
||||
private System.Windows.Forms.ToolStripButton buttonmergegeoclassic;
|
||||
private System.Windows.Forms.ToolStripButton buttonmergegeo;
|
||||
private System.Windows.Forms.ToolStripButton buttonplacegeo;
|
||||
private System.Windows.Forms.ToolStripSeparator seperatortoolsresources;
|
||||
private System.Windows.Forms.ToolStripButton buttonscripteditor;
|
||||
private System.Windows.Forms.ToolStripMenuItem menuview;
|
||||
|
@ -2691,6 +2785,10 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
private System.Windows.Forms.ToolStripMenuItem itemviewfloors;
|
||||
private System.Windows.Forms.ToolStripMenuItem itemviewceilings;
|
||||
private System.Windows.Forms.ToolStripSeparator seperatorviewzoom;
|
||||
private System.Windows.Forms.ToolStripMenuItem itemmergegeoclassic;
|
||||
private System.Windows.Forms.ToolStripMenuItem itemmergegeo;
|
||||
private System.Windows.Forms.ToolStripMenuItem itemreplacegeo;
|
||||
private System.Windows.Forms.ToolStripSeparator separatorgeomerge;
|
||||
private System.Windows.Forms.ToolStripMenuItem itemscripteditor;
|
||||
private System.Windows.Forms.ToolStripSeparator seperatortoolsconfig;
|
||||
private System.Windows.Forms.ToolStripMenuItem itemtestmap;
|
||||
|
|
|
@ -139,6 +139,10 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
// View modes
|
||||
private ToolStripButton[] viewmodesbuttons;
|
||||
private ToolStripMenuItem[] viewmodesitems;
|
||||
|
||||
//mxd. Geometry merge modes
|
||||
private ToolStripButton[] geomergemodesbuttons;
|
||||
private ToolStripMenuItem[] geomergemodesitems;
|
||||
|
||||
// Edit modes
|
||||
private List<ToolStripItem> editmodeitems;
|
||||
|
@ -249,6 +253,17 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
viewmodesitems[(int)ViewMode.Brightness] = itemviewbrightness;
|
||||
viewmodesitems[(int)ViewMode.FloorTextures] = itemviewfloors;
|
||||
viewmodesitems[(int)ViewMode.CeilingTextures] = itemviewceilings;
|
||||
|
||||
//mxd. Make arrays for geometry merge modes
|
||||
int numgeomodes = Enum.GetValues(typeof(MergeGeometryMode)).Length;
|
||||
geomergemodesbuttons = new ToolStripButton[numgeomodes];
|
||||
geomergemodesbuttons[(int)MergeGeometryMode.CLASSIC] = buttonmergegeoclassic;
|
||||
geomergemodesbuttons[(int)MergeGeometryMode.MERGE] = buttonmergegeo;
|
||||
geomergemodesbuttons[(int)MergeGeometryMode.REPLACE] = buttonplacegeo;
|
||||
geomergemodesitems = new ToolStripMenuItem[numgeomodes];
|
||||
geomergemodesitems[(int)MergeGeometryMode.CLASSIC] = itemmergegeoclassic;
|
||||
geomergemodesitems[(int)MergeGeometryMode.MERGE] = itemmergegeo;
|
||||
geomergemodesitems[(int)MergeGeometryMode.REPLACE] = itemreplacegeo;
|
||||
|
||||
// Visual Studio IDE doesn't let me set these in the designer :(
|
||||
buttonzoom.Font = menufile.Font;
|
||||
|
@ -314,10 +329,18 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
}
|
||||
|
||||
// View mode only matters in classic editing modes
|
||||
bool isclassicmode = (General.Editing.Mode is ClassicMode);
|
||||
for(int i = 0; i < Renderer2D.NUM_VIEW_MODES; i++)
|
||||
{
|
||||
viewmodesitems[i].Enabled = (General.Editing.Mode is ClassicMode);
|
||||
viewmodesbuttons[i].Enabled = (General.Editing.Mode is ClassicMode);
|
||||
viewmodesitems[i].Enabled = isclassicmode;
|
||||
viewmodesbuttons[i].Enabled = isclassicmode;
|
||||
}
|
||||
|
||||
//mxd. Merge geometry mode only matters in classic editing modes
|
||||
for(int i = 0; i < geomergemodesbuttons.Length; i++)
|
||||
{
|
||||
geomergemodesbuttons[i].Enabled = isclassicmode;
|
||||
geomergemodesitems[i].Enabled = isclassicmode;
|
||||
}
|
||||
|
||||
UpdateEditMenu();
|
||||
|
@ -2070,6 +2093,10 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
buttonviewceilings.Visible = General.Settings.ToolbarViewModes && maploaded;
|
||||
buttonviewfloors.Visible = General.Settings.ToolbarViewModes && maploaded;
|
||||
buttonviewnormal.Visible = General.Settings.ToolbarViewModes && maploaded;
|
||||
separatorgeomergemodes.Visible = General.Settings.ToolbarGeometry && maploaded; //mxd
|
||||
buttonmergegeoclassic.Visible = General.Settings.ToolbarGeometry && maploaded; //mxd
|
||||
buttonmergegeo.Visible = General.Settings.ToolbarGeometry && maploaded; //mxd
|
||||
buttonplacegeo.Visible = General.Settings.ToolbarGeometry && maploaded; //mxd
|
||||
buttonsnaptogrid.Visible = General.Settings.ToolbarGeometry && maploaded;
|
||||
buttontoggledynamicgrid.Visible = General.Settings.ToolbarGeometry && maploaded; //mxd
|
||||
buttontoggledynamicgrid.Checked = General.Settings.DynamicGridSize; //mxd
|
||||
|
@ -2741,6 +2768,17 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
buttoncut.Enabled = itemcut.Enabled;
|
||||
buttoncopy.Enabled = itemcopy.Enabled;
|
||||
buttonpaste.Enabled = itempaste.Enabled;
|
||||
|
||||
//mxd. Geometry merge mode items
|
||||
if(General.Map != null)
|
||||
{
|
||||
for(int i = 0; i < geomergemodesbuttons.Length; i++)
|
||||
{
|
||||
// Check the correct item
|
||||
geomergemodesbuttons[i].Checked = (i == (int)General.Settings.MergeGeometryMode);
|
||||
geomergemodesitems[i].Checked = (i == (int)General.Settings.MergeGeometryMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//mxd
|
||||
|
@ -2915,6 +2953,36 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
ThingStatisticsForm f = new ThingStatisticsForm();
|
||||
f.ShowDialog(this);
|
||||
}
|
||||
|
||||
//mxd
|
||||
[BeginAction("geomergeclassic")]
|
||||
private void GeoMergeClassic()
|
||||
{
|
||||
General.Settings.MergeGeometryMode = MergeGeometryMode.CLASSIC;
|
||||
UpdateToolbar();
|
||||
UpdateEditMenu();
|
||||
DisplayStatus(StatusType.Action, "\"Merge Dragged Vertices Only\" mode selected");
|
||||
}
|
||||
|
||||
//mxd
|
||||
[BeginAction("geomerge")]
|
||||
private void GeoMerge()
|
||||
{
|
||||
General.Settings.MergeGeometryMode = MergeGeometryMode.MERGE;
|
||||
UpdateToolbar();
|
||||
UpdateEditMenu();
|
||||
DisplayStatus(StatusType.Action, "\"Merge Dragged Geometry\" mode selected");
|
||||
}
|
||||
|
||||
//mxd
|
||||
[BeginAction("georeplace")]
|
||||
private void GeoReplace()
|
||||
{
|
||||
General.Settings.MergeGeometryMode = MergeGeometryMode.REPLACE;
|
||||
UpdateToolbar();
|
||||
UpdateEditMenu();
|
||||
DisplayStatus(StatusType.Action, "\"Replace with Dragged Geometry\" mode selected");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
|
|
@ -420,7 +420,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
MoveGeometryRelative(mousemappos - dragstartmappos, snaptogrid, snaptogridincrement, snaptonearest, snaptocardinaldirection);
|
||||
|
||||
// Stitch geometry
|
||||
General.Map.Map.StitchGeometry(true);
|
||||
General.Map.Map.StitchGeometry(General.Settings.MergeGeometryMode);
|
||||
|
||||
// Snap to map format accuracy
|
||||
General.Map.Map.SnapAllToAccuracy();
|
||||
|
|
|
@ -1648,8 +1648,11 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
}
|
||||
}
|
||||
|
||||
//mxd. We'll need sidedefs marked by StitchGeometry, not all sidedefs from selection...
|
||||
General.Map.Map.ClearMarkedSidedefs(false);
|
||||
|
||||
// Stitch geometry
|
||||
General.Map.Map.StitchGeometry(true);
|
||||
General.Map.Map.StitchGeometry(General.Settings.MergeGeometryMode);
|
||||
|
||||
// Snap to map format accuracy
|
||||
General.Map.Map.SnapAllToAccuracy(General.Map.UDMF && usepreciseposition);
|
||||
|
|
Loading…
Reference in a new issue