Changed: when entering Visual mode, the camera is no longer positioned at "Visual Mode camera" thing when "Sync camera position between 2D and 3D mode" setting is enabled.

Changed: Visplane Explorer plugin is now initialized only in Doom/Hexen map formats.
Fixed, Visual mode: thing cages were not rendered when things didn't have a sprite.
Fixed, Internal, DB2 bug: Plug.Dispose() was never called.
This commit is contained in:
MaxED 2015-10-09 21:57:32 +00:00
parent 13c3155db5
commit 77d2a15f7f
11 changed files with 188 additions and 157 deletions

View file

@ -1048,9 +1048,9 @@ namespace CodeImp.DoomBuilder
// Clean up // Clean up
if(map != null) { map.Dispose(); map = null; } if(map != null) { map.Dispose(); map = null; }
if(editing != null) { editing.Dispose(); editing = null; } if(editing != null) { editing.Dispose(); editing = null; }
if(plugins != null) { plugins.Dispose(); plugins = null; }
if(mainwindow != null) { mainwindow.Dispose(); mainwindow = null; } if(mainwindow != null) { mainwindow.Dispose(); mainwindow = null; }
if(actions != null) { actions.Dispose(); actions = null; } if(actions != null) { actions.Dispose(); actions = null; }
if(plugins != null) { plugins.Dispose(); plugins = null; }
if(types != null) { types.Dispose(); types = null; } if(types != null) { types.Dispose(); types = null; }
try { D3DDevice.Terminate(); } catch(Exception) { } try { D3DDevice.Terminate(); } catch(Exception) { }

View file

@ -44,7 +44,7 @@ using System.Text;
namespace CodeImp.DoomBuilder namespace CodeImp.DoomBuilder
{ {
internal static class MurmurHash2 public static class MurmurHash2
{ {
private const UInt32 m = 0x5bd1e995; private const UInt32 m = 0x5bd1e995;
private const Int32 r = 24; private const Int32 r = 24;

View file

@ -42,7 +42,7 @@ namespace CodeImp.DoomBuilder.Plugins
private Plug plug; private Plug plug;
// Unique name used to refer to this assembly // Unique name used to refer to this assembly
private string name; private readonly string name;
// Disposing // Disposing
private bool isdisposed; private bool isdisposed;
@ -122,6 +122,8 @@ namespace CodeImp.DoomBuilder.Plugins
if(!isdisposed) if(!isdisposed)
{ {
// Clean up // Clean up
plug.Dispose(); //mxd
plug = null; //mxd
asm = null; asm = null;
// Done // Done

View file

@ -217,7 +217,7 @@ namespace CodeImp.DoomBuilder.Plugins
// Go for all plugins the find the one with matching assembly // Go for all plugins the find the one with matching assembly
foreach(Plugin p in plugins) foreach(Plugin p in plugins)
{ {
if(p.Assembly == assembly) return p; if(Equals(p.Assembly, assembly)) return p;
} }
// Nothing found // Nothing found

View file

@ -28,4 +28,4 @@ using System.Runtime.InteropServices;
// Build Number // Build Number
// Revision // Revision
// //
[assembly: AssemblyVersion("2.3.0.2201")] [assembly: AssemblyVersion("2.3.0.2411")]

View file

@ -30,7 +30,6 @@ namespace CodeImp.DoomBuilder.VisualModes
private float anglexy, anglez; private float anglexy, anglez;
private Sector sector; private Sector sector;
private float gravity = 1.0f; //mxd private float gravity = 1.0f; //mxd
private bool udmf; //mxd
#endregion #endregion
@ -56,7 +55,6 @@ namespace CodeImp.DoomBuilder.VisualModes
anglexy = 0.0f; anglexy = 0.0f;
anglez = Angle2D.PI; anglez = Angle2D.PI;
sector = null; sector = null;
udmf = General.Map.UDMF; //mxd
PositionAtThing(); PositionAtThing();
} }
@ -101,12 +99,18 @@ namespace CodeImp.DoomBuilder.VisualModes
// Returns false when it couldn't find a 3D Camera Thing // Returns false when it couldn't find a 3D Camera Thing
public virtual bool PositionAtThing() public virtual bool PositionAtThing()
{ {
if(General.Settings.GZSynchCameras) return true; //mxd
Thing modething = null; Thing modething = null;
Vector3D delta;
// Find a 3D Mode thing // Find a 3D Mode thing
foreach(Thing t in General.Map.Map.Things) foreach(Thing t in General.Map.Map.Things)
if(t.Type == General.Map.Config.Start3DModeThingType) modething = t; {
if(t.Type == General.Map.Config.Start3DModeThingType)
{
modething = t;
break; //mxd
}
}
// Found one? // Found one?
if(modething != null) if(modething != null)
@ -118,7 +122,7 @@ namespace CodeImp.DoomBuilder.VisualModes
// Position camera here // Position camera here
Vector3D wantedposition = new Vector3D(modething.Position.x, modething.Position.y, z + THING_Z_OFFSET); Vector3D wantedposition = new Vector3D(modething.Position.x, modething.Position.y, z + THING_Z_OFFSET);
delta = position - wantedposition; Vector3D delta = position - wantedposition;
if(delta.GetLength() > 1.0f) position = wantedposition; if(delta.GetLength() > 1.0f) position = wantedposition;
// Change angle // Change angle
@ -138,11 +142,18 @@ namespace CodeImp.DoomBuilder.VisualModes
// Returns false when it couldn't find a 3D Camera Thing // Returns false when it couldn't find a 3D Camera Thing
public virtual bool ApplyToThing() public virtual bool ApplyToThing()
{ {
if(General.Settings.GZSynchCameras) return true; //mxd
Thing modething = null; Thing modething = null;
// Find a 3D Mode thing // Find a 3D Mode thing
foreach(Thing t in General.Map.Map.Things) foreach(Thing t in General.Map.Map.Things)
if(t.Type == General.Map.Config.Start3DModeThingType) modething = t; {
if(t.Type == General.Map.Config.Start3DModeThingType)
{
modething = t;
break; //mxd
}
}
// Found one? // Found one?
if(modething != null) if(modething != null)
@ -162,7 +173,7 @@ namespace CodeImp.DoomBuilder.VisualModes
//mxd //mxd
private void UpdateGravity() private void UpdateGravity()
{ {
if(!udmf || sector == null) return; if(!General.Map.UDMF || sector == null) return;
gravity = sector.Fields.GetValue("gravity", 1.0f); gravity = sector.Fields.GetValue("gravity", 1.0f);
} }

View file

@ -227,11 +227,85 @@ namespace CodeImp.DoomBuilder.VisualModes
} }
/// <summary> /// <summary>
/// Sets the color of the cage around the thing geometry. /// Sets the color of the cage around the thing geometry and rebuilds the thing cage.
/// </summary> /// </summary>
protected void SetCageColor(PixelColor color) protected void UpdateThingCage(PixelColor color)
{ {
cagecolor = color.ToColorValue(); cagecolor = color.ToColorValue();
// Trash cage buffer
if(cagebuffer != null) cagebuffer.Dispose();
cagebuffer = null;
// Make a new cage
List<WorldVertex> cageverts;
if(sizeless)
{
WorldVertex v0 = new WorldVertex(-info.Radius + position_v3.X, -info.Radius + position_v3.Y, position_v3.Z);
WorldVertex v1 = new WorldVertex(info.Radius + position_v3.X, info.Radius + position_v3.Y, position_v3.Z);
WorldVertex v2 = new WorldVertex(info.Radius + position_v3.X, -info.Radius + position_v3.Y, position_v3.Z);
WorldVertex v3 = new WorldVertex(-info.Radius + position_v3.X, info.Radius + position_v3.Y, position_v3.Z);
WorldVertex v4 = new WorldVertex(position_v3.X, position_v3.Y, info.Radius + position_v3.Z);
WorldVertex v5 = new WorldVertex(position_v3.X, position_v3.Y, -info.Radius + position_v3.Z);
cageverts = new List<WorldVertex>(new[] { v0, v1, v2, v3, v4, v5 });
}
else
{
float top = position_v3.Z + info.Height;
float bottom = position_v3.Z;
WorldVertex v0 = new WorldVertex(-info.Radius + position_v3.X, -info.Radius + position_v3.Y, bottom);
WorldVertex v1 = new WorldVertex(-info.Radius + position_v3.X, info.Radius + position_v3.Y, bottom);
WorldVertex v2 = new WorldVertex(info.Radius + position_v3.X, info.Radius + position_v3.Y, bottom);
WorldVertex v3 = new WorldVertex(info.Radius + position_v3.X, -info.Radius + position_v3.Y, bottom);
WorldVertex v4 = new WorldVertex(-info.Radius + position_v3.X, -info.Radius + position_v3.Y, top);
WorldVertex v5 = new WorldVertex(-info.Radius + position_v3.X, info.Radius + position_v3.Y, top);
WorldVertex v6 = new WorldVertex(info.Radius + position_v3.X, info.Radius + position_v3.Y, top);
WorldVertex v7 = new WorldVertex(info.Radius + position_v3.X, -info.Radius + position_v3.Y, top);
cageverts = new List<WorldVertex>(new[] { v0, v1,
v1, v2,
v2, v3,
v3, v0,
v4, v5,
v5, v6,
v6, v7,
v7, v4,
v0, v4,
v1, v5,
v2, v6,
v3, v7 });
}
// Make new arrow
if(Thing.IsDirectional)
{
Matrix transform = Matrix.Scaling(info.Radius, info.Radius, info.Radius)
* (Matrix.RotationY(-Thing.RollRad) * Matrix.RotationX(-Thing.PitchRad) * Matrix.RotationZ(Thing.Angle))
* (sizeless ? position : position * Matrix.Translation(0.0f, 0.0f, thingheight / 2f));
WorldVertex a0 = new WorldVertex(Vector3D.Transform(0.0f, 0.0f, 0.0f, transform)); //start
WorldVertex a1 = new WorldVertex(Vector3D.Transform(0.0f, -1.5f, 0.0f, transform)); //end
WorldVertex a2 = new WorldVertex(Vector3D.Transform(0.2f, -1.1f, 0.2f, transform));
WorldVertex a3 = new WorldVertex(Vector3D.Transform(-0.2f, -1.1f, 0.2f, transform));
WorldVertex a4 = new WorldVertex(Vector3D.Transform(0.2f, -1.1f, -0.2f, transform));
WorldVertex a5 = new WorldVertex(Vector3D.Transform(-0.2f, -1.1f, -0.2f, transform));
cageverts.AddRange(new[] { a0, a1,
a1, a2,
a1, a3,
a1, a4,
a1, a5 });
}
// Create buffer
WorldVertex[] cv = cageverts.ToArray();
cagelength = cv.Length / 2;
cagebuffer = new VertexBuffer(General.Map.Graphics.Device, WorldVertex.Stride * cv.Length, Usage.WriteOnly | Usage.Dynamic, VertexFormat.None, Pool.Default);
cagebuffer.Lock(0, WorldVertex.Stride * cv.Length, LockFlags.None).WriteRange(cv);
cagebuffer.Unlock();
} }
/// <summary> /// <summary>
@ -387,7 +461,7 @@ namespace CodeImp.DoomBuilder.VisualModes
if(updategeo) if(updategeo)
{ {
// Trash geometry buffer // Trash geometry buffer
if (geobuffer != null) geobuffer.Dispose(); if(geobuffer != null) geobuffer.Dispose();
geobuffer = null; geobuffer = null;
// Any vertics? // Any vertics?
@ -403,80 +477,6 @@ namespace CodeImp.DoomBuilder.VisualModes
geobuffer.Unlock(); geobuffer.Unlock();
bufferstream.Dispose(); bufferstream.Dispose();
} }
// Trash cage buffer
if(cagebuffer != null) cagebuffer.Dispose();
cagebuffer = null;
// Make a new cage
List<WorldVertex> cageverts;
if(sizeless)
{
WorldVertex v0 = new WorldVertex(-info.Radius + position_v3.X, -info.Radius + position_v3.Y, position_v3.Z);
WorldVertex v1 = new WorldVertex( info.Radius + position_v3.X, info.Radius + position_v3.Y, position_v3.Z);
WorldVertex v2 = new WorldVertex( info.Radius + position_v3.X, -info.Radius + position_v3.Y, position_v3.Z);
WorldVertex v3 = new WorldVertex(-info.Radius + position_v3.X, info.Radius + position_v3.Y, position_v3.Z);
WorldVertex v4 = new WorldVertex(position_v3.X, position_v3.Y, info.Radius + position_v3.Z);
WorldVertex v5 = new WorldVertex(position_v3.X, position_v3.Y, -info.Radius + position_v3.Z);
cageverts = new List<WorldVertex>(new[] { v0, v1, v2, v3, v4, v5 });
}
else
{
float top = position_v3.Z + info.Height;
float bottom = position_v3.Z;
WorldVertex v0 = new WorldVertex(-info.Radius + position_v3.X, -info.Radius + position_v3.Y, bottom);
WorldVertex v1 = new WorldVertex(-info.Radius + position_v3.X, info.Radius + position_v3.Y, bottom);
WorldVertex v2 = new WorldVertex( info.Radius + position_v3.X, info.Radius + position_v3.Y, bottom);
WorldVertex v3 = new WorldVertex( info.Radius + position_v3.X, -info.Radius + position_v3.Y, bottom);
WorldVertex v4 = new WorldVertex(-info.Radius + position_v3.X, -info.Radius + position_v3.Y, top);
WorldVertex v5 = new WorldVertex(-info.Radius + position_v3.X, info.Radius + position_v3.Y, top);
WorldVertex v6 = new WorldVertex( info.Radius + position_v3.X, info.Radius + position_v3.Y, top);
WorldVertex v7 = new WorldVertex( info.Radius + position_v3.X, -info.Radius + position_v3.Y, top);
cageverts = new List<WorldVertex>(new[] { v0, v1,
v1, v2,
v2, v3,
v3, v0,
v4, v5,
v5, v6,
v6, v7,
v7, v4,
v0, v4,
v1, v5,
v2, v6,
v3, v7 });
}
// Make new arrow
if(Thing.IsDirectional)
{
Matrix transform = Matrix.Scaling(info.Radius, info.Radius, info.Radius)
* (Matrix.RotationY(-Thing.RollRad) * Matrix.RotationX(-Thing.PitchRad) * Matrix.RotationZ(Thing.Angle))
* (sizeless ? position : position * Matrix.Translation(0.0f, 0.0f, thingheight / 2f));
WorldVertex a0 = new WorldVertex(Vector3D.Transform( 0.0f, 0.0f, 0.0f, transform)); //start
WorldVertex a1 = new WorldVertex(Vector3D.Transform( 0.0f, -1.5f, 0.0f, transform)); //end
WorldVertex a2 = new WorldVertex(Vector3D.Transform( 0.2f, -1.1f, 0.2f, transform));
WorldVertex a3 = new WorldVertex(Vector3D.Transform(-0.2f, -1.1f, 0.2f, transform));
WorldVertex a4 = new WorldVertex(Vector3D.Transform( 0.2f, -1.1f, -0.2f, transform));
WorldVertex a5 = new WorldVertex(Vector3D.Transform(-0.2f, -1.1f, -0.2f, transform));
cageverts.AddRange(new[] {a0, a1,
a1, a2,
a1, a3,
a1, a4,
a1, a5});
}
// Create buffer
WorldVertex[] cv = cageverts.ToArray();
cagelength = cv.Length / 2;
cagebuffer = new VertexBuffer(General.Map.Graphics.Device, WorldVertex.Stride * cv.Length, Usage.WriteOnly | Usage.Dynamic, VertexFormat.None, Pool.Default);
cagebuffer.Lock(0, WorldVertex.Stride * cv.Length, LockFlags.None).WriteRange(cv);
cagebuffer.Unlock();
//mxd. Check if thing is light //mxd. Check if thing is light
CheckLightState(); CheckLightState();

View file

@ -4018,6 +4018,7 @@ namespace CodeImp.DoomBuilder.Windows
#endregion #endregion
#region ================== Dockers #region ================== Dockers
// This adds a docker // This adds a docker
public void AddDocker(Docker d) public void AddDocker(Docker d)
{ {
@ -4033,9 +4034,11 @@ namespace CodeImp.DoomBuilder.Windows
// This removes a docker // This removes a docker
public bool RemoveDocker(Docker d) public bool RemoveDocker(Docker d)
{ {
if(!dockerspanel.Contains(d)) return true; //mxd. Already removed/never added
// Make sure the full name is set with the plugin name as prefix // Make sure the full name is set with the plugin name as prefix
Plugin plugin = General.Plugins.FindPluginByAssembly(Assembly.GetCallingAssembly()); //Plugin plugin = General.Plugins.FindPluginByAssembly(Assembly.GetCallingAssembly());
d.MakeFullName(plugin.Name.ToLowerInvariant()); //d.MakeFullName(plugin.Name.ToLowerInvariant());
// We must release all keys because the focus may be stolen when // We must release all keys because the focus may be stolen when
// this was the selected docker (the previous docker is automatically selected) // this was the selected docker (the previous docker is automatically selected)
@ -4047,6 +4050,8 @@ namespace CodeImp.DoomBuilder.Windows
// This selects a docker // This selects a docker
public bool SelectDocker(Docker d) public bool SelectDocker(Docker d)
{ {
if(!dockerspanel.Contains(d)) return false; //mxd
// Make sure the full name is set with the plugin name as prefix // Make sure the full name is set with the plugin name as prefix
Plugin plugin = General.Plugins.FindPluginByAssembly(Assembly.GetCallingAssembly()); Plugin plugin = General.Plugins.FindPluginByAssembly(Assembly.GetCallingAssembly());
d.MakeFullName(plugin.Name.ToLowerInvariant()); d.MakeFullName(plugin.Name.ToLowerInvariant());

View file

@ -220,12 +220,23 @@ namespace CodeImp.DoomBuilder.BuilderModes
menusform.Unregister(); menusform.Unregister();
menusform.Dispose(); menusform.Dispose();
menusform = null; menusform = null;
curvelinedefsform.Dispose();
curvelinedefsform = null; //mxd. These are created on demand, so they may be nulls.
findreplaceform.Dispose(); if(curvelinedefsform != null)
findreplaceform = null; {
errorcheckform.Dispose(); curvelinedefsform.Dispose();
errorcheckform = null; curvelinedefsform = null;
}
if(findreplaceform != null)
{
findreplaceform.Dispose();
findreplaceform = null;
}
if(errorcheckform != null)
{
errorcheckform.Dispose();
errorcheckform = null;
}
// Done // Done
me = null; me = null;

View file

@ -414,7 +414,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Apply settings // Apply settings
SetPosition(pos); SetPosition(pos);
SetCageColor(Thing.Color); UpdateThingCage(Thing.Color);
// Keep info for object picking // Keep info for object picking
cageradius2 = thingradius * Angle2D.SQRT2; cageradius2 = thingradius * Angle2D.SQRT2;

View file

@ -17,6 +17,7 @@
#region ================== Namespaces #region ================== Namespaces
using System; using System;
using System.Globalization;
using System.IO; using System.IO;
using CodeImp.DoomBuilder.Plugins.VisplaneExplorer.Properties; using CodeImp.DoomBuilder.Plugins.VisplaneExplorer.Properties;
using CodeImp.DoomBuilder.Windows; using CodeImp.DoomBuilder.Windows;
@ -33,6 +34,7 @@ namespace CodeImp.DoomBuilder.Plugins.VisplaneExplorer
private static BuilderPlug me; private static BuilderPlug me;
private VPOManager vpo; private VPOManager vpo;
private InterfaceForm interfaceform; private InterfaceForm interfaceform;
private bool enabled; //mxd
// Palettes // Palettes
private Palette[] palettes; private Palette[] palettes;
@ -42,55 +44,31 @@ namespace CodeImp.DoomBuilder.Plugins.VisplaneExplorer
#region ================== Properties #region ================== Properties
// Properties // Properties
public static BuilderPlug Me { get { return me; } }
public override string Name { get { return "VisplaneExplorer"; } } public override string Name { get { return "VisplaneExplorer"; } }
internal static VPOManager VPO { get { return me.vpo; } } internal static VPOManager VPO { get { return me.vpo; } }
internal static InterfaceForm InterfaceForm { get { return me.interfaceform; } } internal static InterfaceForm InterfaceForm { get { return me.interfaceform; } }
internal static Palette[] Palettes { get { return me.palettes; } } internal static Palette[] Palettes { get { return me.GetPalettes(); } }
public override int MinimumRevision { get { return 1545; } } public override int MinimumRevision { get { return 2411; } }
#endregion #endregion
#region ================== Initialize / Dispose #region ================== Initialize / Dispose
// This event is called when the plugin is initialized //mxd. Initialize when we can check the map format
public override void OnInitialize() public override void OnMapNewEnd() { OnMapOpenEnd(); }
public override void OnMapOpenEnd()
{ {
base.OnInitialize(); enabled = (General.Map.DOOM || General.Map.HEXEN);
if(enabled)
//General.Actions.BindMethods(this); //mxd. But... we have no methods to bind!
// Load interface controls
interfaceform = new InterfaceForm();
// Load VPO manager (manages multithreading and communication with vpo.dll)
vpo = new VPOManager();
// Keep a static reference
me = this;
}
//mxd. This, actually, can also happen
public override void OnMapNewBegin()
{
OnMapOpenBegin();
}
// Some things cannot be initialized at plugin start, so we do them here
public override void OnMapOpenBegin()
{
base.OnMapOpenBegin();
if (palettes == null)
{ {
// Load palettes // Load interface controls
palettes = new Palette[(int)ViewStats.NumStats]; interfaceform = new InterfaceForm();
palettes[(int)ViewStats.Visplanes] = new Palette(Resources.Visplanes_pal);
palettes[(int)ViewStats.Drawsegs] = new Palette(Resources.Drawsegs_pal); // Load VPO manager (manages multithreading and communication with vpo.dll)
palettes[(int)ViewStats.Solidsegs] = new Palette(Resources.Solidsegs_pal); vpo = new VPOManager();
palettes[(int)ViewStats.Openings] = new Palette(Resources.Openings_pal);
palettes[(int)ViewStats.Heatmap] = new Palette(Resources.Heatmap_pal); //mxd // Keep a static reference
ApplyUserColors(); me = this;
} }
} }
@ -104,45 +82,69 @@ namespace CodeImp.DoomBuilder.Plugins.VisplaneExplorer
// This is called when the plugin is terminated // This is called when the plugin is terminated
public override void Dispose() public override void Dispose()
{ {
// Clean up //mxd. Active and not already disposed?
interfaceform.Dispose(); if(!IsDisposed)
interfaceform = null; {
vpo.Dispose(); if(enabled)
vpo = null; {
base.Dispose(); // Clean up
interfaceform.Dispose();
interfaceform = null;
vpo.Dispose();
vpo = null;
// Done
me = null;
}
base.Dispose();
}
} }
#endregion #endregion
#region ================== Methods #region ================== Methods
//mxd
private Palette[] GetPalettes()
{
if(palettes == null)
{
// Load palettes
palettes = new Palette[(int)ViewStats.NumStats];
palettes[(int)ViewStats.Visplanes] = new Palette(Resources.Visplanes_pal);
palettes[(int)ViewStats.Drawsegs] = new Palette(Resources.Drawsegs_pal);
palettes[(int)ViewStats.Solidsegs] = new Palette(Resources.Solidsegs_pal);
palettes[(int)ViewStats.Openings] = new Palette(Resources.Openings_pal);
palettes[(int)ViewStats.Heatmap] = new Palette(Resources.Heatmap_pal); //mxd
ApplyUserColors();
}
return palettes;
}
// This applies user-defined appearance colors to the palettes // This applies user-defined appearance colors to the palettes
private void ApplyUserColors() private void ApplyUserColors()
{ {
if(palettes != null) //mxd
if(palettes == null)
{ {
// Override special palette indices with user-defined colors GetPalettes();
for(int i = 0; i < palettes.Length; i++) return;
{
palettes[i].SetColor(Tile.POINT_VOID_B, General.Colors.Background.WithAlpha(0).ToInt());
}
} }
// Override special palette indices with user-defined colors
foreach(Palette p in palettes) p.SetColor(Tile.POINT_VOID_B, General.Colors.Background.WithAlpha(0).ToInt());
} }
// This returns a unique temp filename // This returns a unique temp filename
public static string MakeTempFilename(string extension) public static string MakeTempFilename(string extension)
{ {
string filename; string filename;
string chars = "abcdefghijklmnopqrstuvwxyz1234567890";
Random rnd = new Random();
int i;
do do
{ {
// Generate a filename //mxd. Generate a filename
filename = ""; filename = Path.Combine(General.TempPath, MurmurHash2.Hash(DateTime.Now.Ticks.ToString(CultureInfo.InvariantCulture)) + extension);
for(i = 0; i < 8; i++) filename += chars[rnd.Next(chars.Length)];
filename = Path.Combine(General.TempPath, filename + extension);
} }
// Continue while file is not unique // Continue while file is not unique
while(File.Exists(filename) || Directory.Exists(filename)); while(File.Exists(filename) || Directory.Exists(filename));