Things can now be moved, insterted and deleted in Visual modes.

"Place thing at cursor position" Action places Things much more precisely now.
This commit is contained in:
MaxED 2012-07-05 13:48:08 +00:00
parent 24e1fcad6a
commit fcd29375c8
9 changed files with 154 additions and 44 deletions

View file

@ -26,9 +26,9 @@
<li>Fog rendering (including colored fog in maps in UDMF format).</li>
<li><a href="gz_gldefs.html">MD2 and MD3 models</a> rendering in 2D and 3D modes.</li>
<li><a href="gz_mode_drawrect.html">Draw Rectangle</a>, <a href="gz_mode_drawellipse.html">Draw Ellipse</a> and <a href="gz_mode_drawbridge.html">Bridge</a> modes.</li>
<li>Ability to <a href="gz_actions.html#movething">move</a>, insert and delete Things in Visual modes.</li>
<li><a href="gz_actions.html#newtestmap">"Test Map from current position"</a> feature.</li>
<li><a href="gz_settings.html">"Sync camera position between 2D and 3D modes"</a> feature.</li>
<li><a href="gz_actions.html#movething">"Move Things horizontally in Visual Modes"</a> feature.</li>
<li><a href="gz_actions.html#movethingtocursor">"Place Things at cursor position in Visual Modes"</a> feature.</li>
<li>PNG image format support.</li>
<li><a href="gz_plug_colorpicker.html">Color Picker plugin.</a></li>

View file

@ -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<VisualThing>());
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;
}

View file

@ -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; } }
/// <summary>

View file

@ -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

View file

@ -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) {

View file

@ -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<IVisualEventReceiver> objs = GetSelectedObjects(true, true, true);
foreach(IVisualEventReceiver i in objs) i.OnInsert();
PostAction();
}
[BeginAction("deleteitem", BaseAction = true)]
public void Delete()
{
PreAction(UndoGroup.None);
List<IVisualEventReceiver> 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<Thing> { 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<IVisualEventReceiver> 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
}

View file

@ -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()

View file

@ -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();

View file

@ -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()