mirror of
https://git.do.srb2.org/STJr/UltimateZoneBuilder.git
synced 2025-01-31 04:40:55 +00:00
Texture Browser Form: swapped foreground and background colors of texture size labels.
Fixed, Texture Browser Form: well, I broke "Tab" key functionality again (in previous commit)... Maintenance: changed curly braces style to match DB2 one (hopefully not breaking anything in the process...). Maintenance: changed private method names casing to match DB2 one.
This commit is contained in:
parent
99f3ba2844
commit
15b2adfe30
281 changed files with 10033 additions and 5882 deletions
|
@ -192,7 +192,8 @@ namespace CodeImp.DoomBuilder.Actions
|
|||
}
|
||||
|
||||
//mxd. This returns the shortcut key description for an action name
|
||||
public static string GetShortcutKeyDesc(string actionName) {
|
||||
public static string GetShortcutKeyDesc(string actionName)
|
||||
{
|
||||
Action a = General.Actions.GetActionByName(actionName);
|
||||
if(a.ShortcutKey == 0) return a.Title + " (not bound to a key)";
|
||||
return GetShortcutKeyDesc(a.ShortcutKey);
|
||||
|
|
|
@ -36,7 +36,8 @@ namespace CodeImp.DoomBuilder.Actions
|
|||
|
||||
#region ================== Constructor
|
||||
|
||||
public HintsManager() {
|
||||
public HintsManager()
|
||||
{
|
||||
hints = new Dictionary<string, Dictionary<string, string>>(StringComparer.Ordinal);
|
||||
}
|
||||
|
||||
|
@ -46,39 +47,45 @@ namespace CodeImp.DoomBuilder.Actions
|
|||
|
||||
//Hints.cfg is dev-only stuff so bare minimum of boilerplate is present
|
||||
//(e.g. create your Hints.cfg exactly the way it's done in the main project).
|
||||
internal void LoadHints(Assembly asm) {
|
||||
internal void LoadHints(Assembly asm)
|
||||
{
|
||||
// Find a resource named Hints.cfg
|
||||
string[] resnames = asm.GetManifestResourceNames();
|
||||
string asmname = asm.GetName().Name.ToLowerInvariant() + "_";
|
||||
|
||||
foreach (string rn in resnames) {
|
||||
foreach (string rn in resnames)
|
||||
{
|
||||
// Found one?
|
||||
if(rn.EndsWith(HINTS_RESOURCE, StringComparison.InvariantCultureIgnoreCase)) {
|
||||
if(rn.EndsWith(HINTS_RESOURCE, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
string line;
|
||||
string classname = string.Empty;
|
||||
string groupname = string.Empty;
|
||||
List<string> lines = new List<string>(2);
|
||||
|
||||
// Get a stream from the resource
|
||||
using(Stream data = asm.GetManifestResourceStream(rn)) {
|
||||
using(StreamReader reader = new StreamReader(data, Encoding.ASCII)) {
|
||||
while (!reader.EndOfStream) {
|
||||
lines.Add(reader.ReadLine());
|
||||
}
|
||||
using(Stream data = asm.GetManifestResourceStream(rn))
|
||||
{
|
||||
using(StreamReader reader = new StreamReader(data, Encoding.ASCII))
|
||||
{
|
||||
while (!reader.EndOfStream) lines.Add(reader.ReadLine());
|
||||
}
|
||||
}
|
||||
|
||||
Dictionary<string, List<string>> group = new Dictionary<string, List<string>>(StringComparer.Ordinal);
|
||||
|
||||
foreach(string s in lines) {
|
||||
foreach(string s in lines)
|
||||
{
|
||||
line = s.Trim();
|
||||
if(string.IsNullOrEmpty(line) || line.StartsWith("//"))
|
||||
continue;
|
||||
|
||||
//class declaration?
|
||||
if(line.StartsWith(CLASS_MARKER)) {
|
||||
if(!string.IsNullOrEmpty(classname)) {
|
||||
hints.Add(asmname + classname, processHints(group));
|
||||
if(line.StartsWith(CLASS_MARKER))
|
||||
{
|
||||
if(!string.IsNullOrEmpty(classname))
|
||||
{
|
||||
hints.Add(asmname + classname, ProcessHints(group));
|
||||
}
|
||||
|
||||
classname = line.Substring(6, line.Length - 6);
|
||||
|
@ -88,7 +95,8 @@ namespace CodeImp.DoomBuilder.Actions
|
|||
}
|
||||
|
||||
//group declaration?
|
||||
if(line.StartsWith(GROUP_MARKER)) {
|
||||
if(line.StartsWith(GROUP_MARKER))
|
||||
{
|
||||
groupname = line.Substring(6, line.Length - 6);
|
||||
group.Add(groupname, new List<string>());
|
||||
continue;
|
||||
|
@ -99,7 +107,8 @@ namespace CodeImp.DoomBuilder.Actions
|
|||
|
||||
//replace action names with keys
|
||||
int start = line.IndexOf("<k>");
|
||||
while(start != -1) {
|
||||
while(start != -1)
|
||||
{
|
||||
int end = line.IndexOf("</k>");
|
||||
string key = line.Substring(start + 3, end - start - 3);
|
||||
line = line.Substring(0, start) + "{\\b " + Action.GetShortcutKeyDesc(key) + "}" + line.Substring(end + 4, line.Length - end - 4);
|
||||
|
@ -110,24 +119,28 @@ namespace CodeImp.DoomBuilder.Actions
|
|||
}
|
||||
|
||||
//add the last class
|
||||
hints.Add(asmname + classname, processHints(group));
|
||||
hints.Add(asmname + classname, ProcessHints(group));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Dictionary<string, string> processHints(Dictionary<string, List<string>> hintsgroup) {
|
||||
private static Dictionary<string, string> ProcessHints(Dictionary<string, List<string>> hintsgroup)
|
||||
{
|
||||
var result = new Dictionary<string, string>(StringComparer.Ordinal);
|
||||
foreach(KeyValuePair<string, List<string>> group in hintsgroup) {
|
||||
foreach(KeyValuePair<string, List<string>> group in hintsgroup)
|
||||
{
|
||||
result.Add(group.Key, "{\\rtf1" + string.Join("\\par\\par ", group.Value.ToArray()) + "}");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public void ShowHints(Type type, string groupname) {
|
||||
public void ShowHints(Type type, string groupname)
|
||||
{
|
||||
string fullname = type.Assembly.GetName().Name.ToLowerInvariant() + "_" + type.Name;
|
||||
|
||||
if (!hints.ContainsKey(fullname) || !hints[fullname].ContainsKey(groupname)) {
|
||||
if (!hints.ContainsKey(fullname) || !hints[fullname].ContainsKey(groupname))
|
||||
{
|
||||
General.Interface.ShowHints(DEFAULT_HINT);
|
||||
#if DEBUG
|
||||
Console.WriteLine("WARNING: Unable to get hints for class '" + fullname + "', group '" + groupname + "'");
|
||||
|
@ -141,7 +154,8 @@ namespace CodeImp.DoomBuilder.Actions
|
|||
|
||||
#region ================== Utility
|
||||
|
||||
public static string GetRtfString(string text) {
|
||||
public static string GetRtfString(string text)
|
||||
{
|
||||
text = text.Replace("<b>", "{\\b ").Replace("</b>", "}").Replace("<br>", "\\par\\par ");
|
||||
return "{\\rtf1" + text + "}";
|
||||
}
|
||||
|
|
|
@ -74,16 +74,19 @@ namespace CodeImp.DoomBuilder.Compilers
|
|||
|
||||
//xabis
|
||||
// Copy includes from the resources into the compiler's folder, preserving relative pathing and naming
|
||||
foreach (string include in General.Map.ScriptIncludes) {
|
||||
foreach (string include in General.Map.ScriptIncludes)
|
||||
{
|
||||
//grab the script text from the resources
|
||||
MemoryStream s = General.Map.Data.LoadFile(include);
|
||||
|
||||
if (s != null) {
|
||||
if (s != null)
|
||||
{
|
||||
//pull the pk3 or directory sub folder out if applicable
|
||||
FileInfo fi = new FileInfo(Path.Combine(this.tempdir.FullName, include));
|
||||
|
||||
//do not allow files to be overwritten, either accidentally or maliciously
|
||||
if (!fi.Exists) {
|
||||
if (!fi.Exists)
|
||||
{
|
||||
General.WriteLogLine("Copying script include: " + include);
|
||||
|
||||
//create the directory path as needed
|
||||
|
|
|
@ -135,9 +135,12 @@ namespace CodeImp.DoomBuilder.Compilers
|
|||
foreach(string f in info.Files)
|
||||
{
|
||||
string sourcefile = Path.Combine(info.Path, f);
|
||||
if (!File.Exists(sourcefile)) {
|
||||
if (!File.Exists(sourcefile))
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "The file '" + f + "' required by the '" + info.Name + "' compiler is missing. According to the compiler configuration in '" + info.FileName + "', the was expected to be found in the following path: " + info.Path);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
string targetfile = Path.Combine(tempdir.FullName, f);
|
||||
File.Copy(sourcefile, targetfile, true);
|
||||
}
|
||||
|
@ -172,7 +175,8 @@ namespace CodeImp.DoomBuilder.Compilers
|
|||
try
|
||||
{
|
||||
// Go for all assemblies
|
||||
foreach(Assembly a in asms) {
|
||||
foreach(Assembly a in asms)
|
||||
{
|
||||
// Find the class
|
||||
Type[] types = (Equals(a, General.ThisAssembly) ? a.GetTypes() : a.GetExportedTypes());
|
||||
|
||||
|
|
|
@ -129,13 +129,15 @@ namespace CodeImp.DoomBuilder.Compilers
|
|||
General.WriteLogLine("Compile time: " + deltatime.TotalSeconds.ToString("########0.00") + " seconds");
|
||||
|
||||
//mxd
|
||||
if (process.ExitCode > 0 || errorsInNormalOurput || errorsInErrorOutput) {
|
||||
if (errorsInNormalOurput) {
|
||||
if (process.ExitCode > 0 || errorsInNormalOurput || errorsInErrorOutput)
|
||||
{
|
||||
if (errorsInNormalOurput)
|
||||
{
|
||||
ReportError(new CompilerError(outMsg));
|
||||
General.WriteLogLine("Normal output: " + outMsg);
|
||||
}
|
||||
|
||||
if (errorsInErrorOutput) {
|
||||
if (errorsInErrorOutput)
|
||||
{
|
||||
ReportError(new CompilerError(outErr));
|
||||
General.WriteLogLine("Error output: " + outErr);
|
||||
}
|
||||
|
|
|
@ -303,12 +303,13 @@ namespace CodeImp.DoomBuilder.Config
|
|||
//mxd
|
||||
private void SaveTestEngines()
|
||||
{
|
||||
IDictionary resinfo, rlinfo;
|
||||
IDictionary rlinfo;
|
||||
|
||||
// Fill structure
|
||||
resinfo = new ListDictionary();
|
||||
IDictionary resinfo = new ListDictionary();
|
||||
|
||||
for(int i = 0; i < testEngines.Count; i++) {
|
||||
for(int i = 0; i < testEngines.Count; i++)
|
||||
{
|
||||
rlinfo = new ListDictionary();
|
||||
rlinfo.Add("testprogramname", testEngines[i].TestProgramName);
|
||||
rlinfo.Add("testprogram", testEngines[i].TestProgram);
|
||||
|
@ -328,12 +329,13 @@ namespace CodeImp.DoomBuilder.Config
|
|||
//mxd
|
||||
private void SaveLinedefColorPresets()
|
||||
{
|
||||
IDictionary resinfo, rlinfo;
|
||||
IDictionary rlinfo;
|
||||
|
||||
// Fill structure
|
||||
resinfo = new ListDictionary();
|
||||
IDictionary resinfo = new ListDictionary();
|
||||
|
||||
for(int i = 0; i < linedefColorPresets.Length; i++) {
|
||||
for(int i = 0; i < linedefColorPresets.Length; i++)
|
||||
{
|
||||
rlinfo = new ListDictionary();
|
||||
rlinfo.Add("name", linedefColorPresets[i].Name);
|
||||
rlinfo.Add("color", linedefColorPresets[i].Color.ToInt());
|
||||
|
|
|
@ -406,7 +406,8 @@ namespace CodeImp.DoomBuilder.Config
|
|||
#region ================== Loading
|
||||
|
||||
// This loads the map lumps
|
||||
private void LoadMapLumps() {
|
||||
private void LoadMapLumps()
|
||||
{
|
||||
// Get map lumps list
|
||||
IDictionary dic = cfg.ReadSetting("maplumpnames", new Hashtable());
|
||||
foreach(DictionaryEntry de in dic)
|
||||
|
@ -418,7 +419,8 @@ namespace CodeImp.DoomBuilder.Config
|
|||
}
|
||||
|
||||
// This loads the enumerations
|
||||
private void LoadEnums() {
|
||||
private void LoadEnums()
|
||||
{
|
||||
// Get enums list
|
||||
IDictionary dic = cfg.ReadSetting("enums", new Hashtable());
|
||||
foreach(DictionaryEntry de in dic)
|
||||
|
@ -805,7 +807,8 @@ namespace CodeImp.DoomBuilder.Config
|
|||
}
|
||||
|
||||
// Texture Sets
|
||||
private void LoadTextureSets() {
|
||||
private void LoadTextureSets()
|
||||
{
|
||||
// Get sets
|
||||
IDictionary dic = cfg.ReadSetting("texturesets", new Hashtable());
|
||||
foreach(DictionaryEntry de in dic)
|
||||
|
@ -846,7 +849,8 @@ namespace CodeImp.DoomBuilder.Config
|
|||
}
|
||||
|
||||
//mxd
|
||||
private void LoadStringDictionary(Dictionary<string, string> target, string settingname) {
|
||||
private void LoadStringDictionary(Dictionary<string, string> target, string settingname)
|
||||
{
|
||||
IDictionary dic = cfg.ReadSetting(settingname, new Hashtable());
|
||||
foreach(DictionaryEntry de in dic)
|
||||
target.Add(de.Key.ToString(), de.Value.ToString());
|
||||
|
|
|
@ -482,7 +482,7 @@ namespace CodeImp.DoomBuilder.Config
|
|||
#region ================== Methods
|
||||
|
||||
// This makes the path prefix for the given assembly
|
||||
private string GetPluginPathPrefix(Assembly asm)
|
||||
private static string GetPluginPathPrefix(Assembly asm)
|
||||
{
|
||||
Plugin p = General.Plugins.FindPluginByAssembly(asm);
|
||||
return GetPluginPathPrefix(p.Name);
|
||||
|
@ -557,7 +557,8 @@ namespace CodeImp.DoomBuilder.Config
|
|||
|
||||
//mxd. Set default arguments
|
||||
ThingTypeInfo tti = General.Map.Data.GetThingInfoEx(t.Type);
|
||||
if (tti != null) {
|
||||
if (tti != null)
|
||||
{
|
||||
t.Args[0] = (int)tti.Args[0].DefaultValue;
|
||||
t.Args[1] = (int)tti.Args[1].DefaultValue;
|
||||
t.Args[2] = (int)tti.Args[2].DefaultValue;
|
||||
|
|
|
@ -200,20 +200,29 @@ namespace CodeImp.DoomBuilder.Config
|
|||
|
||||
//mxd. Load Snippets
|
||||
string snippetsdir = cfg.ReadSetting("snippetsdir", "");
|
||||
if (!string.IsNullOrEmpty(snippetsdir)) {
|
||||
if (!string.IsNullOrEmpty(snippetsdir))
|
||||
{
|
||||
string snippetspath = Path.Combine(General.SnippetsPath, snippetsdir);
|
||||
if (Directory.Exists(snippetspath)) {
|
||||
if (Directory.Exists(snippetspath))
|
||||
{
|
||||
string[] files = Directory.GetFiles(snippetspath, "*.txt", SearchOption.TopDirectoryOnly);
|
||||
|
||||
foreach (string file in files) {
|
||||
foreach (string file in files)
|
||||
{
|
||||
string name = Path.GetFileNameWithoutExtension(file);
|
||||
if (name.Contains(" ")) {
|
||||
if (name.Contains(" "))
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Warning, "Failed to load snippet '" + file + "' for '" + description + "' script configuration: snippet file name must not contain spaces!");
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
string[] lines = File.ReadAllLines(file);
|
||||
if (lines.Length > 0) {
|
||||
if (lines.Length > 0)
|
||||
{
|
||||
snippets.Add(name, lines);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Warning, "Failed to load snippet '" + file + "' for '" + description + "' script configuration: file is empty!");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -90,7 +90,8 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
private void combobox_Validating(object sender, CancelEventArgs e)
|
||||
{
|
||||
//mxd
|
||||
if(gotTagArgument && combobox.SelectedItem != null) {
|
||||
if(gotTagArgument && combobox.SelectedItem != null)
|
||||
{
|
||||
typehandler.SetValue(((TagInfo)combobox.SelectedItem).Tag);
|
||||
return;
|
||||
}
|
||||
|
@ -200,7 +201,8 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
List<int> tags = new List<int>();
|
||||
List<TagInfo> infos = new List<TagInfo>();
|
||||
|
||||
foreach(Thing t in General.Map.Map.Things) {
|
||||
foreach(Thing t in General.Map.Map.Things)
|
||||
{
|
||||
if(t.Tag == 0 || tags.Contains(t.Tag)) continue;
|
||||
tags.Add(t.Tag);
|
||||
}
|
||||
|
@ -209,7 +211,8 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
tags.Sort();
|
||||
|
||||
//create tag infos
|
||||
foreach(int tag in tags) {
|
||||
foreach(int tag in tags)
|
||||
{
|
||||
if(General.Map.Options.TagLabels.ContainsKey(tag)) //tag labels
|
||||
infos.Add(new TagInfo(tag, General.Map.Options.TagLabels[tag]));
|
||||
else
|
||||
|
@ -234,7 +237,8 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
List<int> tags = new List<int>();
|
||||
List<TagInfo> infos = new List<TagInfo>();
|
||||
|
||||
foreach(Linedef t in General.Map.Map.Linedefs) {
|
||||
foreach(Linedef t in General.Map.Map.Linedefs)
|
||||
{
|
||||
if(t.Tag == 0 || tags.Contains(t.Tag)) continue;
|
||||
tags.Add(t.Tag);
|
||||
}
|
||||
|
@ -243,7 +247,8 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
tags.Sort();
|
||||
|
||||
//create tag infos
|
||||
foreach(int tag in tags) {
|
||||
foreach(int tag in tags)
|
||||
{
|
||||
if(General.Map.Options.TagLabels.ContainsKey(tag)) //tag labels
|
||||
infos.Add(new TagInfo(tag, General.Map.Options.TagLabels[tag]));
|
||||
else
|
||||
|
@ -268,7 +273,8 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
List<int> tags = new List<int>();
|
||||
List<TagInfo> infos = new List<TagInfo>();
|
||||
|
||||
foreach(Sector t in General.Map.Map.Sectors) {
|
||||
foreach(Sector t in General.Map.Map.Sectors)
|
||||
{
|
||||
if(t.Tag == 0 || tags.Contains(t.Tag)) continue;
|
||||
tags.Add(t.Tag);
|
||||
}
|
||||
|
@ -277,7 +283,8 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
tags.Sort();
|
||||
|
||||
//create tag infos
|
||||
foreach(int tag in tags) {
|
||||
foreach(int tag in tags)
|
||||
{
|
||||
if(General.Map.Options.TagLabels.ContainsKey(tag)) //tag labels
|
||||
infos.Add(new TagInfo(tag, General.Map.Options.TagLabels[tag]));
|
||||
else
|
||||
|
@ -295,7 +302,8 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
combobox.DropDownWidth = Tools.GetDropDownWidth(combobox);
|
||||
}
|
||||
// Check if this supports enumerated options
|
||||
else if(typehandler.IsEnumerable) {
|
||||
else if(typehandler.IsEnumerable)
|
||||
{
|
||||
// Show the combobox
|
||||
gotTagArgument = false; //mxd
|
||||
button.Visible = false;
|
||||
|
@ -324,10 +332,13 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
}
|
||||
|
||||
//mxd
|
||||
if(gotTagArgument) {
|
||||
if(gotTagArgument)
|
||||
{
|
||||
combobox.AutoCompleteMode = AutoCompleteMode.Suggest;
|
||||
combobox.AutoCompleteSource = AutoCompleteSource.ListItems;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
combobox.AutoCompleteMode = AutoCompleteMode.None;
|
||||
combobox.AutoCompleteSource = AutoCompleteSource.None;
|
||||
}
|
||||
|
@ -344,11 +355,13 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
{
|
||||
typehandler.SetValue(value);
|
||||
|
||||
if(gotTagArgument) { //mxd
|
||||
foreach(object item in combobox.Items) {
|
||||
if(gotTagArgument) //mxd
|
||||
{
|
||||
foreach(object item in combobox.Items)
|
||||
{
|
||||
TagInfo info = (TagInfo)item;
|
||||
|
||||
if(info.Tag == value) {
|
||||
if(info.Tag == value)
|
||||
{
|
||||
combobox.SelectedItem = item;
|
||||
return;
|
||||
}
|
||||
|
@ -361,7 +374,8 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
}
|
||||
|
||||
//mxd. this sets default value
|
||||
public void SetDefaultValue() {
|
||||
public void SetDefaultValue()
|
||||
{
|
||||
if(gotTagArgument) return; //default tag sounds a bit silly
|
||||
|
||||
typehandler.SetDefaultValue();
|
||||
|
@ -432,8 +446,11 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
}
|
||||
|
||||
//mxd. Very tricky way to close parent control by pressing ENTER or ESCAPE key when combobox.DropDownStyle == ComboBoxStyle.Simple
|
||||
protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
|
||||
if(this.ActiveControl == combobox && combobox.DropDownStyle == ComboBoxStyle.Simple && (keyData == Keys.Return || keyData == Keys.Escape)) {
|
||||
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
|
||||
{
|
||||
if(this.ActiveControl == combobox && combobox.DropDownStyle == ComboBoxStyle.Simple
|
||||
&& (keyData == Keys.Return || keyData == Keys.Escape))
|
||||
{
|
||||
combobox.DropDownStyle = ComboBoxStyle.DropDown;
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -130,7 +130,7 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
}
|
||||
|
||||
//mxd
|
||||
private int CheckboxesComparison(CheckBox cb1, CheckBox cb2)
|
||||
private static int CheckboxesComparison(CheckBox cb1, CheckBox cb2)
|
||||
{
|
||||
return String.Compare(cb1.Text, cb2.Text, StringComparison.Ordinal);
|
||||
}
|
||||
|
|
|
@ -14,11 +14,11 @@ namespace CodeImp.DoomBuilder
|
|||
[Flags]
|
||||
public enum DebugMessageType
|
||||
{
|
||||
Log = 1,
|
||||
Info = 2,
|
||||
Warning = 4,
|
||||
Error = 8,
|
||||
Special = 16,
|
||||
LOG = 1,
|
||||
INFO = 2,
|
||||
WARNING = 4,
|
||||
ERROR = 8,
|
||||
SPECIAL = 16,
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -61,20 +61,20 @@ namespace CodeImp.DoomBuilder
|
|||
|
||||
// Setup colors
|
||||
textcolors = new Dictionary<DebugMessageType, Color> {
|
||||
{ DebugMessageType.Log, SystemColors.WindowText },
|
||||
{ DebugMessageType.Info, Color.DarkGreen },
|
||||
{ DebugMessageType.Warning, Color.DarkOrange },
|
||||
{ DebugMessageType.Error, Color.DarkRed },
|
||||
{ DebugMessageType.Special, Color.DarkMagenta }
|
||||
{ DebugMessageType.LOG, SystemColors.WindowText },
|
||||
{ DebugMessageType.INFO, Color.DarkGreen },
|
||||
{ DebugMessageType.WARNING, Color.DarkOrange },
|
||||
{ DebugMessageType.ERROR, Color.DarkRed },
|
||||
{ DebugMessageType.SPECIAL, Color.DarkMagenta }
|
||||
};
|
||||
|
||||
// Setup headers
|
||||
textheaders = new Dictionary<DebugMessageType, string> {
|
||||
{ DebugMessageType.Log, string.Empty},
|
||||
{ DebugMessageType.Info, string.Empty},
|
||||
{ DebugMessageType.Warning, "Warning: "},
|
||||
{ DebugMessageType.Error, "ERROR: "},
|
||||
{ DebugMessageType.Special, string.Empty}
|
||||
{ DebugMessageType.LOG, string.Empty},
|
||||
{ DebugMessageType.INFO, string.Empty},
|
||||
{ DebugMessageType.WARNING, "Warning: "},
|
||||
{ DebugMessageType.ERROR, "ERROR: "},
|
||||
{ DebugMessageType.SPECIAL, string.Empty}
|
||||
};
|
||||
|
||||
// Word wrap?
|
||||
|
@ -90,12 +90,12 @@ namespace CodeImp.DoomBuilder
|
|||
|
||||
public static void Write(string text)
|
||||
{
|
||||
Write(DebugMessageType.Info, text);
|
||||
Write(DebugMessageType.INFO, text);
|
||||
}
|
||||
|
||||
public static void WriteLine(string text)
|
||||
{
|
||||
Write(DebugMessageType.Info, text + Environment.NewLine);
|
||||
Write(DebugMessageType.INFO, text + Environment.NewLine);
|
||||
}
|
||||
|
||||
public static void Write(DebugMessageType type, string text)
|
||||
|
@ -142,7 +142,7 @@ namespace CodeImp.DoomBuilder
|
|||
{
|
||||
if (starttime == -1)
|
||||
{
|
||||
Write(DebugMessageType.Warning, "Call General.Console.StartTimer before General.Console.StopTimer!");
|
||||
Write(DebugMessageType.WARNING, "Call General.Console.StartTimer before General.Console.StopTimer!");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -153,7 +153,7 @@ namespace CodeImp.DoomBuilder
|
|||
else
|
||||
message = message.TrimEnd() + " " + (endtime - starttime) + " ms.";
|
||||
|
||||
Write(DebugMessageType.Special, message);
|
||||
Write(DebugMessageType.SPECIAL, message);
|
||||
}
|
||||
|
||||
starttime = -1;
|
||||
|
@ -199,7 +199,7 @@ namespace CodeImp.DoomBuilder
|
|||
}
|
||||
|
||||
// Should we display this message?
|
||||
private bool CheckTextFilter(string text, string filter)
|
||||
private static bool CheckTextFilter(string text, string filter)
|
||||
{
|
||||
if (string.IsNullOrEmpty(filter) || filter.Length < 3) return true;
|
||||
return text.ToUpperInvariant().Contains(filter.ToUpperInvariant());
|
||||
|
|
9
Source/Core/Controls/DebugConsole.designer.cs
generated
9
Source/Core/Controls/DebugConsole.designer.cs
generated
|
@ -11,8 +11,10 @@
|
|||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing) {
|
||||
if(disposing && (components != null)) {
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if(disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
|
@ -24,7 +26,8 @@
|
|||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent() {
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.toolStrip1 = new System.Windows.Forms.ToolStrip();
|
||||
this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
|
||||
|
|
|
@ -257,10 +257,10 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
}
|
||||
|
||||
//mxd. This checks if given docker exists in this control
|
||||
public bool Contains(Docker d) {
|
||||
foreach (TabPage page in tabs.TabPages) {
|
||||
public bool Contains(Docker d)
|
||||
{
|
||||
foreach (TabPage page in tabs.TabPages)
|
||||
if ((page.Tag as Docker) == d) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -440,13 +440,13 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
General.MainWindow.Update();
|
||||
|
||||
// Raise event
|
||||
if(UserResize != null)
|
||||
UserResize(this, EventArgs.Empty);
|
||||
if(UserResize != null) UserResize(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
//mxd
|
||||
private void buttonTogglePinning_Click(object sender, EventArgs e) {
|
||||
private void buttonTogglePinning_Click(object sender, EventArgs e)
|
||||
{
|
||||
General.Settings.CollapseDockers = !General.Settings.CollapseDockers;
|
||||
General.MainWindow.SetupInterface();
|
||||
buttonTogglePinning.Image = General.Settings.CollapseDockers ? Properties.Resources.Unpin : Properties.Resources.Pin;
|
||||
|
|
|
@ -121,7 +121,8 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
public void ListFixedFields(List<UniversalFieldInfo> list)
|
||||
{
|
||||
// Add all fields
|
||||
foreach(UniversalFieldInfo uf in list) {
|
||||
foreach(UniversalFieldInfo uf in list)
|
||||
{
|
||||
if(uifields.ContainsKey(uf.Name)) continue; //mxd
|
||||
fieldslist.Rows.Add(new FieldsEditorRow(fieldslist, uf));
|
||||
}
|
||||
|
@ -237,48 +238,6 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
// Sort fields
|
||||
Sort();
|
||||
}
|
||||
|
||||
//mxd
|
||||
/*public object GetValue(string name) {
|
||||
//have required row?
|
||||
foreach (DataGridViewRow row in fieldslist.Rows) {
|
||||
// Row is a field?
|
||||
if (row is FieldsEditorRow) {
|
||||
FieldsEditorRow frow = row as FieldsEditorRow;
|
||||
// Row name matches with field
|
||||
if (frow.Name == name) {
|
||||
// Apply value of field to row
|
||||
if (frow.IsDefined && !frow.IsEmpty)
|
||||
return frow.GetResult(null);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}*/
|
||||
|
||||
//mxd
|
||||
/*public void SetValue(string name, object value, UniversalType type) {
|
||||
//have required row?
|
||||
foreach (DataGridViewRow row in fieldslist.Rows) {
|
||||
// Row is a field?
|
||||
if (row is FieldsEditorRow) {
|
||||
FieldsEditorRow frow = row as FieldsEditorRow;
|
||||
// Row name matches with field
|
||||
if (frow.Name == name) {
|
||||
// Apply value of field to row
|
||||
frow.Define(value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//no such row... let's add it
|
||||
FieldsEditorRow newfrow = new FieldsEditorRow(fieldslist, name, (int)type, value);
|
||||
fieldslist.Rows.Insert(fieldslist.Rows.Count - 1, newfrow);
|
||||
}*/
|
||||
|
||||
|
||||
// This applies the current fields to a UniFields object
|
||||
public void Apply(UniFields tofields)
|
||||
|
@ -287,7 +246,8 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
|
||||
// Go for all the fields
|
||||
UniFields tempfields = new UniFields(tofields);
|
||||
foreach(KeyValuePair<string, UniValue> f in tempfields) {
|
||||
foreach(KeyValuePair<string, UniValue> f in tempfields)
|
||||
{
|
||||
if (uifields.ContainsKey(f.Key)) continue; //mxd
|
||||
|
||||
// Go for all rows
|
||||
|
@ -544,15 +504,19 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
string validname = UniValue.ValidateName(row.Cells[0].Value.ToString());
|
||||
if(validname.Length > 0)
|
||||
{
|
||||
if(uifields.ContainsKey(validname)) { //mxd
|
||||
if(uifields.ContainsKey(validname)) //mxd
|
||||
{
|
||||
MessageBox.Show("Please set this field's value via user interface.");
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check if no other row already has this name
|
||||
foreach (DataGridViewRow r in fieldslist.Rows)
|
||||
{
|
||||
// Name matches and not the same row?
|
||||
if ((r.Index != row.Index) && (r.Cells.Count > 0) && (r.Cells[0].Value != null) &&
|
||||
(r.Cells[0].Value.ToString().ToLowerInvariant() == validname)) {
|
||||
(r.Cells[0].Value.ToString().ToLowerInvariant() == validname))
|
||||
{
|
||||
// Cannot have two rows with same name
|
||||
validname = "";
|
||||
General.ShowWarningMessage("Fields must have unique names!", MessageBoxButtons.OK);
|
||||
|
|
9
Source/Core/Controls/HintsPanel.Designer.cs
generated
9
Source/Core/Controls/HintsPanel.Designer.cs
generated
|
@ -11,8 +11,10 @@
|
|||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing) {
|
||||
if(disposing && (components != null)) {
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if(disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
|
@ -24,7 +26,8 @@
|
|||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent() {
|
||||
private void InitializeComponent()
|
||||
{
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(HintsPanel));
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.hints = new System.Windows.Forms.RichTextBox();
|
||||
|
|
|
@ -5,23 +5,27 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
{
|
||||
internal partial class HintsPanel : UserControl
|
||||
{
|
||||
public HintsPanel() {
|
||||
public HintsPanel()
|
||||
{
|
||||
InitializeComponent();
|
||||
hints.Clear();
|
||||
}
|
||||
|
||||
//hints should be in rtf markup!
|
||||
internal void SetHints(string hintsText) {
|
||||
internal void SetHints(string hintsText)
|
||||
{
|
||||
hints.Clear();
|
||||
hints.SelectedRtf = hintsText;
|
||||
}
|
||||
|
||||
internal void ClearHints() {
|
||||
internal void ClearHints()
|
||||
{
|
||||
hints.Clear();
|
||||
}
|
||||
|
||||
// Fight TextBoxes habit of not releasing the focus by using a carefully placed label
|
||||
private void hints_Enter(object sender, EventArgs e) {
|
||||
private void hints_Enter(object sender, EventArgs e)
|
||||
{
|
||||
label1.Focus();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -123,7 +123,7 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
this.showtexturesize.Location = new System.Drawing.Point(470, 9);
|
||||
this.showtexturesize.Name = "showtexturesize";
|
||||
this.showtexturesize.Size = new System.Drawing.Size(109, 18);
|
||||
this.showtexturesize.TabIndex = 2;
|
||||
this.showtexturesize.TabIndex = 0;
|
||||
this.showtexturesize.Text = "Show image size";
|
||||
this.showtexturesize.UseVisualStyleBackColor = true;
|
||||
this.showtexturesize.CheckedChanged += new System.EventHandler(this.showtexturesize_CheckedChanged);
|
||||
|
@ -134,7 +134,7 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
this.longtexturenames.Location = new System.Drawing.Point(585, 9);
|
||||
this.longtexturenames.Name = "longtexturenames";
|
||||
this.longtexturenames.Size = new System.Drawing.Size(122, 18);
|
||||
this.longtexturenames.TabIndex = 1;
|
||||
this.longtexturenames.TabIndex = 0;
|
||||
this.longtexturenames.Text = "Long texture names";
|
||||
this.longtexturenames.UseVisualStyleBackColor = true;
|
||||
this.longtexturenames.CheckedChanged += new System.EventHandler(this.longtexturenames_CheckedChanged);
|
||||
|
|
|
@ -325,7 +325,7 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
foreach(ListViewItem item in list.Items)
|
||||
{
|
||||
ImageBrowserItem curitem = item as ImageBrowserItem;
|
||||
if(curitem != null && string.Compare(curitem.icon.Name, name, true) == 0)
|
||||
if(curitem != null && string.Compare(curitem.Icon.Name, name, true) == 0)
|
||||
{
|
||||
lvi = curitem;
|
||||
if(item.Group == preferredgroup) break;
|
||||
|
@ -536,9 +536,9 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
//mxd. mixMode: 0 = All, 1 = Textures, 2 = Flats, 3 = Based on BrowseFlats
|
||||
if(!splitter.Panel2Collapsed)
|
||||
{
|
||||
if(mixMode == 1 && i.icon.IsFlat) return false;
|
||||
if(mixMode == 2 && !i.icon.IsFlat) return false;
|
||||
if(mixMode == 3 && (browseFlats != i.icon.IsFlat)) return false;
|
||||
if(mixMode == 1 && i.Icon.IsFlat) return false;
|
||||
if(mixMode == 2 && !i.Icon.IsFlat) return false;
|
||||
if(mixMode == 3 && (browseFlats != i.Icon.IsFlat)) return false;
|
||||
}
|
||||
|
||||
return i.Text.ToUpperInvariant().Contains(objectname.Text.ToUpperInvariant());
|
||||
|
@ -547,9 +547,9 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
//mxd. This validates an item's texture size
|
||||
private static bool ValidateItemSize(ImageBrowserItem i, int w, int h)
|
||||
{
|
||||
if (!i.icon.IsPreviewLoaded) return true;
|
||||
if (w > 0 && i.icon.Width != w) return false;
|
||||
if (h > 0 && i.icon.Height != h) return false;
|
||||
if (!i.Icon.IsPreviewLoaded) return true;
|
||||
if (w > 0 && i.Icon.Width != w) return false;
|
||||
if (h > 0 && i.Icon.Height != h) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
#region ================== Variables
|
||||
|
||||
// Display image and text
|
||||
public readonly ImageData icon;
|
||||
public readonly ImageData Icon;
|
||||
private string imagesize; //mxd
|
||||
private bool showfullname; //mxd
|
||||
private static readonly StringFormat format = new StringFormat { Alignment = StringAlignment.Center }; //mxd
|
||||
|
@ -56,7 +56,7 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
public ListViewGroup ListGroup { get { return listgroup; } set { listgroup = value; } }
|
||||
public bool IsPreviewLoaded { get { return imageloaded; } }
|
||||
public bool ShowFullName { set { showfullname = value; UpdateName(); } }
|
||||
public string TextureName { get { return showfullname ? icon.Name : icon.ShortName; } }
|
||||
public string TextureName { get { return showfullname ? Icon.Name : Icon.ShortName; } }
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -66,7 +66,7 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
public ImageBrowserItem(ImageData icon, object tag, bool showfullname)
|
||||
{
|
||||
// Initialize
|
||||
this.icon = icon;
|
||||
this.Icon = icon;
|
||||
this.Tag = tag;
|
||||
this.showfullname = showfullname; //mxd
|
||||
UpdateName(); //mxd
|
||||
|
@ -80,7 +80,7 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
public bool CheckRedrawNeeded()
|
||||
{
|
||||
UpdateName(); //mxd. Update texture size if needed
|
||||
return (icon.IsPreviewLoaded != imageloaded);
|
||||
return (Icon.IsPreviewLoaded != imageloaded);
|
||||
}
|
||||
|
||||
// This draws the images
|
||||
|
@ -90,7 +90,7 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
Brush backcolor;
|
||||
|
||||
// Remember if the preview is loaded
|
||||
imageloaded = icon.IsPreviewLoaded;
|
||||
imageloaded = Icon.IsPreviewLoaded;
|
||||
|
||||
// Drawing settings
|
||||
g.CompositingQuality = CompositingQuality.HighSpeed;
|
||||
|
@ -123,7 +123,7 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
|
||||
// Draw!
|
||||
g.FillRectangle(backcolor, bounds);
|
||||
icon.DrawPreview(g, imagerect.Location);
|
||||
Icon.DrawPreview(g, imagerect.Location);
|
||||
g.DrawString(Text, this.ListView.Font, forecolor, textpos, format);
|
||||
|
||||
//mxd. Draw size label?
|
||||
|
@ -134,11 +134,11 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
textsize = g.MeasureString(imagesize, sizefont, bounds.Width * 2);
|
||||
textpos = new PointF(bounds.Left + textsize.Width / 2, bounds.Top + 1);
|
||||
imagerect = new Rectangle(bounds.Left + 1, bounds.Top + 1, (int)textsize.Width, (int)textsize.Height);
|
||||
SolidBrush labelbg = new SolidBrush(Color.FromArgb(196, base.ListView.BackColor));
|
||||
SolidBrush labelbg = new SolidBrush(Color.FromArgb(196, base.ListView.ForeColor));
|
||||
|
||||
// Draw
|
||||
g.FillRectangle(labelbg, imagerect);
|
||||
g.DrawString(imagesize, sizefont, new SolidBrush(base.ListView.ForeColor), textpos, format);
|
||||
g.DrawString(imagesize, sizefont, new SolidBrush(base.ListView.BackColor), textpos, format);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -165,9 +165,9 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
//mxd
|
||||
private void UpdateName()
|
||||
{
|
||||
Text = (showfullname ? icon.DisplayName : icon.ShortName);
|
||||
if(General.Settings.ShowTextureSizes && icon.IsPreviewLoaded)
|
||||
imagesize = icon.ScaledWidth + "x" + icon.ScaledHeight;
|
||||
Text = (showfullname ? Icon.DisplayName : Icon.ShortName);
|
||||
if(General.Settings.ShowTextureSizes && Icon.IsPreviewLoaded)
|
||||
imagesize = Icon.ScaledWidth + "x" + Icon.ScaledHeight;
|
||||
}
|
||||
|
||||
// Comparer
|
||||
|
|
|
@ -60,7 +60,8 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
}
|
||||
|
||||
//mxd
|
||||
protected override void OnKeyUp(KeyEventArgs e) {
|
||||
protected override void OnKeyUp(KeyEventArgs e)
|
||||
{
|
||||
if(OnKeyReleased != null) OnKeyReleased(this, e);
|
||||
}
|
||||
|
||||
|
|
|
@ -121,7 +121,8 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
Point cp;
|
||||
|
||||
//mxd. Check if valid extenal data is present
|
||||
if(e.Data.GetDataPresent(DataFormats.FileDrop)) {
|
||||
if(e.Data.GetDataPresent(DataFormats.FileDrop))
|
||||
{
|
||||
e.Effect = DragDropEffects.Copy;
|
||||
return;
|
||||
}
|
||||
|
@ -218,7 +219,8 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
base.OnDragEnter(e);
|
||||
|
||||
//mxd. Check if valid extenal data is present
|
||||
if(e.Data.GetDataPresent(DataFormats.FileDrop)) {
|
||||
if(e.Data.GetDataPresent(DataFormats.FileDrop))
|
||||
{
|
||||
e.Effect = DragDropEffects.Copy;
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -2314,14 +2314,14 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
this.ignoredkeys.Add((int)key + (int)modifier, (int)key + (int)modifier);
|
||||
}
|
||||
|
||||
private void addShortcuts(Menu m)
|
||||
private void AddShortcuts(Menu m)
|
||||
{
|
||||
foreach(MenuItem mi in m.MenuItems)
|
||||
{
|
||||
if(mi.Shortcut != Shortcut.None)
|
||||
AddIgnoredKey(mi.Shortcut);
|
||||
if(mi.MenuItems.Count > 0)
|
||||
addShortcuts(mi);
|
||||
AddShortcuts(mi);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2329,7 +2329,7 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
{
|
||||
if((parentForm != null) && (parentForm.Menu != null))
|
||||
{
|
||||
addShortcuts(parentForm.Menu);
|
||||
AddShortcuts(parentForm.Menu);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -49,8 +49,7 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
|
||||
// The script edit control
|
||||
protected readonly ScriptEditorControl editor;
|
||||
//mxd
|
||||
protected readonly ComboBox navigator;
|
||||
protected readonly ComboBox navigator; //mxd
|
||||
|
||||
// Derived classes must set this!
|
||||
protected ScriptConfiguration config;
|
||||
|
@ -198,7 +197,7 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
// This changes the script configurations
|
||||
public virtual void ChangeScriptConfig(ScriptConfiguration newconfig)
|
||||
{
|
||||
updateNavigator(); //mxd
|
||||
UpdateNavigator(); //mxd
|
||||
}
|
||||
|
||||
// Call this to set the tab title
|
||||
|
@ -307,21 +306,23 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
}
|
||||
|
||||
//mxd
|
||||
protected void updateNavigator()
|
||||
protected void UpdateNavigator()
|
||||
{
|
||||
//mxd. known script type?
|
||||
if (config.ScriptType != ScriptType.UNKNOWN) {
|
||||
switch(config.ScriptType) {
|
||||
if (config.ScriptType != ScriptType.UNKNOWN)
|
||||
{
|
||||
switch(config.ScriptType)
|
||||
{
|
||||
case ScriptType.ACS:
|
||||
updateNavigatorAcs(new MemoryStream(editor.GetText()));
|
||||
UpdateNavigatorAcs(new MemoryStream(editor.GetText()));
|
||||
break;
|
||||
|
||||
case ScriptType.DECORATE:
|
||||
updateNavigatorDecorate(new MemoryStream(editor.GetText()));
|
||||
UpdateNavigatorDecorate(new MemoryStream(editor.GetText()));
|
||||
break;
|
||||
|
||||
case ScriptType.MODELDEF:
|
||||
updateNavigatorModeldef(new MemoryStream(editor.GetText()));
|
||||
UpdateNavigatorModeldef(new MemoryStream(editor.GetText()));
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -329,14 +330,16 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
}
|
||||
|
||||
navigator.Enabled = true;
|
||||
}else{
|
||||
}
|
||||
else
|
||||
{
|
||||
navigator.Items.Clear();
|
||||
navigator.Enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
//mxd
|
||||
private void updateNavigatorDecorate(MemoryStream stream)
|
||||
private void UpdateNavigatorDecorate(MemoryStream stream)
|
||||
{
|
||||
if (stream == null) return;
|
||||
|
||||
|
@ -351,7 +354,7 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
}
|
||||
|
||||
//mxd
|
||||
private void updateNavigatorModeldef(MemoryStream stream)
|
||||
private void UpdateNavigatorModeldef(MemoryStream stream)
|
||||
{
|
||||
if (stream == null) return;
|
||||
|
||||
|
@ -366,7 +369,7 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
}
|
||||
|
||||
//mxd
|
||||
private void updateNavigatorAcs(MemoryStream stream)
|
||||
private void UpdateNavigatorAcs(MemoryStream stream)
|
||||
{
|
||||
if (stream == null) return;
|
||||
|
||||
|
@ -386,7 +389,8 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
internal ScriptType VerifyScriptType()
|
||||
{
|
||||
ScriptTypeParserSE parser = new ScriptTypeParserSE();
|
||||
if (parser.Parse(new MemoryStream(editor.GetText()), config.Description)) {
|
||||
if (parser.Parse(new MemoryStream(editor.GetText()), config.Description))
|
||||
{
|
||||
if (parser.ScriptType != ScriptType.UNKNOWN && config.ScriptType != parser.ScriptType)
|
||||
return parser.ScriptType;
|
||||
}
|
||||
|
@ -424,8 +428,10 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
}
|
||||
|
||||
//mxd
|
||||
protected void navigator_SelectedIndexChanged(object sender, EventArgs e) {
|
||||
if (navigator.SelectedItem is ScriptItem) {
|
||||
private void navigator_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (navigator.SelectedItem is ScriptItem)
|
||||
{
|
||||
ScriptItem si = navigator.SelectedItem as ScriptItem;
|
||||
editor.EnsureLineVisible(editor.LineFromPosition(si.SelectionStart));
|
||||
editor.SelectionStart = si.SelectionStart;
|
||||
|
@ -438,8 +444,9 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
}
|
||||
|
||||
//mxd
|
||||
protected void navigator_DropDown(object sender, EventArgs e) {
|
||||
if(editor.IsChanged) updateNavigator();
|
||||
private void navigator_DropDown(object sender, EventArgs e)
|
||||
{
|
||||
if(editor.IsChanged) UpdateNavigator();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
|
|
@ -664,15 +664,18 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
string spaces = new String(' ', General.Settings.ScriptTabWidth);
|
||||
int entrypos = -1;
|
||||
int entryline = -1;
|
||||
string[] processedlines = processLineBreaks(lines);
|
||||
string[] processedlines = ProcessLineBreaks(lines);
|
||||
|
||||
for (int i = 0; i < lines.Length; i++) {
|
||||
for (int i = 0; i < lines.Length; i++)
|
||||
{
|
||||
processedlines[i] = processedlines[i].Replace("\t", spaces);
|
||||
|
||||
//check if we have the [EP] marker
|
||||
if (entrypos == -1) {
|
||||
if (entrypos == -1)
|
||||
{
|
||||
int pos = processedlines[i].IndexOf("[EP]");
|
||||
if (pos != -1) {
|
||||
if (pos != -1)
|
||||
{
|
||||
entryline = curline + i;
|
||||
entrypos = pos + numtabs;
|
||||
processedlines[i] = processedlines[i].Remove(pos, 4);
|
||||
|
@ -687,7 +690,8 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
scriptedit.ReplaceSel(text);
|
||||
|
||||
//move the cursor if we had the [EP] marker
|
||||
if (entrypos != -1) {
|
||||
if (entrypos != -1)
|
||||
{
|
||||
MoveToLine(entryline);
|
||||
scriptedit.SelectionStart = scriptedit.PositionFromLine(entryline) + entrypos;
|
||||
scriptedit.SelectionEnd = scriptedit.PositionFromLine(entryline) + entrypos;
|
||||
|
@ -695,19 +699,22 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
}
|
||||
|
||||
//mxd. This converts [LB] markers to line breaks if necessary
|
||||
private static string[] processLineBreaks(string[] lines)
|
||||
private static string[] ProcessLineBreaks(string[] lines)
|
||||
{
|
||||
List<string> result = new List<string>(lines.Length);
|
||||
string[] separator = new[] { "[LB]" };
|
||||
|
||||
foreach(string line in lines) {
|
||||
if(line.IndexOf(separator[0]) != -1) {
|
||||
if(General.Settings.SnippetsAllmanStyle) {
|
||||
foreach(string line in lines)
|
||||
{
|
||||
if(line.IndexOf(separator[0]) != -1)
|
||||
{
|
||||
if(General.Settings.SnippetsAllmanStyle)
|
||||
result.AddRange(line.Split(separator, StringSplitOptions.RemoveEmptyEntries));
|
||||
} else {
|
||||
else
|
||||
result.Add(line.Replace(separator[0], " "));
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Add(line);
|
||||
}
|
||||
}
|
||||
|
@ -912,11 +919,10 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
int tippos;
|
||||
int funcline = scriptedit.LineFromPosition(curfunctionstartpos);
|
||||
int curline = scriptedit.LineFromPosition(scriptedit.CurrentPos);
|
||||
if(curline > funcline) {
|
||||
if(curline > funcline)
|
||||
tippos = scriptedit.PositionFromLine(curline) + scriptedit.GetLineIndentation(curline); //scriptedit.PositionFromLine(curline) /*+ (curfunctionstartpos - scriptedit.PositionFromLine(funcline))*/;
|
||||
} else {
|
||||
else
|
||||
tippos = curfunctionstartpos;
|
||||
}
|
||||
|
||||
// Show tip
|
||||
scriptedit.CallTipShow(tippos, functiondef);
|
||||
|
|
|
@ -134,13 +134,13 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
}
|
||||
}
|
||||
|
||||
// Select the first tab
|
||||
//if(tabs.TabPages.Count > 0) tabs.SelectedIndex = 0;
|
||||
|
||||
//mxd. Select "Scripts" tab, because that's what user will want 99% of time
|
||||
if (tabs.TabPages.Count > 0) {
|
||||
foreach (TabPage p in tabs.TabPages) {
|
||||
if (p.Text == "SCRIPTS") {
|
||||
if (tabs.TabPages.Count > 0)
|
||||
{
|
||||
foreach (TabPage p in tabs.TabPages)
|
||||
{
|
||||
if (p.Text == "SCRIPTS")
|
||||
{
|
||||
tabs.SelectedTab = p;
|
||||
break;
|
||||
}
|
||||
|
@ -494,10 +494,10 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
}
|
||||
|
||||
//mxd. Add snippets
|
||||
if(t.Config.Snippets.Count > 0) {
|
||||
foreach(KeyValuePair<string, string[]> group in t.Config.Snippets) {
|
||||
if(t.Config.Snippets.Count > 0)
|
||||
{
|
||||
foreach(KeyValuePair<string, string[]> group in t.Config.Snippets)
|
||||
buttonsnippets.DropDownItems.Add(group.Key).Click += OnInsertSnippetClick;
|
||||
}
|
||||
}
|
||||
|
||||
// Focus to script editor
|
||||
|
@ -530,9 +530,12 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
{
|
||||
//mxd
|
||||
ScriptType st = t.VerifyScriptType();
|
||||
if (st != ScriptType.UNKNOWN) {
|
||||
foreach (ScriptConfiguration cfg in scriptconfigs) {
|
||||
if (cfg.ScriptType == st) {
|
||||
if (st != ScriptType.UNKNOWN)
|
||||
{
|
||||
foreach (ScriptConfiguration cfg in scriptconfigs)
|
||||
{
|
||||
if (cfg.ScriptType == st)
|
||||
{
|
||||
t.ChangeScriptConfig(cfg);
|
||||
break;
|
||||
}
|
||||
|
@ -540,8 +543,7 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
}
|
||||
|
||||
// Mark any errors this script may have
|
||||
if(compilererrors != null)
|
||||
t.MarkScriptErrors(compilererrors);
|
||||
if(compilererrors != null) t.MarkScriptErrors(compilererrors);
|
||||
|
||||
// Add to tabs
|
||||
tabs.TabPages.Add(t);
|
||||
|
@ -579,7 +581,8 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
}
|
||||
|
||||
//mxd. This launches keyword help website
|
||||
public bool LaunchKeywordHelp() {
|
||||
public bool LaunchKeywordHelp()
|
||||
{
|
||||
// Get script
|
||||
ScriptDocumentTab t = (tabs.SelectedTab as ScriptDocumentTab);
|
||||
return t.LaunchKeywordHelp();
|
||||
|
|
|
@ -119,9 +119,8 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
}
|
||||
|
||||
//mxd. Should be called only if script is compiled successfully
|
||||
if (compiler.Errors.Length == 0 && config.ScriptType == ScriptType.ACS) {
|
||||
if (compiler.Errors.Length == 0 && config.ScriptType == ScriptType.ACS)
|
||||
General.Map.UpdateScriptNames();
|
||||
}
|
||||
}
|
||||
|
||||
// Dispose compiler
|
||||
|
|
|
@ -74,7 +74,7 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
editor.SetText(stream.ToArray());
|
||||
editor.ClearUndoRedo();
|
||||
//mxd
|
||||
updateNavigator();
|
||||
UpdateNavigator();
|
||||
}
|
||||
|
||||
// Done
|
||||
|
|
|
@ -11,8 +11,10 @@
|
|||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing) {
|
||||
if(disposing && (components != null)) {
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if(disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
|
@ -24,7 +26,8 @@
|
|||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent() {
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.label23 = new System.Windows.Forms.Label();
|
||||
this.label24 = new System.Windows.Forms.Label();
|
||||
this.reset = new System.Windows.Forms.Button();
|
||||
|
|
|
@ -10,9 +10,9 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
{
|
||||
public class SplitButton : Button
|
||||
{
|
||||
private PushButtonState _state;
|
||||
private const int SplitSectionWidth = 18;
|
||||
private static readonly int BorderSize = SystemInformation.Border3DSize.Width * 2;
|
||||
private PushButtonState state;
|
||||
private const int splitsectionwidth = 18;
|
||||
private static readonly int borderSize = SystemInformation.Border3DSize.Width * 2;
|
||||
private bool skipNextOpen;
|
||||
private Rectangle dropDownRectangle;
|
||||
private bool showSplit;
|
||||
|
@ -111,13 +111,13 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
{
|
||||
get
|
||||
{
|
||||
return _state;
|
||||
return state;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (!_state.Equals(value))
|
||||
if (!state.Equals(value))
|
||||
{
|
||||
_state = value;
|
||||
state = value;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
@ -127,9 +127,7 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
|
||||
protected override bool IsInputKey(Keys keyData)
|
||||
{
|
||||
if (keyData.Equals(Keys.Down) && showSplit)
|
||||
return true;
|
||||
|
||||
if (keyData.Equals(Keys.Down) && showSplit) return true;
|
||||
return base.IsInputKey(keyData);
|
||||
}
|
||||
|
||||
|
@ -302,9 +300,9 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
}
|
||||
|
||||
// calculate the current dropdown rectangle.
|
||||
dropDownRectangle = new Rectangle(bounds.Right - SplitSectionWidth, 0, SplitSectionWidth, bounds.Height);
|
||||
dropDownRectangle = new Rectangle(bounds.Right - splitsectionwidth, 0, splitsectionwidth, bounds.Height);
|
||||
|
||||
int internalBorder = BorderSize;
|
||||
int internalBorder = borderSize;
|
||||
Rectangle focusRect =
|
||||
new Rectangle(internalBorder - 1,
|
||||
internalBorder - 1,
|
||||
|
@ -322,8 +320,8 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
if (drawSplitLine)
|
||||
{
|
||||
// draw two lines at the edge of the dropdown button
|
||||
g.DrawLine(SystemPens.ButtonShadow, bounds.Left + SplitSectionWidth, BorderSize, bounds.Left + SplitSectionWidth, bounds.Bottom - BorderSize);
|
||||
g.DrawLine(SystemPens.ButtonFace, bounds.Left + SplitSectionWidth + 1, BorderSize, bounds.Left + SplitSectionWidth + 1, bounds.Bottom - BorderSize);
|
||||
g.DrawLine(SystemPens.ButtonShadow, bounds.Left + splitsectionwidth, borderSize, bounds.Left + splitsectionwidth, bounds.Bottom - borderSize);
|
||||
g.DrawLine(SystemPens.ButtonFace, bounds.Left + splitsectionwidth + 1, borderSize, bounds.Left + splitsectionwidth + 1, bounds.Bottom - borderSize);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -331,8 +329,8 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
if (drawSplitLine)
|
||||
{
|
||||
// draw two lines at the edge of the dropdown button
|
||||
g.DrawLine(SystemPens.ButtonShadow, bounds.Right - SplitSectionWidth, BorderSize, bounds.Right - SplitSectionWidth, bounds.Bottom - BorderSize);
|
||||
g.DrawLine(SystemPens.ButtonFace, bounds.Right - SplitSectionWidth - 1, BorderSize, bounds.Right - SplitSectionWidth - 1, bounds.Bottom - BorderSize);
|
||||
g.DrawLine(SystemPens.ButtonShadow, bounds.Right - splitsectionwidth, borderSize, bounds.Right - splitsectionwidth, bounds.Bottom - borderSize);
|
||||
g.DrawLine(SystemPens.ButtonFace, bounds.Right - splitsectionwidth - 1, borderSize, bounds.Right - splitsectionwidth - 1, bounds.Bottom - borderSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -402,8 +400,8 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
{
|
||||
if (AutoSize) return CalculateButtonAutoSize();
|
||||
|
||||
if (!string.IsNullOrEmpty(Text) && TextRenderer.MeasureText(Text, Font).Width + SplitSectionWidth > preferredSize.Width)
|
||||
return preferredSize + new Size(SplitSectionWidth + BorderSize * 2, 0);
|
||||
if (!string.IsNullOrEmpty(Text) && TextRenderer.MeasureText(Text, Font).Width + splitsectionwidth > preferredSize.Width)
|
||||
return preferredSize + new Size(splitsectionwidth + borderSize * 2, 0);
|
||||
}
|
||||
|
||||
return preferredSize;
|
||||
|
@ -445,7 +443,7 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
ret_size.Width += (Padding.Horizontal + 6);
|
||||
|
||||
//pad the splitButton arrow region
|
||||
if (showSplit) ret_size.Width += SplitSectionWidth;
|
||||
if (showSplit) ret_size.Width += splitsectionwidth;
|
||||
|
||||
return ret_size;
|
||||
}
|
||||
|
@ -471,7 +469,7 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
textRectangle = OverlayObjectRect(ref content_rect, ref text_size, TextAlign); // Rectangle.Inflate(content_rect, -4, -4);
|
||||
|
||||
//Offset on Windows 98 style when button is pressed
|
||||
if (_state == PushButtonState.Pressed && !Application.RenderWithVisualStyles)
|
||||
if (state == PushButtonState.Pressed && !Application.RenderWithVisualStyles)
|
||||
textRectangle.Offset(1, 1);
|
||||
|
||||
// Image is dependent on ImageAlign
|
||||
|
|
|
@ -11,8 +11,10 @@
|
|||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing) {
|
||||
if(disposing && (components != null)) {
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if(disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
|
@ -24,7 +26,8 @@
|
|||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent() {
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.thingscount = new System.Windows.Forms.Label();
|
||||
this.sectorscount = new System.Windows.Forms.Label();
|
||||
this.sidedefscount = new System.Windows.Forms.Label();
|
||||
|
|
|
@ -4,12 +4,14 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
{
|
||||
public partial class StatisticsControl : UserControl
|
||||
{
|
||||
public StatisticsControl() {
|
||||
public StatisticsControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.Visible = false;
|
||||
}
|
||||
|
||||
public void UpdateStatistics() {
|
||||
public void UpdateStatistics()
|
||||
{
|
||||
verticescount.Text = General.Map.Map.Vertices.Count.ToString();
|
||||
linedefscount.Text = General.Map.Map.Linedefs.Count.ToString();
|
||||
sidedefscount.Text = General.Map.Map.Sidedefs.Count.ToString();
|
||||
|
|
|
@ -148,7 +148,7 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
return new List<TreeNode>(vn.Values);
|
||||
}
|
||||
|
||||
private void GetValidNodes(TreeNode root, ref Dictionary<string, TreeNode> vn)
|
||||
private static void GetValidNodes(TreeNode root, ref Dictionary<string, TreeNode> vn)
|
||||
{
|
||||
if (root.Nodes.Count == 0)
|
||||
{
|
||||
|
|
|
@ -171,20 +171,25 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
arg5.Enabled = arginfo[4].Used;
|
||||
|
||||
//mxd
|
||||
if(hasArg0Str) {
|
||||
if(hasArg0Str)
|
||||
{
|
||||
arg1.Text = '"' + t.Fields["arg0str"].Value.ToString() + '"';
|
||||
} else {
|
||||
setArgumentText(arginfo[0], arg1, t.Args[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetArgumentText(arginfo[0], arg1, t.Args[0]);
|
||||
}
|
||||
setArgumentText(arginfo[1], arg2, t.Args[1]);
|
||||
setArgumentText(arginfo[2], arg3, t.Args[2]);
|
||||
setArgumentText(arginfo[3], arg4, t.Args[3]);
|
||||
setArgumentText(arginfo[4], arg5, t.Args[4]);
|
||||
SetArgumentText(arginfo[1], arg2, t.Args[1]);
|
||||
SetArgumentText(arginfo[2], arg3, t.Args[2]);
|
||||
SetArgumentText(arginfo[3], arg4, t.Args[3]);
|
||||
SetArgumentText(arginfo[4], arg5, t.Args[4]);
|
||||
|
||||
//mxd. Flags
|
||||
flags.Items.Clear();
|
||||
foreach(KeyValuePair<string, bool> group in t.Flags){
|
||||
if(group.Value) {
|
||||
foreach(KeyValuePair<string, bool> group in t.Flags)
|
||||
{
|
||||
if(group.Value)
|
||||
{
|
||||
ListViewItem item = new ListViewItem(General.Map.Config.ThingFlags.ContainsKey(group.Key) ? General.Map.Config.ThingFlags[group.Key] : group.Key);
|
||||
item.Checked = true;
|
||||
flags.Items.Add(item);
|
||||
|
@ -193,7 +198,8 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
|
||||
//mxd. Flags panel visibility and size
|
||||
flagsPanel.Visible = (flags.Items.Count > 0);
|
||||
if(flags.Items.Count > 0) {
|
||||
if(flags.Items.Count > 0)
|
||||
{
|
||||
int itemWidth = flags.Items[0].GetBounds(ItemBoundsPortion.Entire).Width;
|
||||
if(itemWidth == 0) itemWidth = 96;
|
||||
flags.Width = itemWidth * (int)Math.Ceiling(flags.Items.Count / 5.0f);
|
||||
|
@ -206,7 +212,7 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
}
|
||||
|
||||
//mxd
|
||||
private static void setArgumentText(ArgumentInfo info, Label label, int value)
|
||||
private static void SetArgumentText(ArgumentInfo info, Label label, int value)
|
||||
{
|
||||
TypeHandler th = General.Types.GetArgumentHandler(info);
|
||||
th.SetValue(value);
|
||||
|
@ -214,7 +220,8 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
|
||||
if(value < 1 || !General.Map.Options.TagLabels.ContainsKey(value)) return;
|
||||
|
||||
if (th is ThingTagHandler || th is LinedefTagHandler || th is SectorTagHandler) {
|
||||
if (th is ThingTagHandler || th is LinedefTagHandler || th is SectorTagHandler)
|
||||
{
|
||||
label.Text += " (" + General.Map.Options.TagLabels[value] + ")";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,18 +15,21 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
|
||||
public ToolStripCheckBox() : base(new CheckBox()) { }
|
||||
|
||||
protected override void OnSubscribeControlEvents(Control control) {
|
||||
protected override void OnSubscribeControlEvents(Control control)
|
||||
{
|
||||
base.OnSubscribeControlEvents(control);
|
||||
cb = control as CheckBox;
|
||||
cb.CheckedChanged += OnCheckedChanged;
|
||||
}
|
||||
|
||||
protected override void OnUnsubscribeControlEvents(Control control) {
|
||||
protected override void OnUnsubscribeControlEvents(Control control)
|
||||
{
|
||||
base.OnUnsubscribeControlEvents(control);
|
||||
cb.CheckedChanged -= OnCheckedChanged;
|
||||
}
|
||||
|
||||
public void OnCheckedChanged(object sender, EventArgs e) {
|
||||
private void OnCheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
if(CheckedChanged != null) CheckedChanged(this, e);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,20 +40,27 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
position.Text = v.Position.x.ToString("0.##") + ", " + v.Position.y.ToString("0.##");
|
||||
|
||||
//mxd. Height offsets
|
||||
if(General.Map.UDMF) {
|
||||
if(!float.IsNaN(v.ZCeiling)) {
|
||||
if(General.Map.UDMF)
|
||||
{
|
||||
if(!float.IsNaN(v.ZCeiling))
|
||||
{
|
||||
zceiling.Text = v.ZCeiling.ToString("0.##");
|
||||
zceiling.Enabled = true;
|
||||
labelCeilingOffset.Enabled = true;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
zceiling.Text = "--";
|
||||
}
|
||||
|
||||
if(!float.IsNaN(v.ZFloor)) {
|
||||
if(!float.IsNaN(v.ZFloor))
|
||||
{
|
||||
zfloor.Text = v.ZFloor.ToString("0.##");
|
||||
zfloor.Enabled = true;
|
||||
labelFloorOffset.Enabled = true;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
zfloor.Text = "--";
|
||||
}
|
||||
|
||||
|
|
|
@ -319,12 +319,12 @@ namespace CodeImp.DoomBuilder.Data
|
|||
LoadInternalSprites();
|
||||
|
||||
//mxd
|
||||
loadMapInfo();
|
||||
LoadMapInfo();
|
||||
ModelReader.Init();
|
||||
loadVoxels();
|
||||
Dictionary<string, int> actorsByClass = createActorsByClassList();
|
||||
loadModeldefs(actorsByClass);
|
||||
loadGldefs(actorsByClass);
|
||||
LoadVoxels();
|
||||
Dictionary<string, int> actorsByClass = CreateActorsByClassList();
|
||||
LoadModeldefs(actorsByClass);
|
||||
LoadGldefs(actorsByClass);
|
||||
foreach (Thing t in General.Map.Map.Things) t.UpdateCache();
|
||||
General.MainWindow.DisplayReady();
|
||||
|
||||
|
@ -462,7 +462,8 @@ namespace CodeImp.DoomBuilder.Data
|
|||
palette = null;
|
||||
|
||||
//mxd
|
||||
if (modeldefEntries != null) {
|
||||
if (modeldefEntries != null)
|
||||
{
|
||||
foreach (KeyValuePair<int, ModelData> group in modeldefEntries)
|
||||
group.Value.Dispose();
|
||||
}
|
||||
|
@ -1469,19 +1470,22 @@ namespace CodeImp.DoomBuilder.Data
|
|||
#region ================== mxd. Modeldef, Voxeldef, Gldefs, Mapinfo
|
||||
|
||||
//mxd. This creates <Actor Class, Thing.Type> dictionary. Should be called after all DECORATE actors are parsed
|
||||
private Dictionary<string, int> createActorsByClassList() {
|
||||
private Dictionary<string, int> CreateActorsByClassList()
|
||||
{
|
||||
Dictionary<string, int> actors = new Dictionary<string, int>(StringComparer.Ordinal);
|
||||
Dictionary<int, ThingTypeInfo> things = General.Map.Config.GetThingTypes();
|
||||
|
||||
//read our new shiny ClassNames for default game things
|
||||
foreach (KeyValuePair<int, ThingTypeInfo> ti in things) {
|
||||
foreach (KeyValuePair<int, ThingTypeInfo> ti in things)
|
||||
{
|
||||
if (ti.Value.ClassName != null)
|
||||
actors.Add(ti.Value.ClassName, ti.Key);
|
||||
}
|
||||
|
||||
//and for actors defined in DECORATE
|
||||
ICollection<ActorStructure> ac = decorate.Actors;
|
||||
foreach (ActorStructure actor in ac) {
|
||||
foreach (ActorStructure actor in ac)
|
||||
{
|
||||
string className = actor.ClassName.ToLower();
|
||||
if (!actors.ContainsKey(className))
|
||||
actors.Add(className, actor.DoomEdNum);
|
||||
|
@ -1494,22 +1498,25 @@ namespace CodeImp.DoomBuilder.Data
|
|||
}
|
||||
|
||||
//mxd
|
||||
public void ReloadModeldef() {
|
||||
if (modeldefEntries != null) {
|
||||
public void ReloadModeldef()
|
||||
{
|
||||
if (modeldefEntries != null)
|
||||
{
|
||||
foreach (KeyValuePair<int, ModelData> group in modeldefEntries)
|
||||
group.Value.Dispose();
|
||||
}
|
||||
|
||||
General.MainWindow.DisplayStatus(StatusType.Busy, "Reloading model definitions...");
|
||||
loadModeldefs(createActorsByClassList());
|
||||
LoadModeldefs(CreateActorsByClassList());
|
||||
|
||||
General.MainWindow.DisplayStatus(StatusType.Busy, "Reloading voxel definitions...");
|
||||
loadVoxels();
|
||||
LoadVoxels();
|
||||
|
||||
foreach(Thing t in General.Map.Map.Things) t.UpdateCache();
|
||||
|
||||
//rebuild geometry if in Visual mode
|
||||
if (General.Editing.Mode != null && General.Editing.Mode.GetType().Name == "BaseVisualMode") {
|
||||
if (General.Editing.Mode != null && General.Editing.Mode.GetType().Name == "BaseVisualMode")
|
||||
{
|
||||
General.Editing.Mode.OnReloadResources();
|
||||
}
|
||||
|
||||
|
@ -1517,19 +1524,24 @@ namespace CodeImp.DoomBuilder.Data
|
|||
}
|
||||
|
||||
//mxd
|
||||
public void ReloadGldefs() {
|
||||
public void ReloadGldefs()
|
||||
{
|
||||
General.MainWindow.DisplayStatus(StatusType.Busy, "Reloading GLDEFS...");
|
||||
|
||||
try {
|
||||
loadGldefs(createActorsByClassList());
|
||||
} catch(ArgumentNullException) {
|
||||
try
|
||||
{
|
||||
LoadGldefs(CreateActorsByClassList());
|
||||
}
|
||||
catch(ArgumentNullException)
|
||||
{
|
||||
MessageBox.Show("GLDEFS reload failed. Try using 'Reload Resources' instead.\nCheck 'Errors and Warnings' window for more details.");
|
||||
General.MainWindow.DisplayReady();
|
||||
return;
|
||||
}
|
||||
|
||||
//rebuild geometry if in Visual mode
|
||||
if (General.Editing.Mode != null && General.Editing.Mode.GetType().Name == "BaseVisualMode") {
|
||||
if (General.Editing.Mode != null && General.Editing.Mode.GetType().Name == "BaseVisualMode")
|
||||
{
|
||||
General.Editing.Mode.OnReloadResources();
|
||||
}
|
||||
|
||||
|
@ -1537,19 +1549,24 @@ namespace CodeImp.DoomBuilder.Data
|
|||
}
|
||||
|
||||
//mxd
|
||||
public void ReloadMapInfo() {
|
||||
public void ReloadMapInfo()
|
||||
{
|
||||
General.MainWindow.DisplayStatus(StatusType.Busy, "Reloading (Z)MAPINFO...");
|
||||
|
||||
try {
|
||||
loadMapInfo();
|
||||
} catch (ArgumentNullException) {
|
||||
try
|
||||
{
|
||||
LoadMapInfo();
|
||||
}
|
||||
catch (ArgumentNullException)
|
||||
{
|
||||
MessageBox.Show("(Z)MAPINFO reload failed. Try using 'Reload Resources' instead.\nCheck 'Errors and Warnings' window for more details.");
|
||||
General.MainWindow.DisplayReady();
|
||||
return;
|
||||
}
|
||||
|
||||
//rebuild geometry if in Visual mode
|
||||
if (General.Editing.Mode != null && General.Editing.Mode.GetType().Name == "BaseVisualMode") {
|
||||
if (General.Editing.Mode != null && General.Editing.Mode.GetType().Name == "BaseVisualMode")
|
||||
{
|
||||
General.Editing.Mode.OnReloadResources();
|
||||
}
|
||||
|
||||
|
@ -1557,28 +1574,35 @@ namespace CodeImp.DoomBuilder.Data
|
|||
}
|
||||
|
||||
//mxd. This parses modeldefs. Should be called after all DECORATE actors are parsed and actorsByClass dictionary created
|
||||
private void loadModeldefs(Dictionary<string, int> actorsByClass) {
|
||||
private void LoadModeldefs(Dictionary<string, int> actorsByClass)
|
||||
{
|
||||
//if no actors defined in DECORATE or game config...
|
||||
if (actorsByClass == null || actorsByClass.Count == 0) return;
|
||||
|
||||
Dictionary<string, ModelData> modelDefEntriesByName = new Dictionary<string, ModelData>(StringComparer.Ordinal);
|
||||
ModeldefParser parser = new ModeldefParser();
|
||||
|
||||
foreach (DataReader dr in containers) {
|
||||
foreach (DataReader dr in containers)
|
||||
{
|
||||
currentreader = dr;
|
||||
|
||||
Dictionary<string, Stream> streams = dr.GetModeldefData();
|
||||
foreach (KeyValuePair<string, Stream> group in streams) {
|
||||
foreach (KeyValuePair<string, Stream> group in streams)
|
||||
{
|
||||
// Parse the data
|
||||
if(parser.Parse(group.Value, currentreader.Location.location + "\\" + group.Key)) {
|
||||
foreach(KeyValuePair<string, ModelData> g in parser.Entries) {
|
||||
if (modelDefEntriesByName.ContainsKey(g.Key)) {
|
||||
if(parser.Parse(group.Value, currentreader.Location.location + "\\" + group.Key))
|
||||
{
|
||||
foreach(KeyValuePair<string, ModelData> g in parser.Entries)
|
||||
{
|
||||
if (modelDefEntriesByName.ContainsKey(g.Key))
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Warning, "Model definition for actor '" + g.Key + "' is double-defined in '" + group.Key + "'");
|
||||
modelDefEntriesByName[g.Key] = g.Value;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
modelDefEntriesByName.Add(g.Key, g.Value);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1586,7 +1610,8 @@ namespace CodeImp.DoomBuilder.Data
|
|||
|
||||
currentreader = null;
|
||||
|
||||
foreach (KeyValuePair<string, ModelData> e in modelDefEntriesByName) {
|
||||
foreach (KeyValuePair<string, ModelData> e in modelDefEntriesByName)
|
||||
{
|
||||
if (actorsByClass.ContainsKey(e.Key))
|
||||
modeldefEntries[actorsByClass[e.Key]] = modelDefEntriesByName[e.Key];
|
||||
else if(!invalidDecorateActors.Contains(e.Key))
|
||||
|
@ -1595,17 +1620,20 @@ namespace CodeImp.DoomBuilder.Data
|
|||
}
|
||||
|
||||
//mxd
|
||||
private void loadVoxels() {
|
||||
private void LoadVoxels()
|
||||
{
|
||||
//Get names of all voxel models, which can be used "as is"
|
||||
Dictionary<string, bool> voxelNames = new Dictionary<string, bool>(StringComparer.Ordinal);
|
||||
|
||||
foreach(DataReader dr in containers) {
|
||||
foreach(DataReader dr in containers)
|
||||
{
|
||||
currentreader = dr;
|
||||
|
||||
string[] result = dr.GetVoxelNames();
|
||||
if(result == null) continue;
|
||||
|
||||
foreach(string s in result) {
|
||||
foreach(string s in result)
|
||||
{
|
||||
if(!voxelNames.ContainsKey(s)) voxelNames.Add(s, false);
|
||||
}
|
||||
}
|
||||
|
@ -1613,14 +1641,18 @@ namespace CodeImp.DoomBuilder.Data
|
|||
Dictionary<string, List<int>> sprites = new Dictionary<string, List<int>>(StringComparer.Ordinal);
|
||||
|
||||
// Go for all things
|
||||
foreach(ThingTypeInfo ti in thingtypes.Values) {
|
||||
foreach(ThingTypeInfo ti in thingtypes.Values)
|
||||
{
|
||||
// Valid sprite name?
|
||||
string sprite;
|
||||
|
||||
if(ti.Sprite.Length == 0 || ti.Sprite.Length > CLASIC_IMAGE_NAME_LENGTH) {
|
||||
if(ti.Sprite.Length == 0 || ti.Sprite.Length > CLASIC_IMAGE_NAME_LENGTH)
|
||||
{
|
||||
if(ti.Actor == null) continue;
|
||||
sprite = ti.Actor.FindSuitableVoxel(voxelNames);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
sprite = ti.Sprite;
|
||||
}
|
||||
|
||||
|
@ -1633,17 +1665,20 @@ namespace CodeImp.DoomBuilder.Data
|
|||
Dictionary<string, bool> processed = new Dictionary<string, bool>(StringComparer.Ordinal);
|
||||
|
||||
//parse VOXLEDEF
|
||||
foreach(DataReader dr in containers) {
|
||||
foreach(DataReader dr in containers)
|
||||
{
|
||||
currentreader = dr;
|
||||
|
||||
KeyValuePair<string, Stream> group = dr.GetVoxeldefData();
|
||||
if(group.Value != null && parser.Parse(group.Value, group.Key)) {
|
||||
foreach(KeyValuePair<string, ModelData> entry in parser.Entries){
|
||||
foreach(KeyValuePair<string, List<int>> sc in sprites) {
|
||||
if (sc.Key.Contains(entry.Key)) {
|
||||
foreach(int id in sc.Value) {
|
||||
modeldefEntries[id] = entry.Value;
|
||||
}
|
||||
if(group.Value != null && parser.Parse(group.Value, group.Key))
|
||||
{
|
||||
foreach(KeyValuePair<string, ModelData> entry in parser.Entries)
|
||||
{
|
||||
foreach(KeyValuePair<string, List<int>> sc in sprites)
|
||||
{
|
||||
if (sc.Key.Contains(entry.Key))
|
||||
{
|
||||
foreach(int id in sc.Value) modeldefEntries[id] = entry.Value;
|
||||
processed.Add(entry.Key, false);
|
||||
}
|
||||
}
|
||||
|
@ -1654,32 +1689,34 @@ namespace CodeImp.DoomBuilder.Data
|
|||
currentreader = null;
|
||||
|
||||
//get voxel models
|
||||
foreach(KeyValuePair<string, bool> group in voxelNames) {
|
||||
foreach(KeyValuePair<string, bool> group in voxelNames)
|
||||
{
|
||||
if(processed.ContainsKey(group.Key)) continue;
|
||||
foreach (KeyValuePair<string, List<int>> sc in sprites) {
|
||||
if(sc.Key.Contains(group.Key)) {
|
||||
foreach (KeyValuePair<string, List<int>> sc in sprites)
|
||||
{
|
||||
if(sc.Key.Contains(group.Key))
|
||||
{
|
||||
//it's a model without a definition, and it corresponds to a sprite we can display, so let's add it
|
||||
ModelData data = new ModelData { IsVoxel = true };
|
||||
data.ModelNames.Add(group.Key);
|
||||
|
||||
foreach(int id in sprites[sc.Key]) {
|
||||
modeldefEntries[id] = data;
|
||||
}
|
||||
foreach(int id in sprites[sc.Key]) modeldefEntries[id] = data;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//mxd. This parses gldefs. Should be called after all DECORATE actors are parsed and actorsByClass dictionary created
|
||||
private void loadGldefs(Dictionary<string, int> actorsByClass) {
|
||||
private void LoadGldefs(Dictionary<string, int> actorsByClass)
|
||||
{
|
||||
//if no actors defined in DECORATE or game config...
|
||||
if (actorsByClass == null || actorsByClass.Count == 0) return;
|
||||
|
||||
GldefsParser parser = new GldefsParser();
|
||||
parser.OnInclude = loadGldefsFromLocation;
|
||||
GldefsParser parser = new GldefsParser { OnInclude = LoadGldefsFromLocation };
|
||||
|
||||
//load gldefs from resources
|
||||
foreach (DataReader dr in containers) {
|
||||
foreach (DataReader dr in containers)
|
||||
{
|
||||
currentreader = dr;
|
||||
Dictionary<string, Stream> streams = dr.GetGldefsData(General.Map.Config.GameType);
|
||||
|
||||
|
@ -1688,31 +1725,37 @@ namespace CodeImp.DoomBuilder.Data
|
|||
}
|
||||
|
||||
//create gldefsEntries dictionary
|
||||
foreach (KeyValuePair<string, string> e in parser.Objects) { //ClassName, Light name
|
||||
foreach (KeyValuePair<string, string> e in parser.Objects) //ClassName, Light name
|
||||
{
|
||||
|
||||
//if we have decorate actor and light definition for given ClassName...
|
||||
if (actorsByClass.ContainsKey(e.Key) && parser.LightsByName.ContainsKey(e.Value)) {
|
||||
if (actorsByClass.ContainsKey(e.Key) && parser.LightsByName.ContainsKey(e.Value))
|
||||
{
|
||||
int thingType = actorsByClass[e.Key];
|
||||
if (gldefsEntries.ContainsKey(thingType)) {
|
||||
if (gldefsEntries.ContainsKey(thingType))
|
||||
gldefsEntries[thingType] = parser.LightsByName[e.Value];
|
||||
}else{
|
||||
else
|
||||
gldefsEntries.Add(thingType, parser.LightsByName[e.Value]);
|
||||
}
|
||||
} else if(!invalidDecorateActors.Contains(e.Key)) {
|
||||
}
|
||||
else if(!invalidDecorateActors.Contains(e.Key))
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Warning, "Got GLDEFS light for class '" + e.Key + "', but haven't found such class in DECORATE");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//mxd. This loads (Z)MAPINFO
|
||||
private void loadMapInfo() {
|
||||
private void LoadMapInfo()
|
||||
{
|
||||
MapinfoParser parser = new MapinfoParser();
|
||||
|
||||
foreach (DataReader dr in containers) {
|
||||
foreach (DataReader dr in containers)
|
||||
{
|
||||
currentreader = dr;
|
||||
|
||||
Dictionary<string, Stream> streams = dr.GetMapinfoData();
|
||||
foreach (KeyValuePair<string, Stream> group in streams) {
|
||||
foreach (KeyValuePair<string, Stream> group in streams)
|
||||
{
|
||||
// Parse the data
|
||||
parser.Parse(group.Value, Path.Combine(currentreader.Location.location, group.Key), General.Map.Options.LevelName);
|
||||
}
|
||||
|
@ -1721,7 +1764,8 @@ namespace CodeImp.DoomBuilder.Data
|
|||
mapInfo = parser.MapInfo ?? new MapInfo();
|
||||
}
|
||||
|
||||
private void loadGldefsFromLocation(GldefsParser parser, string location) {
|
||||
private void LoadGldefsFromLocation(GldefsParser parser, string location)
|
||||
{
|
||||
Dictionary<string, Stream> streams = currentreader.GetGldefsData(location);
|
||||
|
||||
foreach (KeyValuePair<string, Stream> group in streams)
|
||||
|
@ -1729,11 +1773,10 @@ namespace CodeImp.DoomBuilder.Data
|
|||
}
|
||||
|
||||
//mxd
|
||||
internal MemoryStream LoadFile(string name) {
|
||||
foreach (DataReader dr in containers) {
|
||||
if (dr.FileExists(name))
|
||||
return dr.LoadFile(name);
|
||||
}
|
||||
internal MemoryStream LoadFile(string name)
|
||||
{
|
||||
foreach (DataReader dr in containers)
|
||||
if (dr.FileExists(name)) return dr.LoadFile(name);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -156,17 +156,20 @@ namespace CodeImp.DoomBuilder.Data
|
|||
if(reader is UnknownImageReader)
|
||||
{
|
||||
//mxd. Probably that's a flat?..
|
||||
if (General.Map.Config.MixTexturesFlats) {
|
||||
if (General.Map.Config.MixTexturesFlats)
|
||||
{
|
||||
reader = ImageDataFormat.GetImageReader(mem, ImageDataFormat.DOOMFLAT, General.Map.Data.Palette);
|
||||
}
|
||||
if (reader is UnknownImageReader) {
|
||||
if (reader is UnknownImageReader)
|
||||
{
|
||||
// Data is in an unknown format!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Patch lump '" + p.lumpname + "' data format could not be read, while loading texture '" + this.Name + "'");
|
||||
failCount++; //mxd
|
||||
}
|
||||
}
|
||||
|
||||
if(!(reader is UnknownImageReader)) {
|
||||
if(!(reader is UnknownImageReader))
|
||||
{
|
||||
// Get the patch
|
||||
mem.Seek(0, SeekOrigin.Begin);
|
||||
Bitmap patchbmp = null;
|
||||
|
@ -180,7 +183,8 @@ namespace CodeImp.DoomBuilder.Data
|
|||
if(patchbmp != null)
|
||||
{
|
||||
//mxd. Flip
|
||||
if(p.flipx || p.flipy) {
|
||||
if(p.flipx || p.flipy)
|
||||
{
|
||||
RotateFlipType flip;
|
||||
if(p.flipx && !p.flipy)
|
||||
flip = RotateFlipType.RotateNoneFlipX;
|
||||
|
@ -192,7 +196,8 @@ namespace CodeImp.DoomBuilder.Data
|
|||
}
|
||||
|
||||
//mxd. Then rotate. I do it this way because RotateFlip function rotates THEN flips, and GZDoom does it the other way around.
|
||||
if(p.rotate != 0) {
|
||||
if(p.rotate != 0)
|
||||
{
|
||||
RotateFlipType rotate;
|
||||
if(p.rotate == 90)
|
||||
rotate = RotateFlipType.Rotate90FlipNone;
|
||||
|
@ -224,36 +229,45 @@ namespace CodeImp.DoomBuilder.Data
|
|||
int patchalpha = (int)Math.Round(General.Clamp(p.alpha, 0f, 1f) * 255); //convert alpha to [0-255] range
|
||||
|
||||
//mxd. Blend/Tint support
|
||||
if(p.blendstyle == TexturePathBlendStyle.Blend) {
|
||||
for(PixelColor* cp = pixels + numpixels - 1; cp >= pixels; cp--) {
|
||||
if(p.blendstyle == TexturePathBlendStyle.Blend)
|
||||
{
|
||||
for(PixelColor* cp = pixels + numpixels - 1; cp >= pixels; cp--)
|
||||
{
|
||||
cp->r = (byte)((cp->r * p.blend.r) * PixelColor.BYTE_TO_FLOAT);
|
||||
cp->g = (byte)((cp->g * p.blend.g) * PixelColor.BYTE_TO_FLOAT);
|
||||
cp->b = (byte)((cp->b * p.blend.b) * PixelColor.BYTE_TO_FLOAT);
|
||||
}
|
||||
} else if(p.blendstyle == TexturePathBlendStyle.Tint) {
|
||||
}
|
||||
else if(p.blendstyle == TexturePathBlendStyle.Tint)
|
||||
{
|
||||
float tintammount = p.tintammount - 0.1f;
|
||||
|
||||
if(tintammount > 0) {
|
||||
if(tintammount > 0)
|
||||
{
|
||||
float br = p.blend.r * PixelColor.BYTE_TO_FLOAT * tintammount;
|
||||
float bg = p.blend.g * PixelColor.BYTE_TO_FLOAT * tintammount;
|
||||
float bb = p.blend.b * PixelColor.BYTE_TO_FLOAT * tintammount;
|
||||
float invTint = 1.0f - tintammount;
|
||||
|
||||
for(PixelColor* cp = pixels + numpixels - 1; cp >= pixels; cp--) {
|
||||
for(PixelColor* cp = pixels + numpixels - 1; cp >= pixels; cp--)
|
||||
{
|
||||
cp->r = (byte)(((cp->r * PixelColor.BYTE_TO_FLOAT) * invTint + br) * 255.0f);
|
||||
cp->g = (byte)(((cp->g * PixelColor.BYTE_TO_FLOAT) * invTint + bg) * 255.0f);
|
||||
cp->b = (byte)(((cp->b * PixelColor.BYTE_TO_FLOAT) * invTint + bb) * 255.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//mxd. apply RenderStyle
|
||||
if(p.style == TexturePathRenderStyle.Blend) {
|
||||
if(p.style == TexturePathRenderStyle.Blend)
|
||||
{
|
||||
for(PixelColor* cp = pixels + numpixels - 1; cp >= pixels; cp--)
|
||||
cp->a = (byte)((cp->a * patchalpha) * PixelColor.BYTE_TO_FLOAT);
|
||||
|
||||
|
||||
}
|
||||
//mxd. we need a copy of underlying part of texture for these styles
|
||||
} else if(p.style != TexturePathRenderStyle.Copy) {
|
||||
else if(p.style != TexturePathRenderStyle.Copy)
|
||||
{
|
||||
//copy portion of texture
|
||||
int lockWidth = (p.x + patchbmp.Size.Width > bitmap.Width) ? bitmap.Width - p.x : patchbmp.Size.Width;
|
||||
int lockHeight = (p.y + patchbmp.Size.Height > bitmap.Height) ? bitmap.Height - p.y : patchbmp.Size.Height;
|
||||
|
@ -265,19 +279,25 @@ namespace CodeImp.DoomBuilder.Data
|
|||
//lock texture
|
||||
BitmapData texturebmpdata = null;
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
texturebmpdata = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
|
||||
} catch(Exception e) {
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Cannot lock texture '" + this.Name + "' to apply render style. " + e.GetType().Name + ": " + e.Message);
|
||||
}
|
||||
|
||||
if(texturebmpdata != null) {
|
||||
if(texturebmpdata != null)
|
||||
{
|
||||
PixelColor* texturepixels = (PixelColor*)(texturebmpdata.Scan0.ToPointer());
|
||||
PixelColor* tcp = texturepixels + numpixels - 1;
|
||||
|
||||
switch(p.style) {
|
||||
switch(p.style)
|
||||
{
|
||||
case TexturePathRenderStyle.Add:
|
||||
for(PixelColor* cp = pixels + numpixels - 1; cp >= pixels; cp--) {
|
||||
for(PixelColor* cp = pixels + numpixels - 1; cp >= pixels; cp--)
|
||||
{
|
||||
cp->r = (byte)Math.Min(255, cp->r + tcp->r);
|
||||
cp->g = (byte)Math.Min(255, cp->g + tcp->g);
|
||||
cp->b = (byte)Math.Min(255, cp->b + tcp->b);
|
||||
|
@ -287,7 +307,8 @@ namespace CodeImp.DoomBuilder.Data
|
|||
break;
|
||||
|
||||
case TexturePathRenderStyle.Subtract:
|
||||
for(PixelColor* cp = pixels + numpixels - 1; cp >= pixels; cp--) {
|
||||
for(PixelColor* cp = pixels + numpixels - 1; cp >= pixels; cp--)
|
||||
{
|
||||
cp->r = (byte)Math.Max(0, tcp->r - cp->r);
|
||||
cp->g = (byte)Math.Max(0, tcp->g - cp->g);
|
||||
cp->b = (byte)Math.Max(0, tcp->b - cp->b);
|
||||
|
@ -297,7 +318,8 @@ namespace CodeImp.DoomBuilder.Data
|
|||
break;
|
||||
|
||||
case TexturePathRenderStyle.ReverseSubtract:
|
||||
for(PixelColor* cp = pixels + numpixels - 1; cp >= pixels; cp--) {
|
||||
for(PixelColor* cp = pixels + numpixels - 1; cp >= pixels; cp--)
|
||||
{
|
||||
cp->r = (byte)Math.Max(0, cp->r - tcp->r);
|
||||
cp->g = (byte)Math.Max(0, cp->g - tcp->g);
|
||||
cp->b = (byte)Math.Max(0, cp->b - tcp->b);
|
||||
|
@ -307,7 +329,8 @@ namespace CodeImp.DoomBuilder.Data
|
|||
break;
|
||||
|
||||
case TexturePathRenderStyle.Modulate:
|
||||
for(PixelColor* cp = pixels + numpixels - 1; cp >= pixels; cp--) {
|
||||
for(PixelColor* cp = pixels + numpixels - 1; cp >= pixels; cp--)
|
||||
{
|
||||
cp->r = (byte)((cp->r * tcp->r) * PixelColor.BYTE_TO_FLOAT);
|
||||
cp->g = (byte)((cp->g * tcp->g) * PixelColor.BYTE_TO_FLOAT);
|
||||
cp->b = (byte)((cp->b * tcp->b) * PixelColor.BYTE_TO_FLOAT);
|
||||
|
|
|
@ -470,11 +470,12 @@ namespace CodeImp.DoomBuilder.Data
|
|||
// Error when suspended
|
||||
if (issuspended) throw new Exception("Data reader is suspended");
|
||||
|
||||
//modedef should be in root folder
|
||||
// Modedef should be in root folder
|
||||
string[] files = GetAllFiles("", false);
|
||||
Dictionary<string, Stream> streams = new Dictionary<string, Stream>(StringComparer.Ordinal);
|
||||
|
||||
foreach (string s in files) {
|
||||
foreach (string s in files)
|
||||
{
|
||||
if (s.ToLowerInvariant().IndexOf("modeldef") != -1)
|
||||
streams.Add(s, LoadFile(s));
|
||||
}
|
||||
|
|
|
@ -90,7 +90,8 @@ namespace CodeImp.DoomBuilder.Data
|
|||
}
|
||||
|
||||
//mxd
|
||||
public override Image GetPreview() {
|
||||
public override Image GetPreview()
|
||||
{
|
||||
return base.GetBitmap();
|
||||
}
|
||||
|
||||
|
|
|
@ -121,10 +121,12 @@ namespace CodeImp.DoomBuilder.Data
|
|||
if(reader is UnknownImageReader)
|
||||
{
|
||||
//mxd. Probably that's a flat?..
|
||||
if (General.Map.Config.MixTexturesFlats) {
|
||||
if (General.Map.Config.MixTexturesFlats)
|
||||
{
|
||||
reader = ImageDataFormat.GetImageReader(mem, ImageDataFormat.DOOMFLAT, General.Map.Data.Palette);
|
||||
}
|
||||
if (reader is UnknownImageReader) {
|
||||
if (reader is UnknownImageReader)
|
||||
{
|
||||
// Data is in an unknown format!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Patch lump '" + p.lumpname + "' data format could not be read, while loading texture '" + this.Name + "'. Does this lump contain valid picture data at all?");
|
||||
loadfailed = true;
|
||||
|
@ -132,7 +134,8 @@ namespace CodeImp.DoomBuilder.Data
|
|||
}
|
||||
}
|
||||
|
||||
if(!(reader is UnknownImageReader)) {
|
||||
if(!(reader is UnknownImageReader))
|
||||
{
|
||||
// Draw the patch
|
||||
mem.Seek(0, SeekOrigin.Begin);
|
||||
try { reader.DrawToPixelData(mem, pixels, width, height, p.x, p.y); }
|
||||
|
|
|
@ -78,7 +78,8 @@ namespace CodeImp.DoomBuilder.Data
|
|||
}
|
||||
|
||||
//mxd. Constructor for hires patches
|
||||
public TexturePatch(PatchStructure patch) {
|
||||
public TexturePatch(PatchStructure patch)
|
||||
{
|
||||
// Initialize
|
||||
this.lumpname = patch.Name.ToUpperInvariant();
|
||||
this.x = patch.OffsetX;
|
||||
|
@ -96,13 +97,15 @@ namespace CodeImp.DoomBuilder.Data
|
|||
//mxd. Check data so we don't perform unneeded operations later on
|
||||
if(this.alpha == 1.0f)
|
||||
{
|
||||
if(this.style == TexturePathRenderStyle.Blend || this.style == TexturePathRenderStyle.CopyAlpha || this.style == TexturePathRenderStyle.CopyNewAlpha || this.style == TexturePathRenderStyle.Overlay)
|
||||
if(this.style == TexturePathRenderStyle.Blend
|
||||
|| this.style == TexturePathRenderStyle.CopyAlpha
|
||||
|| this.style == TexturePathRenderStyle.CopyNewAlpha
|
||||
|| this.style == TexturePathRenderStyle.Overlay)
|
||||
this.style = TexturePathRenderStyle.Copy;
|
||||
}
|
||||
|
||||
//mxd. and get rid of render styles we don't support
|
||||
if(this.style == TexturePathRenderStyle.Overlay)
|
||||
this.style = TexturePathRenderStyle.Copy;
|
||||
if(this.style == TexturePathRenderStyle.Overlay) this.style = TexturePathRenderStyle.Copy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -101,25 +101,31 @@ namespace CodeImp.DoomBuilder.Data
|
|||
//mxd
|
||||
invertedflatranges = new List<LumpRange>();
|
||||
|
||||
if(flatranges.Count > 0) {
|
||||
if(flatranges.Count > 0)
|
||||
{
|
||||
//add range before the first flatrange
|
||||
if (flatranges[0].start > 0) {
|
||||
if (flatranges[0].start > 0)
|
||||
{
|
||||
LumpRange range = new LumpRange {start = 0, end = flatranges[0].start - 1};
|
||||
invertedflatranges.Add(range);
|
||||
}
|
||||
|
||||
//add ranges between flatranges
|
||||
for(int i = 1; i < flatranges.Count; i++) {
|
||||
for(int i = 1; i < flatranges.Count; i++)
|
||||
{
|
||||
LumpRange range = new LumpRange { start = flatranges[i - 1].end + 1, end = flatranges[i].start - 1 };
|
||||
invertedflatranges.Add(range);
|
||||
}
|
||||
|
||||
//add range after the last flatrange
|
||||
if(flatranges[flatranges.Count - 1].end < file.Lumps.Count - 1) {
|
||||
if(flatranges[flatranges.Count - 1].end < file.Lumps.Count - 1)
|
||||
{
|
||||
LumpRange range = new LumpRange { start = flatranges[flatranges.Count - 1].end + 1, end = file.Lumps.Count - 1 };
|
||||
invertedflatranges.Add(range);
|
||||
}
|
||||
} else { // No flat ranges? Make one giant range then...
|
||||
}
|
||||
else // No flat ranges? Make one giant range then...
|
||||
{
|
||||
LumpRange range = new LumpRange {start = 0, end = file.Lumps.Count - 1};
|
||||
invertedflatranges.Add(range);
|
||||
}
|
||||
|
@ -356,15 +362,19 @@ namespace CodeImp.DoomBuilder.Data
|
|||
foreach(LumpRange range in textureranges)
|
||||
{
|
||||
// Go for all lumps between start and end exclusive
|
||||
for(int i = range.start + 1; i < range.end; i++) {
|
||||
for(int i = range.start + 1; i < range.end; i++)
|
||||
{
|
||||
// Lump not zero length?
|
||||
if(file.Lumps[i].Length > 0) {
|
||||
if(file.Lumps[i].Length > 0)
|
||||
{
|
||||
// Make the image
|
||||
SimpleTextureImage image = new SimpleTextureImage(file.Lumps[i].Name, file.Lumps[i].Name, defaultscale, defaultscale);
|
||||
|
||||
// Add image to collection
|
||||
images.Add(image);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// Can't load image without size
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Can't load texture '" + file.Lumps[i].Name + "' because it doesn't contain any data.");
|
||||
}
|
||||
|
@ -773,17 +783,20 @@ namespace CodeImp.DoomBuilder.Data
|
|||
#region ================== Voxels (mxd)
|
||||
|
||||
//mxd. This returns the list of voxels, which can be used without VOXELDEF definition
|
||||
public override string[] GetVoxelNames() {
|
||||
public override string[] GetVoxelNames()
|
||||
{
|
||||
// Error when suspended
|
||||
if(issuspended) throw new Exception("Data reader is suspended");
|
||||
|
||||
List<string> voxels = new List<string>();
|
||||
Regex spriteName = new Regex(SPRITE_NAME_PATTERN);
|
||||
|
||||
foreach(LumpRange range in voxelranges) {
|
||||
foreach(LumpRange range in voxelranges)
|
||||
{
|
||||
if(range.start == range.end) continue;
|
||||
|
||||
for(int i = range.start + 1; i < range.end; i++) {
|
||||
for(int i = range.start + 1; i < range.end; i++)
|
||||
{
|
||||
if(spriteName.IsMatch(file.Lumps[i].Name)) voxels.Add(file.Lumps[i].Name);
|
||||
}
|
||||
}
|
||||
|
@ -792,20 +805,23 @@ namespace CodeImp.DoomBuilder.Data
|
|||
}
|
||||
|
||||
//mxd
|
||||
public override KeyValuePair<string, Stream> GetVoxeldefData() {
|
||||
public override KeyValuePair<string, Stream> GetVoxeldefData()
|
||||
{
|
||||
Lump lump = file.FindLump("VOXELDEF");
|
||||
if(lump != null) return new KeyValuePair<string, Stream>("VOXELDEF", lump.Stream);
|
||||
return new KeyValuePair<string, Stream>();
|
||||
}
|
||||
|
||||
//mxd. This finds and returns a voxel stream or null if no voxel was found
|
||||
public override Stream GetVoxelData(string name) {
|
||||
public override Stream GetVoxelData(string name)
|
||||
{
|
||||
// Error when suspended
|
||||
if(issuspended) throw new Exception("Data reader is suspended");
|
||||
|
||||
Lump lump;
|
||||
|
||||
foreach(LumpRange range in voxelranges) {
|
||||
foreach(LumpRange range in voxelranges)
|
||||
{
|
||||
if(range.start == range.end) continue;
|
||||
lump = file.FindLump(name, range.start, range.end);
|
||||
if(lump != null) return lump.Stream;
|
||||
|
@ -841,7 +857,8 @@ namespace CodeImp.DoomBuilder.Data
|
|||
}
|
||||
|
||||
//mxd
|
||||
public override Dictionary<string, Stream> GetMapinfoData() {
|
||||
public override Dictionary<string, Stream> GetMapinfoData()
|
||||
{
|
||||
if (issuspended) throw new Exception("Data reader is suspended");
|
||||
|
||||
Dictionary<string, Stream> streams = new Dictionary<string, Stream>(StringComparer.Ordinal);
|
||||
|
@ -852,26 +869,27 @@ namespace CodeImp.DoomBuilder.Data
|
|||
int lumpindex = file.FindLumpIndex(src);
|
||||
|
||||
//then for MAPINFO
|
||||
if (lumpindex == -1) {
|
||||
if (lumpindex == -1)
|
||||
{
|
||||
src = "MAPINFO";
|
||||
lumpindex = file.FindLumpIndex(src);
|
||||
}
|
||||
|
||||
if(lumpindex != -1)
|
||||
streams.Add(src, file.Lumps[lumpindex].Stream);
|
||||
|
||||
if(lumpindex != -1) streams.Add(src, file.Lumps[lumpindex].Stream);
|
||||
return streams;
|
||||
}
|
||||
|
||||
//mxd
|
||||
public override Dictionary<string, Stream> GetGldefsData(GameType gameType) {
|
||||
public override Dictionary<string, Stream> GetGldefsData(GameType gameType)
|
||||
{
|
||||
if (issuspended) throw new Exception("Data reader is suspended");
|
||||
|
||||
Dictionary<string, Stream> streams = new Dictionary<string, Stream>(StringComparer.Ordinal);
|
||||
int lumpindex;
|
||||
|
||||
//try to load game specific GLDEFS first
|
||||
if (gameType != GameType.UNKNOWN) {
|
||||
if (gameType != GameType.UNKNOWN)
|
||||
{
|
||||
string lumpName = Gldefs.GLDEFS_LUMPS_PER_GAME[(int)gameType];
|
||||
lumpindex = file.FindLumpIndex(lumpName);
|
||||
|
||||
|
@ -882,35 +900,35 @@ namespace CodeImp.DoomBuilder.Data
|
|||
//should be only one entry per wad
|
||||
lumpindex = file.FindLumpIndex("GLDEFS");
|
||||
|
||||
if (lumpindex != -1)
|
||||
streams.Add("GLDEFS", file.Lumps[lumpindex].Stream);
|
||||
|
||||
if (lumpindex != -1) streams.Add("GLDEFS", file.Lumps[lumpindex].Stream);
|
||||
return streams;
|
||||
}
|
||||
|
||||
//mxd
|
||||
public override Dictionary<string, Stream> GetGldefsData(string location) {
|
||||
public override Dictionary<string, Stream> GetGldefsData(string location)
|
||||
{
|
||||
if (issuspended) throw new Exception("Data reader is suspended");
|
||||
|
||||
Dictionary<string, Stream> streams = new Dictionary<string, Stream>(StringComparer.Ordinal);
|
||||
int lumpindex = file.FindLumpIndex(location);
|
||||
|
||||
if (lumpindex != -1)
|
||||
streams.Add(location, file.Lumps[lumpindex].Stream);
|
||||
|
||||
if (lumpindex != -1) streams.Add(location, file.Lumps[lumpindex].Stream);
|
||||
return streams;
|
||||
}
|
||||
|
||||
//mxd
|
||||
public override Dictionary<string, Stream> GetModeldefData() {
|
||||
public override Dictionary<string, Stream> GetModeldefData()
|
||||
{
|
||||
return GetGldefsData("MODELDEF");
|
||||
}
|
||||
|
||||
//mxd
|
||||
internal override MemoryStream LoadFile(string name) {
|
||||
internal override MemoryStream LoadFile(string name)
|
||||
{
|
||||
Lump l = file.FindLump(name);
|
||||
|
||||
if (l != null) {
|
||||
if (l != null)
|
||||
{
|
||||
l.Stream.Seek(0, SeekOrigin.Begin);
|
||||
return new MemoryStream(l.Stream.ReadAllBytes());
|
||||
}
|
||||
|
@ -919,7 +937,8 @@ namespace CodeImp.DoomBuilder.Data
|
|||
}
|
||||
|
||||
//mxd
|
||||
internal override bool FileExists(string name) {
|
||||
internal override bool FileExists(string name)
|
||||
{
|
||||
return file.FindLumpIndex(name) != -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -607,9 +607,12 @@ namespace CodeImp.DoomBuilder.Editing
|
|||
}
|
||||
|
||||
//mxd
|
||||
public override bool OnMapTestBegin(bool testFromCurrentPosition) {
|
||||
if(testFromCurrentPosition) {
|
||||
if(!mouseinside){
|
||||
public override bool OnMapTestBegin(bool testFromCurrentPosition)
|
||||
{
|
||||
if(testFromCurrentPosition)
|
||||
{
|
||||
if(!mouseinside)
|
||||
{
|
||||
General.MainWindow.DisplayStatus(StatusType.Warning, "Can't test from current position: mouse is outside editing vindow!");
|
||||
return false;
|
||||
}
|
||||
|
@ -617,18 +620,25 @@ namespace CodeImp.DoomBuilder.Editing
|
|||
//find Single Player Start. Should be type 1 in all games
|
||||
Thing start = null;
|
||||
|
||||
foreach (Thing t in General.Map.Map.Things) {
|
||||
if (t.Type == 1) {
|
||||
foreach (Thing t in General.Map.Map.Things)
|
||||
{
|
||||
if (t.Type == 1)
|
||||
{
|
||||
//store thing and position
|
||||
if (start == null) {
|
||||
if (start == null)
|
||||
{
|
||||
start = t;
|
||||
}
|
||||
else if(t.Index > start.Index)
|
||||
{
|
||||
//if there are several Player Start 1 things, GZDoom uses one with the biggest index.
|
||||
start = t;
|
||||
} else if(t.Index > start.Index) {
|
||||
start = t; //if there are several Player Start 1 things, GZDoom uses one with the biggest index.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (start == null) {
|
||||
if (start == null)
|
||||
{
|
||||
General.MainWindow.DisplayStatus(StatusType.Warning, "Can't test from current position: no Player 1 start found!");
|
||||
return false;
|
||||
}
|
||||
|
@ -636,13 +646,15 @@ namespace CodeImp.DoomBuilder.Editing
|
|||
//now check if cursor is located inside a sector
|
||||
Sector s = General.Map.Map.GetSectorByCoordinates(mousemappos);
|
||||
|
||||
if(s == null){
|
||||
if(s == null)
|
||||
{
|
||||
General.MainWindow.DisplayStatus(StatusType.Warning, "Can't test from current position: cursor is not inside sector!");
|
||||
return false;
|
||||
}
|
||||
|
||||
//41 = player's height in Doom. Is that so in all other games as well?
|
||||
if (s.CeilHeight - s.FloorHeight < 41) {
|
||||
if (s.CeilHeight - s.FloorHeight < 41)
|
||||
{
|
||||
General.MainWindow.DisplayStatus(StatusType.Warning, "Can't test from current position: sector is too low!");
|
||||
return false;
|
||||
}
|
||||
|
@ -658,8 +670,10 @@ namespace CodeImp.DoomBuilder.Editing
|
|||
return true;
|
||||
}
|
||||
|
||||
public override void OnMapTestEnd(bool testFromCurrentPosition) {
|
||||
if (testFromCurrentPosition) {
|
||||
public override void OnMapTestEnd(bool testFromCurrentPosition)
|
||||
{
|
||||
if (testFromCurrentPosition)
|
||||
{
|
||||
//restore position
|
||||
playerStart.Move(playerStartPosition);
|
||||
playerStart = null;
|
||||
|
@ -759,7 +773,8 @@ namespace CodeImp.DoomBuilder.Editing
|
|||
//mxd
|
||||
PixelColor marqueColor;
|
||||
|
||||
switch(marqueSelectionMode) {
|
||||
switch(marqueSelectionMode)
|
||||
{
|
||||
case MarqueSelectionMode.SELECT:
|
||||
marqueColor = General.Colors.Selection.WithAlpha(SELECTION_ALPHA);
|
||||
break;
|
||||
|
@ -800,7 +815,8 @@ namespace CodeImp.DoomBuilder.Editing
|
|||
/// <summary>
|
||||
/// This selects given map element (mxd)
|
||||
/// </summary>
|
||||
public virtual void SelectMapElement(SelectableElement element) {
|
||||
public virtual void SelectMapElement(SelectableElement element)
|
||||
{
|
||||
element.Selected = true;
|
||||
}
|
||||
|
||||
|
@ -811,7 +827,7 @@ namespace CodeImp.DoomBuilder.Editing
|
|||
[BeginAction("gridsetup", BaseAction = true)]
|
||||
protected void ShowGridSetup()
|
||||
{
|
||||
General.Map.Grid.ShowGridSetup();
|
||||
GridSetup.ShowGridSetup();
|
||||
}
|
||||
|
||||
[BeginAction("pan_view", BaseAction = true)]
|
||||
|
@ -852,10 +868,12 @@ namespace CodeImp.DoomBuilder.Editing
|
|||
|
||||
//mxd
|
||||
[BeginAction("centeroncoordinates", BaseAction = true)]
|
||||
protected virtual void CenterOnCoordinates() {
|
||||
protected virtual void CenterOnCoordinates()
|
||||
{
|
||||
//show form...
|
||||
CenterOnCoordinatesForm form = new CenterOnCoordinatesForm();
|
||||
if (form.ShowDialog() == DialogResult.OK) {
|
||||
if (form.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
//center view
|
||||
renderer2d.PositionView(form.Coordinates.x, form.Coordinates.y);
|
||||
General.Interface.RedrawDisplay();
|
||||
|
|
|
@ -90,7 +90,7 @@ namespace CodeImp.DoomBuilder.Editing
|
|||
#region ================== Methods
|
||||
|
||||
// This makes a prefab of the selection. Returns null when cancelled.
|
||||
internal MemoryStream MakePrefab()
|
||||
private static MemoryStream MakePrefab()
|
||||
{
|
||||
// Let the plugins know
|
||||
if(General.Plugins.OnCopyBegin())
|
||||
|
@ -155,7 +155,7 @@ namespace CodeImp.DoomBuilder.Editing
|
|||
}
|
||||
|
||||
// This pastes a prefab. Returns false when paste was cancelled.
|
||||
internal void PastePrefab(Stream filedata, PasteOptions options)
|
||||
private static void PastePrefab(Stream filedata, PasteOptions options)
|
||||
{
|
||||
// Create undo
|
||||
General.MainWindow.DisplayStatus(StatusType.Action, "Inserted prefab.");
|
||||
|
@ -165,10 +165,13 @@ namespace CodeImp.DoomBuilder.Editing
|
|||
MemoryStream memstream; //mxd
|
||||
filedata.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
memstream = SharpCompressHelper.DecompressStream(filedata); //mxd
|
||||
memstream.Seek(0, SeekOrigin.Begin);
|
||||
}catch(Exception e){
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, e.GetType().Name + " while reading prefab from file: " + e.Message);
|
||||
General.WriteLogLine(e.StackTrace);
|
||||
General.ShowErrorMessage("Unable to load prefab. See log file for error details.", MessageBoxButtons.OK);
|
||||
|
@ -205,7 +208,7 @@ namespace CodeImp.DoomBuilder.Editing
|
|||
}
|
||||
|
||||
// This performs the copy. Returns false when copy was cancelled.
|
||||
private bool DoCopySelection(string desc)
|
||||
private static bool DoCopySelection(string desc)
|
||||
{
|
||||
// Check if possible to copy/paste
|
||||
if(General.Editing.Mode.Attributes.AllowCopyPaste)
|
||||
|
@ -254,7 +257,7 @@ namespace CodeImp.DoomBuilder.Editing
|
|||
}
|
||||
|
||||
// This performs the paste. Returns false when paste was cancelled.
|
||||
private bool DoPasteSelection(PasteOptions options)
|
||||
private static void DoPasteSelection(PasteOptions options)
|
||||
{
|
||||
// Check if possible to copy/paste
|
||||
if(General.Editing.Mode.Attributes.AllowCopyPaste)
|
||||
|
@ -320,25 +323,20 @@ namespace CodeImp.DoomBuilder.Editing
|
|||
General.Editing.Mode.OnPasteEnd(options.Copy());
|
||||
General.Plugins.OnPasteEnd(options);
|
||||
}
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Aborted
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Nothing usefull on the clipboard
|
||||
General.MessageBeep(MessageBeepType.Warning);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Paste not allowed
|
||||
General.MessageBeep(MessageBeepType.Warning);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -269,7 +269,7 @@ namespace CodeImp.DoomBuilder.Editing
|
|||
#region ================== Actions
|
||||
|
||||
// This shows the grid setup dialog
|
||||
internal void ShowGridSetup()
|
||||
internal static void ShowGridSetup()
|
||||
{
|
||||
// Show preferences dialog
|
||||
GridSetupForm gridform = new GridSetupForm();
|
||||
|
|
|
@ -217,25 +217,30 @@ namespace CodeImp.DoomBuilder.Editing
|
|||
if(!General.Map.FormatInterface.HasCustomFields) customfields.Clear();
|
||||
|
||||
//mxd. We don't want to keep unknown flags (like flags from different map format)
|
||||
if(General.Map.Config != null && General.Map.Config.ThingFlags != null) {
|
||||
if(General.Map.Config != null && General.Map.Config.ThingFlags != null)
|
||||
{
|
||||
List<String> unknownfields = new List<string>();
|
||||
foreach(String s in forbiddenfields) {
|
||||
foreach(String s in forbiddenfields)
|
||||
{
|
||||
if(!General.Map.Config.ThingFlags.ContainsKey(s))
|
||||
unknownfields.Add(s);
|
||||
}
|
||||
|
||||
if(unknownfields.Count > 0) {
|
||||
if(unknownfields.Count > 0)
|
||||
{
|
||||
foreach(String s in unknownfields)
|
||||
forbiddenfields.Remove(s);
|
||||
}
|
||||
|
||||
unknownfields = new List<string>();
|
||||
foreach(String s in requiredfields) {
|
||||
foreach(String s in requiredfields)
|
||||
{
|
||||
if(!General.Map.Config.ThingFlags.ContainsKey(s))
|
||||
unknownfields.Add(s);
|
||||
}
|
||||
|
||||
if(unknownfields.Count > 0) {
|
||||
if(unknownfields.Count > 0)
|
||||
{
|
||||
foreach(String s in unknownfields)
|
||||
requiredfields.Remove(s);
|
||||
}
|
||||
|
@ -244,13 +249,15 @@ namespace CodeImp.DoomBuilder.Editing
|
|||
}
|
||||
|
||||
//mxd
|
||||
public void Validate() {
|
||||
public void Validate()
|
||||
{
|
||||
AdjustForMapFormat();
|
||||
|
||||
//Integrity check
|
||||
if(string.IsNullOrEmpty(categoryname) && thingtype == -1 && thingangle == -1
|
||||
&& thingzheight == int.MinValue && thingaction == -1 && thingtag == -1
|
||||
&& requiredfields.Count == 0 && forbiddenfields.Count == 0 && customfields.Count == 0) {
|
||||
&& requiredfields.Count == 0 && forbiddenfields.Count == 0 && customfields.Count == 0)
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Warning, "Things filter '" + name + "' has invalid properties. Configure the thing filter to fix this!");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -876,7 +876,7 @@ namespace CodeImp.DoomBuilder.Editing
|
|||
propsrecorded = null;
|
||||
}
|
||||
|
||||
internal void PlayAddVertex(DeserializerStream ds)
|
||||
private void PlayAddVertex(DeserializerStream ds)
|
||||
{
|
||||
int index; ds.rInt(out index);
|
||||
//LogRecordInfo("PLY: Removing vertex " + index);
|
||||
|
@ -898,7 +898,7 @@ namespace CodeImp.DoomBuilder.Editing
|
|||
propsrecorded = null;
|
||||
}
|
||||
|
||||
internal void PlayRemVertex(DeserializerStream ds)
|
||||
private void PlayRemVertex(DeserializerStream ds)
|
||||
{
|
||||
int index; ds.rInt(out index);
|
||||
Vector2D pos; ds.rVector2D(out pos);
|
||||
|
@ -921,7 +921,7 @@ namespace CodeImp.DoomBuilder.Editing
|
|||
}
|
||||
}
|
||||
|
||||
internal void PlayPrpVertex(DeserializerStream ds)
|
||||
private void PlayPrpVertex(DeserializerStream ds)
|
||||
{
|
||||
int index; ds.rInt(out index);
|
||||
Vertex v = General.Map.Map.GetVertexByIndex(index);
|
||||
|
@ -940,7 +940,7 @@ namespace CodeImp.DoomBuilder.Editing
|
|||
propsrecorded = null;
|
||||
}
|
||||
|
||||
internal void PlayAddLinedef(DeserializerStream ds)
|
||||
private void PlayAddLinedef(DeserializerStream ds)
|
||||
{
|
||||
int index; ds.rInt(out index);
|
||||
//LogRecordInfo("PLY: Removing linedef " + index);
|
||||
|
@ -964,7 +964,7 @@ namespace CodeImp.DoomBuilder.Editing
|
|||
propsrecorded = null;
|
||||
}
|
||||
|
||||
internal void PlayRemLinedef(DeserializerStream ds)
|
||||
private void PlayRemLinedef(DeserializerStream ds)
|
||||
{
|
||||
int index; ds.rInt(out index);
|
||||
int sindex; ds.rInt(out sindex);
|
||||
|
@ -990,7 +990,7 @@ namespace CodeImp.DoomBuilder.Editing
|
|||
}
|
||||
}
|
||||
|
||||
internal void PlayPrpLinedef(DeserializerStream ds)
|
||||
private static void PlayPrpLinedef(DeserializerStream ds)
|
||||
{
|
||||
int index; ds.rInt(out index);
|
||||
Linedef l = General.Map.Map.GetLinedefByIndex(index);
|
||||
|
@ -1009,7 +1009,7 @@ namespace CodeImp.DoomBuilder.Editing
|
|||
propsrecorded = null;
|
||||
}
|
||||
|
||||
internal void PlayRefLinedefStart(DeserializerStream ds)
|
||||
private void PlayRefLinedefStart(DeserializerStream ds)
|
||||
{
|
||||
int index; ds.rInt(out index);
|
||||
Linedef l = General.Map.Map.GetLinedefByIndex(index);
|
||||
|
@ -1033,7 +1033,7 @@ namespace CodeImp.DoomBuilder.Editing
|
|||
propsrecorded = null;
|
||||
}
|
||||
|
||||
internal void PlayRefLinedefEnd(DeserializerStream ds)
|
||||
private void PlayRefLinedefEnd(DeserializerStream ds)
|
||||
{
|
||||
int index; ds.rInt(out index);
|
||||
Linedef l = General.Map.Map.GetLinedefByIndex(index);
|
||||
|
@ -1057,7 +1057,7 @@ namespace CodeImp.DoomBuilder.Editing
|
|||
propsrecorded = null;
|
||||
}
|
||||
|
||||
internal void PlayRefLinedefFront(DeserializerStream ds)
|
||||
private void PlayRefLinedefFront(DeserializerStream ds)
|
||||
{
|
||||
int index; ds.rInt(out index);
|
||||
Linedef l = General.Map.Map.GetLinedefByIndex(index);
|
||||
|
@ -1081,7 +1081,7 @@ namespace CodeImp.DoomBuilder.Editing
|
|||
propsrecorded = null;
|
||||
}
|
||||
|
||||
internal void PlayRefLinedefBack(DeserializerStream ds)
|
||||
private void PlayRefLinedefBack(DeserializerStream ds)
|
||||
{
|
||||
int index; ds.rInt(out index);
|
||||
Linedef l = General.Map.Map.GetLinedefByIndex(index);
|
||||
|
@ -1104,7 +1104,7 @@ namespace CodeImp.DoomBuilder.Editing
|
|||
propsrecorded = null;
|
||||
}
|
||||
|
||||
internal void PlayAddSidedef(DeserializerStream ds)
|
||||
private void PlayAddSidedef(DeserializerStream ds)
|
||||
{
|
||||
int index; ds.rInt(out index);
|
||||
//LogRecordInfo("PLY: Removing sidedef " + index);
|
||||
|
@ -1128,7 +1128,7 @@ namespace CodeImp.DoomBuilder.Editing
|
|||
propsrecorded = null;
|
||||
}
|
||||
|
||||
internal void PlayRemSidedef(DeserializerStream ds)
|
||||
private void PlayRemSidedef(DeserializerStream ds)
|
||||
{
|
||||
int index; ds.rInt(out index);
|
||||
int dindex; ds.rInt(out dindex);
|
||||
|
@ -1155,7 +1155,7 @@ namespace CodeImp.DoomBuilder.Editing
|
|||
}
|
||||
}
|
||||
|
||||
internal void PlayPrpSidedef(DeserializerStream ds)
|
||||
private static void PlayPrpSidedef(DeserializerStream ds)
|
||||
{
|
||||
int index; ds.rInt(out index);
|
||||
Sidedef s = General.Map.Map.GetSidedefByIndex(index);
|
||||
|
@ -1174,7 +1174,7 @@ namespace CodeImp.DoomBuilder.Editing
|
|||
propsrecorded = null;
|
||||
}
|
||||
|
||||
internal void PlayRefSidedefSector(DeserializerStream ds)
|
||||
private void PlayRefSidedefSector(DeserializerStream ds)
|
||||
{
|
||||
int index; ds.rInt(out index);
|
||||
Sidedef sd = General.Map.Map.GetSidedefByIndex(index);
|
||||
|
@ -1197,7 +1197,7 @@ namespace CodeImp.DoomBuilder.Editing
|
|||
propsrecorded = null;
|
||||
}
|
||||
|
||||
internal void PlayAddSector(DeserializerStream ds)
|
||||
private void PlayAddSector(DeserializerStream ds)
|
||||
{
|
||||
int index; ds.rInt(out index);
|
||||
//LogRecordInfo("PLY: Removing sector " + index);
|
||||
|
@ -1217,7 +1217,7 @@ namespace CodeImp.DoomBuilder.Editing
|
|||
propsrecorded = null;
|
||||
}
|
||||
|
||||
internal void PlayRemSector(DeserializerStream ds)
|
||||
private void PlayRemSector(DeserializerStream ds)
|
||||
{
|
||||
int index; ds.rInt(out index);
|
||||
//LogRecordInfo("PLY: Adding sector " + index);
|
||||
|
@ -1239,7 +1239,7 @@ namespace CodeImp.DoomBuilder.Editing
|
|||
}
|
||||
}
|
||||
|
||||
internal void PlayPrpSector(DeserializerStream ds)
|
||||
private static void PlayPrpSector(DeserializerStream ds)
|
||||
{
|
||||
int index; ds.rInt(out index);
|
||||
Sector s = General.Map.Map.GetSectorByIndex(index);
|
||||
|
@ -1257,7 +1257,7 @@ namespace CodeImp.DoomBuilder.Editing
|
|||
propsrecorded = null;
|
||||
}
|
||||
|
||||
internal void PlayAddThing(DeserializerStream ds)
|
||||
private void PlayAddThing(DeserializerStream ds)
|
||||
{
|
||||
int index; ds.rInt(out index);
|
||||
//LogRecordInfo("PLY: Removing thing " + index);
|
||||
|
@ -1277,7 +1277,7 @@ namespace CodeImp.DoomBuilder.Editing
|
|||
propsrecorded = null;
|
||||
}
|
||||
|
||||
internal void PlayRemThing(DeserializerStream ds)
|
||||
private void PlayRemThing(DeserializerStream ds)
|
||||
{
|
||||
int index; ds.rInt(out index);
|
||||
//LogRecordInfo("PLY: Adding thing " + index);
|
||||
|
@ -1299,7 +1299,7 @@ namespace CodeImp.DoomBuilder.Editing
|
|||
}
|
||||
}
|
||||
|
||||
internal void PlayPrpThing(DeserializerStream ds)
|
||||
private static void PlayPrpThing(DeserializerStream ds)
|
||||
{
|
||||
int index; ds.rInt(out index);
|
||||
Thing t = General.Map.Map.GetThingByIndex(index);
|
||||
|
|
|
@ -11,8 +11,10 @@
|
|||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing) {
|
||||
if(disposing && (components != null)) {
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if(disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
|
@ -24,7 +26,8 @@
|
|||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent() {
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.components = new System.ComponentModel.Container();
|
||||
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
|
||||
this.SuspendLayout();
|
||||
|
|
|
@ -57,7 +57,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
|||
|
||||
#region Methods
|
||||
|
||||
private void setDrawRegion()
|
||||
private void SetDrawRegion()
|
||||
{
|
||||
drawRegion = new Rectangle(0, 0, this.Width, this.Height);
|
||||
drawRegion.X += 2;
|
||||
|
@ -94,13 +94,13 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
|||
|
||||
private void AngleSelector_Load(object sender, EventArgs e)
|
||||
{
|
||||
setDrawRegion();
|
||||
SetDrawRegion();
|
||||
}
|
||||
|
||||
private void AngleSelector_SizeChanged(object sender, EventArgs e)
|
||||
{
|
||||
this.Height = this.Width; // Keep it there and keep it square!
|
||||
setDrawRegion();
|
||||
SetDrawRegion();
|
||||
}
|
||||
|
||||
protected override void OnPaint(PaintEventArgs e)
|
||||
|
|
|
@ -11,8 +11,10 @@
|
|||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing) {
|
||||
if(disposing && (components != null)) {
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if(disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
|
@ -24,7 +26,8 @@
|
|||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent() {
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.bReset = new System.Windows.Forms.Button();
|
||||
this.cpColor = new CodeImp.DoomBuilder.Controls.ColorControl();
|
||||
this.tbColor = new CodeImp.DoomBuilder.Controls.AutoSelectTextbox();
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
using System;
|
||||
#region ================== Namespaces
|
||||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
using System.Globalization;
|
||||
|
@ -6,6 +8,8 @@ using CodeImp.DoomBuilder.Rendering;
|
|||
using CodeImp.DoomBuilder.Map;
|
||||
using CodeImp.DoomBuilder.GZBuilder.Tools;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
||||
{
|
||||
public partial class ColorFieldsControl : UserControl
|
||||
|
@ -32,25 +36,32 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
|||
|
||||
#endregion
|
||||
|
||||
public ColorFieldsControl() {
|
||||
public ColorFieldsControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public void SetValueFrom(UniFields fields) {
|
||||
public void SetValueFrom(UniFields fields)
|
||||
{
|
||||
string newValue = String.Format("{0:X6}", UDMFTools.GetInteger(fields, field, defaultValue));
|
||||
tbColor.Text = ((!string.IsNullOrEmpty(tbColor.Text) && tbColor.Text != newValue) ? "" : newValue);
|
||||
checkColor();
|
||||
CheckColor();
|
||||
}
|
||||
|
||||
public void ApplyTo(UniFields fields, int oldValue) {
|
||||
if(string.IsNullOrEmpty(tbColor.Text)) {
|
||||
public void ApplyTo(UniFields fields, int oldValue)
|
||||
{
|
||||
if(string.IsNullOrEmpty(tbColor.Text))
|
||||
{
|
||||
UDMFTools.SetInteger(fields, field, oldValue, defaultValue);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
UDMFTools.SetInteger(fields, field, (cpColor.Color.ToInt() & 0x00ffffff), defaultValue);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkColor() {
|
||||
private void CheckColor()
|
||||
{
|
||||
bool changed = string.IsNullOrEmpty(tbColor.Text) || (cpColor.Color.ToInt() & 0x00ffffff) != defaultValue;
|
||||
bReset.Visible = changed;
|
||||
tbColor.ForeColor = changed ? SystemColors.WindowText : SystemColors.GrayText;
|
||||
|
@ -58,27 +69,31 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
|||
|
||||
#region ================== Events
|
||||
|
||||
private void bReset_Click(object sender, EventArgs e) {
|
||||
private void bReset_Click(object sender, EventArgs e)
|
||||
{
|
||||
cpColor.Color = PixelColor.FromInt(defaultValue).WithAlpha(255);
|
||||
cpColor_ColorChanged(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
private void cpColor_ColorChanged(object sender, EventArgs e) {
|
||||
private void cpColor_ColorChanged(object sender, EventArgs e)
|
||||
{
|
||||
if(blockUpdate) return;
|
||||
|
||||
blockUpdate = true;
|
||||
tbColor.Text = String.Format("{0:X6}", (cpColor.Color.ToInt() & 0x00ffffff));
|
||||
blockUpdate = false;
|
||||
|
||||
checkColor();
|
||||
CheckColor();
|
||||
if(OnValueChanged != null) OnValueChanged(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
private void tbColor_TextChanged(object sender, EventArgs e) {
|
||||
private void tbColor_TextChanged(object sender, EventArgs e)
|
||||
{
|
||||
if(blockUpdate) return;
|
||||
int colorVal;
|
||||
|
||||
if(int.TryParse(tbColor.Text, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out colorVal)){
|
||||
if(int.TryParse(tbColor.Text, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out colorVal))
|
||||
{
|
||||
colorVal = General.Clamp(colorVal, 0, 16777215);
|
||||
|
||||
blockUpdate = true;
|
||||
|
@ -86,7 +101,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
|||
blockUpdate = false;
|
||||
}
|
||||
|
||||
checkColor();
|
||||
CheckColor();
|
||||
if(OnValueChanged != null) OnValueChanged(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
|
|
|
@ -27,17 +27,20 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
|||
public string Flag { get { return flag; } }
|
||||
private string flag;
|
||||
|
||||
public FlagData(string title, string flag) {
|
||||
public FlagData(string title, string flag)
|
||||
{
|
||||
this.title = title;
|
||||
this.flag = flag;
|
||||
}
|
||||
|
||||
public override string ToString() {
|
||||
public override string ToString()
|
||||
{
|
||||
return Title;
|
||||
}
|
||||
}
|
||||
|
||||
public CustomLinedefColorProperties() {
|
||||
public CustomLinedefColorProperties()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
defaultColor = lineColor.Color;
|
||||
|
@ -47,7 +50,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
|||
labelErrors.Text = "";
|
||||
}
|
||||
|
||||
public void Setup(GameConfiguration config) {
|
||||
public void Setup(GameConfiguration config)
|
||||
{
|
||||
udmf = (config.FormatInterface == "UniversalMapSetIO");
|
||||
|
||||
presetUpdating = true;
|
||||
|
@ -75,19 +79,25 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
|||
//get activates
|
||||
List<LinedefActivateInfo> activations = config.LinedefActivates;
|
||||
|
||||
if(activations.Count > 0) {
|
||||
if(activations.Count > 0)
|
||||
{
|
||||
activations.Insert(0, new LinedefActivateInfo("-1", "Any activation"));
|
||||
|
||||
if(udmf) {
|
||||
if(udmf)
|
||||
{
|
||||
foreach(LinedefActivateInfo ai in config.LinedefActivates)
|
||||
udmfactivates.Items.Add(new FlagData(ai.Title, ai.Key), CheckState.Indeterminate);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
activation.Items.AddRange(activations.ToArray());
|
||||
}
|
||||
|
||||
if(!tcLineSettings.TabPages.Contains(tabActivation))
|
||||
tcLineSettings.TabPages.Add(tabActivation);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
tcLineSettings.TabPages.Remove(tabActivation);
|
||||
}
|
||||
|
||||
|
@ -100,7 +110,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
|||
presetUpdating = false;
|
||||
}
|
||||
|
||||
public void SetPreset(LinedefColorPreset preset) {
|
||||
public void SetPreset(LinedefColorPreset preset)
|
||||
{
|
||||
this.Enabled = true;
|
||||
presetUpdating = true;
|
||||
|
||||
|
@ -110,19 +121,27 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
|||
lineColor.Color = this.preset.Color;
|
||||
|
||||
//set flags
|
||||
applyFlagsToControl(flags, cbUseFlags);
|
||||
ApplyFlagsToControl(flags, cbUseFlags);
|
||||
|
||||
//set activation
|
||||
if(udmf) {
|
||||
applyFlagsToControl(udmfactivates, cbUseActivation);
|
||||
} else if(tcLineSettings.TabPages.Contains(tabActivation)) {
|
||||
if(this.preset.Activation == 0) {
|
||||
if(udmf)
|
||||
{
|
||||
ApplyFlagsToControl(udmfactivates, cbUseActivation);
|
||||
}
|
||||
else if(tcLineSettings.TabPages.Contains(tabActivation))
|
||||
{
|
||||
if(this.preset.Activation == 0)
|
||||
{
|
||||
activation.SelectedIndex = 1;
|
||||
cbUseActivation.Checked = false;
|
||||
activation.Enabled = false;
|
||||
} else {
|
||||
for(int i = 0; i < activation.Items.Count; i++) {
|
||||
if(((LinedefActivateInfo)activation.Items[i]).Index == this.preset.Activation) {
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int i = 0; i < activation.Items.Count; i++)
|
||||
{
|
||||
if(((LinedefActivateInfo)activation.Items[i]).Index == this.preset.Activation)
|
||||
{
|
||||
activation.SelectedIndex = i;
|
||||
cbUseActivation.Checked = true;
|
||||
activation.Enabled = true;
|
||||
|
@ -143,53 +162,63 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
|||
presetUpdating = false;
|
||||
}
|
||||
|
||||
public LinedefColorPreset GetPreset() {
|
||||
/*public LinedefColorPreset GetPreset()
|
||||
{
|
||||
return preset;
|
||||
}
|
||||
}*/
|
||||
|
||||
public void UpdateMessages() {
|
||||
public void UpdateMessages()
|
||||
{
|
||||
//warnings/errors?
|
||||
List<string> errors = new List<string>();
|
||||
|
||||
if(!preset.Valid)
|
||||
errors.Add(preset.ErrorDescription);
|
||||
|
||||
if(!string.IsNullOrEmpty(preset.WarningDescription))
|
||||
errors.Add(preset.WarningDescription);
|
||||
|
||||
if(!preset.Valid) errors.Add(preset.ErrorDescription);
|
||||
if(!string.IsNullOrEmpty(preset.WarningDescription)) errors.Add(preset.WarningDescription);
|
||||
labelErrors.Text = (errors.Count > 0 ? string.Join(Environment.NewLine, errors.ToArray()) : "");
|
||||
}
|
||||
|
||||
private void raiseEvent() {
|
||||
if(PresetChanged != null)
|
||||
PresetChanged(this, EventArgs.Empty);
|
||||
private void RaiseEvent()
|
||||
{
|
||||
if(PresetChanged != null) PresetChanged(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
private void applyFlagsToPreset(CheckedListBox source) {
|
||||
if(source.Enabled) {
|
||||
for(int i = 0; i < source.Items.Count; i++) {
|
||||
private void ApplyFlagsToPreset(CheckedListBox source)
|
||||
{
|
||||
if(source.Enabled)
|
||||
{
|
||||
for(int i = 0; i < source.Items.Count; i++)
|
||||
{
|
||||
string flag = ((FlagData)source.Items[i]).Flag;
|
||||
CheckState state = source.GetItemCheckState(i);
|
||||
|
||||
if(state == CheckState.Checked) {
|
||||
if(!preset.Flags.Contains(flag))
|
||||
preset.Flags.Add(flag);
|
||||
if(preset.RestrictedFlags.Contains(flag))
|
||||
preset.RestrictedFlags.Remove(flag);
|
||||
} else if(state == CheckState.Unchecked) {
|
||||
if(preset.Flags.Contains(flag))
|
||||
preset.Flags.Remove(flag);
|
||||
if(!preset.RestrictedFlags.Contains(flag))
|
||||
preset.RestrictedFlags.Add(flag);
|
||||
} else {
|
||||
if(preset.Flags.Contains(flag))
|
||||
preset.Flags.Remove(flag);
|
||||
if(preset.RestrictedFlags.Contains(flag))
|
||||
preset.RestrictedFlags.Remove(flag);
|
||||
switch (state)
|
||||
{
|
||||
case CheckState.Checked:
|
||||
if(!preset.Flags.Contains(flag))
|
||||
preset.Flags.Add(flag);
|
||||
if(preset.RestrictedFlags.Contains(flag))
|
||||
preset.RestrictedFlags.Remove(flag);
|
||||
break;
|
||||
|
||||
case CheckState.Unchecked:
|
||||
if(preset.Flags.Contains(flag))
|
||||
preset.Flags.Remove(flag);
|
||||
if(!preset.RestrictedFlags.Contains(flag))
|
||||
preset.RestrictedFlags.Add(flag);
|
||||
break;
|
||||
|
||||
default:
|
||||
if(preset.Flags.Contains(flag))
|
||||
preset.Flags.Remove(flag);
|
||||
if(preset.RestrictedFlags.Contains(flag))
|
||||
preset.RestrictedFlags.Remove(flag);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for(int i = 0; i < source.Items.Count; i++) {
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int i = 0; i < source.Items.Count; i++)
|
||||
{
|
||||
string flag = ((FlagData)source.Items[i]).Flag;
|
||||
|
||||
if(preset.Flags.Contains(flag))
|
||||
|
@ -200,18 +229,23 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
|||
}
|
||||
}
|
||||
|
||||
private void applyFlagsToControl(CheckedListBox target, CheckBox cb) {
|
||||
if(preset.Flags.Count == 0 && preset.RestrictedFlags.Count == 0) {
|
||||
private void ApplyFlagsToControl(CheckedListBox target, CheckBox cb)
|
||||
{
|
||||
if(preset.Flags.Count == 0 && preset.RestrictedFlags.Count == 0)
|
||||
{
|
||||
cb.Checked = false;
|
||||
target.Enabled = false;
|
||||
|
||||
for(int i = 0; i < target.Items.Count; i++)
|
||||
target.SetItemCheckState(i, CheckState.Indeterminate);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
bool hasFlags = false;
|
||||
CheckState flagState;
|
||||
|
||||
for(int i = 0; i < target.Items.Count; i++) {
|
||||
for(int i = 0; i < target.Items.Count; i++)
|
||||
{
|
||||
string flag = ((FlagData)target.Items[i]).Flag;
|
||||
|
||||
if(preset.Flags.Contains(flag))
|
||||
|
@ -231,79 +265,85 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
|||
}
|
||||
|
||||
//EVENTS
|
||||
private void cbUseFlags_CheckedChanged(object sender, EventArgs e) {
|
||||
private void cbUseFlags_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
if(presetUpdating) return;
|
||||
flags.Enabled = cbUseFlags.Checked;
|
||||
applyFlagsToPreset(flags);
|
||||
ApplyFlagsToPreset(flags);
|
||||
|
||||
if(!flags.Enabled) raiseEvent();
|
||||
if(!flags.Enabled) RaiseEvent();
|
||||
}
|
||||
|
||||
private void flags_SelectedValueChanged(object sender, EventArgs e) {
|
||||
private void flags_SelectedValueChanged(object sender, EventArgs e)
|
||||
{
|
||||
if(presetUpdating) return;
|
||||
applyFlagsToPreset(flags);
|
||||
ApplyFlagsToPreset(flags);
|
||||
|
||||
raiseEvent();
|
||||
RaiseEvent();
|
||||
}
|
||||
|
||||
private void cbUseAction_CheckedChanged(object sender, EventArgs e) {
|
||||
private void cbUseAction_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
if(presetUpdating) return;
|
||||
|
||||
action.Enabled = cbUseAction.Checked;
|
||||
action.Value = 0;
|
||||
//raiseEvent();
|
||||
}
|
||||
|
||||
private void action_ValueChanges(object sender, EventArgs e) {
|
||||
private void action_ValueChanges(object sender, EventArgs e)
|
||||
{
|
||||
if(presetUpdating) return;
|
||||
preset.Action = action.Value;
|
||||
raiseEvent();
|
||||
RaiseEvent();
|
||||
}
|
||||
|
||||
private void cbUseActivation_CheckedChanged(object sender, EventArgs e) {
|
||||
private void cbUseActivation_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
if(presetUpdating) return;
|
||||
activation.Enabled = cbUseActivation.Checked;
|
||||
udmfactivates.Enabled = cbUseActivation.Checked;
|
||||
|
||||
if(udmf) {
|
||||
applyFlagsToPreset(udmfactivates);
|
||||
} else {
|
||||
if(!cbUseActivation.Checked)
|
||||
activation.SelectedIndex = 1;
|
||||
}
|
||||
if(udmf) ApplyFlagsToPreset(udmfactivates);
|
||||
else if(!cbUseActivation.Checked) activation.SelectedIndex = 1;
|
||||
|
||||
if(!cbUseActivation.Checked) raiseEvent();
|
||||
if(!cbUseActivation.Checked) RaiseEvent();
|
||||
}
|
||||
|
||||
private void activation_SelectedIndexChanged(object sender, EventArgs e) {
|
||||
private void activation_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
if(presetUpdating) return;
|
||||
|
||||
preset.Activation = ((LinedefActivateInfo)activation.SelectedItem).Index;
|
||||
raiseEvent();
|
||||
RaiseEvent();
|
||||
}
|
||||
|
||||
private void udmfactivates_SelectedValueChanged(object sender, EventArgs e) {
|
||||
private void udmfactivates_SelectedValueChanged(object sender, EventArgs e)
|
||||
{
|
||||
if(presetUpdating) return;
|
||||
applyFlagsToPreset(udmfactivates);
|
||||
raiseEvent();
|
||||
ApplyFlagsToPreset(udmfactivates);
|
||||
RaiseEvent();
|
||||
}
|
||||
|
||||
private void lineColor_ColorChanged(object sender, EventArgs e) {
|
||||
private void lineColor_ColorChanged(object sender, EventArgs e)
|
||||
{
|
||||
if(presetUpdating) return;
|
||||
|
||||
preset.Color = lineColor.Color;
|
||||
raiseEvent();
|
||||
RaiseEvent();
|
||||
}
|
||||
|
||||
private void flags_ItemCheck(object sender, ItemCheckEventArgs e) {
|
||||
private void flags_ItemCheck(object sender, ItemCheckEventArgs e)
|
||||
{
|
||||
if(presetUpdating) return;
|
||||
|
||||
if(e.CurrentValue == CheckState.Checked)
|
||||
e.NewValue = CheckState.Indeterminate;
|
||||
else if(e.CurrentValue == CheckState.Indeterminate)
|
||||
e.NewValue = CheckState.Unchecked;
|
||||
else
|
||||
e.NewValue = CheckState.Checked;
|
||||
switch (e.CurrentValue)
|
||||
{
|
||||
case CheckState.Checked:
|
||||
e.NewValue = CheckState.Indeterminate;
|
||||
break;
|
||||
case CheckState.Indeterminate:
|
||||
e.NewValue = CheckState.Unchecked;
|
||||
break;
|
||||
default:
|
||||
e.NewValue = CheckState.Checked;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,8 +11,10 @@
|
|||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing) {
|
||||
if(disposing && (components != null)) {
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if(disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
|
@ -24,7 +26,8 @@
|
|||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent() {
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.gbLineColor = new System.Windows.Forms.GroupBox();
|
||||
this.labelErrors = new System.Windows.Forms.Label();
|
||||
this.tcLineSettings = new System.Windows.Forms.TabControl();
|
||||
|
|
|
@ -14,7 +14,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
|||
private const string DEFAULT_PRESET_NAME = "Enter preset name";
|
||||
private const string NO_PRESET_NAME = "ENTER PRESET NAME!";
|
||||
|
||||
public CustomLinedefColorsControl() {
|
||||
public CustomLinedefColorsControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
colorProperties.PresetChanged += colorProperties_PresetChanged;
|
||||
|
@ -22,26 +23,30 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
|||
gbPresets.Enabled = false;
|
||||
}
|
||||
|
||||
public void Setup(GameConfiguration config, ConfigurationInfo configInfo) {
|
||||
public void Setup(GameConfiguration config, ConfigurationInfo configInfo)
|
||||
{
|
||||
colorProperties.Setup(config);
|
||||
lbColorPresets.Items.Clear();
|
||||
|
||||
if(configInfo.LinedefColorPresets.Length > 0) {
|
||||
if(configInfo.LinedefColorPresets.Length > 0)
|
||||
{
|
||||
//validate
|
||||
for(int i = 0; i < configInfo.LinedefColorPresets.Length; i++) {
|
||||
validatePreset(configInfo.LinedefColorPresets[i]);
|
||||
checkDuplicates(configInfo.LinedefColorPresets[i]);
|
||||
for(int i = 0; i < configInfo.LinedefColorPresets.Length; i++)
|
||||
{
|
||||
ValidatePreset(configInfo.LinedefColorPresets[i]);
|
||||
CheckDuplicates(configInfo.LinedefColorPresets[i]);
|
||||
}
|
||||
|
||||
lbColorPresets.Items.AddRange(configInfo.LinedefColorPresets);
|
||||
lbColorPresets.SelectedIndex = 0;
|
||||
}
|
||||
|
||||
updatePresetListControls();
|
||||
UpdatePresetListControls();
|
||||
gbPresets.Enabled = true;
|
||||
}
|
||||
|
||||
public LinedefColorPreset[] GetPresets() {
|
||||
public LinedefColorPreset[] GetPresets()
|
||||
{
|
||||
List<LinedefColorPreset> presets = new List<LinedefColorPreset>();
|
||||
|
||||
foreach(LinedefColorPreset preset in lbColorPresets.Items)
|
||||
|
@ -50,33 +55,38 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
|||
return presets.ToArray();
|
||||
}
|
||||
|
||||
private void validatePreset(LinedefColorPreset preset) {
|
||||
private void ValidatePreset(LinedefColorPreset preset)
|
||||
{
|
||||
bool hasAction = preset.Action != 0;
|
||||
bool hasFlags = preset.Flags.Count > 0 || preset.RestrictedFlags.Count > 0;
|
||||
bool hasActivation = preset.Activation != 0;
|
||||
|
||||
//validate
|
||||
if(!hasAction && !hasFlags && !hasActivation) {
|
||||
if(colorProperties.UDMF) {
|
||||
if(!hasAction && !hasFlags && !hasActivation)
|
||||
{
|
||||
if(colorProperties.UDMF)
|
||||
preset.SetInvalid("Invalid preset: no flags, action or activation type selected!");
|
||||
} else {
|
||||
else
|
||||
preset.SetInvalid("Invalid preset: no flags or action selected!");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
preset.SetValid();
|
||||
}
|
||||
|
||||
private bool validatePresetName() {
|
||||
if(string.IsNullOrEmpty(tbNewPresetName.Text) || tbNewPresetName.Text == DEFAULT_PRESET_NAME || tbNewPresetName.Text == NO_PRESET_NAME) {
|
||||
private bool ValidatePresetName()
|
||||
{
|
||||
if(string.IsNullOrEmpty(tbNewPresetName.Text) || tbNewPresetName.Text == DEFAULT_PRESET_NAME || tbNewPresetName.Text == NO_PRESET_NAME)
|
||||
{
|
||||
tbNewPresetName.ForeColor = Color.DarkRed;
|
||||
tbNewPresetName.Text = string.IsNullOrEmpty(tbNewPresetName.Text) ? DEFAULT_PRESET_NAME : NO_PRESET_NAME;
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach(LinedefColorPreset preset in lbColorPresets.Items) {
|
||||
if(preset.Name.ToLowerInvariant() == tbNewPresetName.Text.ToLowerInvariant()) {
|
||||
foreach(LinedefColorPreset preset in lbColorPresets.Items)
|
||||
{
|
||||
if(preset.Name.ToLowerInvariant() == tbNewPresetName.Text.ToLowerInvariant())
|
||||
{
|
||||
General.ShowWarningMessage("Preset with this name already exists!", MessageBoxButtons.OK);
|
||||
return false;
|
||||
}
|
||||
|
@ -86,9 +96,10 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
|||
return true;
|
||||
}
|
||||
|
||||
private void checkDuplicates(LinedefColorPreset preset)
|
||||
private void CheckDuplicates(LinedefColorPreset preset)
|
||||
{
|
||||
foreach(LinedefColorPreset p in lbColorPresets.Items) {
|
||||
foreach(LinedefColorPreset p in lbColorPresets.Items)
|
||||
{
|
||||
if(preset.Name == p.Name) continue;
|
||||
if(p.Action != preset.Action) continue;
|
||||
if(p.Activation != preset.Activation) continue;
|
||||
|
@ -96,15 +107,19 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
|||
if(p.RestrictedFlags.Count != preset.RestrictedFlags.Count) continue;
|
||||
|
||||
bool gotMismatch = false;
|
||||
foreach(string flag in p.Flags) {
|
||||
if(!preset.Flags.Contains(flag)) {
|
||||
foreach(string flag in p.Flags)
|
||||
{
|
||||
if(!preset.Flags.Contains(flag))
|
||||
{
|
||||
gotMismatch = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
foreach(string flag in p.RestrictedFlags) {
|
||||
if(!preset.RestrictedFlags.Contains(flag)) {
|
||||
foreach(string flag in p.RestrictedFlags)
|
||||
{
|
||||
if(!preset.RestrictedFlags.Contains(flag))
|
||||
{
|
||||
gotMismatch = true;
|
||||
break;
|
||||
}
|
||||
|
@ -118,23 +133,28 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
|||
}
|
||||
}
|
||||
|
||||
private void updatePresetListControls() {
|
||||
private void UpdatePresetListControls()
|
||||
{
|
||||
int c = lbColorPresets.Items.Count;
|
||||
|
||||
bRemovePreset.Enabled = c > 0;
|
||||
colorProperties.Enabled = c > 0;
|
||||
|
||||
if(c < 2) {
|
||||
if(c < 2)
|
||||
{
|
||||
bMoveDown.Enabled = false;
|
||||
bMoveUp.Enabled = false;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
bMoveDown.Enabled = lbColorPresets.SelectedIndex < c - 1;
|
||||
bMoveUp.Enabled = lbColorPresets.SelectedIndex > 0;
|
||||
}
|
||||
}
|
||||
|
||||
//EVENTS
|
||||
private void bMoveDown_Click(object sender, EventArgs e) {
|
||||
private void bMoveDown_Click(object sender, EventArgs e)
|
||||
{
|
||||
if(lbColorPresets.SelectedIndex == -1) return;
|
||||
|
||||
//I like to move it, move it!
|
||||
|
@ -144,11 +164,11 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
|||
|
||||
lbColorPresets.SelectedIndex++;
|
||||
|
||||
if(PresetsChanged != null)
|
||||
PresetsChanged(this, EventArgs.Empty);
|
||||
if(PresetsChanged != null) PresetsChanged(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
private void bMoveUp_Click(object sender, EventArgs e) {
|
||||
private void bMoveUp_Click(object sender, EventArgs e)
|
||||
{
|
||||
if(lbColorPresets.SelectedIndex == -1) return;
|
||||
|
||||
LinedefColorPreset preset = (LinedefColorPreset)lbColorPresets.SelectedItem;
|
||||
|
@ -157,12 +177,12 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
|||
|
||||
lbColorPresets.SelectedIndex--;
|
||||
|
||||
if(PresetsChanged != null)
|
||||
PresetsChanged(this, EventArgs.Empty);
|
||||
if(PresetsChanged != null) PresetsChanged(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
private void bAddPreset_Click(object sender, EventArgs e) {
|
||||
if(!validatePresetName()) return;
|
||||
private void bAddPreset_Click(object sender, EventArgs e)
|
||||
{
|
||||
if(!ValidatePresetName()) return;
|
||||
|
||||
//add new item
|
||||
lbColorPresets.Items.Insert(0, new LinedefColorPreset(tbNewPresetName.Text, colorProperties.DefaultColor));
|
||||
|
@ -174,13 +194,13 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
|||
else
|
||||
lbColorPresets_SelectedIndexChanged(this, EventArgs.Empty);
|
||||
|
||||
updatePresetListControls();
|
||||
UpdatePresetListControls();
|
||||
|
||||
if(PresetsChanged != null)
|
||||
PresetsChanged(this, EventArgs.Empty);
|
||||
if(PresetsChanged != null) PresetsChanged(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
private void bRemovePreset_Click(object sender, EventArgs e) {
|
||||
private void bRemovePreset_Click(object sender, EventArgs e)
|
||||
{
|
||||
if(lbColorPresets.Items.Count == 0 || lbColorPresets.SelectedIndex == -1) return; //sanity check
|
||||
|
||||
//remove item
|
||||
|
@ -188,43 +208,48 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
|||
lbColorPresets.Items.RemoveAt(index);
|
||||
lbColorPresets.SelectedIndex = (index >= lbColorPresets.Items.Count ? lbColorPresets.Items.Count - 1 : index);
|
||||
|
||||
updatePresetListControls();
|
||||
UpdatePresetListControls();
|
||||
|
||||
if(PresetsChanged != null)
|
||||
PresetsChanged(this, EventArgs.Empty);
|
||||
if(PresetsChanged != null) PresetsChanged(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
private void lbColorPresets_SelectedIndexChanged(object sender, EventArgs e) {
|
||||
if(lbColorPresets.SelectedIndex == -1) {
|
||||
private void lbColorPresets_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
if(lbColorPresets.SelectedIndex == -1)
|
||||
{
|
||||
colorProperties.Enabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
colorProperties.SetPreset((LinedefColorPreset)lbColorPresets.SelectedItem);
|
||||
updatePresetListControls();
|
||||
UpdatePresetListControls();
|
||||
}
|
||||
|
||||
private void colorProperties_PresetChanged(object sender, EventArgs e) {
|
||||
private void colorProperties_PresetChanged(object sender, EventArgs e)
|
||||
{
|
||||
LinedefColorPreset preset = (LinedefColorPreset)lbColorPresets.SelectedItem;
|
||||
preset.SetValid(); //clear error/warning messages
|
||||
validatePreset(preset); //validate it
|
||||
checkDuplicates(preset);
|
||||
ValidatePreset(preset); //validate it
|
||||
CheckDuplicates(preset);
|
||||
colorProperties.UpdateMessages(); //update error/warning messages
|
||||
lbColorPresets.Invalidate(); //redraw icons
|
||||
|
||||
if(PresetsChanged != null)
|
||||
PresetsChanged(this, EventArgs.Empty);
|
||||
if(PresetsChanged != null) PresetsChanged(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
private void tbNewPresetName_Click(object sender, EventArgs e) {
|
||||
if(tbNewPresetName.Text == DEFAULT_PRESET_NAME || tbNewPresetName.Text == NO_PRESET_NAME) {
|
||||
private void tbNewPresetName_Click(object sender, EventArgs e)
|
||||
{
|
||||
if(tbNewPresetName.Text == DEFAULT_PRESET_NAME || tbNewPresetName.Text == NO_PRESET_NAME)
|
||||
{
|
||||
tbNewPresetName.Text = "";
|
||||
tbNewPresetName.ForeColor = Color.Black;
|
||||
}
|
||||
}
|
||||
|
||||
private void tbNewPresetName_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e) {
|
||||
if(e.KeyCode == Keys.Enter) {
|
||||
private void tbNewPresetName_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
|
||||
{
|
||||
if(e.KeyCode == Keys.Enter)
|
||||
{
|
||||
bAddPreset_Click(this, EventArgs.Empty);
|
||||
e.IsInputKey = true;
|
||||
}
|
||||
|
|
|
@ -11,8 +11,10 @@
|
|||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing) {
|
||||
if(disposing && (components != null)) {
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if(disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
|
@ -24,7 +26,8 @@
|
|||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent() {
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.gbPresets = new System.Windows.Forms.GroupBox();
|
||||
this.bMoveUp = new System.Windows.Forms.Button();
|
||||
this.bMoveDown = new System.Windows.Forms.Button();
|
||||
|
|
|
@ -6,11 +6,13 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
|||
{
|
||||
internal class IconListBox : ListBox
|
||||
{
|
||||
public IconListBox() {
|
||||
public IconListBox()
|
||||
{
|
||||
this.DrawMode = DrawMode.OwnerDrawFixed;
|
||||
}
|
||||
|
||||
protected override void OnDrawItem(DrawItemEventArgs e) {
|
||||
protected override void OnDrawItem(DrawItemEventArgs e)
|
||||
{
|
||||
e.DrawBackground();
|
||||
e.DrawFocusRectangle();
|
||||
|
||||
|
|
|
@ -706,10 +706,9 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
|||
/// <param name="tn">TreeNode to check.</param>
|
||||
/// <param name="e">MouseEventArgs.</param>
|
||||
/// <returns>True is mouse was clicked inside the node bounds, false if it was clicked ouside the node bounds.</returns>
|
||||
private bool IsClickOnNode(TreeNode tn, MouseEventArgs e)
|
||||
private static bool IsClickOnNode(TreeNode tn, MouseEventArgs e)
|
||||
{
|
||||
if (tn == null)
|
||||
return false;
|
||||
if (tn == null) return false;
|
||||
|
||||
// GKM
|
||||
// Determine the rightmost position we'll process clicks (so that the click has to be on the node's bounds,
|
||||
|
@ -737,7 +736,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
|||
/// <param name="child">Node to check.</param>
|
||||
/// <param name="parent">Parent node.</param>
|
||||
/// <returns>True if specified node is a direct or indirect child of parent node, false if not.</returns>
|
||||
private bool IsChildOf(TreeNode child, TreeNode parent)
|
||||
private static bool IsChildOf(TreeNode child, TreeNode parent)
|
||||
{
|
||||
bool blnChild = false;
|
||||
|
||||
|
@ -821,7 +820,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
|||
/// <param name="down">True to go down, false to go up.</param>
|
||||
/// <param name="intNumber">Number of nodes to go down or up.</param>
|
||||
/// <returns>Next node.</returns>
|
||||
private TreeNode GetNextTreeNode(TreeNode start, bool down, int intNumber)
|
||||
private static TreeNode GetNextTreeNode(TreeNode start, bool down, int intNumber)
|
||||
{
|
||||
int intCounter = 0;
|
||||
TreeNode tnTemp = start;
|
||||
|
|
|
@ -11,8 +11,10 @@
|
|||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing) {
|
||||
if(disposing && (components != null)) {
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if(disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
|
@ -24,7 +26,8 @@
|
|||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent() {
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.label = new System.Windows.Forms.Label();
|
||||
this.bReset = new System.Windows.Forms.Button();
|
||||
this.bLink = new System.Windows.Forms.Button();
|
||||
|
|
|
@ -39,14 +39,15 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
|||
public bool AllowDecimal { get { return value1.AllowDecimal; } set { value1.AllowDecimal = value; value2.AllowDecimal = value; } }
|
||||
public int ButtonStep { get { return value1.ButtonStep; } set { value1.ButtonStep = value; value2.ButtonStep = value; } }
|
||||
public float ButtonStepFloat { get { return value1.ButtonStepFloat; } set { value1.ButtonStepFloat = value; value2.ButtonStepFloat = value; } }
|
||||
public bool AllowValueLinking { get { return allowValueLinking; } set { allowValueLinking = value; updateButtons(); } }
|
||||
public bool LinkValues { get { return linkValues; } set { linkValues = value; updateButtons(); } }
|
||||
public bool AllowValueLinking { get { return allowValueLinking; } set { allowValueLinking = value; UpdateButtons(); } }
|
||||
public bool LinkValues { get { return linkValues; } set { linkValues = value; UpdateButtons(); } }
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Constructor
|
||||
|
||||
public PairedFieldsControl() {
|
||||
public PairedFieldsControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
bResetOffsetX = this.Width - bReset.Left;
|
||||
}
|
||||
|
@ -55,36 +56,44 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
|||
|
||||
#region ================== Methods
|
||||
|
||||
public void SetValuesFrom(UniFields fields, bool first) {
|
||||
public void SetValuesFrom(UniFields fields, bool first)
|
||||
{
|
||||
blockUpdate = true;
|
||||
|
||||
string newValue1;
|
||||
string newValue2;
|
||||
|
||||
if(AllowDecimal) {
|
||||
if(AllowDecimal)
|
||||
{
|
||||
float val1 = UDMFTools.GetFloat(fields, field1, defaultValue);
|
||||
newValue1 = (val1 == Math.Round(val1) ? val1.ToString("0.0") : val1.ToString());
|
||||
|
||||
float val2 = UDMFTools.GetFloat(fields, field2, defaultValue);
|
||||
newValue2 = (val2 == Math.Round(val2) ? val2.ToString("0.0") : val2.ToString());
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
newValue1 = UDMFTools.GetFloat(fields, field1, defaultValue).ToString();
|
||||
newValue2 = UDMFTools.GetFloat(fields, field2, defaultValue).ToString();
|
||||
}
|
||||
|
||||
if(first) {
|
||||
if(first)
|
||||
{
|
||||
value1.Text = newValue1;
|
||||
value2.Text = newValue2;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
value1.Text = ((!string.IsNullOrEmpty(value1.Text) && value1.Text != newValue1) ? string.Empty : newValue1);
|
||||
value2.Text = ((!string.IsNullOrEmpty(value2.Text) && value2.Text != newValue2) ? string.Empty : newValue2);
|
||||
}
|
||||
checkValues();
|
||||
CheckValues();
|
||||
|
||||
blockUpdate = false;
|
||||
}
|
||||
|
||||
public void ApplyTo(UniFields fields, int min, int max, float oldValue1, float oldValue2) {
|
||||
public void ApplyTo(UniFields fields, int min, int max, float oldValue1, float oldValue2)
|
||||
{
|
||||
if(value1.Text != string.Empty)
|
||||
UDMFTools.SetFloat(fields, field1, General.Clamp(value1.GetResultFloat(defaultValue), min, max), defaultValue);
|
||||
else
|
||||
|
@ -96,7 +105,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
|||
UDMFTools.SetFloat(fields, field2, oldValue2, defaultValue);
|
||||
}
|
||||
|
||||
private void checkValues() {
|
||||
private void CheckValues()
|
||||
{
|
||||
bool changed = string.IsNullOrEmpty(value1.Text) || string.IsNullOrEmpty(value2.Text)
|
||||
|| value1.GetResultFloat(defaultValue) != defaultValue || value2.GetResultFloat(defaultValue) != defaultValue;
|
||||
label.Enabled = changed;
|
||||
|
@ -105,12 +115,16 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
|||
if(!blockUpdate && OnValuesChanged != null) OnValuesChanged(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
private void updateButtons() {
|
||||
private void UpdateButtons()
|
||||
{
|
||||
bLink.Visible = allowValueLinking;
|
||||
|
||||
if(!allowValueLinking) {
|
||||
if(!allowValueLinking)
|
||||
{
|
||||
bReset.Left = bLink.Left;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
bReset.Left = this.Width - bResetOffsetX;
|
||||
bLink.Image = (linkValues ? Resources.Link : Resources.Unlink);
|
||||
}
|
||||
|
@ -120,40 +134,46 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
|||
|
||||
#region ================== Events
|
||||
|
||||
private void bLink_Click(object sender, EventArgs e) {
|
||||
private void bLink_Click(object sender, EventArgs e)
|
||||
{
|
||||
linkValues = !linkValues;
|
||||
bLink.Image = (linkValues ? Resources.Link : Resources.Unlink);
|
||||
}
|
||||
|
||||
private void bReset_Click(object sender, EventArgs e) {
|
||||
private void bReset_Click(object sender, EventArgs e)
|
||||
{
|
||||
string newValue = value1.AllowDecimal ? String.Format("{0:0.0}", defaultValue) : defaultValue.ToString();
|
||||
value1.Text = newValue;
|
||||
value2.Text = newValue;
|
||||
checkValues();
|
||||
CheckValues();
|
||||
}
|
||||
|
||||
private void value1_WhenTextChanged(object sender, EventArgs e) {
|
||||
private void value1_WhenTextChanged(object sender, EventArgs e)
|
||||
{
|
||||
if(blockUpdate) return;
|
||||
|
||||
if(linkValues) {
|
||||
if(linkValues)
|
||||
{
|
||||
blockUpdate = true;
|
||||
value2.Text = value1.Text;
|
||||
blockUpdate = false;
|
||||
}
|
||||
|
||||
checkValues();
|
||||
CheckValues();
|
||||
}
|
||||
|
||||
private void value2_WhenTextChanged(object sender, EventArgs e) {
|
||||
private void value2_WhenTextChanged(object sender, EventArgs e)
|
||||
{
|
||||
if(blockUpdate) return;
|
||||
|
||||
if(linkValues) {
|
||||
if(linkValues)
|
||||
{
|
||||
blockUpdate = true;
|
||||
value1.Text = value2.Text;
|
||||
blockUpdate = false;
|
||||
}
|
||||
|
||||
checkValues();
|
||||
CheckValues();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Forms;
|
||||
using CodeImp.DoomBuilder.Properties;
|
||||
|
||||
|
@ -37,18 +38,21 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
|||
{
|
||||
blockUpdate = true;
|
||||
|
||||
if (first) {
|
||||
value1.Text = val1.ToString();
|
||||
value2.Text = val2.ToString();
|
||||
} else {
|
||||
if (!string.IsNullOrEmpty(value1.Text) && value1.Text != val1.ToString())
|
||||
if (first)
|
||||
{
|
||||
value1.Text = val1.ToString(CultureInfo.InvariantCulture);
|
||||
value2.Text = val2.ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!string.IsNullOrEmpty(value1.Text) && value1.Text != val1.ToString(CultureInfo.InvariantCulture))
|
||||
value1.Text = string.Empty;
|
||||
|
||||
if (!string.IsNullOrEmpty(value2.Text) && value2.Text != val2.ToString())
|
||||
if (!string.IsNullOrEmpty(value2.Text) && value2.Text != val2.ToString(CultureInfo.InvariantCulture))
|
||||
value2.Text = string.Empty;
|
||||
}
|
||||
|
||||
checkValues();
|
||||
CheckValues();
|
||||
|
||||
blockUpdate = false;
|
||||
}
|
||||
|
@ -63,10 +67,10 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
|||
return value2.GetResultFloat(original);
|
||||
}
|
||||
|
||||
private void checkValues()
|
||||
private void CheckValues()
|
||||
{
|
||||
bool changed = string.IsNullOrEmpty(value1.Text) || string.IsNullOrEmpty(value2.Text)
|
||||
|| value1.GetResultFloat(defaultValue) != defaultValue || value2.GetResultFloat(defaultValue) != defaultValue;
|
||||
bool changed = (string.IsNullOrEmpty(value1.Text) || string.IsNullOrEmpty(value2.Text)
|
||||
|| value1.GetResultFloat(defaultValue) != defaultValue || value2.GetResultFloat(defaultValue) != defaultValue);
|
||||
label.Enabled = changed;
|
||||
bReset.Visible = changed;
|
||||
|
||||
|
@ -78,7 +82,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
|||
string newValue = String.Format("{0:0.0}", defaultValue);
|
||||
value1.Text = newValue;
|
||||
value2.Text = newValue;
|
||||
checkValues();
|
||||
CheckValues();
|
||||
}
|
||||
|
||||
private void bLink_Click(object sender, EventArgs e)
|
||||
|
@ -91,26 +95,28 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
|||
{
|
||||
if (blockUpdate) return;
|
||||
|
||||
if (linkValues) {
|
||||
if (linkValues)
|
||||
{
|
||||
blockUpdate = true;
|
||||
value2.Text = value1.Text;
|
||||
blockUpdate = false;
|
||||
}
|
||||
|
||||
checkValues();
|
||||
CheckValues();
|
||||
}
|
||||
|
||||
private void value2_WhenTextChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (blockUpdate) return;
|
||||
|
||||
if (linkValues) {
|
||||
if (linkValues)
|
||||
{
|
||||
blockUpdate = true;
|
||||
value1.Text = value2.Text;
|
||||
blockUpdate = false;
|
||||
}
|
||||
|
||||
checkValues();
|
||||
CheckValues();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,8 +11,10 @@
|
|||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing) {
|
||||
if(disposing && (components != null)) {
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if(disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
|
@ -24,7 +26,8 @@
|
|||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent() {
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.label = new System.Windows.Forms.Label();
|
||||
this.bReset = new System.Windows.Forms.Button();
|
||||
this.value1 = new CodeImp.DoomBuilder.Controls.ButtonsNumericTextbox();
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#region ================== Namespaces
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Forms;
|
||||
|
||||
#endregion
|
||||
|
@ -30,36 +31,44 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
|||
|
||||
#endregion
|
||||
|
||||
public PairedIntControl() {
|
||||
public PairedIntControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public void SetValues(int val1, int val2, bool first) {
|
||||
public void SetValues(int val1, int val2, bool first)
|
||||
{
|
||||
blockUpdate = true;
|
||||
|
||||
if (first) {
|
||||
value1.Text = val1.ToString();
|
||||
value2.Text = val2.ToString();
|
||||
} else {
|
||||
if (!string.IsNullOrEmpty(value1.Text) && value1.Text != val1.ToString())
|
||||
if (first)
|
||||
{
|
||||
value1.Text = val1.ToString(CultureInfo.InvariantCulture);
|
||||
value2.Text = val2.ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!string.IsNullOrEmpty(value1.Text) && value1.Text != val1.ToString(CultureInfo.InvariantCulture))
|
||||
value1.Text = string.Empty;
|
||||
|
||||
if (!string.IsNullOrEmpty(value2.Text) && value2.Text != val2.ToString())
|
||||
if (!string.IsNullOrEmpty(value2.Text) && value2.Text != val2.ToString(CultureInfo.InvariantCulture))
|
||||
value2.Text = string.Empty;
|
||||
}
|
||||
|
||||
blockUpdate = false;
|
||||
}
|
||||
|
||||
public int GetValue1(int original) {
|
||||
public int GetValue1(int original)
|
||||
{
|
||||
return value1.GetResult(original);
|
||||
}
|
||||
|
||||
public int GetValue2(int original) {
|
||||
public int GetValue2(int original)
|
||||
{
|
||||
return value2.GetResult(original);
|
||||
}
|
||||
|
||||
private void checkValues() {
|
||||
private void CheckValues()
|
||||
{
|
||||
bool changed = string.IsNullOrEmpty(value1.Text) || string.IsNullOrEmpty(value2.Text)
|
||||
|| value1.GetResult(defaultValue) != defaultValue || value2.GetResult(defaultValue) != defaultValue;
|
||||
label.Enabled = changed;
|
||||
|
@ -68,14 +77,16 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
|||
if(!blockUpdate && OnValuesChanged != null) OnValuesChanged(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
private void bReset_Click(object sender, EventArgs e) {
|
||||
value1.Text = defaultValue.ToString();
|
||||
value2.Text = defaultValue.ToString();
|
||||
checkValues();
|
||||
private void bReset_Click(object sender, EventArgs e)
|
||||
{
|
||||
value1.Text = defaultValue.ToString(CultureInfo.InvariantCulture);
|
||||
value2.Text = defaultValue.ToString(CultureInfo.InvariantCulture);
|
||||
CheckValues();
|
||||
}
|
||||
|
||||
private void value1_WhenTextChanged(object sender, EventArgs e) {
|
||||
checkValues();
|
||||
private void value1_WhenTextChanged(object sender, EventArgs e)
|
||||
{
|
||||
CheckValues();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,8 +11,10 @@
|
|||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing) {
|
||||
if(disposing && (components != null)) {
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if(disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
|
@ -24,7 +26,8 @@
|
|||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent() {
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.components = new System.ComponentModel.Container();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.cbTagPicker = new System.Windows.Forms.ComboBox();
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
using System;
|
||||
#region ================== Namespaces
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows.Forms;
|
||||
using CodeImp.DoomBuilder.Map;
|
||||
using System.Globalization;
|
||||
using CodeImp.DoomBuilder.Types;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
||||
{
|
||||
internal struct TagInfo
|
||||
|
@ -12,52 +16,71 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
|||
public readonly string Label;
|
||||
public readonly int Tag;
|
||||
|
||||
public TagInfo(int tag, string label) {
|
||||
public TagInfo(int tag, string label)
|
||||
{
|
||||
Label = (string.IsNullOrEmpty(label) ? tag.ToString() : tag + " (" + label + ")");
|
||||
Tag = tag;
|
||||
}
|
||||
|
||||
public override string ToString() {
|
||||
public override string ToString()
|
||||
{
|
||||
return Label;
|
||||
}
|
||||
}
|
||||
|
||||
public partial class TagSelector : UserControl
|
||||
{
|
||||
#region ================== Variables
|
||||
|
||||
private List<int> tags;
|
||||
private List<TagInfo> infos;
|
||||
private bool valid;
|
||||
private int tag;
|
||||
private UniversalType elementType;
|
||||
private int rangemode; //0 - none, 1 - positive (>=), -1 - negative (<=)
|
||||
private int offsetmode = 0; //0 - none, 1 - positive (++), -1 - negative (--)
|
||||
|
||||
public TagSelector() {
|
||||
private int offsetmode; //0 - none, 1 - positive (++), -1 - negative (--)
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Constructor
|
||||
|
||||
public TagSelector()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public void Setup(UniversalType elementType) {
|
||||
#endregion
|
||||
|
||||
#region ================== Methods
|
||||
|
||||
public void Setup(UniversalType elementType)
|
||||
{
|
||||
tags = new List<int>();
|
||||
infos = new List<TagInfo>();
|
||||
this.elementType = elementType;
|
||||
|
||||
//collect used tags from sectors...
|
||||
foreach(Sector s in General.Map.Map.Sectors) {
|
||||
foreach(Sector s in General.Map.Map.Sectors)
|
||||
{
|
||||
if(s.Tag == 0 || tags.Contains(s.Tag)) continue;
|
||||
tags.Add(s.Tag);
|
||||
}
|
||||
|
||||
//...and linedefs...
|
||||
if(General.Map.FormatInterface.HasLinedefTag) {
|
||||
foreach(Linedef l in General.Map.Map.Linedefs) {
|
||||
if(General.Map.FormatInterface.HasLinedefTag)
|
||||
{
|
||||
foreach(Linedef l in General.Map.Map.Linedefs)
|
||||
{
|
||||
if(l.Tag == 0 || tags.Contains(l.Tag)) continue;
|
||||
tags.Add(l.Tag);
|
||||
}
|
||||
}
|
||||
|
||||
//...and things...
|
||||
if(General.Map.FormatInterface.HasThingTag) {
|
||||
foreach(Thing t in General.Map.Map.Things) {
|
||||
if(General.Map.FormatInterface.HasThingTag)
|
||||
{
|
||||
foreach(Thing t in General.Map.Map.Things)
|
||||
{
|
||||
if(t.Tag == 0 || tags.Contains(t.Tag)) continue;
|
||||
tags.Add(t.Tag);
|
||||
}
|
||||
|
@ -67,23 +90,26 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
|||
tags.Sort();
|
||||
|
||||
//create tag infos
|
||||
foreach(int tag in tags){
|
||||
foreach(int tag in tags)
|
||||
{
|
||||
if(General.Map.Options.TagLabels.ContainsKey(tag)) //tag labels
|
||||
infos.Add(new TagInfo(tag, General.Map.Options.TagLabels[tag]));
|
||||
else
|
||||
infos.Add(new TagInfo(tag, string.Empty));
|
||||
}
|
||||
|
||||
foreach(TagInfo info in infos)
|
||||
cbTagPicker.Items.Add(info);
|
||||
|
||||
foreach(TagInfo info in infos) cbTagPicker.Items.Add(info);
|
||||
cbTagPicker.DropDownWidth = DoomBuilder.Geometry.Tools.GetDropDownWidth(cbTagPicker);
|
||||
}
|
||||
|
||||
public void SetTag(int newTag) {
|
||||
if(tags.Contains(newTag)) {
|
||||
public void SetTag(int newTag)
|
||||
{
|
||||
if(tags.Contains(newTag))
|
||||
{
|
||||
cbTagPicker.SelectedIndex = tags.IndexOf(newTag);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
cbTagPicker.SelectedIndex = -1;
|
||||
cbTagPicker.Text = newTag.ToString();
|
||||
}
|
||||
|
@ -91,7 +117,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
|||
valid = true;
|
||||
}
|
||||
|
||||
public void ClearTag() {
|
||||
public void ClearTag()
|
||||
{
|
||||
cbTagPicker.SelectedIndex = -1;
|
||||
cbTagPicker.Text = string.Empty;
|
||||
rangemode = 0;
|
||||
|
@ -99,22 +126,26 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
|||
valid = false;
|
||||
}
|
||||
|
||||
public int GetTag(int original) {
|
||||
public int GetTag(int original)
|
||||
{
|
||||
return (valid ? tag : original);
|
||||
}
|
||||
|
||||
public int GetSmartTag(int original, int offset) {
|
||||
public int GetSmartTag(int original, int offset)
|
||||
{
|
||||
if (!valid) return original;
|
||||
if (rangemode != 0) return tag + offset * rangemode;
|
||||
if (offsetmode != 0) return original + tag * offsetmode;
|
||||
return tag;
|
||||
}
|
||||
|
||||
public void ValidateTag() {
|
||||
public void ValidateTag()
|
||||
{
|
||||
rangemode = 0;
|
||||
offsetmode = 0;
|
||||
|
||||
if(cbTagPicker.SelectedIndex != -1) {
|
||||
if(cbTagPicker.SelectedIndex != -1)
|
||||
{
|
||||
tag = infos[cbTagPicker.SelectedIndex].Tag;
|
||||
valid = true;
|
||||
return;
|
||||
|
@ -122,32 +153,44 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
|||
|
||||
//check text
|
||||
string text = cbTagPicker.Text.Trim().ToLowerInvariant();
|
||||
if(string.IsNullOrEmpty(text)) {
|
||||
if(string.IsNullOrEmpty(text))
|
||||
{
|
||||
valid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
//incremental?
|
||||
if(text.Length > 2){
|
||||
if(text.StartsWith(">=")) { //range up
|
||||
if(text.Length > 2)
|
||||
{
|
||||
if(text.StartsWith(">=")) //range up
|
||||
{
|
||||
rangemode = 1;
|
||||
text = text.Substring(2, text.Length - 2);
|
||||
} else if (text.StartsWith("<=")) { //range down
|
||||
}
|
||||
else if(text.StartsWith("<=")) //range down
|
||||
{
|
||||
rangemode = -1;
|
||||
text = text.Substring(2, text.Length - 2);
|
||||
} else if(text.StartsWith("++")) { //relative up
|
||||
}
|
||||
else if(text.StartsWith("++")) //relative up
|
||||
{
|
||||
offsetmode = 1;
|
||||
text = text.Substring(2, text.Length - 2);
|
||||
} else if(text.StartsWith("--")) { //relative down
|
||||
}
|
||||
else if(text.StartsWith("--")) //relative down
|
||||
{
|
||||
offsetmode = -1;
|
||||
text = text.Substring(2, text.Length - 2);
|
||||
}
|
||||
}
|
||||
|
||||
if(!int.TryParse(text, NumberStyles.Integer, CultureInfo.InvariantCulture, out tag)) {
|
||||
if(!int.TryParse(text, NumberStyles.Integer, CultureInfo.InvariantCulture, out tag))
|
||||
{
|
||||
//maybe it's user-pasted label?
|
||||
foreach(TagInfo info in infos) {
|
||||
if(info.Label.ToLowerInvariant().Contains(text)) {
|
||||
foreach(TagInfo info in infos)
|
||||
{
|
||||
if(info.Label.ToLowerInvariant().Contains(text))
|
||||
{
|
||||
tag = info.Tag;
|
||||
valid = true;
|
||||
return;
|
||||
|
@ -166,7 +209,12 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
|||
valid = true;
|
||||
}
|
||||
|
||||
private void newTag_Click(object sender, EventArgs e) {
|
||||
#endregion
|
||||
|
||||
#region ================== Events
|
||||
|
||||
private void newTag_Click(object sender, EventArgs e)
|
||||
{
|
||||
//todo: check tag labels?
|
||||
tag = General.Map.Map.GetNewTag();
|
||||
cbTagPicker.SelectedIndex = -1;
|
||||
|
@ -174,18 +222,22 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
|
|||
valid = true;
|
||||
}
|
||||
|
||||
private void unusedTag_Click(object sender, EventArgs e) {
|
||||
private void unusedTag_Click(object sender, EventArgs e)
|
||||
{
|
||||
tag = General.Map.Map.GetNewTag(elementType);
|
||||
cbTagPicker.SelectedIndex = -1;
|
||||
cbTagPicker.Text = tag.ToString();
|
||||
valid = true;
|
||||
}
|
||||
|
||||
private void clear_Click(object sender, EventArgs e) {
|
||||
private void clear_Click(object sender, EventArgs e)
|
||||
{
|
||||
tag = 0;
|
||||
cbTagPicker.SelectedIndex = -1;
|
||||
cbTagPicker.Text = tag.ToString();
|
||||
valid = true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data
|
|||
public short MaxZ;
|
||||
|
||||
//we need some reference here
|
||||
public BoundingBoxSizes(WorldVertex v) {
|
||||
public BoundingBoxSizes(WorldVertex v)
|
||||
{
|
||||
MinX = MaxX = (short)v.x;
|
||||
MinY = MaxY = (short)v.y;
|
||||
MinZ = MaxZ = (short)v.z;
|
||||
|
@ -23,7 +24,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data
|
|||
public static class BoundingBoxTools
|
||||
{
|
||||
//this creates array of vectors resembling bounding box
|
||||
public static Vector3[] CalculateBoundingBox(BoundingBoxSizes bbs) {
|
||||
public static Vector3[] CalculateBoundingBox(BoundingBoxSizes bbs)
|
||||
{
|
||||
//center
|
||||
Vector3 v0 = new Vector3(bbs.MinX + (bbs.MaxX - bbs.MinX) / 2, bbs.MinY + (bbs.MaxY - bbs.MinY) / 2, bbs.MinZ + (bbs.MaxZ - bbs.MinZ) / 2);
|
||||
|
||||
|
@ -40,7 +42,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data
|
|||
return new[] { v0, v1, v2, v3, v4, v5, v6, v7, v8 };
|
||||
}
|
||||
|
||||
public static Vector3[] CalculateBoundingPlane(BoundingBoxSizes bbs) {
|
||||
public static Vector3[] CalculateBoundingPlane(BoundingBoxSizes bbs)
|
||||
{
|
||||
//mxd. looks like I need only these 2 points, so...
|
||||
//center
|
||||
Vector3 v0 = new Vector3(bbs.MinX + (bbs.MaxX - bbs.MinX) / 2, bbs.MinY + (bbs.MaxY - bbs.MinY) / 2, bbs.MinZ + (bbs.MaxZ - bbs.MinZ) / 2);
|
||||
|
@ -48,21 +51,16 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data
|
|||
return new[] { v0, v1 };
|
||||
}
|
||||
|
||||
public static void UpdateBoundingBoxSizes(ref BoundingBoxSizes bbs, WorldVertex v) {
|
||||
if (v.x < bbs.MinX)
|
||||
bbs.MinX = (short)v.x;
|
||||
else if (v.x > bbs.MaxX)
|
||||
bbs.MaxX = (short)v.x;
|
||||
public static void UpdateBoundingBoxSizes(ref BoundingBoxSizes bbs, WorldVertex v)
|
||||
{
|
||||
if (v.x < bbs.MinX) bbs.MinX = (short)v.x;
|
||||
else if (v.x > bbs.MaxX) bbs.MaxX = (short)v.x;
|
||||
|
||||
if (v.z < bbs.MinZ)
|
||||
bbs.MinZ = (short)v.z;
|
||||
else if (v.z > bbs.MaxZ)
|
||||
bbs.MaxZ = (short)v.z;
|
||||
if (v.z < bbs.MinZ) bbs.MinZ = (short)v.z;
|
||||
else if (v.z > bbs.MaxZ) bbs.MaxZ = (short)v.z;
|
||||
|
||||
if (v.y < bbs.MinY)
|
||||
bbs.MinY = (short)v.y;
|
||||
else if (v.y > bbs.MaxY)
|
||||
bbs.MaxY = (short)v.y;
|
||||
if (v.y < bbs.MinY) bbs.MinY = (short)v.y;
|
||||
else if (v.y > bbs.MaxY) bbs.MaxY = (short)v.y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
namespace CodeImp.DoomBuilder.GZBuilder.Data
|
||||
{
|
||||
public sealed class DynamicLightData {
|
||||
public sealed class DynamicLightData
|
||||
{
|
||||
public DynamicLightType Type; //holds DynamicLightType
|
||||
public Color3 Color;
|
||||
public int PrimaryRadius;
|
||||
|
@ -12,7 +13,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data
|
|||
public bool Subtractive;
|
||||
public bool DontLightSelf;
|
||||
|
||||
public DynamicLightData() {
|
||||
public DynamicLightData()
|
||||
{
|
||||
Color = new Color3();
|
||||
Offset = new Vector3();
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace CodeImp.DoomBuilder.GZBuilder.Data {
|
||||
public class EngineInfo {
|
||||
namespace CodeImp.DoomBuilder.GZBuilder.Data
|
||||
{
|
||||
public class EngineInfo
|
||||
{
|
||||
public const string DEFAULT_ENGINE_NAME = "Engine with no name";
|
||||
|
||||
public string TestProgramName;
|
||||
|
@ -12,11 +14,13 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data {
|
|||
public int TestSkill;
|
||||
public bool TestShortPaths;
|
||||
|
||||
public EngineInfo() {
|
||||
public EngineInfo()
|
||||
{
|
||||
TestProgramName = DEFAULT_ENGINE_NAME;
|
||||
}
|
||||
|
||||
public EngineInfo(EngineInfo other) {
|
||||
public EngineInfo(EngineInfo other)
|
||||
{
|
||||
TestProgramName = other.TestProgramName;
|
||||
TestProgram = other.TestProgram;
|
||||
TestParameters = other.TestParameters;
|
||||
|
@ -25,8 +29,10 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data {
|
|||
TestShortPaths = other.TestShortPaths;
|
||||
}
|
||||
|
||||
public void CheckProgramName(bool forced) {
|
||||
if ((forced || TestProgramName == DEFAULT_ENGINE_NAME) && !String.IsNullOrEmpty(TestProgram)) {
|
||||
public void CheckProgramName(bool forced)
|
||||
{
|
||||
if ((forced || TestProgramName == DEFAULT_ENGINE_NAME) && !String.IsNullOrEmpty(TestProgram))
|
||||
{
|
||||
//get engine name from folder name
|
||||
TestProgramName = Path.GetFileNameWithoutExtension(TestProgram);
|
||||
}
|
||||
|
|
|
@ -22,14 +22,16 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data
|
|||
private const string NOT_VALID = "invalid";
|
||||
private const string DUPLICATE = "duplicate";
|
||||
|
||||
public LinedefColorPreset(string name, PixelColor lineColor) {
|
||||
public LinedefColorPreset(string name, PixelColor lineColor)
|
||||
{
|
||||
Name = name;
|
||||
Color = lineColor;
|
||||
Flags = new List<string>();
|
||||
RestrictedFlags = new List<string>();
|
||||
}
|
||||
|
||||
public LinedefColorPreset(string name, PixelColor lineColor, int action, int activation, List<string> flags, List<string> restrictedFlags) {
|
||||
public LinedefColorPreset(string name, PixelColor lineColor, int action, int activation, List<string> flags, List<string> restrictedFlags)
|
||||
{
|
||||
Name = name;
|
||||
Color = lineColor;
|
||||
Action = action;
|
||||
|
@ -38,7 +40,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data
|
|||
RestrictedFlags = restrictedFlags;
|
||||
}
|
||||
|
||||
public LinedefColorPreset(LinedefColorPreset copyFrom) {
|
||||
public LinedefColorPreset(LinedefColorPreset copyFrom)
|
||||
{
|
||||
Name = copyFrom.Name;
|
||||
Color = copyFrom.Color;
|
||||
Action = copyFrom.Action;
|
||||
|
@ -51,60 +54,62 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data
|
|||
RestrictedFlags.AddRange(copyFrom.RestrictedFlags);
|
||||
}
|
||||
|
||||
public bool Matches(Linedef l) {
|
||||
public bool Matches(Linedef l)
|
||||
{
|
||||
//check action; -1 means Any Action
|
||||
if(Action != 0) {
|
||||
if(Action != 0)
|
||||
{
|
||||
if((Action == -1 && l.Action == 0) || (Action != -1 && l.Action != Action))
|
||||
return false;
|
||||
}
|
||||
|
||||
//check activation; -1 means Any Activation
|
||||
if(Activation != 0) {
|
||||
if(Activation != 0)
|
||||
{
|
||||
if(!General.Map.UDMF && (l.Activate != Activation || (Activation == -1 && l.Activate == 0)))
|
||||
return false;
|
||||
}
|
||||
|
||||
//check flags
|
||||
if(Flags.Count > 0) {
|
||||
foreach(string s in Flags) {
|
||||
if(!l.IsFlagSet(s))
|
||||
return false;
|
||||
if(Flags.Count > 0)
|
||||
{
|
||||
foreach(string s in Flags)
|
||||
{
|
||||
if(!l.IsFlagSet(s)) return false;
|
||||
}
|
||||
}
|
||||
|
||||
//check flags, which should be disabled
|
||||
if(RestrictedFlags.Count > 0) {
|
||||
foreach(string s in RestrictedFlags) {
|
||||
if(l.IsFlagSet(s))
|
||||
return false;
|
||||
if(RestrictedFlags.Count > 0)
|
||||
{
|
||||
foreach(string s in RestrictedFlags)
|
||||
{
|
||||
if(l.IsFlagSet(s)) return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void SetValid() {
|
||||
public void SetValid()
|
||||
{
|
||||
valid = true;
|
||||
errorDescription = "";
|
||||
WarningDescription = "";
|
||||
}
|
||||
|
||||
public void SetInvalid(string reason) {
|
||||
public void SetInvalid(string reason)
|
||||
{
|
||||
valid = false;
|
||||
errorDescription = reason;
|
||||
}
|
||||
|
||||
public override string ToString() {
|
||||
public override string ToString()
|
||||
{
|
||||
List<string> rest = new List<string>();
|
||||
|
||||
if(!valid)
|
||||
rest.Add(NOT_VALID);
|
||||
|
||||
if(!string.IsNullOrEmpty(WarningDescription))
|
||||
rest.Add(DUPLICATE);
|
||||
|
||||
if(rest.Count > 0)
|
||||
return Name + " (" + string.Join(", ", rest.ToArray()) + ")";
|
||||
if(!valid) rest.Add(NOT_VALID);
|
||||
if(!string.IsNullOrEmpty(WarningDescription)) rest.Add(DUPLICATE);
|
||||
if(rest.Count > 0) return Name + " (" + string.Join(", ", rest.ToArray()) + ")";
|
||||
return Name;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,10 +5,12 @@ using CodeImp.DoomBuilder.GZBuilder.Geometry;
|
|||
using CodeImp.DoomBuilder.Geometry;
|
||||
using CodeImp.DoomBuilder.Config;
|
||||
|
||||
namespace CodeImp.DoomBuilder.GZBuilder.Data {
|
||||
|
||||
public static class LinksCollector {
|
||||
private struct ThingsCheckResult {
|
||||
namespace CodeImp.DoomBuilder.GZBuilder.Data
|
||||
{
|
||||
public static class LinksCollector
|
||||
{
|
||||
private struct ThingsCheckResult
|
||||
{
|
||||
public bool ProcessPathNodes;
|
||||
public bool ProcessInterpolationPoints;
|
||||
public bool ProcessThingsWithGoal;
|
||||
|
@ -16,27 +18,31 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data {
|
|||
public bool ProcessActorMovers;
|
||||
}
|
||||
|
||||
public static List<Line3D> GetThingLinks(ICollection<VisualThing> visualThings) {
|
||||
public static List<Line3D> GetThingLinks(ICollection<VisualThing> visualThings)
|
||||
{
|
||||
List<Thing> things = new List<Thing>();
|
||||
foreach (VisualThing vt in visualThings) things.Add(vt.Thing);
|
||||
|
||||
ThingsCheckResult result = checkThings(things);
|
||||
ThingsCheckResult result = CheckThings(things);
|
||||
if (result.ProcessPathNodes || result.ProcessInterpolationPoints || result.ProcessThingsWithGoal || result.ProcessCameras)
|
||||
return getThingLinks(result, true);
|
||||
return GetThingLinks(result, true);
|
||||
return new List<Line3D>();
|
||||
}
|
||||
|
||||
public static List<Line3D> GetThingLinks(ICollection<Thing> things) {
|
||||
ThingsCheckResult result = checkThings(things);
|
||||
public static List<Line3D> GetThingLinks(ICollection<Thing> things)
|
||||
{
|
||||
ThingsCheckResult result = CheckThings(things);
|
||||
if (result.ProcessPathNodes || result.ProcessInterpolationPoints || result.ProcessThingsWithGoal || result.ProcessCameras)
|
||||
return getThingLinks(result, false);
|
||||
return GetThingLinks(result, false);
|
||||
return new List<Line3D>();
|
||||
}
|
||||
|
||||
private static ThingsCheckResult checkThings(ICollection<Thing> things) {
|
||||
private static ThingsCheckResult CheckThings(ICollection<Thing> things)
|
||||
{
|
||||
ThingsCheckResult result = new ThingsCheckResult();
|
||||
|
||||
foreach (Thing t in things) {
|
||||
foreach (Thing t in things)
|
||||
{
|
||||
if(t.Type == 9024) //zdoom path node
|
||||
result.ProcessPathNodes = true;
|
||||
else if(t.Type == 9070) //zdoom camera interpolation point
|
||||
|
@ -58,7 +64,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data {
|
|||
return result;
|
||||
}
|
||||
|
||||
private static List<Line3D> getThingLinks(ThingsCheckResult result, bool correctHeight) {
|
||||
private static List<Line3D> GetThingLinks(ThingsCheckResult result, bool correctHeight)
|
||||
{
|
||||
List<Line3D> lines = new List<Line3D>();
|
||||
Dictionary<int, List<Thing>> pathNodes = new Dictionary<int, List<Thing>>();
|
||||
Dictionary<int, List<Thing>> interpolationPoints = new Dictionary<int, List<Thing>>();
|
||||
|
@ -68,37 +75,36 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data {
|
|||
Dictionary<int, List<Thing>> actorMoverTargets = new Dictionary<int, List<Thing>>();
|
||||
|
||||
//collect relevant things
|
||||
foreach (Thing t in General.Map.Map.Things) {
|
||||
if(result.ProcessPathNodes && t.Type == 9024) {
|
||||
foreach (Thing t in General.Map.Map.Things)
|
||||
{
|
||||
if(result.ProcessPathNodes && t.Type == 9024)
|
||||
{
|
||||
if(!pathNodes.ContainsKey(t.Tag))
|
||||
pathNodes[t.Tag] = new List<Thing>();
|
||||
pathNodes[t.Tag].Add(t);
|
||||
}
|
||||
if(result.ProcessInterpolationPoints && t.Type == 9070) {
|
||||
if(result.ProcessInterpolationPoints && t.Type == 9070)
|
||||
{
|
||||
if(!interpolationPoints.ContainsKey(t.Tag))
|
||||
interpolationPoints[t.Tag] = new List<Thing>();
|
||||
interpolationPoints[t.Tag].Add(t);
|
||||
}
|
||||
if (result.ProcessThingsWithGoal && t.Action == 229 && t.Args[1] != 0) {
|
||||
if (result.ProcessThingsWithGoal && t.Action == 229 && t.Args[1] != 0)
|
||||
thingsWithGoal.Add(t);
|
||||
}
|
||||
if (result.ProcessCameras && t.Type == 9072 && (t.Args[0] != 0 || t.Args[1] != 0)) {
|
||||
if (result.ProcessCameras && t.Type == 9072 && (t.Args[0] != 0 || t.Args[1] != 0))
|
||||
cameras.Add(t);
|
||||
}
|
||||
if(result.ProcessActorMovers && t.Type == 9074 && (t.Args[0] != 0 || t.Args[1] != 0) && t.Args[3] != 0) {
|
||||
if(result.ProcessActorMovers && t.Type == 9074 && (t.Args[0] != 0 || t.Args[1] != 0) && t.Args[3] != 0)
|
||||
actorMovers.Add(t);
|
||||
}
|
||||
}
|
||||
|
||||
if(actorMovers.Count > 0) {
|
||||
if(actorMovers.Count > 0)
|
||||
{
|
||||
List<int> targetedTags = new List<int>();
|
||||
|
||||
foreach(Thing t in actorMovers) {
|
||||
targetedTags.Add(t.Args[3]);
|
||||
}
|
||||
|
||||
foreach(Thing t in General.Map.Map.Things) {
|
||||
if(targetedTags.Contains(t.Tag)) {
|
||||
foreach(Thing t in actorMovers) targetedTags.Add(t.Args[3]);
|
||||
foreach(Thing t in General.Map.Map.Things)
|
||||
{
|
||||
if(targetedTags.Contains(t.Tag))
|
||||
{
|
||||
if(!actorMoverTargets.ContainsKey(t.Tag))
|
||||
actorMoverTargets[t.Tag] = new List<Thing>();
|
||||
actorMoverTargets[t.Tag].Add(t);
|
||||
|
@ -109,18 +115,23 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data {
|
|||
Vector3D start, end;
|
||||
|
||||
//process path nodes
|
||||
if (result.ProcessPathNodes) {
|
||||
foreach (KeyValuePair<int, List<Thing>> group in pathNodes) {
|
||||
foreach(Thing t in group.Value) {
|
||||
if (result.ProcessPathNodes)
|
||||
{
|
||||
foreach (KeyValuePair<int, List<Thing>> group in pathNodes)
|
||||
{
|
||||
foreach(Thing t in group.Value)
|
||||
{
|
||||
if(t.Args[0] == 0) continue; //no goal
|
||||
|
||||
if(pathNodes.ContainsKey(t.Args[0])) {
|
||||
if(pathNodes.ContainsKey(t.Args[0]))
|
||||
{
|
||||
start = t.Position;
|
||||
if(correctHeight) start.z += getCorrectHeight(t);
|
||||
if(correctHeight) start.z += GetCorrectHeight(t);
|
||||
|
||||
foreach(Thing tt in pathNodes[t.Args[0]]) {
|
||||
foreach(Thing tt in pathNodes[t.Args[0]])
|
||||
{
|
||||
end = tt.Position;
|
||||
if(correctHeight) end.z += getCorrectHeight(tt);
|
||||
if(correctHeight) end.z += GetCorrectHeight(tt);
|
||||
lines.Add(new Line3D(start, end));
|
||||
}
|
||||
}
|
||||
|
@ -129,16 +140,21 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data {
|
|||
}
|
||||
|
||||
//process things with Thing_SetGoal
|
||||
if (result.ProcessThingsWithGoal) {
|
||||
foreach (Thing t in thingsWithGoal) {
|
||||
if (pathNodes.ContainsKey(t.Args[1])) {
|
||||
if (t.Args[0] == 0 || t.Args[0] == t.Tag) {
|
||||
if (result.ProcessThingsWithGoal)
|
||||
{
|
||||
foreach (Thing t in thingsWithGoal)
|
||||
{
|
||||
if (pathNodes.ContainsKey(t.Args[1]))
|
||||
{
|
||||
if (t.Args[0] == 0 || t.Args[0] == t.Tag)
|
||||
{
|
||||
start = t.Position;
|
||||
if (correctHeight) start.z += getCorrectHeight(t);
|
||||
if (correctHeight) start.z += GetCorrectHeight(t);
|
||||
|
||||
foreach(Thing tt in pathNodes[t.Args[1]]) {
|
||||
foreach(Thing tt in pathNodes[t.Args[1]])
|
||||
{
|
||||
end = tt.Position;
|
||||
if(correctHeight) end.z += getCorrectHeight(tt);
|
||||
if(correctHeight) end.z += GetCorrectHeight(tt);
|
||||
|
||||
lines.Add(new Line3D(start, end, Line3DType.ACTIVATOR));
|
||||
}
|
||||
|
@ -148,19 +164,24 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data {
|
|||
}
|
||||
|
||||
//process interpolation points
|
||||
if (result.ProcessInterpolationPoints) {
|
||||
foreach (KeyValuePair<int, List<Thing>> group in interpolationPoints) {
|
||||
foreach(Thing t in group.Value) {
|
||||
if (result.ProcessInterpolationPoints)
|
||||
{
|
||||
foreach (KeyValuePair<int, List<Thing>> group in interpolationPoints)
|
||||
{
|
||||
foreach(Thing t in group.Value)
|
||||
{
|
||||
int targetTag = t.Args[3] + (t.Args[4] << 8);
|
||||
if(targetTag == 0) continue; //no goal
|
||||
|
||||
if(interpolationPoints.ContainsKey(targetTag)) {
|
||||
if(interpolationPoints.ContainsKey(targetTag))
|
||||
{
|
||||
start = t.Position;
|
||||
if(correctHeight) start.z += getCorrectHeight(t);
|
||||
if(correctHeight) start.z += GetCorrectHeight(t);
|
||||
|
||||
foreach(Thing tt in interpolationPoints[targetTag]) {
|
||||
foreach(Thing tt in interpolationPoints[targetTag])
|
||||
{
|
||||
end = tt.Position;
|
||||
if(correctHeight) end.z += getCorrectHeight(tt);
|
||||
if(correctHeight) end.z += GetCorrectHeight(tt);
|
||||
lines.Add(new Line3D(start, end));
|
||||
}
|
||||
}
|
||||
|
@ -169,18 +190,22 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data {
|
|||
}
|
||||
|
||||
//process cameras
|
||||
if (result.ProcessCameras) {
|
||||
foreach (Thing t in cameras) {
|
||||
if (result.ProcessCameras)
|
||||
{
|
||||
foreach (Thing t in cameras)
|
||||
{
|
||||
int targetTag = t.Args[0] + (t.Args[1] << 8);
|
||||
if (targetTag == 0) continue; //no goal
|
||||
|
||||
if(interpolationPoints.ContainsKey(targetTag)) {
|
||||
if(interpolationPoints.ContainsKey(targetTag))
|
||||
{
|
||||
start = t.Position;
|
||||
if(correctHeight) start.z += getCorrectHeight(t);
|
||||
if(correctHeight) start.z += GetCorrectHeight(t);
|
||||
|
||||
foreach(Thing tt in interpolationPoints[targetTag]) {
|
||||
foreach(Thing tt in interpolationPoints[targetTag])
|
||||
{
|
||||
end = tt.Position;
|
||||
if(correctHeight) end.z += getCorrectHeight(tt);
|
||||
if(correctHeight) end.z += GetCorrectHeight(tt);
|
||||
lines.Add(new Line3D(start, end, Line3DType.ACTIVATOR));
|
||||
}
|
||||
}
|
||||
|
@ -188,31 +213,37 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data {
|
|||
}
|
||||
|
||||
//process actor movers
|
||||
if(result.ProcessActorMovers) {
|
||||
foreach(Thing t in actorMovers) {
|
||||
if(result.ProcessActorMovers)
|
||||
{
|
||||
foreach(Thing t in actorMovers)
|
||||
{
|
||||
int targetTag = t.Args[0] + (t.Args[1] << 8);
|
||||
if(targetTag == 0) continue; //no goal
|
||||
|
||||
//add interpolation point target
|
||||
if(interpolationPoints.ContainsKey(targetTag)) {
|
||||
if(interpolationPoints.ContainsKey(targetTag))
|
||||
{
|
||||
start = t.Position;
|
||||
if(correctHeight) start.z += getCorrectHeight(t);
|
||||
if(correctHeight) start.z += GetCorrectHeight(t);
|
||||
|
||||
foreach(Thing tt in interpolationPoints[targetTag]) {
|
||||
foreach(Thing tt in interpolationPoints[targetTag])
|
||||
{
|
||||
end = tt.Position;
|
||||
if(correctHeight) end.z += getCorrectHeight(tt);
|
||||
if(correctHeight) end.z += GetCorrectHeight(tt);
|
||||
lines.Add(new Line3D(start, end, Line3DType.ACTIVATOR));
|
||||
}
|
||||
}
|
||||
|
||||
//add thing-to-move target
|
||||
if(actorMoverTargets.ContainsKey(t.Args[3])) {
|
||||
if(actorMoverTargets.ContainsKey(t.Args[3]))
|
||||
{
|
||||
start = t.Position;
|
||||
if(correctHeight) start.z += getCorrectHeight(t);
|
||||
if(correctHeight) start.z += GetCorrectHeight(t);
|
||||
|
||||
foreach(Thing tt in actorMoverTargets[t.Args[3]]) {
|
||||
foreach(Thing tt in actorMoverTargets[t.Args[3]])
|
||||
{
|
||||
end = tt.Position;
|
||||
if(correctHeight) end.z += getCorrectHeight(tt);
|
||||
if(correctHeight) end.z += GetCorrectHeight(tt);
|
||||
lines.Add(new Line3D(start, end, Line3DType.ACTIVATOR));
|
||||
}
|
||||
}
|
||||
|
@ -222,7 +253,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data {
|
|||
return lines;
|
||||
}
|
||||
|
||||
private static float getCorrectHeight(Thing thing) {
|
||||
private static float GetCorrectHeight(Thing thing)
|
||||
{
|
||||
ThingTypeInfo tti = General.Map.Data.GetThingInfo(thing.Type);
|
||||
float height = tti.Height / 2f;
|
||||
if (thing.Sector != null) height += thing.Sector.FloorHeight;
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
using SlimDX;
|
||||
|
||||
namespace CodeImp.DoomBuilder.GZBuilder.Data {
|
||||
public sealed class MapInfo {
|
||||
namespace CodeImp.DoomBuilder.GZBuilder.Data
|
||||
{
|
||||
public sealed class MapInfo
|
||||
{
|
||||
public string Sky1;
|
||||
public float Sky1ScrollSpeed;
|
||||
public string Sky2;
|
||||
|
@ -19,7 +21,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data {
|
|||
public int VertWallShade;
|
||||
public int HorizWallShade;
|
||||
|
||||
public MapInfo() {
|
||||
public MapInfo()
|
||||
{
|
||||
VertWallShade = 16;
|
||||
HorizWallShade = -16;
|
||||
}
|
||||
|
|
|
@ -26,20 +26,19 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data
|
|||
internal bool InheritActorPitch;
|
||||
internal bool InheritActorRoll;
|
||||
|
||||
internal ModelData() {
|
||||
internal ModelData()
|
||||
{
|
||||
ModelNames = new List<string>();
|
||||
TextureNames = new List<string>();
|
||||
Scale = new Vector3(1, 1, 1);
|
||||
}
|
||||
|
||||
internal void Dispose() {
|
||||
if (Model != null) {
|
||||
foreach (Mesh mesh in Model.Meshes)
|
||||
mesh.Dispose();
|
||||
|
||||
foreach (Texture t in Model.Textures)
|
||||
t.Dispose();
|
||||
|
||||
internal void Dispose()
|
||||
{
|
||||
if (Model != null)
|
||||
{
|
||||
foreach (Mesh mesh in Model.Meshes) mesh.Dispose();
|
||||
foreach (Texture t in Model.Textures) t.Dispose();
|
||||
loadstate = ModelLoadState.None;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
using System;
|
||||
|
||||
namespace CodeImp.DoomBuilder.GZBuilder.Data {
|
||||
internal sealed class ScriptItem : Object {
|
||||
namespace CodeImp.DoomBuilder.GZBuilder.Data
|
||||
{
|
||||
internal sealed class ScriptItem : Object
|
||||
{
|
||||
private string name;
|
||||
private int index;
|
||||
private int selectionStart;
|
||||
|
@ -12,42 +14,47 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data {
|
|||
internal int SelectionStart { get { return selectionStart; } }
|
||||
internal int SelectionEnd { get { return selectionEnd; } }
|
||||
|
||||
internal ScriptItem(int index, string name, int selectionStart, int selectionEnd) {
|
||||
internal ScriptItem(int index, string name, int selectionStart, int selectionEnd)
|
||||
{
|
||||
this.name = name;
|
||||
this.index = index;
|
||||
this.selectionStart = selectionStart;
|
||||
this.selectionEnd = selectionEnd;
|
||||
}
|
||||
|
||||
internal ScriptItem(int index, string name) {
|
||||
internal ScriptItem(int index, string name)
|
||||
{
|
||||
this.name = name;
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
internal static int SortByIndex(ScriptItem i1, ScriptItem i2) {
|
||||
internal static int SortByIndex(ScriptItem i1, ScriptItem i2)
|
||||
{
|
||||
if (i1.Index > i2.Index) return 1;
|
||||
if (i1.Index == i2.Index) return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
internal static int SortByName(ScriptItem i1, ScriptItem i2) {
|
||||
internal static int SortByName(ScriptItem i1, ScriptItem i2)
|
||||
{
|
||||
if (i1.Name == i2.Name) return 0;
|
||||
|
||||
if (i1.Name.ToUpper()[0] > i2.Name.ToUpper()[0]) return 1;
|
||||
if (i1.Name.ToUpper()[0] == i2.Name.ToUpper()[0]) {
|
||||
if (i1.Name.ToUpper()[0] == i2.Name.ToUpper()[0])
|
||||
{
|
||||
int len = Math.Min(i1.Name.Length, i2.Name.Length);
|
||||
for (int i = 0; i < len; i++) {
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
if (i1.Name.ToUpper()[i] > i2.Name.ToUpper()[i]) return 1;
|
||||
if (i1.Name.ToUpper()[i] < i2.Name.ToUpper()[i]) return -1;
|
||||
}
|
||||
|
||||
if (i1.Name.Length > i2.Name.Length) return 1;
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public override string ToString() {
|
||||
public override string ToString()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data
|
|||
{
|
||||
internal static class SharpCompressHelper
|
||||
{
|
||||
internal static MemoryStream CompressStream(Stream stream) {
|
||||
internal static MemoryStream CompressStream(Stream stream)
|
||||
{
|
||||
byte[] arr = new byte[stream.Length];
|
||||
stream.Read(arr, 0, (int)stream.Length);
|
||||
|
||||
|
@ -19,7 +20,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data
|
|||
return ms;
|
||||
}
|
||||
|
||||
internal static MemoryStream DecompressStream(Stream stream) {
|
||||
internal static MemoryStream DecompressStream(Stream stream)
|
||||
{
|
||||
BZip2Stream bzip = new BZip2Stream(stream, CompressionMode.Decompress, false);
|
||||
|
||||
byte[] buffer = new byte[16 * 1024];
|
||||
|
|
|
@ -2,8 +2,10 @@
|
|||
using CodeImp.DoomBuilder.Map;
|
||||
using CodeImp.DoomBuilder.Geometry;
|
||||
|
||||
namespace CodeImp.DoomBuilder.GZBuilder.Data {
|
||||
public sealed class ThingCopyData {
|
||||
namespace CodeImp.DoomBuilder.GZBuilder.Data
|
||||
{
|
||||
public sealed class ThingCopyData
|
||||
{
|
||||
// Properties
|
||||
private readonly int type;
|
||||
private readonly Vector3D pos;
|
||||
|
@ -16,7 +18,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data {
|
|||
|
||||
public Vector3D Position { get { return pos; } }
|
||||
|
||||
public ThingCopyData(Thing t) {
|
||||
public ThingCopyData(Thing t)
|
||||
{
|
||||
type = t.Type;
|
||||
angledoom = t.AngleDoom;
|
||||
pos = t.Position;
|
||||
|
@ -27,7 +30,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data {
|
|||
fields = new UniFields(t, t.Fields);
|
||||
}
|
||||
|
||||
public void ApplyTo(Thing t) {
|
||||
public void ApplyTo(Thing t)
|
||||
{
|
||||
t.Type = type;
|
||||
t.Rotate(angledoom);
|
||||
t.Move(pos);
|
||||
|
@ -41,7 +45,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data {
|
|||
for(int i = 0; i < args.Length; i++)
|
||||
t.Args[i] = args[i];
|
||||
|
||||
foreach (KeyValuePair<string, UniValue> group in fields) {
|
||||
foreach (KeyValuePair<string, UniValue> group in fields)
|
||||
{
|
||||
if (t.Fields.ContainsKey(group.Key))
|
||||
t.Fields[group.Key] = group.Value;
|
||||
else
|
||||
|
|
|
@ -23,7 +23,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
internal List<ScriptItem> NumberedScripts { get { return numberedScripts; } }
|
||||
internal List<ScriptItem> Functions { get { return functions; } }
|
||||
|
||||
internal AcsParserSE() {
|
||||
internal AcsParserSE()
|
||||
{
|
||||
namedScripts = new List<ScriptItem>();
|
||||
numberedScripts = new List<ScriptItem>();
|
||||
functions = new List<ScriptItem>();
|
||||
|
@ -31,15 +32,18 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
includes = new List<string>();
|
||||
}
|
||||
|
||||
internal List<string> Includes {
|
||||
internal List<string> Includes
|
||||
{
|
||||
get { return includes; }
|
||||
}
|
||||
|
||||
public override bool Parse(Stream stream, string sourcefilename) {
|
||||
public override bool Parse(Stream stream, string sourcefilename)
|
||||
{
|
||||
return Parse(stream, sourcefilename, false, false);
|
||||
}
|
||||
|
||||
public bool Parse(Stream stream, string sourcefilename, bool processIncludes, bool isinclude) {
|
||||
public bool Parse(Stream stream, string sourcefilename, bool processIncludes, bool isinclude)
|
||||
{
|
||||
base.Parse(stream, sourcefilename);
|
||||
|
||||
//already parsed this?
|
||||
|
@ -53,19 +57,23 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
BinaryReader localreader = datareader;
|
||||
|
||||
// Continue until at the end of the stream
|
||||
while (SkipWhitespace(true)) {
|
||||
while (SkipWhitespace(true))
|
||||
{
|
||||
string token = ReadToken();
|
||||
|
||||
if (!string.IsNullOrEmpty(token)) {
|
||||
if (!string.IsNullOrEmpty(token))
|
||||
{
|
||||
token = token.ToLowerInvariant();
|
||||
|
||||
if (token == "script") {
|
||||
if (token == "script")
|
||||
{
|
||||
int startPos = (int)stream.Position - 7;
|
||||
SkipWhitespace(true);
|
||||
token = ReadToken();
|
||||
|
||||
//is it named script?
|
||||
if (token.IndexOf('"') != -1) {
|
||||
if (token.IndexOf('"') != -1)
|
||||
{
|
||||
//check if we have something like '"mycoolscript"(void)' as a token
|
||||
if(token.LastIndexOf('"') != token.Length - 1)
|
||||
token = token.Substring(0, token.LastIndexOf('"'));
|
||||
|
@ -73,16 +81,20 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
token = StripTokenQuotes(token);
|
||||
ScriptItem i = new ScriptItem(0, token, startPos, (int)stream.Position-1);
|
||||
namedScripts.Add(i);
|
||||
} else { //should be numbered script
|
||||
}
|
||||
else //should be numbered script
|
||||
{
|
||||
//check if we have something like "999(void)" as a token
|
||||
if (token.Contains("(")) token = token.Substring(0, token.IndexOf("("));
|
||||
|
||||
int n;
|
||||
if (int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out n)) {
|
||||
if (int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out n))
|
||||
{
|
||||
int endPos = (int)stream.Position - 1;
|
||||
|
||||
//now find opening brace
|
||||
do {
|
||||
do
|
||||
{
|
||||
SkipWhitespace(true);
|
||||
token = ReadToken();
|
||||
} while (token != "{");
|
||||
|
@ -90,9 +102,11 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
token = ReadLine();
|
||||
string name = "";
|
||||
|
||||
if (token.Length > 0) {
|
||||
if (token.Length > 0)
|
||||
{
|
||||
int commentStart = token.IndexOf("//");
|
||||
if (commentStart != -1) { //found comment
|
||||
if (commentStart != -1) //found comment
|
||||
{
|
||||
commentStart += 2;
|
||||
name = token.Substring(commentStart, token.Length - commentStart).Trim();
|
||||
}
|
||||
|
@ -103,8 +117,9 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
numberedScripts.Add(i);
|
||||
}
|
||||
}
|
||||
|
||||
} else if(token == "function") {
|
||||
}
|
||||
else if(token == "function")
|
||||
{
|
||||
int startPos = (int)stream.Position - 9;
|
||||
SkipWhitespace(true);
|
||||
string funcname = ReadToken(); //read return type
|
||||
|
@ -112,16 +127,21 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
funcname += " " + ReadToken(); //read function name
|
||||
|
||||
//look for opening brace
|
||||
if (!funcname.Contains("(")) {
|
||||
if (!funcname.Contains("("))
|
||||
{
|
||||
SkipWhitespace(true);
|
||||
funcname += " " + ReadToken();
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
funcname = funcname.Replace("(", " (");
|
||||
}
|
||||
|
||||
//look for closing brace
|
||||
if(!funcname.Contains(")")) {
|
||||
do {
|
||||
if(!funcname.Contains(")"))
|
||||
{
|
||||
do
|
||||
{
|
||||
SkipWhitespace(true);
|
||||
token = ReadToken();
|
||||
funcname += " " + token;
|
||||
|
@ -130,12 +150,14 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
|
||||
ScriptItem i = new ScriptItem(0, funcname, startPos, (int)stream.Position - 1);
|
||||
functions.Add(i);
|
||||
|
||||
} else if (processIncludes && (token == "#include" || token == "#import")) {
|
||||
}
|
||||
else if (processIncludes && (token == "#include" || token == "#import"))
|
||||
{
|
||||
SkipWhitespace(true);
|
||||
string includeLump = StripTokenQuotes(ReadToken()).ToLowerInvariant();
|
||||
|
||||
if (!string.IsNullOrEmpty(includeLump)) {
|
||||
if (!string.IsNullOrEmpty(includeLump))
|
||||
{
|
||||
string includeName = Path.GetFileName(includeLump);
|
||||
|
||||
if (includeName == "zcommon.acs" || includeName == "common.acs" || includes.Contains(includeName))
|
||||
|
@ -148,7 +170,9 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
datastream = localstream;
|
||||
datareader = localreader;
|
||||
sourcename = localsourcename;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": got #include directive without include path!");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,35 +11,39 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
private List<ScriptItem> actors;
|
||||
public List<ScriptItem> Actors { get { return actors; } }
|
||||
|
||||
public DecorateParserSE() {
|
||||
public DecorateParserSE()
|
||||
{
|
||||
actors = new List<ScriptItem>();
|
||||
}
|
||||
|
||||
public override bool Parse(Stream stream, string sourcefilename) {
|
||||
public override bool Parse(Stream stream, string sourcefilename)
|
||||
{
|
||||
base.Parse(stream, sourcefilename);
|
||||
|
||||
// Continue until at the end of the stream
|
||||
while (SkipWhitespace(true)) {
|
||||
while (SkipWhitespace(true))
|
||||
{
|
||||
string token = ReadToken();
|
||||
|
||||
if (!string.IsNullOrEmpty(token)) {
|
||||
if (!string.IsNullOrEmpty(token))
|
||||
{
|
||||
token = token.ToLowerInvariant();
|
||||
|
||||
if (token == "actor") {
|
||||
if (token == "actor")
|
||||
{
|
||||
int startPos = (int)stream.Position - 6;
|
||||
SkipWhitespace(true);
|
||||
|
||||
List<string> definition = new List<string>();
|
||||
|
||||
while ((token = ReadToken()) != "{") {
|
||||
while ((token = ReadToken()) != "{")
|
||||
{
|
||||
definition.Add(token);
|
||||
SkipWhitespace(true);
|
||||
}
|
||||
|
||||
string name = "";
|
||||
foreach (string s in definition)
|
||||
name += s + " ";
|
||||
|
||||
foreach (string s in definition) name += s + " ";
|
||||
actors.Add(new ScriptItem(0, name.TrimEnd(), startPos, (int)stream.Position - 2));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
|
||||
private List<string> parsedLumps;
|
||||
|
||||
private struct GldefsLightType {
|
||||
private struct GldefsLightType
|
||||
{
|
||||
public const string POINT = "pointlight";
|
||||
public const string PULSE = "pulselight";
|
||||
public const string FLICKER = "flickerlight";
|
||||
|
@ -30,16 +31,19 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
public static Dictionary<string, DynamicLightType> GLDEFS_TO_GZDOOM_LIGHT_TYPE = new Dictionary<string, DynamicLightType>(StringComparer.Ordinal) { { POINT, DynamicLightType.NORMAL }, { PULSE, DynamicLightType.PULSE }, { FLICKER, DynamicLightType.FLICKER }, { FLICKER2, DynamicLightType.RANDOM }, { SECTOR, DynamicLightType.SECTOR } };
|
||||
}
|
||||
|
||||
public GldefsParser() {
|
||||
public GldefsParser()
|
||||
{
|
||||
parsedLumps = new List<string>();
|
||||
lightsByName = new Dictionary<string, DynamicLightData>(StringComparer.Ordinal); //LightName, Light params
|
||||
objects = new Dictionary<string, string>(StringComparer.Ordinal); //ClassName, LightName
|
||||
}
|
||||
|
||||
public override bool Parse(Stream stream, string sourcefilename) {
|
||||
public override bool Parse(Stream stream, string sourcefilename)
|
||||
{
|
||||
base.Parse(stream, sourcefilename);
|
||||
|
||||
if (parsedLumps.IndexOf(sourcefilename) != -1) {
|
||||
if (parsedLumps.IndexOf(sourcefilename) != -1)
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error: already parsed '" + sourcefilename + "'. Check your #include directives!");
|
||||
return false;
|
||||
}
|
||||
|
@ -51,13 +55,17 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
BinaryReader localreader = datareader;
|
||||
|
||||
// Continue until at the end of the stream
|
||||
while (SkipWhitespace(true)) {
|
||||
while (SkipWhitespace(true))
|
||||
{
|
||||
string token = ReadToken();
|
||||
if (!string.IsNullOrEmpty(token)) {
|
||||
if (!string.IsNullOrEmpty(token))
|
||||
{
|
||||
token = StripTokenQuotes(token.ToLowerInvariant()); //Quotes can be anywhere! ANYWHERE!!! And GZDoom will still parse data correctly
|
||||
|
||||
//got light structure
|
||||
if (token == GldefsLightType.POINT || token == GldefsLightType.PULSE || token == GldefsLightType.FLICKER || token == GldefsLightType.FLICKER2 || token == GldefsLightType.SECTOR) {
|
||||
if (token == GldefsLightType.POINT || token == GldefsLightType.PULSE || token == GldefsLightType.FLICKER
|
||||
|| token == GldefsLightType.FLICKER2 || token == GldefsLightType.SECTOR)
|
||||
{
|
||||
bool gotErrors = false;
|
||||
string lightType = token;
|
||||
|
||||
|
@ -68,27 +76,32 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
SkipWhitespace(true);
|
||||
string lightName = StripTokenQuotes(ReadToken()).ToLowerInvariant();
|
||||
|
||||
if (!string.IsNullOrEmpty(lightName)) {
|
||||
if (!string.IsNullOrEmpty(lightName))
|
||||
{
|
||||
//now find opening brace
|
||||
SkipWhitespace(true);
|
||||
token = ReadToken();
|
||||
if (token != "{") {
|
||||
if (token != "{")
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected '{', but got '" + token + "'");
|
||||
continue; //something wrong with gldefs declaration, continue to next one
|
||||
}
|
||||
|
||||
//read gldefs light structure
|
||||
while (SkipWhitespace(true)) {
|
||||
while (SkipWhitespace(true))
|
||||
{
|
||||
token = ReadToken();
|
||||
|
||||
if (!string.IsNullOrEmpty(token)) {
|
||||
if (!string.IsNullOrEmpty(token))
|
||||
{
|
||||
token = token.ToLowerInvariant();
|
||||
//color
|
||||
if (token == "color") {
|
||||
if (token == "color")
|
||||
{
|
||||
SkipWhitespace(true);
|
||||
|
||||
token = StripTokenQuotes(ReadToken());
|
||||
if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out light.Color.Red)) {
|
||||
if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out light.Color.Red))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Red Color value, but got '" + token + "'");
|
||||
gotErrors = true;
|
||||
|
@ -98,7 +111,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
SkipWhitespace(true);
|
||||
|
||||
token = StripTokenQuotes(ReadToken());
|
||||
if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out light.Color.Green)) {
|
||||
if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out light.Color.Green))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Green Color value, but got '" + token + "'");
|
||||
gotErrors = true;
|
||||
|
@ -108,19 +122,24 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
SkipWhitespace(true);
|
||||
|
||||
token = StripTokenQuotes(ReadToken());
|
||||
if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out light.Color.Blue)) {
|
||||
if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out light.Color.Blue))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Blue Color value, but got '" + token + "'");
|
||||
gotErrors = true;
|
||||
break;
|
||||
}
|
||||
//size
|
||||
} else if (token == "size") {
|
||||
if (lightType != GldefsLightType.SECTOR) {
|
||||
}
|
||||
else if (token == "size")
|
||||
{
|
||||
if (lightType != GldefsLightType.SECTOR)
|
||||
{
|
||||
SkipWhitespace(true);
|
||||
|
||||
token = StripTokenQuotes(ReadToken());
|
||||
if (!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out light.PrimaryRadius)) {
|
||||
if (!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out light.PrimaryRadius))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Size value, but got '" + token + "'");
|
||||
gotErrors = true;
|
||||
|
@ -128,17 +147,22 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
}
|
||||
light.PrimaryRadius *= 2;
|
||||
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": '" + token + "' is not valid property for " + lightType);
|
||||
gotErrors = true;
|
||||
break;
|
||||
}
|
||||
//offset
|
||||
} else if (token == "offset") {
|
||||
}
|
||||
else if (token == "offset")
|
||||
{
|
||||
SkipWhitespace(true);
|
||||
|
||||
token = StripTokenQuotes(ReadToken());
|
||||
if (!ReadSignedFloat(token, ref light.Offset.X)) {
|
||||
if (!ReadSignedFloat(token, ref light.Offset.X))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Offset X value, but got '" + token + "'");
|
||||
gotErrors = true;
|
||||
|
@ -148,7 +172,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
SkipWhitespace(true);
|
||||
|
||||
token = StripTokenQuotes(ReadToken());
|
||||
if (!ReadSignedFloat(token, ref light.Offset.Z)) {
|
||||
if (!ReadSignedFloat(token, ref light.Offset.Z))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Offset Y value, but got '" + token + "'");
|
||||
gotErrors = true;
|
||||
|
@ -158,19 +183,23 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
SkipWhitespace(true);
|
||||
|
||||
token = StripTokenQuotes(ReadToken());
|
||||
if (!ReadSignedFloat(token, ref light.Offset.Y)) {
|
||||
if (!ReadSignedFloat(token, ref light.Offset.Y))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Offset Z value, but got '" + token + "'");
|
||||
gotErrors = true;
|
||||
break;
|
||||
}
|
||||
//subtractive
|
||||
} else if (token == "subtractive") {
|
||||
}
|
||||
else if (token == "subtractive")
|
||||
{
|
||||
SkipWhitespace(true);
|
||||
|
||||
token = StripTokenQuotes(ReadToken());
|
||||
int i;
|
||||
if (!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out i)) {
|
||||
if (!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out i))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Subtractive value, but got '" + token + "'");
|
||||
gotErrors = true;
|
||||
|
@ -179,12 +208,15 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
|
||||
light.Subtractive = i == 1;
|
||||
//dontlightself
|
||||
} else if (token == "dontlightself") {
|
||||
}
|
||||
else if (token == "dontlightself")
|
||||
{
|
||||
SkipWhitespace(true);
|
||||
|
||||
token = StripTokenQuotes(ReadToken());
|
||||
int i;
|
||||
if (!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out i)) {
|
||||
if (!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out i))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Dontlightself value, but got '" + token + "'");
|
||||
gotErrors = true;
|
||||
|
@ -193,61 +225,78 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
|
||||
light.DontLightSelf = (i == 1);
|
||||
//interval
|
||||
} else if (token == "interval") {
|
||||
if (lightType == GldefsLightType.PULSE || lightType == GldefsLightType.FLICKER2) {
|
||||
}
|
||||
else if (token == "interval")
|
||||
{
|
||||
if (lightType == GldefsLightType.PULSE || lightType == GldefsLightType.FLICKER2)
|
||||
{
|
||||
SkipWhitespace(true);
|
||||
|
||||
token = StripTokenQuotes(ReadToken());
|
||||
float interval;
|
||||
if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out interval)) {
|
||||
if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out interval))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Interval value, but got '" + token + "'");
|
||||
gotErrors = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if(interval == 0) {
|
||||
if(interval == 0)
|
||||
General.ErrorLogger.Add(ErrorType.Warning, "Warning in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": Interval value should be greater than zero");
|
||||
}
|
||||
|
||||
//I wrote logic for dynamic lights animation first, so here I modify gldefs settings to fit in existing logic
|
||||
if (lightType == GldefsLightType.PULSE) {
|
||||
if (lightType == GldefsLightType.PULSE)
|
||||
{
|
||||
light.Interval = (int)(interval * 35); //measured in tics (35 per second) in PointLightPulse, measured in seconds in gldefs' PulseLight
|
||||
} else { //FLICKER2. Seems like PointLightFlickerRandom to me
|
||||
}
|
||||
else //FLICKER2. Seems like PointLightFlickerRandom to me
|
||||
{
|
||||
light.Interval = (int)(interval * 350); //0.1 is one second for FlickerLight2
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": '"+token+"' is not valid property for " + lightType);
|
||||
gotErrors = true;
|
||||
break;
|
||||
}
|
||||
//secondarysize
|
||||
} else if (token == "secondarysize") {
|
||||
if (lightType == GldefsLightType.PULSE || lightType == GldefsLightType.FLICKER || lightType == GldefsLightType.FLICKER2) {
|
||||
}
|
||||
else if (token == "secondarysize")
|
||||
{
|
||||
if (lightType == GldefsLightType.PULSE || lightType == GldefsLightType.FLICKER || lightType == GldefsLightType.FLICKER2)
|
||||
{
|
||||
SkipWhitespace(true);
|
||||
|
||||
token = StripTokenQuotes(ReadToken());
|
||||
if (!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out light.SecondaryRadius)) {
|
||||
if (!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out light.SecondaryRadius))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected SecondarySize value, but got '" + token + "'");
|
||||
gotErrors = true;
|
||||
break;
|
||||
}
|
||||
light.SecondaryRadius *= 2;
|
||||
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": '" + token + "' is not valid property for " + lightType);
|
||||
gotErrors = true;
|
||||
break;
|
||||
}
|
||||
//chance
|
||||
} else if (token == "chance") {
|
||||
if (lightType == GldefsLightType.FLICKER) {
|
||||
}
|
||||
else if (token == "chance")
|
||||
{
|
||||
if (lightType == GldefsLightType.FLICKER)
|
||||
{
|
||||
SkipWhitespace(true);
|
||||
|
||||
token = StripTokenQuotes(ReadToken());
|
||||
float chance;
|
||||
if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out chance)) {
|
||||
if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out chance))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Chance value, but got '" + token + "'");
|
||||
gotErrors = true;
|
||||
|
@ -256,26 +305,33 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
|
||||
//transforming from 0.0 .. 1.0 to 0 .. 359 to fit in existing logic
|
||||
light.Interval = (int)(chance * 359.0f);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": '" + token + "' is not valid property for " + lightType);
|
||||
gotErrors = true;
|
||||
break;
|
||||
}
|
||||
//scale
|
||||
} else if (token == "scale") {
|
||||
if (lightType == GldefsLightType.SECTOR) {
|
||||
}
|
||||
else if (token == "scale")
|
||||
{
|
||||
if (lightType == GldefsLightType.SECTOR)
|
||||
{
|
||||
SkipWhitespace(true);
|
||||
|
||||
token = StripTokenQuotes(ReadToken());
|
||||
float scale;
|
||||
if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out scale)) {
|
||||
if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out scale))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Scale value, but got '" + token + "'");
|
||||
gotErrors = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (scale > 1.0f) {
|
||||
if (scale > 1.0f)
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": scale must be in 0.0 - 1.0 range, but is " + scale);
|
||||
gotErrors = true;
|
||||
break;
|
||||
|
@ -284,46 +340,51 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
//sector light doesn't have animation, so we will store it's size in Interval
|
||||
//transforming from 0.0 .. 1.0 to 0 .. 10 to preserve value.
|
||||
light.Interval = (int)(scale * 10.0f);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": '" + token + "' is not valid property for " + lightType);
|
||||
gotErrors = true;
|
||||
break;
|
||||
}
|
||||
|
||||
//end of structure
|
||||
} else if (token == "}") {
|
||||
if (!gotErrors) {
|
||||
}
|
||||
//end of structure
|
||||
else if (token == "}")
|
||||
{
|
||||
if (!gotErrors)
|
||||
{
|
||||
//general checks
|
||||
if (light.Color.Red == 0.0f && light.Color.Green == 0.0f && light.Color.Blue == 0.0f) {
|
||||
if (light.Color.Red == 0.0f && light.Color.Green == 0.0f && light.Color.Blue == 0.0f)
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Warning, "'" + sourcefilename + "', line " + GetCurrentLineNumber() + ": light Color is " + light.Color.Red + "," + light.Color.Green + "," + light.Color.Blue + ". It won't be shown in GZDoom!");
|
||||
gotErrors = true;
|
||||
}
|
||||
|
||||
//light-type specific checks
|
||||
if (light.Type == DynamicLightType.NORMAL) {
|
||||
if (light.PrimaryRadius == 0) {
|
||||
General.ErrorLogger.Add(ErrorType.Warning, "'" + sourcefilename + "', line " + GetCurrentLineNumber() + ": light Size is 0. It won't be shown in GZDoom!");
|
||||
gotErrors = true;
|
||||
}
|
||||
if (light.Type == DynamicLightType.NORMAL && light.PrimaryRadius == 0)
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Warning, "'" + sourcefilename + "', line " + GetCurrentLineNumber() + ": light Size is 0. It won't be shown in GZDoom!");
|
||||
gotErrors = true;
|
||||
}
|
||||
|
||||
if (light.Type == DynamicLightType.FLICKER || light.Type == DynamicLightType.PULSE || light.Type == DynamicLightType.RANDOM) {
|
||||
if (light.PrimaryRadius == 0 && light.SecondaryRadius == 0) {
|
||||
if (light.Type == DynamicLightType.FLICKER || light.Type == DynamicLightType.PULSE || light.Type == DynamicLightType.RANDOM)
|
||||
{
|
||||
if (light.PrimaryRadius == 0 && light.SecondaryRadius == 0)
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Warning, "'" + sourcefilename + "', line " + GetCurrentLineNumber() + ": 'Size' and 'SecondarySize' are 0. This light won't be shown in GZDoom!");
|
||||
gotErrors = true;
|
||||
}
|
||||
}
|
||||
|
||||
//offset it slightly to avoid shading glitches
|
||||
if (light.Offset.Z == 0.0f)
|
||||
light.Offset.Z = 0.1f;
|
||||
if (light.Offset.Z == 0.0f) light.Offset.Z = 0.1f;
|
||||
|
||||
if (!gotErrors) {
|
||||
if (lightsByName.ContainsKey(lightName)) {
|
||||
if (!gotErrors)
|
||||
{
|
||||
if (lightsByName.ContainsKey(lightName))
|
||||
lightsByName[lightName] = light;
|
||||
} else {
|
||||
else
|
||||
lightsByName.Add(lightName, light);
|
||||
}
|
||||
}
|
||||
}
|
||||
break; //break out of this parsing loop
|
||||
|
@ -331,19 +392,22 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else if (token == "object") {
|
||||
}
|
||||
else if (token == "object")
|
||||
{
|
||||
SkipWhitespace(true);
|
||||
|
||||
//read object class
|
||||
string objectClass = StripTokenQuotes(ReadToken()).ToLowerInvariant();
|
||||
|
||||
if (!string.IsNullOrEmpty(objectClass)) {
|
||||
if (!string.IsNullOrEmpty(objectClass))
|
||||
{
|
||||
//now find opening brace
|
||||
SkipWhitespace(true);
|
||||
token = ReadToken();
|
||||
|
||||
if (token != "{") {
|
||||
if (token != "{")
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected '{', but got '" + token + "'");
|
||||
continue;
|
||||
}
|
||||
|
@ -353,48 +417,59 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
bool foundFrame = false;
|
||||
|
||||
//read frames structure
|
||||
while (SkipWhitespace(true)) {
|
||||
while (SkipWhitespace(true))
|
||||
{
|
||||
token = ReadToken();
|
||||
|
||||
if (!string.IsNullOrEmpty(token)) {
|
||||
if (!string.IsNullOrEmpty(token))
|
||||
{
|
||||
token = StripTokenQuotes(token).ToLowerInvariant();
|
||||
|
||||
if(!foundLight && !foundFrame && token == "frame") {
|
||||
if(!foundLight && !foundFrame && token == "frame")
|
||||
{
|
||||
SkipWhitespace(true);
|
||||
token = ReadToken().ToLowerInvariant(); //should be frame name
|
||||
|
||||
//use this frame if it's 4 characters long or it's the first frame
|
||||
foundFrame = (token.Length == 4 || (token.Length > 4 && token[4] == 'a'));
|
||||
} else if(!foundLight && foundFrame && token == "light") { //just use first light and be done with it
|
||||
}
|
||||
else if(!foundLight && foundFrame && token == "light") //just use first light and be done with it
|
||||
{
|
||||
SkipWhitespace(true);
|
||||
token = ReadToken().ToLowerInvariant(); //should be light name
|
||||
|
||||
if (!string.IsNullOrEmpty(token)) {
|
||||
if (lightsByName.ContainsKey(token)) {
|
||||
if (!string.IsNullOrEmpty(token))
|
||||
{
|
||||
if (lightsByName.ContainsKey(token))
|
||||
{
|
||||
if (objects.ContainsKey(objectClass))
|
||||
objects[objectClass] = token;
|
||||
else
|
||||
objects.Add(objectClass, token);
|
||||
foundLight = true;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Warning, "Light declaration not found for light '" + token + "' ('" + sourcefilename + "', line " + GetCurrentLineNumber()+")");
|
||||
}
|
||||
}
|
||||
} else if (token == "{") { //continue in this loop until object structure ends
|
||||
}
|
||||
else if (token == "{") //continue in this loop until object structure ends
|
||||
{
|
||||
bracesCount++;
|
||||
} else if (token == "}") {
|
||||
if (--bracesCount < 1)
|
||||
break; //This was Cave Johnson. And we are done here.
|
||||
}
|
||||
else if (token == "}")
|
||||
{
|
||||
if (--bracesCount < 1) break; //This was Cave Johnson. And we are done here.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else if (token == "#include") {
|
||||
}
|
||||
else if (token == "#include")
|
||||
{
|
||||
SkipWhitespace(true);
|
||||
string includeLump = StripTokenQuotes(ReadToken()).ToLowerInvariant();
|
||||
|
||||
if (!string.IsNullOrEmpty(includeLump)) {
|
||||
if (!string.IsNullOrEmpty(includeLump))
|
||||
{
|
||||
// Callback to parse this file
|
||||
if (OnInclude != null)
|
||||
OnInclude(this, includeLump.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar));
|
||||
|
@ -403,21 +478,26 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
datastream = localstream;
|
||||
datareader = localreader;
|
||||
sourcename = localsourcename;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": got #include directive with missing or incorrect path: '" + includeLump + "'");
|
||||
}
|
||||
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unknown structure!
|
||||
string token2;
|
||||
do {
|
||||
do
|
||||
{
|
||||
if (!SkipWhitespace(true)) break;
|
||||
token2 = ReadToken();
|
||||
if (token2 == null) break;
|
||||
}
|
||||
while (token2 != "{");
|
||||
int scopelevel = 1;
|
||||
do {
|
||||
do
|
||||
{
|
||||
if (!SkipWhitespace(true)) break;
|
||||
token2 = ReadToken();
|
||||
if (token2 == null) break;
|
||||
|
|
|
@ -11,19 +11,19 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
private MapInfo mapInfo;
|
||||
public MapInfo MapInfo { get { return mapInfo; } }
|
||||
|
||||
public bool Parse(Stream stream, string sourcefilename, string mapName) {
|
||||
public bool Parse(Stream stream, string sourcefilename, string mapName)
|
||||
{
|
||||
base.Parse(stream, sourcefilename);
|
||||
|
||||
mapName = mapName.ToLowerInvariant();
|
||||
mapInfo = new MapInfo();
|
||||
|
||||
while (SkipWhitespace(true)) {
|
||||
while (SkipWhitespace(true))
|
||||
{
|
||||
string token = ReadToken();
|
||||
if (token != null) {
|
||||
if (token != null)
|
||||
{
|
||||
token = token.ToLowerInvariant();
|
||||
|
||||
if (parseBlock(token, mapName))
|
||||
break;
|
||||
if (ParseBlock(token, mapName)) break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,36 +39,40 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
}
|
||||
|
||||
//returns true if parsing is finished
|
||||
private bool parseBlock(string token, string mapName) {
|
||||
private bool ParseBlock(string token, string mapName)
|
||||
{
|
||||
string curBlockName;
|
||||
|
||||
if (token == "map" || token == "defaultmap" || token == "adddefaultmap") {
|
||||
if (token == "map" || token == "defaultmap" || token == "adddefaultmap")
|
||||
{
|
||||
curBlockName = token;
|
||||
|
||||
if (token == "map") { //check map name
|
||||
if (token == "map") //check map name
|
||||
{
|
||||
//get map name
|
||||
SkipWhitespace(true);
|
||||
token = ReadToken().ToLowerInvariant();
|
||||
|
||||
if (token != mapName)
|
||||
return false; //not finished, search for next "map", "defaultmap" or "adddefaultmap" block
|
||||
} else if (token == "defaultmap") {
|
||||
if (token != mapName) return false; //not finished, search for next "map", "defaultmap" or "adddefaultmap" block
|
||||
}
|
||||
else if (token == "defaultmap")
|
||||
{
|
||||
//reset MapInfo
|
||||
mapInfo = new MapInfo();
|
||||
}
|
||||
|
||||
//search for required keys
|
||||
while (SkipWhitespace(true)) {
|
||||
while (SkipWhitespace(true))
|
||||
{
|
||||
token = ReadToken().ToLowerInvariant();
|
||||
|
||||
//sky1 or sky2
|
||||
if (token == "sky1" || token == "sky2") {
|
||||
if (token == "sky1" || token == "sky2")
|
||||
{
|
||||
string skyType = token;
|
||||
SkipWhitespace(true);
|
||||
token = StripTokenQuotes(ReadToken()).ToLowerInvariant();
|
||||
|
||||
//new format
|
||||
if (token == "=") {
|
||||
if (token == "=")
|
||||
{
|
||||
SkipWhitespace(true);
|
||||
|
||||
//should be sky texture name
|
||||
|
@ -77,7 +81,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
if (gotComma) token = token.Replace(",", "");
|
||||
string skyTexture = StripTokenQuotes(token).ToLowerInvariant();
|
||||
|
||||
if (!string.IsNullOrEmpty(skyTexture)) {
|
||||
if (!string.IsNullOrEmpty(skyTexture))
|
||||
{
|
||||
if (skyType == "sky1")
|
||||
mapInfo.Sky1 = skyTexture;
|
||||
else
|
||||
|
@ -87,16 +92,18 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
SkipWhitespace(true);
|
||||
token = StripTokenQuotes(ReadToken());
|
||||
|
||||
if (!gotComma && token == ",") {
|
||||
if (!gotComma && token == ",")
|
||||
{
|
||||
gotComma = true;
|
||||
SkipWhitespace(true);
|
||||
token = ReadToken();
|
||||
}
|
||||
|
||||
if (gotComma) {
|
||||
if (gotComma)
|
||||
{
|
||||
float scrollSpeed = 0;
|
||||
|
||||
if (!ReadSignedFloat(token, ref scrollSpeed)) {
|
||||
if (!ReadSignedFloat(token, ref scrollSpeed))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Warning, "Unexpected token found in '" + sourcename + "' at line " + GetCurrentLineNumber() + ": expected " + skyType + " scroll speed value, but got '" + token + "'");
|
||||
datastream.Seek(-token.Length - 1, SeekOrigin.Current); //step back and try parsing this token again
|
||||
|
@ -107,17 +114,24 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
mapInfo.Sky1ScrollSpeed = scrollSpeed;
|
||||
else
|
||||
mapInfo.Sky2ScrollSpeed = scrollSpeed;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
datastream.Seek(-token.Length - 1, SeekOrigin.Current); //step back and try parsing this token again
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
datastream.Seek(-token.Length - 1, SeekOrigin.Current); //step back and try parsing this token again
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Unexpected token found in '" + sourcename + "' at line " + GetCurrentLineNumber() + ": expected " + skyType + " texture name.");
|
||||
}
|
||||
//old format
|
||||
} else {
|
||||
}
|
||||
//old format
|
||||
else
|
||||
{
|
||||
//token should be sky1/2 name
|
||||
if (!string.IsNullOrEmpty(token)) {
|
||||
if (!string.IsNullOrEmpty(token))
|
||||
{
|
||||
if (skyType == "sky1")
|
||||
mapInfo.Sky1 = token;
|
||||
else
|
||||
|
@ -128,7 +142,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
token = StripTokenQuotes(ReadToken());
|
||||
|
||||
float scrollSpeed = 0;
|
||||
if (!ReadSignedFloat(token, ref scrollSpeed)) {
|
||||
if (!ReadSignedFloat(token, ref scrollSpeed))
|
||||
{
|
||||
// Not numeric!
|
||||
datastream.Seek(-token.Length - 1, SeekOrigin.Current); //step back and try parsing this token again
|
||||
continue;
|
||||
|
@ -139,56 +154,70 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
else
|
||||
mapInfo.Sky2ScrollSpeed = scrollSpeed;
|
||||
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
datastream.Seek(-token.Length - 1, SeekOrigin.Current); //step back and try parsing this token again
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Unexpected token found in '" + sourcename + "' at line " + GetCurrentLineNumber() + ": expected " + skyType + " texture name.");
|
||||
}
|
||||
}
|
||||
}
|
||||
//fade or outsidefog
|
||||
} else if (token == "fade" || token == "outsidefog") {
|
||||
else if (token == "fade" || token == "outsidefog")
|
||||
{
|
||||
string fadeType = token;
|
||||
SkipWhitespace(true);
|
||||
token = StripTokenQuotes(ReadToken()).ToLowerInvariant();
|
||||
|
||||
//new format?
|
||||
if (token == "=") {
|
||||
if (token == "=")
|
||||
{
|
||||
SkipWhitespace(true);
|
||||
token = ReadToken();
|
||||
}
|
||||
|
||||
//get the color value
|
||||
string colorVal = StripTokenQuotes(token).ToLowerInvariant().Replace(" ", "");
|
||||
if(!string.IsNullOrEmpty(colorVal)) {
|
||||
if(!string.IsNullOrEmpty(colorVal))
|
||||
{
|
||||
Color4 color = new Color4();
|
||||
|
||||
//try to get the color...
|
||||
if(getColor(colorVal, ref color)) {
|
||||
if(GetColor(colorVal, ref color))
|
||||
{
|
||||
if(fadeType == "fade")
|
||||
mapInfo.FadeColor = color;
|
||||
else
|
||||
mapInfo.OutsideFogColor = color;
|
||||
} else { //...or not
|
||||
}
|
||||
else //...or not
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Failed to parse " + fadeType + " value from string '" + colorVal + "' in '" + sourcename + "' at line " + GetCurrentLineNumber());
|
||||
datastream.Seek(-token.Length - 1, SeekOrigin.Current); //step back and try parsing this token again
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Unexpected token found in '" + sourcename + "' at line " + GetCurrentLineNumber() + ": expected " + fadeType + " color value.");
|
||||
datastream.Seek(-token.Length - 1, SeekOrigin.Current); //step back and try parsing this token again
|
||||
}
|
||||
}
|
||||
//vertwallshade or horizwallshade
|
||||
} else if (token == "vertwallshade" || token == "horizwallshade") {
|
||||
else if (token == "vertwallshade" || token == "horizwallshade")
|
||||
{
|
||||
string shadeType = token;
|
||||
SkipWhitespace(true);
|
||||
token = StripTokenQuotes(ReadToken());
|
||||
|
||||
//new format
|
||||
if(token == "=") {
|
||||
if(token == "=")
|
||||
{
|
||||
SkipWhitespace(true);
|
||||
token = StripTokenQuotes(ReadToken());
|
||||
}
|
||||
|
||||
int val = 0;
|
||||
if(!ReadSignedInt(token, ref val)) {
|
||||
if(!ReadSignedInt(token, ref val))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Unexpected token found in '" + sourcename + "' at line " + GetCurrentLineNumber() + ": expected " + shadeType + " value, but got '" + token + "'");
|
||||
datastream.Seek(-token.Length - 1, SeekOrigin.Current); //step back and try parsing this token again
|
||||
|
@ -199,62 +228,77 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
mapInfo.VertWallShade = General.Clamp(val, -255, 255);
|
||||
else
|
||||
mapInfo.HorizWallShade = General.Clamp(val, -255, 255);
|
||||
}
|
||||
//fogdensity or outsidefogdensity
|
||||
} else if(token == "fogdensity" || token == "outsidefogdensity") {
|
||||
else if(token == "fogdensity" || token == "outsidefogdensity")
|
||||
{
|
||||
string densityType = token;
|
||||
SkipWhitespace(true);
|
||||
token = StripTokenQuotes(ReadToken());
|
||||
|
||||
//new format
|
||||
if(token == "=") {
|
||||
if(token == "=")
|
||||
{
|
||||
SkipWhitespace(true);
|
||||
token = StripTokenQuotes(ReadToken());
|
||||
}
|
||||
|
||||
int val;
|
||||
if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out val)) {
|
||||
if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out val))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Unexpected token found in '" + sourcename + "' at line " + GetCurrentLineNumber() + ": expected " + densityType + " value, but got '" + token + "'");
|
||||
datastream.Seek(-token.Length - 1, SeekOrigin.Current); //step back and try parsing this token again
|
||||
continue;
|
||||
}
|
||||
|
||||
if (densityType == "fogdensity") {
|
||||
if (densityType == "fogdensity")
|
||||
mapInfo.FogDensity = (int)(1024 * (256.0f / val));
|
||||
} else {
|
||||
else
|
||||
mapInfo.OutsideFogDensity = (int)(1024 * (256.0f / val));
|
||||
}
|
||||
//doublesky
|
||||
} else if (token == "doublesky") {
|
||||
}
|
||||
//doublesky
|
||||
else if (token == "doublesky")
|
||||
{
|
||||
mapInfo.DoubleSky = true;
|
||||
|
||||
}
|
||||
//evenlighting
|
||||
} else if (token == "evenlighting") {
|
||||
else if (token == "evenlighting")
|
||||
{
|
||||
mapInfo.EvenLighting = true;
|
||||
}
|
||||
//smoothlighting
|
||||
} else if (token == "smoothlighting") {
|
||||
else if (token == "smoothlighting")
|
||||
{
|
||||
mapInfo.SmoothLighting = true;
|
||||
//block end
|
||||
} else if (token == "}") {
|
||||
return (curBlockName == "map" || parseBlock(token, mapName));
|
||||
}
|
||||
//block end
|
||||
else if (token == "}")
|
||||
{
|
||||
return (curBlockName == "map" || ParseBlock(token, mapName));
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool getColor(string name, ref Color4 color) {
|
||||
private static bool GetColor(string name, ref Color4 color)
|
||||
{
|
||||
if (name == "black") return true;
|
||||
|
||||
//probably it's a hex color (like FFCC11)?
|
||||
int ci;
|
||||
if (int.TryParse(name, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out ci)) {
|
||||
if (int.TryParse(name, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out ci))
|
||||
{
|
||||
color = new Color4(ci) {Alpha = 1.0f};
|
||||
return true;
|
||||
}
|
||||
|
||||
//probably it's a color name?
|
||||
Color c = Color.FromName(name); //should be similar to C++ color name detection, I suppose
|
||||
if (c.IsKnownColor) {
|
||||
if (c.IsKnownColor)
|
||||
{
|
||||
color = new Color4(c);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -4,54 +4,60 @@ using System.IO;
|
|||
using CodeImp.DoomBuilder.ZDoom;
|
||||
using CodeImp.DoomBuilder.GZBuilder.Data;
|
||||
|
||||
namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
||||
|
||||
internal class ModeldefParser : ZDTextParser {
|
||||
namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
||||
{
|
||||
internal class ModeldefParser : ZDTextParser
|
||||
{
|
||||
private Dictionary<string, ModelData> entries; //classname, entry
|
||||
internal Dictionary<string, ModelData> Entries { get { return entries; } }
|
||||
internal string Source { get { return sourcename; } }
|
||||
|
||||
internal ModeldefParser() {
|
||||
internal ModeldefParser()
|
||||
{
|
||||
entries = new Dictionary<string, ModelData>(StringComparer.Ordinal);
|
||||
}
|
||||
|
||||
//should be called after all decorate actors are parsed
|
||||
public override bool Parse(Stream stream, string sourcefilename) {
|
||||
public override bool Parse(Stream stream, string sourcefilename)
|
||||
{
|
||||
base.Parse(stream, sourcefilename);
|
||||
entries = new Dictionary<string, ModelData>(StringComparer.Ordinal);
|
||||
|
||||
// Continue until at the end of the stream
|
||||
while (SkipWhitespace(true)) {
|
||||
while (SkipWhitespace(true))
|
||||
{
|
||||
string token = ReadToken();
|
||||
|
||||
if (token != null) {
|
||||
if (token != null)
|
||||
{
|
||||
token = StripTokenQuotes(token).ToLowerInvariant();
|
||||
|
||||
if (token == "model") { //model structure start
|
||||
if (token == "model") //model structure start
|
||||
{
|
||||
//find classname
|
||||
SkipWhitespace(true);
|
||||
string className = StripTokenQuotes(ReadToken(ActorStructure.ACTOR_CLASS_SPECIAL_TOKENS)).ToLowerInvariant();
|
||||
|
||||
if(!string.IsNullOrEmpty(className) && !entries.ContainsKey(className)) {
|
||||
if(!string.IsNullOrEmpty(className) && !entries.ContainsKey(className))
|
||||
{
|
||||
//now find opening brace
|
||||
SkipWhitespace(true);
|
||||
token = ReadToken();
|
||||
if (token != "{") {
|
||||
if (token != "{")
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Unexpected token found in '"+sourcefilename+"' at line "+GetCurrentLineNumber()+": expected '{', but got '" + token + "'");
|
||||
continue; //something wrong with modeldef declaration, continue to next one
|
||||
}
|
||||
|
||||
ModeldefStructure mds = new ModeldefStructure();
|
||||
ModelData mde = mds.Parse(this);
|
||||
if (mde != null) {
|
||||
entries.Add(className, mde);
|
||||
}
|
||||
if (mde != null) entries.Add(className, mde);
|
||||
}
|
||||
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unknown structure!
|
||||
string token2;
|
||||
if (token != "{") {
|
||||
if (token != "{")
|
||||
{
|
||||
do
|
||||
{
|
||||
if (!SkipWhitespace(true)) break;
|
||||
|
@ -62,7 +68,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
}
|
||||
|
||||
int scopelevel = 1;
|
||||
do {
|
||||
do
|
||||
{
|
||||
if (!SkipWhitespace(true)) break;
|
||||
token2 = ReadToken();
|
||||
if (token2 == null) break;
|
||||
|
|
|
@ -1,36 +1,48 @@
|
|||
using System.IO;
|
||||
#region ================== Namespaces
|
||||
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using CodeImp.DoomBuilder.ZDoom;
|
||||
using CodeImp.DoomBuilder.GZBuilder.Data;
|
||||
|
||||
#endregion
|
||||
|
||||
//mxd. Modeldef parser used to create ScriptItems for use in script editor's navigator
|
||||
namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
||||
internal sealed class ModeldefParserSE : ZDTextParser {
|
||||
private List<ScriptItem> models;
|
||||
namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
||||
{
|
||||
internal sealed class ModeldefParserSE : ZDTextParser
|
||||
{
|
||||
private readonly List<ScriptItem> models;
|
||||
internal List<ScriptItem> Models { get { return models; } }
|
||||
|
||||
public ModeldefParserSE() {
|
||||
public ModeldefParserSE()
|
||||
{
|
||||
models = new List<ScriptItem>();
|
||||
}
|
||||
|
||||
public override bool Parse(Stream stream, string sourcefilename) {
|
||||
public override bool Parse(Stream stream, string sourcefilename)
|
||||
{
|
||||
base.Parse(stream, sourcefilename);
|
||||
|
||||
// Continue until at the end of the stream
|
||||
while (SkipWhitespace(true)) {
|
||||
while (SkipWhitespace(true))
|
||||
{
|
||||
string token = ReadToken();
|
||||
|
||||
if (!string.IsNullOrEmpty(token)) {
|
||||
if (!string.IsNullOrEmpty(token))
|
||||
{
|
||||
token = token.ToUpperInvariant();
|
||||
|
||||
if(token == "MODEL"){
|
||||
if(token == "MODEL")
|
||||
{
|
||||
int startPos = (int)stream.Position - 6;
|
||||
SkipWhitespace(true);
|
||||
string modelName = ReadToken();
|
||||
SkipWhitespace(true);
|
||||
token = ReadToken(); //this should be "{"
|
||||
|
||||
if (token == "{") {
|
||||
if (token == "{")
|
||||
{
|
||||
ScriptItem i = new ScriptItem(0, modelName, startPos, (int)stream.Position - 2);
|
||||
models.Add(i);
|
||||
}
|
||||
|
|
|
@ -1,15 +1,22 @@
|
|||
using System;
|
||||
#region ================== Namespaces
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Globalization;
|
||||
using SlimDX;
|
||||
using CodeImp.DoomBuilder.GZBuilder.Data;
|
||||
using CodeImp.DoomBuilder.Geometry;
|
||||
|
||||
namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
||||
internal sealed class ModeldefStructure {
|
||||
#endregion
|
||||
|
||||
namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
||||
{
|
||||
internal sealed class ModeldefStructure
|
||||
{
|
||||
private const int MAX_MODELS = 4; //maximum models per modeldef entry, zero-based
|
||||
|
||||
internal ModelData Parse(ModeldefParser parser) {
|
||||
internal ModelData Parse(ModeldefParser parser)
|
||||
{
|
||||
string[] textureNames = new string[4];
|
||||
string[] modelNames = new string[4];
|
||||
string path = "";
|
||||
|
@ -26,18 +33,22 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
bool allParsed = false;
|
||||
|
||||
//read modeldef structure contents
|
||||
while(!gotErrors && !allParsed && parser.SkipWhitespace(true)) {
|
||||
while(!gotErrors && !allParsed && parser.SkipWhitespace(true))
|
||||
{
|
||||
token = parser.ReadToken();
|
||||
|
||||
if (!string.IsNullOrEmpty(token)) {
|
||||
if (!string.IsNullOrEmpty(token))
|
||||
{
|
||||
token = parser.StripTokenQuotes(token).ToLowerInvariant(); //ANYTHING can be quoted...
|
||||
//path
|
||||
switch (token) {
|
||||
|
||||
switch (token)
|
||||
{
|
||||
case "path":
|
||||
parser.SkipWhitespace(true);
|
||||
path = parser.StripTokenQuotes(parser.ReadToken()).Replace("/", "\\");
|
||||
|
||||
if(string.IsNullOrEmpty(path)) {
|
||||
if(string.IsNullOrEmpty(path))
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected path to model, but got '" + token + "'");
|
||||
gotErrors = true;
|
||||
}
|
||||
|
@ -49,14 +60,16 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
//model index
|
||||
int index;
|
||||
token = parser.StripTokenQuotes(parser.ReadToken());
|
||||
if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out index)) {
|
||||
if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out index))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected model index, but got '" + token + "'");
|
||||
gotErrors = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if(index >= MAX_MODELS) {
|
||||
if(index >= MAX_MODELS)
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": GZDoom doesn't allow more than " + MAX_MODELS + " models per MODELDEF entry!");
|
||||
gotErrors = true;
|
||||
break;
|
||||
|
@ -66,18 +79,23 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
|
||||
//model path
|
||||
token = parser.StripTokenQuotes(parser.ReadToken()).ToLowerInvariant();
|
||||
if(string.IsNullOrEmpty(token)) {
|
||||
if(string.IsNullOrEmpty(token))
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected model name, but got '" + token + "'");
|
||||
gotErrors = true;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
//check extension
|
||||
string fileExt = Path.GetExtension(token);
|
||||
if(string.IsNullOrEmpty(fileExt)) {
|
||||
if(string.IsNullOrEmpty(fileExt))
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": model '" + token + "' won't be loaded. Models without extension are not supported by GZDoom.");
|
||||
gotErrors = true;
|
||||
break;
|
||||
}
|
||||
if(fileExt != ".md3" && fileExt != ".md2") {
|
||||
if(fileExt != ".md3" && fileExt != ".md2")
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": model '" + token + "' won't be loaded. Only MD2 and MD3 models are supported.");
|
||||
gotErrors = true;
|
||||
break;
|
||||
|
@ -94,14 +112,16 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
//skin index
|
||||
int skinIndex;
|
||||
token = parser.StripTokenQuotes(parser.ReadToken());
|
||||
if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out skinIndex)) {
|
||||
if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out skinIndex))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected skin index, but got '" + token + "'");
|
||||
gotErrors = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if(skinIndex >= MAX_MODELS) {
|
||||
if(skinIndex >= MAX_MODELS)
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": GZDoom doesn't allow more than " + MAX_MODELS + " skins per MODELDEF entry!");
|
||||
gotErrors = true;
|
||||
break;
|
||||
|
@ -111,16 +131,22 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
|
||||
//skin path
|
||||
token = parser.StripTokenQuotes(parser.ReadToken()).ToLowerInvariant();
|
||||
if(string.IsNullOrEmpty(token)) {
|
||||
if(string.IsNullOrEmpty(token))
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected skin name, but got '" + token + "'");
|
||||
gotErrors = true;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
//check extension
|
||||
string ext = Path.GetExtension(token);
|
||||
if(Array.IndexOf(TextureData.SUPPORTED_TEXTURE_EXTENSIONS, ext) == -1) {
|
||||
if(Array.IndexOf(TextureData.SUPPORTED_TEXTURE_EXTENSIONS, ext) == -1)
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": image format '" + ext + "' is not supported!");
|
||||
textureNames[skinIndex] = TextureData.INVALID_TEXTURE;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
//GZDoom allows skins with identical modelIndex, it uses the last one encountered
|
||||
textureNames[skinIndex] = Path.Combine(path, token);
|
||||
}
|
||||
|
@ -131,7 +157,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
parser.SkipWhitespace(true);
|
||||
|
||||
token = parser.StripTokenQuotes(parser.ReadToken());
|
||||
if(!parser.ReadSignedFloat(token, ref scale.X)) {
|
||||
if(!parser.ReadSignedFloat(token, ref scale.X))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected scale X value, but got '" + token + "'");
|
||||
gotErrors = true;
|
||||
|
@ -141,7 +168,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
parser.SkipWhitespace(true);
|
||||
|
||||
token = parser.StripTokenQuotes(parser.ReadToken());
|
||||
if(!parser.ReadSignedFloat(token, ref scale.Y)) {
|
||||
if(!parser.ReadSignedFloat(token, ref scale.Y))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected scale Y value, but got '" + token + "'");
|
||||
gotErrors = true;
|
||||
|
@ -151,7 +179,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
parser.SkipWhitespace(true);
|
||||
|
||||
token = parser.StripTokenQuotes(parser.ReadToken());
|
||||
if(!parser.ReadSignedFloat(token, ref scale.Z)) {
|
||||
if(!parser.ReadSignedFloat(token, ref scale.Z))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected scale Z value, but got '" + token + "'");
|
||||
gotErrors = true;
|
||||
|
@ -162,7 +191,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
parser.SkipWhitespace(true);
|
||||
|
||||
token = parser.StripTokenQuotes(parser.ReadToken());
|
||||
if(!parser.ReadSignedFloat(token, ref zOffset)) {
|
||||
if(!parser.ReadSignedFloat(token, ref zOffset))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected ZOffset value, but got '" + token + "'");
|
||||
gotErrors = true;
|
||||
|
@ -173,7 +203,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
parser.SkipWhitespace(true);
|
||||
|
||||
token = parser.StripTokenQuotes(parser.ReadToken());
|
||||
if(!parser.ReadSignedFloat(token, ref angleOffset)) {
|
||||
if(!parser.ReadSignedFloat(token, ref angleOffset))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected AngleOffset value, but got '" + token + "'");
|
||||
gotErrors = true;
|
||||
|
@ -184,7 +215,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
parser.SkipWhitespace(true);
|
||||
|
||||
token = parser.StripTokenQuotes(parser.ReadToken());
|
||||
if(!parser.ReadSignedFloat(token, ref pitchOffset)) {
|
||||
if(!parser.ReadSignedFloat(token, ref pitchOffset))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected PitchOffset value, but got '" + token + "'");
|
||||
gotErrors = true;
|
||||
|
@ -195,7 +227,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
parser.SkipWhitespace(true);
|
||||
|
||||
token = parser.StripTokenQuotes(parser.ReadToken());
|
||||
if(!parser.ReadSignedFloat(token, ref rollOffset)) {
|
||||
if(!parser.ReadSignedFloat(token, ref rollOffset))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected RollOffset value, but got '" + token + "'");
|
||||
gotErrors = true;
|
||||
|
@ -214,7 +247,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
case "frame":
|
||||
//parsed all required fields. if got more than one model - find which one(s) should be displayed
|
||||
int len = modelNames.GetLength(0);
|
||||
if(!gotErrors && len > 1) {
|
||||
if(!gotErrors && len > 1)
|
||||
{
|
||||
string spriteLump = null;
|
||||
string spriteFrame = null;
|
||||
bool[] modelsUsed = new bool[MAX_MODELS];
|
||||
|
@ -223,21 +257,28 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
parser.DataStream.Seek(-token.Length - 1, SeekOrigin.Current);
|
||||
|
||||
//here we check which models are used in first encountered lump and frame
|
||||
while(parser.SkipWhitespace(true)) {
|
||||
while(parser.SkipWhitespace(true))
|
||||
{
|
||||
token = parser.StripTokenQuotes(parser.ReadToken()).ToLowerInvariant();
|
||||
|
||||
if(token == "frameindex" || token == "frame") {
|
||||
if(token == "frameindex" || token == "frame")
|
||||
{
|
||||
bool frameIndex = (token == "frameindex");
|
||||
parser.SkipWhitespace(true);
|
||||
|
||||
//should be sprite lump
|
||||
token = parser.StripTokenQuotes(parser.ReadToken()).ToLowerInvariant();
|
||||
|
||||
if(string.IsNullOrEmpty(spriteLump)) {
|
||||
if(string.IsNullOrEmpty(spriteLump))
|
||||
{
|
||||
spriteLump = token;
|
||||
} else if(spriteLump != token) { //got another lump
|
||||
for(int i = 0; i < modelsUsed.Length; i++) {
|
||||
if(!modelsUsed[i]) {
|
||||
}
|
||||
else if(spriteLump != token) //got another lump
|
||||
{
|
||||
for(int i = 0; i < modelsUsed.Length; i++)
|
||||
{
|
||||
if(!modelsUsed[i])
|
||||
{
|
||||
modelNames[i] = null;
|
||||
textureNames[i] = null;
|
||||
}
|
||||
|
@ -250,11 +291,16 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
//should be sprite frame
|
||||
token = parser.StripTokenQuotes(parser.ReadToken()).ToLowerInvariant();
|
||||
|
||||
if(string.IsNullOrEmpty(spriteFrame)) {
|
||||
if(string.IsNullOrEmpty(spriteFrame))
|
||||
{
|
||||
spriteFrame = token;
|
||||
} else if(spriteFrame != token) { //got another frame
|
||||
for(int i = 0; i < modelsUsed.Length; i++) {
|
||||
if(!modelsUsed[i]) {
|
||||
}
|
||||
else if(spriteFrame != token) //got another frame
|
||||
{
|
||||
for(int i = 0; i < modelsUsed.Length; i++)
|
||||
{
|
||||
if(!modelsUsed[i])
|
||||
{
|
||||
modelNames[i] = null;
|
||||
textureNames[i] = null;
|
||||
}
|
||||
|
@ -268,20 +314,23 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
token = parser.StripTokenQuotes(parser.ReadToken());
|
||||
|
||||
int modelIndex;
|
||||
if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out modelIndex)) {
|
||||
if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out modelIndex))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected model index, but got '" + token + "'");
|
||||
gotErrors = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if(modelIndex >= MAX_MODELS) {
|
||||
if(modelIndex >= MAX_MODELS)
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": GZDoom doesn't allow more than " + MAX_MODELS + " models per MODELDEF entry!");
|
||||
gotErrors = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if(modelNames[modelIndex] == null) {
|
||||
if(modelNames[modelIndex] == null)
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": got model index, which doesn't correspond to any defined model!");
|
||||
gotErrors = true;
|
||||
break;
|
||||
|
@ -294,9 +343,11 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
//should be frame name or index. Currently I have no use for it
|
||||
token = parser.StripTokenQuotes(parser.ReadToken());
|
||||
|
||||
if(frameIndex) {
|
||||
if(frameIndex)
|
||||
{
|
||||
int frame;
|
||||
if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out frame)) {
|
||||
if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out frame))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected model frame, but got '" + token + "'");
|
||||
gotErrors = true;
|
||||
|
@ -304,7 +355,9 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
//must be "}", step back
|
||||
parser.DataStream.Seek(-token.Length - 1, SeekOrigin.Current);
|
||||
break;
|
||||
|
@ -318,7 +371,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
}
|
||||
|
||||
//find closing brace, then quit;
|
||||
while (parser.SkipWhitespace(true)) {
|
||||
while (parser.SkipWhitespace(true))
|
||||
{
|
||||
token = parser.ReadToken();
|
||||
if (token == "}") break;
|
||||
}
|
||||
|
@ -335,8 +389,10 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
mde.InheritActorPitch = inheritactorpitch;
|
||||
mde.InheritActorRoll = inheritactorroll;
|
||||
|
||||
for(int i = 0; i < modelNames.Length; i++) {
|
||||
if (!string.IsNullOrEmpty(modelNames[i])) {
|
||||
for(int i = 0; i < modelNames.Length; i++)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(modelNames[i]))
|
||||
{
|
||||
mde.TextureNames.Add(string.IsNullOrEmpty(textureNames[i]) ? textureNames[i] : textureNames[i].ToLowerInvariant());
|
||||
mde.ModelNames.Add(modelNames[i].ToLowerInvariant());
|
||||
}
|
||||
|
|
|
@ -1,39 +1,53 @@
|
|||
using System.IO;
|
||||
#region ================== Namespaces
|
||||
|
||||
using System.IO;
|
||||
using CodeImp.DoomBuilder.Config;
|
||||
using CodeImp.DoomBuilder.ZDoom;
|
||||
|
||||
#endregion
|
||||
|
||||
//mxd. Parser used to determine which script type given text is.
|
||||
namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
||||
internal sealed class ScriptTypeParserSE :ZDTextParser {
|
||||
namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
||||
{
|
||||
internal sealed class ScriptTypeParserSE :ZDTextParser
|
||||
{
|
||||
private ScriptType scriptType;
|
||||
internal ScriptType ScriptType { get { return scriptType; } }
|
||||
|
||||
internal ScriptTypeParserSE() {
|
||||
internal ScriptTypeParserSE()
|
||||
{
|
||||
scriptType = ScriptType.UNKNOWN;
|
||||
}
|
||||
|
||||
public override bool Parse(Stream stream, string sourcefilename) {
|
||||
public override bool Parse(Stream stream, string sourcefilename)
|
||||
{
|
||||
base.Parse(stream, sourcefilename);
|
||||
|
||||
// Continue until at the end of the stream
|
||||
while (SkipWhitespace(true)) {
|
||||
while (SkipWhitespace(true))
|
||||
{
|
||||
string token = ReadToken();
|
||||
|
||||
if (!string.IsNullOrEmpty(token)) {
|
||||
if (!string.IsNullOrEmpty(token))
|
||||
{
|
||||
token = token.ToUpperInvariant();
|
||||
|
||||
if (token == "MODEL") {
|
||||
if (token == "MODEL")
|
||||
{
|
||||
SkipWhitespace(true);
|
||||
ReadToken(); //should be model name
|
||||
SkipWhitespace(true);
|
||||
token = ReadToken();//should be opening brace
|
||||
|
||||
if (token == "{") {
|
||||
if (token == "{")
|
||||
{
|
||||
scriptType = ScriptType.MODELDEF;
|
||||
return true;
|
||||
}
|
||||
|
||||
}else if(token == "SCRIPT"){
|
||||
}
|
||||
else if(token == "SCRIPT")
|
||||
{
|
||||
SkipWhitespace(true);
|
||||
ReadToken(); //should be script name or number
|
||||
SkipWhitespace(true);
|
||||
|
@ -41,19 +55,23 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
SkipWhitespace(true);
|
||||
token = ReadToken(); //should be opening brace
|
||||
|
||||
if (token == "{") {
|
||||
if (token == "{")
|
||||
{
|
||||
scriptType = ScriptType.ACS;
|
||||
return true;
|
||||
}
|
||||
|
||||
}else if(token == "ACTOR"){
|
||||
}
|
||||
else if(token == "ACTOR")
|
||||
{
|
||||
SkipWhitespace(true);
|
||||
ReadToken(); //should be actor name
|
||||
|
||||
SkipWhitespace(true);
|
||||
token = ReadToken();
|
||||
|
||||
if (token == ":" || token == "{" || token == "REPLACES") {
|
||||
if (token == ":" || token == "{" || token == "REPLACES")
|
||||
{
|
||||
scriptType = ScriptType.DECORATE;
|
||||
return true;
|
||||
}
|
||||
|
@ -61,7 +79,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|||
SkipWhitespace(true);
|
||||
token = ReadToken(); //should be actor name
|
||||
|
||||
if (token == "{") {
|
||||
if (token == "{")
|
||||
{
|
||||
scriptType = ScriptType.DECORATE;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
using System;
|
||||
using CodeImp.DoomBuilder.Geometry;
|
||||
|
||||
namespace CodeImp.DoomBuilder.GZBuilder.Geometry {
|
||||
namespace CodeImp.DoomBuilder.GZBuilder.Geometry
|
||||
{
|
||||
public enum Line3DType
|
||||
{
|
||||
DEFAULT,
|
||||
ACTIVATOR,
|
||||
}
|
||||
|
||||
public class Line3D {
|
||||
public class Line3D
|
||||
{
|
||||
// Coordinates
|
||||
public Vector3D v1;
|
||||
public Vector3D v2;
|
||||
|
@ -16,13 +18,15 @@ namespace CodeImp.DoomBuilder.GZBuilder.Geometry {
|
|||
private Line3DType lineType;
|
||||
|
||||
// Constructors
|
||||
public Line3D(Vector3D v1, Vector3D v2) {
|
||||
public Line3D(Vector3D v1, Vector3D v2)
|
||||
{
|
||||
this.v1 = v1;
|
||||
this.v2 = v2;
|
||||
this.lineType = Line3DType.DEFAULT;
|
||||
}
|
||||
|
||||
public Line3D(Vector3D v1, Vector3D v2, Line3DType lineType) {
|
||||
public Line3D(Vector3D v1, Vector3D v2, Line3DType lineType)
|
||||
{
|
||||
this.v1 = v1;
|
||||
this.v2 = v2;
|
||||
this.lineType = lineType;
|
||||
|
@ -31,7 +35,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.Geometry {
|
|||
public Vector3D GetDelta() { return v2 - v1; }
|
||||
|
||||
// This calculates the angle
|
||||
public float GetAngle() {
|
||||
public float GetAngle()
|
||||
{
|
||||
// Calculate and return the angle
|
||||
Vector2D d = GetDelta();
|
||||
return -(float)Math.Atan2(-d.y, d.x) + Angle2D.PIHALF;//mxd // (float)Math.PI * 0.5f;
|
||||
|
|
|
@ -8,88 +8,111 @@ namespace CodeImp.DoomBuilder.GZBuilder.Tools
|
|||
public static class UDMFTools
|
||||
{
|
||||
//float
|
||||
public static void SetFloat(UniFields fields, string key, float value) {
|
||||
public static void SetFloat(UniFields fields, string key, float value)
|
||||
{
|
||||
SetFloat(fields, key, value, 0f);
|
||||
}
|
||||
|
||||
public static void SetFloat(UniFields fields, string key, float value, float defaultValue) {
|
||||
public static void SetFloat(UniFields fields, string key, float value, float defaultValue)
|
||||
{
|
||||
if(fields == null) return;
|
||||
|
||||
if(value != defaultValue) {
|
||||
if(value != defaultValue)
|
||||
{
|
||||
if(!fields.ContainsKey(key))
|
||||
fields.Add(key, new UniValue(UniversalType.Float, value));
|
||||
else
|
||||
fields[key].Value = value;
|
||||
} else if(fields.ContainsKey(key)) { //don't save default value
|
||||
}
|
||||
else if(fields.ContainsKey(key)) //don't save default value
|
||||
{
|
||||
fields.Remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
public static float GetFloat(UniFields fields, string key) {
|
||||
public static float GetFloat(UniFields fields, string key)
|
||||
{
|
||||
return GetFloat(fields, key, 0f);
|
||||
}
|
||||
|
||||
public static float GetFloat(UniFields fields, string key, float defaultValue) {
|
||||
public static float GetFloat(UniFields fields, string key, float defaultValue)
|
||||
{
|
||||
if(fields == null) return defaultValue;
|
||||
return fields.GetValue(key, defaultValue);
|
||||
}
|
||||
|
||||
//int
|
||||
public static void SetInteger(UniFields fields, string key, int value) {
|
||||
public static void SetInteger(UniFields fields, string key, int value)
|
||||
{
|
||||
SetInteger(fields, key, value, 0);
|
||||
}
|
||||
|
||||
public static void SetInteger(UniFields fields, string key, int value, int defaultValue) {
|
||||
public static void SetInteger(UniFields fields, string key, int value, int defaultValue)
|
||||
{
|
||||
if(fields == null) return;
|
||||
|
||||
if(value != defaultValue) {
|
||||
if(value != defaultValue)
|
||||
{
|
||||
if(!fields.ContainsKey(key))
|
||||
fields.Add(key, new UniValue(UniversalType.Integer, value));
|
||||
else
|
||||
fields[key].Value = value;
|
||||
} else if(fields.ContainsKey(key)) { //don't save default value
|
||||
}
|
||||
else if(fields.ContainsKey(key)) //don't save default value
|
||||
{
|
||||
fields.Remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
public static int GetInteger(UniFields fields, string key) {
|
||||
public static int GetInteger(UniFields fields, string key)
|
||||
{
|
||||
return GetInteger(fields, key, 0);
|
||||
}
|
||||
|
||||
public static int GetInteger(UniFields fields, string key, int defaultValue) {
|
||||
public static int GetInteger(UniFields fields, string key, int defaultValue)
|
||||
{
|
||||
if(fields == null) return defaultValue;
|
||||
return fields.GetValue(key, defaultValue);
|
||||
}
|
||||
|
||||
public static void SetString(UniFields fields, string key, string value, string defaultValue) {
|
||||
public static void SetString(UniFields fields, string key, string value, string defaultValue)
|
||||
{
|
||||
if(fields == null) return;
|
||||
|
||||
if(value != defaultValue) {
|
||||
if(value != defaultValue)
|
||||
{
|
||||
if(!fields.ContainsKey(key))
|
||||
fields.Add(key, new UniValue(UniversalType.String, value));
|
||||
else
|
||||
fields[key].Value = value;
|
||||
} else if(fields.ContainsKey(key)) { //don't save default value
|
||||
}
|
||||
else if(fields.ContainsKey(key)) //don't save default value
|
||||
{
|
||||
fields.Remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ClearFields(UniFields fields, string[] keys) {
|
||||
public static void ClearFields(UniFields fields, string[] keys)
|
||||
{
|
||||
if(fields == null) return;
|
||||
|
||||
foreach(string key in keys){
|
||||
foreach(string key in keys)
|
||||
{
|
||||
if(fields.ContainsKey(key)) fields.Remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ClearField(UniFields fields, string key) {
|
||||
public static void ClearField(UniFields fields, string key)
|
||||
{
|
||||
if(fields == null || !fields.ContainsKey(key)) return;
|
||||
fields.Remove(key);
|
||||
}
|
||||
|
||||
public static bool FieldsMatch(UniFields fields1, UniFields fields2) {
|
||||
public static bool FieldsMatch(UniFields fields1, UniFields fields2)
|
||||
{
|
||||
if (fields1.Keys.Count != fields2.Keys.Count) return false;
|
||||
foreach(KeyValuePair<string, UniValue> group in fields1) {
|
||||
foreach(KeyValuePair<string, UniValue> group in fields1)
|
||||
{
|
||||
if (!fields2.ContainsKey(group.Key)) return false;
|
||||
if (fields2[group.Key].Type != fields1[group.Key].Type) return false;
|
||||
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
using System;
|
||||
#region ================== Namespaces
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
using System.Threading;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace CodeImp.DoomBuilder.GZBuilder.Windows
|
||||
{
|
||||
public partial class ExceptionDialog : Form
|
||||
|
@ -10,33 +14,38 @@ namespace CodeImp.DoomBuilder.GZBuilder.Windows
|
|||
private readonly bool cannotContinue;
|
||||
private readonly string logPath;
|
||||
|
||||
public ExceptionDialog(UnhandledExceptionEventArgs e) {
|
||||
public ExceptionDialog(UnhandledExceptionEventArgs e)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
logPath = Path.Combine(General.SettingsPath, @"GZCrash.txt");
|
||||
Exception ex = (Exception)e.ExceptionObject;
|
||||
errorDescription.Text = "Error in " + ex.Source + ":";
|
||||
using(StreamWriter sw = File.CreateText(logPath)) {
|
||||
sw.Write(getExceptionDescription(ex));
|
||||
using(StreamWriter sw = File.CreateText(logPath))
|
||||
{
|
||||
sw.Write(GetExceptionDescription(ex));
|
||||
}
|
||||
|
||||
errorMessage.Text = ex.Message + Environment.NewLine + ex.StackTrace;
|
||||
cannotContinue = true; //cannot recover from this...
|
||||
}
|
||||
|
||||
public ExceptionDialog(ThreadExceptionEventArgs e) {
|
||||
public ExceptionDialog(ThreadExceptionEventArgs e)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
logPath = Path.Combine(General.SettingsPath, @"GZCrash.txt");
|
||||
errorDescription.Text = "Error in " + e.Exception.Source + ":";
|
||||
using(StreamWriter sw = File.CreateText(logPath)) {
|
||||
sw.Write(getExceptionDescription(e.Exception));
|
||||
using(StreamWriter sw = File.CreateText(logPath))
|
||||
{
|
||||
sw.Write(GetExceptionDescription(e.Exception));
|
||||
}
|
||||
|
||||
errorMessage.Text = e.Exception.Message + Environment.NewLine + e.Exception.StackTrace;
|
||||
}
|
||||
|
||||
public void Setup() {
|
||||
public void Setup()
|
||||
{
|
||||
bContinue.Enabled = !cannotContinue;
|
||||
|
||||
string[] titles = {
|
||||
|
@ -107,18 +116,21 @@ namespace CodeImp.DoomBuilder.GZBuilder.Windows
|
|||
this.Text = titles[new Random().Next(0, titles.Length - 1)];
|
||||
}
|
||||
|
||||
private string getExceptionDescription(Exception ex) {
|
||||
private static string GetExceptionDescription(Exception ex)
|
||||
{
|
||||
//add to error logger
|
||||
General.ErrorLogger.Add(ErrorType.Error, "**** " + ex.Source + ": " + ex.Message + " ****");
|
||||
|
||||
string message = "********EXCEPTION DETAILS********"
|
||||
+ Environment.NewLine + ex.Source + ": " + ex.Message + Environment.NewLine + ex.StackTrace;
|
||||
|
||||
if(File.Exists(General.LogFile)) {
|
||||
try {
|
||||
if(File.Exists(General.LogFile))
|
||||
{
|
||||
try
|
||||
{
|
||||
string[] lines = File.ReadAllLines(General.LogFile);
|
||||
message += Environment.NewLine + Environment.NewLine + "***********ACTIONS LOG***********";
|
||||
for(int i = lines.Length - 1; i > -1; i--)
|
||||
for(int i = lines.Length - 1; i > -1; i--)
|
||||
message += Environment.NewLine + lines[i];
|
||||
} catch(Exception) { }
|
||||
}
|
||||
|
@ -126,28 +138,35 @@ namespace CodeImp.DoomBuilder.GZBuilder.Windows
|
|||
return message;
|
||||
}
|
||||
|
||||
private void reportLink_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) {
|
||||
private void reportLink_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
||||
{
|
||||
if(!File.Exists(logPath)) return;
|
||||
System.Diagnostics.Process.Start("explorer.exe", @"/select, " + logPath);
|
||||
reportLink.LinkVisited = true;
|
||||
}
|
||||
|
||||
private void threadLink_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) {
|
||||
try {
|
||||
private void threadLink_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
System.Diagnostics.Process.Start("http://forum.zdoom.org/viewtopic.php?f=3&t=32392&start=9999999");
|
||||
} catch(Exception) {
|
||||
}
|
||||
catch(Exception)
|
||||
{
|
||||
MessageBox.Show("Unable to open URL...");
|
||||
}
|
||||
|
||||
threadLink.LinkVisited = true;
|
||||
}
|
||||
|
||||
private void bContinue_Click(object sender, EventArgs e) {
|
||||
private void bContinue_Click(object sender, EventArgs e)
|
||||
{
|
||||
this.DialogResult = DialogResult.OK;
|
||||
this.Close();
|
||||
}
|
||||
|
||||
private void bToClipboard_Click(object sender, EventArgs e) {
|
||||
private void bToClipboard_Click(object sender, EventArgs e)
|
||||
{
|
||||
errorMessage.SelectAll();
|
||||
errorMessage.Copy();
|
||||
errorMessage.DeselectAll();
|
||||
|
|
|
@ -11,8 +11,10 @@
|
|||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing) {
|
||||
if(disposing && (components != null)) {
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if(disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
|
@ -24,7 +26,8 @@
|
|||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent() {
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.bQuit = new System.Windows.Forms.Button();
|
||||
this.bContinue = new System.Windows.Forms.Button();
|
||||
this.errorMessage = new System.Windows.Forms.TextBox();
|
||||
|
|
|
@ -11,8 +11,10 @@
|
|||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing) {
|
||||
if(disposing && (components != null)) {
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if(disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
|
@ -24,7 +26,8 @@
|
|||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent() {
|
||||
private void InitializeComponent()
|
||||
{
|
||||
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle();
|
||||
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle2 = new System.Windows.Forms.DataGridViewCellStyle();
|
||||
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle3 = new System.Windows.Forms.DataGridViewCellStyle();
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
using System;
|
||||
#region ================== Namespaces
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
|
@ -8,27 +10,38 @@ using CodeImp.DoomBuilder.Geometry;
|
|||
using CodeImp.DoomBuilder.Editing;
|
||||
using CodeImp.DoomBuilder.Windows;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace CodeImp.DoomBuilder.GZBuilder.Windows
|
||||
{
|
||||
public partial class TagStatisticsForm : DelayedForm
|
||||
{
|
||||
private static Size size = Size.Empty;
|
||||
private static Point location = Point.Empty;
|
||||
|
||||
public TagStatisticsForm() {
|
||||
|
||||
#region ================== Constructor
|
||||
|
||||
public TagStatisticsForm()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
//apply window size and location
|
||||
if(!size.IsEmpty && !location.IsEmpty){
|
||||
if(!size.IsEmpty && !location.IsEmpty)
|
||||
{
|
||||
this.StartPosition = FormStartPosition.Manual;
|
||||
this.Size = size;
|
||||
this.Location = location;
|
||||
}
|
||||
|
||||
setup();
|
||||
Setup();
|
||||
}
|
||||
|
||||
private void setup() {
|
||||
#endregion
|
||||
|
||||
#region ================== Methods
|
||||
|
||||
private void Setup()
|
||||
{
|
||||
//collect all tags
|
||||
List<int> tags = new List<int>();
|
||||
Dictionary<int, int> sectorsCountByTag = new Dictionary<int, int>();
|
||||
|
@ -36,7 +49,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.Windows
|
|||
Dictionary<int, int> thingsCountByTag = new Dictionary<int, int>();
|
||||
|
||||
//collect used tags from sectors...
|
||||
foreach(Sector s in General.Map.Map.Sectors) {
|
||||
foreach(Sector s in General.Map.Map.Sectors)
|
||||
{
|
||||
if(s.Tag == 0) continue;
|
||||
if(!tags.Contains(s.Tag)) tags.Add(s.Tag);
|
||||
|
||||
|
@ -47,8 +61,10 @@ namespace CodeImp.DoomBuilder.GZBuilder.Windows
|
|||
}
|
||||
|
||||
//...and linedefs...
|
||||
if(General.Map.FormatInterface.HasLinedefTag) {
|
||||
foreach(Linedef l in General.Map.Map.Linedefs) {
|
||||
if(General.Map.FormatInterface.HasLinedefTag)
|
||||
{
|
||||
foreach(Linedef l in General.Map.Map.Linedefs)
|
||||
{
|
||||
if(l.Tag == 0) continue;
|
||||
if(!tags.Contains(l.Tag)) tags.Add(l.Tag);
|
||||
|
||||
|
@ -57,13 +73,17 @@ namespace CodeImp.DoomBuilder.GZBuilder.Windows
|
|||
else
|
||||
linedefsCountByTag[l.Tag] += 1;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
Linedefs.Visible = false;
|
||||
}
|
||||
|
||||
//...and things...
|
||||
if(General.Map.FormatInterface.HasThingTag) {
|
||||
foreach(Thing t in General.Map.Map.Things) {
|
||||
if(General.Map.FormatInterface.HasThingTag)
|
||||
{
|
||||
foreach(Thing t in General.Map.Map.Things)
|
||||
{
|
||||
if(t.Tag == 0) continue;
|
||||
if(!tags.Contains(t.Tag)) tags.Add(t.Tag);
|
||||
|
||||
|
@ -72,14 +92,17 @@ namespace CodeImp.DoomBuilder.GZBuilder.Windows
|
|||
else
|
||||
thingsCountByTag[t.Tag] += 1;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
Things.Visible = false;
|
||||
}
|
||||
|
||||
//create rows
|
||||
dataGridView.Rows.Clear();
|
||||
foreach(int tag in tags) {
|
||||
addRow(tag,
|
||||
foreach(int tag in tags)
|
||||
{
|
||||
AddRow(tag,
|
||||
General.Map.Options.TagLabels.ContainsKey(tag) ? General.Map.Options.TagLabels[tag] : string.Empty,
|
||||
sectorsCountByTag.ContainsKey(tag) ? sectorsCountByTag[tag] : 0,
|
||||
linedefsCountByTag.ContainsKey(tag) ? linedefsCountByTag[tag] : 0,
|
||||
|
@ -89,7 +112,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.Windows
|
|||
dataGridView.Sort(TagColumn, ListSortDirection.Ascending);
|
||||
}
|
||||
|
||||
private void addRow(int tag, string label, int sectorsCount, int linesCount, int thingsCount) {
|
||||
private void AddRow(int tag, string label, int sectorsCount, int linesCount, int thingsCount)
|
||||
{
|
||||
DataGridViewRow row = new DataGridViewRow();
|
||||
|
||||
row.Cells.Add(new DataGridViewTextBoxCell { Value = tag });
|
||||
|
@ -101,10 +125,13 @@ namespace CodeImp.DoomBuilder.GZBuilder.Windows
|
|||
dataGridView.Rows.Add(row);
|
||||
}
|
||||
|
||||
private static List<Sector> getSectorsWithTag(int tag, int count) {
|
||||
private static List<Sector> GetSectorsWithTag(int tag, int count)
|
||||
{
|
||||
List<Sector> list = new List<Sector>();
|
||||
foreach(Sector s in General.Map.Map.Sectors) {
|
||||
if(s.Tag == tag) {
|
||||
foreach(Sector s in General.Map.Map.Sectors)
|
||||
{
|
||||
if(s.Tag == tag)
|
||||
{
|
||||
list.Add(s);
|
||||
if(list.Count == count) break;
|
||||
}
|
||||
|
@ -113,10 +140,13 @@ namespace CodeImp.DoomBuilder.GZBuilder.Windows
|
|||
return list;
|
||||
}
|
||||
|
||||
private static List<Linedef> getLinedefsWithTag(int tag, int count) {
|
||||
private static List<Linedef> GetLinedefsWithTag(int tag, int count)
|
||||
{
|
||||
List<Linedef> list = new List<Linedef>();
|
||||
foreach(Linedef l in General.Map.Map.Linedefs) {
|
||||
if(l.Tag == tag) {
|
||||
foreach(Linedef l in General.Map.Map.Linedefs)
|
||||
{
|
||||
if(l.Tag == tag)
|
||||
{
|
||||
list.Add(l);
|
||||
if(list.Count == count) break;
|
||||
}
|
||||
|
@ -125,10 +155,13 @@ namespace CodeImp.DoomBuilder.GZBuilder.Windows
|
|||
return list;
|
||||
}
|
||||
|
||||
private static List<Thing> getThingsWithTag(int tag, int count) {
|
||||
private static List<Thing> GetThingsWithTag(int tag, int count)
|
||||
{
|
||||
List<Thing> list = new List<Thing>();
|
||||
foreach(Thing t in General.Map.Map.Things) {
|
||||
if(t.Tag == tag) {
|
||||
foreach(Thing t in General.Map.Map.Things)
|
||||
{
|
||||
if(t.Tag == tag)
|
||||
{
|
||||
list.Add(t);
|
||||
if(list.Count == count) break;
|
||||
}
|
||||
|
@ -137,18 +170,22 @@ namespace CodeImp.DoomBuilder.GZBuilder.Windows
|
|||
return list;
|
||||
}
|
||||
|
||||
private static void showSelection(List<Vector2D> points) {
|
||||
private static void ShowSelection(List<Vector2D> points)
|
||||
{
|
||||
RectangleF area = MapSet.CreateEmptyArea();
|
||||
|
||||
// Make a view area from the points
|
||||
foreach(Vector2D p in points) area = MapSet.IncreaseArea(area, p);
|
||||
|
||||
// Make the area square, using the largest side
|
||||
if(area.Width > area.Height) {
|
||||
if(area.Width > area.Height)
|
||||
{
|
||||
float delta = area.Width - area.Height;
|
||||
area.Y -= delta * 0.5f;
|
||||
area.Height += delta;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
float delta = area.Height - area.Width;
|
||||
area.X -= delta * 0.5f;
|
||||
area.Width += delta;
|
||||
|
@ -158,17 +195,25 @@ namespace CodeImp.DoomBuilder.GZBuilder.Windows
|
|||
area.Inflate(100f, 100f);
|
||||
|
||||
// Zoom to area
|
||||
ClassicMode editmode = (General.Editing.Mode as ClassicMode);
|
||||
editmode.CenterOnArea(area, 0.6f);
|
||||
if (General.Editing.Mode is ClassicMode)
|
||||
{
|
||||
ClassicMode editmode = (General.Editing.Mode as ClassicMode);
|
||||
editmode.CenterOnArea(area, 0.6f);
|
||||
}
|
||||
}
|
||||
|
||||
//events
|
||||
private void apply_Click(object sender, EventArgs e) {
|
||||
#endregion
|
||||
|
||||
#region ================== Events
|
||||
|
||||
private void apply_Click(object sender, EventArgs e)
|
||||
{
|
||||
//refill TagLabels with table data
|
||||
dataGridView.Sort(TagColumn, ListSortDirection.Ascending);
|
||||
General.Map.Options.TagLabels.Clear();
|
||||
|
||||
foreach(DataGridViewRow row in dataGridView.Rows) {
|
||||
foreach(DataGridViewRow row in dataGridView.Rows)
|
||||
{
|
||||
string label = row.Cells[1].Value.ToString();
|
||||
if(!string.IsNullOrEmpty(label))
|
||||
General.Map.Options.TagLabels.Add((int)row.Cells[0].Value, label);
|
||||
|
@ -177,20 +222,25 @@ namespace CodeImp.DoomBuilder.GZBuilder.Windows
|
|||
this.Close();
|
||||
}
|
||||
|
||||
private void cancel_Click(object sender, EventArgs e) {
|
||||
private void cancel_Click(object sender, EventArgs e)
|
||||
{
|
||||
this.Close();
|
||||
}
|
||||
|
||||
private void dataGridView_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e) {
|
||||
private void dataGridView_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
|
||||
{
|
||||
if(e.ColumnIndex < 2 || e.RowIndex == -1) return;
|
||||
|
||||
//select
|
||||
if (e.Button == MouseButtons.Left) {
|
||||
if (e.Button == MouseButtons.Left)
|
||||
{
|
||||
int tag = (int)dataGridView.Rows[e.RowIndex].Cells[0].Value;
|
||||
|
||||
if(e.ColumnIndex == 2) { //sectors
|
||||
List<Sector> list = getSectorsWithTag(tag, (int)dataGridView.Rows[e.RowIndex].Cells[2].Value);
|
||||
if(list.Count > 0) {
|
||||
if(e.ColumnIndex == 2) //sectors
|
||||
{
|
||||
List<Sector> list = GetSectorsWithTag(tag, (int)dataGridView.Rows[e.RowIndex].Cells[2].Value);
|
||||
if(list.Count > 0)
|
||||
{
|
||||
General.Map.Map.ClearSelectedSectors();
|
||||
General.Map.Map.ClearSelectedLinedefs();
|
||||
|
||||
|
@ -198,25 +248,31 @@ namespace CodeImp.DoomBuilder.GZBuilder.Windows
|
|||
General.Editing.ChangeMode("SectorsMode");
|
||||
ClassicMode mode = (ClassicMode)General.Editing.Mode;
|
||||
|
||||
foreach(Sector s in list) {
|
||||
foreach(Sector s in list)
|
||||
{
|
||||
mode.SelectMapElement(s);
|
||||
|
||||
foreach(Sidedef sd in s.Sidedefs) {
|
||||
foreach(Sidedef sd in s.Sidedefs)
|
||||
{
|
||||
points.Add(sd.Line.Start.Position);
|
||||
points.Add(sd.Line.End.Position);
|
||||
}
|
||||
}
|
||||
|
||||
showSelection(points);
|
||||
ShowSelection(points);
|
||||
}
|
||||
} else if(e.ColumnIndex == 3) { //linedefs
|
||||
List<Linedef> list = getLinedefsWithTag(tag, (int)dataGridView.Rows[e.RowIndex].Cells[3].Value);
|
||||
if(list.Count > 0) {
|
||||
}
|
||||
else if(e.ColumnIndex == 3) //linedefs
|
||||
{
|
||||
List<Linedef> list = GetLinedefsWithTag(tag, (int)dataGridView.Rows[e.RowIndex].Cells[3].Value);
|
||||
if(list.Count > 0)
|
||||
{
|
||||
General.Map.Map.ClearSelectedSectors();
|
||||
General.Map.Map.ClearSelectedLinedefs();
|
||||
|
||||
List<Vector2D> points = new List<Vector2D>();
|
||||
foreach(Linedef l in list) {
|
||||
foreach(Linedef l in list)
|
||||
{
|
||||
l.Selected = true;
|
||||
points.Add(l.Start.Position);
|
||||
points.Add(l.End.Position);
|
||||
|
@ -224,15 +280,19 @@ namespace CodeImp.DoomBuilder.GZBuilder.Windows
|
|||
|
||||
General.Map.Map.Update();
|
||||
General.Editing.ChangeMode("LinedefsMode");
|
||||
showSelection(points);
|
||||
ShowSelection(points);
|
||||
}
|
||||
} else if(e.ColumnIndex == 4) { //things
|
||||
List<Thing> list = getThingsWithTag(tag, (int)dataGridView.Rows[e.RowIndex].Cells[4].Value);
|
||||
if(list.Count > 0) {
|
||||
}
|
||||
else if(e.ColumnIndex == 4) //things
|
||||
{
|
||||
List<Thing> list = GetThingsWithTag(tag, (int)dataGridView.Rows[e.RowIndex].Cells[4].Value);
|
||||
if(list.Count > 0)
|
||||
{
|
||||
General.Map.Map.ClearSelectedThings();
|
||||
|
||||
List<Vector2D> points = new List<Vector2D>();
|
||||
foreach(Thing t in list) {
|
||||
foreach(Thing t in list)
|
||||
{
|
||||
t.Selected = true;
|
||||
|
||||
Vector2D p = t.Position;
|
||||
|
@ -245,55 +305,70 @@ namespace CodeImp.DoomBuilder.GZBuilder.Windows
|
|||
|
||||
General.Map.Map.Update();
|
||||
General.Editing.ChangeMode("ThingsMode");
|
||||
showSelection(points);
|
||||
ShowSelection(points);
|
||||
}
|
||||
}
|
||||
|
||||
//open properties window
|
||||
} else if(e.Button == MouseButtons.Right) {
|
||||
|
||||
}
|
||||
else if(e.Button == MouseButtons.Right) //open properties window
|
||||
{
|
||||
dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Selected = true;
|
||||
int tag = (int)dataGridView.Rows[e.RowIndex].Cells[0].Value;
|
||||
|
||||
if(e.ColumnIndex == 2) { //sectors
|
||||
List<Sector> list = getSectorsWithTag(tag, (int)dataGridView.Rows[e.RowIndex].Cells[2].Value);
|
||||
if(list.Count > 0) {
|
||||
if(e.ColumnIndex == 2) //sectors
|
||||
{
|
||||
List<Sector> list = GetSectorsWithTag(tag, (int)dataGridView.Rows[e.RowIndex].Cells[2].Value);
|
||||
if(list.Count > 0)
|
||||
{
|
||||
General.MainWindow.ShowEditSectors(list);
|
||||
General.Map.Map.Update();
|
||||
setup();
|
||||
Setup();
|
||||
}
|
||||
} else if(e.ColumnIndex == 3) { //linedefs
|
||||
List<Linedef> list = getLinedefsWithTag(tag, (int)dataGridView.Rows[e.RowIndex].Cells[3].Value);
|
||||
if(list.Count > 0) {
|
||||
}
|
||||
else if(e.ColumnIndex == 3) //linedefs
|
||||
{
|
||||
List<Linedef> list = GetLinedefsWithTag(tag, (int)dataGridView.Rows[e.RowIndex].Cells[3].Value);
|
||||
if(list.Count > 0)
|
||||
{
|
||||
General.MainWindow.ShowEditLinedefs(list);
|
||||
General.Map.Map.Update();
|
||||
setup();
|
||||
Setup();
|
||||
}
|
||||
} else if(e.ColumnIndex == 4) { //things
|
||||
List<Thing> list = getThingsWithTag(tag, (int)dataGridView.Rows[e.RowIndex].Cells[4].Value);
|
||||
if(list.Count > 0) {
|
||||
}
|
||||
else if(e.ColumnIndex == 4) //things
|
||||
{
|
||||
List<Thing> list = GetThingsWithTag(tag, (int)dataGridView.Rows[e.RowIndex].Cells[4].Value);
|
||||
if(list.Count > 0)
|
||||
{
|
||||
General.MainWindow.ShowEditThings(list);
|
||||
General.Map.Map.Update();
|
||||
setup();
|
||||
Setup();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void dataGridView_CellMouseDoubleClick(object sender, DataGridViewCellMouseEventArgs e) {
|
||||
private void dataGridView_CellMouseDoubleClick(object sender, DataGridViewCellMouseEventArgs e)
|
||||
{
|
||||
if(e.ColumnIndex < 2 || e.RowIndex == -1) return;
|
||||
int tag = (int)dataGridView.Rows[e.RowIndex].Cells[0].Value;
|
||||
|
||||
if(e.ColumnIndex == 2) { //sectors
|
||||
List<Sector> list = getSectorsWithTag(tag, (int)dataGridView.Rows[e.RowIndex].Cells[2].Value);
|
||||
if(list.Count > 0) {
|
||||
if(e.ColumnIndex == 2) //sectors
|
||||
{
|
||||
List<Sector> list = GetSectorsWithTag(tag, (int)dataGridView.Rows[e.RowIndex].Cells[2].Value);
|
||||
if(list.Count > 0)
|
||||
{
|
||||
General.Map.Map.ClearSelectedSectors();
|
||||
General.Map.Map.ClearSelectedLinedefs();
|
||||
|
||||
List<Vector2D> points = new List<Vector2D>();
|
||||
foreach(Sector s in list) {
|
||||
foreach(Sector s in list)
|
||||
{
|
||||
s.Selected = true;
|
||||
|
||||
foreach(Sidedef sd in s.Sidedefs) {
|
||||
foreach(Sidedef sd in s.Sidedefs)
|
||||
{
|
||||
points.Add(sd.Line.Start.Position);
|
||||
points.Add(sd.Line.End.Position);
|
||||
}
|
||||
|
@ -301,16 +376,20 @@ namespace CodeImp.DoomBuilder.GZBuilder.Windows
|
|||
|
||||
General.Map.Map.Update();
|
||||
General.Editing.ChangeMode("SectorsMode");
|
||||
showSelection(points);
|
||||
ShowSelection(points);
|
||||
}
|
||||
} else if(e.ColumnIndex == 3) { //linedefs
|
||||
List<Linedef> list = getLinedefsWithTag(tag, (int)dataGridView.Rows[e.RowIndex].Cells[3].Value);
|
||||
if(list.Count > 0) {
|
||||
}
|
||||
else if(e.ColumnIndex == 3) //linedefs
|
||||
{
|
||||
List<Linedef> list = GetLinedefsWithTag(tag, (int)dataGridView.Rows[e.RowIndex].Cells[3].Value);
|
||||
if(list.Count > 0)
|
||||
{
|
||||
General.Map.Map.ClearSelectedSectors();
|
||||
General.Map.Map.ClearSelectedLinedefs();
|
||||
|
||||
List<Vector2D> points = new List<Vector2D>();
|
||||
foreach(Linedef l in list) {
|
||||
foreach(Linedef l in list)
|
||||
{
|
||||
l.Selected = true;
|
||||
points.Add(l.Start.Position);
|
||||
points.Add(l.End.Position);
|
||||
|
@ -318,15 +397,19 @@ namespace CodeImp.DoomBuilder.GZBuilder.Windows
|
|||
|
||||
General.Map.Map.Update();
|
||||
General.Editing.ChangeMode("LinedefsMode");
|
||||
showSelection(points);
|
||||
ShowSelection(points);
|
||||
}
|
||||
} else if(e.ColumnIndex == 4) { //things
|
||||
List<Thing> list = getThingsWithTag(tag, (int)dataGridView.Rows[e.RowIndex].Cells[4].Value);
|
||||
if(list.Count > 0) {
|
||||
}
|
||||
else if(e.ColumnIndex == 4) //things
|
||||
{
|
||||
List<Thing> list = GetThingsWithTag(tag, (int)dataGridView.Rows[e.RowIndex].Cells[4].Value);
|
||||
if(list.Count > 0)
|
||||
{
|
||||
General.Map.Map.ClearSelectedThings();
|
||||
|
||||
List<Vector2D> points = new List<Vector2D>();
|
||||
foreach(Thing t in list) {
|
||||
foreach(Thing t in list)
|
||||
{
|
||||
t.Selected = true;
|
||||
|
||||
Vector2D p = t.Position;
|
||||
|
@ -339,14 +422,17 @@ namespace CodeImp.DoomBuilder.GZBuilder.Windows
|
|||
|
||||
General.Map.Map.Update();
|
||||
General.Editing.ChangeMode("ThingsMode");
|
||||
showSelection(points);
|
||||
ShowSelection(points);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void TagStatisticsForm_FormClosing(object sender, FormClosingEventArgs e) {
|
||||
private void TagStatisticsForm_FormClosing(object sender, FormClosingEventArgs e)
|
||||
{
|
||||
size = this.Size;
|
||||
location = this.Location;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,36 +16,43 @@ namespace CodeImp.DoomBuilder.GZBuilder.Windows
|
|||
private static Size size = Size.Empty;
|
||||
private static Point location = Point.Empty;
|
||||
|
||||
public ThingStatisticsForm() {
|
||||
public ThingStatisticsForm()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
//apply window size and location
|
||||
if (!size.IsEmpty && !location.IsEmpty) {
|
||||
if (!size.IsEmpty && !location.IsEmpty)
|
||||
{
|
||||
this.StartPosition = FormStartPosition.Manual;
|
||||
this.Size = size;
|
||||
this.Location = location;
|
||||
}
|
||||
|
||||
setup();
|
||||
Setup();
|
||||
}
|
||||
|
||||
private void setup() {
|
||||
private void Setup()
|
||||
{
|
||||
Dictionary<int, int> thingcounts = new Dictionary<int, int>();
|
||||
Dictionary<int, string> thingtitles = new Dictionary<int, string>();
|
||||
Dictionary<int, string> thingclasses = new Dictionary<int, string>();
|
||||
|
||||
dataGridView.Rows.Clear();
|
||||
|
||||
foreach(ThingTypeInfo ti in General.Map.Data.ThingTypes) {
|
||||
foreach(ThingTypeInfo ti in General.Map.Data.ThingTypes)
|
||||
{
|
||||
thingcounts.Add(ti.Index, 0);
|
||||
thingtitles.Add(ti.Index, ti.Title);
|
||||
thingclasses.Add(ti.Index, ti.ClassName);
|
||||
}
|
||||
|
||||
foreach(Thing t in General.Map.Map.Things) {
|
||||
if (thingcounts.ContainsKey(t.Type)) {
|
||||
foreach(Thing t in General.Map.Map.Things)
|
||||
{
|
||||
if (thingcounts.ContainsKey(t.Type))
|
||||
{
|
||||
thingcounts[t.Type]++;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
thingcounts.Add(t.Type, 1);
|
||||
thingtitles.Add(t.Type, "Unknown thing");
|
||||
thingclasses.Add(t.Type, "-");
|
||||
|
@ -53,7 +60,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.Windows
|
|||
}
|
||||
|
||||
//add rows
|
||||
foreach (KeyValuePair<int, int> group in thingcounts) {
|
||||
foreach (KeyValuePair<int, int> group in thingcounts)
|
||||
{
|
||||
if (hideUnused.Checked && group.Value == 0) continue;
|
||||
|
||||
DataGridViewRow row = new DataGridViewRow();
|
||||
|
@ -69,27 +77,31 @@ namespace CodeImp.DoomBuilder.GZBuilder.Windows
|
|||
dataGridView.Sort(ThingType, ListSortDirection.Ascending);
|
||||
}
|
||||
|
||||
private static List<Thing> getThingsByType(int type) {
|
||||
private static List<Thing> GetThingsByType(int type)
|
||||
{
|
||||
List<Thing> list = new List<Thing>();
|
||||
foreach (Thing t in General.Map.Map.Things) {
|
||||
foreach (Thing t in General.Map.Map.Things)
|
||||
if (t.Type == type) list.Add(t);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private static void showSelection(List<Vector2D> points) {
|
||||
private static void ShowSelection(List<Vector2D> points)
|
||||
{
|
||||
RectangleF area = MapSet.CreateEmptyArea();
|
||||
|
||||
// Make a view area from the points
|
||||
foreach (Vector2D p in points) area = MapSet.IncreaseArea(area, p);
|
||||
|
||||
// Make the area square, using the largest side
|
||||
if (area.Width > area.Height) {
|
||||
if (area.Width > area.Height)
|
||||
{
|
||||
float delta = area.Width - area.Height;
|
||||
area.Y -= delta * 0.5f;
|
||||
area.Height += delta;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
float delta = area.Height - area.Width;
|
||||
area.X -= delta * 0.5f;
|
||||
area.Width += delta;
|
||||
|
@ -99,19 +111,26 @@ namespace CodeImp.DoomBuilder.GZBuilder.Windows
|
|||
area.Inflate(100f, 100f);
|
||||
|
||||
// Zoom to area
|
||||
ClassicMode editmode = (General.Editing.Mode as ClassicMode);
|
||||
editmode.CenterOnArea(area, 0.6f);
|
||||
if (General.Editing.Mode is ClassicMode)
|
||||
{
|
||||
ClassicMode editmode = (General.Editing.Mode as ClassicMode);
|
||||
editmode.CenterOnArea(area, 0.6f);
|
||||
}
|
||||
}
|
||||
|
||||
private void dataGridView_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e) {
|
||||
private void dataGridView_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
|
||||
{
|
||||
if (e.RowIndex == -1) return;
|
||||
if (e.Button == MouseButtons.Left) { //select
|
||||
List<Thing> list = getThingsByType((int)dataGridView.Rows[e.RowIndex].Cells[0].Value);
|
||||
if (list.Count > 0) {
|
||||
if (e.Button == MouseButtons.Left) //select
|
||||
{
|
||||
List<Thing> list = GetThingsByType((int)dataGridView.Rows[e.RowIndex].Cells[0].Value);
|
||||
if (list.Count > 0)
|
||||
{
|
||||
General.Map.Map.ClearSelectedThings();
|
||||
|
||||
List<Vector2D> points = new List<Vector2D>();
|
||||
foreach (Thing t in list) {
|
||||
foreach (Thing t in list)
|
||||
{
|
||||
t.Selected = true;
|
||||
|
||||
Vector2D p = t.Position;
|
||||
|
@ -124,31 +143,35 @@ namespace CodeImp.DoomBuilder.GZBuilder.Windows
|
|||
|
||||
General.Map.Map.Update();
|
||||
General.Editing.ChangeMode("ThingsMode");
|
||||
showSelection(points);
|
||||
ShowSelection(points);
|
||||
}
|
||||
} else if (e.Button == MouseButtons.Right) { //edit
|
||||
List<Thing> list = getThingsByType((int)dataGridView.Rows[e.RowIndex].Cells[0].Value);
|
||||
if (list.Count > 0) {
|
||||
}
|
||||
else if (e.Button == MouseButtons.Right) //edit
|
||||
{
|
||||
List<Thing> list = GetThingsByType((int)dataGridView.Rows[e.RowIndex].Cells[0].Value);
|
||||
if (list.Count > 0)
|
||||
{
|
||||
General.MainWindow.ShowEditThings(list);
|
||||
General.Map.Map.Update();
|
||||
setup();
|
||||
Setup();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void hideUnused_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
setup();
|
||||
Setup();
|
||||
}
|
||||
|
||||
private void apply_Click(object sender, EventArgs e) {
|
||||
private void apply_Click(object sender, EventArgs e)
|
||||
{
|
||||
this.Close();
|
||||
}
|
||||
|
||||
private void ThingStatisticsForm_FormClosing(object sender, FormClosingEventArgs e) {
|
||||
private void ThingStatisticsForm_FormClosing(object sender, FormClosingEventArgs e)
|
||||
{
|
||||
size = this.Size;
|
||||
location = this.Location;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,15 +4,16 @@ using SlimDX.Direct3D9;
|
|||
|
||||
namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
||||
{
|
||||
internal class GZModel {
|
||||
internal class GZModel
|
||||
{
|
||||
internal List<Mesh> Meshes;
|
||||
internal List<Texture> Textures;
|
||||
internal Vector3[] BoundingBox;
|
||||
|
||||
internal GZModel() {
|
||||
internal GZModel()
|
||||
{
|
||||
Meshes = new List<Mesh>();
|
||||
Textures = new List<Texture>();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -29,7 +29,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
public List<Mesh> Meshes;
|
||||
public string Errors;
|
||||
|
||||
public MD3LoadResult() {
|
||||
public MD3LoadResult()
|
||||
{
|
||||
Skins = new List<string>();
|
||||
Meshes = new List<Mesh>();
|
||||
}
|
||||
|
@ -41,9 +42,12 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
|
||||
#region ================== Init
|
||||
|
||||
internal static void Init() {
|
||||
if(vertexElements == null) {
|
||||
vertexElements = new[] {
|
||||
internal static void Init()
|
||||
{
|
||||
if(vertexElements == null)
|
||||
{
|
||||
vertexElements = new[]
|
||||
{
|
||||
new VertexElement(0, 0, DeclarationType.Float3, DeclarationMethod.Default, DeclarationUsage.Position, 0),
|
||||
new VertexElement(0, 12, DeclarationType.Color, DeclarationMethod.Default, DeclarationUsage.Color, 0),
|
||||
new VertexElement(0, 16, DeclarationType.Float2, DeclarationMethod.Default, DeclarationUsage.TextureCoordinate, 0),
|
||||
|
@ -57,35 +61,31 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
|
||||
#region ================== Load
|
||||
|
||||
public static void Load(ModelData mde, List<DataReader> containers, Device device) {
|
||||
if(mde.IsVoxel) {
|
||||
loadKVX(mde, containers, device);
|
||||
} else {
|
||||
loadModel(mde, containers, device);
|
||||
}
|
||||
public static void Load(ModelData mde, List<DataReader> containers, Device device)
|
||||
{
|
||||
if(mde.IsVoxel)
|
||||
LoadKVX(mde, containers, device);
|
||||
else
|
||||
LoadModel(mde, containers, device);
|
||||
}
|
||||
|
||||
private static void loadKVX(ModelData mde, List<DataReader> containers, Device device) {
|
||||
private static void LoadKVX(ModelData mde, List<DataReader> containers, Device device)
|
||||
{
|
||||
mde.Model = new GZModel();
|
||||
|
||||
//prepare WhiteTexture... just in case :)
|
||||
//if(General.Map.Data.WhiteTexture.Texture == null || General.Map.Data.WhiteTexture.Texture.Disposed)
|
||||
//General.Map.Data.WhiteTexture.CreateTexture();
|
||||
|
||||
for(int i = 0; i < mde.ModelNames.Count; i++) {
|
||||
for(int i = 0; i < mde.ModelNames.Count; i++)
|
||||
{
|
||||
//find the model
|
||||
Stream ms;
|
||||
|
||||
foreach(DataReader dr in containers) {
|
||||
foreach(DataReader dr in containers)
|
||||
{
|
||||
ms = dr.GetVoxelData(mde.ModelNames[i]);
|
||||
if(ms == null) continue;
|
||||
|
||||
//load kvx
|
||||
ReadKVX(mde, ms, device);
|
||||
|
||||
//add texture
|
||||
//mde.Model.Textures.Add(General.Map.Data.WhiteTexture.Texture);
|
||||
|
||||
//done
|
||||
ms.Close();
|
||||
ms.Dispose();
|
||||
|
@ -97,24 +97,28 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
mde.TextureNames = null;
|
||||
mde.ModelNames = null;
|
||||
|
||||
if(mde.Model.Meshes == null || mde.Model.Meshes.Count == 0) {
|
||||
if(mde.Model.Meshes == null || mde.Model.Meshes.Count == 0)
|
||||
{
|
||||
mde.Model = null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void loadModel(ModelData mde, List<DataReader> containers, Device device) {
|
||||
private static void LoadModel(ModelData mde, List<DataReader> containers, Device device)
|
||||
{
|
||||
mde.Model = new GZModel();
|
||||
BoundingBoxSizes bbs = new BoundingBoxSizes();
|
||||
MD3LoadResult result = new MD3LoadResult();
|
||||
|
||||
//load models and textures
|
||||
for(int i = 0; i < mde.ModelNames.Count; i++) {
|
||||
for(int i = 0; i < mde.ModelNames.Count; i++)
|
||||
{
|
||||
//need to use model skins?
|
||||
bool useSkins = string.IsNullOrEmpty(mde.TextureNames[i]);
|
||||
|
||||
//load mesh
|
||||
MemoryStream ms = LoadFile(containers, mde.ModelNames[i], true);
|
||||
if (ms == null) {
|
||||
if (ms == null)
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error while loading '" + mde.ModelNames[i] + "': unable to find file.");
|
||||
continue;
|
||||
}
|
||||
|
@ -132,9 +136,12 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
ms.Dispose();
|
||||
|
||||
//got errors?
|
||||
if(!String.IsNullOrEmpty(result.Errors)) {
|
||||
if(!String.IsNullOrEmpty(result.Errors))
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error while loading '" + mde.ModelNames[i] + "': " + result.Errors);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
//add loaded data to ModeldefEntry
|
||||
mde.Model.Meshes.AddRange(result.Meshes);
|
||||
|
||||
|
@ -146,15 +153,20 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
List<string> errors = new List<string>();
|
||||
|
||||
//texture has unsupported extension?
|
||||
if(mde.TextureNames[i] == TextureData.INVALID_TEXTURE) {
|
||||
if(mde.TextureNames[i] == TextureData.INVALID_TEXTURE)
|
||||
{
|
||||
for (int c = 0; c < result.Meshes.Count; c++)
|
||||
mde.Model.Textures.Add(General.Map.Data.UnknownTexture3D.Texture);
|
||||
|
||||
//texture not defined in MODELDEF?
|
||||
} else if(useSkins) {
|
||||
}
|
||||
else if(useSkins)
|
||||
{
|
||||
//try to use model's own skins
|
||||
for(int m = 0; m < result.Meshes.Count; m++) {
|
||||
if(string.IsNullOrEmpty(result.Skins[m])) {
|
||||
for(int m = 0; m < result.Meshes.Count; m++)
|
||||
{
|
||||
if(string.IsNullOrEmpty(result.Skins[m]))
|
||||
{
|
||||
mde.Model.Textures.Add(General.Map.Data.UnknownTexture3D.Texture);
|
||||
errors.Add("texture not found in MODELDEF or model skin.");
|
||||
continue;
|
||||
|
@ -163,7 +175,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
string path = result.Skins[m].Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
|
||||
ext = Path.GetExtension(path);
|
||||
|
||||
if(Array.IndexOf(TextureData.SUPPORTED_TEXTURE_EXTENSIONS, ext) == -1) {
|
||||
if(Array.IndexOf(TextureData.SUPPORTED_TEXTURE_EXTENSIONS, ext) == -1)
|
||||
{
|
||||
mde.Model.Textures.Add(General.Map.Data.UnknownTexture3D.Texture);
|
||||
errors.Add("image format '" + ext + "' is not supported!");
|
||||
continue;
|
||||
|
@ -175,7 +188,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
|
||||
Texture t = LoadTexture(containers, path, device);
|
||||
|
||||
if(t == null) {
|
||||
if(t == null)
|
||||
{
|
||||
mde.Model.Textures.Add(General.Map.Data.UnknownTexture3D.Texture);
|
||||
errors.Add("unable to load skin '" + result.Skins[m] + "'");
|
||||
continue;
|
||||
|
@ -183,20 +197,24 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
|
||||
mde.Model.Textures.Add(t);
|
||||
}
|
||||
|
||||
//try to use texture loaded from MODELDEFS
|
||||
} else {
|
||||
}
|
||||
else //try to use texture loaded from MODELDEFS
|
||||
{
|
||||
Texture t = LoadTexture(containers, mde.TextureNames[i], device);
|
||||
if(t == null) {
|
||||
if(t == null)
|
||||
{
|
||||
mde.Model.Textures.Add(General.Map.Data.UnknownTexture3D.Texture);
|
||||
errors.Add("unable to load texture '" + mde.TextureNames[i] + "'");
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
mde.Model.Textures.Add(t);
|
||||
}
|
||||
}
|
||||
|
||||
//report errors
|
||||
if(errors.Count > 0) {
|
||||
if(errors.Count > 0)
|
||||
{
|
||||
foreach(string e in errors)
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error while loading '" + mde.ModelNames[i] + "': " + e);
|
||||
}
|
||||
|
@ -207,7 +225,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
mde.TextureNames = null;
|
||||
mde.ModelNames = null;
|
||||
|
||||
if(mde.Model.Meshes == null || mde.Model.Meshes.Count == 0) {
|
||||
if(mde.Model.Meshes == null || mde.Model.Meshes.Count == 0)
|
||||
{
|
||||
mde.Model = null;
|
||||
return;
|
||||
}
|
||||
|
@ -219,13 +238,16 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
|
||||
#region ================== MD3
|
||||
|
||||
private static MD3LoadResult ReadMD3Model(ref BoundingBoxSizes bbs, ModelData mde, bool useSkins, MemoryStream s, Device device) {
|
||||
private static MD3LoadResult ReadMD3Model(ref BoundingBoxSizes bbs, ModelData mde, bool useSkins, MemoryStream s, Device device)
|
||||
{
|
||||
long start = s.Position;
|
||||
MD3LoadResult result = new MD3LoadResult();
|
||||
|
||||
using (var br = new BinaryReader(s, Encoding.ASCII)) {
|
||||
using (var br = new BinaryReader(s, Encoding.ASCII))
|
||||
{
|
||||
string magic = ReadString(br, 4);
|
||||
if (magic != "IDP3"){
|
||||
if (magic != "IDP3")
|
||||
{
|
||||
result.Errors = "magic should be 'IDP3', not '" + magic + "'";
|
||||
return result;
|
||||
}
|
||||
|
@ -245,24 +267,30 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
Dictionary<string, List<int>> vertexOffsets = new Dictionary<string, List<int>>(StringComparer.Ordinal);
|
||||
|
||||
string error;
|
||||
for (int c = 0; c < numSurfaces; c++) {
|
||||
for (int c = 0; c < numSurfaces; c++)
|
||||
{
|
||||
string skin = "";
|
||||
error = ReadSurface(ref bbs, ref skin, br, polyIndecesList, vertList, mde);
|
||||
|
||||
if(!string.IsNullOrEmpty(error)) {
|
||||
if(!string.IsNullOrEmpty(error))
|
||||
{
|
||||
result.Errors = error;
|
||||
return result;
|
||||
}
|
||||
|
||||
if(useSkins) {
|
||||
if(polyIndecesListsPerTexture.ContainsKey(skin)) {
|
||||
if(useSkins)
|
||||
{
|
||||
if(polyIndecesListsPerTexture.ContainsKey(skin))
|
||||
{
|
||||
polyIndecesListsPerTexture[skin].Add(polyIndecesList);
|
||||
vertListsPerTexture[skin].AddRange(vertList.ToArray());
|
||||
vertexOffsets[skin].Add(vertList.Count);
|
||||
} else {
|
||||
polyIndecesListsPerTexture.Add(skin, new List<List<int>>() { polyIndecesList } );
|
||||
}
|
||||
else
|
||||
{
|
||||
polyIndecesListsPerTexture.Add(skin, new List<List<int>> { polyIndecesList } );
|
||||
vertListsPerTexture.Add(skin, vertList);
|
||||
vertexOffsets.Add(skin, new List<int>() { vertList.Count });
|
||||
vertexOffsets.Add(skin, new List<int> { vertList.Count });
|
||||
}
|
||||
|
||||
//reset lists
|
||||
|
@ -271,20 +299,27 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
}
|
||||
}
|
||||
|
||||
if(!useSkins) { //create mesh
|
||||
if(!useSkins)
|
||||
{
|
||||
//create mesh
|
||||
CreateMesh(device, ref result, vertList, polyIndecesList);
|
||||
result.Skins.Add("");
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
//create a mesh for each surface texture
|
||||
foreach(KeyValuePair<string, List<List<int>>> group in polyIndecesListsPerTexture) {
|
||||
foreach(KeyValuePair<string, List<List<int>>> group in polyIndecesListsPerTexture)
|
||||
{
|
||||
polyIndecesList = new List<int>();
|
||||
int offset = 0;
|
||||
|
||||
//collect indices, fix vertex offsets
|
||||
for(int i = 0; i < group.Value.Count; i++) {
|
||||
if(i > 0) {
|
||||
offset += vertexOffsets[group.Key][i - 1]; //Damn I need to rewrite all of this stuff from scratch...
|
||||
|
||||
for(int i = 0; i < group.Value.Count; i++)
|
||||
{
|
||||
if(i > 0)
|
||||
{
|
||||
//TODO: Damn I need to rewrite all of this stuff from scratch...
|
||||
offset += vertexOffsets[group.Key][i - 1];
|
||||
for(int c = 0; c < group.Value[i].Count; c++)
|
||||
group.Value[i][c] += offset;
|
||||
}
|
||||
|
@ -300,7 +335,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
return result;
|
||||
}
|
||||
|
||||
private static string ReadSurface(ref BoundingBoxSizes bbs, ref string skin, BinaryReader br, List<int> polyIndecesList, List<WorldVertex> vertList, ModelData mde) {
|
||||
private static string ReadSurface(ref BoundingBoxSizes bbs, ref string skin, BinaryReader br, List<int> polyIndecesList, List<WorldVertex> vertList, ModelData mde)
|
||||
{
|
||||
int vertexOffset = vertList.Count;
|
||||
long start = br.BaseStream.Position;
|
||||
string magic = ReadString(br, 4);
|
||||
|
@ -333,7 +369,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
if (start + ofsST != br.BaseStream.Position)
|
||||
br.BaseStream.Position = start + ofsST;
|
||||
|
||||
for (int i = 0; i < numVerts; i++) {
|
||||
for (int i = 0; i < numVerts; i++)
|
||||
{
|
||||
WorldVertex v = new WorldVertex();
|
||||
v.c = -1; //white
|
||||
v.u = br.ReadSingle();
|
||||
|
@ -350,7 +387,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
float angleOfsetCos = (float)Math.Cos(mde.AngleOffset);
|
||||
float angleOfsetSin = (float)Math.Sin(mde.AngleOffset);
|
||||
|
||||
for (int i = vertexOffset; i < vertexOffset + numVerts; i++) {
|
||||
for (int i = vertexOffset; i < vertexOffset + numVerts; i++)
|
||||
{
|
||||
WorldVertex v = vertList[i];
|
||||
|
||||
//read vertex
|
||||
|
@ -359,7 +397,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
v.z = (float)br.ReadInt16() / 64;
|
||||
|
||||
//rotate it
|
||||
if (mde.AngleOffset != 0) {
|
||||
if (mde.AngleOffset != 0)
|
||||
{
|
||||
float rx = angleOfsetCos * v.x - angleOfsetSin * v.y;
|
||||
float ry = angleOfsetSin * v.x + angleOfsetCos * v.y;
|
||||
v.y = ry;
|
||||
|
@ -392,16 +431,19 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
return "";
|
||||
}
|
||||
|
||||
private static void CreateMesh(Device device, ref MD3LoadResult result, List<WorldVertex> verts, List<int> indices) {
|
||||
private static void CreateMesh(Device device, ref MD3LoadResult result, List<WorldVertex> verts, List<int> indices)
|
||||
{
|
||||
//create mesh
|
||||
Mesh mesh = new Mesh(device, indices.Count / 3, verts.Count, MeshFlags.Use32Bit | MeshFlags.IndexBufferManaged | MeshFlags.VertexBufferManaged, vertexElements);
|
||||
|
||||
using(DataStream stream = mesh.LockVertexBuffer(LockFlags.None)) {
|
||||
using(DataStream stream = mesh.LockVertexBuffer(LockFlags.None))
|
||||
{
|
||||
stream.WriteRange(verts.ToArray());
|
||||
}
|
||||
mesh.UnlockVertexBuffer();
|
||||
|
||||
using(DataStream stream = mesh.LockIndexBuffer(LockFlags.None)) {
|
||||
using(DataStream stream = mesh.LockIndexBuffer(LockFlags.None))
|
||||
{
|
||||
stream.WriteRange(indices.ToArray());
|
||||
}
|
||||
mesh.UnlockIndexBuffer();
|
||||
|
@ -416,19 +458,23 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
|
||||
#region ================== MD2
|
||||
|
||||
private static MD3LoadResult ReadMD2Model(ref BoundingBoxSizes bbs, ModelData mde, MemoryStream s, Device device) {
|
||||
private static MD3LoadResult ReadMD2Model(ref BoundingBoxSizes bbs, ModelData mde, MemoryStream s, Device device)
|
||||
{
|
||||
long start = s.Position;
|
||||
MD3LoadResult result = new MD3LoadResult();
|
||||
|
||||
using (var br = new BinaryReader(s, Encoding.ASCII)) {
|
||||
using (var br = new BinaryReader(s, Encoding.ASCII))
|
||||
{
|
||||
string magic = ReadString(br, 4);
|
||||
if(magic != "IDP2") { //magic number: "IDP2"
|
||||
if(magic != "IDP2") //magic number: "IDP2"
|
||||
{
|
||||
result.Errors = "magic should be 'IDP2', not '" + magic + "'";
|
||||
return result;
|
||||
}
|
||||
|
||||
int modelVersion = br.ReadInt32();
|
||||
if(modelVersion != 8) { //MD2 version. Must be equal to 8
|
||||
if(modelVersion != 8) //MD2 version. Must be equal to 8
|
||||
{
|
||||
result.Errors = "MD2 version must be 8 but is " + modelVersion;
|
||||
return result;
|
||||
}
|
||||
|
@ -442,8 +488,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
int num_tris = br.ReadInt32(); //Number of triangles
|
||||
s.Position += 4; //Number of OpenGL commands
|
||||
|
||||
if(br.ReadInt32() == 0) { //Total number of frames
|
||||
//General.ErrorLogger.Add(ErrorType.Error, "Unable to load model '" + path + "': model has 0 frames.");
|
||||
if(br.ReadInt32() == 0) //Total number of frames
|
||||
{
|
||||
result.Errors = "model has 0 frames.";
|
||||
return result;
|
||||
}
|
||||
|
@ -461,7 +507,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
//polygons
|
||||
s.Position = ofs_tris + start;
|
||||
|
||||
for (int i = 0; i < num_tris; i++) {
|
||||
for (int i = 0; i < num_tris; i++)
|
||||
{
|
||||
polyIndecesList.Add(br.ReadUInt16());
|
||||
polyIndecesList.Add(br.ReadUInt16());
|
||||
polyIndecesList.Add(br.ReadUInt16());
|
||||
|
@ -492,7 +539,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
float angleOfsetSin = (float)Math.Sin(angle);
|
||||
|
||||
//verts
|
||||
for (int i = 0; i < num_verts; i++) {
|
||||
for (int i = 0; i < num_verts; i++)
|
||||
{
|
||||
WorldVertex v = new WorldVertex();
|
||||
|
||||
v.x = (br.ReadByte() * scale.X + translate.X);
|
||||
|
@ -500,7 +548,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
v.z = (br.ReadByte() * scale.Z + translate.Z);
|
||||
|
||||
//rotate it
|
||||
if (angle != 0) {
|
||||
if (angle != 0)
|
||||
{
|
||||
float rx = angleOfsetCos * v.x - angleOfsetSin * v.y;
|
||||
float ry = angleOfsetSin * v.x + angleOfsetCos * v.y;
|
||||
v.y = ry;
|
||||
|
@ -519,7 +568,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
s.Position += 1; //vertex normal
|
||||
}
|
||||
|
||||
for (int i = 0; i < polyIndecesList.Count; i++) {
|
||||
for (int i = 0; i < polyIndecesList.Count; i++)
|
||||
{
|
||||
WorldVertex v = vertList[polyIndecesList[i]];
|
||||
|
||||
//bounding box
|
||||
|
@ -530,11 +580,14 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
float tv = uvCoordsList[uvIndecesList[i]].Y;
|
||||
|
||||
//uv-coordinates already set?
|
||||
if(v.c == -1 && (v.u != tu || v.v != tv)) {
|
||||
if(v.c == -1 && (v.u != tu || v.v != tv))
|
||||
{
|
||||
//add a new vertex
|
||||
vertList.Add(new WorldVertex(v.x, v.y, v.z, -1, tu, tv));
|
||||
polyIndecesList[i] = vertList.Count - 1;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
v.u = tu;
|
||||
v.v = tv;
|
||||
v.c = -1; //set color to white
|
||||
|
@ -547,12 +600,14 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
//mesh
|
||||
Mesh mesh = new Mesh(device, polyIndecesList.Count / 3, vertList.Count, MeshFlags.Use32Bit | MeshFlags.IndexBufferManaged | MeshFlags.VertexBufferManaged, vertexElements);
|
||||
|
||||
using (DataStream stream = mesh.LockVertexBuffer(LockFlags.None)) {
|
||||
using (DataStream stream = mesh.LockVertexBuffer(LockFlags.None))
|
||||
{
|
||||
stream.WriteRange(vertList.ToArray());
|
||||
}
|
||||
mesh.UnlockVertexBuffer();
|
||||
|
||||
using (DataStream stream = mesh.LockIndexBuffer(LockFlags.None)) {
|
||||
using (DataStream stream = mesh.LockIndexBuffer(LockFlags.None))
|
||||
{
|
||||
stream.WriteRange(polyIndecesList.ToArray());
|
||||
}
|
||||
mesh.UnlockIndexBuffer();
|
||||
|
@ -571,13 +626,15 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
|
||||
#region ================== KVX
|
||||
|
||||
private static void ReadKVX(ModelData mde, Stream stream, Device device) {
|
||||
private static void ReadKVX(ModelData mde, Stream stream, Device device)
|
||||
{
|
||||
PixelColor[] palette = new PixelColor[256];
|
||||
List<WorldVertex> verts = new List<WorldVertex>();
|
||||
int xsize, ysize, zsize;
|
||||
Vector3D pivot;
|
||||
|
||||
using(BinaryReader reader = new BinaryReader(stream, Encoding.ASCII)) {
|
||||
using(BinaryReader reader = new BinaryReader(stream, Encoding.ASCII))
|
||||
{
|
||||
reader.ReadInt32(); //numbytes, we don't use that
|
||||
xsize = reader.ReadInt32();
|
||||
ysize = reader.ReadInt32();
|
||||
|
@ -592,20 +649,25 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
int[] xoffset = new int[xsize + 1]; //why is it xsize + 1, not xsize?..
|
||||
short[,] xyoffset = new short[xsize, ysize + 1]; //why is it ysize + 1, not ysize?..
|
||||
|
||||
for(int i = 0; i < xoffset.Length; i++) {
|
||||
for(int i = 0; i < xoffset.Length; i++)
|
||||
{
|
||||
xoffset[i] = reader.ReadInt32();
|
||||
}
|
||||
|
||||
for(int x = 0; x < xsize; x++) {
|
||||
for(int y = 0; y < ysize + 1; y++) {
|
||||
for(int x = 0; x < xsize; x++)
|
||||
{
|
||||
for(int y = 0; y < ysize + 1; y++)
|
||||
{
|
||||
xyoffset[x, y] = reader.ReadInt16();
|
||||
}
|
||||
}
|
||||
|
||||
//read slabs
|
||||
List<int> offsets = new List<int>(xsize * ysize);
|
||||
for(int x = 0; x < xsize; x++) {
|
||||
for(int y = 0; y < ysize; y++) {
|
||||
for(int x = 0; x < xsize; x++)
|
||||
{
|
||||
for(int y = 0; y < ysize; y++)
|
||||
{
|
||||
offsets.Add(xoffset[x] + xyoffset[x, y] + 28); //for some reason offsets are counted from start of xoffset[]...
|
||||
}
|
||||
}
|
||||
|
@ -614,58 +676,74 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
int slabsEnd = (int)(reader.BaseStream.Length - 768);
|
||||
|
||||
//read palette
|
||||
if(!mde.OverridePalette) {
|
||||
if(!mde.OverridePalette)
|
||||
{
|
||||
reader.BaseStream.Position = slabsEnd;
|
||||
for(int i = 0; i < 256; i++) {
|
||||
for(int i = 0; i < 256; i++)
|
||||
{
|
||||
byte r = (byte)(reader.ReadByte() * 4);
|
||||
byte g = (byte)(reader.ReadByte() * 4);
|
||||
byte b = (byte)(reader.ReadByte() * 4);
|
||||
palette[i] = new PixelColor(255, r, g, b);
|
||||
}
|
||||
} else {
|
||||
for(int i = 0; i < 256; i++ ) {
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int i = 0; i < 256; i++ )
|
||||
{
|
||||
palette[i] = General.Map.Data.Palette[i];
|
||||
}
|
||||
}
|
||||
|
||||
for(int x = 0; x < xsize; x++) {
|
||||
for(int y = 0; y < ysize; y++) {
|
||||
for(int x = 0; x < xsize; x++)
|
||||
{
|
||||
for(int y = 0; y < ysize; y++)
|
||||
{
|
||||
reader.BaseStream.Position = offsets[counter];
|
||||
int next = (counter < offsets.Count - 1 ? offsets[counter + 1] : slabsEnd);
|
||||
|
||||
//read slab
|
||||
while(reader.BaseStream.Position < next) {
|
||||
while(reader.BaseStream.Position < next)
|
||||
{
|
||||
int ztop = reader.ReadByte();
|
||||
int zleng = reader.ReadByte();
|
||||
if(ztop + zleng > zsize) break;
|
||||
int flags = reader.ReadByte();
|
||||
|
||||
if(zleng > 0) {
|
||||
if(zleng > 0)
|
||||
{
|
||||
List<int> colorIndices = new List<int>(zleng);
|
||||
for(int i = 0; i < zleng; i++) {
|
||||
for(int i = 0; i < zleng; i++)
|
||||
{
|
||||
colorIndices.Add(reader.ReadByte());
|
||||
}
|
||||
|
||||
if((flags & 16) != 0) {
|
||||
if((flags & 16) != 0)
|
||||
{
|
||||
AddFace(verts, new Vector3D(x, y, ztop), new Vector3D(x + 1, y, ztop), new Vector3D(x, y + 1, ztop), new Vector3D(x + 1, y + 1, ztop), pivot, colorIndices[0], mde.AngleOffset, mde.Scale.X);
|
||||
}
|
||||
|
||||
int z = ztop;
|
||||
int cstart = 0;
|
||||
while(z < ztop + zleng) {
|
||||
while(z < ztop + zleng)
|
||||
{
|
||||
int c = 0;
|
||||
while(z + c < ztop + zleng && colorIndices[cstart + c] == colorIndices[cstart]) c++;
|
||||
|
||||
if((flags & 1) != 0) {
|
||||
if((flags & 1) != 0)
|
||||
{
|
||||
AddFace(verts, new Vector3D(x, y, z), new Vector3D(x, y + 1, z), new Vector3D(x, y, z + c), new Vector3D(x, y + 1, z + c), pivot, colorIndices[cstart], mde.AngleOffset, mde.Scale.X);
|
||||
}
|
||||
if((flags & 2) != 0) {
|
||||
if((flags & 2) != 0)
|
||||
{
|
||||
AddFace(verts, new Vector3D(x + 1, y + 1, z), new Vector3D(x + 1, y, z), new Vector3D(x + 1, y + 1, z + c), new Vector3D(x + 1, y, z + c), pivot, colorIndices[cstart], mde.AngleOffset, mde.Scale.X);
|
||||
}
|
||||
if((flags & 4) != 0) {
|
||||
if((flags & 4) != 0)
|
||||
{
|
||||
AddFace(verts, new Vector3D(x + 1, y, z), new Vector3D(x, y, z), new Vector3D(x + 1, y, z + c), new Vector3D(x, y, z + c), pivot, colorIndices[cstart], mde.AngleOffset, mde.Scale.X);
|
||||
}
|
||||
if((flags & 8) != 0) {
|
||||
if((flags & 8) != 0)
|
||||
{
|
||||
AddFace(verts, new Vector3D(x, y + 1, z), new Vector3D(x + 1, y + 1, z), new Vector3D(x, y + 1, z + c), new Vector3D(x + 1, y + 1, z + c), pivot, colorIndices[cstart], mde.AngleOffset, mde.Scale.X);
|
||||
}
|
||||
|
||||
|
@ -674,7 +752,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
cstart += c;
|
||||
}
|
||||
|
||||
if((flags & 32) != 0) {
|
||||
if((flags & 32) != 0)
|
||||
{
|
||||
z = ztop + zleng - 1;
|
||||
AddFace(verts, new Vector3D(x + 1, y, z + 1), new Vector3D(x, y, z + 1), new Vector3D(x + 1, y + 1, z + 1), new Vector3D(x, y + 1, z + 1), pivot, colorIndices[zleng - 1], mde.AngleOffset, mde.Scale.X);
|
||||
}
|
||||
|
@ -698,7 +777,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
mde.Model.BoundingBox = BoundingBoxTools.CalculateBoundingBox(bbs);
|
||||
|
||||
//create bitmap
|
||||
Bitmap bmp = createVoxelTexture(palette);
|
||||
Bitmap bmp = CreateVoxelTexture(palette);
|
||||
|
||||
//create texture
|
||||
MemoryStream memstream = new MemoryStream((4096 * 4) + 4096);
|
||||
|
@ -713,7 +792,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
|
||||
//create mesh
|
||||
int[] indices = new int[verts.Count];
|
||||
for(int i = 0; i < verts.Count; i++) {
|
||||
for(int i = 0; i < verts.Count; i++)
|
||||
{
|
||||
indices[i] = i;
|
||||
}
|
||||
|
||||
|
@ -734,7 +814,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
}
|
||||
|
||||
// Shameless GZDoom rip-off
|
||||
private static void AddFace(List<WorldVertex> verts, Vector3D v1, Vector3D v2, Vector3D v3, Vector3D v4, Vector3D pivot, int colorIndex, float angle, float scale) {
|
||||
private static void AddFace(List<WorldVertex> verts, Vector3D v1, Vector3D v2, Vector3D v3, Vector3D v4, Vector3D pivot, int colorIndex, float angle, float scale)
|
||||
{
|
||||
float pu0 = (colorIndex % 16) / 16f;
|
||||
float pu1 = pu0 + 0.0001f;
|
||||
float pv0 = (colorIndex / 16) / 16f;
|
||||
|
@ -780,8 +861,10 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
verts.Add(wv4);
|
||||
}
|
||||
|
||||
private static WorldVertex TransformVertex(WorldVertex v, float angle, float scale) {
|
||||
if (angle != 0) {
|
||||
private static WorldVertex TransformVertex(WorldVertex v, float angle, float scale)
|
||||
{
|
||||
if (angle != 0)
|
||||
{
|
||||
float angleOfsetCos = (float) Math.Cos(angle);
|
||||
float angleOfsetSin = (float) Math.Sin(angle);
|
||||
|
||||
|
@ -791,7 +874,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
v.x = rx1;
|
||||
}
|
||||
|
||||
if (scale != 1.0f) {
|
||||
if (scale != 1.0f)
|
||||
{
|
||||
v.x *= scale;
|
||||
v.y *= scale;
|
||||
v.z *= scale;
|
||||
|
@ -800,16 +884,19 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
return v;
|
||||
}
|
||||
|
||||
private unsafe static Bitmap createVoxelTexture(PixelColor[] palette) {
|
||||
private unsafe static Bitmap CreateVoxelTexture(PixelColor[] palette)
|
||||
{
|
||||
Bitmap bmp = new Bitmap(16, 16);
|
||||
BitmapData bmpdata = bmp.LockBits(new Rectangle(0, 0, 16, 16), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
|
||||
|
||||
if(bmpdata != null) {
|
||||
if(bmpdata != null)
|
||||
{
|
||||
PixelColor* pixels = (PixelColor*)(bmpdata.Scan0.ToPointer());
|
||||
const int numpixels = 256;
|
||||
int i = 255;
|
||||
|
||||
for(PixelColor* cp = pixels + numpixels - 1; cp >= pixels; cp--, i--) {
|
||||
for(PixelColor* cp = pixels + numpixels - 1; cp >= pixels; cp--, i--)
|
||||
{
|
||||
cp->r = palette[i].r;
|
||||
cp->g = palette[i].g;
|
||||
cp->b = palette[i].b;
|
||||
|
@ -820,7 +907,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
|
||||
//scale bitmap, so colors stay (almost) the same when bilinear filtering is enabled
|
||||
Bitmap scaled = new Bitmap(64, 64);
|
||||
using(Graphics gs = Graphics.FromImage(scaled)) {
|
||||
using(Graphics gs = Graphics.FromImage(scaled))
|
||||
{
|
||||
gs.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
|
||||
gs.DrawImage(bmp, new Rectangle(0, 0, 64, 64), new Rectangle(0, 0, 16, 16), GraphicsUnit.Pixel);
|
||||
}
|
||||
|
@ -832,18 +920,20 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
|
||||
#region ================== Utility
|
||||
|
||||
private static MemoryStream LoadFile(List<DataReader> containers, string path, bool isModel) {
|
||||
foreach(DataReader dr in containers) {
|
||||
private static MemoryStream LoadFile(List<DataReader> containers, string path, bool isModel)
|
||||
{
|
||||
foreach(DataReader dr in containers)
|
||||
{
|
||||
if(isModel && dr is WADReader) continue; //models cannot be stored in WADs
|
||||
|
||||
//load file
|
||||
if(dr.FileExists(path))
|
||||
return dr.LoadFile(path);
|
||||
if(dr.FileExists(path)) return dr.LoadFile(path);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Texture LoadTexture(List<DataReader> containers, string path, Device device) {
|
||||
private static Texture LoadTexture(List<DataReader> containers, string path, Device device)
|
||||
{
|
||||
if(string.IsNullOrEmpty(path)) return null;
|
||||
|
||||
MemoryStream ms = LoadFile(containers, path, false);
|
||||
|
@ -852,14 +942,16 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
Texture texture = null;
|
||||
|
||||
//create texture
|
||||
if(Path.GetExtension(path) == ".pcx") { //pcx format requires special handling...
|
||||
if(Path.GetExtension(path) == ".pcx") //pcx format requires special handling...
|
||||
{
|
||||
FileImageReader fir = new FileImageReader();
|
||||
Bitmap bitmap = fir.ReadAsBitmap(ms);
|
||||
|
||||
ms.Close();
|
||||
ms.Dispose();
|
||||
|
||||
if(bitmap != null) {
|
||||
if(bitmap != null)
|
||||
{
|
||||
BitmapData bmlock = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, bitmap.PixelFormat);
|
||||
texture = new Texture(device, bitmap.Width, bitmap.Height, 1, Usage.None, Format.A8R8G8B8, Pool.Managed);
|
||||
|
||||
|
@ -869,7 +961,9 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
bitmap.UnlockBits(bmlock);
|
||||
texture.UnlockRectangle(0);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
texture = Texture.FromStream(device, ms);
|
||||
|
||||
ms.Close();
|
||||
|
@ -879,18 +973,22 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
return texture;
|
||||
}
|
||||
|
||||
private static string ReadString(BinaryReader br, int len) {
|
||||
private static string ReadString(BinaryReader br, int len)
|
||||
{
|
||||
var NAME = string.Empty;
|
||||
int i;
|
||||
for (i = 0; i < len; ++i) {
|
||||
for (i = 0; i < len; ++i)
|
||||
{
|
||||
var c = br.ReadChar();
|
||||
if (c == '\0') {
|
||||
if (c == '\0')
|
||||
{
|
||||
++i;
|
||||
break;
|
||||
}
|
||||
NAME += c;
|
||||
}
|
||||
for (; i < len; ++i) {
|
||||
for (; i < len; ++i)
|
||||
{
|
||||
br.ReadChar();
|
||||
}
|
||||
return NAME;
|
||||
|
|
|
@ -84,9 +84,9 @@ namespace CodeImp.DoomBuilder
|
|||
#region ================== Crc32
|
||||
sealed class Crc32
|
||||
{
|
||||
const uint CrcSeed = 0xFFFFFFFF;
|
||||
const uint CRC_SEED = 0xFFFFFFFF;
|
||||
|
||||
readonly static uint[] CrcTable = new uint[] {
|
||||
readonly static uint[] CRC_TABLE = new uint[] {
|
||||
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419,
|
||||
0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4,
|
||||
0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07,
|
||||
|
@ -139,11 +139,12 @@ namespace CodeImp.DoomBuilder
|
|||
0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8,
|
||||
0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B,
|
||||
0x2D02EF8D
|
||||
};
|
||||
};
|
||||
|
||||
internal static uint ComputeCrc32(uint oldCrc, byte value) {
|
||||
/*internal static uint ComputeCrc32(uint oldCrc, byte value)
|
||||
{
|
||||
return (Crc32.CrcTable[(oldCrc ^ value) & 0xFF] ^ (oldCrc >> 8));
|
||||
}
|
||||
}*/
|
||||
|
||||
/// <summary>
|
||||
/// The crc data checksum so far.
|
||||
|
@ -153,21 +154,12 @@ namespace CodeImp.DoomBuilder
|
|||
/// <summary>
|
||||
/// Returns the CRC32 data checksum computed so far.
|
||||
/// </summary>
|
||||
public long Value {
|
||||
get {
|
||||
return crc;
|
||||
}
|
||||
set {
|
||||
crc = (uint)value;
|
||||
}
|
||||
}
|
||||
public long Value { get { return crc; } set { crc = (uint)value; } }
|
||||
|
||||
/// <summary>
|
||||
/// Resets the CRC32 data checksum as if no update was ever called.
|
||||
/// </summary>
|
||||
public void Reset() {
|
||||
crc = 0;
|
||||
}
|
||||
public void Reset() { crc = 0; }
|
||||
|
||||
/// <summary>
|
||||
/// Updates the checksum with the int bval.
|
||||
|
@ -175,10 +167,11 @@ namespace CodeImp.DoomBuilder
|
|||
/// <param name = "value">
|
||||
/// the byte is taken as the lower 8 bits of value
|
||||
/// </param>
|
||||
public void Update(int value) {
|
||||
crc ^= CrcSeed;
|
||||
crc = CrcTable[(crc ^ value) & 0xFF] ^ (crc >> 8);
|
||||
crc ^= CrcSeed;
|
||||
public void Update(int value)
|
||||
{
|
||||
crc ^= CRC_SEED;
|
||||
crc = CRC_TABLE[(crc ^ value) & 0xFF] ^ (crc >> 8);
|
||||
crc ^= CRC_SEED;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -187,11 +180,9 @@ namespace CodeImp.DoomBuilder
|
|||
/// <param name="buffer">
|
||||
/// buffer an array of bytes
|
||||
/// </param>
|
||||
public void Update(byte[] buffer) {
|
||||
if (buffer == null) {
|
||||
throw new ArgumentNullException("buffer");
|
||||
}
|
||||
|
||||
public void Update(byte[] buffer)
|
||||
{
|
||||
if (buffer == null) throw new ArgumentNullException("buffer");
|
||||
Update(buffer, 0, buffer.Length);
|
||||
}
|
||||
|
||||
|
@ -207,26 +198,20 @@ namespace CodeImp.DoomBuilder
|
|||
/// <param name = "count">
|
||||
/// The number of data bytes to update the CRC with.
|
||||
/// </param>
|
||||
public void Update(byte[] buffer, int offset, int count) {
|
||||
if (buffer == null) {
|
||||
throw new ArgumentNullException("buffer");
|
||||
public void Update(byte[] buffer, int offset, int count)
|
||||
{
|
||||
if (buffer == null) throw new ArgumentNullException("buffer");
|
||||
if (count < 0) throw new ArgumentOutOfRangeException("count", "Count cannot be less than zero");
|
||||
if (offset < 0 || offset + count > buffer.Length) throw new ArgumentOutOfRangeException("offset");
|
||||
|
||||
crc ^= CRC_SEED;
|
||||
|
||||
while (--count >= 0)
|
||||
{
|
||||
crc = CRC_TABLE[(crc ^ buffer[offset++]) & 0xFF] ^ (crc >> 8);
|
||||
}
|
||||
|
||||
if (count < 0) {
|
||||
throw new ArgumentOutOfRangeException("count", "Count cannot be less than zero");
|
||||
}
|
||||
|
||||
if (offset < 0 || offset + count > buffer.Length) {
|
||||
throw new ArgumentOutOfRangeException("offset");
|
||||
}
|
||||
|
||||
crc ^= CrcSeed;
|
||||
|
||||
while (--count >= 0) {
|
||||
crc = CrcTable[(crc ^ buffer[offset++]) & 0xFF] ^ (crc >> 8);
|
||||
}
|
||||
|
||||
crc ^= CrcSeed;
|
||||
crc ^= CRC_SEED;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
|
|
@ -88,7 +88,7 @@ namespace CodeImp.DoomBuilder
|
|||
erroradded = true;
|
||||
prefix = "ERROR: ";
|
||||
#if DEBUG
|
||||
DebugConsole.WriteLine(DebugMessageType.Error, message);
|
||||
DebugConsole.WriteLine(DebugMessageType.ERROR, message);
|
||||
#endif
|
||||
break;
|
||||
|
||||
|
@ -96,7 +96,7 @@ namespace CodeImp.DoomBuilder
|
|||
warningadded = true;
|
||||
prefix = "WARNING: ";
|
||||
#if DEBUG
|
||||
DebugConsole.WriteLine(DebugMessageType.Warning, message);
|
||||
DebugConsole.WriteLine(DebugMessageType.WARNING, message);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -262,7 +262,7 @@ namespace CodeImp.DoomBuilder
|
|||
}
|
||||
|
||||
// This loads and returns a game configuration
|
||||
private static Configuration loadGameConfiguration(string filename)
|
||||
private static Configuration LoadGameConfiguration(string filename)
|
||||
{
|
||||
// Make the full filepathname
|
||||
string filepathname = Path.Combine(configspath, filename);
|
||||
|
@ -320,7 +320,7 @@ namespace CodeImp.DoomBuilder
|
|||
foreach(string filepath in filenames)
|
||||
{
|
||||
// Check if it can be loaded
|
||||
cfg = loadGameConfiguration(Path.GetFileName(filepath));
|
||||
cfg = LoadGameConfiguration(Path.GetFileName(filepath));
|
||||
if(cfg != null)
|
||||
{
|
||||
fullfilename = Path.GetFileName(filepath);
|
||||
|
@ -710,17 +710,19 @@ namespace CodeImp.DoomBuilder
|
|||
|
||||
//mxd. Check enabled game configuration
|
||||
bool noneenabled = true;
|
||||
for(int i = 0; i < configs.Count; i++) {
|
||||
if(configs[i].Enabled) {
|
||||
for(int i = 0; i < configs.Count; i++)
|
||||
{
|
||||
if(configs[i].Enabled)
|
||||
{
|
||||
noneenabled = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(noneenabled) {
|
||||
if(MessageBox.Show("No game configurations are currently enabled.\nPlease enable at least one game configuration", "Warning", MessageBoxButtons.OK) == DialogResult.OK) {
|
||||
if(noneenabled)
|
||||
{
|
||||
if(MessageBox.Show("No game configurations are currently enabled.\nPlease enable at least one game configuration", "Warning", MessageBoxButtons.OK) == DialogResult.OK)
|
||||
mainwindow.ShowConfiguration();
|
||||
}
|
||||
}
|
||||
|
||||
// Run application from the main window
|
||||
|
@ -1132,8 +1134,8 @@ namespace CodeImp.DoomBuilder
|
|||
[BeginAction("openmap")]
|
||||
internal static void OpenMap()
|
||||
{
|
||||
//mxd
|
||||
if(map != null && map.Launcher.GameEngineRunning) {
|
||||
if(map != null && map.Launcher.GameEngineRunning) //mxd
|
||||
{
|
||||
ShowWarningMessage("Cannot open a map while game engine is running" + Environment.NewLine + "Please close '" + map.ConfigSettings.TestProgram + "' first.", MessageBoxButtons.OK);
|
||||
return;
|
||||
}
|
||||
|
@ -1641,7 +1643,7 @@ namespace CodeImp.DoomBuilder
|
|||
#if DEBUG
|
||||
// Output to consoles
|
||||
Console.WriteLine(line);
|
||||
DebugConsole.WriteLine(DebugMessageType.Log, line); //mxd
|
||||
DebugConsole.WriteLine(DebugMessageType.LOG, line); //mxd
|
||||
#endif
|
||||
// Write to log file
|
||||
try { File.AppendAllText(logfile, line + Environment.NewLine); }
|
||||
|
@ -1654,7 +1656,7 @@ namespace CodeImp.DoomBuilder
|
|||
#if DEBUG
|
||||
// Output to consoles
|
||||
Console.Write(text);
|
||||
DebugConsole.Write(DebugMessageType.Log, text);
|
||||
DebugConsole.Write(DebugMessageType.LOG, text);
|
||||
#endif
|
||||
|
||||
// Write to log file
|
||||
|
|
|
@ -75,7 +75,8 @@ namespace CodeImp.DoomBuilder
|
|||
General.Actions.UnbindMethods(this);
|
||||
|
||||
//mxd. Terminate process?
|
||||
if (process != null) {
|
||||
if (process != null)
|
||||
{
|
||||
process.CloseMainWindow();
|
||||
process.Close();
|
||||
}
|
||||
|
@ -243,7 +244,8 @@ namespace CodeImp.DoomBuilder
|
|||
|
||||
//mxd
|
||||
[BeginAction("testmapfromview")]
|
||||
public void TestFromView() {
|
||||
public void TestFromView()
|
||||
{
|
||||
if(!General.Editing.Mode.OnMapTestBegin(true)) return;
|
||||
TestAtSkill(General.Map.ConfigSettings.TestSkill);
|
||||
General.Editing.Mode.OnMapTestEnd(true);
|
||||
|
@ -253,7 +255,8 @@ namespace CodeImp.DoomBuilder
|
|||
public void TestAtSkill(int skill)
|
||||
{
|
||||
//mxd
|
||||
if (process != null) {
|
||||
if (process != null)
|
||||
{
|
||||
General.ShowWarningMessage("Game engine is already running." + Environment.NewLine + " Please close '" + General.Map.ConfigSettings.TestProgram + "' before testing again", MessageBoxButtons.OK);
|
||||
return;
|
||||
}
|
||||
|
@ -342,7 +345,8 @@ namespace CodeImp.DoomBuilder
|
|||
}
|
||||
|
||||
//mxd
|
||||
private void testingFinished() {
|
||||
private void TestingFinished()
|
||||
{
|
||||
//Done
|
||||
TimeSpan deltatime = TimeSpan.FromTicks(process.ExitTime.Ticks - process.StartTime.Ticks);
|
||||
process = null;
|
||||
|
@ -359,9 +363,11 @@ namespace CodeImp.DoomBuilder
|
|||
}
|
||||
|
||||
//mxd
|
||||
public void StopGameEngine() {
|
||||
public void StopGameEngine()
|
||||
{
|
||||
//mxd. Terminate process?
|
||||
if(process != null) {
|
||||
if(process != null)
|
||||
{
|
||||
process.CloseMainWindow();
|
||||
process.Close();
|
||||
process = null;
|
||||
|
@ -372,8 +378,9 @@ namespace CodeImp.DoomBuilder
|
|||
}
|
||||
|
||||
//mxd
|
||||
private void ProcessOnExited(object sender, EventArgs eventArgs) {
|
||||
General.MainWindow.Invoke(new EngineExitedCallback(testingFinished));
|
||||
private void ProcessOnExited(object sender, EventArgs eventArgs)
|
||||
{
|
||||
General.MainWindow.Invoke(new EngineExitedCallback(TestingFinished));
|
||||
}
|
||||
|
||||
// This deletes the previous temp file and creates a new, empty temp file
|
||||
|
|
|
@ -553,12 +553,14 @@ namespace CodeImp.DoomBuilder {
|
|||
/// <summary>
|
||||
/// This exports the structures from memory into a WAD file with the current map format.
|
||||
/// </summary>
|
||||
public bool ExportToFile(string filepathname) {
|
||||
public bool ExportToFile(string filepathname)
|
||||
{
|
||||
return SaveMap(filepathname, SavePurpose.Testing);
|
||||
}
|
||||
|
||||
// Initializes for an existing map
|
||||
internal bool SaveMap(string newfilepathname, SavePurpose purpose) {
|
||||
internal bool SaveMap(string newfilepathname, SavePurpose purpose)
|
||||
{
|
||||
MapSet outputset;
|
||||
string nodebuildername, settingsfile;
|
||||
StatusInfo oldstatus;
|
||||
|
@ -577,14 +579,13 @@ namespace CodeImp.DoomBuilder {
|
|||
|
||||
// Only recompile scripts when the scripts have changed
|
||||
// (not when only the map changed)
|
||||
if (localscriptschanged) {
|
||||
if (!CompileScriptLumps()) {
|
||||
// Compiler failure
|
||||
if (errors.Count > 0)
|
||||
General.ShowErrorMessage("Error while compiling scripts: " + errors[0].description, MessageBoxButtons.OK);
|
||||
else
|
||||
General.ShowErrorMessage("Unknown compiler error while compiling scripts!", MessageBoxButtons.OK);
|
||||
}
|
||||
if(localscriptschanged && !CompileScriptLumps())
|
||||
{
|
||||
// Compiler failure
|
||||
if(errors.Count > 0)
|
||||
General.ShowErrorMessage("Error while compiling scripts: " + errors[0].description, MessageBoxButtons.OK);
|
||||
else
|
||||
General.ShowErrorMessage("Unknown compiler error while compiling scripts!", MessageBoxButtons.OK);
|
||||
}
|
||||
|
||||
// Show script window if there are any errors and we are going to test the map
|
||||
|
@ -594,13 +595,16 @@ namespace CodeImp.DoomBuilder {
|
|||
|
||||
// Only write the map and rebuild nodes when the actual map has changed
|
||||
// (not when only scripts have changed)
|
||||
if (changed) {
|
||||
if (changed)
|
||||
{
|
||||
// Make a copy of the map data
|
||||
outputset = map.Clone();
|
||||
|
||||
// Remove all flags from all 3D Start things
|
||||
foreach (Thing t in outputset.Things) {
|
||||
if (t.Type == config.Start3DModeThingType) {
|
||||
foreach (Thing t in outputset.Things)
|
||||
{
|
||||
if (t.Type == config.Start3DModeThingType)
|
||||
{
|
||||
// We're not using SetFlag here, this doesn't have to be undone.
|
||||
// Please note that this is totally exceptional!
|
||||
List<string> flagkeys = new List<string>(t.Flags.Keys);
|
||||
|
@ -609,7 +613,8 @@ namespace CodeImp.DoomBuilder {
|
|||
}
|
||||
|
||||
// Do we need sidedefs compression?
|
||||
if (map.Sidedefs.Count > io.MaxSidedefs) {
|
||||
if (map.Sidedefs.Count > io.MaxSidedefs)
|
||||
{
|
||||
// Compress sidedefs
|
||||
oldstatus = General.MainWindow.Status;
|
||||
General.MainWindow.DisplayStatus(StatusType.Busy, "Compressing sidedefs...");
|
||||
|
@ -617,7 +622,8 @@ namespace CodeImp.DoomBuilder {
|
|||
General.MainWindow.DisplayStatus(oldstatus);
|
||||
|
||||
// Check if it still doesnt fit
|
||||
if (outputset.Sidedefs.Count > io.MaxSidedefs) {
|
||||
if (outputset.Sidedefs.Count > io.MaxSidedefs)
|
||||
{
|
||||
// Problem! Can't save the map like this!
|
||||
General.ShowErrorMessage("Unable to save the map: There are too many unique sidedefs!", MessageBoxButtons.OK);
|
||||
return false;
|
||||
|
@ -625,25 +631,29 @@ namespace CodeImp.DoomBuilder {
|
|||
}
|
||||
|
||||
// Check things
|
||||
if (map.Things.Count > io.MaxThings) {
|
||||
if (map.Things.Count > io.MaxThings)
|
||||
{
|
||||
General.ShowErrorMessage("Unable to save the map: There are too many things!", MessageBoxButtons.OK);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check sectors
|
||||
if (map.Sectors.Count > io.MaxSectors) {
|
||||
if (map.Sectors.Count > io.MaxSectors)
|
||||
{
|
||||
General.ShowErrorMessage("Unable to save the map: There are too many sectors!", MessageBoxButtons.OK);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check linedefs
|
||||
if (map.Linedefs.Count > io.MaxLinedefs) {
|
||||
if (map.Linedefs.Count > io.MaxLinedefs)
|
||||
{
|
||||
General.ShowErrorMessage("Unable to save the map: There are too many linedefs!", MessageBoxButtons.OK);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check vertices
|
||||
if (map.Vertices.Count > io.MaxVertices) {
|
||||
if (map.Vertices.Count > io.MaxVertices)
|
||||
{
|
||||
General.ShowErrorMessage("Unable to save the map: There are too many vertices!", MessageBoxButtons.OK);
|
||||
return false;
|
||||
}
|
||||
|
@ -681,15 +691,19 @@ namespace CodeImp.DoomBuilder {
|
|||
// Determine original map name
|
||||
origmapname = (options.PreviousName != "" && purpose != SavePurpose.IntoFile) ? options.PreviousName : options.CurrentName;
|
||||
|
||||
try {
|
||||
if (File.Exists(newfilepathname)) {
|
||||
try
|
||||
{
|
||||
if (File.Exists(newfilepathname))
|
||||
{
|
||||
// mxd. Check if target wad already has a map with the same name
|
||||
if (purpose == SavePurpose.IntoFile) {
|
||||
if (purpose == SavePurpose.IntoFile)
|
||||
{
|
||||
WAD wad = new WAD(newfilepathname, true);
|
||||
int mapindex = wad.FindLumpIndex(origmapname);
|
||||
wad.Dispose();
|
||||
|
||||
if(mapindex != -1 && MessageBox.Show(General.MainWindow, "Target file already contains map '" + origmapname + "'\nDo you want to replace it?", "Map already exists!", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.No) {
|
||||
if(mapindex != -1 && MessageBox.Show(General.MainWindow, "Target file already contains map '" + origmapname + "'\nDo you want to replace it?", "Map already exists!", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.No)
|
||||
{
|
||||
data.Resume();
|
||||
General.WriteLogLine("Map saving cancelled...");
|
||||
return false;
|
||||
|
@ -705,7 +719,8 @@ namespace CodeImp.DoomBuilder {
|
|||
|
||||
// Except when saving INTO another file,
|
||||
// kill the target file if it is different from source file
|
||||
if ((purpose != SavePurpose.IntoFile) && (newfilepathname != filepathname)) {
|
||||
if ((purpose != SavePurpose.IntoFile) && (newfilepathname != filepathname))
|
||||
{
|
||||
// Kill target file
|
||||
if (File.Exists(newfilepathname)) File.Delete(newfilepathname);
|
||||
|
||||
|
@ -715,13 +730,15 @@ namespace CodeImp.DoomBuilder {
|
|||
}
|
||||
|
||||
// On Save AS we have to copy the previous file to the new file
|
||||
if ((purpose == SavePurpose.AsNewFile) && (filepathname != "")) {
|
||||
if ((purpose == SavePurpose.AsNewFile) && (filepathname != ""))
|
||||
{
|
||||
// Copy if original file still exists
|
||||
if (File.Exists(filepathname)) File.Copy(filepathname, newfilepathname, true);
|
||||
}
|
||||
|
||||
// If the target file exists, we need to rebuild it
|
||||
if (File.Exists(newfilepathname)) {
|
||||
if (File.Exists(newfilepathname))
|
||||
{
|
||||
// Move the target file aside
|
||||
string origwadfile = newfilepathname + ".temp";
|
||||
File.Move(newfilepathname, origwadfile);
|
||||
|
@ -734,9 +751,12 @@ namespace CodeImp.DoomBuilder {
|
|||
|
||||
// Copy all lumps, except the original map
|
||||
GameConfiguration origcfg; //mxd
|
||||
if (origmapconfigname == configinfo.Filename) {
|
||||
if (origmapconfigname == configinfo.Filename)
|
||||
{
|
||||
origcfg = config;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
ConfigurationInfo ci = General.GetConfigurationInfo(origmapconfigname);
|
||||
origcfg = new GameConfiguration(ci.Configuration);
|
||||
}
|
||||
|
@ -752,12 +772,16 @@ namespace CodeImp.DoomBuilder {
|
|||
// Create new target file
|
||||
targetwad = new WAD(newfilepathname);
|
||||
}
|
||||
} catch (IOException) {
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
General.ShowErrorMessage("IO Error while writing target file: " + newfilepathname + ". Please make sure the location is accessible and not in use by another program.", MessageBoxButtons.OK);
|
||||
data.Resume();
|
||||
General.WriteLogLine("Map saving failed");
|
||||
return false;
|
||||
} catch (UnauthorizedAccessException) {
|
||||
}
|
||||
catch (UnauthorizedAccessException)
|
||||
{
|
||||
General.ShowErrorMessage("Error while accessing target file: " + newfilepathname + ". Please make sure the location is accessible and not in use by another program.", MessageBoxButtons.OK);
|
||||
data.Resume();
|
||||
General.WriteLogLine("Map saving failed");
|
||||
|
@ -776,10 +800,13 @@ namespace CodeImp.DoomBuilder {
|
|||
|
||||
// Find the map header in target
|
||||
index = targetwad.FindLumpIndex(options.PreviousName);
|
||||
if (index > -1) {
|
||||
if (index > -1)
|
||||
{
|
||||
// Rename the map lump name
|
||||
targetwad.Lumps[index].Rename(options.CurrentName);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// Houston, we've got a problem!
|
||||
General.ShowErrorMessage("Error renaming map lump name: the original map lump could not be found!", MessageBoxButtons.OK);
|
||||
options.CurrentName = options.PreviousName;
|
||||
|
@ -796,9 +823,11 @@ namespace CodeImp.DoomBuilder {
|
|||
data.Resume();
|
||||
|
||||
// Not saved for testing purpose?
|
||||
if (purpose != SavePurpose.Testing) {
|
||||
if (purpose != SavePurpose.Testing)
|
||||
{
|
||||
// Saved in a different file?
|
||||
if (newfilepathname != filepathname) {
|
||||
if (newfilepathname != filepathname)
|
||||
{
|
||||
// Keep new filename
|
||||
filepathname = newfilepathname;
|
||||
filetitle = Path.GetFileName(filepathname);
|
||||
|
@ -807,11 +836,14 @@ namespace CodeImp.DoomBuilder {
|
|||
ReloadResources();
|
||||
}
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
// Open or create the map settings
|
||||
settingsfile = newfilepathname.Substring(0, newfilepathname.Length - 4) + ".dbs";
|
||||
options.WriteConfiguration(settingsfile);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// Warning only
|
||||
General.ErrorLogger.Add(ErrorType.Warning, "Could not write the map settings configuration file. " + e.GetType().Name + ": " + e.Message);
|
||||
}
|
||||
|
@ -1234,7 +1266,8 @@ namespace CodeImp.DoomBuilder {
|
|||
{
|
||||
// Check if this is a known lump name
|
||||
if (maplumps.ContainsKey(source.Lumps[mapheaderindex + i].Name) ||
|
||||
(maplumps.ContainsKey(CONFIG_MAP_HEADER) && (source.Lumps[mapheaderindex + i].Name == mapheadername))) {
|
||||
(maplumps.ContainsKey(CONFIG_MAP_HEADER) && (source.Lumps[mapheaderindex + i].Name == mapheadername)))
|
||||
{
|
||||
// Is this the lump we are looking for?
|
||||
if (source.Lumps[mapheaderindex + i].Name == lumpname)
|
||||
{
|
||||
|
@ -1648,7 +1681,7 @@ namespace CodeImp.DoomBuilder {
|
|||
if (stream != null)
|
||||
{
|
||||
AcsParserSE parser = new AcsParserSE();
|
||||
parser.OnInclude = updateScriptsFromLocation;
|
||||
parser.OnInclude = UpdateScriptsFromLocation;
|
||||
parser.Parse(stream, "SCRIPTS", true, false);
|
||||
|
||||
if(parser.NamedScripts.Count > 0 && (FormatInterface is DoomMapSetIO || FormatInterface is HexenMapSetIO))
|
||||
|
@ -1675,7 +1708,7 @@ namespace CodeImp.DoomBuilder {
|
|||
}
|
||||
|
||||
//mxd
|
||||
private static void updateScriptsFromLocation(AcsParserSE parser, string path)
|
||||
private static void UpdateScriptsFromLocation(AcsParserSE parser, string path)
|
||||
{
|
||||
MemoryStream s = General.Map.Data.LoadFile(path);
|
||||
if(s != null && s.Length > 0) parser.Parse(s, path, true, true);
|
||||
|
@ -1954,7 +1987,7 @@ namespace CodeImp.DoomBuilder {
|
|||
//snap vertices?
|
||||
if (verts.Count > 0)
|
||||
{
|
||||
snapVertices(verts);
|
||||
SnapVertices(verts);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1966,12 +1999,12 @@ namespace CodeImp.DoomBuilder {
|
|||
}
|
||||
else
|
||||
{
|
||||
snapThings(things);
|
||||
SnapThings(things);
|
||||
}
|
||||
}
|
||||
|
||||
//mxd
|
||||
private void snapVertices(ICollection<Vertex> verts)
|
||||
private void SnapVertices(ICollection<Vertex> verts)
|
||||
{
|
||||
//we are terribly busy...
|
||||
Cursor.Current = Cursors.AppStarting;
|
||||
|
@ -2091,7 +2124,7 @@ namespace CodeImp.DoomBuilder {
|
|||
}
|
||||
|
||||
//mxd
|
||||
private static void snapThings(IEnumerable<Thing> things)
|
||||
private static void SnapThings(IEnumerable<Thing> things)
|
||||
{
|
||||
//we are terribly busy...
|
||||
Cursor.Current = Cursors.AppStarting;
|
||||
|
|
|
@ -10,63 +10,59 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
{
|
||||
//mxd. Ported from Cubic Bezier curve tools by Andy Woodruff (http://cartogrammar.com/source/CubicBezier.as)
|
||||
//"default" values: z = 0.5, angleFactor = 0.75; if targetSegmentLength <= 0, will return lines
|
||||
public static Curve CurveThroughPoints(List<Vector2D> points, float z, float angleFactor, int targetSegmentLength) {
|
||||
public static Curve CurveThroughPoints(List<Vector2D> points, float z, float angleFactor, int targetSegmentLength)
|
||||
{
|
||||
Curve result = new Curve();
|
||||
|
||||
// First calculate all the curve control points
|
||||
// None of this junk will do any good if there are only two points
|
||||
if(points.Count > 2 && targetSegmentLength > 0) {
|
||||
if(points.Count > 2 && targetSegmentLength > 0)
|
||||
{
|
||||
List<List<Vector2D>> controlPts = new List<List<Vector2D>>(); // An array to store the two control points (of a cubic Bézier curve) for each point
|
||||
|
||||
// Make sure z is between 0 and 1 (too messy otherwise)
|
||||
if(z <= 0)
|
||||
z = 0.1f;
|
||||
else if(z > 1)
|
||||
z = 1;
|
||||
if(z <= 0) z = 0.1f;
|
||||
else if(z > 1) z = 1;
|
||||
|
||||
// Make sure angleFactor is between 0 and 1
|
||||
if(angleFactor < 0)
|
||||
angleFactor = 0;
|
||||
else if(angleFactor > 1)
|
||||
angleFactor = 1;
|
||||
if(angleFactor < 0) angleFactor = 0;
|
||||
else if(angleFactor > 1) angleFactor = 1;
|
||||
|
||||
// Ordinarily, curve calculations will start with the second point and go through the second-to-last point
|
||||
int firstPt = 1;
|
||||
int lastPt = points.Count - 1;
|
||||
|
||||
// Check if this is a closed line (the first and last points are the same)
|
||||
if(points[0].x == points[points.Count - 1].x && points[0].y == points[points.Count - 1].y) {
|
||||
if(points[0].x == points[points.Count - 1].x && points[0].y == points[points.Count - 1].y)
|
||||
{
|
||||
// Include first and last points in curve calculations
|
||||
firstPt = 0;
|
||||
lastPt = points.Count;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
controlPts.Add(new List<Vector2D>()); //add a dummy entry
|
||||
}
|
||||
|
||||
// Loop through all the points (except the first and last if not a closed line) to get curve control points for each.
|
||||
for(int i = firstPt; i < lastPt; i++) {
|
||||
|
||||
for(int i = firstPt; i < lastPt; i++)
|
||||
{
|
||||
// The previous, current, and next points
|
||||
Vector2D p0 = (i - 1 < 0) ? points[points.Count - 2] : points[i - 1]; // If the first point (of a closed line), use the second-to-last point as the previous point
|
||||
Vector2D p1 = points[i];
|
||||
Vector2D p2 = (i + 1 == points.Count) ? points[1] : points[i + 1]; // If the last point (of a closed line), use the second point as the next point
|
||||
|
||||
float a = Vector2D.Distance(p0, p1); // Distance from previous point to current point
|
||||
if(a < 0.001)
|
||||
a = 0.001f; // Correct for near-zero distances, a cheap way to prevent division by zero
|
||||
if(a < 0.001) a = 0.001f; // Correct for near-zero distances, a cheap way to prevent division by zero
|
||||
float b = Vector2D.Distance(p1, p2); // Distance from current point to next point
|
||||
if(b < 0.001)
|
||||
b = 0.001f;
|
||||
if(b < 0.001) b = 0.001f;
|
||||
float c = Vector2D.Distance(p0, p2); // Distance from previous point to next point
|
||||
if(c < 0.001)
|
||||
c = 0.001f;
|
||||
if(c < 0.001) c = 0.001f;
|
||||
|
||||
float cos = (b * b + a * a - c * c) / (2 * b * a);
|
||||
// Make sure above value is between -1 and 1 so that Math.acos will work
|
||||
if(cos < -1)
|
||||
cos = -1;
|
||||
else if(cos > 1)
|
||||
cos = 1;
|
||||
if(cos < -1) cos = -1;
|
||||
else if(cos > 1) cos = 1;
|
||||
|
||||
float C = (float)Math.Acos(cos); // Angle formed by the two sides of the triangle (described by the three points above) adjacent to the current point
|
||||
|
||||
|
@ -83,10 +79,8 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
(defined above) and the perpendicular to this is nice for the line tangent to the curve.
|
||||
The curve control points will be along that tangent line.
|
||||
*/
|
||||
if(a > b)
|
||||
aPt = aPt.GetNormal() * b; // Scale the segment to aPt (bPt to aPt) to the size of b (bPt to cPt) if b is shorter.
|
||||
else if(b > a)
|
||||
cPt = cPt.GetNormal() * a; // Scale the segment to cPt (bPt to cPt) to the size of a (aPt to bPt) if a is shorter.
|
||||
if(a > b) aPt = aPt.GetNormal() * b; // Scale the segment to aPt (bPt to aPt) to the size of b (bPt to cPt) if b is shorter.
|
||||
else if(b > a) cPt = cPt.GetNormal() * a; // Scale the segment to cPt (bPt to cPt) to the size of a (aPt to bPt) if a is shorter.
|
||||
|
||||
// Offset aPt and cPt by the current point to get them back to their absolute position.
|
||||
aPt += p1;
|
||||
|
@ -101,16 +95,20 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
float ry = ay + by;
|
||||
|
||||
// Correct for three points in a line by finding the angle between just two of them
|
||||
if(rx == 0 && ry == 0) {
|
||||
if(rx == 0 && ry == 0)
|
||||
{
|
||||
rx = -bx; // Really not sure why this seems to have to be negative
|
||||
ry = by;
|
||||
}
|
||||
|
||||
// Switch rx and ry when y or x difference is 0. This seems to prevent the angle from being perpendicular to what it should be.
|
||||
if(ay == 0 && by == 0) {
|
||||
if(ay == 0 && by == 0)
|
||||
{
|
||||
rx = 0;
|
||||
ry = 1;
|
||||
} else if(ax == 0 && bx == 0) {
|
||||
}
|
||||
else if(ax == 0 && bx == 0)
|
||||
{
|
||||
rx = 1;
|
||||
ry = 0;
|
||||
}
|
||||
|
@ -138,13 +136,14 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
Check for that and switch them if it's true.
|
||||
*/
|
||||
if(Vector2D.Distance(controlPoint2, p2) > Vector2D.Distance(controlPoint1, p2))
|
||||
controlPts.Add(new List<Vector2D>() { controlPoint2, controlPoint1 });
|
||||
controlPts.Add(new List<Vector2D> { controlPoint2, controlPoint1 });
|
||||
else
|
||||
controlPts.Add(new List<Vector2D>() { controlPoint1, controlPoint2 });
|
||||
controlPts.Add(new List<Vector2D> { controlPoint1, controlPoint2 });
|
||||
}
|
||||
|
||||
// If this isn't a closed line, draw a regular quadratic Bézier curve from the first to second points, using the first control point of the second point
|
||||
if(firstPt == 1) {
|
||||
if(firstPt == 1)
|
||||
{
|
||||
float length = (points[1] - points[0]).GetLength();
|
||||
int numSteps = Math.Max(1, (int)Math.Round(length / targetSegmentLength));
|
||||
CurveSegment segment = new CurveSegment();
|
||||
|
@ -157,7 +156,8 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
}
|
||||
|
||||
// Loop through points to draw cubic Bézier curves through the penultimate point, or through the last point if the line is closed.
|
||||
for(int i = firstPt; i < lastPt - 1; i++) {
|
||||
for(int i = firstPt; i < lastPt - 1; i++)
|
||||
{
|
||||
float length = (points[i + 1] - points[i]).GetLength();
|
||||
int numSteps = Math.Max(1, (int)Math.Round(length / targetSegmentLength));
|
||||
|
||||
|
@ -172,7 +172,8 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
}
|
||||
|
||||
// If this isn't a closed line, curve to the last point using the second control point of the penultimate point.
|
||||
if(lastPt == points.Count - 1) {
|
||||
if(lastPt == points.Count - 1)
|
||||
{
|
||||
float length = (points[lastPt] - points[lastPt - 1]).GetLength();
|
||||
int numSteps = Math.Max(1, (int)Math.Round(length / targetSegmentLength));
|
||||
|
||||
|
@ -186,12 +187,15 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
}
|
||||
|
||||
// create lines
|
||||
} else if(points.Count >= 2) {
|
||||
for(int i = 0; i < points.Count - 1; i++) {
|
||||
}
|
||||
else if(points.Count >= 2)
|
||||
{
|
||||
for(int i = 0; i < points.Count - 1; i++)
|
||||
{
|
||||
CurveSegment segment = new CurveSegment();
|
||||
segment.Start = points[i];
|
||||
segment.End = points[i + 1];
|
||||
segment.Points = new Vector2D[] { segment.Start, segment.End };
|
||||
segment.Points = new[] { segment.Start, segment.End };
|
||||
segment.UpdateLength();
|
||||
result.Segments.Add(segment);
|
||||
}
|
||||
|
@ -201,23 +205,25 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
return result;
|
||||
}
|
||||
|
||||
public static void CreateQuadraticCurve(CurveSegment segment, int steps) {
|
||||
public static void CreateQuadraticCurve(CurveSegment segment, int steps)
|
||||
{
|
||||
segment.CurveType = CurveSegmentType.QUADRATIC;
|
||||
segment.Points = GetQuadraticCurve(segment.Start, segment.CPMid, segment.End, steps);
|
||||
segment.UpdateLength();
|
||||
}
|
||||
|
||||
//this returns array of Vector2D to draw 3-point bezier curve
|
||||
public static Vector2D[] GetQuadraticCurve(Vector2D p1, Vector2D p2, Vector2D p3, int steps) {
|
||||
if(steps < 0)
|
||||
return null;
|
||||
public static Vector2D[] GetQuadraticCurve(Vector2D p1, Vector2D p2, Vector2D p3, int steps)
|
||||
{
|
||||
if(steps < 0) return null;
|
||||
|
||||
int totalSteps = steps + 1;
|
||||
Vector2D[] points = new Vector2D[totalSteps];
|
||||
float step = 1f / steps;
|
||||
float curStep = 0f;
|
||||
|
||||
for(int i = 0; i < totalSteps; i++) {
|
||||
for(int i = 0; i < totalSteps; i++)
|
||||
{
|
||||
points[i] = GetPointOnQuadraticCurve(p1, p2, p3, curStep);
|
||||
curStep += step;
|
||||
}
|
||||
|
@ -225,30 +231,33 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
return points;
|
||||
}
|
||||
|
||||
public static void CreateCubicCurve(CurveSegment segment, int steps) {
|
||||
public static void CreateCubicCurve(CurveSegment segment, int steps)
|
||||
{
|
||||
segment.CurveType = CurveSegmentType.CUBIC;
|
||||
segment.Points = GetCubicCurve(segment.Start, segment.End, segment.CPStart, segment.CPEnd, steps);
|
||||
segment.UpdateLength();
|
||||
}
|
||||
|
||||
//this returns array of Vector2D to draw 4-point bezier curve
|
||||
public static Vector2D[] GetCubicCurve(Vector2D p1, Vector2D p2, Vector2D cp1, Vector2D cp2, int steps) {
|
||||
if(steps < 0)
|
||||
return null;
|
||||
public static Vector2D[] GetCubicCurve(Vector2D p1, Vector2D p2, Vector2D cp1, Vector2D cp2, int steps)
|
||||
{
|
||||
if(steps < 0) return null;
|
||||
|
||||
int totalSteps = steps + 1;
|
||||
Vector2D[] points = new Vector2D[totalSteps];
|
||||
float step = 1f / steps;
|
||||
float curStep = 0f;
|
||||
|
||||
for(int i = 0; i < totalSteps; i++) {
|
||||
for(int i = 0; i < totalSteps; i++)
|
||||
{
|
||||
points[i] = GetPointOnCubicCurve(p1, p2, cp1, cp2, curStep);
|
||||
curStep += step;
|
||||
}
|
||||
return points;
|
||||
}
|
||||
|
||||
public static Vector2D GetPointOnCurve(CurveSegment segment, float delta) {
|
||||
public static Vector2D GetPointOnCurve(CurveSegment segment, float delta)
|
||||
{
|
||||
if(segment.CurveType == CurveSegmentType.QUADRATIC)
|
||||
return GetPointOnQuadraticCurve(segment.Start, segment.CPMid, segment.End, delta);
|
||||
|
||||
|
@ -261,7 +270,8 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
throw new Exception("GetPointOnCurve: got unknown curve type: " + segment.CurveType);
|
||||
}
|
||||
|
||||
public static Vector2D GetPointOnQuadraticCurve(Vector2D p1, Vector2D p2, Vector2D p3, float delta) {
|
||||
public static Vector2D GetPointOnQuadraticCurve(Vector2D p1, Vector2D p2, Vector2D p3, float delta)
|
||||
{
|
||||
float invDelta = 1f - delta;
|
||||
|
||||
float m1 = invDelta * invDelta;
|
||||
|
@ -274,7 +284,8 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
return new Vector2D(px, py);
|
||||
}
|
||||
|
||||
public static Vector2D GetPointOnCubicCurve(Vector2D p1, Vector2D p2, Vector2D cp1, Vector2D cp2, float delta) {
|
||||
public static Vector2D GetPointOnCubicCurve(Vector2D p1, Vector2D p2, Vector2D cp1, Vector2D cp2, float delta)
|
||||
{
|
||||
float invDelta = 1f - delta;
|
||||
|
||||
float m1 = invDelta * invDelta * invDelta;
|
||||
|
@ -289,7 +300,8 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
}
|
||||
|
||||
//it's basically 2-point bezier curve
|
||||
public static Vector2D GetPointOnLine(Vector2D p1, Vector2D p2, float delta) {
|
||||
public static Vector2D GetPointOnLine(Vector2D p1, Vector2D p2, float delta)
|
||||
{
|
||||
return new Vector2D((int)((1f - delta) * p1.x + delta * p2.x), (int)((1f - delta) * p1.y + delta * p2.y));
|
||||
}
|
||||
}
|
||||
|
@ -300,29 +312,34 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
public List<Vector2D> Shape;
|
||||
public float Length;
|
||||
|
||||
public Curve() {
|
||||
public Curve()
|
||||
{
|
||||
Segments = new List<CurveSegment>();
|
||||
}
|
||||
|
||||
public void UpdateShape() {
|
||||
public void UpdateShape()
|
||||
{
|
||||
Shape = new List<Vector2D>();
|
||||
Length = 0;
|
||||
|
||||
foreach(CurveSegment segment in Segments) {
|
||||
foreach(CurveSegment segment in Segments)
|
||||
{
|
||||
Length += segment.Length;
|
||||
|
||||
foreach(Vector2D point in segment.Points) {
|
||||
foreach(Vector2D point in segment.Points)
|
||||
{
|
||||
if(Shape.Count == 0 || point != Shape[Shape.Count - 1])
|
||||
Shape.Add(point);
|
||||
}
|
||||
}
|
||||
|
||||
float curDelta = 0;
|
||||
for(int i = 0; i < Segments.Count; i++) {
|
||||
/*float curDelta = 0;
|
||||
for(int i = 0; i < Segments.Count; i++)
|
||||
{
|
||||
Segments[i].Delta = Segments[i].Length / Length;
|
||||
curDelta += Segments[i].Delta;
|
||||
Segments[i].GlobalDelta = curDelta;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -335,11 +352,12 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
public Vector2D CPMid;
|
||||
public Vector2D CPEnd;
|
||||
public float Length;
|
||||
public float Delta; //length of this segment / total curve length
|
||||
public float GlobalDelta; //length of this segment / total curve length + deltas of previous segments
|
||||
//public float Delta; //length of this segment / total curve length
|
||||
//public float GlobalDelta; //length of this segment / total curve length + deltas of previous segments
|
||||
public CurveSegmentType CurveType;
|
||||
|
||||
public void UpdateLength() {
|
||||
public void UpdateLength()
|
||||
{
|
||||
if(Points.Length < 2)
|
||||
return;
|
||||
|
||||
|
|
|
@ -91,7 +91,8 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
}
|
||||
|
||||
//mxd. This tests if given lines intersects
|
||||
public static bool GetIntersection(Line2D line1, Line2D line2) {
|
||||
public static bool GetIntersection(Line2D line1, Line2D line2)
|
||||
{
|
||||
return GetIntersection(line1.v1, line1.v2, line2.v1.x, line2.v1.y, line2.v2.x, line2.v2.y);
|
||||
}
|
||||
|
||||
|
|
|
@ -104,14 +104,15 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
}
|
||||
|
||||
//mxd. Addeed to make compiler a bit more happy...
|
||||
public override int GetHashCode() {
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return base.GetHashCode();
|
||||
}
|
||||
|
||||
//mxd. Addeed to make compiler a bit more happy...
|
||||
public override bool Equals(object obj) {
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if(object.Equals(obj, null)) return false;
|
||||
|
||||
LinedefSide other = (LinedefSide)obj;
|
||||
return (this.line == other.line) && (this.front == other.front);
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue