diff --git a/Build/Configurations/Includes/Common.cfg b/Build/Configurations/Includes/Common.cfg index 7583ae05..981eefa4 100644 --- a/Build/Configurations/Includes/Common.cfg +++ b/Build/Configurations/Includes/Common.cfg @@ -15,6 +15,14 @@ start3dmode = 32000; // Flat used as sky skyflatname = "F_SKY1"; +// Map boundaries. Map objects can only be placed within these boundaries +// WARNING: changing this may mess your map up, so only change it when you +// know what you are doing +leftboundary = -32768; +rightboundary = 32767; +topboundary = 32767; +bottomboundary = -32768; + // Maximum length of texture name length in characters (0 for unlimited) // WARNING: changing this may destroy your WAD file. Only change it when diff --git a/Source/Core/Config/GameConfiguration.cs b/Source/Core/Config/GameConfiguration.cs index e994f20f..cf2dac01 100644 --- a/Source/Core/Config/GameConfiguration.cs +++ b/Source/Core/Config/GameConfiguration.cs @@ -73,6 +73,10 @@ namespace CodeImp.DoomBuilder.Config private string decorategames; private string skyflatname; private int maxtexturenamelength; + private int leftboundary; + private int rightboundary; + private int topboundary; + private int bottomboundary; private bool doomlightlevels; // Skills @@ -159,6 +163,10 @@ namespace CodeImp.DoomBuilder.Config public string DecorateGames { get { return decorategames; } } public string SkyFlatName { get { return skyflatname; } } public int MaxTextureNamelength { get { return maxtexturenamelength; } } + public int LeftBoundary { get { return leftboundary; } } + public int RightBoundary { get { return rightboundary; } } + public int TopBoundary { get { return topboundary; } } + public int BottomBoundary { get { return bottomboundary; } } public bool DoomLightLevels { get { return doomlightlevels; } } // Skills @@ -267,6 +275,10 @@ namespace CodeImp.DoomBuilder.Config decorategames = cfg.ReadSetting("decorategames", ""); skyflatname = cfg.ReadSetting("skyflatname", "F_SKY1"); maxtexturenamelength = cfg.ReadSetting("maxtexturenamelength", 8); + leftboundary = cfg.ReadSetting("leftboundary", -32768); + rightboundary = cfg.ReadSetting("rightboundary", 32767); + topboundary = cfg.ReadSetting("topboundary", 32767); + bottomboundary = cfg.ReadSetting("bottomboundary", -32768); doomlightlevels = cfg.ReadSetting("doomlightlevels", true); for(int i = 0; i < Linedef.NUM_ARGS; i++) makedoorargs[i] = cfg.ReadSetting("makedoorarg" + i.ToString(CultureInfo.InvariantCulture), 0); diff --git a/Source/Core/Editing/GridSetup.cs b/Source/Core/Editing/GridSetup.cs index 9b78f487..ce6af311 100644 --- a/Source/Core/Editing/GridSetup.cs +++ b/Source/Core/Editing/GridSetup.cs @@ -236,8 +236,16 @@ namespace CodeImp.DoomBuilder.Editing // This snaps to the nearest grid coordinate public static Vector2D SnappedToGrid(Vector2D v, float gridsize, float gridsizeinv) { - return new Vector2D((float)Math.Round(v.x * gridsizeinv) * gridsize, - (float)Math.Round(v.y * gridsizeinv) * gridsize); + Vector2D sv = new Vector2D((float)Math.Round(v.x * gridsizeinv) * gridsize, + (float)Math.Round(v.y * gridsizeinv) * gridsize); + + if (sv.x < General.Map.Config.LeftBoundary) sv.x = General.Map.Config.LeftBoundary; + else if (sv.x > General.Map.Config.RightBoundary) sv.x = General.Map.Config.RightBoundary; + + if (sv.y > General.Map.Config.TopBoundary) sv.y = General.Map.Config.TopBoundary; + else if (sv.y < General.Map.Config.BottomBoundary) sv.y = General.Map.Config.BottomBoundary; + + return sv; } #endregion diff --git a/Source/Core/Rendering/Plotter.cs b/Source/Core/Rendering/Plotter.cs index 35978325..4a7199a5 100644 --- a/Source/Core/Rendering/Plotter.cs +++ b/Source/Core/Rendering/Plotter.cs @@ -157,29 +157,33 @@ namespace CodeImp.DoomBuilder.Rendering } // This draws a dotted grid line horizontally - public void DrawGridLineH(int y, ref PixelColor c) + public void DrawGridLineH(int y, int x1, int x2, ref PixelColor c) { int numpixels = visiblewidth >> 1; int offset = y & 0x01; int ywidth = y * width; + x1 = General.Clamp(x1 >> 1, 0, numpixels - 1); + x2 = General.Clamp(x2 >> 1, 0, numpixels - 1); - if((y >= 0) && (y < height)) + if ((y >= 0) && (y < height)) { // Draw all pixels on this line - for(int i = 0; i < numpixels; i++) pixels[ywidth + ((i << 1) | offset)] = c; + for (int i = x1; i < x2; i++) pixels[ywidth + ((i << 1) | offset)] = c; } } // This draws a dotted grid line vertically - public void DrawGridLineV(int x, ref PixelColor c) + public void DrawGridLineV(int x, int y1, int y2, ref PixelColor c) { int numpixels = visibleheight >> 1; int offset = x & 0x01; + y1 = General.Clamp(y1 >> 1, 0, numpixels - 1); + y2 = General.Clamp(y2 >> 1, 0, numpixels - 1); if((x >= 0) && (x < width)) { // Draw all pixels on this line - for(int i = 0; i < numpixels; i++) pixels[((i << 1) | offset) * width + x] = c; + for (int i = y1; i < y2; i++) pixels[((i << 1) | offset) * width + x] = c; } } diff --git a/Source/Core/Rendering/Renderer2D.cs b/Source/Core/Rendering/Renderer2D.cs index 57e15c2e..afc06bb3 100644 --- a/Source/Core/Rendering/Renderer2D.cs +++ b/Source/Core/Rendering/Renderer2D.cs @@ -831,9 +831,13 @@ namespace CodeImp.DoomBuilder.Rendering private void RenderGrid(float size, PixelColor c, Plotter gridplotter) { Vector2D ltpos, rbpos; + Vector2D tlb, rbb; Vector2D pos = new Vector2D(); float sizeinv = 1f / size; - + float ystart, yend; + float xstart, xend; + float from, to; + // Only render grid when not screen-filling if((size * scale) > 6f) { @@ -844,21 +848,48 @@ namespace CodeImp.DoomBuilder.Rendering // Clip to nearest grid ltpos = GridSetup.SnappedToGrid(ltpos, size, sizeinv); rbpos = GridSetup.SnappedToGrid(rbpos, size, sizeinv); - + + // Translate top left boundary and right bottom boundary of map + // to screen coords + tlb = new Vector2D(General.Map.Config.LeftBoundary, General.Map.Config.TopBoundary).GetTransformed(translatex, translatey, scale, -scale); + rbb = new Vector2D(General.Map.Config.RightBoundary, General.Map.Config.BottomBoundary).GetTransformed(translatex, translatey, scale, -scale); + // Draw all horizontal grid lines - for(float y = ltpos.y + size; y > rbpos.y - size; y -= size) + ystart = rbpos.y > General.Map.Config.BottomBoundary ? rbpos.y : General.Map.Config.BottomBoundary; + yend = ltpos.y < General.Map.Config.TopBoundary ? ltpos.y : General.Map.Config.TopBoundary; + + for (float y = ystart; y < yend + size; y += size) { + if (y > General.Map.Config.TopBoundary) y = General.Map.Config.TopBoundary; + else if (y < General.Map.Config.BottomBoundary) y = General.Map.Config.BottomBoundary; + + from = tlb.x < 0 ? 0 : tlb.x; + to = rbb.x > windowsize.Width ? windowsize.Width : rbb.x; + pos.y = y; pos = pos.GetTransformed(translatex, translatey, scale, -scale); - gridplotter.DrawGridLineH((int)pos.y, ref c); + + // Note: I'm not using Math.Ceiling in this case, because that doesn't work right. + gridplotter.DrawGridLineH((int)pos.y, (int)Math.Round(from + 0.49999f), (int)Math.Round(to + 0.49999f), ref c); } - + // Draw all vertical grid lines - for(float x = ltpos.x - size; x < rbpos.x + size; x += size) + xstart = ltpos.x > General.Map.Config.LeftBoundary ? ltpos.x : General.Map.Config.LeftBoundary; + xend = rbpos.x < General.Map.Config.RightBoundary ? rbpos.x : General.Map.Config.RightBoundary; + + for (float x = xstart; x < xend + size; x += size) { + if (x > General.Map.Config.RightBoundary) x = General.Map.Config.RightBoundary; + else if (x < General.Map.Config.LeftBoundary) x = General.Map.Config.LeftBoundary; + + from = tlb.y < 0 ? 0 : tlb.y; + to = rbb.y > windowsize.Height ? windowsize.Height : rbb.y; + pos.x = x; pos = pos.GetTransformed(translatex, translatey, scale, -scale); - gridplotter.DrawGridLineV((int)pos.x, ref c); + + // Note: I'm not using Math.Ceiling in this case, because that doesn't work right. + gridplotter.DrawGridLineV((int)pos.x, (int)Math.Round(from + 0.49999f), (int)Math.Round(to + 0.49999f), ref c); } } } diff --git a/Source/Plugins/BuilderModes/ClassicModes/DragGeometryMode.cs b/Source/Plugins/BuilderModes/ClassicModes/DragGeometryMode.cs index c1fe7041..9669e3d0 100644 --- a/Source/Plugins/BuilderModes/ClassicModes/DragGeometryMode.cs +++ b/Source/Plugins/BuilderModes/ClassicModes/DragGeometryMode.cs @@ -165,10 +165,20 @@ namespace CodeImp.DoomBuilder.BuilderModes { Vector2D oldpos = dragitem.Position; Vector2D anchorpos = dragitemposition + offset; - int i = 0; + Vector2D tl, br; // don't move if the offset contains invalid data if (!offset.IsFinite()) return false; + + // Find the outmost vertices + tl = br = oldpositions[0]; + for (int i = 0; i < oldpositions.Count; i++) + { + if (oldpositions[i].x < tl.x) tl.x = (int)oldpositions[i].x; + if (oldpositions[i].x > br.x) br.x = (int)oldpositions[i].x; + if (oldpositions[i].y > tl.y) tl.y = (int)oldpositions[i].y; + if (oldpositions[i].y < br.y) br.y = (int)oldpositions[i].y; + } // Snap to nearest? if(snapnearest) @@ -245,9 +255,17 @@ namespace CodeImp.DoomBuilder.BuilderModes offset += dragitem.Position - anchorpos; } + // Make sure the offset is inside the map boundaries + if (offset.x + tl.x < General.Map.Config.LeftBoundary) offset.x = General.Map.Config.LeftBoundary - tl.x; + if (offset.x + br.x > General.Map.Config.RightBoundary) offset.x = General.Map.Config.RightBoundary - br.x; + if (offset.y + tl.y > General.Map.Config.TopBoundary) offset.y = General.Map.Config.TopBoundary - tl.y; + if (offset.y + br.y < General.Map.Config.BottomBoundary) offset.y = General.Map.Config.BottomBoundary - br.y; + // Drag item moved? if(!snapgrid || (dragitem.Position != oldpos)) { + int i = 0; + // Move selected geometry foreach(Vertex v in selectedverts) { diff --git a/Source/Plugins/BuilderModes/ClassicModes/DragThingsMode.cs b/Source/Plugins/BuilderModes/ClassicModes/DragThingsMode.cs index 1bd0c730..f664a660 100644 --- a/Source/Plugins/BuilderModes/ClassicModes/DragThingsMode.cs +++ b/Source/Plugins/BuilderModes/ClassicModes/DragThingsMode.cs @@ -157,11 +157,21 @@ namespace CodeImp.DoomBuilder.BuilderModes { Vector2D oldpos = dragitem.Position; Thing nearest; - int i = 0; + Vector2D tl, br; // don't move if the offset contains invalid data if (!offset.IsFinite()) return false; - + + // Find the outmost things + tl = br = oldpositions[0]; + for (int i = 0; i < oldpositions.Count; i++) + { + if (oldpositions[i].x < tl.x) tl.x = (int)oldpositions[i].x; + if (oldpositions[i].x > br.x) br.x = (int)oldpositions[i].x; + if (oldpositions[i].y > tl.y) tl.y = (int)oldpositions[i].y; + if (oldpositions[i].y < br.y) br.y = (int)oldpositions[i].y; + } + // Snap to nearest? if(snapnearest) { @@ -193,9 +203,17 @@ namespace CodeImp.DoomBuilder.BuilderModes offset += (Vector2D)dragitem.Position - (dragitemposition + offset); } + // Make sure the offset is inside the map boundaries + if (offset.x + tl.x < General.Map.Config.LeftBoundary) offset.x = General.Map.Config.LeftBoundary - tl.x; + if (offset.x + br.x > General.Map.Config.RightBoundary) offset.x = General.Map.Config.RightBoundary - br.x; + if (offset.y + tl.y > General.Map.Config.TopBoundary) offset.y = General.Map.Config.TopBoundary - tl.y; + if (offset.y + br.y < General.Map.Config.BottomBoundary) offset.y = General.Map.Config.BottomBoundary - br.y; + // Drag item moved? if(!snapgrid || ((Vector2D)dragitem.Position != oldpos)) { + int i = 0; + // Move selected geometry foreach(Thing t in selectedthings) { diff --git a/Source/Plugins/BuilderModes/ClassicModes/DrawGeometryMode.cs b/Source/Plugins/BuilderModes/ClassicModes/DrawGeometryMode.cs index 2eea1c80..0ba819b4 100644 --- a/Source/Plugins/BuilderModes/ClassicModes/DrawGeometryMode.cs +++ b/Source/Plugins/BuilderModes/ClassicModes/DrawGeometryMode.cs @@ -208,6 +208,7 @@ namespace CodeImp.DoomBuilder.BuilderModes public static DrawnVertex GetCurrentPosition(Vector2D mousemappos, bool snaptonearest, bool snaptogrid, IRenderer2D renderer, List points) { DrawnVertex p = new DrawnVertex(); + Vector2D vm = mousemappos; float vrange = BuilderPlug.Me.StitchRange / renderer.Scale; // Snap to nearest? @@ -289,11 +290,55 @@ namespace CodeImp.DoomBuilder.BuilderModes } } + // if the mouse cursor is outside the map bondaries check if the line between the last set point and the + // mouse cursor intersect any of the boundary lines. If it does, set the position to this intersection + if (points.Count > 0 && + (mousemappos.x < General.Map.Config.LeftBoundary || mousemappos.x > General.Map.Config.RightBoundary || + mousemappos.y > General.Map.Config.TopBoundary || mousemappos.y < General.Map.Config.BottomBoundary)) + { + Line2D dline = new Line2D(mousemappos, points[points.Count - 1].pos); + bool foundintersection = false; + float u = 0.0f; + List blines = new List(); + + // lines for left, top, right and bottom bondaries + blines.Add(new Line2D(General.Map.Config.LeftBoundary, General.Map.Config.BottomBoundary, General.Map.Config.LeftBoundary, General.Map.Config.TopBoundary)); + blines.Add(new Line2D(General.Map.Config.LeftBoundary, General.Map.Config.TopBoundary, General.Map.Config.RightBoundary, General.Map.Config.TopBoundary)); + blines.Add(new Line2D(General.Map.Config.RightBoundary, General.Map.Config.TopBoundary, General.Map.Config.RightBoundary, General.Map.Config.BottomBoundary)); + blines.Add(new Line2D(General.Map.Config.RightBoundary, General.Map.Config.BottomBoundary, General.Map.Config.LeftBoundary, General.Map.Config.BottomBoundary)); + + // check for intersections with boundaries + for (int i = 0; i < blines.Count; i++) + { + if (!foundintersection) + { + // only check for intersection if the last set point is not on the + // line we are checking against + if (blines[i].GetSideOfLine(points[points.Count - 1].pos) != 0.0f) + { + foundintersection = blines[i].GetIntersection(dline, out u); + } + } + } + + // if there was no intersection set the position to the last set point + if (!foundintersection) + vm = points[points.Count - 1].pos; + else + vm = dline.GetCoordinatesAt(u); + + } + + // Snap to grid? if(snaptogrid) { // Aligned to grid - p.pos = General.Map.Grid.SnappedToGrid(mousemappos); + p.pos = General.Map.Grid.SnappedToGrid(vm); + + // special handling + if (p.pos.x > General.Map.Config.RightBoundary) p.pos.x = General.Map.Config.RightBoundary; + if (p.pos.y < General.Map.Config.BottomBoundary) p.pos.y = General.Map.Config.BottomBoundary; p.stitch = snaptonearest; p.stitchline = snaptonearest; return p; @@ -301,7 +346,7 @@ namespace CodeImp.DoomBuilder.BuilderModes else { // Normal position - p.pos = mousemappos; + p.pos = vm; p.stitch = snaptonearest; p.stitchline = snaptonearest; return p; @@ -315,14 +360,18 @@ namespace CodeImp.DoomBuilder.BuilderModes } // This draws a point at a specific location - public void DrawPointAt(DrawnVertex p) + public bool DrawPointAt(DrawnVertex p) { - DrawPointAt(p.pos, p.stitch, p.stitchline); + return DrawPointAt(p.pos, p.stitch, p.stitchline); } // This draws a point at a specific location - public void DrawPointAt(Vector2D pos, bool stitch, bool stitchline) + public bool DrawPointAt(Vector2D pos, bool stitch, bool stitchline) { + if (pos.x < General.Map.Config.LeftBoundary || pos.x > General.Map.Config.RightBoundary || + pos.y > General.Map.Config.TopBoundary || pos.y < General.Map.Config.BottomBoundary) + return false; + DrawnVertex newpoint = new DrawnVertex(); newpoint.pos = pos; newpoint.stitch = stitch; @@ -345,6 +394,8 @@ namespace CodeImp.DoomBuilder.BuilderModes FinishDraw(); } } + + return true; } #endregion @@ -498,7 +549,8 @@ namespace CodeImp.DoomBuilder.BuilderModes if(General.Interface.MouseInDisplay) { DrawnVertex newpoint = GetCurrentPosition(); - DrawPointAt(newpoint); + + if(!DrawPointAt(newpoint)) General.Interface.DisplayStatus(StatusType.Warning, "Failed to draw point: outside of map boundaries."); } } diff --git a/Source/Plugins/BuilderModes/ClassicModes/EditSelectionMode.cs b/Source/Plugins/BuilderModes/ClassicModes/EditSelectionMode.cs index c9ad817c..ec8bb34f 100644 --- a/Source/Plugins/BuilderModes/ClassicModes/EditSelectionMode.cs +++ b/Source/Plugins/BuilderModes/ClassicModes/EditSelectionMode.cs @@ -957,6 +957,56 @@ namespace CodeImp.DoomBuilder.BuilderModes // Anything to do? if((selectedthings.Count > 0) || (selectedvertices.Count > 0)) { + Vector2D tl = new Vector2D(General.Map.Config.RightBoundary, General.Map.Config.BottomBoundary); + Vector2D br = new Vector2D(General.Map.Config.LeftBoundary, General.Map.Config.RightBoundary); + + foreach (Vertex v in selectedvertices) + { + if (v.Position.x < tl.x) tl.x = (int)v.Position.x; + if (v.Position.x > br.x) br.x = (int)v.Position.x; + if (v.Position.y > tl.y) tl.y = (int)v.Position.y; + if (v.Position.y < br.y) br.y = (int)v.Position.y; + } + + foreach (Thing t in selectedthings) + { + if (t.Position.x < tl.x) tl.x = (int)t.Position.x; + if (t.Position.x > br.x) br.x = (int)t.Position.x; + if (t.Position.y > tl.y) tl.y = (int)t.Position.y; + if (t.Position.y < br.y) br.y = (int)t.Position.y; + } + + // Check if the selection is outside the map boundaries + if (tl.x < General.Map.Config.LeftBoundary || br.x > General.Map.Config.RightBoundary || + tl.y > General.Map.Config.TopBoundary || br.y < General.Map.Config.BottomBoundary) + { + General.Interface.DisplayStatus(StatusType.Warning, "Error: selection out of map boundaries."); + + // If we're in the process of switching to another mode, reset to selection + // to its old position + if (modealreadyswitching == true) + { + // Reset geometry in original position + int index = 0; + foreach (Vertex v in selectedvertices) + v.Move(vertexpos[index++]); + + index = 0; + foreach (Thing t in selectedthings) + { + t.Rotate(thingangle[index]); + t.Move(thingpos[index++]); + } + + // Resume normal undo/redo recording + General.Map.UndoRedo.IgnorePropChanges = false; + + General.Map.Map.Update(true, true); + } + + return; + } + Cursor.Current = Cursors.AppStarting; if(!pasting) diff --git a/Source/Plugins/BuilderModes/ClassicModes/LinedefsMode.cs b/Source/Plugins/BuilderModes/ClassicModes/LinedefsMode.cs index c85f4c04..37db6237 100644 --- a/Source/Plugins/BuilderModes/ClassicModes/LinedefsMode.cs +++ b/Source/Plugins/BuilderModes/ClassicModes/LinedefsMode.cs @@ -369,8 +369,11 @@ namespace CodeImp.DoomBuilder.BuilderModes bool snaptogrid = General.Interface.ShiftState ^ General.Interface.SnapToGrid; bool snaptonearest = General.Interface.CtrlState ^ General.Interface.AutoMerge; DrawnVertex v = DrawGeometryMode.GetCurrentPosition(mousemappos, snaptonearest, snaptogrid, renderer, new List()); - drawmode.DrawPointAt(v); - General.Editing.ChangeMode(drawmode); + + if (drawmode.DrawPointAt(v)) + General.Editing.ChangeMode(drawmode); + else + General.Interface.DisplayStatus(StatusType.Warning, "Failed to draw point: outside of map boundaries."); } base.OnEditBegin(); diff --git a/Source/Plugins/BuilderModes/ClassicModes/SectorsMode.cs b/Source/Plugins/BuilderModes/ClassicModes/SectorsMode.cs index 9169e9ba..10bef4ca 100644 --- a/Source/Plugins/BuilderModes/ClassicModes/SectorsMode.cs +++ b/Source/Plugins/BuilderModes/ClassicModes/SectorsMode.cs @@ -591,8 +591,11 @@ namespace CodeImp.DoomBuilder.BuilderModes bool snaptogrid = General.Interface.ShiftState ^ General.Interface.SnapToGrid; bool snaptonearest = General.Interface.CtrlState ^ General.Interface.AutoMerge; DrawnVertex v = DrawGeometryMode.GetCurrentPosition(mousemappos, snaptonearest, snaptogrid, renderer, new List()); - drawmode.DrawPointAt(v); - General.Editing.ChangeMode(drawmode); + + if(drawmode.DrawPointAt(v)) + General.Editing.ChangeMode(drawmode); + else + General.Interface.DisplayStatus(StatusType.Warning, "Failed to draw point: outside of map boundaries."); } base.OnEditBegin(); diff --git a/Source/Plugins/BuilderModes/ClassicModes/ThingsMode.cs b/Source/Plugins/BuilderModes/ClassicModes/ThingsMode.cs index 62952e6c..6e6b61e7 100644 --- a/Source/Plugins/BuilderModes/ClassicModes/ThingsMode.cs +++ b/Source/Plugins/BuilderModes/ClassicModes/ThingsMode.cs @@ -347,10 +347,18 @@ namespace CodeImp.DoomBuilder.BuilderModes // Insert a new item and select it for dragging General.Map.UndoRedo.CreateUndo("Insert thing"); Thing t = InsertThing(mousemappos); - General.Map.Map.ClearSelectedThings(); - t.Selected = true; - Highlight(t); - General.Interface.RedrawDisplay(); + + if (t == null) + { + General.Map.UndoRedo.WithdrawUndo(); + } + else + { + General.Map.Map.ClearSelectedThings(); + t.Selected = true; + Highlight(t); + General.Interface.RedrawDisplay(); + } } } @@ -537,6 +545,12 @@ namespace CodeImp.DoomBuilder.BuilderModes // Insert new thing General.Map.UndoRedo.CreateUndo("Insert thing"); Thing t = InsertThing(mousemappos); + + if (t == null) + { + General.Map.UndoRedo.WithdrawUndo(); + return; + } // Edit the thing? if(BuilderPlug.Me.EditNewThing) @@ -562,6 +576,13 @@ namespace CodeImp.DoomBuilder.BuilderModes // This creates a new thing private Thing InsertThing(Vector2D pos) { + if (pos.x < General.Map.Config.LeftBoundary || pos.x > General.Map.Config.RightBoundary || + pos.y > General.Map.Config.TopBoundary || pos.y < General.Map.Config.BottomBoundary) + { + General.Interface.DisplayStatus(StatusType.Warning, "Failed to insert thing: outside of map boundaries."); + return null; + } + // Create things at mouse position Thing t = General.Map.Map.CreateThing(); General.Settings.ApplyDefaultThingSettings(t); diff --git a/Source/Plugins/BuilderModes/ClassicModes/VerticesMode.cs b/Source/Plugins/BuilderModes/ClassicModes/VerticesMode.cs index 5ce63704..08eb848e 100644 --- a/Source/Plugins/BuilderModes/ClassicModes/VerticesMode.cs +++ b/Source/Plugins/BuilderModes/ClassicModes/VerticesMode.cs @@ -322,8 +322,11 @@ namespace CodeImp.DoomBuilder.BuilderModes // Start drawing mode DrawGeometryMode drawmode = new DrawGeometryMode(); DrawnVertex v = DrawGeometryMode.GetCurrentPosition(mousemappos, snaptonearest, snaptogrid, renderer, new List()); - drawmode.DrawPointAt(v); - General.Editing.ChangeMode(drawmode); + + if (drawmode.DrawPointAt(v)) + General.Editing.ChangeMode(drawmode); + else + General.Interface.DisplayStatus(StatusType.Warning, "Failed to draw point: outside of map boundaries."); } }