From fcd29375c8f272ced12dec6181aec76c9a5d7c02 Mon Sep 17 00:00:00 2001 From: MaxED Date: Thu, 5 Jul 2012 13:48:08 +0000 Subject: [PATCH] Things can now be moved, insterted and deleted in Visual modes. "Place thing at cursor position" Action places Things much more precisely now. --- Help/gz_features.html | 2 +- Source/Core/Rendering/Renderer3D.cs | 15 ++- Source/Core/VisualModes/VisualGeometry.cs | 4 +- Source/Core/VisualModes/VisualMode.cs | 34 +++++- Source/Core/VisualModes/VisualThing.cs | 9 +- .../VisualModes/BaseVisualMode.cs | 106 +++++++++++++++--- .../VisualModes/BaseVisualThing.cs | 8 +- .../VisualModes/BaseVisualMode.cs | 7 +- .../VisualModes/BaseVisualThing.cs | 13 +-- 9 files changed, 154 insertions(+), 44 deletions(-) diff --git a/Help/gz_features.html b/Help/gz_features.html index 09eefa43..c1ed692a 100644 --- a/Help/gz_features.html +++ b/Help/gz_features.html @@ -26,9 +26,9 @@
  • Fog rendering (including colored fog in maps in UDMF format).
  • MD2 and MD3 models rendering in 2D and 3D modes.
  • Draw Rectangle, Draw Ellipse and Bridge modes.
  • +
  • Ability to move, insert and delete Things in Visual modes.
  • "Test Map from current position" feature.
  • "Sync camera position between 2D and 3D modes" feature.
  • -
  • "Move Things horizontally in Visual Modes" feature.
  • "Place Things at cursor position in Visual Modes" feature.
  • PNG image format support.
  • Color Picker plugin.
  • diff --git a/Source/Core/Rendering/Renderer3D.cs b/Source/Core/Rendering/Renderer3D.cs index 438e3a68..24af1e83 100644 --- a/Source/Core/Rendering/Renderer3D.cs +++ b/Source/Core/Rendering/Renderer3D.cs @@ -1186,10 +1186,6 @@ namespace CodeImp.DoomBuilder.Rendering //mxd. gather models if (General.Settings.GZDrawModels && (!General.Settings.GZDrawSelectedModelsOnly || t.Selected) && t.Thing.IsModel) { ModeldefEntry mde = General.Map.Data.ModeldefEntries[t.Thing.Type]; - - //if (!isThingOnScreen(t.BoundingBox)) - //return; - if (!thingsWithModel.ContainsKey(mde)) thingsWithModel.Add(mde, new List()); thingsWithModel[mde].Add(t); @@ -1220,13 +1216,13 @@ namespace CodeImp.DoomBuilder.Rendering Vector3D thingNormal = D3DDevice.V3D(bbox[0]) - cameraposition; //bbox[0] is always thing center if (Vector3D.DotProduct(camNormal, thingNormal) < 0) { //behind camera plane - //GZBuilder.GZGeneral.TraceLine("Skipped geo. Vector3D.DotProduct(camNormal, thingNormal) < 0"); + //GZBuilder.GZGeneral.Trace("Skipped geo. Vector3D.DotProduct(camNormal, thingNormal) < 0"); return false; } int len = bbox.Length; Vector3 screenPos; - int behingCount = 0; + int behindCount = 0; int leftCount = 0; int rightCount = 0; int topCount = 0; @@ -1240,7 +1236,7 @@ namespace CodeImp.DoomBuilder.Rendering return true; if (screenPos.Z < 0) - behingCount++; + behindCount++; if (screenPos.X < 0) leftCount++; @@ -1252,8 +1248,11 @@ namespace CodeImp.DoomBuilder.Rendering bottomCount++; } - if (behingCount == len || leftCount == len || rightCount == len || topCount == len || bottomCount == len) + if (behindCount == len || leftCount == len || rightCount == len || topCount == len || bottomCount == len) { + //dbg + //GZBuilder.GZGeneral.Trace("Skipped geo. Not on screen"); return false; //Not on screen + } return true; } diff --git a/Source/Core/VisualModes/VisualGeometry.cs b/Source/Core/VisualModes/VisualGeometry.cs index 66f83301..74c4b179 100644 --- a/Source/Core/VisualModes/VisualGeometry.cs +++ b/Source/Core/VisualModes/VisualGeometry.cs @@ -91,14 +91,14 @@ namespace CodeImp.DoomBuilder.VisualModes #region ================== Properties // Internal properties - internal WorldVertex[] Vertices { get { return vertices; } } + public WorldVertex[] Vertices { get { return vertices; } } //mxd internal int VertexOffset { get { return vertexoffset; } set { vertexoffset = value; } } internal int Triangles { get { return triangles; } } internal int RenderPassInt { get { return renderpass; } } internal Color4 ModColor4 { get { return modcolor4; } } //mxd - internal Vector3[] BoundingBox { get { return boundingBox; } } + public Vector3[] BoundingBox { get { return boundingBox; } } public VisualGeometryType GeometryType { get { return geoType; } } /// diff --git a/Source/Core/VisualModes/VisualMode.cs b/Source/Core/VisualModes/VisualMode.cs index b440bccc..ef0c2530 100644 --- a/Source/Core/VisualModes/VisualMode.cs +++ b/Source/Core/VisualModes/VisualMode.cs @@ -425,17 +425,43 @@ namespace CodeImp.DoomBuilder.VisualModes [BeginAction("placethingatcursor", BaseAction = true)] protected void placeThingAtCursor() { + Vector2D hitCoords = getHitPosition(); + if (!hitCoords.IsFinite()) { + General.Interface.DisplayStatus(StatusType.Warning, "Cannot place Thing here"); + return; + } + + moveSelectedThings(new Vector2D((float)Math.Round(hitCoords.x), (float)Math.Round(hitCoords.y)), true); + } + + //mxd. + protected Vector2D getHitPosition() { Vector3D start = General.Map.VisualCamera.Position; Vector3D delta = General.Map.VisualCamera.Target - General.Map.VisualCamera.Position; delta = delta.GetFixedLength(General.Settings.ViewDistance * 0.98f); VisualPickResult target = PickObject(start, start + delta); - if (target.picked == null) { - General.Interface.DisplayStatus(StatusType.Warning, "Cannot place Thing here"); - return; + if (target.picked == null) return new Vector2D(float.NaN, float.NaN); + + //now find where exactly did we hit + Vector2D hitCoords = new Vector2D(); + if (target.picked is VisualGeometry) { + VisualGeometry vg = target.picked as VisualGeometry; + hitCoords = getIntersection(start, start + delta, new Vector3D(vg.BoundingBox[0].X, vg.BoundingBox[0].Y, vg.BoundingBox[0].Z), new Vector3D(vg.Vertices[0].nx, vg.Vertices[0].ny, vg.Vertices[0].nz)); + } else if (target.picked is VisualThing) { + VisualThing vt = target.picked as VisualThing; + hitCoords = getIntersection(start, start + delta, new Vector3D(vt.BoundingBox[0].X, vt.BoundingBox[0].Y, vt.BoundingBox[0].Z), D3DDevice.V3D(vt.Center - vt.PositionV3)); + } else { + return new Vector2D(float.NaN, float.NaN); } - moveSelectedThings(new Vector2D((float)Math.Round(target.hitpos.x), (float)Math.Round(target.hitpos.y)), true); + return hitCoords; + } + + //mxd. this checks intersection between line and plane + protected Vector2D getIntersection(Vector3D start, Vector3D end, Vector3D planeCenter, Vector3D planeNormal) { + Vector3D delta = new Vector3D(planeCenter.x - start.x, planeCenter.y - start.y, planeCenter.z - start.z); + return start + Vector3D.DotProduct(planeNormal, delta) / Vector3D.DotProduct(planeNormal, end - start) * (end - start); } //should move selected things in specified direction diff --git a/Source/Core/VisualModes/VisualThing.cs b/Source/Core/VisualModes/VisualThing.cs index 63503940..c2191038 100644 --- a/Source/Core/VisualModes/VisualThing.cs +++ b/Source/Core/VisualModes/VisualThing.cs @@ -499,7 +499,14 @@ namespace CodeImp.DoomBuilder.VisualModes //mxd. update bounding box public void UpdateBoundingBox() { - updateBoundingBox(lightRadius, lightRadius * 2f); + //updateBoundingBox(lightRadius, lightRadius * 2f); + if (thing.IsModel) { + updateBoundingBoxForModel(); + } else if (lightType != -1 && lightRadius > thing.Size) { + updateBoundingBox(lightRadius, lightRadius * 2); + } else { + updateBoundingBox((int)thing.Size, thingHeight); + } } private void updateBoundingBox(float width, float height) { diff --git a/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs b/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs index 8bbcab40..b00dc81f 100644 --- a/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs +++ b/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs @@ -959,6 +959,40 @@ namespace CodeImp.DoomBuilder.BuilderModes return new NullVisualEventReceiver(); } } + + //mxd. Copied from BuilderModes.ThingsMode + // 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 thing + Thing t = General.Map.Map.CreateThing(); + if (t != null) { + General.Settings.ApplyDefaultThingSettings(t); + t.Move(pos); + t.UpdateConfiguration(); + General.Map.IsChanged = true; + + // Update things filter so that it includes this thing + General.Map.ThingsFilter.Update(); + + // Snap to grid enabled? + if (General.Interface.SnapToGrid) { + // Snap to grid + t.SnapToGrid(); + } + else { + // Snap to map format accuracy + t.SnapToAccuracy(); + } + } + + return t; + } #endregion @@ -1308,24 +1342,62 @@ namespace CodeImp.DoomBuilder.BuilderModes foreach(IVisualEventReceiver i in objs) i.OnPasteProperties(); PostAction(); } - - [BeginAction("insertitem", BaseAction = true)] - public void Insert() - { - PreAction(UndoGroup.None); - List objs = GetSelectedObjects(true, true, true); - foreach(IVisualEventReceiver i in objs) i.OnInsert(); - PostAction(); - } - [BeginAction("deleteitem", BaseAction = true)] - public void Delete() - { - PreAction(UndoGroup.None); - List objs = GetSelectedObjects(true, true, true); - foreach(IVisualEventReceiver i in objs) i.OnDelete(); - PostAction(); - } + //mxd. now we can actually insert things in Visual modes + [BeginAction("insertitem", BaseAction = true)] + public void Insert() { + Vector2D hitpos = getHitPosition(); + + if (!hitpos.IsFinite()) { + General.Interface.DisplayStatus(StatusType.Warning, "Cannot insert item here!"); + return; + } + + ClearSelection(); + PreActionNoChange(); + + General.Map.UndoRedo.CreateUndo("Insert thing"); + + Thing t = InsertThing(new Vector2D(hitpos.x, hitpos.y)); + + if (t == null) { + General.Map.UndoRedo.WithdrawUndo(); + return; + } + + // Edit the thing? + if (BuilderPlug.Me.EditNewThing) + General.Interface.ShowEditThings(new List { t }); + + //add thing to blockmap + blockmap.AddThing(t); + + General.Interface.DisplayStatus(StatusType.Action, "Inserted a new thing."); + General.Map.IsChanged = true; + General.Map.ThingsFilter.Update(); + PostAction(); + } + + [BeginAction("deleteitem", BaseAction = true)] //mxd. now we can actually delete things in Visual modes + public void Delete() { + List objs = GetSelectedObjects(false, false, true); + if (objs.Count == 0) return; + + string rest = objs.Count + " thing" + (objs.Count > 1 ? "s." : "."); + + //make undo + General.Map.UndoRedo.CreateUndo("Delete " + rest); + General.Interface.DisplayStatus(StatusType.Info, "Deleted " + rest); + + PreActionNoChange(); + foreach (IVisualEventReceiver i in objs) i.OnDelete(); //are they deleted from BlockMap automatically?.. + + // Update cache values + General.Map.IsChanged = true; + General.Map.ThingsFilter.Update(); + + PostAction(); + } #endregion } diff --git a/Source/Plugins/BuilderModes/VisualModes/BaseVisualThing.cs b/Source/Plugins/BuilderModes/VisualModes/BaseVisualThing.cs index cf6124f4..1554fd3d 100644 --- a/Source/Plugins/BuilderModes/VisualModes/BaseVisualThing.cs +++ b/Source/Plugins/BuilderModes/VisualModes/BaseVisualThing.cs @@ -388,7 +388,7 @@ namespace CodeImp.DoomBuilder.BuilderModes public virtual void OnProcess(double deltatime) { } public virtual void OnTextureFloodfill() { } public virtual void OnInsert() { } - public virtual void OnDelete() { } + //public virtual void OnDelete() { } public virtual void ApplyTexture(string texture) { } public virtual void ApplyUpperUnpegged(bool set) { } public virtual void ApplyLowerUnpegged(bool set) { } @@ -410,6 +410,12 @@ namespace CodeImp.DoomBuilder.BuilderModes mode.AddSelectedObject(this); } } + + //mxd. Delete thing + public virtual void OnDelete() { + this.Thing.Dispose(); + this.Dispose(); + } // Copy properties public virtual void OnCopyProperties() diff --git a/Source/Plugins/GZDoomEditing/VisualModes/BaseVisualMode.cs b/Source/Plugins/GZDoomEditing/VisualModes/BaseVisualMode.cs index f7cfff7d..d79a0b77 100644 --- a/Source/Plugins/GZDoomEditing/VisualModes/BaseVisualMode.cs +++ b/Source/Plugins/GZDoomEditing/VisualModes/BaseVisualMode.cs @@ -1591,9 +1591,9 @@ namespace CodeImp.DoomBuilder.GZDoomEditing [BeginAction("insertitem", BaseAction = true)] //mxd. now we can actually insert things in Visual modes public void Insert() { - PickTarget(); + Vector2D hitpos = getHitPosition(); - if (target.picked == null) { + if (!hitpos.IsFinite()) { General.Interface.DisplayStatus(StatusType.Warning, "Cannot insert item here!"); return; } @@ -1602,7 +1602,8 @@ namespace CodeImp.DoomBuilder.GZDoomEditing PreActionNoChange(); General.Map.UndoRedo.CreateUndo("Insert thing"); - Thing t = InsertThing(new Vector2D(target.hitpos.x, target.hitpos.y)); + + Thing t = InsertThing(new Vector2D(hitpos.x, hitpos.y)); if (t == null) { General.Map.UndoRedo.WithdrawUndo(); diff --git a/Source/Plugins/GZDoomEditing/VisualModes/BaseVisualThing.cs b/Source/Plugins/GZDoomEditing/VisualModes/BaseVisualThing.cs index ecce5255..cb0365bc 100644 --- a/Source/Plugins/GZDoomEditing/VisualModes/BaseVisualThing.cs +++ b/Source/Plugins/GZDoomEditing/VisualModes/BaseVisualThing.cs @@ -428,13 +428,6 @@ namespace CodeImp.DoomBuilder.GZDoomEditing public virtual void ApplyTexture(string texture) { } public virtual void ApplyUpperUnpegged(bool set) { } public virtual void ApplyLowerUnpegged(bool set) { } - - //mxd. Delete thing - public virtual void OnDelete() { - this.Thing.Dispose(); - this.Dispose(); - } - // Return texture name public virtual string GetTextureName() { return ""; } @@ -453,6 +446,12 @@ namespace CodeImp.DoomBuilder.GZDoomEditing mode.AddSelectedObject(this); } } + + //mxd. Delete thing + public virtual void OnDelete() { + this.Thing.Dispose(); + this.Dispose(); + } // Copy properties public virtual void OnCopyProperties()