/// <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 ObjectManager.UnifiedObject GetMirroredObject(ObjectManager.UnifiedObject Prototype) { if (Prototype is ObjectManager.StaticObject) { ObjectManager.StaticObject s = (ObjectManager.StaticObject)Prototype; return(GetMirroredStaticObject(s)); } else if (Prototype is ObjectManager.AnimatedObjectCollection) { ObjectManager.AnimatedObjectCollection a = (ObjectManager.AnimatedObjectCollection)Prototype; ObjectManager.AnimatedObjectCollection Result = new ObjectManager.AnimatedObjectCollection(); Result.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); } else { return(null); } }
private static void CreateTouchElement(TrainManager.ElementsGroup Group, Vector3 Position, Vector3 Size, int ScreenIndex, int SoundIndex, Translations.Command Command, int CommandOption) { Vertex t0 = new Vertex(Size.X, Size.Y, -Size.Z); Vertex t1 = new Vertex(Size.X, -Size.Y, -Size.Z); Vertex t2 = new Vertex(-Size.X, -Size.Y, -Size.Z); Vertex t3 = new Vertex(-Size.X, Size.Y, -Size.Z); Vertex t4 = new Vertex(Size.X, Size.Y, Size.Z); Vertex t5 = new Vertex(Size.X, -Size.Y, Size.Z); Vertex t6 = new Vertex(-Size.X, -Size.Y, Size.Z); Vertex t7 = new Vertex(-Size.X, Size.Y, Size.Z); ObjectManager.StaticObject Object = new ObjectManager.StaticObject(); Object.Mesh.Vertices = new VertexTemplate[] { t0, t1, t2, t3, t4, t5, t6, t7 }; Object.Mesh.Faces = new MeshFace[] { new MeshFace(new int[] { 0, 1, 2, 3 }), new MeshFace(new int[] { 0, 4, 5, 1 }), new MeshFace(new int[] { 0, 3, 7, 4 }), new MeshFace(new int[] { 6, 5, 4, 7 }), new MeshFace(new int[] { 6, 7, 3, 2 }), new MeshFace(new int[] { 6, 2, 1, 5 }) }; Object.Mesh.Materials = new MeshMaterial[1]; Object.Mesh.Materials[0].Flags = 0; Object.Mesh.Materials[0].Color = Color32.White; Object.Mesh.Materials[0].TransparentColor = Color24.Blue; Object.Mesh.Materials[0].DaytimeTexture = null; Object.Mesh.Materials[0].NighttimeTexture = null; Object.Dynamic = true; if (Group.TouchElements == null) { Group.TouchElements = new TrainManager.TouchElement[0]; } int n = Group.TouchElements.Length; Array.Resize(ref Group.TouchElements, n + 1); Group.TouchElements[n] = new TrainManager.TouchElement { Element = new ObjectManager.AnimatedObject(), JumpScreenIndex = ScreenIndex, SoundIndex = SoundIndex, Command = Command, CommandOption = CommandOption }; Group.TouchElements[n].Element.States = new ObjectManager.AnimatedObjectState[1]; Group.TouchElements[n].Element.States[0].Position = Position; Group.TouchElements[n].Element.States[0].Object = Object; Group.TouchElements[n].Element.CurrentState = 0; Group.TouchElements[n].Element.ObjectIndex = ObjectManager.CreateDynamicObject(); ObjectManager.Objects[Group.TouchElements[n].Element.ObjectIndex] = Object.Clone(); int m = Interface.CurrentControls.Length; Array.Resize(ref Interface.CurrentControls, m + 1); Interface.CurrentControls[m].Command = Command; Interface.CurrentControls[m].Method = Interface.ControlMethod.Touch; Interface.CurrentControls[m].Option = CommandOption; }
/// <summary>Creates a mirrored copy of the prototype object</summary> /// <param name="Prototype">The prototype</param> /// <returns>The mirrored copy</returns> private static ObjectManager.StaticObject GetMirroredStaticObject(ObjectManager.StaticObject Prototype) { ObjectManager.StaticObject Result = ObjectManager.CloneObject(Prototype); for (int i = 0; i < Result.Mesh.Vertices.Length; i++) { Result.Mesh.Vertices[i].Coordinates.X = -Result.Mesh.Vertices[i].Coordinates.X; } for (int i = 0; i < Result.Mesh.Faces.Length; i++) { for (int k = 0; k < Result.Mesh.Faces[i].Vertices.Length; k++) { Result.Mesh.Faces[i].Vertices[k].Normal.X = -Result.Mesh.Faces[i].Vertices[k].Normal.X; } Result.Mesh.Faces[i].Flip(); } return(Result); }
internal static void Parse(string fileName, TrainManager.Train Train, ref ObjectManager.UnifiedObject[] CarObjects, ref ObjectManager.UnifiedObject[] BogieObjects) { //The current XML file to load XmlDocument currentXML = new XmlDocument(); //Load the marker's XML file currentXML.Load(fileName); currentPath = System.IO.Path.GetDirectoryName(fileName); CarObjectsReversed = new bool[Train.Cars.Length]; BogieObjectsReversed = new bool[Train.Cars.Length * 2]; if (currentXML.DocumentElement != null) { XmlNodeList DocumentNodes = currentXML.DocumentElement.SelectNodes("/openBVE/Train/Car"); if (DocumentNodes == null || DocumentNodes.Count == 0) { Interface.AddMessage(Interface.MessageType.Error, false, "No car nodes defined in XML file " + fileName); //If we have no appropriate nodes specified, return false and fallback to loading the legacy Sound.cfg file throw new Exception("Empty train.xml file"); } //Use the index here for easy access to the car count for (int i = 0; i < DocumentNodes.Count; i++) { if (i > Train.Cars.Length) { Interface.AddMessage(Interface.MessageType.Warning, false, "WARNING: A total of " + DocumentNodes.Count + " cars were specified in XML file " + fileName + " whilst only " + Train.Cars.Length + " were specified in the train.dat file."); break; } if (DocumentNodes[i].ChildNodes.OfType <XmlElement>().Any()) { ParseCarNode(DocumentNodes[i], fileName, i, ref Train, ref CarObjects, ref BogieObjects); } else if (!String.IsNullOrEmpty(DocumentNodes[i].InnerText)) { try { string childFile = OpenBveApi.Path.CombineFile(currentPath, DocumentNodes[i].InnerText); XmlDocument childXML = new XmlDocument(); childXML.Load(childFile); XmlNodeList childNodes = childXML.DocumentElement.SelectNodes("/openBVE/Car"); //We need to save and restore the current path to make relative paths within the child file work correctly string savedPath = currentPath; currentPath = System.IO.Path.GetDirectoryName(childFile); ParseCarNode(childNodes[0], fileName, i, ref Train, ref CarObjects, ref BogieObjects); currentPath = savedPath; } catch { Interface.AddMessage(Interface.MessageType.Error, false, "Failed to load the child Car XML file specified in " + DocumentNodes[i].InnerText); } } if (i == DocumentNodes.Count && i < Train.Cars.Length) { //If this is the case, the number of motor cars is the primary thing which may get confused.... //Not a lot to be done about this until a full replacement is built for the train.dat file & we can dump it entirely Interface.AddMessage(Interface.MessageType.Warning, false, "WARNING: The number of cars specified in the train.xml file does not match that in the train.dat- Some properties may be invalid."); } } if (Train.Cars[Train.DriverCar].CameraRestrictionMode != Camera.RestrictionMode.NotSpecified) { World.CameraRestriction = Train.Cars[Train.DriverCar].CameraRestrictionMode; World.UpdateViewingDistances(); } DocumentNodes = currentXML.DocumentElement.SelectNodes("/openBVE/Train/NotchDescriptions"); if (DocumentNodes != null && DocumentNodes.Count > 0) { //Optional section for (int i = 0; i < DocumentNodes.Count; i++) { if (DocumentNodes[i].ChildNodes.OfType <XmlElement>().Any()) { foreach (XmlNode c in DocumentNodes[i].ChildNodes) { switch (c.Name.ToLowerInvariant()) { case "power": Train.PowerNotchDescriptions = c.InnerText.Split(';'); for (int j = 0; j < Train.PowerNotchDescriptions.Length; j++) { Size s = Renderer.MeasureString(Fonts.NormalFont, Train.PowerNotchDescriptions[j]); if (s.Width > Train.MaxPowerNotchWidth) { Train.MaxPowerNotchWidth = s.Width; } } break; case "brake": Train.BrakeNotchDescriptions = c.InnerText.Split(';'); for (int j = 0; j < Train.BrakeNotchDescriptions.Length; j++) { Size s = Renderer.MeasureString(Fonts.NormalFont, Train.BrakeNotchDescriptions[j]); if (s.Width > Train.MaxBrakeNotchWidth) { Train.MaxBrakeNotchWidth = s.Width; } } break; case "reverser": Train.ReverserDescriptions = c.InnerText.Split(';'); for (int j = 0; j < Train.ReverserDescriptions.Length; j++) { Size s = Renderer.MeasureString(Fonts.NormalFont, Train.ReverserDescriptions[j]); if (s.Width > Train.MaxReverserWidth) { Train.MaxReverserWidth = s.Width; } } break; } } } } } for (int i = 0; i < Train.Cars.Length; i++) { if (CarObjects[i] != null) { if (CarObjectsReversed[i]) { { // reverse axle positions double temp = Train.Cars[i].FrontAxle.Position; Train.Cars[i].FrontAxle.Position = -Train.Cars[i].RearAxle.Position; Train.Cars[i].RearAxle.Position = -temp; } if (CarObjects[i] is ObjectManager.StaticObject) { ObjectManager.StaticObject obj = (ObjectManager.StaticObject)CarObjects[i]; obj.ApplyScale(-1.0, 1.0, -1.0); } else if (CarObjects[i] is ObjectManager.AnimatedObjectCollection) { ObjectManager.AnimatedObjectCollection obj = (ObjectManager.AnimatedObjectCollection)CarObjects[i]; for (int j = 0; j < obj.Objects.Length; j++) { for (int h = 0; h < obj.Objects[j].States.Length; h++) { obj.Objects[j].States[h].Object.ApplyScale(-1.0, 1.0, -1.0); obj.Objects[j].States[h].Position.X *= -1.0; obj.Objects[j].States[h].Position.Z *= -1.0; } obj.Objects[j].TranslateXDirection.X *= -1.0; obj.Objects[j].TranslateXDirection.Z *= -1.0; obj.Objects[j].TranslateYDirection.X *= -1.0; obj.Objects[j].TranslateYDirection.Z *= -1.0; obj.Objects[j].TranslateZDirection.X *= -1.0; obj.Objects[j].TranslateZDirection.Z *= -1.0; } } else { throw new NotImplementedException(); } } } } //Check for bogie objects and reverse if necessary..... int bogieObjects = 0; for (int i = 0; i < Train.Cars.Length * 2; i++) { bool IsOdd = (i % 2 != 0); int CarIndex = i / 2; if (BogieObjects[i] != null) { bogieObjects++; if (BogieObjectsReversed[i]) { { // reverse axle positions if (IsOdd) { double temp = Train.Cars[CarIndex].FrontBogie.FrontAxle.Position; Train.Cars[CarIndex].FrontBogie.FrontAxle.Position = -Train.Cars[CarIndex].FrontBogie.RearAxle.Position; Train.Cars[CarIndex].FrontBogie.RearAxle.Position = -temp; } else { double temp = Train.Cars[CarIndex].RearBogie.FrontAxle.Position; Train.Cars[CarIndex].RearBogie.FrontAxle.Position = -Train.Cars[CarIndex].RearBogie.RearAxle.Position; Train.Cars[CarIndex].RearBogie.RearAxle.Position = -temp; } } if (BogieObjects[i] is ObjectManager.StaticObject) { ObjectManager.StaticObject obj = (ObjectManager.StaticObject)BogieObjects[i]; obj.ApplyScale(-1.0, 1.0, -1.0); } else if (BogieObjects[i] is ObjectManager.AnimatedObjectCollection) { ObjectManager.AnimatedObjectCollection obj = (ObjectManager.AnimatedObjectCollection)BogieObjects[i]; for (int j = 0; j < obj.Objects.Length; j++) { for (int h = 0; h < obj.Objects[j].States.Length; h++) { obj.Objects[j].States[h].Object.ApplyScale(-1.0, 1.0, -1.0); obj.Objects[j].States[h].Position.X *= -1.0; obj.Objects[j].States[h].Position.Z *= -1.0; } obj.Objects[j].TranslateXDirection.X *= -1.0; obj.Objects[j].TranslateXDirection.Z *= -1.0; obj.Objects[j].TranslateYDirection.X *= -1.0; obj.Objects[j].TranslateYDirection.Z *= -1.0; obj.Objects[j].TranslateZDirection.X *= -1.0; obj.Objects[j].TranslateZDirection.Z *= -1.0; } } else { throw new NotImplementedException(); } } } } } }
/// <summary>Creates a transformed copy of the prototype object</summary> /// <param name="Prototype">The prototype</param> /// <returns>Thetransformed copy</returns> private static ObjectManager.StaticObject GetTransformedStaticObject(ObjectManager.StaticObject Prototype, double NearDistance, double FarDistance) { ObjectManager.StaticObject Result = ObjectManager.CloneObject(Prototype); int n = 0; double x2 = 0.0, x3 = 0.0, x6 = 0.0, x7 = 0.0; for (int i = 0; i < Result.Mesh.Vertices.Length; i++) { if (n == 2) { x2 = Result.Mesh.Vertices[i].Coordinates.X; } else if (n == 3) { x3 = Result.Mesh.Vertices[i].Coordinates.X; } else if (n == 6) { x6 = Result.Mesh.Vertices[i].Coordinates.X; } else if (n == 7) { x7 = Result.Mesh.Vertices[i].Coordinates.X; } n++; if (n == 8) { break; } } if (n >= 4) { int m = 0; for (int i = 0; i < Result.Mesh.Vertices.Length; i++) { if (m == 0) { Result.Mesh.Vertices[i].Coordinates.X = NearDistance - x3; } else if (m == 1) { Result.Mesh.Vertices[i].Coordinates.X = FarDistance - x2; if (n < 8) { m = 8; break; } } else if (m == 4) { Result.Mesh.Vertices[i].Coordinates.X = NearDistance - x7; } else if (m == 5) { Result.Mesh.Vertices[i].Coordinates.X = NearDistance - x6; m = 8; break; } m++; if (m == 8) { break; } } } return(Result); }