/// <summary>Creates a mirrored copy of the prototype object (Animated objects)</summary> /// <param name="Prototype">The prototype</param> /// <returns>The mirrored copy</returns> private static UnifiedObject GetMirroredObject(UnifiedObject Prototype) { if (Prototype is ObjectManager.StaticObject) { ObjectManager.StaticObject s = (ObjectManager.StaticObject)Prototype; return(GetMirroredStaticObject(s)); } if (Prototype is ObjectManager.AnimatedObjectCollection) { ObjectManager.AnimatedObjectCollection a = (ObjectManager.AnimatedObjectCollection)Prototype; ObjectManager.AnimatedObjectCollection Result = new ObjectManager.AnimatedObjectCollection { Objects = new ObjectManager.AnimatedObject[a.Objects.Length] }; for (int i = 0; i < a.Objects.Length; i++) { Result.Objects[i] = a.Objects[i].Clone(); for (int j = 0; j < a.Objects[i].States.Length; j++) { Result.Objects[i].States[j].Object = GetMirroredStaticObject(a.Objects[i].States[j].Object); } Result.Objects[i].TranslateXDirection.X *= -1.0; Result.Objects[i].TranslateYDirection.X *= -1.0; Result.Objects[i].TranslateZDirection.X *= -1.0; Result.Objects[i].RotateXDirection.X *= -1.0; Result.Objects[i].RotateYDirection.X *= -1.0; Result.Objects[i].RotateZDirection.X *= -1.0; } return(Result); } return(null); }
internal void Create(PoleDictionary Poles, Vector3 WorldPosition, Transformation RailTransformation, Vector2 Direction, double planar, double updown, double StartingDistance, double EndingDistance) { double dz = StartingDistance / Interval; dz -= Math.Floor(dz + 0.5); if (dz >= -0.01 & dz <= 0.01) { if (Mode == 0) { if (Location <= 0.0) { Poles[0][Type].CreateObject(WorldPosition, RailTransformation, Transformation.NullTransformation, StartingDistance, EndingDistance, StartingDistance); } else { UnifiedObject Pole = Poles[0][Type].Mirror(); Pole.CreateObject(WorldPosition, RailTransformation, Transformation.NullTransformation, StartingDistance, EndingDistance, StartingDistance); } } else { int m = Mode; double dx = -Location * 3.8; double wa = Math.Atan2(Direction.Y, Direction.X) - planar; Vector3 w = new Vector3(Math.Cos(wa), Math.Tan(updown), Math.Sin(wa)); w.Normalize(); double sx = Direction.Y; double sy = 0.0; double sz = -Direction.X; Vector3 wpos = WorldPosition + new Vector3(sx * dx + w.X * dz, sy * dx + w.Y * dz, sz * dx + w.Z * dz); int type = Type; Poles[m][type].CreateObject(wpos, RailTransformation, Transformation.NullTransformation, StartingDistance, EndingDistance, StartingDistance); } } }
public static UnifiedObject InstantiateObject(Node parent, UnifiedObject templateObject, Vector3 position, Transform baseTransformation, Transform auxTransformation, bool accurateObjectDisposal, double startingDistance, double endingDistance, double blockLength, double trackPosition) { StaticObject instantiatedObject = (StaticObject)templateObject.Clone(); MeshInstance instantiatedMesh = instantiatedObject.ObjectMeshInstance; Transform finalTrans = baseTransformation * auxTransformation; instantiatedMesh.GlobalTransform = new Transform(finalTrans.basis, Vector3.Zero); parent.AddChild(instantiatedMesh); instantiatedMesh.GlobalTranslate(position); return(instantiatedObject); // UnifiedObject retObject = null; // if (templateObject is StaticObject) // { // retObject = new StaticObject(); // retObject.gameObject = instantiatedMesh; // } // else if (templateObject is AnimatedObjectCollection) // { // } // return retObject; }
public override bool LoadObject(string path, System.Text.Encoding Encoding, out UnifiedObject Object) { if (base.LoadObject(path, Encoding, out Object)) { return(true); } if (System.IO.File.Exists(path) || System.IO.Directory.Exists(path)) { Encoding = TextEncoding.GetSystemEncodingFromFile(path, Encoding); for (int i = 0; i < Program.CurrentHost.Plugins.Length; i++) { if (Program.CurrentHost.Plugins[i].Object != null) { try { if (Program.CurrentHost.Plugins[i].Object.CanLoadObject(path)) { try { UnifiedObject obj; if (Program.CurrentHost.Plugins[i].Object.LoadObject(path, Encoding, out obj)) { obj.OptimizeObject(false, Interface.CurrentOptions.ObjectOptimizationBasicThreshold, Interface.CurrentOptions.ObjectOptimizationVertexCulling); Object = obj; StaticObject staticObject = Object as StaticObject; if (staticObject != null) { StaticObjectCache.Add(ValueTuple.Create(path, false), staticObject); return(true); } AnimatedObjectCollection aoc = Object as AnimatedObjectCollection; if (aoc != null) { AnimatedObjectCollectionCache.Add(path, aoc); } return(true); } Interface.AddMessage(MessageType.Error, false, "Plugin " + Program.CurrentHost.Plugins[i].Title + " returned unsuccessfully at LoadObject"); } catch (Exception ex) { Interface.AddMessage(MessageType.Error, false, "Plugin " + Program.CurrentHost.Plugins[i].Title + " raised the following exception at LoadObject:" + ex.Message); } } } catch (Exception ex) { Interface.AddMessage(MessageType.Error, false, "Plugin " + Program.CurrentHost.Plugins[i].Title + " raised the following exception at CanLoadObject:" + ex.Message); } } } Interface.AddMessage(MessageType.Error, false, "No plugin found that is capable of loading object " + path); } else { ReportProblem(OpenBveApi.Hosts.ProblemType.PathNotFound, path); } Object = null; return(false); }
public void LoadCarSections(UnifiedObject currentObject, bool visibleFromInterior) { int j = CarSections.Length; Array.Resize(ref CarSections, j + 1); CarSections[j] = new CarSection(TrainManagerBase.currentHost, ObjectType.Dynamic, visibleFromInterior, currentObject); }
internal void LoadCarSections(UnifiedObject currentObject) { int j = CarSections.Length; Array.Resize(ref CarSections, j + 1); CarSections[j] = new CarSection(); if (currentObject is ObjectManager.StaticObject) { ObjectManager.StaticObject s = (ObjectManager.StaticObject)currentObject; CarSections[j].Elements = new ObjectManager.AnimatedObject[1]; CarSections[j].Elements[0] = new ObjectManager.AnimatedObject { States = new ObjectManager.AnimatedObjectState[1] }; CarSections[j].Elements[0].States[0].Position = Vector3.Zero; CarSections[j].Elements[0].States[0].Object = s; CarSections[j].Elements[0].CurrentState = 0; CarSections[j].Elements[0].ObjectIndex = ObjectManager.CreateDynamicObject(); } else if (currentObject is ObjectManager.AnimatedObjectCollection) { ObjectManager.AnimatedObjectCollection a = (ObjectManager.AnimatedObjectCollection)currentObject; CarSections[j].Elements = new ObjectManager.AnimatedObject[a.Objects.Length]; for (int h = 0; h < a.Objects.Length; h++) { CarSections[j].Elements[h] = a.Objects[h].Clone(); CarSections[j].Elements[h].ObjectIndex = ObjectManager.CreateDynamicObject(); } } }
public override bool LoadObject(string path, System.Text.Encoding Encoding, out UnifiedObject unifiedObject) { if (currentObjParser == ObjParsers.Assimp) { try { unifiedObject = AssimpObjParser.ReadObject(path); return(true); } catch (Exception ex) { currentHost.AddMessage(MessageType.Error, false, "The new Obj parser raised the following exception: " + ex); } } try { unifiedObject = WavefrontObjParser.ReadObject(path, Encoding); return(true); } catch { unifiedObject = null; currentHost.AddMessage(MessageType.Error, false, "An unexpected error occured whilst attempting to load the following object: " + path); } return(false); }
public override bool LoadObject(string path, System.Text.Encoding Encoding, out UnifiedObject unifiedObject) { try { if (currentXParser != XParsers.Original) { try { if (currentXParser == XParsers.NewXParser) { unifiedObject = NewXParser.ReadObject(path, Encoding); return(true); } unifiedObject = AssimpXParser.ReadObject(path); return(true); } catch (Exception ex) { currentHost.AddMessage(MessageType.Error, false, "The new X parser raised the following exception: " + ex); unifiedObject = XObjectParser.ReadObject(path, Encoding); return(true); } } unifiedObject = XObjectParser.ReadObject(path, Encoding); return(true); } catch { unifiedObject = null; currentHost.AddMessage(MessageType.Error, false, "An unexpected error occured whilst attempting to load the following object: " + path); } return(false); }
internal void CreateObject(UnifiedObject Prototype, OpenBveApi.Math.Vector3 Position, Transformation BaseTransformation, Transformation AuxTransformation, bool AccurateObjectDisposal, double StartingDistance, double EndingDistance, double BlockLength, double TrackPosition) { if (Prototype != null) { CreateObject(Prototype, Position, BaseTransformation, AuxTransformation, -1, AccurateObjectDisposal, StartingDistance, EndingDistance, BlockLength, TrackPosition, 1.0, false); } }
internal void LoadCarSections(UnifiedObject currentObject, bool visibleFromInterior) { int j = CarSections.Length; Array.Resize(ref CarSections, j + 1); CarSections[j] = new CarSection(Program.CurrentHost, ObjectType.Dynamic); CarSections[j].VisibleFromInterior = visibleFromInterior; if (currentObject is StaticObject) { StaticObject s = (StaticObject)currentObject; CarSections[j].Groups[0].Elements = new AnimatedObject[1]; CarSections[j].Groups[0].Elements[0] = new AnimatedObject(Program.CurrentHost) { States = new[] { new ObjectState(s) }, CurrentState = 0 }; Program.CurrentHost.CreateDynamicObject(ref CarSections[j].Groups[0].Elements[0].internalObject); } else if (currentObject is AnimatedObjectCollection) { AnimatedObjectCollection a = (AnimatedObjectCollection)currentObject; CarSections[j].Groups[0].Elements = new AnimatedObject[a.Objects.Length]; for (int h = 0; h < a.Objects.Length; h++) { CarSections[j].Groups[0].Elements[h] = a.Objects[h].Clone(); Program.CurrentHost.CreateDynamicObject(ref CarSections[j].Groups[0].Elements[h].internalObject); } } }
public override bool LoadObject(string path, System.Text.Encoding Encoding, out UnifiedObject Object) { if (System.IO.File.Exists(path) || System.IO.Directory.Exists(path)) { for (int i = 0; i < Plugins.LoadedPlugins.Length; i++) { if (Plugins.LoadedPlugins[i].Object != null) { try { if (Plugins.LoadedPlugins[i].Object.CanLoadObject(path)) { try { if (Plugins.LoadedPlugins[i].Object.LoadObject(path, Encoding, out Object)) { return(true); } Interface.AddMessage(MessageType.Error, false, "Plugin " + Plugins.LoadedPlugins[i].Title + " returned unsuccessfully at LoadObject"); } catch (Exception ex) { Interface.AddMessage(MessageType.Error, false, "Plugin " + Plugins.LoadedPlugins[i].Title + " raised the following exception at LoadObject:" + ex.Message); } } } catch (Exception ex) { Interface.AddMessage(MessageType.Error, false, "Plugin " + Plugins.LoadedPlugins[i].Title + " raised the following exception at CanLoadObject:" + ex.Message); } } } Interface.AddMessage(MessageType.Error, false, "No plugin found that is capable of loading object " + path); } else { ReportProblem(ProblemType.PathNotFound, path); } Object = null; return(false); }
internal void LoadCarSections(UnifiedObject currentObject) { int j = CarSections.Length; Array.Resize(ref CarSections, j + 1); CarSections[j] = new CarSection { Groups = new ElementsGroup[1] }; CarSections[j].Groups[0] = new ElementsGroup(); if (currentObject is StaticObject) { StaticObject s = (StaticObject)currentObject; CarSections[j].Groups[0].Elements = new AnimatedObject[1]; CarSections[j].Groups[0].Elements[0] = new AnimatedObject(Program.CurrentHost) { States = new[] { new ObjectState() } }; CarSections[j].Groups[0].Elements[0].States[0].Prototype = s; CarSections[j].Groups[0].Elements[0].CurrentState = 0; Program.CurrentHost.CreateDynamicObject(ref CarSections[j].Groups[0].Elements[0].internalObject); } else if (currentObject is AnimatedObjectCollection) { AnimatedObjectCollection a = (AnimatedObjectCollection)currentObject; CarSections[j].Groups[0].Elements = new AnimatedObject[a.Objects.Length]; for (int h = 0; h < a.Objects.Length; h++) { CarSections[j].Groups[0].Elements[h] = a.Objects[h].Clone(); Program.CurrentHost.CreateDynamicObject(ref CarSections[j].Groups[0].Elements[h].internalObject); } } }
internal static void DragFile(object sender, FileDropEventArgs e) { int n = Files.Length; Array.Resize <string>(ref Files, n + 1); Files[n] = e.FileName; // reset ReducedMode = false; LightingRelative = -1.0; Game.Reset(); Textures.UnloadAllTextures(); //Fonts.Initialize(); Interface.ClearMessages(); for (int i = 0; i < Files.Length; i++) { #if !DEBUG try { #endif if (String.Compare(System.IO.Path.GetFileName(Files[i]), "extensions.cfg", StringComparison.OrdinalIgnoreCase) == 0) { UnifiedObject[] carObjects; UnifiedObject[] bogieObjects; TrainManager.Train train; ExtensionsCfgParser.ParseExtensionsConfig(Files[i], System.Text.Encoding.UTF8, out carObjects, out bogieObjects, out train, true); double z = 0.0; for (int j = 0; j < carObjects.Length; j++) { ObjectManager.CreateObject(carObjects[j], new Vector3(0.0, 0.0, z), new Transformation(0.0, 0.0, 0.0), new Transformation(0.0, 0.0, 0.0), true, 0.0, 0.0, 25.0, 0.0); if (j < train.Cars.Length - 1) { z -= (train.Cars[j].Length + train.Cars[j + 1].Length) / 2; } } } else { UnifiedObject o = ObjectManager.LoadObject(Files[i], System.Text.Encoding.UTF8, false, false, false); ObjectManager.CreateObject(o, Vector3.Zero, new Transformation(0.0, 0.0, 0.0), new Transformation(0.0, 0.0, 0.0), true, 0.0, 0.0, 25.0, 0.0); } #if !DEBUG } catch (Exception ex) { Interface.AddMessage(MessageType.Critical, false, "Unhandled error (" + ex.Message + ") encountered while processing the file " + Files[i] + "."); } #endif } ObjectManager.InitializeVisibility(); ObjectManager.FinishCreatingObjects(); ObjectManager.UpdateVisibility(0.0, true); ObjectManager.UpdateAnimatedWorldObjects(0.01, true); }
internal static int CreateStaticObject(UnifiedObject Prototype, Vector3 Position, Transformation BaseTransformation, Transformation AuxTransformation, bool AccurateObjectDisposal, double AccurateObjectDisposalZOffset, double StartingDistance, double EndingDistance, double BlockLength, double TrackPosition, double Brightness) { StaticObject obj = (StaticObject)Prototype; if (obj == null) { Interface.AddMessage(MessageType.Error, false, "Attempted to use an animated object where only static objects are allowed."); return(-1); } return(CreateStaticObject(obj, Position, BaseTransformation, AuxTransformation, AccurateObjectDisposal, AccurateObjectDisposalZOffset, StartingDistance, EndingDistance, BlockLength, TrackPosition, Brightness)); }
public static bool LoadObject(string path, Encoding encoding, out UnifiedObject obj) { foreach (var intf in interfaces) { if (intf.CanLoadObject(path) && intf.LoadObject(path, encoding, out obj)) { return(true); } } obj = null; return(false); }
public override bool LoadObject(string path, Encoding Encoding, out UnifiedObject unifiedObject) { try { unifiedObject = ReadObject(path, Encoding); return(true); } catch { unifiedObject = null; return(false); } }
public override bool LoadObject(string path, Encoding Encoding, out UnifiedObject unifiedObject) { try { unifiedObject = MsTsShapeParser.ReadObject(path); } catch { unifiedObject = null; return(false); } return(true); }
internal void CreateObject(UnifiedObject Prototype, OpenBveApi.Math.Vector3 Position, Transformation BaseTransformation, Transformation AuxTransformation, int SectionIndex, bool AccurateObjectDisposal, double StartingDistance, double EndingDistance, double BlockLength, double TrackPosition, double Brightness, bool DuplicateMaterials) { if (Prototype is StaticObject) { StaticObject s = (StaticObject)Prototype; CreateStaticObject(s, Position, BaseTransformation, AuxTransformation, AccurateObjectDisposal, 0.0, StartingDistance, EndingDistance, BlockLength, TrackPosition, Brightness); } else if (Prototype is AnimatedObjectCollection) { AnimatedObjectCollection a = (AnimatedObjectCollection)Prototype; a.CreateObject(Position, BaseTransformation, AuxTransformation, SectionIndex, AccurateObjectDisposal, StartingDistance, EndingDistance, BlockLength, TrackPosition, Brightness, DuplicateMaterials); } }
public override bool LoadObject(string path, System.Text.Encoding Encoding, out UnifiedObject unifiedObject) { try { unifiedObject = ReadObject(path, Encoding); return(true); } catch { unifiedObject = null; currentHost.AddMessage(MessageType.Error, false, "An unexpected error occured whilst attempting to load the following object: " + path); } return(false); }
internal int CreateStaticObject(UnifiedObject Prototype, Vector3 Position, Transformation BaseTransformation, Transformation AuxTransformation, bool AccurateObjectDisposal, double AccurateObjectDisposalZOffset, double StartingDistance, double EndingDistance, double BlockLength, double TrackPosition, double Brightness) { StaticObject obj = Prototype as StaticObject; if (obj == null) { Interface.AddMessage(MessageType.Error, false, "Attempted to use an animated object where only static objects are allowed."); return(-1); } if (obj.Mesh.Faces.Length == 0) { //Null object- Waste of time trying to calculate anything for these return(-1); } return(base.CreateStaticObject(obj, Position, BaseTransformation, AuxTransformation, AccurateObjectDisposal, AccurateObjectDisposalZOffset, StartingDistance, EndingDistance, BlockLength, TrackPosition, Brightness)); }
internal void CreateObject(UnifiedObject Prototype, Vector3 Position, Transformation BaseTransformation, Transformation AuxTransformation, int SectionIndex, bool AccurateObjectDisposal, double StartingDistance, double EndingDistance, double BlockLength, double TrackPosition, double Brightness) { if (Prototype is StaticObject) { StaticObject s = (StaticObject)Prototype; if (s.Mesh.Faces.Length == 0) { return; } CreateStaticObject(s, Position, BaseTransformation, AuxTransformation, AccurateObjectDisposal, 0.0, StartingDistance, EndingDistance, BlockLength, TrackPosition, Brightness); } else if (Prototype is AnimatedObjectCollection) { AnimatedObjectCollection a = (AnimatedObjectCollection)Prototype; a.CreateObject(Position, BaseTransformation, AuxTransformation, SectionIndex, AccurateObjectDisposal, StartingDistance, EndingDistance, BlockLength, TrackPosition, Brightness, true); } }
internal void Create(Vector3 wpos, Transformation RailTransformation, double StartingDistance, double EndingDistance, ObjectDictionary Beacon) { UnifiedObject obj = null; if (Beacon.ContainsKey(BeaconStructureIndex)) { obj = Beacon[BeaconStructureIndex]; } if (obj != null) { double dx = Position.X; double dy = Position.Y; double dz = TrackPosition - StartingDistance; wpos += dx * RailTransformation.X + dy * RailTransformation.Y + dz * RailTransformation.Z; double tpos = TrackPosition; obj.CreateObject(wpos, RailTransformation, new Transformation(Yaw, Pitch, Roll), StartingDistance, EndingDistance, tpos); } }
internal void Create(Vector3 wpos, Transformation RailTransformation, double StartingDistance, double EndingDistance, double Brightness, ObjectDictionary Beacon) { UnifiedObject obj = null; if (BeaconStructureIndex == -2) { switch (Type) { case 0: obj = CompatibilityObjects.TransponderS; break; case 1: obj = CompatibilityObjects.TransponderSN; break; case 2: obj = CompatibilityObjects.TransponderFalseStart; break; case 3: obj = CompatibilityObjects.TransponderPOrigin; break; case 4: obj = CompatibilityObjects.TransponderPStop; break; } } else { int b = BeaconStructureIndex; if (b >= 0 & Beacon.ContainsKey(b)) { obj = Beacon[b]; } } if (obj != null) { double dx = Position.X; double dy = Position.Y; double dz = TrackPosition - StartingDistance; wpos += dx * RailTransformation.X + dy * RailTransformation.Y + dz * RailTransformation.Z; double tpos = TrackPosition; if (BeaconStructureIndex == -2) { obj.CreateObject(wpos, RailTransformation, new Transformation(Yaw, Pitch, Roll), -1, StartingDistance, EndingDistance, tpos, Brightness); } else { obj.CreateObject(wpos, RailTransformation, new Transformation(Yaw, Pitch, Roll), StartingDistance, EndingDistance, tpos); } } }
/// <summary>Loads an object</summary> /// <param name="Path">The absolute on-disk path to the object</param> /// <param name="Encoding">The detected text encoding</param> /// <param name="Object">The handle to the object</param> /// <returns>Whether loading the object was successful</returns> public virtual bool LoadObject(string Path, System.Text.Encoding Encoding, out UnifiedObject Object) { ValueTuple <string, bool> key = ValueTuple.Create(Path, false); if (StaticObjectCache.ContainsKey(key)) { Object = StaticObjectCache[key].Clone(); return(true); } if (AnimatedObjectCollectionCache.ContainsKey(Path)) { Object = AnimatedObjectCollectionCache[Path].Clone(); return(true); } Object = null; return(false); }
public override bool LoadObject(string path, Encoding Encoding, out UnifiedObject unifiedObject) { try { if (path.ToLowerInvariant().EndsWith(".l3dobj", StringComparison.InvariantCultureIgnoreCase)) { unifiedObject = Ls3DObjectParser.ReadObject(path, Vector3.Zero); } else { unifiedObject = Ls3DGrpParser.ReadObject(path, Encoding, Vector3.Zero); } } catch { unifiedObject = null; return(false); } return(true); }
public void Create(PoleDictionary poles, Vector3 worldPos, Transform railTransform, Vector2 direction, float planar, float updown, float startingDistance, float endingDistance) { if (!Exists) { return; } float dz = startingDistance / Interval; dz -= Godot.Mathf.Floor(dz + 0.5f); if (dz >= -0.01 & dz <= 0.01) { if (Mode == 0) { if (Location <= 0.0) { poles[0][Type].CreateObject(worldPos, railTransform, startingDistance, endingDistance, startingDistance); } else { UnifiedObject Pole = poles[0][Type].Mirror(); Pole.CreateObject(worldPos, railTransform, startingDistance, endingDistance, startingDistance); } } else { int m = Mode; float dx = -Location * 3.8f; float wa = Godot.Mathf.Atan2(direction.y, direction.x) - planar; Vector3 w = new Vector3(Godot.Mathf.Cos(wa), Godot.Mathf.Tan(updown), Godot.Mathf.Sin(wa)); w = w.Normalized(); float sx = direction.y; float sy = 0.0f; float sz = -direction.x; Vector3 wpos = worldPos + new Vector3(sx * dx + w.x * dz, sy * dx + w.y * dz, sz * dx + w.z * dz); int type = Type; poles[m][type].CreateObject(wpos, railTransform, startingDistance, endingDistance, startingDistance); } } }
internal static void LoadAutoGeneratedObjects(string CompatibilityFolder, out string LimitGraphicsPath) { string SignalPath = OpenBveApi.Path.CombineDirectory(CompatibilityFolder, "Signals"); SignalPost = ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(SignalPath, "signal_post.csv"), System.Text.Encoding.UTF8, false); string LimitPath = OpenBveApi.Path.CombineDirectory(CompatibilityFolder, "Limits"); LimitGraphicsPath = OpenBveApi.Path.CombineDirectory(LimitPath, "Graphics"); LimitPostStraight = ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(LimitPath, "limit_straight.csv"), System.Text.Encoding.UTF8, false); LimitPostLeft = ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(LimitPath, "limit_left.csv"), System.Text.Encoding.UTF8, false); LimitPostRight = ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(LimitPath, "limit_right.csv"), System.Text.Encoding.UTF8, false); LimitPostInfinite = ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(LimitPath, "limit_infinite.csv"), System.Text.Encoding.UTF8, false); LimitOneDigit = ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(LimitPath, "limit_1_digit.csv"), System.Text.Encoding.UTF8, false); LimitTwoDigits = ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(LimitPath, "limit_2_digits.csv"), System.Text.Encoding.UTF8, false); LimitThreeDigits = ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(LimitPath, "limit_3_digits.csv"), System.Text.Encoding.UTF8, false); StopPost = ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(CompatibilityFolder, "stop.csv"), System.Text.Encoding.UTF8, false); string TransponderPath = OpenBveApi.Path.CombineDirectory(CompatibilityFolder, "Transponders"); TransponderS = ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(TransponderPath, "s.csv"), System.Text.Encoding.UTF8, false); TransponderSN = ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(TransponderPath, "sn.csv"), System.Text.Encoding.UTF8, false); TransponderFalseStart = ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(TransponderPath, "falsestart.csv"), System.Text.Encoding.UTF8, false); TransponderPOrigin = ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(TransponderPath, "porigin.csv"), System.Text.Encoding.UTF8, false); TransponderPStop = ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(TransponderPath, "pstop.csv"), System.Text.Encoding.UTF8, false); }
// create object internal static void CreateObject(UnifiedObject Prototype, World.Vector3D Position, World.Transformation BaseTransformation, World.Transformation AuxTransformation, bool AccurateObjectDisposal, double StartingDistance, double EndingDistance, double BlockLength, double TrackPosition) { if (Prototype != null) { CreateObject(Prototype, Position, BaseTransformation, AuxTransformation, -1, AccurateObjectDisposal, StartingDistance, EndingDistance, BlockLength, TrackPosition, 1.0, false); } else { int a = ObjectsUsed; if (a >= Objects.Length) { Array.Resize<StaticObject>(ref Objects, Objects.Length << 1); } ObjectsUsed++; } }
/// <summary>Loads a Loksim3D GruppenObject</summary> /// <param name="FileName">The filename to load</param> /// <param name="Encoding">The text encoding of the containing file (Currently ignored, REMOVE??)</param> /// <param name="Rotation">A three-dimemsional vector describing the rotation to be applied</param> /// <returns>A new animated object collection, containing the GruppenObject's meshes etc.</returns> internal static ObjectManager.AnimatedObjectCollection ReadObject(string FileName, Encoding Encoding, Vector3 Rotation) { XmlDocument currentXML = new XmlDocument(); ObjectManager.AnimatedObjectCollection Result = new ObjectManager.AnimatedObjectCollection(); Result.Objects = new ObjectManager.AnimatedObject[0]; try { currentXML.Load(FileName); } catch (Exception ex) { //The XML is not strictly valid string[] Lines = File.ReadAllLines(FileName); using (var stringReader = new StringReader(Lines[0])) { var settings = new XmlReaderSettings { ConformanceLevel = ConformanceLevel.Fragment }; using (var xmlReader = XmlReader.Create(stringReader, settings)) { if (xmlReader.Read()) { //Attempt to find the text encoding and re-read the file var result = xmlReader.GetAttribute("encoding"); if (result != null) { var e = System.Text.Encoding.GetEncoding(result); Lines = File.ReadAllLines(FileName, e); //Turf out the old encoding, as our string array should now be UTF-8 Lines[0] = "<?xml version=\"1.0\"?>"; } } } } for (int i = 0; i < Lines.Length; i++) { while (Lines[i].IndexOf("\"\"", StringComparison.InvariantCulture) != -1) { //Loksim parser tolerates multiple quotes, strict XML does not Lines[i] = Lines[i].Replace("\"\"", "\""); } while (Lines[i].IndexOf(" ", StringComparison.InvariantCulture) != -1) { //Replace double-spaces with singles Lines[i] = Lines[i].Replace(" ", " "); } } bool tryLoad = false; try { //Horrible hack: Write out our string array to a new memory stream, then load from this stream //Why can't XmlDocument.Load() just take a string array...... using (var stream = new MemoryStream()) { var sw = new StreamWriter(stream); foreach (var line in Lines) { sw.Write(line); sw.Flush(); } sw.Flush(); stream.Position = 0; currentXML.Load(stream); tryLoad = true; } } catch { //Generic catch-all clause } if (!tryLoad) { //Pass out the *original* XML error, not anything generated when we've tried to correct it Interface.AddMessage(MessageType.Error, false, "Error parsing Loksim3D XML: " + ex.Message); return(null); } } string BaseDir = System.IO.Path.GetDirectoryName(FileName); GruppenObject[] CurrentObjects = new GruppenObject[0]; //Check for null if (currentXML.DocumentElement != null) { UnifiedObject[] obj = new UnifiedObject[0]; XmlNodeList DocumentNodes = currentXML.DocumentElement.SelectNodes("/GRUPPENOBJECT"); if (DocumentNodes != null) { foreach (XmlNode outerNode in DocumentNodes) { if (outerNode.ChildNodes.OfType <XmlElement>().Any()) { foreach (XmlNode node in outerNode.ChildNodes) { if (node.Name == "Object" && node.ChildNodes.OfType <XmlElement>().Any()) { foreach (XmlNode childNode in node.ChildNodes) { if (childNode.Name == "Props" && childNode.Attributes != null) { GruppenObject Object = new GruppenObject { Rotation = Rotation }; foreach (XmlAttribute attribute in childNode.Attributes) { switch (attribute.Name) { case "Name": string ObjectFile = OpenBveApi.Path.Loksim3D.CombineFile(BaseDir, attribute.Value, Program.FileSystem.LoksimPackageInstallationDirectory); if (!File.Exists(ObjectFile)) { Object.Name = null; Interface.AddMessage(MessageType.Warning, true, "Ls3d Object file " + attribute.Value + " not found."); } else { Object.Name = ObjectFile; } break; case "Position": string[] SplitPosition = attribute.Value.Split(';'); double.TryParse(SplitPosition[0], out Object.Position.X); double.TryParse(SplitPosition[1], out Object.Position.Y); double.TryParse(SplitPosition[2], out Object.Position.Z); break; case "Rotation": string[] SplitRotation = attribute.Value.Split(';'); Vector3 r; double.TryParse(SplitRotation[0], out r.X); double.TryParse(SplitRotation[1], out r.Y); double.TryParse(SplitRotation[2], out r.Z); Object.Rotation += r; break; case "ShowOn": //Defines when the object should be shown Object.FunctionScript = FunctionScriptNotation.GetPostfixNotationFromInfixNotation(GetAnimatedFunction(attribute.Value, false)); break; case "HideOn": //Defines when the object should be hidden Object.FunctionScript = FunctionScriptNotation.GetPostfixNotationFromInfixNotation(GetAnimatedFunction(attribute.Value, true)); break; case "FixedDynamicVisibility": if (attribute.Value.ToLowerInvariant() == "true") { Object.FixedDynamicVisibility = true; } else { Object.FixedDynamicVisibility = false; } break; case "DynamicVisibility": if (Object.FixedDynamicVisibility) { Object.FunctionScript = FunctionScriptNotation.GetPostfixNotationFromInfixNotation(GetDynamicFunction(attribute.Value)); } break; } } if (Object.Name != null) { Array.Resize <GruppenObject>(ref CurrentObjects, CurrentObjects.Length + 1); CurrentObjects[CurrentObjects.Length - 1] = Object; } } } } } } } //We've loaded the XML references, now load the objects into memory //Single mesh object, containing all static components of the LS3D object //If we use multiples, the Z-sorting throws a wobbly StaticObject staticObject = null; for (int i = 0; i < CurrentObjects.Length; i++) { if (CurrentObjects[i] == null || string.IsNullOrEmpty(CurrentObjects[i].Name)) { continue; } StaticObject Object = null; ObjectManager.AnimatedObjectCollection AnimatedObject = null; try { if (CurrentObjects[i].Name.ToLowerInvariant().EndsWith(".l3dgrp")) { AnimatedObject = ReadObject(CurrentObjects[i].Name, Encoding, CurrentObjects[i].Rotation); } else if (CurrentObjects[i].Name.ToLowerInvariant().EndsWith(".l3dobj")) { Object = (StaticObject)ObjectManager.LoadObject(CurrentObjects[i].Name, Encoding, false, false, false, CurrentObjects[i].Rotation); } else { throw new Exception("Format " + System.IO.Path.GetExtension(CurrentObjects[i].Name) + " is not currently supported by the Loksim3D object parser"); } } catch (Exception ex) { Interface.AddMessage(MessageType.Error, false, ex.Message); } if (Object != null) { if (!string.IsNullOrEmpty(CurrentObjects[i].FunctionScript)) { //If the function script is not empty, this is a new animated object bit Array.Resize <UnifiedObject>(ref obj, obj.Length + 1); obj[obj.Length - 1] = Object; int aL = Result.Objects.Length; Array.Resize <ObjectManager.AnimatedObject>(ref Result.Objects, aL + 1); ObjectManager.AnimatedObject a = new ObjectManager.AnimatedObject(); AnimatedObjectState aos = new AnimatedObjectState(Object, CurrentObjects[i].Position); a.States = new AnimatedObjectState[] { aos }; Result.Objects[aL] = a; Result.Objects[aL].StateFunction = new FunctionScript(Program.CurrentHost, CurrentObjects[i].FunctionScript + " 1 == --", false); } else { //Otherwise, join to the main static mesh & update co-ords for (int j = 0; j < Object.Mesh.Vertices.Length; j++) { Object.Mesh.Vertices[j].Coordinates += CurrentObjects[i].Position; } staticObject.JoinObjects(Object); } } else if (AnimatedObject != null) { int rl = Result.Objects.Length; int l = AnimatedObject.Objects.Length; Array.Resize <ObjectManager.AnimatedObject>(ref Result.Objects, Result.Objects.Length + l); for (int o = rl; o < rl + l; o++) { if (AnimatedObject.Objects[o - rl] != null) { Result.Objects[o] = AnimatedObject.Objects[o - rl].Clone(); for (int si = 0; si < Result.Objects[o].States.Length; si++) { Result.Objects[o].States[si].Position += CurrentObjects[i].Position; } } else { Result.Objects[o] = new ObjectManager.AnimatedObject(); Result.Objects[o].States = new AnimatedObjectState[0]; } } } } if (staticObject != null) { Array.Resize <ObjectManager.AnimatedObject>(ref Result.Objects, Result.Objects.Length + 1); ObjectManager.AnimatedObject a = new ObjectManager.AnimatedObject(); AnimatedObjectState aos = new AnimatedObjectState(staticObject, Vector3.Zero); a.States = new AnimatedObjectState[] { aos }; Result.Objects[Result.Objects.Length - 1] = a; } } return(Result); } //Didn't find an acceptable XML object //Probably will cause things to throw an absolute wobbly somewhere.... return(null); }
// process events internal static void KeyDown(object sender, KeyboardKeyEventArgs e) { switch (e.Key) { case Key.LShift: case Key.RShift: ShiftPressed = true; break; case Key.F5: // reset ReducedMode = false; LightingRelative = -1.0; Game.Reset(); Textures.UnloadAllTextures(); //Fonts.Initialize(); Interface.ClearMessages(); for (int i = 0; i < Files.Length; i++) { #if !DEBUG try { #endif if (String.Compare(System.IO.Path.GetFileName(Files[i]), "extensions.cfg", StringComparison.OrdinalIgnoreCase) == 0) { UnifiedObject[] carObjects; UnifiedObject[] bogieObjects; double[] axleLocations; TrainManager.Train train; ExtensionsCfgParser.ParseExtensionsConfig(Files[i], System.Text.Encoding.UTF8, out carObjects, out bogieObjects, out axleLocations, out train, true); if (axleLocations.Length == 0) { axleLocations = new double[train.Cars.Length * 2]; for (int j = 0; j < train.Cars.Length; j++) { double ap = train.Cars.Length * 0.4; axleLocations[j] = ap; j++; axleLocations[j] = -ap; } } double z = 0.0; for (int j = 0; j < carObjects.Length; j++) { ObjectManager.CreateObject(carObjects[j], new Vector3(0.0, 0.0, z), new Transformation(0.0, 0.0, 0.0), new Transformation(0.0, 0.0, 0.0), true, 0.0, 0.0, 25.0, 0.0); if (j < train.Cars.Length - 1) { z -= (train.Cars[j].Length + train.Cars[j + 1].Length) / 2; } } z = 0.0; for (int j = 0; j < bogieObjects.Length; j++) { ObjectManager.CreateObject(bogieObjects[j], new Vector3(0.0, 0.0, z + axleLocations[j]), new Transformation(0.0, 0.0, 0.0), new Transformation(0.0, 0.0, 0.0), true, 0.0, 0.0, 25.0, 0.0); j++; ObjectManager.CreateObject(bogieObjects[j], new Vector3(0.0, 0.0, z - axleLocations[j]), new Transformation(0.0, 0.0, 0.0), new Transformation(0.0, 0.0, 0.0), true, 0.0, 0.0, 25.0, 0.0); if (j < train.Cars.Length - 1) { z -= (train.Cars[j].Length + train.Cars[j + 1].Length) / 2; } } } else { UnifiedObject o = ObjectManager.LoadObject(Files[i], System.Text.Encoding.UTF8, false, false, false); ObjectManager.CreateObject(o, Vector3.Zero, new Transformation(0.0, 0.0, 0.0), new Transformation(0.0, 0.0, 0.0), true, 0.0, 0.0, 25.0, 0.0); } #if !DEBUG } catch (Exception ex) { Interface.AddMessage(MessageType.Critical, false, "Unhandled error (" + ex.Message + ") encountered while processing the file " + Files[i] + "."); } #endif } ObjectManager.InitializeVisibility(); ObjectManager.UpdateVisibility(0.0, true); ObjectManager.UpdateAnimatedWorldObjects(0.01, true); break; case Key.F7: { OpenFileDialog Dialog = new OpenFileDialog { CheckFileExists = true, Multiselect = true, Filter = @"All supported object files|*.csv;*.b3d;*.x;*.animated;extensions.cfg;*.l3dobj;*.l3dgrp;*.obj;*.s|openBVE Objects|*.csv;*.b3d;*.x;*.animated;extensions.cfg|LokSim 3D Objects|*.l3dobj;*.l3dgrp|Wavefront Objects|*.obj|Microsoft Train Simulator Objects|*.s|All files|*" }; if (Dialog.ShowDialog() == DialogResult.OK) { Application.DoEvents(); string[] f = Dialog.FileNames; int n = Files.Length; Array.Resize <string>(ref Files, n + f.Length); for (int i = 0; i < f.Length; i++) { Files[n + i] = f[i]; } // reset ReducedMode = false; LightingRelative = -1.0; Game.Reset(); Textures.UnloadAllTextures(); Interface.ClearMessages(); for (int i = 0; i < Files.Length; i++) { #if !DEBUG try { #endif if (String.Compare(System.IO.Path.GetFileName(Files[i]), "extensions.cfg", StringComparison.OrdinalIgnoreCase) == 0) { UnifiedObject[] carObjects; UnifiedObject[] bogieObjects; double[] axleLocations; TrainManager.Train train; ExtensionsCfgParser.ParseExtensionsConfig(Files[i], System.Text.Encoding.UTF8, out carObjects, out bogieObjects, out axleLocations, out train, true); if (axleLocations.Length == 0) { axleLocations = new double[train.Cars.Length * 2]; for (int j = 0; j < train.Cars.Length; j++) { double ap = train.Cars.Length * 0.4; axleLocations[j] = ap; j++; axleLocations[j] = -ap; } } double z = 0.0; for (int j = 0; j < carObjects.Length; j++) { ObjectManager.CreateObject(carObjects[j], new Vector3(0.0, 0.0, z), new Transformation(0.0, 0.0, 0.0), new Transformation(0.0, 0.0, 0.0), true, 0.0, 0.0, 25.0, 0.0); if (j < train.Cars.Length - 1) { z -= (train.Cars[j].Length + train.Cars[j + 1].Length) / 2; } } z = 0.0; for (int j = 0; j < bogieObjects.Length; j++) { ObjectManager.CreateObject(bogieObjects[j], new Vector3(0.0, 0.0, z + axleLocations[j]), new Transformation(0.0, 0.0, 0.0), new Transformation(0.0, 0.0, 0.0), true, 0.0, 0.0, 25.0, 0.0); j++; ObjectManager.CreateObject(bogieObjects[j], new Vector3(0.0, 0.0, z - axleLocations[j]), new Transformation(0.0, 0.0, 0.0), new Transformation(0.0, 0.0, 0.0), true, 0.0, 0.0, 25.0, 0.0); if (j < train.Cars.Length - 1) { z -= (train.Cars[j].Length + train.Cars[j + 1].Length) / 2; } } } else { UnifiedObject o = ObjectManager.LoadObject(Files[i], System.Text.Encoding.UTF8, false, false, false); ObjectManager.CreateObject(o, Vector3.Zero, new Transformation(0.0, 0.0, 0.0), new Transformation(0.0, 0.0, 0.0), true, 0.0, 0.0, 25.0, 0.0); } #if !DEBUG } catch (Exception ex) { Interface.AddMessage(MessageType.Critical, false, "Unhandled error (" + ex.Message + ") encountered while processing the file " + Files[i] + "."); } #endif } ObjectManager.InitializeVisibility(); ObjectManager.FinishCreatingObjects(); ObjectManager.UpdateVisibility(0.0, true); ObjectManager.UpdateAnimatedWorldObjects(0.01, true); } else { if (Program.CurrentlyRunOnMono) { //HACK: Dialog doesn't close properly when pressing the ESC key under Mono //Avoid calling Application.DoEvents() unless absolutely necessary though! Application.DoEvents(); } } Dialog.Dispose(); } break; case Key.F9: if (Interface.MessageCount != 0) { formMessages.ShowMessages(); Application.DoEvents(); } break; case Key.Delete: ReducedMode = false; LightingRelative = -1.0; Game.Reset(); Textures.UnloadAllTextures(); //Fonts.Initialize(); Interface.ClearMessages(); Files = new string[] { }; break; case Key.Left: RotateX = -1; ReducedMode = false; break; case Key.Right: RotateX = 1; ReducedMode = false; break; case Key.Up: RotateY = -1; ReducedMode = false; break; case Key.Down: RotateY = 1; ReducedMode = false; break; case Key.A: case Key.Keypad4: MoveX = -1; ReducedMode = false; break; case Key.D: case Key.Keypad6: MoveX = 1; ReducedMode = false; break; case Key.Keypad8: MoveY = 1; ReducedMode = false; break; case Key.Keypad2: MoveY = -1; ReducedMode = false; break; case Key.W: case Key.Keypad9: MoveZ = 1; ReducedMode = false; break; case Key.S: case Key.Keypad3: MoveZ = -1; ReducedMode = false; break; case Key.Keypad5: ResetCamera(); break; case Key.F: case Key.F1: Renderer.OptionWireframe = !Renderer.OptionWireframe; if (Renderer.OptionWireframe) { GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); } else { GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill); } break; case Key.N: case Key.F2: Renderer.OptionNormals = !Renderer.OptionNormals; break; case Key.L: case Key.F3: LightingTarget = 1 - LightingTarget; ReducedMode = false; break; case Key.I: case Key.F4: Renderer.OptionInterface = !Renderer.OptionInterface; ReducedMode = false; break; case Key.F8: formOptions.ShowOptions(); Application.DoEvents(); break; case Key.F10: formTrain.ShowTrainSettings(); break; case Key.G: case Key.C: Renderer.OptionCoordinateSystem = !Renderer.OptionCoordinateSystem; ReducedMode = false; break; case Key.B: if (ShiftPressed) { ColorDialog dialog = new ColorDialog(); dialog.FullOpen = true; if (dialog.ShowDialog() == DialogResult.OK) { Renderer.BackgroundColor = -1; Renderer.ApplyBackgroundColor(dialog.Color.R, dialog.Color.G, dialog.Color.B); } } else { Renderer.BackgroundColor++; if (Renderer.BackgroundColor >= Renderer.MaxBackgroundColor) { Renderer.BackgroundColor = 0; } Renderer.ApplyBackgroundColor(); } ReducedMode = false; break; } }
// optimize object internal static void OptimizeObject(UnifiedObject Prototype, bool PreserveVertices) { if (Prototype is StaticObject) { StaticObject s = (StaticObject)Prototype; OptimizeObject(s, PreserveVertices); } else if (Prototype is AnimatedObjectCollection) { AnimatedObjectCollection a = (AnimatedObjectCollection)Prototype; for (int i = 0; i < a.Objects.Length; i++) { for (int j = 0; j < a.Objects[i].States.Length; j++) { OptimizeObject(a.Objects[i].States[j].Object, PreserveVertices); } } } }
internal static void CreateObject(UnifiedObject Prototype, Vector3 Position, World.Transformation BaseTransformation, World.Transformation AuxTransformation, int SectionIndex, bool AccurateObjectDisposal, double StartingDistance, double EndingDistance, double BlockLength, double TrackPosition, double Brightness, bool DuplicateMaterials) { if (Prototype is StaticObject) { StaticObject s = (StaticObject)Prototype; CreateStaticObject(s, Position, BaseTransformation, AuxTransformation, AccurateObjectDisposal, 0.0, StartingDistance, EndingDistance, BlockLength, TrackPosition, Brightness, DuplicateMaterials); } else if (Prototype is AnimatedObjectCollection) { AnimatedObjectCollection a = (AnimatedObjectCollection)Prototype; CreateAnimatedWorldObjects(a.Objects, Position, BaseTransformation, AuxTransformation, SectionIndex, AccurateObjectDisposal, StartingDistance, EndingDistance, BlockLength, TrackPosition, Brightness, DuplicateMaterials); } }
// create object internal static void CreateObject(UnifiedObject Prototype, Vector3 Position, World.Transformation BaseTransformation, World.Transformation AuxTransformation, bool AccurateObjectDisposal, double StartingDistance, double EndingDistance, double BlockLength, double TrackPosition) { CreateObject(Prototype, Position, BaseTransformation, AuxTransformation, -1, AccurateObjectDisposal, StartingDistance, EndingDistance, BlockLength, TrackPosition, 1.0, false); }
private static void LoadEverythingThreaded() { Program.FileSystem.AppendToLogFile("Loading route file: " + CurrentRouteFile); Program.FileSystem.AppendToLogFile("INFO: Route file hash " + CsvRwRouteParser.GetChecksum(CurrentRouteFile)); string RailwayFolder = GetRailwayFolder(CurrentRouteFile); string ObjectFolder = OpenBveApi.Path.CombineDirectory(RailwayFolder, "Object"); string SoundFolder = OpenBveApi.Path.CombineDirectory(RailwayFolder, "Sound"); Game.Reset(true, false); Game.MinimalisticSimulation = true; // screen Program.Renderer.Camera.CurrentMode = CameraViewMode.Interior; //First, check the format of the route file //RW routes were written for BVE1 / 2, and have a different command syntax bool IsRW = CsvRwRouteParser.isRWFile(CurrentRouteFile); Program.FileSystem.AppendToLogFile("Route file format is: " + (IsRW ? "RW" : "CSV")); CsvRwRouteParser.ParseRoute(CurrentRouteFile, IsRW, CurrentRouteEncoding, CurrentTrainFolder, ObjectFolder, SoundFolder, false); Thread createIllustrations = new Thread(Game.RouteInformation.LoadInformation) { IsBackground = true }; createIllustrations.Start(); System.Threading.Thread.Sleep(1); if (Cancel) { return; } Program.CurrentRoute.Atmosphere.CalculateSeaLevelConstants(); if (Program.CurrentRoute.BogusPreTrainInstructions.Length != 0) { double t = Program.CurrentRoute.BogusPreTrainInstructions[0].Time; double p = Program.CurrentRoute.BogusPreTrainInstructions[0].TrackPosition; for (int i = 1; i < Program.CurrentRoute.BogusPreTrainInstructions.Length; i++) { if (Program.CurrentRoute.BogusPreTrainInstructions[i].Time > t) { t = Program.CurrentRoute.BogusPreTrainInstructions[i].Time; } else { t += 1.0; Program.CurrentRoute.BogusPreTrainInstructions[i].Time = t; } if (Program.CurrentRoute.BogusPreTrainInstructions[i].TrackPosition > p) { p = Program.CurrentRoute.BogusPreTrainInstructions[i].TrackPosition; } else { p += 1.0; Program.CurrentRoute.BogusPreTrainInstructions[i].TrackPosition = p; } } } World.CameraTrackFollower = new TrackFollower(Program.CurrentHost) { Train = null, Car = null }; if (Program.CurrentRoute.Stations.Length == 1) { //Log the fact that only a single station is present, as this is probably not right Program.FileSystem.AppendToLogFile("The processed route file only contains a single station."); } Program.FileSystem.AppendToLogFile("Route file loaded successfully."); RouteProgress = 1.0; // initialize trains System.Threading.Thread.Sleep(1); if (Cancel) { return; } TrainManager.Trains = new TrainManager.Train[Game.PrecedingTrainTimeDeltas.Length + 1 + (Program.CurrentRoute.BogusPreTrainInstructions.Length != 0 ? 1 : 0)]; for (int k = 0; k < TrainManager.Trains.Length; k++) { if (k == TrainManager.Trains.Length - 1 & Program.CurrentRoute.BogusPreTrainInstructions.Length != 0) { TrainManager.Trains[k] = new TrainManager.Train(TrainState.Bogus); } else { TrainManager.Trains[k] = new TrainManager.Train(TrainState.Pending); } } TrainManager.PlayerTrain = TrainManager.Trains[Game.PrecedingTrainTimeDeltas.Length]; UnifiedObject[] CarObjects = null; UnifiedObject[] BogieObjects = null; UnifiedObject[] CouplerObjects = null; // load trains double TrainProgressMaximum = 0.7 + 0.3 * (double)TrainManager.Trains.Length; for (int k = 0; k < TrainManager.Trains.Length; k++) { //Sleep for 20ms to allow route loading locks to release Thread.Sleep(20); if (TrainManager.Trains[k].State == TrainState.Bogus) { // bogus train string TrainData = OpenBveApi.Path.CombineFile(Program.FileSystem.GetDataFolder("Compatibility", "PreTrain"), "train.dat"); TrainDatParser.ParseTrainData(TrainData, System.Text.Encoding.UTF8, TrainManager.Trains[k]); System.Threading.Thread.Sleep(1); if (Cancel) { return; } TrainManager.Trains[k].InitializeCarSounds(); System.Threading.Thread.Sleep(1); if (Cancel) { return; } TrainProgressCurrentWeight = 0.3 / TrainProgressMaximum; TrainProgressCurrentSum += TrainProgressCurrentWeight; } else { TrainManager.Trains[k].TrainFolder = CurrentTrainFolder; // real train if (TrainManager.Trains[k].IsPlayerTrain) { Program.FileSystem.AppendToLogFile("Loading player train: " + TrainManager.Trains[k].TrainFolder); } else { Program.FileSystem.AppendToLogFile("Loading AI train: " + TrainManager.Trains[k].TrainFolder); } TrainProgressCurrentWeight = 0.1 / TrainProgressMaximum; string TrainData = OpenBveApi.Path.CombineFile(TrainManager.Trains[k].TrainFolder, "train.dat"); TrainDatParser.ParseTrainData(TrainData, CurrentTrainEncoding, TrainManager.Trains[k]); TrainProgressCurrentSum += TrainProgressCurrentWeight; System.Threading.Thread.Sleep(1); if (Cancel) { return; } TrainProgressCurrentWeight = 0.2 / TrainProgressMaximum; SoundCfgParser.ParseSoundConfig(TrainManager.Trains[k].TrainFolder, CurrentTrainEncoding, TrainManager.Trains[k]); TrainProgressCurrentSum += TrainProgressCurrentWeight; System.Threading.Thread.Sleep(1); if (Cancel) { return; } // door open/close speed for (int i = 0; i < TrainManager.Trains[k].Cars.Length; i++) { if (TrainManager.Trains[k].Cars[i].Specs.DoorOpenFrequency <= 0.0) { if (TrainManager.Trains[k].Cars[i].Doors[0].OpenSound.Buffer != null & TrainManager.Trains[k].Cars[i].Doors[1].OpenSound.Buffer != null) { Program.Sounds.LoadBuffer(TrainManager.Trains[k].Cars[i].Doors[0].OpenSound.Buffer); Program.Sounds.LoadBuffer(TrainManager.Trains[k].Cars[i].Doors[1].OpenSound.Buffer); double a = TrainManager.Trains[k].Cars[i].Doors[0].OpenSound.Buffer.Duration; double b = TrainManager.Trains[k].Cars[i].Doors[1].OpenSound.Buffer.Duration; TrainManager.Trains[k].Cars[i].Specs.DoorOpenFrequency = a + b > 0.0 ? 2.0 / (a + b) : 0.8; } else if (TrainManager.Trains[k].Cars[i].Doors[0].OpenSound.Buffer != null) { Program.Sounds.LoadBuffer(TrainManager.Trains[k].Cars[i].Doors[0].OpenSound.Buffer); double a = TrainManager.Trains[k].Cars[i].Doors[0].OpenSound.Buffer.Duration; TrainManager.Trains[k].Cars[i].Specs.DoorOpenFrequency = a > 0.0 ? 1.0 / a : 0.8; } else if (TrainManager.Trains[k].Cars[i].Doors[1].OpenSound.Buffer != null) { Program.Sounds.LoadBuffer(TrainManager.Trains[k].Cars[i].Doors[0].OpenSound.Buffer); double b = TrainManager.Trains[k].Cars[i].Doors[1].OpenSound.Buffer.Duration; TrainManager.Trains[k].Cars[i].Specs.DoorOpenFrequency = b > 0.0 ? 1.0 / b : 0.8; } else { TrainManager.Trains[k].Cars[i].Specs.DoorOpenFrequency = 0.8; } } if (TrainManager.Trains[k].Cars[i].Specs.DoorCloseFrequency <= 0.0) { if (TrainManager.Trains[k].Cars[i].Doors[0].CloseSound.Buffer != null & TrainManager.Trains[k].Cars[i].Doors[1].CloseSound.Buffer != null) { Program.Sounds.LoadBuffer(TrainManager.Trains[k].Cars[i].Doors[0].CloseSound.Buffer); Program.Sounds.LoadBuffer(TrainManager.Trains[k].Cars[i].Doors[1].CloseSound.Buffer); double a = TrainManager.Trains[k].Cars[i].Doors[0].CloseSound.Buffer.Duration; double b = TrainManager.Trains[k].Cars[i].Doors[1].CloseSound.Buffer.Duration; TrainManager.Trains[k].Cars[i].Specs.DoorCloseFrequency = a + b > 0.0 ? 2.0 / (a + b) : 0.8; } else if (TrainManager.Trains[k].Cars[i].Doors[0].CloseSound.Buffer != null) { Program.Sounds.LoadBuffer(TrainManager.Trains[k].Cars[i].Doors[0].CloseSound.Buffer); double a = TrainManager.Trains[k].Cars[i].Doors[0].CloseSound.Buffer.Duration; TrainManager.Trains[k].Cars[i].Specs.DoorCloseFrequency = a > 0.0 ? 1.0 / a : 0.8; } else if (TrainManager.Trains[k].Cars[i].Doors[1].CloseSound.Buffer != null) { Program.Sounds.LoadBuffer(TrainManager.Trains[k].Cars[i].Doors[0].CloseSound.Buffer); double b = TrainManager.Trains[k].Cars[i].Doors[1].CloseSound.Buffer.Duration; TrainManager.Trains[k].Cars[i].Specs.DoorCloseFrequency = b > 0.0 ? 1.0 / b : 0.8; } else { TrainManager.Trains[k].Cars[i].Specs.DoorCloseFrequency = 0.8; } } const double f = 0.015; const double g = 2.75; TrainManager.Trains[k].Cars[i].Specs.DoorOpenPitch = Math.Exp(f * Math.Tan(g * (Program.RandomNumberGenerator.NextDouble() - 0.5))); TrainManager.Trains[k].Cars[i].Specs.DoorClosePitch = Math.Exp(f * Math.Tan(g * (Program.RandomNumberGenerator.NextDouble() - 0.5))); TrainManager.Trains[k].Cars[i].Specs.DoorOpenFrequency /= TrainManager.Trains[k].Cars[i].Specs.DoorOpenPitch; TrainManager.Trains[k].Cars[i].Specs.DoorCloseFrequency /= TrainManager.Trains[k].Cars[i].Specs.DoorClosePitch; /* * Remove the following two lines, then the pitch at which doors play * takes their randomized opening and closing times into account. * */ TrainManager.Trains[k].Cars[i].Specs.DoorOpenPitch = 1.0; TrainManager.Trains[k].Cars[i].Specs.DoorClosePitch = 1.0; } } // add panel section if (TrainManager.Trains[k].IsPlayerTrain) { TrainProgressCurrentWeight = 0.7 / TrainProgressMaximum; TrainManager.ParsePanelConfig(TrainManager.Trains[k].TrainFolder, CurrentTrainEncoding, TrainManager.Trains[k]); TrainProgressCurrentSum += TrainProgressCurrentWeight; System.Threading.Thread.Sleep(1); if (Cancel) { return; } Program.FileSystem.AppendToLogFile("Train panel loaded sucessfully."); } // add exterior section if (TrainManager.Trains[k].State != TrainState.Bogus) { bool LoadObjects = false; if (CarObjects == null) { CarObjects = new UnifiedObject[TrainManager.Trains[k].Cars.Length]; BogieObjects = new UnifiedObject[TrainManager.Trains[k].Cars.Length * 2]; CouplerObjects = new UnifiedObject[TrainManager.Trains[k].Cars.Length]; LoadObjects = true; } string tXml = OpenBveApi.Path.CombineFile(TrainManager.Trains[k].TrainFolder, "train.xml"); if (System.IO.File.Exists(tXml)) { TrainXmlParser.Parse(tXml, TrainManager.Trains[k], ref CarObjects, ref BogieObjects, ref CouplerObjects); } else { ExtensionsCfgParser.ParseExtensionsConfig(TrainManager.Trains[k].TrainFolder, CurrentTrainEncoding, ref CarObjects, ref BogieObjects, ref CouplerObjects, TrainManager.Trains[k], LoadObjects); } World.CameraCar = TrainManager.Trains[k].DriverCar; System.Threading.Thread.Sleep(1); if (Cancel) { return; } //Stores the current array index of the bogie object to add //Required as there are two bogies per car, and we're using a simple linear array.... int currentBogieObject = 0; for (int i = 0; i < TrainManager.Trains[k].Cars.Length; i++) { if (CarObjects[i] == null) { // load default exterior object string file = OpenBveApi.Path.CombineFile(Program.FileSystem.GetDataFolder("Compatibility"), "exterior.csv"); StaticObject so = ObjectManager.LoadStaticObject(file, System.Text.Encoding.UTF8, false); if (so == null) { CarObjects[i] = null; } else { double sx = TrainManager.Trains[k].Cars[i].Width; double sy = TrainManager.Trains[k].Cars[i].Height; double sz = TrainManager.Trains[k].Cars[i].Length; so.ApplyScale(sx, sy, sz); CarObjects[i] = so; } } if (CarObjects[i] != null) { // add object TrainManager.Trains[k].Cars[i].LoadCarSections(CarObjects[i]); } if (CouplerObjects[i] != null) { TrainManager.Trains[k].Cars[i].Coupler.LoadCarSections(CouplerObjects[i]); } //Load bogie objects if (BogieObjects[currentBogieObject] != null) { TrainManager.Trains[k].Cars[i].FrontBogie.LoadCarSections(BogieObjects[currentBogieObject]); } currentBogieObject++; if (BogieObjects[currentBogieObject] != null) { TrainManager.Trains[k].Cars[i].RearBogie.LoadCarSections(BogieObjects[currentBogieObject]); } currentBogieObject++; } } // place cars TrainManager.Trains[k].PlaceCars(0.0); // configure ai / timetable if (TrainManager.Trains[k].IsPlayerTrain) { TrainManager.Trains[k].TimetableDelta = 0.0; } else if (TrainManager.Trains[k].State != TrainState.Bogus) { TrainManager.Trains[k].AI = new Game.SimpleHumanDriverAI(TrainManager.Trains[k]); TrainManager.Trains[k].TimetableDelta = Game.PrecedingTrainTimeDeltas[k]; TrainManager.Trains[k].Specs.DoorOpenMode = TrainManager.DoorMode.Manual; TrainManager.Trains[k].Specs.DoorCloseMode = TrainManager.DoorMode.Manual; } } /* * HACK: Store the TrainManager.Trains reference in the RouteManager also * Note that this may change when the TrainManager is separated from the lump * Remember not to modify via this ref */ // ReSharper disable once CoVariantArrayConversion Program.CurrentRoute.Trains = TrainManager.Trains; TrainProgress = 1.0; // finished created objects System.Threading.Thread.Sleep(1); if (Cancel) { return; } Array.Resize(ref ObjectManager.AnimatedWorldObjects, ObjectManager.AnimatedWorldObjectsUsed); // update sections if (Program.CurrentRoute.Sections.Length > 0) { Program.CurrentRoute.UpdateAllSections(); } // load plugin for (int i = 0; i < TrainManager.Trains.Length; i++) { if (TrainManager.Trains[i].State != TrainState.Bogus) { if (TrainManager.Trains[i].IsPlayerTrain) { if (!TrainManager.Trains[i].LoadCustomPlugin(TrainManager.Trains[i].TrainFolder, CurrentTrainEncoding)) { TrainManager.Trains[i].LoadDefaultPlugin(TrainManager.Trains[i].TrainFolder); } } else { TrainManager.Trains[i].LoadDefaultPlugin(TrainManager.Trains[i].TrainFolder); } } } }