/// <summary>Loads an object</summary> /// <param name="FileName">The file to load</param> /// <param name="Encoding">The text endcoding of the base file (Used if the encoding cannot be auto-detected)</param> /// <param name="PreserveVertices">Whether object should be optimized to remove duplicate vertices</param> /// <param name="ForceTextureRepeatX">Whether texture repeat is forced on the X-axis</param> /// <param name="ForceTextureRepeatY">Whether texture repeat is forced on the Y-axis</param> /// <returns>The new object, or a null reference if loading fails</returns> /* * Notes for refactoring: * * Unused vertices must only be preserved in deformable objects (e.g. Crack and Form) * * ForceTextureRepeatX / Y is only used for animated objects using the TextureShiftFunction * * TODO / BUG: ForceTextureRepeat is only supported by the B3D / CSV parser * * TODO / BUG: No detection of actual file contents, which will make all parsers barf */ internal static UnifiedObject LoadObject(string FileName, Encoding Encoding, bool PreserveVertices, bool ForceTextureRepeatX, bool ForceTextureRepeatY) { if (String.IsNullOrEmpty(FileName)) { return(null); } #if !DEBUG try { #endif if (!System.IO.Path.HasExtension(FileName)) { while (true) { var f = OpenBveApi.Path.CombineFile(System.IO.Path.GetDirectoryName(FileName), System.IO.Path.GetFileName(FileName) + ".x"); if (System.IO.File.Exists(f)) { FileName = f; break; } f = OpenBveApi.Path.CombineFile(System.IO.Path.GetDirectoryName(FileName), System.IO.Path.GetFileName(FileName) + ".csv"); if (System.IO.File.Exists(f)) { FileName = f; break; } f = OpenBveApi.Path.CombineFile(System.IO.Path.GetDirectoryName(FileName), System.IO.Path.GetFileName(FileName) + ".b3d"); if (System.IO.File.Exists(f)) { FileName = f; break; } f = OpenBveApi.Path.CombineFile(System.IO.Path.GetDirectoryName(FileName), System.IO.Path.GetFileName(FileName) + ".xml"); if (System.IO.File.Exists(f)) { FileName = f; break; } f = OpenBveApi.Path.CombineFile(System.IO.Path.GetDirectoryName(FileName), System.IO.Path.GetFileName(FileName) + ".l3dgrp"); if (System.IO.File.Exists(f)) { FileName = f; break; } f = OpenBveApi.Path.CombineFile(System.IO.Path.GetDirectoryName(FileName), System.IO.Path.GetFileName(FileName) + ".l3dobj"); if (System.IO.File.Exists(f)) { FileName = f; break; } } } UnifiedObject Result; TextEncoding.Encoding newEncoding = TextEncoding.GetEncodingFromFile(FileName); if (newEncoding != TextEncoding.Encoding.Unknown) { switch (newEncoding) { case TextEncoding.Encoding.Utf7: Encoding = System.Text.Encoding.UTF7; break; case TextEncoding.Encoding.Utf8: Encoding = System.Text.Encoding.UTF8; break; case TextEncoding.Encoding.Utf16Le: Encoding = System.Text.Encoding.Unicode; break; case TextEncoding.Encoding.Utf16Be: Encoding = System.Text.Encoding.BigEndianUnicode; break; case TextEncoding.Encoding.Utf32Le: Encoding = System.Text.Encoding.UTF32; break; case TextEncoding.Encoding.Utf32Be: Encoding = System.Text.Encoding.GetEncoding(12001); break; case TextEncoding.Encoding.Shift_JIS: Encoding = System.Text.Encoding.GetEncoding(932); break; case TextEncoding.Encoding.Windows1252: Encoding = System.Text.Encoding.GetEncoding(1252); break; case TextEncoding.Encoding.Big5: Encoding = System.Text.Encoding.GetEncoding(950); break; case TextEncoding.Encoding.EUC_KR: Encoding = System.Text.Encoding.GetEncoding(949); break; } } string e = System.IO.Path.GetExtension(FileName); if (e == null) { Interface.AddMessage(MessageType.Error, false, "The file " + FileName + " does not have a recognised extension."); return(null); } switch (e.ToLowerInvariant()) { case ".csv": case ".b3d": Result = CsvB3dObjectParser.ReadObject(FileName, Encoding); break; case ".x": if (Interface.CurrentOptions.CurrentXParser != Interface.XParsers.Original) { try { if (Interface.CurrentOptions.CurrentXParser == Interface.XParsers.NewXParser) { Result = NewXParser.ReadObject(FileName, Encoding); } else { Result = AssimpXParser.ReadObject(FileName); } } catch (Exception ex) { Interface.AddMessage(MessageType.Error, false, "The new X parser raised the following exception: " + ex); Result = XObjectParser.ReadObject(FileName, Encoding); } } else { Result = XObjectParser.ReadObject(FileName, Encoding); } break; case ".animated": Result = AnimatedObjectParser.ReadObject(FileName, Encoding); break; case ".xml": Result = XMLParser.ReadObject(FileName, Encoding); break; case ".l3dgrp": Result = Ls3DGrpParser.ReadObject(FileName, Encoding, new Vector3()); break; case ".l3dobj": Result = Ls3DObjectParser.ReadObject(FileName, new Vector3()); break; case ".obj": if (Interface.CurrentOptions.CurrentObjParser == Interface.ObjParsers.Assimp) { try { Result = AssimpObjParser.ReadObject(FileName); } catch (Exception ex) { Interface.AddMessage(MessageType.Error, false, "The new Obj parser raised the following exception: " + ex); Result = WavefrontObjParser.ReadObject(FileName, Encoding); } } else { Result = WavefrontObjParser.ReadObject(FileName, Encoding); } break; case ".s": Result = MsTsShapeParser.ReadObject(FileName); break; default: Interface.AddMessage(MessageType.Error, false, "The file extension is not supported: " + FileName); return(null); } if (Result != null) { Result.OptimizeObject(PreserveVertices); } return(Result); #if !DEBUG } catch (Exception ex) { Interface.AddMessage(MessageType.Error, true, "An unexpected error occured (" + ex.Message + ") while attempting to load the file " + FileName); return(null); } #endif }
//The XML Parser Class will allow loading of an object with more advanced //properties than are currently available with the CSV and B3D formats, whilst //not requiring backwards incompatible changes public static UnifiedObject ReadObject(string fileName, Encoding encoding) { //The current XML file to load XmlDocument currentXML = new XmlDocument(); ObjectManager.StaticObject Object = null; //Load the object's XML file currentXML.Load(fileName); //Check for null if (currentXML.DocumentElement != null) { XmlNodeList DocumentNodes = currentXML.DocumentElement.SelectNodes("/openbve/object"); //Check this file actually contains OpenBVE object nodes if (DocumentNodes != null) { foreach (XmlNode node in DocumentNodes) { string objectPath; try { var fn = System.IO.Path.GetDirectoryName(fileName); var InnerNode = node.SelectSingleNode("filename").InnerText; InnerNode = InnerNode.Trim(); objectPath = OpenBveApi.Path.CombineFile(fn, InnerNode); } catch (Exception) { Interface.AddMessage(MessageType.Error, false, "The XML does not contain a valid object path: " + fileName); return(null); } if (objectPath != null && System.IO.File.Exists(objectPath)) { switch (System.IO.Path.GetExtension(objectPath).ToLowerInvariant()) { case ".csv": case ".b3d": Object = CsvB3dObjectParser.ReadObject(objectPath, encoding); break; case ".x": Object = XObjectParser.ReadObject(objectPath, encoding); break; case ".animated": //Not currently working. //Object = AnimatedObjectParser.ReadObject(objectPath, encoding, LoadMode); break; } try { var BoundingBoxUpper = node.SelectSingleNode("boundingboxupper").InnerText; var BoundingBoxLower = node.SelectSingleNode("boundingboxlower").InnerText; Object.Mesh.BoundingBox = new Vector3[2]; var splitStrings = BoundingBoxUpper.Split(','); if (splitStrings.Length != 3) { //Throw exception, as this isn't a valid 3D point throw new Exception(); } Object.Mesh.BoundingBox[0].X = Double.Parse(splitStrings[0]); Object.Mesh.BoundingBox[0].Y = Double.Parse(splitStrings[1]); Object.Mesh.BoundingBox[0].Z = Double.Parse(splitStrings[2]); splitStrings = BoundingBoxLower.Split(','); if (splitStrings.Length != 3) { //Throw exception, as this isn't a valid 3D point throw new Exception(); } Object.Mesh.BoundingBox[1].X = Double.Parse(splitStrings[0]); Object.Mesh.BoundingBox[1].Y = Double.Parse(splitStrings[1]); Object.Mesh.BoundingBox[1].Y = Double.Parse(splitStrings[2]); } catch (Exception) { Interface.AddMessage(MessageType.Error, false, "The XML contained an invalid bounding box entry: " + fileName); } var selectSingleNode = node.SelectSingleNode("author"); if (selectSingleNode != null) { //Attempt to load author information from XML Object.Author = selectSingleNode.InnerText.Trim(); } selectSingleNode = node.SelectSingleNode("copyright"); if (selectSingleNode != null) { //Attempt to load copyright information from XML Object.Copyright = selectSingleNode.InnerText.Trim(); } return(Object); } Interface.AddMessage(MessageType.Error, false, "The file extension is not supported: " + objectPath); return(null); } } } //We couldn't find any valid XML, so return a null object return(null); }
internal static StaticObject LoadStaticObject(string FileName, Encoding Encoding, bool PreserveVertices) { if (String.IsNullOrEmpty(FileName)) { return(null); } #if !DEBUG try { #endif if (!System.IO.Path.HasExtension(FileName)) { while (true) { string f = OpenBveApi.Path.CombineFile(System.IO.Path.GetDirectoryName(FileName), System.IO.Path.GetFileName(FileName) + ".x"); if (System.IO.File.Exists(f)) { FileName = f; break; } f = OpenBveApi.Path.CombineFile(System.IO.Path.GetDirectoryName(FileName), System.IO.Path.GetFileName(FileName) + ".csv"); if (System.IO.File.Exists(f)) { FileName = f; break; } f = OpenBveApi.Path.CombineFile(System.IO.Path.GetDirectoryName(FileName), System.IO.Path.GetFileName(FileName) + ".b3d"); if (System.IO.File.Exists(f)) { FileName = f; } break; } } StaticObject Result; string e = System.IO.Path.GetExtension(FileName); if (e == null) { Interface.AddMessage(MessageType.Error, false, "The file " + FileName + " does not have a recognised extension."); return(null); } switch (e.ToLowerInvariant()) { case ".csv": case ".b3d": Result = CsvB3dObjectParser.ReadObject(FileName, Encoding); break; case ".x": if (Interface.CurrentOptions.CurrentXParser != Interface.XParsers.Original) { try { if (Interface.CurrentOptions.CurrentXParser == Interface.XParsers.NewXParser) { Result = NewXParser.ReadObject(FileName, Encoding); } else { Result = AssimpXParser.ReadObject(FileName); } } catch (Exception ex) { Interface.AddMessage(MessageType.Error, false, "The new X parser raised the following exception: " + ex); Result = XObjectParser.ReadObject(FileName, Encoding); } } else { Result = XObjectParser.ReadObject(FileName, Encoding); } break; case ".animated": case ".s": Interface.AddMessage(MessageType.Error, false, "Tried to load an animated object even though only static objects are allowed: " + FileName); return(null); case ".obj": if (Interface.CurrentOptions.CurrentObjParser == Interface.ObjParsers.Assimp) { try { Result = AssimpObjParser.ReadObject(FileName); } catch (Exception ex) { Interface.AddMessage(MessageType.Error, false, "The new Obj parser raised the following exception: " + ex); Result = WavefrontObjParser.ReadObject(FileName, Encoding); } } else { Result = WavefrontObjParser.ReadObject(FileName, Encoding); } break; /* * This will require implementing a specific static object load function- Leave alone for the moment * * case ".xml": * Result = XMLParser.ReadObject(FileName, Encoding, ForceTextureRepeatX, ForceTextureRepeatY); * break; */ default: Interface.AddMessage(MessageType.Error, false, "The file extension is not supported: " + FileName); return(null); } if (Result != null) { Result.OptimizeObject(PreserveVertices); } return(Result); #if !DEBUG } catch (Exception ex) { Interface.AddMessage(MessageType.Error, true, "An unexpected error occured (" + ex.Message + ") while attempting to load the file " + FileName); return(null); } #endif }