diff --git a/Build/Configurations/Includes/Doom_things.cfg b/Build/Configurations/Includes/Doom_things.cfg index 601ccbb3312e06ed9a19eefa7c6e5fc463113971..04ead12c6d182252c8c20fee3ed025d9fac7ffb8 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 68e292f789725b50418cdeac5e5826adfa558da5..72858a3739f25e508fe71071d5614f7946e64321 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 8b5d3259a8534dd34cb83c72226afb26b87891cf..9a59c636000acdd516a53194970da7805119c1a1 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 e393814c982f85f988901d4281236425ef61d3d4..f01c688f1c1cc5240711281c67fac0e82f5497e2 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 27a5099f689750f9002493139e12a064a63999fc..50da0f4d364d2b2218f9d298d55e47f5a8d53a0f 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 ea22d8e520640ddce0c2f0b570cb3308e543336b..e32ae4fb62bf28254aabde42cf1ecf50566ae922 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 ec0fc5b43cd802835bec7d94a497a28dae74874a..05319c2b19dd3c6053f36549dc4c7a70ab1a642b 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 9b24fabb760d12cf664a3b47f1510713e8f712a6..af3cbcc11f36c84a5bbd7ca1f85593d4d95f79f6 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 fb8cdd086e290815c7b04e49efbdc8aa495588fb..80d77c219f0afa0206339882acda9a3cc8c0a6a2 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 74a3524f15a4dde0cbadc5c118c1ec25751ac4da..40e53842df43093ddc99286a61f39028342f890f 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 0000000000000000000000000000000000000000..af491586a8d2f6b9585d0f59531aacd4de2b021b --- /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 0000000000000000000000000000000000000000..9c53faaf71e62022222e46ee73f3649784ba5581 --- /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 17c5797c912508aa90b907fdae6d81b37272186e..e0b4b8eb84453b03e8e529e7c580e91038220857 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 4e799e542761dde70530dfb1167e9fce6bcdb89d..0000000000000000000000000000000000000000 --- 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 a9193119b1d436d61ff1b82c735167be4b838597..1442cd08e9310f01b68301313ead4af8051a158b 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 02851523f602d90a5c9c7650e8af76525459be1f..e1889794ed1b3944e0be65cc58bae724dacdfc0f 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 e9b1e0c2ec61ea0579c56045498ade67c9369641..4ccf015f70e7d519776166ebb638dcb07cec2499 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 1103c2992785019b83764f5f5f5bf2cd8c34225d..87431dbe7f61cb0ad015511859473d13c410bb33 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 ffd4def12f5e8252b83053243ef2c6e46570282d..6ab1085b1a96839c4af51e80baf52ccac61f1999 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 c24cc870c3035c91f7be74339f23f9ad5fe10b26..c3b147837982b0bcc36b89c59cc4ff083c120867 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 196f71bd12a78965e5aedaa5895b94ead1133c7e..1b072a2994d039189bfaa1e628b01150dc2f266c 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 6115635f1f251846a81f3bce618fe5387cdf48ee..8b9c5efc41acc33b22a769f95642a8748617ae7c 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 10d57de79a3b43c4e3e0cf327ce62b2a556ecd8e..d5de3024767237f42f909460766a1fe984fe4a78 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 fe28a4fb8c826950e9383d7153292909c42be271..cc42d913cc8b06fab01c01d560c83b262b4fd41f 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 1f360795429f046a7bb066a3c3f89d49cec35076..14924fa3f14b665be35452db2aaa80716038b4cf 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 af33cf6365ea111c4457fdb6e49978ba4351ec2d..f458da09b4d159a748fb9b74ec7c89c109d94d4b 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 546a50af97a1ed44144736348797c20d9f8e710c..67ac96bafe7aa46a9246830284db017c8d76c7c8 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 57ca33146f028b9d9e923eaf02224db0356e00e7..ccca9a4a8d337b6a60e5dd8b550acb1137fcd279 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);