From 3a0426cd7f56cb200855b86fc2e3ed5fa99e704c Mon Sep 17 00:00:00 2001 From: MaxED <j.maxed@gmail.com> Date: Mon, 21 May 2012 23:51:32 +0000 Subject: [PATCH] GZDoomBuilder 1.06a: MODELDEFs and models can now be loaded from PK3 resources (does anybody know if models or MODELDEFs can be stored in WADs?). Negative scale and zOffset are now correctly parsed from MODELDEFs (model surfaces may be inverted though). Fixed a crash while reading MODELDEFs when Operation System's decimal separator was set to comma. Fixed a crash when user changed Thing type in Visual mode to a new one with model override, which wasn't previously used in a map. Fixed a bug introduced in 1.06 when models weren't rendered in Visual mode when Fullbright mode was on. Non-breaking space is now correctly handled by all Doom Builder's data parsers. ColorPicker plugin: Fixed a crash when user attempted to open ColorPicker window to edit sector properties in Visual mode, using hilighted surface as selection source, without selecting anything before doing so. --- Build/Configurations/Includes/Doom_things.cfg | 2 +- Source/Core/Builder.csproj | 5 +- Source/Core/Builder.sln | 12 - Source/Core/Data/DataManager.cs | 135 +++++++++- Source/Core/Data/DataReader.cs | 7 + Source/Core/Data/DirectoryReader.cs | 4 +- Source/Core/Data/PK3Reader.cs | 9 +- Source/Core/Data/PK3StructuredReader.cs | 36 ++- Source/Core/Data/WADReader.cs | 1 - Source/Core/GZBuilder/Data/ModelDefEntry.cs | 26 +- .../Core/GZBuilder/GZDoom/ModeldefParser.cs | 88 +++++++ .../GZBuilder/GZDoom/ModeldefStructure.cs | 230 ++++++++++++++++++ Source/Core/GZBuilder/GZGeneral.cs | 122 +++------- Source/Core/GZBuilder/IO/ModelDefParser.cs | 197 --------------- Source/Core/GZBuilder/md3/GZModel.cs | 2 +- Source/Core/GZBuilder/md3/ModelReader.cs | 197 ++++++--------- Source/Core/General/MapManager.cs | 6 + Source/Core/IO/WAD.cs | 4 +- Source/Core/Rendering/Renderer2D.cs | 8 +- Source/Core/Rendering/Renderer3D.cs | 13 +- Source/Core/VisualModes/VisualMode.cs | 2 +- Source/Core/VisualModes/VisualThing.cs | 31 +-- Source/Core/ZDoom/DecorateParser.cs | 2 +- Source/Core/ZDoom/TexturesParser.cs | 2 +- Source/Core/ZDoom/ZDTextParser.cs | 30 ++- .../VisualModes/BaseVisualThing.cs | 14 ++ .../GZDoomEditing/GZDoomEditing.csproj | 1 + .../VisualModes/BaseVisualThing.cs | 14 ++ 28 files changed, 708 insertions(+), 492 deletions(-) create mode 100644 Source/Core/GZBuilder/GZDoom/ModeldefParser.cs create mode 100644 Source/Core/GZBuilder/GZDoom/ModeldefStructure.cs delete mode 100644 Source/Core/GZBuilder/IO/ModelDefParser.cs diff --git a/Build/Configurations/Includes/Doom_things.cfg b/Build/Configurations/Includes/Doom_things.cfg index 601ccbb33..04ead12c6 100644 --- a/Build/Configurations/Includes/Doom_things.cfg +++ b/Build/Configurations/Includes/Doom_things.cfg @@ -367,7 +367,7 @@ powerups title = "Invisibility"; sprite = "PINSA0"; height = 45; - class = "BlurSphere "; + class = "BlurSphere"; } 2025 { diff --git a/Source/Core/Builder.csproj b/Source/Core/Builder.csproj index 68e292f78..72858a373 100644 --- a/Source/Core/Builder.csproj +++ b/Source/Core/Builder.csproj @@ -713,10 +713,11 @@ </Compile> <Compile Include="GZBuilder\Data\BoundingBox.cs" /> <Compile Include="GZBuilder\Data\GZDoomLight.cs" /> - <Compile Include="GZBuilder\Data\ModelDefEntry.cs" /> + <Compile Include="GZBuilder\Data\ModeldefEntry.cs" /> <Compile Include="GZBuilder\Data\ThingBoundingBox.cs" /> + <Compile Include="GZBuilder\GZDoom\ModeldefParser.cs" /> + <Compile Include="GZBuilder\GZDoom\ModeldefStructure.cs" /> <Compile Include="GZBuilder\GZGeneral.cs" /> - <Compile Include="GZBuilder\IO\ModelDefParser.cs" /> <Compile Include="GZBuilder\md3\GZModel.cs" /> <Compile Include="GZBuilder\md3\ModelReader.cs" /> <Compile Include="IO\DoomColormapReader.cs" /> diff --git a/Source/Core/Builder.sln b/Source/Core/Builder.sln index 8b5d3259a..9a59c6360 100644 --- a/Source/Core/Builder.sln +++ b/Source/Core/Builder.sln @@ -3,8 +3,6 @@ Microsoft Visual Studio Solution File, Format Version 10.00 # Visual C# Express 2008 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Builder", "Builder.csproj", "{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ColorPicker", "..\Plugins\ColorPicker\ColorPicker.csproj", "{A4761900-0EA3-4FE4-A919-847FD5080EFC}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -25,16 +23,6 @@ Global {818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Release|Mixed Platforms.Build.0 = Release|x86 {818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Release|x86.ActiveCfg = Release|x86 {818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Release|x86.Build.0 = Release|x86 - {A4761900-0EA3-4FE4-A919-847FD5080EFC}.Debug|Any CPU.ActiveCfg = Debug|x86 - {A4761900-0EA3-4FE4-A919-847FD5080EFC}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {A4761900-0EA3-4FE4-A919-847FD5080EFC}.Debug|Mixed Platforms.Build.0 = Debug|x86 - {A4761900-0EA3-4FE4-A919-847FD5080EFC}.Debug|x86.ActiveCfg = Debug|x86 - {A4761900-0EA3-4FE4-A919-847FD5080EFC}.Debug|x86.Build.0 = Debug|x86 - {A4761900-0EA3-4FE4-A919-847FD5080EFC}.Release|Any CPU.ActiveCfg = Release|x86 - {A4761900-0EA3-4FE4-A919-847FD5080EFC}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {A4761900-0EA3-4FE4-A919-847FD5080EFC}.Release|Mixed Platforms.Build.0 = Release|x86 - {A4761900-0EA3-4FE4-A919-847FD5080EFC}.Release|x86.ActiveCfg = Release|x86 - {A4761900-0EA3-4FE4-A919-847FD5080EFC}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Source/Core/Data/DataManager.cs b/Source/Core/Data/DataManager.cs index e393814c9..f01c688f1 100644 --- a/Source/Core/Data/DataManager.cs +++ b/Source/Core/Data/DataManager.cs @@ -33,6 +33,10 @@ using CodeImp.DoomBuilder.Map; using CodeImp.DoomBuilder.Windows; using CodeImp.DoomBuilder.ZDoom; +using CodeImp.DoomBuilder.GZBuilder.Data; +using CodeImp.DoomBuilder.GZBuilder.GZDoom; +using CodeImp.DoomBuilder.GZBuilder.MD3; + #endregion namespace CodeImp.DoomBuilder.Data @@ -65,7 +69,10 @@ namespace CodeImp.DoomBuilder.Data private AllTextureSet alltextures; //mxd Folders - private List<string> folders; + //private List<string> folders; + + //mxd modeldefs + private Dictionary<int, ModeldefEntry> modeldefEntries; // Background loading private Queue<ImageData> imageque; @@ -107,7 +114,8 @@ namespace CodeImp.DoomBuilder.Data #region ================== Properties //mxd - public List<string> Folders { get { return folders; } } + //public List<string> Folders { get { return folders; } } + public Dictionary<int, ModeldefEntry> ModeldefEntries { get { return modeldefEntries; } } public Playpal Palette { get { return palette; } } public PreviewManager Previews { get { return previews; } } @@ -247,9 +255,6 @@ namespace CodeImp.DoomBuilder.Data internalsprites = new Dictionary<string, ImageData>(); thingcategories = General.Map.Config.GetThingCategories(); thingtypes = General.Map.Config.GetThingTypes(); - - //mxd - folders = new List<string>(); // Load texture sets foreach(DefinedTextureSet ts in General.Map.ConfigSettings.TextureSets) @@ -285,10 +290,6 @@ namespace CodeImp.DoomBuilder.Data // Directory container case DataLocation.RESOURCE_DIRECTORY: c = new DirectoryReader(dl); - - //mxd - folders.Add(dl.location); - break; // PK3 file container @@ -322,6 +323,9 @@ namespace CodeImp.DoomBuilder.Data thingcount = LoadDecorateThings(); spritecount = LoadThingSprites(); LoadInternalSprites(); + + //mxd + loadModeldefs(); // Process colormaps (we just put them in as textures) foreach(KeyValuePair<long, ImageData> t in colormapsonly) @@ -434,6 +438,13 @@ namespace CodeImp.DoomBuilder.Data foreach(KeyValuePair<long, ImageData> i in flats) i.Value.Dispose(); foreach(KeyValuePair<long, ImageData> i in sprites) i.Value.Dispose(); palette = null; + + //mxd + if (modeldefEntries != null) { + foreach (KeyValuePair<int, ModeldefEntry> group in modeldefEntries) { + group.Value.Dispose(); + } + } // Dispose containers foreach(DataReader c in containers) c.Dispose(); @@ -1342,10 +1353,110 @@ namespace CodeImp.DoomBuilder.Data } #endregion - - #region ================== Tools - // This finds the first IWAD resource + #region ================== Modeldef and models + + public void LoadModels() { + General.MainWindow.DisplayStatus(StatusType.Busy, "Loading models..."); + + foreach (Thing t in General.Map.Map.Things) + LoadModelForThing(t); + + General.MainWindow.RedrawDisplay(); + } + + public bool LoadModelForThing(Thing t) { + if (modeldefEntries.ContainsKey(t.Type)) { + if (modeldefEntries[t.Type].Model == null) { + //load model and texture + ModeldefEntry mde = modeldefEntries[t.Type]; + + foreach (DataReader dr in containers) { + currentreader = dr; + if (currentreader.Location.location == mde.Location) { + ModelReader.Parse(ref mde, (PK3StructuredReader)currentreader, General.Map.Graphics.Device); + break; + } + } + currentreader = null; + + if (mde.Model != null) { + GZBuilder.GZGeneral.LogAndTraceWarning("Loaded model for Thing ¹" + t.Type); + return true; + } else { + modeldefEntries.Remove(t.Type); + GZBuilder.GZGeneral.LogAndTraceWarning("Failed to load model(s) for Thing ¹" + t.Type + ", model(s) location is "+mde.Location+ "\\" + mde.Path +". MODELDEF node removed."); + return false; + } + } + return true; + } + return false; + } + + //mxd. This parses modeldefs + private void loadModeldefs() { + General.MainWindow.DisplayStatus(StatusType.Busy, "Parsing model definitions..."); + + Dictionary<string, int> Actors = new Dictionary<string, int>(); + Dictionary<int, ThingTypeInfo> things = General.Map.Config.GetThingTypes(); + + //read our new shiny ClassNames for default game 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; //General.Map.Data.Decorate.Actors; + foreach (ActorStructure actor in ac) { + string className = actor.ClassName.ToLower(); + if (actor.DoomEdNum != -1 && !Actors.ContainsKey(className)) //we don't need actors without DoomEdNum + Actors.Add(className, actor.DoomEdNum); + } + + Dictionary<string, ModeldefEntry> modelDefEntriesByName = new Dictionary<string, ModeldefEntry>(); + ModeldefParser mdeParser = new ModeldefParser(); + + foreach (DataReader dr in containers) { + currentreader = dr; + + Dictionary<string, Stream> streams = dr.GetModeldefData(); + foreach (KeyValuePair<string, Stream> group in streams) { + //dbg + GZBuilder.GZGeneral.Trace("Adding mdes from " + currentreader.Location.location); + + // Parse the data + group.Value.Seek(0, SeekOrigin.Begin); + mdeParser.Parse(group.Value, currentreader.Location.location + "\\" + group.Key); + Dictionary<string, ModeldefEntry> mdes = mdeParser.ModelDefEntries; + + if (mdes != null) { + foreach (KeyValuePair<string, ModeldefEntry> g in mdes) { + g.Value.Location = currentreader.Location.location; + modelDefEntriesByName.Add(g.Key, g.Value); + } + } + } + } + + currentreader = null; + modeldefEntries = new Dictionary<int, ModeldefEntry>(); + + foreach (KeyValuePair<string, ModeldefEntry> e in modelDefEntriesByName) { + if (Actors.ContainsKey(e.Key)) { + modeldefEntries[Actors[e.Key]] = modelDefEntriesByName[e.Key]; + } else { + GZBuilder.GZGeneral.LogAndTraceWarning("Got MODELDEF override for class '" + e.Key + "', but haven't found such class in Decorate"); + } + } + } + + #endregion + + #region ================== Tools + + // This finds the first IWAD resource // Returns false when not found internal bool FindFirstIWAD(out DataLocation result) { diff --git a/Source/Core/Data/DataReader.cs b/Source/Core/Data/DataReader.cs index 27a5099f6..50da0f4d3 100644 --- a/Source/Core/Data/DataReader.cs +++ b/Source/Core/Data/DataReader.cs @@ -156,6 +156,13 @@ namespace CodeImp.DoomBuilder.Data // When implemented, this returns the decorate lump public virtual List<Stream> GetDecorateData(string pname) { return new List<Stream>(); } + //mxd. When implemented, this returns the modeldef lump + public virtual Dictionary<string, Stream> GetModeldefData() { return new Dictionary<string, Stream>(); } + + //mxd + //public Stream GetModel(string path) { return null; } + //protected abstract MemoryStream LoadFile(string filename); + #endregion } } diff --git a/Source/Core/Data/DirectoryReader.cs b/Source/Core/Data/DirectoryReader.cs index ea22d8e52..e32ae4fb6 100644 --- a/Source/Core/Data/DirectoryReader.cs +++ b/Source/Core/Data/DirectoryReader.cs @@ -268,7 +268,7 @@ namespace CodeImp.DoomBuilder.Data } // This returns true if the specified file exists - protected override bool FileExists(string filename) + public override bool FileExists(string filename) { return files.FileExists(filename); } @@ -314,7 +314,7 @@ namespace CodeImp.DoomBuilder.Data // This loads an entire file in memory and returns the stream // NOTE: Callers are responsible for disposing the stream! - protected override MemoryStream LoadFile(string filename) + public override MemoryStream LoadFile(string filename) { return new MemoryStream(File.ReadAllBytes(Path.Combine(location.location, filename))); } diff --git a/Source/Core/Data/PK3Reader.cs b/Source/Core/Data/PK3Reader.cs index ec0fc5b43..05319c2b1 100644 --- a/Source/Core/Data/PK3Reader.cs +++ b/Source/Core/Data/PK3Reader.cs @@ -267,7 +267,7 @@ namespace CodeImp.DoomBuilder.Data } // This returns true if the specified file exists - protected override bool FileExists(string filename) + public override bool FileExists(string filename) { return files.FileExists(filename); } @@ -313,7 +313,7 @@ namespace CodeImp.DoomBuilder.Data // This loads an entire file in memory and returns the stream // NOTE: Callers are responsible for disposing the stream! - protected override MemoryStream LoadFile(string filename) + public override MemoryStream LoadFile(string filename) { MemoryStream filedata = null; byte[] copybuffer = new byte[4096]; @@ -359,7 +359,10 @@ namespace CodeImp.DoomBuilder.Data } else { - return filedata; + //mxd. rewind before use + filedata.Position = 0; + + return filedata; } } diff --git a/Source/Core/Data/PK3StructuredReader.cs b/Source/Core/Data/PK3StructuredReader.cs index 9b24fabb7..af3cbcc11 100644 --- a/Source/Core/Data/PK3StructuredReader.cs +++ b/Source/Core/Data/PK3StructuredReader.cs @@ -417,10 +417,32 @@ namespace CodeImp.DoomBuilder.Data } #endregion - - #region ================== Methods - - // This loads the images in this directory + + #region ================== Modeldef + + //mxd + public override Dictionary<string, Stream> GetModeldefData() { + Dictionary<string, Stream> streams = new Dictionary<string, Stream>(); + // Error when suspended + if (issuspended) throw new Exception("Data reader is suspended"); + + //modedef should be in root folder + string[] allFiles = GetAllFiles("", false); + + foreach (string s in allFiles) { + if (s.ToLowerInvariant().IndexOf("modeldef") != -1) { + streams.Add(s, LoadFile(s)); + } + } + + return streams; + } + + #endregion + + #region ================== Methods + + // This loads the images in this directory private ICollection<ImageData> LoadDirectoryImages(string path, int imagetype, bool includesubdirs) { List<ImageData> images = new List<ImageData>(); @@ -466,7 +488,8 @@ namespace CodeImp.DoomBuilder.Data protected abstract ImageData CreateImage(string name, string filename, int imagetype); // This must return true if the specified file exists - protected abstract bool FileExists(string filename); + //mxd + public abstract bool FileExists(string filename); // This must return all files in a given directory protected abstract string[] GetAllFiles(string path, bool subfolders); @@ -488,7 +511,8 @@ namespace CodeImp.DoomBuilder.Data // This must load an entire file in memory and returns the stream // NOTE: Callers are responsible for disposing the stream! - protected abstract MemoryStream LoadFile(string filename); + //mxd + public abstract MemoryStream LoadFile(string filename); // This must create a temp file for the speciied file and return the absolute path to the temp file // NOTE: Callers are responsible for removing the temp file when done! diff --git a/Source/Core/Data/WADReader.cs b/Source/Core/Data/WADReader.cs index fb8cdd086..80d77c219 100644 --- a/Source/Core/Data/WADReader.cs +++ b/Source/Core/Data/WADReader.cs @@ -816,7 +816,6 @@ namespace CodeImp.DoomBuilder.Data return streams; } - #endregion } } diff --git a/Source/Core/GZBuilder/Data/ModelDefEntry.cs b/Source/Core/GZBuilder/Data/ModelDefEntry.cs index 74a3524f1..40e53842d 100644 --- a/Source/Core/GZBuilder/Data/ModelDefEntry.cs +++ b/Source/Core/GZBuilder/Data/ModelDefEntry.cs @@ -5,27 +5,39 @@ using System.Text; using SlimDX; using SlimDX.Direct3D9; -using ColladaDotNet.Pipeline.MD3; +using CodeImp.DoomBuilder.GZBuilder.MD3; namespace CodeImp.DoomBuilder.GZBuilder.Data { - public class ModelDefEntry + public class ModeldefEntry { - public string Name; - public string Path; + public string ClassName; + public string Path; //this holds Path parameter of MODELDEF entry public List<string> ModelNames; public List<string> TextureNames; + public string Location; //this holds location of resource, from which modeldef was loaded public GZModel Model; public Vector3 Scale; public float zOffset; - public ModelDefEntry() { - Scale = new Vector3(1, 1, 1); - zOffset = 0; + public ModeldefEntry() { ModelNames = new List<string>(); TextureNames = new List<string>(); } + + public void Dispose() { + if (Model != null) { + foreach (IndexBuffer ib in Model.Indeces2D) + ib.Dispose(); + + foreach (Mesh mesh in Model.Meshes) + mesh.Dispose(); + + foreach (Texture t in Model.Textures) + t.Dispose(); + } + } } } diff --git a/Source/Core/GZBuilder/GZDoom/ModeldefParser.cs b/Source/Core/GZBuilder/GZDoom/ModeldefParser.cs new file mode 100644 index 000000000..af491586a --- /dev/null +++ b/Source/Core/GZBuilder/GZDoom/ModeldefParser.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +using CodeImp.DoomBuilder.ZDoom; +using CodeImp.DoomBuilder.GZBuilder.Data; +using CodeImp.DoomBuilder.GZBuilder.GZDoom; + +namespace CodeImp.DoomBuilder.GZBuilder.GZDoom { + + public class ModeldefParser : ZDTextParser { + public static string INVALID_TEXTURE = "**INVALID_TEXTURE**"; + + private Dictionary<string, ModeldefEntry> modelDefEntries; //classname, entry + public Dictionary<string, ModeldefEntry> ModelDefEntries { get { return modelDefEntries; } } + + public string Source { get { return sourcename; } } + + //should be called after all decorate actors are parsed + public override bool Parse(Stream stream, string sourcefilename) { + base.Parse(stream, sourcefilename); + modelDefEntries = new Dictionary<string, ModeldefEntry>(); + + // Continue until at the end of the stream + while (SkipWhitespace(true)) { + string token = ReadToken(); + if (token != null) { + token = token.ToLowerInvariant(); + + if (token == "model") { //model structure start + //find classname + SkipWhitespace(true); + string className = StripTokenQuotes(ReadToken()).ToLowerInvariant(); + + if (!string.IsNullOrEmpty(className)) { + if (modelDefEntries.ContainsKey(className)) + continue; //already got this class; continue to next one + + //now find opening brace + SkipWhitespace(true); + token = ReadToken(); + if (token != "{") { + GZBuilder.GZGeneral.LogAndTraceWarning("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(); + ModeldefEntry mde = mds.Parse(this); + if (mde != null) { + GZBuilder.GZGeneral.Trace("Got mds for class " + className); + mde.ClassName = className; + modelDefEntries.Add(className, mde); + } + } else { + continue; //no class name found. continue to next structure + } + + } else { + // Unknown structure! + string token2; + do { + if (!SkipWhitespace(true)) break; + token2 = ReadToken(); + if (token2 == null) break; + } + while (token2 != "{"); + int scopelevel = 1; + do { + if (!SkipWhitespace(true)) break; + token2 = ReadToken(); + if (token2 == null) break; + if (token2 == "{") scopelevel++; + if (token2 == "}") scopelevel--; + } + while (scopelevel > 0); + } + + } + + } + + if (modelDefEntries.Count > 0) + return true; + return false; + } + } +} diff --git a/Source/Core/GZBuilder/GZDoom/ModeldefStructure.cs b/Source/Core/GZBuilder/GZDoom/ModeldefStructure.cs new file mode 100644 index 000000000..9c53faaf7 --- /dev/null +++ b/Source/Core/GZBuilder/GZDoom/ModeldefStructure.cs @@ -0,0 +1,230 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Text; + +using SlimDX; +using SlimDX.Direct3D9; + +using CodeImp.DoomBuilder.GZBuilder.Data; + +namespace CodeImp.DoomBuilder.GZBuilder.GZDoom { + public sealed class ModeldefStructure { + private string[] supportedTextureExtensions = { ".jpg", ".tga", ".png", ".dds" }; + + public ModeldefEntry Parse(ModeldefParser parser) { + string[] textureNames = new string[16]; + string[] modelNames = new string[16]; + string path = ""; + Vector3 scale = new Vector3(1, 1, 1); + float zOffset = 0; + string token; + bool gotErrors = false; + + //read modeldef structure contents + while (parser.SkipWhitespace(true)) { + token = parser.ReadToken(); + + if (!string.IsNullOrEmpty(token)) { + token = token.ToLowerInvariant(); + + char a = token[0]; + char c = " "[0]; + bool b1 = Char.IsWhiteSpace(a); + bool b2 = Char.IsWhiteSpace(c); + bool f; + +//path + if (token == "path") { + parser.SkipWhitespace(true); + path = parser.StripTokenQuotes(parser.ReadToken()).Replace("/", "\\"); + + if (string.IsNullOrEmpty(path)) { + GZBuilder.GZGeneral.LogAndTraceWarning("Expected path to model, but got '" + token + "' in " + parser.Source + " at line "+parser.GetCurrentLineNumber()); + //GZBuilder.GZGeneral.LogAndTraceWarning("Expected path to model, but got '" + token + "'"); + gotErrors = true; + break; + } +//model + } else if (token == "model") { + parser.SkipWhitespace(true); + + //model index + int modelIndex; + token = parser.ReadToken(); + if (!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out modelIndex)) { + // Not numeric! + GZBuilder.GZGeneral.LogAndTraceWarning("Expected model index, but got '" + token + "' in " + parser.Source + " at line " + parser.GetCurrentLineNumber()); + gotErrors = true; + break; + } + + //model path + token = parser.StripTokenQuotes(parser.ReadToken()).ToLowerInvariant(); + if (string.IsNullOrEmpty(token)) { + GZBuilder.GZGeneral.LogAndTraceWarning("Expected model name, but got '" + token + "' in " + parser.Source + " at line " + parser.GetCurrentLineNumber()); + gotErrors = true; + break; + } else { + //check extension + int dotPos = token.LastIndexOf("."); + string fileExt = token.Substring(token.LastIndexOf("."), token.Length - dotPos); + if (fileExt != ".md3" && fileExt != ".md2") { + GZBuilder.GZGeneral.LogAndTraceWarning("Model '" + token + "' not parsed in " + parser.Source + " at line " + parser.GetCurrentLineNumber() +". Only MD3 and MD2 models are supported."); + gotErrors = true; + break; + } + + if (modelNames[modelIndex] != null) { + GZBuilder.GZGeneral.LogAndTraceWarning("Error: already got model for index " + modelIndex + " in " + parser.Source + " at line " + parser.GetCurrentLineNumber()); + gotErrors = true; + break; + } else { + modelNames[modelIndex] = token; + } + } +//skin + } else if (token == "skin") { + parser.SkipWhitespace(true); + + //skin index + int skinIndex; + token = parser.ReadToken(); + if (!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out skinIndex)) { + // Not numeric! + GZBuilder.GZGeneral.LogAndTraceWarning("Expected skin index, but got '" + token + "' in " + parser.Source + " at line " + parser.GetCurrentLineNumber()); + gotErrors = true; + break; + } + + //skin path + token = parser.StripTokenQuotes(parser.ReadToken()).ToLowerInvariant(); + if (string.IsNullOrEmpty(token)) { + GZBuilder.GZGeneral.LogAndTraceWarning("Expected skin name, but got '" + token + "' in " + parser.Source + " at line " + parser.GetCurrentLineNumber()); + gotErrors = true; + break; + } else { + //check extension + int dotPos = token.LastIndexOf("."); + string fileExt = token.Substring(token.LastIndexOf("."), token.Length - dotPos); + if(Array.IndexOf(supportedTextureExtensions, fileExt) == -1) + token = ModeldefParser.INVALID_TEXTURE; + + if (textureNames[skinIndex] != null) { + GZBuilder.GZGeneral.LogAndTraceWarning("Already got model for index " + skinIndex + " in " + parser.Source + " at line " + parser.GetCurrentLineNumber()); + gotErrors = true; + break; + } else { + textureNames[skinIndex] = token; + } + } +//scale + } else if (token == "scale") { + parser.SkipWhitespace(true); + + token = parser.ReadToken(); + + int sign = 1; + if (token == "-") { + sign = -1; + token = parser.ReadToken(); + } + + if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out scale.X)) { + // Not numeric! + GZBuilder.GZGeneral.LogAndTraceWarning("Expected scale X value, but got '" + token + "' in " + parser.Source + " at line " + parser.GetCurrentLineNumber()); + gotErrors = true; + break; + } + scale.X *= sign; + + parser.SkipWhitespace(true); + + token = parser.ReadToken(); + + sign = 1; + if (token == "-") { + sign = -1; + token = parser.ReadToken(); + } + + if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out scale.Y)) { + // Not numeric! + GZBuilder.GZGeneral.LogAndTraceWarning("Expected scale Y value, but got '" + token + "' in " + parser.Source + " at line " + parser.GetCurrentLineNumber()); + gotErrors = true; + break; + } + scale.Y *= sign; + + + parser.SkipWhitespace(true); + + token = parser.ReadToken(); + + sign = 1; + if (token == "-") { + sign = -1; + token = parser.ReadToken(); + } + + if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out scale.Z)) { + // Not numeric! + GZBuilder.GZGeneral.LogAndTraceWarning("Expected scale Z value, but got '" + token + "' in " + parser.Source + " at line " + parser.GetCurrentLineNumber()); + gotErrors = true; + break; + } + scale.Z *= sign; +//zoffset + } else if (token == "zoffset") { + parser.SkipWhitespace(true); + + token = parser.ReadToken(); + + int sign = 1; + if (token == "-") { + sign = -1; + token = parser.ReadToken(); + } + + if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out zOffset)) { + // Not numeric! + GZBuilder.GZGeneral.LogAndTraceWarning("Expected ZOffset value, but got '" + token + "' in " + parser.Source + " at line " + parser.GetCurrentLineNumber()); + gotErrors = true; + break; + } + zOffset *= sign; +//frameindex + } else if (token == "frameindex") { + //parsed all required fields + break; + } + } + } + + //find closing brace, then quit; + while (parser.SkipWhitespace(true)) { + token = parser.ReadToken(); + if (token == "}") + break; + } + + if (gotErrors) + return null; + + //classname is set in ModeldefParser + ModeldefEntry mde = new ModeldefEntry(); + mde.Path = path; + mde.Scale = scale; + mde.zOffset = zOffset; + + for (int i = 0; i < textureNames.Length; i++ ) { + if (textureNames[i] != null && modelNames[i] != null) { + mde.TextureNames.Add(textureNames[i]); + mde.ModelNames.Add(modelNames[i]); + } + } + + return mde; + } + } +} diff --git a/Source/Core/GZBuilder/GZGeneral.cs b/Source/Core/GZBuilder/GZGeneral.cs index 17c5797c9..e0b4b8eb8 100644 --- a/Source/Core/GZBuilder/GZGeneral.cs +++ b/Source/Core/GZBuilder/GZGeneral.cs @@ -10,20 +10,14 @@ using CodeImp.DoomBuilder.Actions; using CodeImp.DoomBuilder.Windows; using CodeImp.DoomBuilder.Config; -using CodeImp.DoomBuilder.GZBuilder.IO; using CodeImp.DoomBuilder.GZBuilder.Data; using CodeImp.DoomBuilder.GZBuilder.Controls; -using ColladaDotNet.Pipeline.MD3; - namespace CodeImp.DoomBuilder.GZBuilder { //mxd. should get rid of this class one day... public class GZGeneral { - private static Dictionary<int, ModelDefEntry> modelDefEntries; //doomEdNum, entry - public static Dictionary<int, ModelDefEntry> ModelDefEntries { get { return modelDefEntries; } } - //gzdoom light types private static int[] gzLights = { /* normal lights */ 9800, 9801, 9802, 9803, 9804, /* additive lights */ 9810, 9811, 9812, 9813, 9814, /* negative lights */ 9820, 9821, 9822, 9823, 9824, /* vavoom lights */ 1502, 1503}; public static int[] GZ_LIGHTS { get { return gzLights; } } @@ -34,6 +28,8 @@ namespace CodeImp.DoomBuilder.GZBuilder public static bool UDMF; + //public static float[] FogTable; // light to fog conversion table for black fog + //version public const float Version = 1.06f; @@ -48,6 +44,26 @@ namespace CodeImp.DoomBuilder.GZBuilder General.Actions.BindMethods(typeof(GZGeneral)); General.MainWindow.UpdateGZDoomPannel(); + //create fog table + /*FogTable = new float[256]; + byte gl_distfog = 255; + + for (int i = 0; i < 256; i++) { + if (i < 164) { + FogTable[i] = (gl_distfog >> 1) + (gl_distfog) * (164 - i) / 164; + } else if (i < 230) { + FogTable[i] = (gl_distfog >> 1) - (gl_distfog >> 1) * (i - 164) / (230 - 164); + } else FogTable[i] = 0; + + //if (i < 128) { + //distfogtable[1][i] = 6.f + (gl_distfog >> 1) + (gl_distfog) * (128 - i) / 48; + //} else if (i < 216) { + //distfogtable[1][i] = (216.f - i) / ((216.f - 128.f)) * gl_distfog / 10; + //} else distfogtable[1][i] = 0; + }*/ + + //float[] ft = FogTable; + //create console #if DEBUG ConsoleDocker cd = new ConsoleDocker(); @@ -58,105 +74,25 @@ namespace CodeImp.DoomBuilder.GZBuilder } public static void OnMapOpenEnd() { - loadModelDefs(); - loadModels(); UDMF = (General.Map.Config.FormatInterface == "UniversalMapSetIO"); General.MainWindow.UpdateGZDoomPannel(); } public static void OnReloadResources() { - loadModelDefs(); - loadModels(); - #if DEBUG ((ConsoleDocker)console.Control).Clear(); #endif } - public static bool LoadModelForThing(Thing t) { - if (modelDefEntries.ContainsKey(t.Type)) { - string msg = "GZBuilder: got model override for Thing â„–" + t.Type; - General.ErrorLogger.Add(ErrorType.Warning, msg); - General.WriteLogLine(msg); - - if (modelDefEntries[t.Type].Model == null) { - //load model and texture - ModelDefEntry mde = modelDefEntries[t.Type]; - mde.Model = ModelReader.Parse(mde, General.Map.Graphics.Device); - - if (mde.Model != null) { - //General.Map.IsChanged = true; - //General.MainWindow.RedrawDisplay(); //update display - msg = "GZBuilder: loaded model for Thing â„–" + t.Type; - General.ErrorLogger.Add(ErrorType.Warning, msg); - General.WriteLogLine(msg); - return true; - } else { - modelDefEntries.Remove(t.Type); - msg = "GZBuilder: failed to load model(s) for Thing â„–" + t.Type + ". ModelDef node removed."; - General.ErrorLogger.Add(ErrorType.Warning, msg); - General.WriteLogLine(msg); - return false; - } - } - return true; - } - return false; - } - -//functions - private static void loadModelDefs() { - General.MainWindow.DisplayStatus(StatusType.Busy, "Parsing model definitions..."); - - Dictionary<string, int> Actors = new Dictionary<string,int>(); - Dictionary<int, ThingTypeInfo> things = General.Map.Config.GetThingTypes(); - - //read our new shiny ClassNames for default game 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 = General.Map.Data.Decorate.Actors; - foreach (ActorStructure actor in ac) { - string className = actor.ClassName.ToLower(); - if (actor.DoomEdNum != -1 && !Actors.ContainsKey(className)) //we don't need actors without DoomEdNum - Actors.Add(className, actor.DoomEdNum); - } - - Dictionary<string, ModelDefEntry> modelDefEntriesByName = new Dictionary<string, ModelDefEntry>(); - - foreach (string folder in General.Map.Data.Folders) - ModelDefParser.ParseFolder(modelDefEntriesByName, folder); - - modelDefEntries = new Dictionary<int, ModelDefEntry>(); - - foreach (KeyValuePair<string, ModelDefEntry> e in modelDefEntriesByName) { - if (Actors.ContainsKey(e.Value.Name)) { - modelDefEntries[Actors[e.Value.Name]] = modelDefEntriesByName[e.Value.Name]; - } else { - string msg = "GZBuilder: ModelDefEntry wasn't found in Decorate: '" + e.Value.Name + "'"; - General.ErrorLogger.Add(ErrorType.Warning, msg); - General.WriteLogLine(msg); - } - } - } - - //load models for things which are already in the map - private static void loadModels() { - General.MainWindow.DisplayStatus(StatusType.Busy, "Loading models..."); - string msg = "GZBuilder: loading models..."; - General.ErrorLogger.Add(ErrorType.Warning, msg); - General.WriteLogLine(msg); - - foreach(Thing t in General.Map.Map.Things) - LoadModelForThing(t); - - General.MainWindow.RedrawDisplay(); +//debug + public static void LogAndTraceWarning(string message) { + General.ErrorLogger.Add(ErrorType.Warning, message); + General.WriteLogLine(message); +#if DEBUG + Trace(message); +#endif } -//debug public static void Trace(string message) { #if DEBUG ((ConsoleDocker)console.Control).Trace(message); diff --git a/Source/Core/GZBuilder/IO/ModelDefParser.cs b/Source/Core/GZBuilder/IO/ModelDefParser.cs deleted file mode 100644 index 4e799e542..000000000 --- a/Source/Core/GZBuilder/IO/ModelDefParser.cs +++ /dev/null @@ -1,197 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Globalization; -using CodeImp.DoomBuilder.GZBuilder.Data; - -namespace CodeImp.DoomBuilder.GZBuilder.IO -{ - class ModelDefParser - { - public static string INVALID_TEXTURE = "**INVALID_TEXTURE**"; - private static string[] SUPPORTED_TEXTURE_EXTENSIONS = { ".jpg", ".tga", ".png", ".dds", ".bmp" }; - - public static void ParseFolder(Dictionary<string, ModelDefEntry> modelDefEntriesByName, string path) { - string[] files = Directory.GetFiles(path); - - foreach (string fileName in files) { - if (fileName.ToLower().IndexOf("modeldef") != -1) - Parse(modelDefEntriesByName, path, fileName); - } - - logAndTrace("ModelDefParser: parsed " + modelDefEntriesByName.Count + " definitions;"); - } - - public static void Parse(Dictionary<string, ModelDefEntry> modelDefEntriesByName, string path, string fileName) { - logAndTrace("ModelDefParser: Parsing '" + fileName + "'"); - - if (File.Exists(fileName)) { - StreamReader s = File.OpenText(fileName); - string contents = s.ReadToEnd(); - s.Close(); - - contents = StripComments(contents).ToLower(); - - int startIndex = 0; - int mdlIndex = 0; - - while ((mdlIndex = contents.IndexOf("model", startIndex)) != -1) { - startIndex = contents.IndexOf("}", mdlIndex); - parseModelDef(modelDefEntriesByName, path, contents.Substring(mdlIndex, startIndex - mdlIndex)); - } - - } else { - logAndTrace("ModelDefParser: File '" + fileName + "' doesn't exist!"); - } - } - - private static void parseModelDef(Dictionary<string, ModelDefEntry> modelDefEntriesByName, string path, string modelDef) { - string[] modelNames = new string[16]; - string[] textureNames = new string[16]; - - string[] lines = modelDef.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); - char[] space = new char[] { ' ' }; - string[] parts = lines[0].Split(space, StringSplitOptions.RemoveEmptyEntries); - string name = parts[1].Trim().Replace("{", ""); - - if (modelDefEntriesByName.ContainsKey(name)) { - General.WriteLogLine("Already have ModelDef for '" + name + "'"); - return; - } - char[] splitter = new char[] { ' ', '"' }; - ModelDefEntry mde = new ModelDefEntry(); - mde.Name = name; - - for (int i = 1; i < lines.Length; i++) { - parts = lines[i].Split(space, StringSplitOptions.RemoveEmptyEntries); - - if (parts.Length > 0) { - string s = parts[0].Trim(); - - //LOTS of boilerplate! Yay!!! - if (s.IndexOf("frameindex") != -1) { - if (mde.Name != String.Empty && mde.Path != String.Empty) { - for (int c = 0; c < modelNames.Length; c++) { - if (modelNames[c] != null && textureNames[c] != null) { - mde.ModelNames.Add(modelNames[c]); - mde.TextureNames.Add(textureNames[c]); - } - } - - if (mde.ModelNames.Count > 0 && mde.TextureNames.Count > 0) - modelDefEntriesByName[mde.Name] = mde; - else - logAndTrace("Error while parsing ModelDef. Not all required fileds are present." + Environment.NewLine + "Parsed data: [" + Environment.NewLine + ModelDefEntry_ToString(mde) + "]" + Environment.NewLine); - return; //we don't want to parse all frames - - } - logAndTrace("Error while parsing ModelDef. Not all required fileds are present." + Environment.NewLine + "Parsed data: [" + Environment.NewLine + ModelDefEntry_ToString(mde) + "]" + Environment.NewLine); - return; - - } else if (s.IndexOf("model") != -1) { - if (parts.Length != 3) { - logAndTrace("Incorrect syntax in 'model' token for class '" + name + "': expected 3 entries, but got " + parts.Length + "!"); - return; - } - - int fileIndex = int.Parse(parts[1].Trim(splitter), NumberStyles.Integer); - string fileName = parts[2].Trim(splitter); - string fileExt = Path.GetExtension(fileName); - - if (fileExt == ".md3" || fileExt == ".md2") { - if (modelNames[fileIndex] != null) { - logAndTrace("Incorrect syntax in 'model' token for class '" + name + "': already got model with index " + fileIndex + "!"); - return; - } - modelNames[fileIndex] = fileName; - - } else { - logAndTrace("Model '" + fileName + "' not parsed. Only MD3 and MD2 models are supported."); - return; - } - - } else if (s.IndexOf("path") != -1) { - if (parts.Length != 2) { - logAndTrace("Incorrect syntax in 'path' token for class '" + name + "': expected 2 entries, but got " + parts.Length + "!"); - return; - } - - mde.Path = path + "\\" + parts[1].Trim(splitter).Replace("/", "\\"); - - } else if (s.IndexOf("skin") != -1) { - if (parts.Length != 3) { - logAndTrace("Incorrect syntax in 'skin' token for class '" + name + "': expected 3 entries, but got " + parts.Length + "!"); - return; - } - - int index = int.Parse(parts[1].Trim(splitter), NumberStyles.Integer); - if (textureNames[index] != null) { - logAndTrace("Incorrect syntax in 'skin' token for class '" + name + "': already got skin with index " + index + "!"); - return; - } - - string textureName = parts[2].Trim(splitter); - string fileExt = Path.GetExtension(textureName); - textureNames[index] = Array.IndexOf(SUPPORTED_TEXTURE_EXTENSIONS, fileExt) == -1 ? INVALID_TEXTURE : textureName; - - } else if (s.IndexOf("scale") != -1) { - if (parts.Length != 4) { - logAndTrace("Incorrect syntax in 'scale' token for class '" + name + "': expected 4 entries, but got " + parts.Length + "!"); - return; - } - - mde.Scale.X = float.Parse(parts[1], NumberStyles.Float); - mde.Scale.Y = float.Parse(parts[2], NumberStyles.Float); - mde.Scale.Z = float.Parse(parts[3], NumberStyles.Float); - - } else if (s.IndexOf("zoffset") != -1) { - if (parts.Length != 2) { - logAndTrace("Incorrect syntax in 'zoffset' token for class '" + name + "': expected 2 entries, but got " + parts.Length + "!"); - return; - } - - mde.zOffset = float.Parse(parts[1], NumberStyles.Float); - } - } - } - } - - private static string ModelDefEntry_ToString(ModelDefEntry mde) { - string[] models = new string[mde.ModelNames.Count]; - mde.ModelNames.CopyTo(models); - - string[] textures = new string[mde.TextureNames.Count]; - mde.TextureNames.CopyTo(textures); - - return "Name: " + mde.Name + Environment.NewLine - + "Path: " + mde.Path + Environment.NewLine - + "Models: " + String.Join(", ", models) + Environment.NewLine - + "Skins: " + String.Join(", ", textures) + Environment.NewLine - + "Scale: " + mde.Scale + Environment.NewLine - + "zOffset: " + mde.zOffset + Environment.NewLine; - } - - private static string StripComments(string contents) { - int start, end; - - //comments - while ((start = contents.IndexOf("//")) != -1) { - end = contents.IndexOf(Environment.NewLine, start); - contents = contents.Remove(start, end - start); - } - - //block comments - while ((start = contents.IndexOf("/*")) != -1) { - end = contents.IndexOf("*/"); - contents = contents.Remove(start, end - start + 2); - } - - return contents; - } - - private static void logAndTrace(string message) { - General.ErrorLogger.Add(ErrorType.Warning, message); - General.WriteLogLine(message); - } - } -} \ No newline at end of file diff --git a/Source/Core/GZBuilder/md3/GZModel.cs b/Source/Core/GZBuilder/md3/GZModel.cs index a9193119b..1442cd08e 100644 --- a/Source/Core/GZBuilder/md3/GZModel.cs +++ b/Source/Core/GZBuilder/md3/GZModel.cs @@ -4,7 +4,7 @@ using SlimDX.Direct3D9; using CodeImp.DoomBuilder.Geometry; -namespace ColladaDotNet.Pipeline.MD3 +namespace CodeImp.DoomBuilder.GZBuilder.MD3 { public class GZModel { public List<Mesh> Meshes; diff --git a/Source/Core/GZBuilder/md3/ModelReader.cs b/Source/Core/GZBuilder/md3/ModelReader.cs index 02851523f..e1889794e 100644 --- a/Source/Core/GZBuilder/md3/ModelReader.cs +++ b/Source/Core/GZBuilder/md3/ModelReader.cs @@ -5,83 +5,90 @@ using System.Text; using System.Collections.Generic; using CodeImp.DoomBuilder; +using CodeImp.DoomBuilder.Data; using CodeImp.DoomBuilder.Rendering; using CodeImp.DoomBuilder.GZBuilder.Data; -using CodeImp.DoomBuilder.GZBuilder.IO; +using CodeImp.DoomBuilder.GZBuilder.GZDoom; using SlimDX; using SlimDX.Direct3D9; //mxd. Original version taken from here: http://colladadotnet.codeplex.com/SourceControl/changeset/view/40680 -namespace ColladaDotNet.Pipeline.MD3 { - public class ModelReader { - public static GZModel Parse(ModelDefEntry mde, Device D3DDevice) { - string[] modelPaths = new string[mde.ModelNames.Count]; - string[] texturePaths = new string[mde.TextureNames.Count]; - - mde.ModelNames.CopyTo(modelPaths); - mde.TextureNames.CopyTo(texturePaths); - - if (modelPaths.Length != texturePaths.Length || texturePaths.Length == 0 || modelPaths.Length == 0) { - General.ErrorLogger.Add(ErrorType.Warning, "MD3Reader: wrong parse params! (modelPaths=" + modelPaths.ToString() + "; texturePaths=" + texturePaths.ToString() + ")"); - return null; - } +namespace CodeImp.DoomBuilder.GZBuilder.MD3 +{ + internal class ModelReader + { + public static void Parse(ref ModeldefEntry mde, PK3StructuredReader reader, Device D3DDevice) { + string[] modelNames = new string[mde.ModelNames.Count]; + string[] textureNames = new string[mde.TextureNames.Count]; + + mde.ModelNames.CopyTo(modelNames); + mde.TextureNames.CopyTo(textureNames); + + //should never happen + /*if (modelNames.Length != textureNames.Length || textureNames.Length == 0 || modelNames.Length == 0) { + General.ErrorLogger.Add(ErrorType.Warning, "MD3Reader: wrong parse params! (modelPaths=" + modelNames.ToString() + "; texturePaths=" + textureNames.ToString() + ")"); + return; + }*/ - GZModel model = new GZModel(); - model.NUM_MESHES = (byte)modelPaths.Length; + mde.Model = new GZModel(); + mde.Model.NUM_MESHES = (byte)modelNames.Length; BoundingBoxSizes bbs = new BoundingBoxSizes(); - for (int i = 0; i < modelPaths.Length; i++) { - string modelPath = mde.Path + "\\" + modelPaths[i]; - if (File.Exists(modelPath)) { + for (int i = 0; i < modelNames.Length; i++) { + string modelPath = Path.Combine(mde.Path, modelNames[i]); + + if (reader.FileExists(modelPath)) { + MemoryStream stream = reader.LoadFile(modelPath); General.WriteLogLine("MD3Reader: loading '" + modelPath + "'"); + //mesh - string ext = modelPaths[i].Substring(modelPaths[i].Length - 4); - bool loaded = false; - if (ext == ".md3") { - loaded = ReadMD3Model(ref bbs, mde, model, modelPath, D3DDevice); - } else if (ext == ".md2") { - loaded = ReadMD2Model(ref bbs, mde, model, modelPath, D3DDevice); - } + string ext = modelNames[i].Substring(modelNames[i].Length - 4); + string error = ""; + if (ext == ".md3") + error = ReadMD3Model(ref bbs, ref mde, stream, D3DDevice); + else if (ext == ".md2") + error = ReadMD2Model(ref bbs, ref mde, stream, D3DDevice); //texture - if (loaded) { - string texturePath = mde.Path + "\\" + texturePaths[i]; - if (texturePaths[i] != ModelDefParser.INVALID_TEXTURE && File.Exists(texturePath)) { - model.Textures.Add(Texture.FromFile(D3DDevice, texturePath)); + if (string.IsNullOrEmpty(error)) { + string texturePath = Path.Combine(mde.Path, textureNames[i]); + + if (textureNames[i] != ModeldefParser.INVALID_TEXTURE && reader.FileExists(texturePath)) { + mde.Model.Textures.Add(Texture.FromStream(D3DDevice, reader.LoadFile(texturePath))); } else { - model.Textures.Add(General.Map.Data.UnknownTexture3D.Texture); - if (texturePaths[i] != ModelDefParser.INVALID_TEXTURE) - General.ErrorLogger.Add(ErrorType.Warning, "MD3Reader: unable to load texture '" + texturePath + "' - no such file"); + mde.Model.Textures.Add(General.Map.Data.UnknownTexture3D.Texture); + if (textureNames[i] != ModeldefParser.INVALID_TEXTURE) + GZBuilder.GZGeneral.LogAndTraceWarning("MD3Reader: unable to load texture '" + texturePath + "' - no such file"); } } else { - model.NUM_MESHES--; + GZBuilder.GZGeneral.LogAndTraceWarning("MD3Reader: error while loading " + modelPath + ": " + error); + mde.Model.NUM_MESHES--; } + stream.Dispose(); + } else { - General.ErrorLogger.Add(ErrorType.Warning, "MD3Reader: unable to load model '" + mde.Path + "\\" + modelPaths[i] + "' - no such file"); - model.NUM_MESHES--; + GZBuilder.GZGeneral.LogAndTraceWarning("MD3Reader: unable to load model '" + modelPath + "' - no such file"); + mde.Model.NUM_MESHES--; } } - if (model.NUM_MESHES <= 0) - return null; - - model.BoundingBox = BoundingBoxTools.CalculateBoundingBox(bbs); + if (mde.Model.NUM_MESHES <= 0) { + mde.Model = null; + return; + } - return model; + mde.Model.BoundingBox = BoundingBoxTools.CalculateBoundingBox(bbs); } - private static bool ReadMD3Model(ref BoundingBoxSizes bbs, ModelDefEntry mde, GZModel model, string modelPath, Device D3DDevice) { - FileStream s = new FileStream(modelPath, FileMode.Open); + private static string ReadMD3Model(ref BoundingBoxSizes bbs, ref ModeldefEntry mde, MemoryStream s, Device D3DDevice) { long start = s.Position; using (var br = new BinaryReader(s, Encoding.ASCII)) { string magic = ReadString(br, 4); - if (magic != "IDP3") { - General.ErrorLogger.Add(ErrorType.Warning, "MD3Reader: Error while loading '" + modelPath + "': Magic should be 'IDP3', not '" + magic + "'"); - return false; - } + if (magic != "IDP3") + return "magic should be 'IDP3', not '" + magic + "'"; s.Position += 80; int numSurfaces = br.ReadInt32(); @@ -94,8 +101,12 @@ namespace ColladaDotNet.Pipeline.MD3 { List<short> polyIndecesList = new List<short>(); List<WorldVertex> vertList = new List<WorldVertex>(); - for (int c = 0; c < numSurfaces; ++c) - ReadSurface(ref bbs, br, polyIndecesList, vertList, mde); + string error = ""; + for (int c = 0; c < numSurfaces; ++c) { + error = ReadSurface(ref bbs, br, polyIndecesList, vertList, mde); + if (!string.IsNullOrEmpty(error)) + return error; + } //indeces for rendering current mesh in 2d short[] indeces2d_arr = CreateLineListIndeces(polyIndecesList); @@ -112,7 +123,7 @@ namespace ColladaDotNet.Pipeline.MD3 { mesh.IndexBuffer.Unlock(); mesh.OptimizeInPlace(MeshOptimizeFlags.AttributeSort); - model.Meshes.Add(mesh); + mde.Model.Meshes.Add(mesh); //2d data IndexBuffer indeces2d = new IndexBuffer(D3DDevice, 2 * indeces2d_arr.Length, Usage.WriteOnly, Pool.Managed, true); @@ -120,19 +131,17 @@ namespace ColladaDotNet.Pipeline.MD3 { stream.WriteRange(indeces2d_arr); indeces2d.Unlock(); - model.Indeces2D.Add(indeces2d); - model.NumIndeces2D.Add((short)polyIndecesList.Count); + mde.Model.Indeces2D.Add(indeces2d); + mde.Model.NumIndeces2D.Add((short)polyIndecesList.Count); } - return true; + return ""; } - private static void ReadSurface(ref BoundingBoxSizes bbs, BinaryReader br, List<short> polyIndecesList, List<WorldVertex> vertList, ModelDefEntry mde) { + private static string ReadSurface(ref BoundingBoxSizes bbs, BinaryReader br, List<short> polyIndecesList, List<WorldVertex> vertList, ModeldefEntry mde) { var start = br.BaseStream.Position; string magic = ReadString(br, 4); - if (magic != "IDP3") { - General.ErrorLogger.Add(ErrorType.Warning, "MD3Reader: Error while reading surface: Magic should be 'IDP3', not '" + magic + "'"); - return; - } + if (magic != "IDP3") + return "error while reading surface: Magic should be 'IDP3', not '" + magic + "'"; br.BaseStream.Position += 76; int numVerts = br.ReadInt32(); //Number of Vertex objects defined in this Surface, up to MD3_MAX_VERTS. Current value of MD3_MAX_VERTS is 4096. @@ -170,9 +179,7 @@ namespace ColladaDotNet.Pipeline.MD3 { for (int i = 0; i < numVerts; i++) { WorldVertex v = vertList[i]; - //short[] coords = new short[] { br.ReadInt16(), br.ReadInt16(), br.ReadInt16() }; - //v.Position = new Vector3((float)coords[1] / 64, -(float)coords[0] / 64, (float)coords[2] / 64); v.y = -(float)br.ReadInt16() / 64 * mde.Scale.X; v.x = (float)br.ReadInt16() / 64 * mde.Scale.Y; v.z = (float)br.ReadInt16() / 64 * mde.Scale.Z + mde.zOffset; @@ -192,23 +199,20 @@ namespace ColladaDotNet.Pipeline.MD3 { if (start + ofsEnd != br.BaseStream.Position) br.BaseStream.Position = start + ofsEnd; + return ""; } - private static bool ReadMD2Model(ref BoundingBoxSizes bbs, ModelDefEntry mde, GZModel model, string modelPath, Device D3DDevice) { - FileStream s = new FileStream(modelPath, FileMode.Open); + private static string ReadMD2Model(ref BoundingBoxSizes bbs, ref ModeldefEntry mde, MemoryStream s, Device D3DDevice) { long start = s.Position; using (var br = new BinaryReader(s, Encoding.ASCII)) { string magic = ReadString(br, 4); - if (magic != "IDP2") { //magic number: "IDP2" - General.ErrorLogger.Add(ErrorType.Warning, "MD3Reader: Error while loading '" + modelPath + "': Magic should be 'IDP2', not '" + magic + "'"); - return false; - } + if (magic != "IDP2") //magic number: "IDP2" + return "magic should be 'IDP2', not '" + magic + "'"; + int modelVersion = br.ReadInt32(); - if (modelVersion != 8) { //MD2 version. Must be equal to 8 - General.ErrorLogger.Add(ErrorType.Warning, "MD3Reader: Error while loading '" + modelPath + "': MD2 version must be 8 but is " + modelVersion); - return false; - } + if (modelVersion != 8) //MD2 version. Must be equal to 8 + return "MD2 version must be 8 but is " + modelVersion; int texWidth = br.ReadInt32(); int texHeight = br.ReadInt32(); @@ -219,10 +223,8 @@ namespace ColladaDotNet.Pipeline.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.Warning, "MD3Reader: Error while loading '" + modelPath + "': Model has 0 frames"); - return false; - } + if (br.ReadInt32() == 0) //Total number of frames + return "model has 0 frames"; s.Position += 4; //Offset to skin names (each skin name is an unsigned char[64] and are null terminated) int ofs_uv = br.ReadInt32();//Offset to s-t texture coordinates @@ -284,7 +286,6 @@ namespace ColladaDotNet.Pipeline.MD3 { WorldVertex v = vertList[polyIndecesList[i]]; //bounding box - //BoundingBoxTools.UpdateBoundingBoxSizes(ref bbs, v); BoundingBoxTools.UpdateBoundingBoxSizes(ref bbs, new WorldVertex(v.y, v.x, v.z)); //uv @@ -309,7 +310,7 @@ namespace ColladaDotNet.Pipeline.MD3 { mesh.IndexBuffer.Unlock(); mesh.OptimizeInPlace(MeshOptimizeFlags.AttributeSort); - model.Meshes.Add(mesh); + mde.Model.Meshes.Add(mesh); //2d data IndexBuffer indeces2d = new IndexBuffer(D3DDevice, 2 * indeces2d_arr.Length, Usage.WriteOnly, Pool.Managed, true); @@ -317,12 +318,11 @@ namespace ColladaDotNet.Pipeline.MD3 { stream.WriteRange(indeces2d_arr); indeces2d.Unlock(); - model.Indeces2D.Add(indeces2d); - model.NumIndeces2D.Add((short)polyIndecesList.Count); - model.Angle = -90.0f * (float)Math.PI / 180.0f; - - return true; + mde.Model.Indeces2D.Add(indeces2d); + mde.Model.NumIndeces2D.Add((short)polyIndecesList.Count); + mde.Model.Angle = -90.0f * (float)Math.PI / 180.0f; } + return ""; } //this creates list of vertex indeces for rendering using LineList method @@ -344,41 +344,6 @@ namespace ColladaDotNet.Pipeline.MD3 { return indeces2d_arr; } - //this creates array of vectors resembling bounding box - /*private 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); - - //corners - Vector3 v1 = new Vector3(bbs.MinX, bbs.MinY, bbs.MinZ); - Vector3 v2 = new Vector3(bbs.MaxX, bbs.MinY, bbs.MinZ); - Vector3 v3 = new Vector3(bbs.MinX, bbs.MaxY, bbs.MinZ); - Vector3 v4 = new Vector3(bbs.MaxX, bbs.MaxY, bbs.MinZ); - Vector3 v5 = new Vector3(bbs.MinX, bbs.MinY, bbs.MaxZ); - Vector3 v6 = new Vector3(bbs.MaxX, bbs.MinY, bbs.MaxZ); - Vector3 v7 = new Vector3(bbs.MinX, bbs.MaxY, bbs.MaxZ); - Vector3 v8 = new Vector3(bbs.MaxX, bbs.MaxY, bbs.MaxZ); - - return new Vector3[] { v0, v1, v2, v3, v4, v5, v6, v7, v8 }; - } - - private 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.y < bbs.MinY) - bbs.MinY = (short)v.y; - else if (v.y > bbs.MaxY) - bbs.MaxY = (short)v.y; - }*/ - private static string ReadString(BinaryReader br, int len) { var NAME = string.Empty; int i = 0; diff --git a/Source/Core/General/MapManager.cs b/Source/Core/General/MapManager.cs index e9b1e0c2e..4ccf015f7 100644 --- a/Source/Core/General/MapManager.cs +++ b/Source/Core/General/MapManager.cs @@ -286,6 +286,9 @@ namespace CodeImp.DoomBuilder map.UpdateConfiguration(); map.Update(); thingsfilter.Update(); + + //mxd. load models + data.LoadModels(); // Bind any methods General.Actions.BindMethods(this); @@ -409,6 +412,9 @@ namespace CodeImp.DoomBuilder map.SnapAllToAccuracy(); map.Update(); thingsfilter.Update(); + + //mxd. load models + data.LoadModels(); // Bind any methods General.Actions.BindMethods(this); diff --git a/Source/Core/IO/WAD.cs b/Source/Core/IO/WAD.cs index 1103c2992..87431dbe7 100644 --- a/Source/Core/IO/WAD.cs +++ b/Source/Core/IO/WAD.cs @@ -365,7 +365,7 @@ namespace CodeImp.DoomBuilder.IO // This finds a lump by name, returns -1 when not found public int FindLumpIndex(string name, int start, int end) { - byte[] fixedname; + //byte[] fixedname; long longname = Lump.MakeLongName(name); // Fix end when it exceeds length @@ -375,7 +375,7 @@ namespace CodeImp.DoomBuilder.IO name = name.ToUpperInvariant(); // Make fixed name - fixedname = Lump.MakeFixedName(name, ENCODING); + //fixedname = Lump.MakeFixedName(name, ENCODING); // Loop through the lumps for(int i = start; i <= end; i++) diff --git a/Source/Core/Rendering/Renderer2D.cs b/Source/Core/Rendering/Renderer2D.cs index ffd4def12..6ab1085b1 100644 --- a/Source/Core/Rendering/Renderer2D.cs +++ b/Source/Core/Rendering/Renderer2D.cs @@ -37,7 +37,7 @@ using CodeImp.DoomBuilder.Editing; //mxd using CodeImp.DoomBuilder.GZBuilder.Data; -using ColladaDotNet.Pipeline.MD3; +using CodeImp.DoomBuilder.GZBuilder.MD3; #endregion @@ -943,7 +943,7 @@ namespace CodeImp.DoomBuilder.Rendering { //mxd. Collect things with models for rendering if (General.Settings.GZDrawModels && (!General.Settings.GZDrawSelectedModelsOnly || t.Selected)) { - Dictionary<int, ModelDefEntry> mde = GZBuilder.GZGeneral.ModelDefEntries; + Dictionary<int, ModeldefEntry> mde = General.Map.Data.ModeldefEntries; if (mde != null && mde.ContainsKey(t.Type)) { thingsWithModel[screenpos] = t; } @@ -1119,12 +1119,12 @@ namespace CodeImp.DoomBuilder.Rendering graphics.Shaders.Things2D.BeginPass(1); foreach(KeyValuePair<Vector2D, Thing> group in thingsWithModel){ - ModelDefEntry mde = GZBuilder.GZGeneral.ModelDefEntries[group.Value.Type]; + ModeldefEntry mde = General.Map.Data.ModeldefEntries[group.Value.Type]; if (mde.Model != null) RenderModel(mde.Model, group.Key, group.Value.Angle + mde.Model.Angle, group.Value.Selected); else - group.Value.IsModel = GZBuilder.GZGeneral.LoadModelForThing(group.Value); + group.Value.IsModel = General.Map.Data.LoadModelForThing(group.Value); } graphics.Shaders.Things2D.EndPass(); } diff --git a/Source/Core/Rendering/Renderer3D.cs b/Source/Core/Rendering/Renderer3D.cs index c24cc870c..c3b147837 100644 --- a/Source/Core/Rendering/Renderer3D.cs +++ b/Source/Core/Rendering/Renderer3D.cs @@ -34,7 +34,7 @@ using CodeImp.DoomBuilder.VisualModes; using CodeImp.DoomBuilder.Map; //mxd -using ColladaDotNet.Pipeline.MD3; +using CodeImp.DoomBuilder.GZBuilder.MD3; using CodeImp.DoomBuilder.GZBuilder.Data; #endregion @@ -81,7 +81,7 @@ namespace CodeImp.DoomBuilder.Rendering private List<VisualThing> thingsWithLight; private int[] lightOffsets; private Dictionary<Texture, List<VisualGeometry>> litGeometry; - private Dictionary<ModelDefEntry, List<VisualThing>> thingsWithModel; + private Dictionary<ModeldefEntry, List<VisualThing>> thingsWithModel; //dbg //int geoSkipped = 0; //int totalGeo = 0; @@ -499,7 +499,7 @@ namespace CodeImp.DoomBuilder.Rendering things = new Dictionary<ImageData, List<VisualThing>>[RENDER_PASSES]; thingsbydistance = new BinaryHeap<VisualThing>(); //mxd - thingsWithModel = new Dictionary<ModelDefEntry, List<VisualThing>>(); + thingsWithModel = new Dictionary<ModeldefEntry, List<VisualThing>>(); litGeometry = new Dictionary<Texture, List<VisualGeometry>>(); for(int i = 0; i < RENDER_PASSES; i++) @@ -1003,15 +1003,14 @@ namespace CodeImp.DoomBuilder.Rendering //mxd. render models private void RenderModels() { - int shaderpass = 4; - if (fullbrightness) shaderpass++; + int shaderpass = fullbrightness ? 1 : 4; int currentshaderpass = shaderpass; int highshaderpass = shaderpass + 2; // Begin rendering with this shader graphics.Shaders.World3D.BeginPass(currentshaderpass); - foreach (KeyValuePair<ModelDefEntry, List<VisualThing>> group in thingsWithModel) { + foreach (KeyValuePair<ModeldefEntry, List<VisualThing>> group in thingsWithModel) { foreach (VisualThing t in group.Value) { Color4 vertexColor = new Color4(t.VertexColor); vertexColor.Alpha = 1.0f; @@ -1177,7 +1176,7 @@ namespace CodeImp.DoomBuilder.Rendering } //mxd. gather models } else if (General.Settings.GZDrawModels && (!General.Settings.GZDrawSelectedModelsOnly || t.Selected) && t.Thing.IsModel) { - ModelDefEntry mde = GZBuilder.GZGeneral.ModelDefEntries[t.Thing.Type]; + ModeldefEntry mde = General.Map.Data.ModeldefEntries[t.Thing.Type]; if (!isThingOnScreen(t.BoundingBox)) return; diff --git a/Source/Core/VisualModes/VisualMode.cs b/Source/Core/VisualModes/VisualMode.cs index 196f71bd1..1b072a299 100644 --- a/Source/Core/VisualModes/VisualMode.cs +++ b/Source/Core/VisualModes/VisualMode.cs @@ -792,7 +792,7 @@ namespace CodeImp.DoomBuilder.VisualModes if (refreshSelection || selectedVisualThings == null) { selectedVisualThings = new List<VisualThing>(); foreach (KeyValuePair<Thing, VisualThing> group in allthings) { - if (group.Value.Selected) + if (group.Value != null && group.Value.Selected) selectedVisualThings.Add(group.Value); } } diff --git a/Source/Core/VisualModes/VisualThing.cs b/Source/Core/VisualModes/VisualThing.cs index 6115635f1..8b9c5efc4 100644 --- a/Source/Core/VisualModes/VisualThing.cs +++ b/Source/Core/VisualModes/VisualThing.cs @@ -93,9 +93,6 @@ namespace CodeImp.DoomBuilder.VisualModes private Vector3 position_v3; private float lightDelta; //used in light animation private Vector3[] boundingBox; - - //mxd. model - private bool checkedIfModel; #endregion @@ -202,7 +199,7 @@ namespace CodeImp.DoomBuilder.VisualModes #endregion #region ================== Methods - + // This sets the distance from the camera internal void CalculateCameraDistance(Vector2D campos) { @@ -222,7 +219,7 @@ namespace CodeImp.DoomBuilder.VisualModes if(geobuffer != null) geobuffer.Dispose(); geobuffer = null; updategeo = true; - checkedIfModel = false; + //checkedIfModel = false; } // This is called resets when the device is reset @@ -295,19 +292,15 @@ namespace CodeImp.DoomBuilder.VisualModes // Do we need to update the geometry buffer? if (updategeo) { - //mxd - if (!checkedIfModel) { - //check if thing is model - if (GZBuilder.GZGeneral.ModelDefEntries.ContainsKey(thing.Type)) { - ModelDefEntry mde = GZBuilder.GZGeneral.ModelDefEntries[thing.Type]; - if (mde.Model == null) - thing.IsModel = GZBuilder.GZGeneral.LoadModelForThing(thing); - else - thing.IsModel = true; - } - if (thing.IsModel) - updateBoundingBoxForModel(); - checkedIfModel = true; + //mxd. check if thing is model + if (General.Map.Data.ModeldefEntries.ContainsKey(thing.Type)) { + ModeldefEntry mde = General.Map.Data.ModeldefEntries[thing.Type]; + if (mde.Model == null) + thing.IsModel = General.Map.Data.LoadModelForThing(thing); + else + thing.IsModel = true; + } else { + thing.IsModel = false; } // Trash geometry buffer @@ -474,7 +467,7 @@ namespace CodeImp.DoomBuilder.VisualModes //mxd. update bounding box from model bounding box private void updateBoundingBoxForModel() { - ModelDefEntry mde = GZBuilder.GZGeneral.ModelDefEntries[thing.Type]; + ModeldefEntry mde = General.Map.Data.ModeldefEntries[thing.Type]; int len = mde.Model.BoundingBox.Length; boundingBox = new Vector3[len]; for (int i = 0; i < len; i++) { diff --git a/Source/Core/ZDoom/DecorateParser.cs b/Source/Core/ZDoom/DecorateParser.cs index 10d57de79..d5de30247 100644 --- a/Source/Core/ZDoom/DecorateParser.cs +++ b/Source/Core/ZDoom/DecorateParser.cs @@ -75,7 +75,7 @@ namespace CodeImp.DoomBuilder.ZDoom public DecorateParser() { // Syntax - whitespace = "\n \t\r"; + whitespace = "\n \t\r\u00A0"; //mxd. non-breaking space is also space :) specialtokens = ":{}+-\n;,"; // Initialize diff --git a/Source/Core/ZDoom/TexturesParser.cs b/Source/Core/ZDoom/TexturesParser.cs index fe28a4fb8..cc42d913c 100644 --- a/Source/Core/ZDoom/TexturesParser.cs +++ b/Source/Core/ZDoom/TexturesParser.cs @@ -63,7 +63,7 @@ namespace CodeImp.DoomBuilder.ZDoom public TexturesParser() { // Syntax - whitespace = "\n \t\r"; + whitespace = "\n \t\r\u00A0"; //mxd. non-breaking space is also space :) specialtokens = ",{}\n"; // Initialize diff --git a/Source/Core/ZDoom/ZDTextParser.cs b/Source/Core/ZDoom/ZDTextParser.cs index 1f3607954..14924fa3f 100644 --- a/Source/Core/ZDoom/ZDTextParser.cs +++ b/Source/Core/ZDoom/ZDTextParser.cs @@ -40,7 +40,7 @@ namespace CodeImp.DoomBuilder.ZDoom #region ================== Variables // Parsing - protected string whitespace = "\n \t\r"; + protected string whitespace = "\n \t\r\u00A0"; //mxd. non-breaking space is also space :) protected string specialtokens = ":{}+-\n;"; // Input data stream @@ -297,7 +297,7 @@ namespace CodeImp.DoomBuilder.ZDoom // This reports an error protected internal void ReportError(string message) { - long position = datastream.Position; + /*long position = datastream.Position; long readpos = 0; int linenumber = 1; @@ -313,13 +313,35 @@ namespace CodeImp.DoomBuilder.ZDoom } // Return to original position - datastream.Seek(position, SeekOrigin.Begin); + datastream.Seek(position, SeekOrigin.Begin);*/ // Set error information errordesc = message; - errorline = linenumber; + errorline = GetCurrentLineNumber(); errorsource = sourcename; } + + //mxd + protected internal int GetCurrentLineNumber() { + long position = datastream.Position; + long readpos = 0; + int linenumber = 1; + + // Find the line on which we found this error + datastream.Seek(0, SeekOrigin.Begin); + StreamReader textreader = new StreamReader(datastream, Encoding.ASCII); + while (readpos < position) { + string line = textreader.ReadLine(); + if (line == null) break; + readpos += line.Length + 2; + linenumber++; + } + + // Return to original position + datastream.Seek(position, SeekOrigin.Begin); + + return linenumber; + } #endregion } diff --git a/Source/Plugins/BuilderModes/VisualModes/BaseVisualThing.cs b/Source/Plugins/BuilderModes/VisualModes/BaseVisualThing.cs index af33cf636..f458da09b 100644 --- a/Source/Plugins/BuilderModes/VisualModes/BaseVisualThing.cs +++ b/Source/Plugins/BuilderModes/VisualModes/BaseVisualThing.cs @@ -34,6 +34,8 @@ using CodeImp.DoomBuilder.VisualModes; using CodeImp.DoomBuilder.Config; using CodeImp.DoomBuilder.Data; +using CodeImp.DoomBuilder.GZBuilder.Data; + #endregion namespace CodeImp.DoomBuilder.BuilderModes @@ -200,6 +202,18 @@ namespace CodeImp.DoomBuilder.BuilderModes pos.z = Thing.Sector.CeilHeight - info.Height; } } + + //mxd. check model state + if (General.Map.Data.ModeldefEntries.ContainsKey(Thing.Type)) { + ModeldefEntry mde = General.Map.Data.ModeldefEntries[Thing.Type]; + if (mde.Model == null) { + Thing.IsModel = General.Map.Data.LoadModelForThing(Thing); + } else { + Thing.IsModel = true; + } + } else { + Thing.IsModel = false; + } // Apply settings SetPosition(pos); diff --git a/Source/Plugins/GZDoomEditing/GZDoomEditing.csproj b/Source/Plugins/GZDoomEditing/GZDoomEditing.csproj index 546a50af9..67ac96baf 100644 --- a/Source/Plugins/GZDoomEditing/GZDoomEditing.csproj +++ b/Source/Plugins/GZDoomEditing/GZDoomEditing.csproj @@ -95,6 +95,7 @@ <ProjectReference Include="..\..\Core\Builder.csproj"> <Project>{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}</Project> <Name>Builder</Name> + <Private>False</Private> </ProjectReference> </ItemGroup> <ItemGroup> diff --git a/Source/Plugins/GZDoomEditing/VisualModes/BaseVisualThing.cs b/Source/Plugins/GZDoomEditing/VisualModes/BaseVisualThing.cs index 57ca33146..ccca9a4a8 100644 --- a/Source/Plugins/GZDoomEditing/VisualModes/BaseVisualThing.cs +++ b/Source/Plugins/GZDoomEditing/VisualModes/BaseVisualThing.cs @@ -34,6 +34,8 @@ using CodeImp.DoomBuilder.VisualModes; using CodeImp.DoomBuilder.Config; using CodeImp.DoomBuilder.Data; +using CodeImp.DoomBuilder.GZBuilder.Data; + #endregion namespace CodeImp.DoomBuilder.GZDoomEditing @@ -236,6 +238,18 @@ namespace CodeImp.DoomBuilder.GZDoomEditing pos.z = sd.Ceiling.plane.GetZ(Thing.Position) - info.Height; } } + + //mxd. check model state + if (General.Map.Data.ModeldefEntries.ContainsKey(Thing.Type)) { + ModeldefEntry mde = General.Map.Data.ModeldefEntries[Thing.Type]; + if (mde.Model == null) { + Thing.IsModel = General.Map.Data.LoadModelForThing(Thing); + } else { + Thing.IsModel = true; + } + } else { + Thing.IsModel = false; + } // Apply settings SetPosition(pos); -- GitLab