Added, Draw Ellipse mode: angle setting can now be changed using "Rotate Clockwise" and "Rotate Counterclockwise" actions.

Added, Draw Line and Draw Curve modes: added "Auto-finish drawing" setting. When enabled, the modes will automatically finish drawing when currently drawn lines and already existing level geometry form a closed shape.
Changed: sector-wise linedef flipping is now done using the new "Align Linedefs" action. "Flip Linedefs" action works the same as in DB2 again.
Changed: when a map was already loaded, using "Open Map" action will use that map's directory as the starting directory.
Changed: official IWADs can no longer be saved.
Changed: disabled lump ranges/duplicate entries checks for official IWADs.
Changed: wad type is now preserved when saving a map (previously all wads were saved as PWADs).
Changed: moved Updater.exe launch much closer to the editor termination point to avoid any chance of it closing the editor before it properly closes itself.
Updated ZDoom_DECORATE.cfg (A_Blast).
Updated documentation.
This commit is contained in:
MaxED 2016-03-14 10:25:27 +00:00
parent 5fde78a2c9
commit 23d2a27dec
38 changed files with 726 additions and 222 deletions

View file

@ -368,7 +368,7 @@ keywords
A_BarrelDestroy = "A_BarrelDestroy";
//Miscellaneous functions not listed in the "Action functions" wiki article
A_Bang4Cloud = "A_Bang4Cloud";
A_Blast = "A_Blast[(int flags = 0[, int strength = 255[, int radius = 255[, float speed = 20.0[, str blasteffect = \"BlastEffect\"[, str blastsound = \"BlastRadius\"]]]]])]\nA_Blast[(int flags = 0[, int strength = 255[, float radius = 255.0[, float speed = 20.0[, str blasteffect = \"BlastEffect\"[, str blastsound = \"BlastRadius\"]]]]])]";
A_Blast = "A_Blast[(int flags = 0[, float strength = 255.0[, float radius = 255.0[, float speed = 20.0[, str blasteffect = \"BlastEffect\"[, str blastsound = \"BlastRadius\"]]]]])]";
A_BishopMissileWeave = "A_BishopMissileWeave";
A_DropWeaponPieces = "A_DropWeaponPieces(str actorclass1, str actorclass2, str actorclass3)";
A_Feathers = "A_Feathers";

Binary file not shown.

Before

Width:  |  Height:  |  Size: 220 KiB

After

Width:  |  Height:  |  Size: 313 KiB

View file

@ -25,7 +25,9 @@ This mode lets you draw various curve shapes. <br>
<b>Default key:</b> Ctrl-Alt-D.<br>
<b>Additional actions:</b> Increase Subdivision Level, Decrease Subdivision Level.<br><br>
You can activate this mode by pressing <strong>Ctrl-Alt-D</strong> (default key).<br>
You can use the side panel or &quot;<strong>Increase Subdivision Level</strong>&quot; and &quot;<strong>Decrease Subdivision Level</strong>&quot; actions to control how detailed the curve is:
Press "<strong>Continuous drawing</strong>" button on the mode panel to disable automatic switching to previous editing mode after finishing drawing.<br>
Press "<strong>Auto-finish drawing</strong>" button on the mode panel to automatically finish drawing when currently drawn lines and already existing level geometry form a closed shape.<br>
You can use the mode panel or &quot;<strong>Increase Subdivision Level</strong>&quot; and &quot;<strong>Decrease Subdivision Level</strong>&quot; actions to control how detailed the curve is:
<br>
<img src="draw_curve.jpg" /></div>
</body>

View file

@ -21,14 +21,15 @@ This mode lets you draw various ellipsoid shapes.<br>
<b>Menu path:</b> Mode -&gt; Draw Ellipse.<br>
<b>Action category:</b> Drawing.<br>
<b>Default key:</b> Ctrl-Alt-D.<br>
<b>Additional actions:</b> Increase Subdivision Level, Decrease Subdivision Level, Increase Corners Bevel, Decrease Corners Bevel.<br>
<b>Additional actions:</b> Increase Subdivision Level, Decrease Subdivision Level, Increase Corners Bevel, Decrease Corners Bevel, Rotate Clockwise, Rotate Counterclockwise.<br>
<br>
You can activate this mode by pressing <strong>Alt-Shift-D</strong> (default key).<br>
You can use the side panel or &quot;<strong>Increase Subdivision Level</strong>&quot; and &quot;<strong>Decrease Subdivision Level</strong>&quot; actions to control the number of sides ellipse has:
<br>
Press "<strong>Continuous drawing</strong>" button on the mode panel to disable automatic switching to previous editing mode after finishing drawing.<br>
You can use the mode panel or &quot;<strong>Rotate Clockwise</strong>&quot; and &quot;<strong>Rotate Counterclockwise</strong>&quot; actions to rotate the shape.<br>
You can use the mode panel or &quot;<strong>Increase Subdivision Level</strong>&quot; and &quot;<strong>Decrease Subdivision Level</strong>&quot; actions to control the number of sides ellipse has.<br>
<img src="draw_ellipse1.jpg" />
<br>
You can use side panel or &quot;<strong>Increase Corners Bevel</strong>&quot; and &quot;<strong>Decrease Corners Bevel</strong>&quot; actions to bevel the ellipse: <br>
You can use mode panel or &quot;<strong>Increase Corners Bevel</strong>&quot; and &quot;<strong>Decrease Corners Bevel</strong>&quot; actions to bevel the ellipse: <br>
<img src="draw_ellipse2.jpg" />
<br>
When using &quot;<strong>Increase/Decrease Corners Bevel</strong>&quot; actions, the bevel increment is based on the current grid size.</p>

View file

@ -24,8 +24,9 @@
<b>Default key:</b> none.<br />
<b>Additional actions:</b> Increase Subdivision Level, Decrease Subdivision Level, Increase Corners Bevel, Decrease Corners Bevel.</p>
<p>You can use the side panel or &quot;<strong>Increase/Decrease Subdivision Level</strong>&quot; and &quot;<strong>Increase/Decrease Corners Bevel</strong>&quot; actions to change the number of horizontal and vertical slices.<br />
Check "<strong>Lock slices to grid</strong>" to match slices number to current grid size.<br />
Check &quot;<strong>Triangulate</strong>&quot; if you want to create triangles instead of quads:</p>
Change "<strong>Lock slices to grid</strong>" setting to match slices number to current grid size horizontally, vertically or in both directions.<br />
Check &quot;<strong>Triangulate</strong>&quot; if you want to create triangles instead of quads.<br />
Check "<strong>Continuous drawing</strong>" to disable automatic switching to previous editing mode after finishing drawing.</p>
<p><img src="draw_grid_tri.jpg" alt="" /></p>
</div>
</body>

View file

@ -21,9 +21,11 @@ This mode lets you draw various rectangle shapes.<br>
<b>Menu path:</b> Mode -&gt; Draw Rectangle.<br />
<b>Action category:</b> Drawing.<br>
<b>Default key:</b> Ctrl-Shift-D.<br>
<b>Additional actions:</b> Increase Subdivision Level, Decrease Subdivision Level, Increase Corners Bevel, Decrease Corners Bevel.<br><br>
<b>Additional actions:</b> Increase Subdivision Level, Decrease Subdivision Level, Increase Corners Bevel, Decrease Corners Bevel.<br>
<br>
You can activate this mode by pressing <strong>Ctrl-Shift-D</strong> (default key).<br>
You can use the side panel or &quot;<strong>Increase/Decrease Subdivision Level</strong>&quot; and &quot;<strong>Increase/Decrease Corners Bevel</strong>&quot; actions to change corner bevel amount and detail level:
Press "<strong>Continuous drawing</strong>" button on the mode panel to disable automatic switching to previous editing mode after finishing drawing.<br>
You can use the mode panel or &quot;<strong>Increase/Decrease Subdivision Level</strong>&quot; and &quot;<strong>Increase/Decrease Corners Bevel</strong>&quot; actions to change corner bevel amount and detail level:
<br>
<img src="draw_rectangle1.jpg" />
<br>

View file

@ -83,7 +83,7 @@ namespace CodeImp.DoomBuilder.Data
// Initialize
file = new WAD(location.location, true);
is_iwad = (file.Type == WAD.TYPE_IWAD);
is_iwad = file.IsIWAD;
strictpatches = dl.option1;
patchranges = new List<LumpRange>();
spriteranges = new List<LumpRange>();
@ -175,7 +175,7 @@ namespace CodeImp.DoomBuilder.Data
public override void Resume()
{
file = new WAD(location.location, true);
is_iwad = (file.Type == WAD.TYPE_IWAD);
is_iwad = file.IsIWAD;
base.Resume();
}
@ -219,23 +219,27 @@ namespace CodeImp.DoomBuilder.Data
}
}
//mxd. Display warnings for unclosed ranges
foreach(KeyValuePair<LumpRange, KeyValuePair<string, string>> group in failedranges)
// Don't check official IWADs
if(!file.IsOfficialIWAD)
{
if(successfulrangestarts.ContainsKey(group.Key.start)) continue;
General.ErrorLogger.Add(ErrorType.Warning, "\"" + group.Value.Key + "\" range at index " + group.Key.start + " is not closed in resource \"" + location.location + "\" (\"" + group.Value.Value + "\" marker is missing).");
}
//mxd. Check duplicates
foreach(LumpRange range in ranges)
{
HashSet<string> names = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
for(int i = range.start + 1; i < range.end; i++)
//mxd. Display warnings for unclosed ranges
foreach(KeyValuePair<LumpRange, KeyValuePair<string, string>> group in failedranges)
{
if(names.Contains(file.Lumps[i].Name))
General.ErrorLogger.Add(ErrorType.Warning, elementname + " \"" + file.Lumps[i].Name + "\", index " + i + " is double defined in resource \"" + location.location + "\".");
else
names.Add(file.Lumps[i].Name);
if(successfulrangestarts.ContainsKey(group.Key.start)) continue;
General.ErrorLogger.Add(ErrorType.Warning, "\"" + group.Value.Key + "\" range at index " + group.Key.start + " is not closed in resource \"" + location.location + "\" (\"" + group.Value.Value + "\" marker is missing).");
}
//mxd. Check duplicates
foreach(LumpRange range in ranges)
{
HashSet<string> names = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
for(int i = range.start + 1; i < range.end; i++)
{
if(names.Contains(file.Lumps[i].Name))
General.ErrorLogger.Add(ErrorType.Warning, elementname + " \"" + file.Lumps[i].Name + "\", index " + i + " is double defined in resource \"" + location.location + "\".");
else
names.Add(file.Lumps[i].Name);
}
}
}
}

View file

@ -461,7 +461,6 @@ namespace CodeImp.DoomBuilder.Editing
#region ================== Processing
// Processing
public override void OnProcess(float deltatime) { OnProcess((long)deltatime); } //mxd. DB2 compatibility
public override void OnProcess(long deltatime)
{
base.OnProcess(deltatime);

View file

@ -246,7 +246,6 @@ namespace CodeImp.DoomBuilder.Editing
// Processing events
public virtual void OnProcess(long deltatime) { }
public virtual void OnProcess(float deltatime) { OnProcess((long)deltatime); } //mxd. DB2 compatibility
// Generic events
public virtual void OnReloadResources() { }

View file

@ -231,6 +231,7 @@ namespace CodeImp.DoomBuilder
public static bool NoSettings { get { return nosettings; } }
public static EditingManager Editing { get { return editing; } }
public static ErrorLogger ErrorLogger { get { return errorlogger; } }
internal static int PendingUpdateRev; //mxd
#endregion
@ -993,7 +994,7 @@ namespace CodeImp.DoomBuilder
// Terminate properly?
if(properexit)
{
General.WriteLogLine("Termination requested");
General.WriteLogLine(PendingUpdateRev != 0 ? "Program update requested" : "Termination requested");
// Unbind static methods from actions
General.Actions.UnbindMethods(typeof(General));
@ -1018,7 +1019,14 @@ namespace CodeImp.DoomBuilder
if(mainwindow != null) { mainwindow.Dispose(); mainwindow = null; }
if(actions != null) { actions.Dispose(); actions = null; }
if(types != null) { types.Dispose(); types = null; }
try { D3DDevice.Terminate(); } catch(Exception) { }
try { D3DDevice.Terminate(); } catch { }
//mxd. Launch the updater?
if(PendingUpdateRev != 0)
{
General.WriteLogLine("Initiating update to R" + PendingUpdateRev + "...");
Process.Start(Path.Combine(apppath, "Updater.exe"), "-rev " + PendingUpdateRev);
}
// Application ends here and now
General.WriteLogLine("Termination done");
@ -1181,7 +1189,10 @@ namespace CodeImp.DoomBuilder
openfile.Filter = "Doom WAD Files (*.wad)|*.wad";
openfile.Title = "Open Map";
if(!string.IsNullOrEmpty(settings.LastUsedMapFolder) && Directory.Exists(settings.LastUsedMapFolder)) //mxd
openfile.InitialDirectory = settings.LastUsedMapFolder; //mxd
{
openfile.RestoreDirectory = true;
openfile.InitialDirectory = settings.LastUsedMapFolder;
}
openfile.AddExtension = false;
openfile.CheckFileExists = true;
openfile.Multiselect = false;
@ -1468,6 +1479,12 @@ namespace CodeImp.DoomBuilder
savefile.OverwritePrompt = true;
savefile.ValidateNames = true;
savefile.FileName = map.FileTitle; //mxd
if(map.FilePathName.Length > 0) //mxd
{
savefile.RestoreDirectory = true;
savefile.InitialDirectory = Path.GetDirectoryName(map.FilePathName);
}
if(savefile.ShowDialog(mainwindow) == DialogResult.OK)
{
// Check if we're saving to the same file as the original.

View file

@ -664,7 +664,7 @@ namespace CodeImp.DoomBuilder
General.MainWindow.DisplayStatus(StatusType.Busy, "Compressing sidedefs...");
outputset.CompressSidedefs();
// Check if it still doesnt fit
// Check if it still doesnt
if(outputset.Sidedefs.Count > io.MaxSidedefs)
{
// Problem! Can't save the map like this!
@ -727,6 +727,20 @@ namespace CodeImp.DoomBuilder
General.WriteLogLine("Saving map to file: " + newfilepathname);
//mxd. Official IWAD check...
WAD hashtest = new WAD(newfilepathname, true);
if(hashtest.IsOfficialIWAD)
{
General.WriteLogLine("Map saving aborted: attempt to modify official IWAD");
General.ShowErrorMessage("Official IWADs should not be modified.\nConsider making a PWAD instead", MessageBoxButtons.OK);
return false;
}
else
{
hashtest.Dispose();
hashtest = null;
}
// Scripts changed?
bool localscriptschanged = CheckScriptChanged();
@ -907,7 +921,7 @@ namespace CodeImp.DoomBuilder
WAD origwad = new WAD(origwadfile, true);
// Create new target file
targetwad = new WAD(newfilepathname);
targetwad = new WAD(newfilepathname) { IsIWAD = origwad.IsIWAD }; //mxd. Let's preserve wad type
// Copy all lumps, except the original map
GameConfiguration origcfg; //mxd

View file

@ -359,7 +359,6 @@ namespace CodeImp.DoomBuilder.Geometry
{
// Add line to path
path.Add(new LinedefSide(nextline, nextfront));
if(!tracecount.ContainsKey(nextline)) tracecount.Add(nextline, 1); else tracecount[nextline]++;
// Determine next vertex to use
Vertex v = nextfront ? nextline.End : nextline.Start;
@ -390,6 +389,21 @@ namespace CodeImp.DoomBuilder.Geometry
Linedef prevline = nextline;
nextline = (lines[0] == nextline ? lines[1] : lines[0]);
//mxd. Try to pick a line with lower tracecount...
// Otherwise we will just walk the same path trise
int curcount = (!tracecount.ContainsKey(nextline) ? 0 : tracecount[nextline]);
if(curcount > 0)
{
foreach(Linedef l in lines)
{
if(l != nextline && l != prevline && (!tracecount.ContainsKey(l) || tracecount[l] < curcount))
{
nextline = l;
break;
}
}
}
// Are we allowed to trace this line again?
if(!tracecount.ContainsKey(nextline) || (tracecount[nextline] < 3))
{
@ -403,6 +417,9 @@ namespace CodeImp.DoomBuilder.Geometry
path = null;
}
}
//mxd. Increase trace count
if(!tracecount.ContainsKey(nextline)) tracecount.Add(nextline, 1); else tracecount[nextline]++;
}
// Continue as long as we have not reached the start yet
// or we have no next line to trace

View file

@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
using System.IO;
@ -30,11 +31,58 @@ namespace CodeImp.DoomBuilder.IO
#region ================== Constants
// WAD types
public const string TYPE_IWAD = "IWAD";
public const string TYPE_PWAD = "PWAD";
private const string TYPE_IWAD = "IWAD";
private const string TYPE_PWAD = "PWAD";
// Encoder
public static readonly Encoding ENCODING = Encoding.ASCII;
//mxd. Official IWAD MD5 hashes
private static readonly HashSet<string> IWAD_HASHES = new HashSet<string>
{
////// DOOM IWADS //////
"d9153ced9fd5b898b36cc5844e35b520", // DOOM2 1.666g MD5
"30e3c2d0350b67bfbf47271970b74b2f", // DOOM2 1.666 MD5
"ea74a47a791fdef2e9f2ea8b8a9da13b", // DOOM2 1.7 MD5
"d7a07e5d3f4625074312bc299d7ed33f", // DOOM2 1.7a MD5
"c236745bb01d89bbb866c8fed81b6f8c", // DOOM2 1.8 MD5
"25e1459ca71d321525f84628f45ca8cd", // DOOM2 1.9 MD5
"3cb02349b3df649c86290907eed64e7b", // DOOM2 French MD5
"c3bea40570c23e511a7ed3ebcd9865f7", // BFG DOOM2 MD5
"981b03e6d1dc033301aa3095acc437ce", // DOOM 1.1 MD5
"792fd1fea023d61210857089a7c1e351", // DOOM 1.2 MD5
"464e3723a7e7f97039ac9fd057096adb", // DOOM 1.6b MD5
"54978d12de87f162b9bcc011676cb3c0", // DOOM 1.666 MD5
"11e1cd216801ea2657723abc86ecb01f", // DOOM 1.8 MD5
"1cd63c5ddff1bf8ce844237f580e9cf3", // DOOM 1.9 MD5
"fb35c4a5a9fd49ec29ab6e900572c524", // BFG DOOM MD5
"c4fe9fd920207691a9f493668e0a2083", // ULTIMATE DOOM MD5
"75c8cf89566741fa9d22447604053bd7", // PLUTONIA MD5
"3493be7e1e2588bc9c8b31eab2587a04", // PLUTONIA RARE MD5
"4e158d9953c79ccf97bd0663244cc6b6", // TNT MD5
"1d39e405bf6ee3df69a8d2646c8d5c49", // TNT Fixed MD5
"be626c12b7c9d94b1dfb9c327566b4ff", // PSN TNT MD5
////// HERETIC IWADS //////
"3117e399cdb4298eaa3941625f4b2923", // HERETIC 1.0 MD5
"1e4cb4ef075ad344dd63971637307e04", // HERETIC 1.2 MD5
"66d686b1ed6d35ff103f15dbd30e0341", // HERETIC 1.3 MD5
////// HEXEN IWADS //////
"c88a2bb3d783e2ad7b599a8e301e099e", // HEXEN Beta MD5
"b2543a03521365261d0a0f74d5dd90f0", // HEXEN 1.0 MD5
"abb033caf81e26f12a2103e1fa25453f", // HEXEN 1.1 MD5
"1077432e2690d390c256ac908b5f4efa", // HEXEN DK 1.0 MD5
"78d5898e99e220e4de64edaa0e479593", // HEXEN DK 1.1 MD5
////// STRIFE IWADS //////
"8f2d3a6a289f5d2f2f9c1eec02b47299", // STRIFE 1.0 MD5
"2fed2031a5b03892106e0f117f17901f", // STRIFE 1.2 MD5
};
#endregion
@ -47,15 +95,16 @@ namespace CodeImp.DoomBuilder.IO
private BinaryWriter writer;
// Header
private string type;
private int numlumps;
private int lumpsoffset;
private bool isiwad; //mxd
private bool isofficialiwad; //mxd
// Lumps
private List<Lump> lumps;
// Status
private readonly bool isreadonly;
private bool isreadonly;
private bool isdisposed;
#endregion
@ -63,10 +112,11 @@ namespace CodeImp.DoomBuilder.IO
#region ================== Properties
public string Filename { get { return filename; } }
public string Type { get { return type; } }
public Encoding Encoding { get { return ENCODING; } }
public bool IsReadOnly { get { return isreadonly; } }
public bool IsDisposed { get { return isdisposed; } }
public bool IsIWAD { get { return isiwad; } set { isiwad = value; } } //mxd
public bool IsOfficialIWAD { get { return isofficialiwad; } } //mxd
public List<Lump> Lumps { get { return lumps; } }
#endregion
@ -131,6 +181,12 @@ namespace CodeImp.DoomBuilder.IO
{
FileAccess access;
FileShare share;
// Keep filename
filename = pathfilename;
//mxd
CheckHash();
// Determine if opening for read only
if(isreadonly)
@ -146,9 +202,6 @@ namespace CodeImp.DoomBuilder.IO
share = FileShare.Read;
}
// Keep filename
filename = pathfilename;
// Open the file stream
file = File.Open(pathfilename, FileMode.OpenOrCreate, access, share);
@ -157,7 +210,7 @@ namespace CodeImp.DoomBuilder.IO
if(!isreadonly) writer = new BinaryWriter(file, ENCODING);
// Is the WAD file zero length?
if(file.Length == 0)
if(file.Length < 4)
{
// Create the headers in file
CreateHeaders();
@ -173,14 +226,15 @@ namespace CodeImp.DoomBuilder.IO
private void CreateHeaders()
{
// Default settings
type = TYPE_PWAD;
isiwad = false; //mxd
isofficialiwad = false; //mxd
lumpsoffset = 12;
// New lumps array
lumps = new List<Lump>(numlumps);
// Write the headers
WriteHeaders();
if(!isreadonly) WriteHeaders();
}
// This reads the WAD header and lumps table
@ -193,7 +247,7 @@ namespace CodeImp.DoomBuilder.IO
file.Seek(0, SeekOrigin.Begin);
// Read WAD type
type = ENCODING.GetString(reader.ReadBytes(4));
isiwad = (ENCODING.GetString(reader.ReadBytes(4)) == TYPE_IWAD); //mxd
// Number of lumps
numlumps = reader.ReadInt32();
@ -223,14 +277,14 @@ namespace CodeImp.DoomBuilder.IO
}
}
// This reads the WAD header and lumps table
// This writes the WAD header and lumps table
public void WriteHeaders()
{
// Seek to beginning
file.Seek(0, SeekOrigin.Begin);
// Write WAD type
writer.Write(ENCODING.GetBytes(type));
writer.Write(ENCODING.GetBytes(isiwad ? TYPE_IWAD : TYPE_PWAD));
// Number of lumps
writer.Write(numlumps);
@ -250,6 +304,48 @@ namespace CodeImp.DoomBuilder.IO
writer.Write(lumps[i].FixedName);
}
}
//mxd
private void CheckHash()
{
// Open the file stream
FileStream fs = File.Open(filename, FileMode.OpenOrCreate, FileAccess.Read, FileShare.ReadWrite);
// Empty file can't be official iwad
if(fs.Length > 4)
{
BinaryReader r = new BinaryReader(fs, ENCODING);
// Read WAD type
if(ENCODING.GetString(r.ReadBytes(4)) == TYPE_IWAD)
{
// Rewind
r.BaseStream.Position = 0;
// Check hash
MD5 hasher = MD5.Create();
byte[] data = hasher.ComputeHash(r.BaseStream);
// Create a new Stringbuilder to collect the bytes and create a string.
StringBuilder hash = new StringBuilder();
// Loop through each byte of the hashed data and format each one as a hexadecimal string.
for(int i = 0; i < data.Length; i++)
{
hash.Append(data[i].ToString("x2"));
}
isofficialiwad = IWAD_HASHES.Contains(hash.ToString());
if(!isreadonly && isofficialiwad) isreadonly = true;
}
// Close the reader
r.Close();
}
// Close the file
fs.Dispose();
}
// This flushes writing changes
/*public void Flush()

View file

@ -1099,7 +1099,6 @@ namespace CodeImp.DoomBuilder.VisualModes
/// <summary>
/// While this mode is active, this is called continuously to process whatever needs processing.
/// </summary>
public override void OnProcess(float deltatime) { OnProcess((long)deltatime); } //mxd. DB2 compatibility
public override void OnProcess(long deltatime)
{
base.OnProcess(deltatime);

View file

@ -4182,12 +4182,13 @@ namespace CodeImp.DoomBuilder.Windows
// Update ignored revision number
General.Settings.IgnoredRemoteRevision = (form.IgnoreThisUpdate ? remoterev : 0);
if(result == DialogResult.OK && General.AskSaveMap())
if(result == DialogResult.OK)
{
// Launch the updater
Process.Start(Path.Combine(General.AppPath, "Updater.exe"), "-rev " + remoterev);
// Updater will be launched from General.Terminate
General.PendingUpdateRev = remoterev;
// Close
General.WriteLogLine("Initiating shutdown due to update request...");
General.Exit(true);
}
}

View file

@ -446,7 +446,7 @@ namespace CodeImp.DoomBuilder.Windows
}
// Check if we should warn the user for missing resources
if((wadfile.Type != WAD.TYPE_IWAD) && (locations.Count == 0) && (configinfo.Resources.Count == 0))
if((!wadfile.IsIWAD) && (locations.Count == 0) && (configinfo.Resources.Count == 0))
{
if(MessageBox.Show(this, "You are about to load a map without selecting any resources. Textures, flats and " +
"sprites may not be shown correctly or may not show up at all. Do you want to continue?", Application.ProductName,

View file

@ -183,7 +183,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
General.Map.UndoRedo.CreateUndo("Curve draw");
// Make an analysis and show info
string[] adjectives = new[]
string[] adjectives =
{
"beautiful", "lovely", "romantic", "stylish", "cheerful", "comical",
"awesome", "accurate", "adorable", "adventurous", "attractive", "cute",
@ -197,27 +197,23 @@ namespace CodeImp.DoomBuilder.BuilderModes
List<DrawnVertex> verts = new List<DrawnVertex>();
//if we have a curve...
// If we have a curve...
if(points.Count > 2)
{
//is it a closed curve?
int lastPoint;
if(points[0].pos == points[points.Count - 1].pos)
{
lastPoint = curve.Segments.Count;
}
// Is it an (auto)closed curve?
int lastpoint;
if(drawingautoclosed || points[0].pos == points[points.Count - 1].pos)
lastpoint = curve.Segments.Count;
else
{
lastPoint = curve.Segments.Count - 1;
}
lastpoint = curve.Segments.Count - 1;
for(int i = 0; i < lastPoint; i++)
for(int i = 0; i < lastpoint; i++)
{
int next = (i == curve.Segments.Count - 1 ? 0 : i + 1);
bool stitch = points[i].stitch && points[next].stitch;
bool stitchline = points[i].stitchline && points[next].stitchline;
//add segment points except the last one
// Add segment points except the last one
for(int c = 0; c < curve.Segments[i].Points.Length - 1; c++)
{
DrawnVertex dv = new DrawnVertex();
@ -228,9 +224,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
}
}
//add last point
// Add the last point
DrawnVertex end = new DrawnVertex();
end.pos = curve.Segments[lastPoint - 1].End;
end.pos = curve.Segments[lastpoint - 1].End;
end.stitch = verts[verts.Count - 1].stitch;
end.stitchline = verts[verts.Count - 1].stitchline;
verts.Add(end);
@ -283,6 +279,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Reset settings
points.Clear();
labels.Clear();
drawingautoclosed = false;
// Redraw display
General.Interface.RedrawDisplay();
@ -319,9 +316,11 @@ namespace CodeImp.DoomBuilder.BuilderModes
panel.SegmentLength = segmentlength;
panel.OnValueChanged += OptionsPanelOnValueChanged;
panel.OnContinuousDrawingChanged += OnContinuousDrawingChanged;
panel.OnAutoCloseDrawingChanged += OnAutoCloseDrawingChanged;
// Needs to be set after adding the OnContinuousDrawingChanged event...
// Needs to be set after adding the events...
panel.ContinuousDrawing = General.Settings.ReadPluginSetting("drawcurvemode.continuousdrawing", false);
panel.AutoCloseDrawing = General.Settings.ReadPluginSetting("drawlinesmode.autoclosedrawing", false);
}
protected override void AddInterface()
@ -334,6 +333,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Store settings
General.Settings.WritePluginSetting("drawcurvemode.segmentlength", segmentlength);
General.Settings.WritePluginSetting("drawcurvemode.continuousdrawing", panel.ContinuousDrawing);
General.Settings.WritePluginSetting("drawlinesmode.autoclosedrawing", panel.AutoCloseDrawing);
// Remove the buttons
panel.Unregister();

View file

@ -1,6 +1,8 @@
#region ================== Namespaces
using System;
using System.Collections.Generic;
using CodeImp.DoomBuilder.Actions;
using CodeImp.DoomBuilder.Editing;
using CodeImp.DoomBuilder.Geometry;
@ -20,17 +22,22 @@ namespace CodeImp.DoomBuilder.BuilderModes
public class DrawEllipseMode : DrawRectangleMode
{
#region ================== Variables
// Drawing
private float angle; // in radians
// Interface
private DrawEllipseOptionsPanel panel;
// Drawing
private float angle; // in radians
#endregion
#region ================== Constructor
public DrawEllipseMode()
{
autoclosedrawing = false;
}
#endregion
#region ================== Settings panel
@ -135,9 +142,14 @@ namespace CodeImp.DoomBuilder.BuilderModes
return shape;
}
protected override string GetHintText()
protected override string GetHintText()
{
return "BVL: " + bevelwidth + "; VERTS: " + subdivisions;
List<string> result = new List<string>();
if(bevelwidth != 0) result.Add("BVL: " + bevelwidth);
if(subdivisions != 0) result.Add("VERTS: " + subdivisions);
if(panel.Angle != 0) result.Add("ANGLE: " + panel.Angle);
return string.Join("; ", result.ToArray());
}
#endregion
@ -229,6 +241,22 @@ namespace CodeImp.DoomBuilder.BuilderModes
}
}
[BeginAction("rotateclockwise")]
private void IncreaseAngle()
{
panel.Angle = General.ClampAngle(panel.Angle + 5);
angle = Angle2D.DegToRad(panel.Angle);
Update();
}
[BeginAction("rotatecounterclockwise")]
private void DecreaseAngle()
{
panel.Angle = General.ClampAngle(panel.Angle - 5);
angle = Angle2D.DegToRad(panel.Angle);
Update();
}
#endregion
}
}

View file

@ -66,6 +66,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
protected bool snaptocardinaldirection; //mxd. ALT-SHIFT to enable
protected static bool usefourcardinaldirections;
protected bool continuousdrawing; //mxd. Restart after finishing drawing?
protected bool autoclosedrawing; //mxd. Finish drawing when new points and existing geometry form a closed shape
protected bool drawingautoclosed; //mxd
//mxd. Labels display style
protected bool labelshowangle = true;
@ -428,28 +430,125 @@ namespace CodeImp.DoomBuilder.BuilderModes
labels.Add(new LineLengthLabel(labelshowangle, labeluseoffset));
Update();
// Check if point stitches with the first
if((points.Count > 1) && points[points.Count - 1].stitch)
if(points.Count > 1)
{
Vector2D p1 = points[0].pos;
Vector2D p2 = points[points.Count - 1].pos;
Vector2D delta = p1 - p2;
if((Math.Abs(delta.x) <= 0.001f) && (Math.Abs(delta.y) <= 0.001f))
// Check if point stitches with the first
if(points[points.Count - 1].stitch)
{
//mxd. Seems... logical?
if(points.Count == 2)
Vector2D p1 = points[0].pos;
Vector2D p2 = points[points.Count - 1].pos;
Vector2D delta = p1 - p2;
if((Math.Abs(delta.x) <= 0.001f) && (Math.Abs(delta.y) <= 0.001f))
{
OnCancel();
//mxd. Seems... logical?
if(points.Count == 2)
{
OnCancel();
return true;
}
// Finish drawing
FinishDraw();
return true;
}
}
//mxd. Points and existing geometry form a closed shape?
if(continuousdrawing && autoclosedrawing)
{
// Determive center point
float minx = float.MaxValue;
float maxx = float.MinValue;
float miny = float.MaxValue;
float maxy = float.MinValue;
foreach(DrawnVertex v in points)
{
if(v.pos.x < minx) minx = v.pos.x;
if(v.pos.x > maxx) maxx = v.pos.x;
if(v.pos.y < miny) miny = v.pos.y;
if(v.pos.y > maxy) maxy = v.pos.y;
}
Vector2D shapecenter = new Vector2D(minx + (maxx - minx) / 2, miny + (maxy - miny) / 2);
// Finish drawing
FinishDraw();
// Determine center point between start and end points
minx = Math.Min(points[0].pos.x, points[points.Count - 1].pos.x);
maxx = Math.Max(points[0].pos.x, points[points.Count - 1].pos.x);
miny = Math.Min(points[0].pos.y, points[points.Count - 1].pos.y);
maxy = Math.Max(points[0].pos.y, points[points.Count - 1].pos.y);
Vector2D startendcenter = new Vector2D(minx + (maxx - minx) / 2, miny + (maxy - miny) / 2);
// Offset the center perpendicular to the start -> end line direction...
if(shapecenter == startendcenter)
{
shapecenter -= new Line2D(points[0].pos, points[points.Count - 1].pos).GetPerpendicular().GetNormal();
}
// Do the check
if(CanFinishDrawing(points[0].pos, points[points.Count - 1].pos, shapecenter))
{
drawingautoclosed = true;
FinishDraw();
}
}
}
return true;
}
//mxd
private static bool CanFinishDrawing(Vector2D start, Vector2D end, Vector2D center)
{
Linedef startline = FindPotentialLine(start, center);
if(startline == null) return false;
Linedef endline = FindPotentialLine(end, center);
if(endline == null) return false;
// Can finish drawing if a path between startline and endline exists
return Tools.FindClosestPath(startline, startline.SideOfLine(center) < 0.0f, endline, endline.SideOfLine(center) < 0.0f, true) != null;
}
//mxd
private static Linedef FindPotentialLine(Vector2D target, Vector2D center)
{
// Target position on top of existing vertex?
Vertex v = General.Map.Map.NearestVertex(target);
if(v == null) return null;
Linedef result = null;
if(v.Position == target)
{
float mindistance = float.MaxValue;
foreach(Linedef l in v.Linedefs)
{
if(result == null)
{
result = l;
mindistance = Vector2D.DistanceSq(l.GetCenterPoint(), center);
}
else
{
float curdistance = Vector2D.DistanceSq(l.GetCenterPoint(), center);
if(curdistance < mindistance)
{
mindistance = curdistance;
result = l;
}
}
}
}
else
{
// Result position will split a line?
result = General.Map.Map.NearestLinedef(target);
if(result.DistanceTo(target, true) > BuilderPlug.Me.StitchRange) return null;
}
return result;
}
#endregion
@ -460,9 +559,11 @@ namespace CodeImp.DoomBuilder.BuilderModes
//Add options docker
panel = new DrawLineOptionsPanel();
panel.OnContinuousDrawingChanged += OnContinuousDrawingChanged;
panel.OnAutoCloseDrawingChanged += OnAutoCloseDrawingChanged;
// Needs to be set after adding the OnContinuousDrawingChanged event...
// Needs to be set after adding the events...
panel.ContinuousDrawing = General.Settings.ReadPluginSetting("drawlinesmode.continuousdrawing", false);
panel.AutoCloseDrawing = General.Settings.ReadPluginSetting("drawlinesmode.autoclosedrawing", false);
}
protected virtual void AddInterface()
@ -473,6 +574,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
protected virtual void RemoveInterface()
{
General.Settings.WritePluginSetting("drawlinesmode.continuousdrawing", panel.ContinuousDrawing);
General.Settings.WritePluginSetting("drawlinesmode.autoclosedrawing", panel.AutoCloseDrawing);
panel.Unregister();
}
@ -509,7 +611,11 @@ namespace CodeImp.DoomBuilder.BuilderModes
public override void OnCancel()
{
//mxd. Cannot leave this way when continuous drawing is enabled
if(continuousdrawing) return;
if(continuousdrawing)
{
drawingautoclosed = false;
return;
}
// Cancel base class
base.OnCancel();
@ -584,6 +690,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
//mxd. Reset settings
points.Clear();
labels.Clear();
drawingautoclosed = false;
//mxd. Redraw display
General.Interface.RedrawDisplay();
@ -650,6 +757,12 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
continuousdrawing = (bool)value;
}
//mxd
protected void OnAutoCloseDrawingChanged(object value, EventArgs e)
{
autoclosedrawing = (bool)value;
}
#endregion

View file

@ -72,6 +72,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
snaptogrid = true;
usefourcardinaldirections = true;
autoclosedrawing = false;
gridpoints = new List<DrawnVertex[]>();
}
@ -144,6 +145,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Reset settings
points.Clear();
labels.Clear();
drawingautoclosed = false;
// Redraw display
General.Interface.RedrawDisplay();

View file

@ -58,6 +58,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
snaptogrid = true;
usefourcardinaldirections = true;
autoclosedrawing = false;
}
public override void Dispose()
@ -263,9 +264,13 @@ namespace CodeImp.DoomBuilder.BuilderModes
return points;
}
protected virtual string GetHintText()
protected virtual string GetHintText()
{
return "BVL: " + bevelwidth + "; SUB: " + subdivisions;
List<string> result = new List<string>();
if(bevelwidth != 0) result.Add("BVL: " + bevelwidth);
if(subdivisions != 0) result.Add("SUB: " + subdivisions);
return string.Join("; ", result.ToArray());
}
// Update top-left and bottom-right points, which define drawing shape
@ -362,7 +367,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
General.Map.UndoRedo.CreateUndo(undoname);
// Make an analysis and show info
string[] adjectives = new[] { "gloomy", "sad", "unhappy", "lonely", "troubled", "depressed", "heartsick", "glum", "pessimistic", "bitter", "downcast" }; // aaand my english vocabulary ends here :)
string[] adjectives = { "gloomy", "sad", "unhappy", "lonely", "troubled", "depressed", "heartsick", "glum", "pessimistic", "bitter", "downcast" }; // aaand my english vocabulary ends here :)
string word = adjectives[new Random().Next(adjectives.Length - 1)];
string a = (word[0] == 'u' ? "an " : "a ");
@ -411,6 +416,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Reset settings
points.Clear();
labels.Clear();
drawingautoclosed = false;
// Redraw display
General.Interface.RedrawDisplay();

View file

@ -1290,63 +1290,122 @@ namespace CodeImp.DoomBuilder.BuilderModes
}
// Any selected lines?
if(selected.Count > 0)
if(selected.Count == 0)
{
// Make undo
if(selected.Count > 1)
{
General.Map.UndoRedo.CreateUndo("Flip " + selected.Count + " linedefs");
General.Interface.DisplayStatus(StatusType.Action, "Flipped " + selected.Count + " linedefs.");
}
else
{
General.Map.UndoRedo.CreateUndo("Flip linedef");
General.Interface.DisplayStatus(StatusType.Action, "Flipped a linedef.");
}
//mxd. Do it sector-wise
Dictionary<Sector, int> sectors = new Dictionary<Sector, int>();
foreach(Linedef l in selected)
{
if(l.Front != null && l.Front.Sector != null)
{
if(!sectors.ContainsKey(l.Front.Sector)) sectors.Add(l.Front.Sector, 0);
sectors[l.Front.Sector]++;
}
if(l.Back != null && l.Back.Sector != null)
{
if(!sectors.ContainsKey(l.Back.Sector)) sectors.Add(l.Back.Sector, 0);
sectors[l.Back.Sector]++;
}
}
//mxd. Sort the collection so sectors with the most selected linedefs go first
List<KeyValuePair<Sector, int>> sortedlist = sectors.ToList();
sortedlist.Sort((firstPair, nextPair) => firstPair.Value.CompareTo(nextPair.Value));
sortedlist.Reverse();
//mxd. Gather our ordered sectors
List<Sector> sectorslist = new List<Sector>(sortedlist.Count());
sectorslist.AddRange(sortedlist.Select(pair => pair.Key));
//mxd. Flip the lines
Tools.FlipSectorLinedefs(sectorslist, true);
// Remove selection if only one linedef was selected
if(selected.Count == 1)
{
foreach(Linedef ld in selected) ld.Selected = false;
selected.Clear();
}
// Redraw
General.Map.Map.Update();
General.Map.IsChanged = true;
General.Interface.RefreshInfo();
General.Interface.RedrawDisplay();
General.Interface.DisplayStatus(StatusType.Warning, "This action requires a selection!");
return;
}
// Make undo
if(selected.Count > 1)
{
General.Map.UndoRedo.CreateUndo("Flip " + selected.Count + " linedefs");
General.Interface.DisplayStatus(StatusType.Action, "Flipped " + selected.Count + " linedefs.");
}
else
{
General.Map.UndoRedo.CreateUndo("Flip linedef");
General.Interface.DisplayStatus(StatusType.Action, "Flipped a linedef.");
}
// Flip all selected linedefs
foreach(Linedef l in selected)
{
l.FlipVertices();
l.FlipSidedefs();
}
// Remove selection if only one linedef was selected
if(selected.Count == 1)
{
foreach(Linedef ld in selected) ld.Selected = false;
selected.Clear();
}
// Redraw
General.Map.Map.Update();
General.Map.IsChanged = true;
General.Interface.RefreshInfo();
General.Interface.RedrawDisplay();
}
[BeginAction("alignlinedefs")]
public void AlignLinedefs() //mxd
{
// No selected lines?
ICollection<Linedef> selected = General.Map.Map.GetSelectedLinedefs(true);
if(selected.Count == 0)
{
// Anything highlighted?
if(highlighted != null)
{
// Select the highlighted item
highlighted.Selected = true;
selected.Add(highlighted);
}
}
// Any selected lines?
if(selected.Count == 0)
{
General.Interface.DisplayStatus(StatusType.Warning, "This action requires a selection!");
return;
}
// Make undo
if(selected.Count > 1)
{
General.Map.UndoRedo.CreateUndo("Align " + selected.Count + " linedefs");
General.Interface.DisplayStatus(StatusType.Action, "Aligned " + selected.Count + " linedefs.");
}
else
{
General.Map.UndoRedo.CreateUndo("Align linedef");
General.Interface.DisplayStatus(StatusType.Action, "Aligned a linedef.");
}
//mxd. Do it sector-wise
Dictionary<Sector, int> sectors = new Dictionary<Sector, int>();
foreach(Linedef l in selected)
{
if(l.Front != null && l.Front.Sector != null)
{
if(!sectors.ContainsKey(l.Front.Sector)) sectors.Add(l.Front.Sector, 0);
sectors[l.Front.Sector]++;
}
if(l.Back != null && l.Back.Sector != null)
{
if(!sectors.ContainsKey(l.Back.Sector)) sectors.Add(l.Back.Sector, 0);
sectors[l.Back.Sector]++;
}
}
//mxd. Sort the collection so sectors with the most selected linedefs go first
List<KeyValuePair<Sector, int>> sortedlist = sectors.ToList();
sortedlist.Sort((firstPair, nextPair) => firstPair.Value.CompareTo(nextPair.Value));
sortedlist.Reverse();
//mxd. Gather our ordered sectors
List<Sector> sectorslist = new List<Sector>(sortedlist.Count());
sectorslist.AddRange(sortedlist.Select(pair => pair.Key));
//mxd. Flip the lines
Tools.FlipSectorLinedefs(sectorslist, true);
// Remove selection if only one linedef was selected
if(selected.Count == 1)
{
foreach(Linedef ld in selected) ld.Selected = false;
selected.Clear();
}
// Redraw
General.Map.Map.Update();
General.Map.IsChanged = true;
General.Interface.RefreshInfo();
General.Interface.RedrawDisplay();
}
[BeginAction("flipsidedefs")]
@ -1363,6 +1422,13 @@ namespace CodeImp.DoomBuilder.BuilderModes
}
}
//mxd. Any selected lines?
if(selected.Count == 0)
{
General.Interface.DisplayStatus(StatusType.Warning, "This action requires a selection!");
return;
}
//mxd. Do this only with double-sided linedefs
List<Linedef> validlines = new List<Linedef>();
foreach(Linedef l in selected)
@ -1370,39 +1436,38 @@ namespace CodeImp.DoomBuilder.BuilderModes
if(l.Front != null && l.Back != null) validlines.Add(l);
}
// Any selected lines?
if(validlines.Count > 0)
//mxd. Any double-sided lines selected?
if(validlines.Count == 0)
{
// Make undo
if(validlines.Count > 1)
{
General.Map.UndoRedo.CreateUndo("Flip " + validlines.Count + " sidedefs");
General.Interface.DisplayStatus(StatusType.Action, "Flipped " + validlines.Count + " sidedefs.");
}
else
{
General.Map.UndoRedo.CreateUndo("Flip sidedef");
General.Interface.DisplayStatus(StatusType.Action, "Flipped a sidedef.");
}
// Flip sidedefs in all selected linedefs
foreach(Linedef l in validlines)
{
l.FlipSidedefs();
l.Front.Sector.UpdateNeeded = true;
l.Back.Sector.UpdateNeeded = true;
}
// Redraw
General.Map.Map.Update();
General.Map.IsChanged = true;
General.Interface.RefreshInfo();
General.Interface.RedrawDisplay();
}
else
{
General.Interface.DisplayStatus(StatusType.Warning, "No sidedefs to flip (only 2-sided linedefs can be flipped)!");
General.Interface.DisplayStatus(StatusType.Warning, "No sidedefs to flip! Only 2-sided linedefs can be flipped.");
return;
}
// Make undo
if(validlines.Count > 1)
{
General.Map.UndoRedo.CreateUndo("Flip " + validlines.Count + " sidedefs");
General.Interface.DisplayStatus(StatusType.Action, "Flipped " + validlines.Count + " sidedefs.");
}
else
{
General.Map.UndoRedo.CreateUndo("Flip sidedef");
General.Interface.DisplayStatus(StatusType.Action, "Flipped a sidedef.");
}
// Flip sidedefs in all selected linedefs
foreach(Linedef l in validlines)
{
l.FlipSidedefs();
l.Front.Sector.UpdateNeeded = true;
l.Back.Sector.UpdateNeeded = true;
}
// Redraw
General.Map.Map.Update();
General.Map.IsChanged = true;
General.Interface.RefreshInfo();
General.Interface.RedrawDisplay();
}
//mxd. Make gradient brightness

View file

@ -2411,6 +2411,57 @@ namespace CodeImp.DoomBuilder.BuilderModes
//mxd
[BeginAction("fliplinedefs")]
public void FlipLinedefs()
{
// Get selection
ICollection<Sector> selected = General.Map.Map.GetSelectedSectors(true);
if(selected.Count == 0 && highlighted != null && !highlighted.IsDisposed)
selected.Add(highlighted);
if(selected.Count == 0)
{
General.Interface.DisplayStatus(StatusType.Warning, "This action requires a selection!");
return;
}
// Make undo
if(selected.Count > 1)
{
General.Map.UndoRedo.CreateUndo("Align linedefs of " + selected.Count + " sectors");
General.Interface.DisplayStatus(StatusType.Action, "Aligned linedefs of " + selected.Count + "sectors.");
}
else
{
General.Map.UndoRedo.CreateUndo("Align sector linedefs");
General.Interface.DisplayStatus(StatusType.Action, "Aligned sector linedefs.");
}
HashSet<Linedef> selectedlines = new HashSet<Linedef>();
foreach(Sector s in selected)
{
foreach(Sidedef side in s.Sidedefs)
{
if(!selectedlines.Contains(side.Line)) selectedlines.Add(side.Line);
}
}
// Flip all selected linedefs
foreach(Linedef l in selectedlines)
{
l.FlipVertices();
l.FlipSidedefs();
}
// Redraw
General.Map.Map.Update();
General.Map.IsChanged = true;
General.Interface.RefreshInfo();
General.Interface.RedrawDisplay();
}
//mxd
[BeginAction("alignlinedefs")]
public void AlignLinedefs()
{
// Get selection
ICollection<Sector> selection = General.Map.Map.GetSelectedSectors(true);
@ -2427,13 +2478,13 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Make undo
if(selection.Count > 1)
{
General.Map.UndoRedo.CreateUndo("Flip linedefs of " + selection.Count + " sectors");
General.Interface.DisplayStatus(StatusType.Action, "Flipped linedefs of " + selection.Count + "sectors.");
General.Map.UndoRedo.CreateUndo("Align linedefs of " + selection.Count + " sectors");
General.Interface.DisplayStatus(StatusType.Action, "Aligned linedefs of " + selection.Count + "sectors.");
}
else
{
General.Map.UndoRedo.CreateUndo("Flip sector linedefs");
General.Interface.DisplayStatus(StatusType.Action, "Flipped sector linedefs.");
General.Map.UndoRedo.CreateUndo("Align sector linedefs");
General.Interface.DisplayStatus(StatusType.Action, "Aligned sector linedefs.");
}
// Flip lines

View file

@ -29,11 +29,12 @@
private void InitializeComponent()
{
this.toolstrip = new System.Windows.Forms.ToolStrip();
this.continuousdrawing = new System.Windows.Forms.ToolStripButton();
this.autoclosedrawing = new System.Windows.Forms.ToolStripButton();
this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
this.seglabel = new System.Windows.Forms.ToolStripLabel();
this.seglen = new CodeImp.DoomBuilder.Controls.ToolStripNumericUpDown();
this.reset = new System.Windows.Forms.ToolStripButton();
this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
this.continuousdrawing = new System.Windows.Forms.ToolStripButton();
this.toolstrip.SuspendLayout();
this.SuspendLayout();
//
@ -41,16 +42,43 @@
//
this.toolstrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.continuousdrawing,
this.autoclosedrawing,
this.toolStripSeparator1,
this.seglabel,
this.seglen,
this.reset});
this.toolstrip.Location = new System.Drawing.Point(0, 0);
this.toolstrip.Name = "toolstrip";
this.toolstrip.Size = new System.Drawing.Size(320, 25);
this.toolstrip.Size = new System.Drawing.Size(562, 25);
this.toolstrip.TabIndex = 7;
this.toolstrip.Text = "toolStrip1";
//
// continuousdrawing
//
this.continuousdrawing.CheckOnClick = true;
this.continuousdrawing.Image = global::CodeImp.DoomBuilder.BuilderModes.Properties.Resources.Repeat;
this.continuousdrawing.ImageTransparentColor = System.Drawing.Color.Magenta;
this.continuousdrawing.Name = "continuousdrawing";
this.continuousdrawing.Size = new System.Drawing.Size(135, 22);
this.continuousdrawing.Text = "Continuous drawing";
this.continuousdrawing.CheckedChanged += new System.EventHandler(this.continuousdrawing_CheckedChanged);
//
// autoclosedrawing
//
this.autoclosedrawing.CheckOnClick = true;
this.autoclosedrawing.Image = global::CodeImp.DoomBuilder.BuilderModes.Properties.Resources.NewSector2;
this.autoclosedrawing.ImageTransparentColor = System.Drawing.Color.Magenta;
this.autoclosedrawing.Margin = new System.Windows.Forms.Padding(2, 1, 0, 2);
this.autoclosedrawing.Name = "autoclosedrawing";
this.autoclosedrawing.Size = new System.Drawing.Size(131, 22);
this.autoclosedrawing.Text = "Auto-close drawing";
this.autoclosedrawing.CheckedChanged += new System.EventHandler(this.autoclosedrawing_CheckedChanged);
//
// toolStripSeparator1
//
this.toolStripSeparator1.Name = "toolStripSeparator1";
this.toolStripSeparator1.Size = new System.Drawing.Size(6, 25);
//
// seglabel
//
this.seglabel.Name = "seglabel";
@ -87,32 +115,17 @@
this.reset.Image = global::CodeImp.DoomBuilder.BuilderModes.Properties.Resources.Reset;
this.reset.ImageTransparentColor = System.Drawing.Color.Magenta;
this.reset.Name = "reset";
this.reset.Size = new System.Drawing.Size(23, 20);
this.reset.Size = new System.Drawing.Size(23, 22);
this.reset.Text = "Reset";
this.reset.Click += new System.EventHandler(this.reset_Click);
//
// toolStripSeparator1
//
this.toolStripSeparator1.Name = "toolStripSeparator1";
this.toolStripSeparator1.Size = new System.Drawing.Size(6, 25);
//
// continuousdrawing
//
this.continuousdrawing.CheckOnClick = true;
this.continuousdrawing.Image = global::CodeImp.DoomBuilder.BuilderModes.Properties.Resources.Repeat;
this.continuousdrawing.ImageTransparentColor = System.Drawing.Color.Magenta;
this.continuousdrawing.Name = "continuousdrawing";
this.continuousdrawing.Size = new System.Drawing.Size(135, 22);
this.continuousdrawing.Text = "Continuous drawing";
this.continuousdrawing.CheckedChanged += new System.EventHandler(this.continuousdrawing_CheckedChanged);
//
// DrawCurveOptionsPanel
//
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.Controls.Add(this.toolstrip);
this.Name = "DrawCurveOptionsPanel";
this.Size = new System.Drawing.Size(320, 60);
this.Size = new System.Drawing.Size(562, 60);
this.toolstrip.ResumeLayout(false);
this.toolstrip.PerformLayout();
this.ResumeLayout(false);
@ -128,6 +141,7 @@
private System.Windows.Forms.ToolStripButton reset;
private System.Windows.Forms.ToolStripButton continuousdrawing;
private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
private System.Windows.Forms.ToolStripButton autoclosedrawing;
}
}

View file

@ -7,10 +7,12 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
public event EventHandler OnValueChanged;
public event EventHandler OnContinuousDrawingChanged;
public event EventHandler OnAutoCloseDrawingChanged;
private bool blockevents;
public int SegmentLength { get { return (int)seglen.Value; } set { blockevents = true; seglen.Value = value; blockevents = false; } }
public bool ContinuousDrawing { get { return continuousdrawing.Checked; } set { continuousdrawing.Checked = value; } }
public bool AutoCloseDrawing { get { return autoclosedrawing.Checked; } set { autoclosedrawing.Checked = value; } }
public DrawCurveOptionsPanel(int minLength, int maxLength)
{
@ -25,6 +27,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
public void Register()
{
General.Interface.AddButton(continuousdrawing);
General.Interface.AddButton(autoclosedrawing);
General.Interface.AddButton(toolStripSeparator1);
General.Interface.AddButton(seglabel);
General.Interface.AddButton(seglen);
@ -37,6 +40,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
General.Interface.RemoveButton(seglen);
General.Interface.RemoveButton(seglabel);
General.Interface.RemoveButton(toolStripSeparator1);
General.Interface.RemoveButton(autoclosedrawing);
General.Interface.RemoveButton(continuousdrawing);
}
@ -54,5 +58,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
if(OnContinuousDrawingChanged != null) OnContinuousDrawingChanged(continuousdrawing.Checked, EventArgs.Empty);
}
private void autoclosedrawing_CheckedChanged(object sender, EventArgs e)
{
if(OnAutoCloseDrawingChanged != null) OnAutoCloseDrawingChanged(autoclosedrawing.Checked, EventArgs.Empty);
}
}
}

View file

@ -30,16 +30,18 @@
{
this.toolStrip1 = new System.Windows.Forms.ToolStrip();
this.continuousdrawing = new System.Windows.Forms.ToolStripButton();
this.autoclosedrawing = new System.Windows.Forms.ToolStripButton();
this.toolStrip1.SuspendLayout();
this.SuspendLayout();
//
// toolStrip1
//
this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.continuousdrawing});
this.continuousdrawing,
this.autoclosedrawing});
this.toolStrip1.Location = new System.Drawing.Point(0, 0);
this.toolStrip1.Name = "toolStrip1";
this.toolStrip1.Size = new System.Drawing.Size(200, 25);
this.toolStrip1.Size = new System.Drawing.Size(406, 25);
this.toolStrip1.TabIndex = 8;
this.toolStrip1.Text = "toolStrip1";
//
@ -53,13 +55,24 @@
this.continuousdrawing.Text = "Continuous drawing";
this.continuousdrawing.CheckedChanged += new System.EventHandler(this.continuousdrawing_CheckedChanged);
//
// autoclosedrawing
//
this.autoclosedrawing.CheckOnClick = true;
this.autoclosedrawing.Image = global::CodeImp.DoomBuilder.BuilderModes.Properties.Resources.NewSector2;
this.autoclosedrawing.ImageTransparentColor = System.Drawing.Color.Magenta;
this.autoclosedrawing.Margin = new System.Windows.Forms.Padding(2, 1, 0, 2);
this.autoclosedrawing.Name = "autoclosedrawing";
this.autoclosedrawing.Size = new System.Drawing.Size(133, 22);
this.autoclosedrawing.Text = "Auto-finish drawing";
this.autoclosedrawing.CheckedChanged += new System.EventHandler(this.autoclosedrawing_CheckedChanged);
//
// DrawLineOptionsPanel
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.toolStrip1);
this.Name = "DrawLineOptionsPanel";
this.Size = new System.Drawing.Size(200, 60);
this.Size = new System.Drawing.Size(406, 60);
this.toolStrip1.ResumeLayout(false);
this.toolStrip1.PerformLayout();
this.ResumeLayout(false);
@ -71,5 +84,6 @@
private System.Windows.Forms.ToolStrip toolStrip1;
private System.Windows.Forms.ToolStripButton continuousdrawing;
private System.Windows.Forms.ToolStripButton autoclosedrawing;
}
}

View file

@ -6,8 +6,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
internal partial class DrawLineOptionsPanel : UserControl
{
public event EventHandler OnContinuousDrawingChanged;
public event EventHandler OnAutoCloseDrawingChanged;
public bool ContinuousDrawing { get { return continuousdrawing.Checked; } set { continuousdrawing.Checked = value; } }
public bool AutoCloseDrawing { get { return autoclosedrawing.Checked; } set { autoclosedrawing.Checked = value; } }
public DrawLineOptionsPanel()
{
@ -17,10 +19,12 @@ namespace CodeImp.DoomBuilder.BuilderModes
public void Register()
{
General.Interface.AddButton(continuousdrawing);
General.Interface.AddButton(autoclosedrawing);
}
public void Unregister()
{
General.Interface.RemoveButton(autoclosedrawing);
General.Interface.RemoveButton(continuousdrawing);
}
@ -28,5 +32,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
if(OnContinuousDrawingChanged != null) OnContinuousDrawingChanged(continuousdrawing.Checked, EventArgs.Empty);
}
private void autoclosedrawing_CheckedChanged(object sender, EventArgs e)
{
if(OnAutoCloseDrawingChanged != null) OnAutoCloseDrawingChanged(autoclosedrawing.Checked, EventArgs.Empty);
}
}
}

View file

@ -88,7 +88,6 @@
0,
0,
0});
this.radius.ValueChanged += new System.EventHandler(this.ValueChanged);
//
// subdivslabel
//
@ -118,7 +117,6 @@
0,
0,
0});
this.subdivs.ValueChanged += new System.EventHandler(this.ValueChanged);
//
// continuousdrawing
//

View file

@ -107,6 +107,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
this.itemcopyprops = new System.Windows.Forms.ToolStripMenuItem();
this.itempasteprops = new System.Windows.Forms.ToolStripMenuItem();
this.itempastepropsoptions = new System.Windows.Forms.ToolStripMenuItem();
this.alignsectorlinedefsitem = new System.Windows.Forms.ToolStripMenuItem();
this.alignlinedefsitem = new System.Windows.Forms.ToolStripMenuItem();
this.menustrip.SuspendLayout();
this.manualstrip.SuspendLayout();
this.fileMenuStrip.SuspendLayout();
@ -135,6 +137,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
this.selectdoublesideditem,
this.toolStripMenuItem4,
this.fliplinedefsitem,
this.alignlinedefsitem,
this.flipsidedefsitem,
this.toolStripMenuItem1,
this.curvelinedefsitem,
@ -318,6 +321,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
this.mergesectorsitem,
this.toolStripMenuItem2,
this.flipsectorlinedefsitem,
this.alignsectorlinedefsitem,
this.toolStripSeparator8,
this.makedooritem,
this.toolStripSeparator4,
@ -847,6 +851,23 @@ namespace CodeImp.DoomBuilder.BuilderModes
this.itempastepropsoptions.Text = "Paste Properties Special...";
this.itempastepropsoptions.Click += new System.EventHandler(this.InvokeTaggedAction);
//
// alignsectorlinedefsitem
//
this.alignsectorlinedefsitem.Image = global::CodeImp.DoomBuilder.BuilderModes.Properties.Resources.Flip;
this.alignsectorlinedefsitem.Name = "alignsectorlinedefsitem";
this.alignsectorlinedefsitem.Size = new System.Drawing.Size(224, 22);
this.alignsectorlinedefsitem.Tag = "alignlinedefs";
this.alignsectorlinedefsitem.Text = "Align &Linedefs";
this.alignsectorlinedefsitem.Click += new System.EventHandler(this.InvokeTaggedAction);
//
// alignlinedefsitem
//
this.alignlinedefsitem.Image = global::CodeImp.DoomBuilder.BuilderModes.Properties.Resources.Flip;
this.alignlinedefsitem.Name = "alignlinedefsitem";
this.alignlinedefsitem.Size = new System.Drawing.Size(224, 22);
this.alignlinedefsitem.Tag = "alignlinedefs";
this.alignlinedefsitem.Text = "Align &Linedefs";
//
// MenusForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
@ -955,5 +976,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
private System.Windows.Forms.ToolStripMenuItem itempasteprops;
private System.Windows.Forms.ToolStripMenuItem itempastepropsoptions;
private System.Windows.Forms.ToolStripSeparator separatorcopyprops;
private System.Windows.Forms.ToolStripMenuItem alignsectorlinedefsitem;
private System.Windows.Forms.ToolStripMenuItem alignlinedefsitem;
}
}

View file

@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:2.0.50727.5485
// Runtime Version:2.0.50727.5466
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@ -256,6 +256,13 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties {
}
}
internal static System.Drawing.Bitmap NewSector2 {
get {
object obj = ResourceManager.GetObject("NewSector2", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
internal static System.Drawing.Bitmap PasteProperties {
get {
object obj = ResourceManager.GetObject("PasteProperties", resourceCulture);

View file

@ -118,6 +118,9 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="Join" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Join.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="FloorAlign" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\FloorAlign.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
@ -136,6 +139,9 @@
<data name="ViewSelectionEffects" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\ViewSelectionEffects.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Flip" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Flip.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="HideAll" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\HideAll.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
@ -193,9 +199,6 @@
<data name="Text" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Text.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Show" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Show.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="BrightnessGradient" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\BrightnessGradient.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
@ -211,8 +214,8 @@
<data name="Reset" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Reset.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Join" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Join.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
<data name="Show" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Show.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="ViewSelectionIndex" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\ViewSelectionIndex.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
@ -229,8 +232,8 @@
<data name="ColorPick" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\ColorPick.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Flip" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Flip.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
<data name="Repeat" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Repeat.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="FlipSelectionH" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\FlipSelectionH.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
@ -256,7 +259,7 @@
<data name="Show3" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Show3.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Repeat" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Repeat.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
<data name="NewSector2" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\NewSector2.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>

View file

@ -298,6 +298,16 @@ fliplinedefs
allowscroll = true;
}
alignlinedefs //mxd
{
title = "Align Linedefs";
category = "linedefs";
description = "This aligns the selected linedefs, so their front (or back) point towards (or away from) the same sector.";
allowkeys = true;
allowmouse = true;
allowscroll = true;
}
flipsidedefs
{
title = "Flip Sidedefs";

View file

@ -580,7 +580,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
}
// Processing
public virtual void OnProcess(float deltatime)
public virtual void OnProcess(long deltatime)
{
// If the texture was not loaded, but is loaded now, then re-setup geometry
if(setuponloadedtexture != 0)

View file

@ -795,7 +795,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
}
// Processing
public virtual void OnProcess(float deltatime)
public virtual void OnProcess(long deltatime)
{
// If the texture was not loaded, but is loaded now, then re-setup geometry
if(setuponloadedtexture != 0)

View file

@ -606,7 +606,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
public void OnTextureAlign(bool alignx, bool aligny) { }
public void OnToggleUpperUnpegged() { }
public void OnToggleLowerUnpegged() { }
public void OnProcess(float deltatime) { }
public void OnProcess(long deltatime) { }
public void OnTextureFloodfill() { }
public void OnInsert() { }
public void OnTextureFit(FitTextureOptions options) { } //mxd

View file

@ -254,7 +254,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
public void OnToggleLowerUnpegged() { }
public void OnResetTextureOffset() { }
public void OnResetLocalTextureOffset() { } //mxd
public void OnProcess(float deltatime) { }
public void OnProcess(long deltatime) { }
public void OnTextureFloodfill() { }
public void OnInsert() { }
public void ApplyTexture(string texture) { }

View file

@ -48,7 +48,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
void OnTextureFloodfill();
void OnToggleUpperUnpegged();
void OnToggleLowerUnpegged();
void OnProcess(float deltatime);
void OnProcess(long deltatime);
void OnInsert();
void OnDelete();

View file

@ -48,7 +48,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
public void OnTextureFloodfill() { }
public void OnToggleUpperUnpegged() { }
public void OnToggleLowerUnpegged() { }
public void OnProcess(float deltatime) { }
public void OnProcess(long deltatime) { }
public void OnInsert() { }
public void OnDelete() { }
public void ApplyTexture(string texture) { }