Fixed a crash when trying to update a vertex handle geometry.

The editor will fail more gracefully when no D3D device is detected.
In some cases the editor was constantly checking D3D device availability when minimized.
Added more DX-related debug output (only in Debug builds).
This commit is contained in:
MaxED 2014-09-17 12:46:47 +00:00
parent 2d9c439325
commit c6b0f38563
10 changed files with 296 additions and 132 deletions

View file

@ -65,8 +65,16 @@ namespace CodeImp.DoomBuilder.Actions
CooperativeLevel.Nonexclusive | CooperativeLevel.Foreground);
// Aquire device
try { mouse.Acquire(); }
catch(Exception) { }
try
{
mouse.Acquire();
}
catch (Exception e)
{
#if DEBUG
System.Console.WriteLine("MouseInput initialization failed: " + e.Message);
#endif
}
// We have no destructor
GC.SuppressFinalize(this);
@ -121,15 +129,34 @@ namespace CodeImp.DoomBuilder.Actions
}
// Reaquire device
try { mouse.Acquire(); }
catch(Exception) { }
try
{
mouse.Acquire();
}
catch (Exception e)
{
#if DEBUG
System.Console.WriteLine("MouseInput process failed: " + e.Message);
#endif
}
return new Vector2D();
}
catch(DirectInputException)
catch(DirectInputException die)
{
#if DEBUG
System.Console.WriteLine("MouseInput process failed: " + die.Message);
#endif
// Reaquire device
try { mouse.Acquire(); }
catch(Exception) { }
try
{
mouse.Acquire();
}
catch (Exception e)
{
#if DEBUG
System.Console.WriteLine("MouseInput process failed: " + die.Message);
#endif
}
return new Vector2D();
}
}

View file

@ -1,32 +1,93 @@
using SlimDX.Direct3D9;
#region ================== Namespaces
using System;
using SlimDX.Direct3D9;
using CodeImp.DoomBuilder.Rendering;
#endregion
namespace CodeImp.DoomBuilder.GZBuilder.Rendering
{
internal sealed class SizelessVisualThingCage
internal sealed class SizelessVisualThingCage : IDisposable, ID3DResource
{
public VertexBuffer Shape { get { return shape; } }
#region ================== Constants
private const float RADIUS = 1.0f;
#endregion
#region ================== Variables
private VertexBuffer shape;
private bool isdisposed;
public SizelessVisualThingCage(Device device) {
float radius = 1.0f;
#endregion
WorldVertex v0 = new WorldVertex(-radius, -radius, 0f);
WorldVertex v1 = new WorldVertex(radius, radius, 0f);
WorldVertex v2 = new WorldVertex(radius, -radius, 0f);
WorldVertex v3 = new WorldVertex(-radius, radius, 0f);
WorldVertex v4 = new WorldVertex(0f, 0f, radius);
WorldVertex v5 = new WorldVertex(0f, 0f, -radius);
#region ================== Properties
WorldVertex[] vs = new WorldVertex[]{ v0, v1, v2, v3, v4, v5 };
public VertexBuffer Shape { get { return shape; } }
shape = new VertexBuffer(device, WorldVertex.Stride * vs.Length, Usage.WriteOnly | Usage.Dynamic, VertexFormat.None, Pool.Default);
shape.Lock(0, WorldVertex.Stride * vs.Length, LockFlags.None).WriteRange<WorldVertex>(vs);
#endregion
#region ================== Constructor / Disposer
public SizelessVisualThingCage()
{
// Create geometry
ReloadResource();
// Register as resource
General.Map.Graphics.RegisterResource(this);
}
public void Dispose()
{
// Not already disposed?
if (!isdisposed)
{
// Clean up
if(shape != null) shape.Dispose();
shape = null;
// Unregister resource
General.Map.Graphics.UnregisterResource(this);
// Done
isdisposed = true;
}
}
#endregion
#region ================== Methods
// This is called resets when the device is reset
// (when resized or display adapter was changed)
public void ReloadResource()
{
WorldVertex v0 = new WorldVertex(-RADIUS, -RADIUS, 0f);
WorldVertex v1 = new WorldVertex(RADIUS, RADIUS, 0f);
WorldVertex v2 = new WorldVertex(RADIUS, -RADIUS, 0f);
WorldVertex v3 = new WorldVertex(-RADIUS, RADIUS, 0f);
WorldVertex v4 = new WorldVertex(0f, 0f, RADIUS);
WorldVertex v5 = new WorldVertex(0f, 0f, -RADIUS);
WorldVertex[] vs = new[] { v0, v1, v2, v3, v4, v5 };
shape = new VertexBuffer(General.Map.Graphics.Device, WorldVertex.Stride * vs.Length, Usage.WriteOnly | Usage.Dynamic, VertexFormat.None, Pool.Default);
shape.Lock(0, WorldVertex.Stride * vs.Length, LockFlags.None).WriteRange(vs);
shape.Unlock();
}
public void Dispose() {
// This is called before a device is reset
// (when resized or display adapter was changed)
public void UnloadResource()
{
// Trash geometry buffer
if(shape != null) shape.Dispose();
shape = null;
}
#endregion
}
}

View file

@ -1,18 +1,66 @@
using System;
#region ================== Namespaces
using System;
using SlimDX.Direct3D9;
using CodeImp.DoomBuilder.Rendering;
#endregion
namespace CodeImp.DoomBuilder.GZBuilder.Rendering
{
sealed class ThingBoundingBox : IDisposable
sealed class ThingBoundingBox : IDisposable, ID3DResource
{
public VertexBuffer Cage { get { return cage; }}
public VertexBuffer Arrow { get { return arrow; } }
#region ================== Variables
private VertexBuffer cage;
private VertexBuffer arrow;
public ThingBoundingBox(Device device) {
private bool isdisposed;
#endregion
#region ================== Properties
public VertexBuffer Cage { get { return cage; } }
public VertexBuffer Arrow { get { return arrow; } }
#endregion
#region ================== Constructor / Disposer
public ThingBoundingBox()
{
// Create geometry
ReloadResource();
// Register as resource
General.Map.Graphics.RegisterResource(this);
}
public void Dispose()
{
// Not already disposed?
if (!isdisposed)
{
if (arrow != null) arrow.Dispose();
if (cage != null) cage.Dispose();
// Unregister resource
General.Map.Graphics.UnregisterResource(this);
// Done
isdisposed = true;
}
}
#endregion
#region ================== Methods
// This is called resets when the device is reset
// (when resized or display adapter was changed)
public void ReloadResource()
{
WorldVertex v0 = new WorldVertex(-1.0f, -1.0f, 0.0f);
WorldVertex v1 = new WorldVertex(-1.0f, 1.0f, 0.0f);
WorldVertex v2 = new WorldVertex(1.0f, 1.0f, 0.0f);
@ -37,10 +85,10 @@ namespace CodeImp.DoomBuilder.GZBuilder.Rendering
v2, v6,
v3, v7 };
cage = new VertexBuffer(device, WorldVertex.Stride * cageVerts.Length, Usage.WriteOnly | Usage.Dynamic, VertexFormat.None, Pool.Default);
cage.Lock(0, WorldVertex.Stride * cageVerts.Length, LockFlags.None).WriteRange<WorldVertex>(cageVerts);
cage = new VertexBuffer(General.Map.Graphics.Device, WorldVertex.Stride * cageVerts.Length, Usage.WriteOnly | Usage.Dynamic, VertexFormat.None, Pool.Default);
cage.Lock(0, WorldVertex.Stride * cageVerts.Length, LockFlags.None).WriteRange(cageVerts);
cage.Unlock();
//arrow
WorldVertex a0 = new WorldVertex(); //start
WorldVertex a1 = new WorldVertex(1.5f, 0.0f, 0.0f); //end
@ -55,14 +103,22 @@ namespace CodeImp.DoomBuilder.GZBuilder.Rendering
a1, a4,
a1, a5};
arrow = new VertexBuffer(device, WorldVertex.Stride * arrowVerts.Length, Usage.WriteOnly | Usage.Dynamic, VertexFormat.None, Pool.Default);
arrow.Lock(0, WorldVertex.Stride * arrowVerts.Length, LockFlags.None).WriteRange<WorldVertex>(arrowVerts);
arrow = new VertexBuffer(General.Map.Graphics.Device, WorldVertex.Stride * arrowVerts.Length, Usage.WriteOnly | Usage.Dynamic, VertexFormat.None, Pool.Default);
arrow.Lock(0, WorldVertex.Stride * arrowVerts.Length, LockFlags.None).WriteRange(arrowVerts);
arrow.Unlock();
}
public void Dispose() {
if (arrow != null) arrow.Dispose();
if (cage != null) cage.Dispose();
// This is called before a device is reset
// (when resized or display adapter was changed)
public void UnloadResource()
{
// Trash geometry buffers
if(cage != null) cage.Dispose();
if(arrow != null) arrow.Dispose();
cage = null;
arrow = null;
}
#endregion
}
}

View file

@ -1,18 +1,66 @@
using CodeImp.DoomBuilder.VisualModes;
#region ================== Namespaces
using System;
using CodeImp.DoomBuilder.VisualModes;
using SlimDX.Direct3D9;
using CodeImp.DoomBuilder.Rendering;
#endregion
namespace CodeImp.DoomBuilder.GZBuilder.Rendering
{
internal sealed class VisualVertexHandle
internal sealed class VisualVertexHandle : IDisposable, ID3DResource
{
#region ================== Variables
private VertexBuffer upper;
private VertexBuffer lower;
private bool isdisposed;
#endregion
#region ================== Properties
public VertexBuffer Upper { get { return upper; } }
private readonly VertexBuffer upper;
public VertexBuffer Lower { get { return lower; } }
private readonly VertexBuffer lower;
public VisualVertexHandle(Device device) {
#endregion
#region ================== Constructor / Disposer
public VisualVertexHandle()
{
// Create geometry
ReloadResource();
// Register as resource
General.Map.Graphics.RegisterResource(this);
}
public void Dispose()
{
// Not already disposed?
if(!isdisposed)
{
if(upper != null) upper.Dispose();
if(lower != null) lower.Dispose();
// Unregister resource
General.Map.Graphics.UnregisterResource(this);
// Done
isdisposed = true;
}
}
#endregion
#region ================== Methods
// This is called resets when the device is reset
// (when resized or display adapter was changed)
public void ReloadResource()
{
float radius = VisualVertex.DEFAULT_SIZE * General.Settings.GZVertexScale3D;
WorldVertex c = new WorldVertex();
@ -36,8 +84,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.Rendering
v2, v3,
v3, v0 };
upper = new VertexBuffer(device, WorldVertex.Stride * vu.Length, Usage.WriteOnly | Usage.Dynamic, VertexFormat.None, Pool.Default);
upper.Lock(0, WorldVertex.Stride * vu.Length, LockFlags.None).WriteRange<WorldVertex>(vu);
upper = new VertexBuffer(General.Map.Graphics.Device, WorldVertex.Stride * vu.Length, Usage.WriteOnly | Usage.Dynamic, VertexFormat.None, Pool.Default);
upper.Lock(0, WorldVertex.Stride * vu.Length, LockFlags.None).WriteRange(vu);
upper.Unlock();
WorldVertex[] vl = new WorldVertex[]{ c, v4,
@ -50,14 +98,22 @@ namespace CodeImp.DoomBuilder.GZBuilder.Rendering
v6, v7,
v7, v4, };
lower = new VertexBuffer(device, WorldVertex.Stride * vl.Length, Usage.WriteOnly | Usage.Dynamic, VertexFormat.None, Pool.Default);
lower.Lock(0, WorldVertex.Stride * vl.Length, LockFlags.None).WriteRange<WorldVertex>(vl);
lower = new VertexBuffer(General.Map.Graphics.Device, WorldVertex.Stride * vl.Length, Usage.WriteOnly | Usage.Dynamic, VertexFormat.None, Pool.Default);
lower.Lock(0, WorldVertex.Stride * vl.Length, LockFlags.None).WriteRange(vl);
lower.Unlock();
}
public void Dispose() {
// This is called before a device is reset
// (when resized or display adapter was changed)
public void UnloadResource()
{
// Trash geometry buffers
if(upper != null) upper.Dispose();
if(lower != null) lower.Dispose();
upper = null;
lower = null;
}
#endregion
}
}

View file

@ -1290,6 +1290,18 @@ namespace CodeImp.DoomBuilder
//mxd
mainwindow.UpdateGZDoomPanel();
settings.LastUsedMapFolder = Path.GetDirectoryName(filename);
settings.FindDefaultDrawSettings();
// Let the plugins know
plugins.OnMapOpenEnd();
// All done
mainwindow.SetupInterface();
mainwindow.RedrawDisplay();
mainwindow.UpdateThingsFilters();
mainwindow.UpdateInterface();
mainwindow.HideInfo();
mainwindow.AddHintsDocker(); //mxd
}
else
{
@ -1301,19 +1313,6 @@ namespace CodeImp.DoomBuilder
mainwindow.ShowSplashDisplay();
}
settings.FindDefaultDrawSettings(); //mxd
// Let the plugins know
plugins.OnMapOpenEnd();
// All done
mainwindow.SetupInterface();
mainwindow.RedrawDisplay();
mainwindow.UpdateThingsFilters();
mainwindow.UpdateInterface();
mainwindow.HideInfo();
mainwindow.AddHintsDocker(); //mxd
if(errorlogger.IsErrorAdded)
{
// Show any errors if preferred

View file

@ -333,10 +333,9 @@ namespace CodeImp.DoomBuilder.Rendering
private PresentParameters CreatePresentParameters(int adapter)
{
PresentParameters displaypp = new PresentParameters();
DisplayMode currentmode;
// Get current display mode
currentmode = d3d.Adapters[adapter].CurrentDisplayMode;
DisplayMode currentmode = d3d.Adapters[adapter].CurrentDisplayMode;
// Make present parameters
displaypp.Windowed = true;
@ -398,9 +397,12 @@ namespace CodeImp.DoomBuilder.Rendering
// Reset the device
device.Reset(displaypp);
}
catch(Exception)
catch(Exception e)
{
// Failed to re-initialize
#if DEBUG
Console.WriteLine("Device reset failed: " + e.Message);
#endif
return false;
}
@ -523,7 +525,7 @@ namespace CodeImp.DoomBuilder.Rendering
}
else
{
// Read to go!
// Ready to go!
return true;
}
}

View file

@ -145,19 +145,8 @@ namespace CodeImp.DoomBuilder.Rendering
if(!isdisposed)
{
// Clean up
//mxd
if(bbox != null) bbox.Dispose();
if(vertexHandle != null) vertexHandle.Dispose();
if(sizelessThingHandle != null) sizelessThingHandle.Dispose();
if(selectionimage != null) selectionimage.Dispose();
if(highlightimage != null) highlightimage.Dispose();
//mxd
bbox = null;
vertexHandle = null;
sizelessThingHandle = null;
selectionimage = null;
highlightimage = null;
@ -175,19 +164,9 @@ namespace CodeImp.DoomBuilder.Rendering
public override void UnloadResource()
{
crosshairverts = null;
//mxd
if(bbox != null) bbox.Dispose();
if(vertexHandle != null) vertexHandle.Dispose();
if(sizelessThingHandle != null) sizelessThingHandle.Dispose();
if(selectionimage != null) selectionimage.Dispose();
if(highlightimage != null) highlightimage.Dispose();
//mxd
vertexHandle = null;
bbox = null;
sizelessThingHandle = null;
selectionimage = null;
highlightimage = null;
}
@ -197,7 +176,6 @@ namespace CodeImp.DoomBuilder.Rendering
public override void ReloadResource()
{
CreateMatrices2D();
SetupHelperObjects();
SetupTextures();
}
@ -256,15 +234,16 @@ namespace CodeImp.DoomBuilder.Rendering
//mxd
private void SetupHelperObjects()
{
bbox = new ThingBoundingBox(graphics.Device);
sizelessThingHandle = new SizelessVisualThingCage(graphics.Device);
UpdateVertexHandle();
bbox = new ThingBoundingBox();
sizelessThingHandle = new SizelessVisualThingCage();
vertexHandle = new VisualVertexHandle();
}
//mxd
internal void UpdateVertexHandle()
{
vertexHandle = new VisualVertexHandle(graphics.Device);
vertexHandle.UnloadResource();
vertexHandle.ReloadResource();
}
#endregion

View file

@ -124,7 +124,6 @@ namespace CodeImp.DoomBuilder.VisualModes
// This updates the visual sector
public void Update()
{
DataStream bufferstream;
int numverts = 0;
int v = 0;
@ -143,12 +142,12 @@ namespace CodeImp.DoomBuilder.VisualModes
Usage.WriteOnly | Usage.Dynamic, VertexFormat.None, Pool.Default);
// Fill the buffer
bufferstream = geobuffer.Lock(0, WorldVertex.Stride * numverts, LockFlags.Discard);
DataStream bufferstream = geobuffer.Lock(0, WorldVertex.Stride * numverts, LockFlags.Discard);
foreach(VisualGeometry g in allgeometry)
{
if((g.Vertices != null) && (g.Vertices.Length > 0))
{
bufferstream.WriteRange<WorldVertex>(g.Vertices);
bufferstream.WriteRange(g.Vertices);
g.VertexOffset = v;
v += g.Vertices.Length;
}

View file

@ -390,8 +390,6 @@ namespace CodeImp.DoomBuilder.Windows
// Generic event that invokes the tagged action
public void InvokeTaggedAction(object sender, EventArgs e)
{
//string asmname;
this.Update();
if(sender is ToolStripItem)
@ -585,8 +583,6 @@ namespace CodeImp.DoomBuilder.Windows
// Window is being closed
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
int windowstate;
if(e.CloseReason != CloseReason.ApplicationExitCall)
{
//mxd
@ -610,6 +606,7 @@ namespace CodeImp.DoomBuilder.Windows
General.Actions.UnbindMethods(this);
// Determine window state to save
int windowstate;
if(this.WindowState != FormWindowState.Minimized)
windowstate = (int)this.WindowState;
else
@ -1030,6 +1027,9 @@ namespace CodeImp.DoomBuilder.Windows
// Disable timer (only redraw once)
redrawtimer.Enabled = false;
// Don't do anything when minimized (mxd)
if(this.WindowState == FormWindowState.Minimized) return;
// Resume control layouts
//if(displayresized) General.LockWindowUpdate(IntPtr.Zero);
@ -1748,40 +1748,30 @@ namespace CodeImp.DoomBuilder.Windows
}
}
// This hides redundant seperators and shows single seperators
// This hides redundant separators
internal void UpdateSeparators()
{
UpdateToolStripSeparators(toolbar.Items, false);
UpdateToolStripSeparators(menumode.DropDownItems, true);
UpdateToolStripSeparators(toolbar.Items);
UpdateToolStripSeparators(menumode.DropDownItems);
//mxd
UpdateToolStripSeparators(modestoolbar.Items, false);
UpdateToolStripSeparators(modecontrolsloolbar.Items, false);
UpdateToolStripSeparators(modestoolbar.Items);
UpdateToolStripSeparators(modecontrolsloolbar.Items);
}
// This updates the seperators
// Hides redundant seperators and shows single seperators
private static void UpdateToolStripSeparators(ToolStripItemCollection items, bool defaultvisible)
// This hides redundant separators (mxd)
private static void UpdateToolStripSeparators(ToolStripItemCollection items)
{
ToolStripItem pvi = null;
foreach(ToolStripItem i in items)
{
bool separatorvisible = false;
// This is a seperator?
if(i is ToolStripSeparator)
if (i is ToolStripSeparator)
{
// Make visible when previous item was not a seperator
separatorvisible = !(pvi is ToolStripSeparator) && (pvi != null);
i.Visible = separatorvisible;
i.Visible = !(pvi != null && (!pvi.Visible || pvi is ToolStripSeparator));
}
// Keep as previous visible item
if(i.Visible || separatorvisible || (defaultvisible && !(i is ToolStripSeparator))) pvi = i;
pvi = i;
}
// Hide last item if it is a seperator
if(pvi is ToolStripSeparator) pvi.Visible = false;
}
// This enables or disables all editing mode items and toolbar buttons

View file

@ -197,6 +197,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
undoredodocker = new Docker("undoredo", "Undo / Redo", undoredopanel);
General.Interface.AddDocker(undoredodocker);
//mxd. Create Overrides docker
drawingOverridesPanel = new SectorDrawingOptionsPanel();
drawingOverridesDocker = new Docker("drawingoverrides", "Draw Settings", drawingOverridesPanel);
//mxd
General.Actions.BindMethods(this);
}
@ -209,8 +213,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
// Clean up
General.Interface.RemoveDocker(undoredodocker);
General.Interface.RemoveDocker(drawingOverridesDocker); //mxd
undoredopanel.Dispose();
drawingOverridesPanel.Dispose(); //mxd
menusform.Unregister();
menusform.Dispose();
menusform = null;
@ -375,11 +381,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
undoredopanel.UpdateList();
//mxd
if (drawingOverridesPanel == null) {
drawingOverridesPanel = new SectorDrawingOptionsPanel();
drawingOverridesDocker = new Docker("drawingoverrides", "Draw Settings", drawingOverridesPanel);
General.Interface.AddDocker(drawingOverridesDocker);
}
General.Interface.AddDocker(drawingOverridesDocker);
drawingOverridesPanel.Setup();
}
@ -391,11 +393,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
undoredopanel.UpdateList();
//mxd
if (drawingOverridesPanel == null) {
drawingOverridesPanel = new SectorDrawingOptionsPanel();
drawingOverridesDocker = new Docker("drawingoverrides", "Draw Settings", drawingOverridesPanel);
General.Interface.AddDocker(drawingOverridesDocker);
}
General.Interface.AddDocker(drawingOverridesDocker);
drawingOverridesPanel.Setup();
General.Map.Renderer2D.UpdateExtraFloorFlag(); //mxd
}
@ -408,9 +406,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
//mxd
General.Interface.RemoveDocker(drawingOverridesDocker);
drawingOverridesDocker = null;
drawingOverridesPanel.Dispose();
drawingOverridesPanel = null;
//mxd. Save settings
saveSettings();