private static StaticObject LoadTextualX(string Text) { Text = Text.Replace("\r\n", " ").Replace("\n", " ").Replace("\r", " ").Replace("\t", " ").Trim(new char[] { }); StaticObject obj = new StaticObject(Plugin.currentHost); MeshBuilder builder = new MeshBuilder(Plugin.currentHost); Material material = new Material(); Block block = new TextualBlock(Text); while (block.Position() < block.Length() - 5) { Block subBlock = block.ReadSubBlock(); ParseSubBlock(subBlock, ref obj, ref builder, ref material); } builder.Apply(ref obj); obj.Mesh.CreateNormals(); if (rootMatrix != Matrix4D.NoTransformation) { for (int i = 0; i < obj.Mesh.Vertices.Length; i++) { obj.Mesh.Vertices[i].Coordinates.Transform(rootMatrix); } } return(obj); }
public SimpleSkin(StaticObject staticObject, WGTFile weightFile) { List <uint> staticObjectIndices = staticObject.GetIndices(); List <StaticObjectVertex> staticObjectVertices = staticObject.GetVertices(); int currentVertexOffset = 0; foreach (StaticObjectSubmesh submesh in staticObject.Submeshes) { // Build vertices List <SimpleSkinVertex> vertices = new(staticObjectVertices.Count); for (int i = 0; i < submesh.Vertices.Count; i++) { StaticObjectVertex vertex = submesh.Vertices[i]; WGTWeight weightData = weightFile.Weights[i + currentVertexOffset]; vertices.Add(new SimpleSkinVertex(vertex.Position, weightData.BoneIndices, weightData.Weights, Vector3.Zero, vertex.UV)); } this.Submeshes.Add(new SimpleSkinSubmesh(submesh.Name, submesh.Indices.Select(x => (ushort)x).ToList(), vertices)); currentVertexOffset += submesh.Vertices.Count; } }
public EffectImage(int type) { hideCounter = 1000; if (type == 1) { image = new StaticObject(".\\Sprites\\GUI\\invencible"); } else if (type == 2) { image = new StaticObject(".\\Sprites\\GUI\\magnetic"); } if (type == 3) { image = new StaticObject(".\\Sprites\\GUI\\mushrain"); hideCounter = 200; } if (type == 4) { image = new StaticObject(".\\Sprites\\GUI\\stop"); } goaway = false; }
public static Entity Resolve(RealmManager manager, ushort id) { XElement node = manager.GameData.ObjectTypeToElement[id]; string type = node.Element("Class").Value; switch (type) { case "Projectile": throw new Exception("Projectile should not instantiated using Entity.Resolve"); case "Sign": return(new Sign(manager, id)); case "Wall": case "DoubleWall": return(new Wall(manager, id, node)); case "ConnectedWall": case "CaveWall": return(new ConnectedObject(manager, id)); case "GameObject": case "CharacterChanger": case "MoneyChanger": case "NameChanger": case "Stalagmite": return(new StaticObject(manager, id, StaticObject.GetHP(node), true, false, true)); case "MarketplaceGround": case "GuildRegister": case "GuildChronicle": case "GuildBoard": case "SpiderWeb": case "InteractNPC": return(new StaticObject(manager, id, null, false, false, false)); case "Container": return(new Container(manager, id)); case "Reforge": case "Forge": return(new Container(manager, id, true)); case "Player": throw new Exception("Player should not instantiated using Entity.Resolve"); case "Character": //Other characters means enemy return(new Enemy(manager, id)); case "Portal": return(new Portal(manager, id, null)); case "ClosedVaultChest": case "Merchant": return(new Merchants(manager, id)); case "GuildHallPortal": return(new StaticObject(manager, id, null, false, false, false)); case "GuildMerchant": return(new GuildMerchant(manager, id)); //case "InteractNPC": //return new InteractNPC(manager, id); default: log.WarnFormat("Not supported type: {0}", type); return(new Entity(manager, id)); } }
/** * Adiciona uma entidade na camada */ public void add(StaticObject entity) { objList.AddLast(entity); }
public static void ProductionInterface(StaticObject selectedFacility, string sFacilityType) { DeadButton = new GUIStyle(GUI.skin.button); DeadButton.normal.background = null; DeadButton.hover.background = null; DeadButton.active.background = null; DeadButton.focused.background = null; DeadButton.normal.textColor = Color.white; DeadButton.hover.textColor = Color.white; DeadButton.active.textColor = Color.white; DeadButton.focused.textColor = Color.white; DeadButton.fontSize = 14; DeadButton.fontStyle = FontStyle.Bold; DeadButtonRed = new GUIStyle(GUI.skin.button); DeadButtonRed.normal.background = null; DeadButtonRed.hover.background = null; DeadButtonRed.active.background = null; DeadButtonRed.focused.background = null; DeadButtonRed.normal.textColor = Color.red; DeadButtonRed.hover.textColor = Color.yellow; DeadButtonRed.active.textColor = Color.red; DeadButtonRed.focused.textColor = Color.red; DeadButtonRed.fontSize = 12; DeadButtonRed.fontStyle = FontStyle.Bold; BoxNoBorder = new GUIStyle(GUI.skin.box); BoxNoBorder.normal.background = null; BoxNoBorder.normal.textColor = Color.white; Yellowtext = new GUIStyle(GUI.skin.box); Yellowtext.normal.textColor = Color.yellow; Yellowtext.normal.background = null; LabelInfo = new GUIStyle(GUI.skin.label); LabelInfo.normal.background = null; LabelInfo.normal.textColor = Color.white; LabelInfo.fontSize = 13; LabelInfo.fontStyle = FontStyle.Bold; LabelInfo.padding.left = 3; LabelInfo.padding.top = 0; LabelInfo.padding.bottom = 0; ButtonSmallText = new GUIStyle(GUI.skin.button); ButtonSmallText.fontSize = 12; ButtonSmallText.fontStyle = FontStyle.Normal; float fStaffing = 0; float fProductionRate = 0; float fLastCheck = 0; fStaffing = (float)selectedFacility.getSetting("StaffCurrent"); fProductionRate = (float)selectedFacility.getSetting("ProductionRateCurrent") * (fStaffing / 2f); if (fProductionRate < 0.01f) { float fDefaultRate = 0.01f; if (sFacilityType == "Business") { fDefaultRate = 0.10f; } if (sFacilityType == "Mining") { fDefaultRate = 0.05f; } selectedFacility.setSetting("ProductionRateCurrent", fDefaultRate); PersistenceUtils.saveStaticPersistence(selectedFacility); fProductionRate = fDefaultRate * (fStaffing / 2f); } fLastCheck = (float)selectedFacility.getSetting("LastCheck"); if (fLastCheck == 0) { fLastCheck = (float)Planetarium.GetUniversalTime(); selectedFacility.setSetting("LastCheck", fLastCheck); PersistenceUtils.saveStaticPersistence(selectedFacility); } if (sFacilityType == "Research" || sFacilityType == "Business" || sFacilityType == "Mining") { string sProduces = ""; float fMax = 0f; float fCurrent = 0f; if (sFacilityType == "Research") { sProduces = "Science"; fMax = (float)selectedFacility.getSetting("ScienceOMax"); if (fMax < 1) { fMax = (float)selectedFacility.model.getSetting("DefaultScienceOMax"); if (fMax < 1) { fMax = 10f; } selectedFacility.setSetting("ScienceOMax", fMax); PersistenceUtils.saveStaticPersistence(selectedFacility); } fCurrent = (float)selectedFacility.getSetting("ScienceOCurrent"); } if (sFacilityType == "Business") { sProduces = "Funds"; fMax = (float)selectedFacility.getSetting("FundsOMax"); if (fMax < 1) { fMax = (float)selectedFacility.model.getSetting("DefaultFundsOMax"); if (fMax < 1) { fMax = 10000f; } selectedFacility.setSetting("FundsOMax", fMax); PersistenceUtils.saveStaticPersistence(selectedFacility); } fCurrent = (float)selectedFacility.getSetting("FundsOCurrent"); } if (sFacilityType == "Mining") { sProduces = "Ore"; fMax = (float)selectedFacility.model.getSetting("OreMax"); if (fMax < 1) { fMax = 500f; } fCurrent = (float)selectedFacility.getSetting("OreCurrent"); } double dTime = Planetarium.GetUniversalTime(); // Deal with revert exploits if (fLastCheck > (float)dTime) { selectedFacility.setSetting("LastCheck", (float)dTime); PersistenceUtils.saveStaticPersistence(selectedFacility); } if ((float)dTime - fLastCheck > 43200) { float fDays = (((float)dTime - fLastCheck) / 43200); float fProduced = fDays * fProductionRate; fCurrent = fCurrent + fProduced; if (fCurrent > fMax) { fCurrent = fMax; } if (sFacilityType == "Research") { selectedFacility.setSetting("ScienceOCurrent", fCurrent); } if (sFacilityType == "Business") { selectedFacility.setSetting("FundsOCurrent", fCurrent); } if (sFacilityType == "Mining") { selectedFacility.setSetting("OreCurrent", fCurrent); } selectedFacility.setSetting("LastCheck", (float)dTime); PersistenceUtils.saveStaticPersistence(selectedFacility); } GUILayout.BeginHorizontal(); GUILayout.Label("Produces: " + sProduces, LabelInfo); GUILayout.FlexibleSpace(); GUILayout.Label("Current: " + fCurrent.ToString("#0") + " | Max: " + fMax.ToString("#0"), LabelInfo); GUILayout.EndHorizontal(); //if (GUILayout.Button("Upgrade Max Capacity", ButtonSmallText, GUILayout.Height(20))) //{ } if (sFacilityType == "Research") { if (GUILayout.Button("Transfer Science to KSC R&D", ButtonSmallText, GUILayout.Height(20))) { ResearchAndDevelopment.Instance.AddScience(fCurrent, TransactionReasons.Cheating); selectedFacility.setSetting("ScienceOCurrent", 0f); PersistenceUtils.saveStaticPersistence(selectedFacility); } /* GUILayout.BeginHorizontal(); * { * if (GUILayout.Button("Assign a Special Project", ButtonSmallText, GUILayout.Height(20))) * { } * if (GUILayout.Button("Deliver Research Materials", ButtonSmallText, GUILayout.Height(20))) * { } * } * GUILayout.EndHorizontal(); * if (GUILayout.Button("Assign a Kerbonaut Scientist", ButtonSmallText, GUILayout.Height(20))) * { } */ } if (sFacilityType == "Business") { if (GUILayout.Button("Transfer Funds to KSC Account", ButtonSmallText, GUILayout.Height(20))) { Funding.Instance.AddFunds((double)fCurrent, TransactionReasons.Cheating); selectedFacility.setSetting("FundsOCurrent", 0f); PersistenceUtils.saveStaticPersistence(selectedFacility); } } /* if (sFacilityType == "Mining") * { * if (GUILayout.Button("Transfer Ore to/from Craft", ButtonSmallText, GUILayout.Height(20))) * { * if (bTransferOreToC) bTransferOreToC = false; * else bTransferOreToC = true; * } * * if (bTransferOreToC) * { * // Ore transfer to craft GUI * GUILayout.Label("Select Craft & Container", LabelInfo); * scrollOreTransfer = GUILayout.BeginScrollView(scrollOreTransfer); * GUILayout.Label("Select Craft & Container", LabelInfo); * GUILayout.Label("Select Craft & Container", LabelInfo); * GUILayout.Label("Select Craft & Container", LabelInfo); * GUILayout.EndScrollView(); * GUILayout.BeginHorizontal(); * if (GUILayout.Button("Into Craft", GUILayout.Height(23))) * { * * } * if (GUILayout.Button("Out of Craft", GUILayout.Height(23))) * { * * } * GUILayout.EndHorizontal(); * GUILayout.BeginHorizontal(); * GUILayout.Label("Amount: ", LabelInfo); * sOreTransferAmount = GUILayout.TextField(sOreTransferAmount, 7, GUILayout.Width(120)); * if (GUILayout.Button("Max", GUILayout.Height(23))) * { * * } * GUILayout.EndHorizontal(); * if (GUILayout.Button("Proceed", GUILayout.Height(23))) * { * * } * * GUILayout.FlexibleSpace(); * } * * if (GUILayout.Button("Transfer Ore to Facility", ButtonSmallText, GUILayout.Height(20))) * { * if (bTransferOreToF) bTransferOreToF = false; * else bTransferOreToF = true; * * } * * if (bTransferOreToF) * { * // Ore transfer to Facility GUI * GUILayout.Label("Select Destination Facility", LabelInfo); * scrollOreTransfer2 = GUILayout.BeginScrollView(scrollOreTransfer2); * GUILayout.Label("Select Destination Facility", LabelInfo); * GUILayout.Label("Select Destination Facility", LabelInfo); * GUILayout.Label("Select Destination Facility", LabelInfo); * GUILayout.EndScrollView(); * * GUILayout.BeginHorizontal(); * GUILayout.Label("Amount: ", LabelInfo); * sOreTransferAmount = GUILayout.TextField(sOreTransferAmount, 7, GUILayout.Width(120)); * if (GUILayout.Button("Max", GUILayout.Height(23))) * { * * } * GUILayout.EndHorizontal(); * GUILayout.BeginHorizontal(); * GUILayout.Label("Transfer Cost: X Funds"); * if (GUILayout.Button("Proceed", GUILayout.Height(23))) * { * * } * GUILayout.EndHorizontal(); * GUILayout.FlexibleSpace(); * } * * if (GUILayout.Button("Assign a Kerbonaut Engineer", ButtonSmallText, GUILayout.Height(20))) * { } * } */ GUILayout.Space(5); GUILayout.BeginHorizontal(); { GUILayout.Label("Production Rate: Up to " + fProductionRate.ToString("#0.00") + " per 12 hrs", LabelInfo); GUILayout.FlexibleSpace(); //if (GUILayout.Button(" Upgrade ", ButtonSmallText, GUILayout.Height(20))) //{ } } GUILayout.EndHorizontal(); GUILayout.Space(3); } }
// join objects internal static void JoinObjects(ref StaticObject Base, StaticObject Add) { if (Base == null & Add == null) { return; } else if (Base == null) { Base = CloneObject(Add); } else if (Add != null) { int mf = Base.Mesh.Faces.Length; int mm = Base.Mesh.Materials.Length; int mv = Base.Mesh.Vertices.Length; Array.Resize<World.MeshFace>(ref Base.Mesh.Faces, mf + Add.Mesh.Faces.Length); Array.Resize<World.MeshMaterial>(ref Base.Mesh.Materials, mm + Add.Mesh.Materials.Length); Array.Resize<World.Vertex>(ref Base.Mesh.Vertices, mv + Add.Mesh.Vertices.Length); for (int i = 0; i < Add.Mesh.Faces.Length; i++) { Base.Mesh.Faces[mf + i] = Add.Mesh.Faces[i]; for (int j = 0; j < Base.Mesh.Faces[mf + i].Vertices.Length; j++) { Base.Mesh.Faces[mf + i].Vertices[j].Index += (ushort)mv; } Base.Mesh.Faces[mf + i].Material += (ushort)mm; } for (int i = 0; i < Add.Mesh.Materials.Length; i++) { Base.Mesh.Materials[mm + i] = Add.Mesh.Materials[i]; } for (int i = 0; i < Add.Mesh.Vertices.Length; i++) { Base.Mesh.Vertices[mv + i] = Add.Mesh.Vertices[i]; } } }
internal static int CreateStaticObject(StaticObject Prototype, Vector3 Position, World.Transformation BaseTransformation, World.Transformation AuxTransformation, bool AccurateObjectDisposal, double AccurateObjectDisposalZOffset, double StartingDistance, double EndingDistance, double BlockLength, double TrackPosition, double Brightness, bool DuplicateMaterials) { int a = ObjectsUsed; if (a >= Objects.Length) { Array.Resize<StaticObject>(ref Objects, Objects.Length << 1); } ApplyStaticObjectData(ref Objects[a], Prototype, Position, BaseTransformation, AuxTransformation, AccurateObjectDisposal, AccurateObjectDisposalZOffset, StartingDistance, EndingDistance, BlockLength, TrackPosition, Brightness, DuplicateMaterials); for (int i = 0; i < Prototype.Mesh.Faces.Length; i++) { switch (Prototype.Mesh.Faces[i].Flags & World.MeshFace.FaceTypeMask) { case World.MeshFace.FaceTypeTriangles: Game.InfoTotalTriangles++; break; case World.MeshFace.FaceTypeTriangleStrip: Game.InfoTotalTriangleStrip++; break; case World.MeshFace.FaceTypeQuads: Game.InfoTotalQuads++; break; case World.MeshFace.FaceTypeQuadStrip: Game.InfoTotalQuadStrip++; break; case World.MeshFace.FaceTypePolygon: Game.InfoTotalPolygon++; break; } } ObjectsUsed++; return a; }
public static Entity Resolve(RealmManager manager, ushort id) { var node = manager.GameData.ObjectTypeToElement[id]; var cls = node.Element("Class"); if (cls == null) { throw new ArgumentException("Invalid XML Element, field class is missing"); } var type = cls.Value; switch (type) { case "Projectile": throw new Exception("Projectile should not instantiated using Entity.Resolve"); case "Sign": return(new Sign(manager, id)); case "Wall": case "DoubleWall": return(new Wall(manager, id, node)); case "ConnectedWall": case "CaveWall": return(new ConnectedObject(manager, id)); case "GameObject": case "CharacterChanger": case "MoneyChanger": case "NameChanger": return(new StaticObject(manager, id, StaticObject.GetHP(node), StaticObject.GetStatic(node), false, true)); case "GuildRegister": case "GuildChronicle": case "GuildBoard": return(new StaticObject(manager, id, null, false, false, false)); case "Container": return(new Container(manager, node)); case "Player": throw new Exception("Player should not instantiated using Entity.Resolve"); case "Character": //Other characters means enemy return(new Enemy(manager, id)); case "Portal": case "GuildHallPortal": return(new Portal(manager, id, null)); case "ClosedVaultChest": case "ClosedVaultChestGold": case "ClosedGiftChest": case "VaultChest": case "Merchant": return(new Merchants(manager, id)); case "GuildMerchant": return(new GuildMerchant(manager, id)); case "ArenaGuard": case "ArenaPortal": case "MysteryBoxGround": case "ReskinVendor": case "PetUpgrader": case "FortuneTeller": case "YardUpgrader": case "FortuneGround": case "QuestRewards": return(new StaticObject(manager, id, null, true, false, false)); case "Pet": throw new Exception("Pets should not instantiated using Entity.Resolve"); default: Log.Warn("Not supported type: " + type); return(new Entity(manager, id)); } }
public override bool LoadStaticObject(string path, System.Text.Encoding Encoding, bool PreserveVertices, out StaticObject Object) { if (base.LoadStaticObject(path, Encoding, PreserveVertices, 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 unifiedObject; if (Program.CurrentHost.Plugins[i].Object.LoadObject(path, Encoding, out unifiedObject)) { StaticObject staticObject = unifiedObject as StaticObject; if (staticObject != null) { staticObject.OptimizeObject(PreserveVertices, Interface.CurrentOptions.ObjectOptimizationBasicThreshold, Interface.CurrentOptions.ObjectOptimizationVertexCulling); Object = staticObject; StaticObjectCache.Add(ValueTuple.Create(path, PreserveVertices), Object); return(true); } Object = null; Interface.AddMessage(MessageType.Error, false, "Attempted to load " + path + " which is an animated object where only static objects are allowed."); } 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); }
private static void ParseSubBlock(Block block, ref StaticObject obj, ref MeshBuilder builder, ref Material material) { Block subBlock; switch (block.Token) { default: return; case TemplateID.Template: string GUID = block.ReadString(); /* * Valid Microsoft templates are listed here: * https://docs.microsoft.com/en-us/windows/desktop/direct3d9/dx9-graphics-reference-x-file-format-templates * However, an application may define it's own template (or by the looks of things override another) * by declaring this at the head of the file, and using a unique GUID * * Mesquoia does this by defining a copy of the Boolean template using a WORD as opposed to a DWORD * No practical effect in this case, however be wary of this.... */ return; case TemplateID.Header: int majorVersion = block.ReadUInt16(); int minorVersion = block.ReadUInt16(); int flags = block.ReadUInt16(); switch (flags) { /* According to http://paulbourke.net/dataformats/directx/#xfilefrm_Template_Header * it is possible for a file to contain a mix of both binary and textual blocks. * * The Header block controls the format of the file from this point onwards. * majorVersion and minorVersion relate to the legacy Direct3D retained mode API * and can probably be ignored. (Assume that features are cumulative and backwards compatible) * flags sets whether the blocks from this point onwards are binary or textual. * * TODO: Need a mixed mode file sample if we want this to work. * Probably exceedingly uncommon, so low priority */ case 0: if (block is TextualBlock) { throw new Exception("Mixed-mode text and binary objects are not supported by this parser."); } break; default: if (block is BinaryBlock) { throw new Exception("Mixed-mode text and binary objects are not supported by this parser."); } break; } return; case TemplateID.Frame: currentLevel++; if (builder.Vertices.Count != 0) { builder.Apply(ref obj); builder = new MeshBuilder(Plugin.currentHost); } while (block.Position() < block.Length() - 5) { /* * TODO: Whilst https://docs.microsoft.com/en-us/windows/desktop/direct3d9/frame suggests the Frame template should only contain * Mesh, FrameTransformMatrix or Frame templates by default, 3DS Max stuffs all manner of things into here * * It would be nice to get 3DS max stuff detected specifically, especially as we don't support most of this */ //TemplateID[] validTokens = { TemplateID.Mesh , TemplateID.FrameTransformMatrix, TemplateID.Frame }; subBlock = block.ReadSubBlock(); ParseSubBlock(subBlock, ref obj, ref builder, ref material); } currentLevel--; break; case TemplateID.FrameTransformMatrix: double[] matrixValues = new double[16]; for (int i = 0; i < 16; i++) { matrixValues[i] = block.ReadSingle(); } if (currentLevel > 1) { builder.TransformMatrix = new Matrix4D(matrixValues); } else { rootMatrix = new Matrix4D(matrixValues); } break; case TemplateID.Mesh: if (builder.Vertices.Count != 0) { builder.Apply(ref obj); builder = new MeshBuilder(Plugin.currentHost); } int nVerts = block.ReadUInt16(); if (nVerts == 0) { //Some null objects contain an empty mesh Plugin.currentHost.AddMessage(MessageType.Warning, false, "nVertices should be greater than zero in Mesh " + block.Label); } for (int i = 0; i < nVerts; i++) { builder.Vertices.Add(new Vertex(new Vector3(block.ReadSingle(), block.ReadSingle(), block.ReadSingle()))); } int nFaces = block.ReadUInt16(); if (nFaces == 0) { try { /* * A mesh has been defined with no faces. * If we are not at the end of the block, * attempt to read the next sub-block * * If this fails, the face count is probably incorrect * * NOTE: In this case, the face statement will be an empty string / whitespace * hence the block.ReadString() call */ block.ReadString(); if (block.Position() < block.Length() - 5) { subBlock = block.ReadSubBlock(); ParseSubBlock(subBlock, ref obj, ref builder, ref material); } goto NoFaces; } catch { throw new Exception("nFaces was declared as zero, but unrecognised data remains in the block"); } } for (int i = 0; i < nFaces; i++) { int fVerts = block.ReadUInt16(); if (nFaces == 0) { throw new Exception("fVerts must be greater than zero"); } MeshFace f = new MeshFace(); f.Vertices = new MeshFaceVertex[fVerts]; for (int j = 0; j < fVerts; j++) { f.Vertices[j].Index = block.ReadUInt16(); } builder.Faces.Add(f); } NoFaces: while (block.Position() < block.Length() - 5) { subBlock = block.ReadSubBlock(); ParseSubBlock(subBlock, ref obj, ref builder, ref material); } break; case TemplateID.MeshMaterialList: int nMaterials = block.ReadUInt16(); int nFaceIndices = block.ReadUInt16(); if (nFaceIndices == 1 && builder.Faces.Count > 1) { //Single material for all faces int globalMaterial = block.ReadUInt16(); for (int i = 0; i < builder.Faces.Count; i++) { MeshFace f = builder.Faces[i]; f.Material = (ushort)(globalMaterial + 1); builder.Faces[i] = f; } } else if (nFaceIndices == builder.Faces.Count) { for (int i = 0; i < nFaceIndices; i++) { int fMaterial = block.ReadUInt16(); MeshFace f = builder.Faces[i]; f.Material = (ushort)(fMaterial + 1); builder.Faces[i] = f; } } else { throw new Exception("nFaceIndices must match the number of faces in the mesh"); } for (int i = 0; i < nMaterials; i++) { subBlock = block.ReadSubBlock(TemplateID.Material); ParseSubBlock(subBlock, ref obj, ref builder, ref material); } break; case TemplateID.Material: int m = builder.Materials.Length; Array.Resize(ref builder.Materials, m + 1); builder.Materials[m] = new Material(); builder.Materials[m].Color = new Color32((byte)(255 * block.ReadSingle()), (byte)(255 * block.ReadSingle()), (byte)(255 * block.ReadSingle()), (byte)(255 * block.ReadSingle())); double mPower = block.ReadSingle(); //TODO: Unsure what this does... Color24 mSpecular = new Color24((byte)block.ReadSingle(), (byte)block.ReadSingle(), (byte)block.ReadSingle()); builder.Materials[m].EmissiveColor = new Color24((byte)(255 * block.ReadSingle()), (byte)(255 * block.ReadSingle()), (byte)(255 * block.ReadSingle())); builder.Materials[m].Flags |= MaterialFlags.Emissive; //TODO: Check exact behaviour if (Plugin.BlackTransparency) { builder.Materials[m].TransparentColor = Color24.Black; //TODO: Check, also can we optimise which faces have the transparent color set? builder.Materials[m].Flags |= MaterialFlags.TransparentColor; } if (block.Position() < block.Length() - 5) { subBlock = block.ReadSubBlock(TemplateID.TextureFilename); ParseSubBlock(subBlock, ref obj, ref builder, ref builder.Materials[m]); } break; case TemplateID.TextureFilename: try { material.DaytimeTexture = OpenBveApi.Path.CombineFile(currentFolder, block.ReadString()); } catch { //Empty / malformed texture argument material.DaytimeTexture = null; } if (!System.IO.File.Exists(material.DaytimeTexture) && material.DaytimeTexture != null) { Plugin.currentHost.AddMessage(MessageType.Error, true, "Texure " + material.DaytimeTexture + " was not found in file " + currentFile); material.DaytimeTexture = null; } break; case TemplateID.MeshTextureCoords: int nCoords = block.ReadUInt16(); for (int i = 0; i < nCoords; i++) { builder.Vertices[i].TextureCoordinates = new Vector2(block.ReadSingle(), block.ReadSingle()); } break; case TemplateID.MeshNormals: int nNormals = block.ReadUInt16(); Vector3[] normals = new Vector3[nNormals]; for (int i = 0; i < nNormals; i++) { normals[i] = new Vector3(block.ReadSingle(), block.ReadSingle(), block.ReadSingle()); normals[i].Normalize(); } int nFaceNormals = block.ReadUInt16(); if (nFaceNormals != builder.Faces.Count) { throw new Exception("nFaceNormals must match the number of faces in the mesh"); } for (int i = 0; i < nFaceNormals; i++) { int nVertexNormals = block.ReadUInt16(); if (nVertexNormals != builder.Faces[i].Vertices.Length) { throw new Exception("nVertexNormals must match the number of verticies in the face"); } for (int j = 0; j < nVertexNormals; j++) { builder.Faces[i].Vertices[j].Normal = normals[block.ReadUInt16()]; } } break; case TemplateID.MeshVertexColors: int nVertexColors = block.ReadUInt16(); for (int i = 0; i < nVertexColors; i++) { builder.Vertices[i] = new ColoredVertex((Vertex)builder.Vertices[i], new Color128(block.ReadSingle(), block.ReadSingle(), block.ReadSingle())); } break; case TemplateID.MeshFaceWraps: int nMeshFaceWraps = block.ReadUInt16(); if (nMeshFaceWraps != builder.Faces.Count) { throw new Exception("nMeshFaceWraps must match the number of faces in the mesh"); } /* * MeshFaceWraps is a 2 * boolean array, representing the clamping on X / Y axis for each face * The current engine only supports clamping on a per-texture basis & this was discontinued in * later versions of DirectX so just validate this is structurally valid and ignore for the minute */ break; } }
//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(); 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(new char[] { }); 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)) { UnifiedObject obj; switch (System.IO.Path.GetExtension(objectPath).ToLowerInvariant()) { case ".csv": case ".b3d": Program.CurrentHost.LoadObject(objectPath, encoding, out obj); Object = (StaticObject)obj; break; case ".x": Program.CurrentHost.LoadObject(objectPath, encoding, out obj); Object = (StaticObject)obj; 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(new[] { ',' }); 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(new[] { ',' }); 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(new char[] { }); } selectSingleNode = node.SelectSingleNode("copyright"); if (selectSingleNode != null) { //Attempt to load copyright information from XML Object.Copyright = selectSingleNode.InnerText.Trim(new char[] { }); } 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 void ApplyStaticObjectData(ref StaticObject Object, StaticObject Prototype, World.Vector3D Position, World.Transformation BaseTransformation, World.Transformation AuxTransformation, bool AccurateObjectDisposal, double AccurateObjectDisposalZOffset, double StartingDistance, double EndingDistance, double TrackPosition, double Brightness, bool DuplicateMaterials) { Object = new StaticObject(); Object.StartingDistance = float.MaxValue; Object.EndingDistance = float.MinValue; bool brightnesschange = Brightness != 1.0; // vertices Object.Mesh.Vertices = new World.Vertex[Prototype.Mesh.Vertices.Length]; for (int j = 0; j < Prototype.Mesh.Vertices.Length; j++) { Object.Mesh.Vertices[j] = Prototype.Mesh.Vertices[j]; if (AccurateObjectDisposal) { World.Rotate(ref Object.Mesh.Vertices[j].Coordinates.X, ref Object.Mesh.Vertices[j].Coordinates.Y, ref Object.Mesh.Vertices[j].Coordinates.Z, AuxTransformation); if (Object.Mesh.Vertices[j].Coordinates.Z < Object.StartingDistance) { Object.StartingDistance = (float)Object.Mesh.Vertices[j].Coordinates.Z; } if (Object.Mesh.Vertices[j].Coordinates.Z > Object.EndingDistance) { Object.EndingDistance = (float)Object.Mesh.Vertices[j].Coordinates.Z; } Object.Mesh.Vertices[j].Coordinates = Prototype.Mesh.Vertices[j].Coordinates; } World.Rotate(ref Object.Mesh.Vertices[j].Coordinates.X, ref Object.Mesh.Vertices[j].Coordinates.Y, ref Object.Mesh.Vertices[j].Coordinates.Z, AuxTransformation); World.Rotate(ref Object.Mesh.Vertices[j].Coordinates.X, ref Object.Mesh.Vertices[j].Coordinates.Y, ref Object.Mesh.Vertices[j].Coordinates.Z, BaseTransformation); Object.Mesh.Vertices[j].Coordinates.X += Position.X; Object.Mesh.Vertices[j].Coordinates.Y += Position.Y; Object.Mesh.Vertices[j].Coordinates.Z += Position.Z; } if (AccurateObjectDisposal) { Object.StartingDistance += (float)AccurateObjectDisposalZOffset; Object.EndingDistance += (float)AccurateObjectDisposalZOffset; } // faces Object.Mesh.Faces = new World.MeshFace[Prototype.Mesh.Faces.Length]; for (int j = 0; j < Prototype.Mesh.Faces.Length; j++) { Object.Mesh.Faces[j].Flags = Prototype.Mesh.Faces[j].Flags; Object.Mesh.Faces[j].Material = Prototype.Mesh.Faces[j].Material; Object.Mesh.Faces[j].Vertices = new World.MeshFaceVertex[Prototype.Mesh.Faces[j].Vertices.Length]; for (int k = 0; k < Prototype.Mesh.Faces[j].Vertices.Length; k++) { Object.Mesh.Faces[j].Vertices[k] = Prototype.Mesh.Faces[j].Vertices[k]; double nx = Object.Mesh.Faces[j].Vertices[k].Normal.X; double ny = Object.Mesh.Faces[j].Vertices[k].Normal.Y; double nz = Object.Mesh.Faces[j].Vertices[k].Normal.Z; if (nx * nx + ny * ny + nz * nz != 0.0) { World.Rotate(ref Object.Mesh.Faces[j].Vertices[k].Normal.X, ref Object.Mesh.Faces[j].Vertices[k].Normal.Y, ref Object.Mesh.Faces[j].Vertices[k].Normal.Z, AuxTransformation); World.Rotate(ref Object.Mesh.Faces[j].Vertices[k].Normal.X, ref Object.Mesh.Faces[j].Vertices[k].Normal.Y, ref Object.Mesh.Faces[j].Vertices[k].Normal.Z, BaseTransformation); } } } // materials Object.Mesh.Materials = new World.MeshMaterial[Prototype.Mesh.Materials.Length]; for (int j = 0; j < Prototype.Mesh.Materials.Length; j++) { Object.Mesh.Materials[j] = Prototype.Mesh.Materials[j]; Object.Mesh.Materials[j].Color.R = (byte)Math.Round((double)Prototype.Mesh.Materials[j].Color.R * Brightness); Object.Mesh.Materials[j].Color.G = (byte)Math.Round((double)Prototype.Mesh.Materials[j].Color.G * Brightness); Object.Mesh.Materials[j].Color.B = (byte)Math.Round((double)Prototype.Mesh.Materials[j].Color.B * Brightness); } if (AccurateObjectDisposal) { Object.StartingDistance += (float)TrackPosition; Object.EndingDistance += (float)TrackPosition; } else { Object.StartingDistance = (float)StartingDistance; Object.EndingDistance = (float)EndingDistance; } }
private void GenerateGravestone() { var maxed = 0; foreach (var i in XmlDatas.TypeToElement[ObjectType].Elements("LevelIncrease")) { var limit = int.Parse(XmlDatas.TypeToElement[ObjectType].Element(i.Value).Attribute("max").Value); var idx = StatsManager.StatsNameToIndex(i.Value); if (Stats[idx] >= limit) maxed++; } short objType; int? time; switch (maxed) { case 8: objType = 0x0735; time = null; /* if (player.objType = 782) //Wizard { objType = 0x0723; time = null; } else if (player.objType = 784) //Priest { objType = 0x0723; time = null; } else if (player.objType = 768) //Rogue { objType = 0x0723; time = null; } else if (player.objType = 801) //Necromancer { objType = 0x0723; time = null; } else if (player.objType = 798) //Knight { objType = 0x0723; time = null; } else if (player.objType = 800) //Assassin { objType = 0x0723; time = null; } else if (player.objType = 802) //Huntress { objType = 0x0723; time = null; } else if (player.objType = 804) //Trickster { objType = 0x0723; time = null; } else if (player.objType = 775) //Warrior { objType = 0x0723; time = null; } * else if (player.objType = 782) { objType = 0x0723; time = null; } else if (player.objType = 782) { objType = 0x0723; time = null; } else if (player.objType = 782) { objType = 0x0723; time = null; } else if (player.objType = 782) { objType = 0x0723; time = null; } else if (player.objType = 782) { objType = 0x0723; time = null; } */ break; case 7: objType = 0x0734; time = null; break; case 6: objType = 0x072b; time = null; break; case 5: objType = 0x072a; time = null; break; case 4: objType = 0x0729; time = null; break; case 3: objType = 0x0728; time = null; break; case 2: objType = 0x0727; time = null; break; case 1: objType = 0x0726; time = null; break; default: if (Level <= 1) { objType = 0x0723; time = 30*1000; } else if (Level < 20) { objType = 0x0724; time = 60*1000; } else { objType = 0x0725; time = 5*60*1000; } break; } var obj = new StaticObject(objType, time, true, time != null, false); obj.Move(X, Y); obj.Name = Name; Owner.EnterWorld(obj); }
private void GenerateGravestone() { var maxed = (from i in XmlData.TypeToElement[ObjectType].Elements("LevelIncrease") let limit = int.Parse(XmlData.TypeToElement[ObjectType].Element(i.Value).Attribute("max").Value) let idx = StatsManager.StatsNameToIndex(i.Value) where Stats[idx] >= limit select limit).Count(); short objType; int? time; switch (maxed) { case 8: objType = 0x0735; time = null; break; case 7: objType = 0x0734; time = null; break; case 6: objType = 0x072b; time = null; break; case 5: objType = 0x072a; time = null; break; case 4: objType = 0x0729; time = null; break; case 3: objType = 0x0728; time = null; break; case 2: objType = 0x0727; time = null; break; case 1: objType = 0x0726; time = null; break; default: if (Level <= 1) { objType = 0x0723; time = 30 * 1000; } else if (Level < 20) { objType = 0x0724; time = 60 * 1000; } else { objType = 0x0725; time = 5 * 60 * 1000; } break; } var obj = new StaticObject(objType, time, true, time != null, false); obj.Move(X, Y); obj.Name = Name; Owner.EnterWorld(obj); }
public static void HangarInterface(StaticObject selectedFacility) { DeadButton = new GUIStyle(GUI.skin.button); DeadButton.normal.background = null; DeadButton.hover.background = null; DeadButton.active.background = null; DeadButton.focused.background = null; DeadButton.normal.textColor = Color.white; DeadButton.hover.textColor = Color.white; DeadButton.active.textColor = Color.white; DeadButton.focused.textColor = Color.white; DeadButton.fontSize = 14; DeadButton.fontStyle = FontStyle.Bold; DeadButtonRed = new GUIStyle(GUI.skin.button); DeadButtonRed.normal.background = null; DeadButtonRed.hover.background = null; DeadButtonRed.active.background = null; DeadButtonRed.focused.background = null; DeadButtonRed.normal.textColor = Color.red; DeadButtonRed.hover.textColor = Color.yellow; DeadButtonRed.active.textColor = Color.red; DeadButtonRed.focused.textColor = Color.red; DeadButtonRed.fontSize = 12; DeadButtonRed.fontStyle = FontStyle.Bold; BoxNoBorder = new GUIStyle(GUI.skin.box); BoxNoBorder.normal.background = null; BoxNoBorder.normal.textColor = Color.white; Yellowtext = new GUIStyle(GUI.skin.box); Yellowtext.normal.textColor = Color.yellow; Yellowtext.normal.background = null; LabelInfo = new GUIStyle(GUI.skin.label); LabelInfo.normal.background = null; LabelInfo.normal.textColor = Color.white; LabelInfo.fontSize = 13; LabelInfo.fontStyle = FontStyle.Bold; LabelInfo.padding.left = 3; LabelInfo.padding.top = 0; LabelInfo.padding.bottom = 0; ButtonSmallText = new GUIStyle(GUI.skin.button); ButtonSmallText.fontSize = 12; ButtonSmallText.fontStyle = FontStyle.Normal; sInStorage = (string)selectedFacility.getSetting("InStorage"); sInStorage2 = (string)selectedFacility.getSetting("TargetID"); sInStorage3 = (string)selectedFacility.getSetting("TargetType"); float fMaxMass = (float)selectedFacility.model.getSetting("DefaultFacilityMassCapacity"); if (fMaxMass < 1) { fMaxMass = 25f; } float fMaxCrafts = (float)selectedFacility.model.getSetting("DefaultFacilityCraftCapacity"); if (fMaxCrafts < 1 || fMaxCrafts > 3) { fMaxCrafts = 2; } GUILayout.Space(2); GUILayout.Label("Where necessary craft are disassembled for storage or re-assembled before being rolled out. Please note that for game purposes, this procedure is instantaneous.", LabelInfo); GUILayout.BeginHorizontal(); GUILayout.Label("Max Craft: " + fMaxCrafts.ToString("#0"), LabelInfo); GUILayout.FlexibleSpace(); GUILayout.Label("Max Mass/Craft: " + fMaxMass.ToString("#0") + " T", LabelInfo); GUILayout.EndHorizontal(); if (sInStorage == null || sInStorage == "") { sInStorage = "None"; selectedFacility.setSetting("InStorage", "None"); PersistenceUtils.saveStaticPersistence(selectedFacility); } if (sInStorage2 == null || sInStorage2 == "") { sInStorage2 = "None"; selectedFacility.setSetting("TargetID", "None"); PersistenceUtils.saveStaticPersistence(selectedFacility); } if (sInStorage3 == null || sInStorage3 == "") { sInStorage3 = "None"; selectedFacility.setSetting("TargetType", "None"); PersistenceUtils.saveStaticPersistence(selectedFacility); } if (sInStorage == "None" && sInStorage2 == "None" && sInStorage3 == "None") { GUILayout.Label("No craft currently held in this facility.", LabelInfo); } else { int iNumberCrafts = NumberCraftHangared(selectedFacility); GUILayout.Box("Stored Craft (" + iNumberCrafts.ToString() + "/" + fMaxCrafts.ToString("#0") + ")", Yellowtext); List <Vessel> lVessels = FlightGlobals.Vessels; foreach (Vessel vVesselStored in lVessels) { if (vVesselStored.id.ToString() == sInStorage) { if (GUILayout.Button("" + vVesselStored.vesselName, ButtonSmallText, GUILayout.Height(20))) { // Empty the hangar if (HangarwayIsClear(selectedFacility)) { sInStorage = "None"; UnhangarCraft(vVesselStored, selectedFacility); sInStorage = "None"; } else { MiscUtils.HUDMessage("Cannot roll craft out. Clear the way first!", 10, 3); } } break; } } foreach (Vessel vVesselStored in lVessels) { if (vVesselStored.id.ToString() == sInStorage2) { if (GUILayout.Button("" + vVesselStored.vesselName, ButtonSmallText, GUILayout.Height(20))) { // Empty the hangar if (HangarwayIsClear(selectedFacility)) { sInStorage2 = "None"; UnhangarCraft(vVesselStored, selectedFacility); sInStorage2 = "None"; } else { MiscUtils.HUDMessage("Cannot roll craft out. Clear the way first!", 10, 3); } } break; } } foreach (Vessel vVesselStored in lVessels) { if (vVesselStored.id.ToString() == sInStorage3) { if (GUILayout.Button("" + vVesselStored.vesselName, ButtonSmallText, GUILayout.Height(20))) { // Empty the hangar if (HangarwayIsClear(selectedFacility)) { sInStorage3 = "None"; UnhangarCraft(vVesselStored, selectedFacility); sInStorage3 = "None"; } else { MiscUtils.HUDMessage("Cannot roll craft out. Clear the way first!", 10, 3); } } break; } } } GUILayout.Space(5); scrollNearbyCraft = GUILayout.BeginScrollView(scrollNearbyCraft); GUILayout.Box("Nearby Craft", Yellowtext); bool bNearbyCraft = false; foreach (Vessel vVessel in FlightGlobals.Vessels) { if (vVessel == null) { continue; } if (!vVessel.loaded) { continue; } if (vVessel.vesselType == VesselType.SpaceObject) { continue; } if (vVessel.vesselType == VesselType.Debris) { continue; } if (vVessel.vesselType == VesselType.EVA) { continue; } if (vVessel.vesselType == VesselType.Flag) { continue; } if (vVessel.vesselType == VesselType.Unknown) { continue; } if (vVessel == FlightGlobals.ActiveVessel) { continue; } if (vVessel.situation != Vessel.Situations.LANDED) { continue; } if (vVessel.GetCrewCount() > 0) { continue; } var vDistToCraft = Vector3.Distance(vVessel.gameObject.transform.position, selectedFacility.gameObject.transform.position); if (vDistToCraft > 250) { continue; } bNearbyCraft = true; if (GUILayout.Button(" " + vVessel.vesselName + " ", ButtonSmallText, GUILayout.Height(20))) { float fMass = vVessel.GetTotalMass(); if (fMass > fMaxMass) { MiscUtils.HUDMessage("Craft too heavy for this facility. Max " + fMaxMass.ToString("#0") + "T per craft.", 10, 3); } else { float fMaxCraft = (float)selectedFacility.model.getSetting("DefaultFacilityCraftCapacity"); if (fMaxCraft < 1 || fMaxCraft > 3) { fMaxCraft = 2; } int iNumberCraft = NumberCraftHangared(selectedFacility); if (iNumberCraft < (int)fMaxCraft) { HangarCraft(vVessel, selectedFacility, (int)fMaxCraft); } else { MiscUtils.HUDMessage("This facility is full. Max craft: " + fMaxCraft.ToString("#0"), 10, 3); } } } } if (!bNearbyCraft) { GUILayout.Label("There are no craft close enough to store in this facility.", LabelInfo); } GUILayout.EndScrollView(); GUILayout.FlexibleSpace(); }
/// <summary>Loads a static object</summary> /// <param name="Path">The absolute on-disk path to the object</param> /// <param name="Encoding">The detected text encoding</param> /// <param name="PreserveVertices">Whether optimization is to be performed on the object</param> /// <param name="Object">The handle to the object</param> /// <returns>Whether loading the object was successful</returns> /// <remarks>This will return false if an animated object is attempted to be loaded. /// Selecting to preserve vertices may be useful if using the object as a deformable.</remarks> public virtual bool LoadStaticObject(string Path, System.Text.Encoding Encoding, bool PreserveVertices, out StaticObject Object) { ValueTuple <string, bool> key = ValueTuple.Create(Path, PreserveVertices); if (StaticObjectCache.ContainsKey(key)) { Object = (StaticObject)StaticObjectCache[key].Clone(); return(true); } Object = null; return(false); }
/// <summary>Loads a Wavefront object from a file.</summary> /// <param name="FileName">The text file to load the animated object from. Must be an absolute file name.</param> /// <param name="Encoding">The encoding the file is saved in.</param> /// <returns>The object loaded.</returns> internal static StaticObject ReadObject(string FileName, System.Text.Encoding Encoding) { StaticObject Object = new StaticObject(Plugin.currentHost); MeshBuilder Builder = new MeshBuilder(); /* * Temporary arrays */ List <Vector3> tempVertices = new List <Vector3>(); List <Vector3> tempNormals = new List <Vector3>(); List <Vector2> tempCoords = new List <Vector2>(); Material[] TempMaterials = new Material[0]; //Stores the current material int currentMaterial = -1; //Read the contents of the file string[] Lines = File.ReadAllLines(FileName, Encoding); //Preprocess for (int i = 0; i < Lines.Length; i++) { // Strip hash comments int c = Lines[i].IndexOf("#", StringComparison.Ordinal); if (c >= 0) { Lines[i] = Lines[i].Substring(0, c); } // collect arguments List <string> Arguments = new List <string>(Lines[i].Split(new char[] { ' ', '\t' }, StringSplitOptions.None)); for (int j = Arguments.Count - 1; j >= 0; j--) { Arguments[j] = Arguments[j].Trim(new char[] { }); if (Arguments[j] == string.Empty) { Arguments.RemoveAt(j); } } if (Arguments.Count == 0) { continue; } switch (Arguments[0].ToLowerInvariant()) { case "v": //Vertex Vector3 vertex = new Vector3(); if (!double.TryParse(Arguments[1], out vertex.X)) { Plugin.currentHost.AddMessage(MessageType.Warning, false, "Invalid X co-ordinate in Vertex at Line " + i); } if (!double.TryParse(Arguments[2], out vertex.Y)) { Plugin.currentHost.AddMessage(MessageType.Warning, false, "Invalid Y co-ordinate in Vertex at Line " + i); } if (!double.TryParse(Arguments[3], out vertex.Z)) { Plugin.currentHost.AddMessage(MessageType.Warning, false, "Invalid Z co-ordinate in Vertex at Line " + i); } tempVertices.Add(vertex); break; case "vt": //Vertex texture co-ords Vector2 coords = new Vector2(); if (!double.TryParse(Arguments[1], out coords.X)) { Plugin.currentHost.AddMessage(MessageType.Warning, false, "Invalid X co-ordinate in Texture Co-ordinates at Line " + i); } if (!double.TryParse(Arguments[2], out coords.Y)) { Plugin.currentHost.AddMessage(MessageType.Warning, false, "Invalid X co-ordinate in Texture Co-Ordinates at Line " + i); } tempCoords.Add(coords); break; case "vn": Vector3 normal = new Vector3(); if (!double.TryParse(Arguments[1], out normal.X)) { Plugin.currentHost.AddMessage(MessageType.Warning, false, "Invalid X co-ordinate in Vertex Normal at Line " + i); } if (!double.TryParse(Arguments[2], out normal.Y)) { Plugin.currentHost.AddMessage(MessageType.Warning, false, "Invalid Y co-ordinate in Vertex Normal at Line " + i); } if (!double.TryParse(Arguments[3], out normal.Z)) { Plugin.currentHost.AddMessage(MessageType.Warning, false, "Invalid Z co-ordinate in Vertex Normal at Line " + i); } tempNormals.Add(normal); //Vertex normals break; case "vp": //Parameter space verticies, not supported throw new NotSupportedException("Parameter space verticies are not supported by this parser"); case "f": //Creates a new face //Create the temp list to hook out the vertices List <VertexTemplate> vertices = new List <VertexTemplate>(); List <Vector3> normals = new List <Vector3>(); for (int f = 1; f < Arguments.Count; f++) { Vertex newVertex = new Vertex(); string[] faceArguments = Arguments[f].Split(new char[] { '/' }, StringSplitOptions.None); int idx; if (!int.TryParse(faceArguments[0], out idx)) { Plugin.currentHost.AddMessage(MessageType.Warning, false, "Invalid Vertex index in Face " + f + " at Line " + i); continue; } int currentVertex = tempVertices.Count; if (idx != Math.Abs(idx)) { //Offset, so we seem to need to add one.... currentVertex++; currentVertex += idx; } else { currentVertex = idx; } if (currentVertex > tempVertices.Count) { Plugin.currentHost.AddMessage(MessageType.Warning, false, "Vertex index " + idx + " was greater than the available number of vertices in Face " + f + " at Line " + i); continue; } newVertex.Coordinates = tempVertices[currentVertex - 1]; if (faceArguments.Length <= 1) { normals.Add(new Vector3()); } else { if (!int.TryParse(faceArguments[1], out idx)) { if (!string.IsNullOrEmpty(faceArguments[1])) { Plugin.currentHost.AddMessage(MessageType.Warning, false, "Invalid Texture Co-ordinate index in Face " + f + " at Line " + i); } newVertex.TextureCoordinates = new Vector2(); } else { int currentCoord = tempCoords.Count; if (idx != Math.Abs(idx)) { //Offset, so we seem to need to add one.... currentCoord++; currentCoord += idx; } else { currentCoord = idx; } if (currentCoord > tempCoords.Count) { Plugin.currentHost.AddMessage(MessageType.Warning, false, "Texture Co-ordinate index " + currentCoord + " was greater than the available number of texture co-ordinates in Face " + f + " at Line " + i); } else { newVertex.TextureCoordinates = tempCoords[currentCoord - 1]; } } } if (faceArguments.Length <= 2) { normals.Add(new Vector3()); } else { if (!int.TryParse(faceArguments[2], out idx)) { if (!string.IsNullOrEmpty(faceArguments[2])) { Plugin.currentHost.AddMessage(MessageType.Warning, false, "Invalid Vertex Normal index in Face " + f + " at Line " + i); } normals.Add(new Vector3()); } else { int currentNormal = tempNormals.Count; if (idx != Math.Abs(idx)) { //Offset, so we seem to need to add one.... currentNormal++; currentNormal += idx; } else { currentNormal = idx; } if (currentNormal > tempNormals.Count) { Plugin.currentHost.AddMessage(MessageType.Warning, false, "Vertex Normal index " + currentNormal + " was greater than the available number of normals in Face " + f + " at Line " + i); normals.Add(new Vector3()); } else { normals.Add(tempNormals[currentNormal - 1]); } } } vertices.Add(newVertex); } MeshFaceVertex[] Vertices = new MeshFaceVertex[vertices.Count]; for (int k = 0; k < vertices.Count; k++) { Builder.Vertices.Add(vertices[k]); Vertices[k].Index = (ushort)(Builder.Vertices.Count - 1); Vertices[k].Normal = normals[k]; } Builder.Faces.Add(currentMaterial == -1 ? new MeshFace(Vertices, 0) : new MeshFace(Vertices, (ushort)currentMaterial)); break; case "g": //Starts a new face group and (normally) applies a new texture ApplyMeshBuilder(ref Object, Builder); Builder = new MeshBuilder(); break; case "s": /* * Changes the smoothing group applied to these vertexes: * 0- Disabled (Overriden by Vertex normals) * Otherwise appears to be a bitmask (32 available groups) * whereby faces within the same groups have their normals averaged * to appear smooth joins * * Not really supported at the minute, probably requires the engine * twiddling to deliberately support specifiying the shading type for a face * */ break; case "mtllib": //Loads the library of materials used by this file string MaterialsPath = OpenBveApi.Path.CombineFile(Path.GetDirectoryName(FileName), Arguments[1]); if (File.Exists(MaterialsPath)) { LoadMaterials(MaterialsPath, ref TempMaterials); } break; case "usemtl": for (int m = 0; m < TempMaterials.Length; m++) { if (TempMaterials[m].Key.ToLowerInvariant() == Arguments[1].ToLowerInvariant()) { bool mf = false; for (int k = 0; k < Builder.Materials.Length; k++) { if (Builder.Materials[k].Key != null && Builder.Materials[k].Key.ToLowerInvariant() == Arguments[1].ToLowerInvariant()) { mf = true; currentMaterial = k; break; } } if (!mf) { Array.Resize(ref Builder.Materials, Builder.Materials.Length + 1); Builder.Materials[Builder.Materials.Length - 1] = TempMaterials[m]; currentMaterial = Builder.Materials.Length - 1; } break; } if (m == TempMaterials.Length) { Plugin.currentHost.AddMessage(MessageType.Error, true, "Material " + Arguments[1] + " was not found."); currentMaterial = -1; } } break; default: Plugin.currentHost.AddMessage(MessageType.Warning, false, "Unrecognised command " + Arguments[0]); break; } } ApplyMeshBuilder(ref Object, Builder); Object.Mesh.CreateNormals(); return(Object); }
void InitVault() { var vaultChestPosition = new List <IntPoint>(); var giftChestPosition = new List <IntPoint>(); var spawn = new IntPoint(0, 0); var w = Map.Width; var h = Map.Height; for (var y = 0; y < h; y++) { for (var x = 0; x < w; x++) { var tile = Map[x, y]; switch (tile.Region) { case TileRegion.Spawn: spawn = new IntPoint(x, y); break; case TileRegion.Vault: vaultChestPosition.Add(new IntPoint(x, y)); break; case TileRegion.Gifting_Chest: giftChestPosition.Add(new IntPoint(x, y)); break; } } } vaultChestPosition.Sort((x, y) => Comparer <int> .Default.Compare( (x.X - spawn.X) * (x.X - spawn.X) + (x.Y - spawn.Y) * (x.Y - spawn.Y), (y.X - spawn.X) * (y.X - spawn.X) + (y.Y - spawn.Y) * (y.Y - spawn.Y))); giftChestPosition.Sort((x, y) => Comparer <int> .Default.Compare( (x.X - spawn.X) * (x.X - spawn.X) + (x.Y - spawn.Y) * (x.Y - spawn.Y), (y.X - spawn.X) * (y.X - spawn.X) + (y.Y - spawn.Y) * (y.Y - spawn.Y))); for (var i = 0; i < _client.Account.VaultCount && vaultChestPosition.Count > 0; i++) { var vaultChest = new DbVaultSingle(_client.Account, i); var con = new Container(_client.Manager, 0x0504, null, false, vaultChest); con.BagOwners = new int[] { _client.Account.AccountId }; con.Inventory.SetItems(vaultChest.Items); con.Inventory.InventoryChanged += (sender, e) => SaveChest(((Inventory)sender).Parent); con.Move(vaultChestPosition[0].X + 0.5f, vaultChestPosition[0].Y + 0.5f); EnterWorld(con); vaultChestPosition.RemoveAt(0); vaults.AddFirst(con); } foreach (var i in vaultChestPosition) { var x = new ClosedVaultChest(_client.Manager, 0x0505); x.Move(i.X + 0.5f, i.Y + 0.5f); EnterWorld(x); } var gifts = _client.Account.Gifts.ToList(); while (gifts.Count > 0 && giftChestPosition.Count > 0) { var c = Math.Min(8, gifts.Count); var items = gifts.GetRange(0, c); gifts.RemoveRange(0, c); if (c < 8) { items.AddRange(Enumerable.Repeat(ushort.MaxValue, 8 - c)); } var con = new GiftChest(_client.Manager, 0x0744, null, false); con.BagOwners = new int[] { _client.Account.AccountId }; con.Inventory.SetItems(items); con.Move(giftChestPosition[0].X + 0.5f, giftChestPosition[0].Y + 0.5f); EnterWorld(con); giftChestPosition.RemoveAt(0); } foreach (var i in giftChestPosition) { var x = new StaticObject(_client.Manager, 0x0743, null, true, false, false); x.Move(i.X + 0.5f, i.Y + 0.5f); EnterWorld(x); } // devon roach if (_client.Account.Name.Equals("Devon")) { var e = new Enemy(Manager, 0x12C); e.Move(38, 68); EnterWorld(e); } }
private static void ApplyMeshBuilder(ref StaticObject Object, MeshBuilder Builder) { if (Builder.Faces.Count != 0) { int mf = Object.Mesh.Faces.Length; int mm = Object.Mesh.Materials.Length; int mv = Object.Mesh.Vertices.Length; Array.Resize <MeshFace>(ref Object.Mesh.Faces, mf + Builder.Faces.Count); if (mm == 0) { if (Object.Mesh.Materials.Length == 0) { /* * If the object has no materials defined at all, we need to add one */ Array.Resize(ref Object.Mesh.Materials, 1); Object.Mesh.Materials[0] = new MeshMaterial(); Object.Mesh.Materials[0].Color = Color32.White; Object.Mesh.Materials[0].Flags = (byte)(0 | 0); Object.Mesh.Materials[0].DaytimeTexture = null; Object.Mesh.Materials[0].NighttimeTexture = null; mm++; } } if (Builder.Materials.Length > 0) { Array.Resize <MeshMaterial>(ref Object.Mesh.Materials, mm + Builder.Materials.Length); } else { /* * If no materials have been defined for this face group, use the last material */ mm -= 1; } Array.Resize <VertexTemplate>(ref Object.Mesh.Vertices, mv + Builder.Vertices.Count); for (int i = 0; i < Builder.Vertices.Count; i++) { Object.Mesh.Vertices[mv + i] = new Vertex((Vertex)Builder.Vertices[i]); } for (int i = 0; i < Builder.Faces.Count; i++) { Object.Mesh.Faces[mf + i] = Builder.Faces[i]; for (int j = 0; j < Object.Mesh.Faces[mf + i].Vertices.Length; j++) { Object.Mesh.Faces[mf + i].Vertices[j].Index += (ushort)mv; } Object.Mesh.Faces[mf + i].Material += (ushort)mm; } for (int i = 0; i < Builder.Materials.Length; i++) { Object.Mesh.Materials[mm + i].Flags = new MaterialFlags(); if (Builder.Materials[i].EmissiveColorUsed) { Object.Mesh.Materials[mm + i].Flags |= MaterialFlags.Emissive; } if (Builder.Materials[i].TransparentColorUsed) { Object.Mesh.Materials[mm + i].Flags |= MaterialFlags.TransparentColor; } Object.Mesh.Materials[mm + i].Color = Builder.Materials[i].Color; Object.Mesh.Materials[mm + i].TransparentColor = Builder.Materials[i].TransparentColor; if (Builder.Materials[i].DaytimeTexture != null) { Texture tday; if (Builder.Materials[i].TransparentColorUsed) { Plugin.currentHost.RegisterTexture(Builder.Materials[i].DaytimeTexture, new TextureParameters(null, new Color24(Builder.Materials[i].TransparentColor.R, Builder.Materials[i].TransparentColor.G, Builder.Materials[i].TransparentColor.B)), out tday); } else { Plugin.currentHost.RegisterTexture(Builder.Materials[i].DaytimeTexture, new TextureParameters(null, null), out tday); } Object.Mesh.Materials[mm + i].DaytimeTexture = tday; } else { Object.Mesh.Materials[mm + i].DaytimeTexture = null; } Object.Mesh.Materials[mm + i].EmissiveColor = Builder.Materials[i].EmissiveColor; if (Builder.Materials[i].NighttimeTexture != null) { Texture tnight; if (Builder.Materials[i].TransparentColorUsed) { Plugin.currentHost.RegisterTexture(Builder.Materials[i].NighttimeTexture, new TextureParameters(null, new Color24(Builder.Materials[i].TransparentColor.R, Builder.Materials[i].TransparentColor.G, Builder.Materials[i].TransparentColor.B)), out tnight); } else { Plugin.currentHost.RegisterTexture(Builder.Materials[i].NighttimeTexture, new TextureParameters(null, null), out tnight); } Object.Mesh.Materials[mm + i].NighttimeTexture = tnight; } else { Object.Mesh.Materials[mm + i].NighttimeTexture = null; } Object.Mesh.Materials[mm + i].DaytimeNighttimeBlend = 0; Object.Mesh.Materials[mm + i].BlendMode = Builder.Materials[i].BlendMode; Object.Mesh.Materials[mm + i].GlowAttenuationData = Builder.Materials[i].GlowAttenuationData; Object.Mesh.Materials[mm + i].WrapMode = OpenGlTextureWrapMode.RepeatRepeat; } } }
private void GenerateGravestone() { var maxed = (from i in Manager.GameData.ObjectTypeToElement[ObjectType].Elements("LevelIncrease") let xElement = Manager.GameData.ObjectTypeToElement[ObjectType].Element(i.Value) where xElement != null let limit = int.Parse(xElement.Attribute("max").Value) let idx = StatsManager.StatsNameToIndex(i.Value) where Stats[idx] >= limit select limit).Count(); ushort objType; int? time; switch (maxed) { case 8: objType = 0x0735; time = null; break; case 7: objType = 0x0734; time = null; break; case 6: objType = 0x072b; time = null; break; case 5: objType = 0x072a; time = null; break; case 4: objType = 0x0729; time = null; break; case 3: objType = 0x0728; time = null; break; case 2: objType = 0x0727; time = null; break; case 1: objType = 0x0726; time = null; break; default: if (Level <= 1) { objType = 0x0723; time = 30 * 1000; } else if (Level < 20) { objType = 0x0724; time = 60 * 1000; } else { objType = 0x0725; time = 5 * 60 * 1000; } break; } var obj = new StaticObject(Manager, objType, time, true, time != null, false); obj.Move(X, Y); obj.Name = Name; Owner.EnterWorld(obj); }
// parse extensions config internal static void ParseExtensionsConfig(string TrainPath, System.Text.Encoding Encoding, ref UnifiedObject[] CarObjects, ref UnifiedObject[] BogieObjects, ref UnifiedObject[] CouplerObjects, TrainManager.Train Train, bool LoadObjects) { bool[] CarObjectsReversed = new bool[Train.Cars.Length]; bool[] BogieObjectsReversed = new bool[Train.Cars.Length * 2]; bool[] CarsDefined = new bool[Train.Cars.Length]; bool[] BogiesDefined = new bool[Train.Cars.Length * 2]; System.Globalization.CultureInfo Culture = System.Globalization.CultureInfo.InvariantCulture; string FileName = OpenBveApi.Path.CombineFile(TrainPath, "extensions.cfg"); if (System.IO.File.Exists(FileName)) { Encoding = TextEncoding.GetSystemEncodingFromFile(FileName, Encoding); string[] Lines = System.IO.File.ReadAllLines(FileName, Encoding); for (int i = 0; i < Lines.Length; i++) { int j = Lines[i].IndexOf(';'); if (j >= 0) { Lines[i] = Lines[i].Substring(0, j).Trim(new char[] { }); } else { Lines[i] = Lines[i].Trim(new char[] { }); } } for (int i = 0; i < Lines.Length; i++) { if (Lines[i].Length != 0) { switch (Lines[i].ToLowerInvariant()) { case "[exterior]": // exterior i++; while (i < Lines.Length && !Lines[i].StartsWith("[", StringComparison.Ordinal) & !Lines[i].EndsWith("]", StringComparison.Ordinal)) { if (Lines[i].Length != 0) { int j = Lines[i].IndexOf("=", StringComparison.Ordinal); if (j >= 0) { string a = Lines[i].Substring(0, j).TrimEnd(new char[] { }); string b = Lines[i].Substring(j + 1).TrimStart(new char[] { }); int n; if (int.TryParse(a, System.Globalization.NumberStyles.Integer, Culture, out n)) { if (n >= 0 & n < Train.Cars.Length) { if (Path.ContainsInvalidChars(b)) { Interface.AddMessage(MessageType.Error, false, "File contains illegal characters at line " + (i + 1).ToString(Culture) + " in file " + FileName); } else { string File = OpenBveApi.Path.CombineFile(TrainPath, b); if (System.IO.File.Exists(File)) { if (LoadObjects) { Program.CurrentHost.LoadObject(File, Encoding, out CarObjects[n]); } } else { Interface.AddMessage(MessageType.Error, true, "The car object " + File + " does not exist at line " + (i + 1).ToString(Culture) + " in file " + FileName); } } } else { Interface.AddMessage(MessageType.Error, false, "The car index " + a + " does not reference an existing car at line " + (i + 1).ToString(Culture) + " in file " + FileName); } } else { Interface.AddMessage(MessageType.Error, false, "The car index is expected to be an integer at line " + (i + 1).ToString(Culture) + " in file " + FileName); } } else { Interface.AddMessage(MessageType.Error, false, "Invalid statement " + Lines[i] + " encountered at line " + (i + 1).ToString(Culture) + " in file " + FileName); } } i++; } i--; break; default: if (Lines[i].StartsWith("[car", StringComparison.OrdinalIgnoreCase) & Lines[i].EndsWith("]", StringComparison.Ordinal)) { // car string t = Lines[i].Substring(4, Lines[i].Length - 5); int n; if (int.TryParse(t, System.Globalization.NumberStyles.Integer, Culture, out n)) { if (n >= 0 & n < Train.Cars.Length) { if (CarsDefined[n]) { Interface.AddMessage(MessageType.Error, false, "Car " + n.ToString(Culture) + " has already been declared at line " + (i + 1).ToString(Culture) + " in file " + FileName); } CarsDefined[n] = true; bool DefinedLength = false; bool DefinedAxles = false; i++; while (i < Lines.Length && !Lines[i].StartsWith("[", StringComparison.Ordinal) & !Lines[i].EndsWith("]", StringComparison.Ordinal)) { if (Lines[i].Length != 0) { int j = Lines[i].IndexOf("=", StringComparison.Ordinal); if (j >= 0) { string a = Lines[i].Substring(0, j).TrimEnd(new char[] { }); string b = Lines[i].Substring(j + 1).TrimStart(new char[] { }); switch (a.ToLowerInvariant()) { case "object": if (string.IsNullOrEmpty(b)) { Interface.AddMessage(MessageType.Error, true, "An empty car object was supplied at line " + (i + 1).ToString(Culture) + " in file " + FileName); break; } if (Path.ContainsInvalidChars(b)) { Interface.AddMessage(MessageType.Error, false, "File contains illegal characters at line " + (i + 1).ToString(Culture) + " in file " + FileName); } else { string File = OpenBveApi.Path.CombineFile(TrainPath, b); if (System.IO.File.Exists(File)) { if (LoadObjects) { Program.CurrentHost.LoadObject(File, Encoding, out CarObjects[n]); } } else { Interface.AddMessage(MessageType.Error, true, "The car object " + File + " does not exist at line " + (i + 1).ToString(Culture) + " in file " + FileName); } } break; case "length": { double m; if (double.TryParse(b, System.Globalization.NumberStyles.Float, Culture, out m)) { if (m > 0.0) { Train.Cars[n].Length = m; Train.Cars[n].BeaconReceiverPosition = 0.5 * m; DefinedLength = true; } else { Interface.AddMessage(MessageType.Error, false, "Value is expected to be a positive floating-point number in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName); } } else { Interface.AddMessage(MessageType.Error, false, "Value is expected to be a positive floating-point number in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName); } } break; case "axles": { int k = b.IndexOf(','); if (k >= 0) { string c = b.Substring(0, k).TrimEnd(new char[] { }); string d = b.Substring(k + 1).TrimStart(new char[] { }); double rear, front; if (!double.TryParse(c, System.Globalization.NumberStyles.Float, Culture, out rear)) { Interface.AddMessage(MessageType.Error, false, "Rear is expected to be a floating-point number in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName); } else if (!double.TryParse(d, System.Globalization.NumberStyles.Float, Culture, out front)) { Interface.AddMessage(MessageType.Error, false, "Front is expected to be a floating-point number in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName); } else if (rear >= front) { Interface.AddMessage(MessageType.Error, false, "Rear is expected to be less than Front in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName); } else { Train.Cars[n].RearAxle.Position = rear; Train.Cars[n].FrontAxle.Position = front; DefinedAxles = true; } } else { Interface.AddMessage(MessageType.Error, false, "An argument-separating comma is expected in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName); } } break; case "reversed": CarObjectsReversed[n] = b.Equals("true", StringComparison.OrdinalIgnoreCase); break; case "loadingsway": Train.Cars[n].EnableLoadingSway = b.Equals("true", StringComparison.OrdinalIgnoreCase); break; default: Interface.AddMessage(MessageType.Warning, false, "Unsupported key-value pair " + a + " encountered at line " + (i + 1).ToString(Culture) + " in file " + FileName); break; } } else { Interface.AddMessage(MessageType.Error, false, "Invalid statement " + Lines[i] + " encountered at line " + (i + 1).ToString(Culture) + " in file " + FileName); } } i++; } i--; if (DefinedLength & !DefinedAxles) { double AxleDistance = 0.4 * Train.Cars[n].Length; Train.Cars[n].RearAxle.Position = -AxleDistance; Train.Cars[n].FrontAxle.Position = AxleDistance; } } else { Interface.AddMessage(MessageType.Error, false, "The car index " + t + " does not reference an existing car at line " + (i + 1).ToString(Culture) + " in file " + FileName); } } else { Interface.AddMessage(MessageType.Error, false, "The car index is expected to be an integer at line " + (i + 1).ToString(Culture) + " in file " + FileName); } } else if (Lines[i].StartsWith("[coupler", StringComparison.OrdinalIgnoreCase) & Lines[i].EndsWith("]", StringComparison.Ordinal)) { // coupler string t = Lines[i].Substring(8, Lines[i].Length - 9); int n; if (int.TryParse(t, System.Globalization.NumberStyles.Integer, Culture, out n)) { if (n >= 0 & n < Train.Cars.Length - 1) { i++; while (i < Lines.Length && !Lines[i].StartsWith("[", StringComparison.Ordinal) & !Lines[i].EndsWith("]", StringComparison.Ordinal)) { if (Lines[i].Length != 0) { int j = Lines[i].IndexOf("=", StringComparison.Ordinal); if (j >= 0) { string a = Lines[i].Substring(0, j).TrimEnd(new char[] { }); string b = Lines[i].Substring(j + 1).TrimStart(new char[] { }); switch (a.ToLowerInvariant()) { case "distances": { int k = b.IndexOf(','); if (k >= 0) { string c = b.Substring(0, k).TrimEnd(new char[] { }); string d = b.Substring(k + 1).TrimStart(new char[] { }); double min, max; if (!double.TryParse(c, System.Globalization.NumberStyles.Float, Culture, out min)) { Interface.AddMessage(MessageType.Error, false, "Minimum is expected to be a floating-point number in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName); } else if (!double.TryParse(d, System.Globalization.NumberStyles.Float, Culture, out max)) { Interface.AddMessage(MessageType.Error, false, "Maximum is expected to be a floating-point number in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName); } else if (min > max) { Interface.AddMessage(MessageType.Error, false, "Minimum is expected to be less than Maximum in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName); } else { Train.Cars[n].Coupler.MinimumDistanceBetweenCars = min; Train.Cars[n].Coupler.MaximumDistanceBetweenCars = max; } } else { Interface.AddMessage(MessageType.Error, false, "An argument-separating comma is expected in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName); } } break; case "object": if (string.IsNullOrEmpty(b)) { Interface.AddMessage(MessageType.Error, true, "An empty coupler object was supplied at line " + (i + 1).ToString(Culture) + " in file " + FileName); break; } if (Path.ContainsInvalidChars(b)) { Interface.AddMessage(MessageType.Error, false, "File contains illegal characters at line " + (i + 1).ToString(Culture) + " in file " + FileName); } else { string File = OpenBveApi.Path.CombineFile(TrainPath, b); if (System.IO.File.Exists(File)) { if (LoadObjects) { Program.CurrentHost.LoadObject(File, Encoding, out CouplerObjects[n]); } } else { Interface.AddMessage(MessageType.Error, true, "The coupler object " + File + " does not exist at line " + (i + 1).ToString(Culture) + " in file " + FileName); } } break; default: Interface.AddMessage(MessageType.Warning, false, "Unsupported key-value pair " + a + " encountered at line " + (i + 1).ToString(Culture) + " in file " + FileName); break; } } else { Interface.AddMessage(MessageType.Error, false, "Invalid statement " + Lines[i] + " encountered at line " + (i + 1).ToString(Culture) + " in file " + FileName); } } i++; } i--; } else { Interface.AddMessage(MessageType.Error, false, "The coupler index " + t + " does not reference an existing coupler at line " + (i + 1).ToString(Culture) + " in file " + FileName); } } else { Interface.AddMessage(MessageType.Error, false, "The coupler index is expected to be an integer at line " + (i + 1).ToString(Culture) + " in file " + FileName); } } else if (Lines[i].StartsWith("[bogie", StringComparison.OrdinalIgnoreCase) & Lines[i].EndsWith("]", StringComparison.Ordinal)) { // car string t = Lines[i].Substring(6, Lines[i].Length - 7); int n; if (int.TryParse(t, System.Globalization.NumberStyles.Integer, Culture, out n)) { if (n > BogiesDefined.Length - 1) { continue; } if (BogiesDefined[n]) { Interface.AddMessage(MessageType.Error, false, "Bogie " + n.ToString(Culture) + " has already been declared at line " + (i + 1).ToString(Culture) + " in file " + FileName); } BogiesDefined[n] = true; //Assuming that there are two bogies per car bool IsOdd = (n % 2 != 0); int CarIndex = n / 2; if (n >= 0 & n < Train.Cars.Length * 2) { bool DefinedAxles = false; i++; while (i < Lines.Length && !Lines[i].StartsWith("[", StringComparison.Ordinal) & !Lines[i].EndsWith("]", StringComparison.Ordinal)) { if (Lines[i].Length != 0) { int j = Lines[i].IndexOf("=", StringComparison.Ordinal); if (j >= 0) { string a = Lines[i].Substring(0, j).TrimEnd(new char[] { }); string b = Lines[i].Substring(j + 1).TrimStart(new char[] { }); switch (a.ToLowerInvariant()) { case "object": if (Path.ContainsInvalidChars(b)) { Interface.AddMessage(MessageType.Error, false, "File contains illegal characters at line " + (i + 1).ToString(Culture) + " in file " + FileName); } else { if (string.IsNullOrEmpty(b)) { Interface.AddMessage(MessageType.Error, true, "An empty bogie object was supplied at line " + (i + 1).ToString(Culture) + " in file " + FileName); break; } string File = OpenBveApi.Path.CombineFile(TrainPath, b); if (System.IO.File.Exists(File)) { if (LoadObjects) { Program.CurrentHost.LoadObject(File, Encoding, out BogieObjects[n]); } } else { Interface.AddMessage(MessageType.Error, true, "The bogie object " + File + " does not exist at line " + (i + 1).ToString(Culture) + " in file " + FileName); } } break; case "length": { Interface.AddMessage(MessageType.Error, false, "A defined length is not supported for bogies at line " + (i + 1).ToString(Culture) + " in file " + FileName); } break; case "axles": { int k = b.IndexOf(','); if (k >= 0) { string c = b.Substring(0, k).TrimEnd(new char[] { }); string d = b.Substring(k + 1).TrimStart(new char[] { }); double rear, front; if (!double.TryParse(c, System.Globalization.NumberStyles.Float, Culture, out rear)) { Interface.AddMessage(MessageType.Error, false, "Rear is expected to be a floating-point number in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName); } else if (!double.TryParse(d, System.Globalization.NumberStyles.Float, Culture, out front)) { Interface.AddMessage(MessageType.Error, false, "Front is expected to be a floating-point number in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName); } else if (rear >= front) { Interface.AddMessage(MessageType.Error, false, "Rear is expected to be less than Front in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName); } else { if (IsOdd) { Train.Cars[CarIndex].FrontBogie.RearAxle.Position = rear; Train.Cars[CarIndex].FrontBogie.FrontAxle.Position = front; } else { Train.Cars[CarIndex].RearBogie.RearAxle.Position = rear; Train.Cars[CarIndex].RearBogie.FrontAxle.Position = front; } DefinedAxles = true; } } else { Interface.AddMessage(MessageType.Error, false, "An argument-separating comma is expected in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName); } } break; case "reversed": BogieObjectsReversed[n] = b.Equals("true", StringComparison.OrdinalIgnoreCase); break; default: Interface.AddMessage(MessageType.Warning, false, "Unsupported key-value pair " + a + " encountered at line " + (i + 1).ToString(Culture) + " in file " + FileName); break; } } else { Interface.AddMessage(MessageType.Error, false, "Invalid statement " + Lines[i] + " encountered at line " + (i + 1).ToString(Culture) + " in file " + FileName); } } i++; } i--; if (!DefinedAxles) { if (IsOdd) { double AxleDistance = 0.4 * Train.Cars[CarIndex].FrontBogie.Length; Train.Cars[CarIndex].FrontBogie.RearAxle.Position = -AxleDistance; Train.Cars[CarIndex].FrontBogie.FrontAxle.Position = AxleDistance; } else { double AxleDistance = 0.4 * Train.Cars[CarIndex].RearBogie.Length; Train.Cars[CarIndex].RearBogie.RearAxle.Position = -AxleDistance; Train.Cars[CarIndex].RearBogie.FrontAxle.Position = AxleDistance; } } } else { Interface.AddMessage(MessageType.Error, false, "The car index " + t + " does not reference an existing car at line " + (i + 1).ToString(Culture) + " in file " + FileName); } } else { Interface.AddMessage(MessageType.Error, false, "The car index is expected to be an integer at line " + (i + 1).ToString(Culture) + " in file " + FileName); } } else { // default if (Lines.Length == 1 && Encoding.Equals(Encoding.Unicode)) { /* * If only one line, there's a good possibility that our file is NOT Unicode at all * and that the misdetection has turned it into garbage * * Try again with ASCII instead */ ParseExtensionsConfig(TrainPath, Encoding.GetEncoding(1252), ref CarObjects, ref BogieObjects, ref CouplerObjects, Train, LoadObjects); return; } Interface.AddMessage(MessageType.Error, false, "Invalid statement " + Lines[i] + " encountered at line " + (i + 1).ToString(Culture) + " in file " + FileName); } break; } } } // check for car objects and reverse if necessary int carObjects = 0; for (int i = 0; i < Train.Cars.Length; i++) { if (CarObjects[i] != null) { carObjects++; if (CarObjectsReversed[i] && LoadObjects) { { // 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 StaticObject) { StaticObject obj = (StaticObject)CarObjects[i]; obj.ApplyScale(-1.0, 1.0, -1.0); } else if (CarObjects[i] is AnimatedObjectCollection) { AnimatedObjectCollection obj = (AnimatedObjectCollection)CarObjects[i]; for (int j = 0; j < obj.Objects.Length; j++) { for (int h = 0; h < obj.Objects[j].States.Length; h++) { if (obj.Objects[j].States[h].Prototype == null) { continue; //object failed to load? } obj.Objects[j].States[h].Prototype.ApplyScale(-1.0, 1.0, -1.0); Matrix4D t = obj.Objects[j].States[h].Translation; t.Row3.X *= -1.0f; t.Row3.Z *= -1.0f; obj.Objects[j].States[h].Translation = t; } 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] && LoadObjects) { { // 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 StaticObject) { StaticObject obj = (StaticObject)BogieObjects[i]; obj.ApplyScale(-1.0, 1.0, -1.0); } else if (BogieObjects[i] is AnimatedObjectCollection) { AnimatedObjectCollection obj = (AnimatedObjectCollection)BogieObjects[i]; for (int j = 0; j < obj.Objects.Length; j++) { for (int h = 0; h < obj.Objects[j].States.Length; h++) { if (obj.Objects[j].States[h].Prototype == null) { continue; //object failed to load? } obj.Objects[j].States[h].Prototype.ApplyScale(-1.0, 1.0, -1.0); Matrix4D t = obj.Objects[j].States[h].Translation; t.Row3.X *= -1.0f; t.Row3.Z *= -1.0f; obj.Objects[j].States[h].Translation = t; } 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(); } } } } if (carObjects > 0 & carObjects < Train.Cars.Length) { Interface.AddMessage(MessageType.Warning, false, "An incomplete set of exterior objects was provided in file " + FileName); } if (bogieObjects > 0 & bogieObjects < Train.Cars.Length * 2) { Interface.AddMessage(MessageType.Warning, false, "An incomplete set of bogie objects was provided in file " + FileName); } } }
internal static void ApplyStaticObjectData(ref StaticObject Object, StaticObject Prototype, Vector3 Position, World.Transformation BaseTransformation, World.Transformation AuxTransformation, bool AccurateObjectDisposal, double AccurateObjectDisposalZOffset, double StartingDistance, double EndingDistance, double BlockLength, double TrackPosition, double Brightness, bool DuplicateMaterials) { Object = new StaticObject(); Object.StartingDistance = float.MaxValue; Object.EndingDistance = float.MinValue; bool brightnesschange = Brightness != 1.0; // vertices Object.Mesh.Vertices = new World.Vertex[Prototype.Mesh.Vertices.Length]; for (int j = 0; j < Prototype.Mesh.Vertices.Length; j++) { Object.Mesh.Vertices[j] = Prototype.Mesh.Vertices[j]; if (AccurateObjectDisposal) { World.Rotate(ref Object.Mesh.Vertices[j].Coordinates.X, ref Object.Mesh.Vertices[j].Coordinates.Y, ref Object.Mesh.Vertices[j].Coordinates.Z, AuxTransformation); if (Object.Mesh.Vertices[j].Coordinates.Z < Object.StartingDistance) { Object.StartingDistance = (float)Object.Mesh.Vertices[j].Coordinates.Z; } if (Object.Mesh.Vertices[j].Coordinates.Z > Object.EndingDistance) { Object.EndingDistance = (float)Object.Mesh.Vertices[j].Coordinates.Z; } Object.Mesh.Vertices[j].Coordinates = Prototype.Mesh.Vertices[j].Coordinates; } World.Rotate(ref Object.Mesh.Vertices[j].Coordinates.X, ref Object.Mesh.Vertices[j].Coordinates.Y, ref Object.Mesh.Vertices[j].Coordinates.Z, AuxTransformation); World.Rotate(ref Object.Mesh.Vertices[j].Coordinates.X, ref Object.Mesh.Vertices[j].Coordinates.Y, ref Object.Mesh.Vertices[j].Coordinates.Z, BaseTransformation); Object.Mesh.Vertices[j].Coordinates.X += Position.X; Object.Mesh.Vertices[j].Coordinates.Y += Position.Y; Object.Mesh.Vertices[j].Coordinates.Z += Position.Z; } if (AccurateObjectDisposal) { Object.StartingDistance += (float)AccurateObjectDisposalZOffset; Object.EndingDistance += (float)AccurateObjectDisposalZOffset; } // faces Object.Mesh.Faces = new World.MeshFace[Prototype.Mesh.Faces.Length]; for (int j = 0; j < Prototype.Mesh.Faces.Length; j++) { Object.Mesh.Faces[j].Flags = Prototype.Mesh.Faces[j].Flags; Object.Mesh.Faces[j].Material = Prototype.Mesh.Faces[j].Material; Object.Mesh.Faces[j].Vertices = new World.MeshFaceVertex[Prototype.Mesh.Faces[j].Vertices.Length]; for (int k = 0; k < Prototype.Mesh.Faces[j].Vertices.Length; k++) { Object.Mesh.Faces[j].Vertices[k] = Prototype.Mesh.Faces[j].Vertices[k]; double nx = Object.Mesh.Faces[j].Vertices[k].Normal.X; double ny = Object.Mesh.Faces[j].Vertices[k].Normal.Y; double nz = Object.Mesh.Faces[j].Vertices[k].Normal.Z; if (nx * nx + ny * ny + nz * nz != 0.0) { World.Rotate(ref Object.Mesh.Faces[j].Vertices[k].Normal.X, ref Object.Mesh.Faces[j].Vertices[k].Normal.Y, ref Object.Mesh.Faces[j].Vertices[k].Normal.Z, AuxTransformation); World.Rotate(ref Object.Mesh.Faces[j].Vertices[k].Normal.X, ref Object.Mesh.Faces[j].Vertices[k].Normal.Y, ref Object.Mesh.Faces[j].Vertices[k].Normal.Z, BaseTransformation); } } } // materials Object.Mesh.Materials = new World.MeshMaterial[Prototype.Mesh.Materials.Length]; for (int j = 0; j < Prototype.Mesh.Materials.Length; j++) { Object.Mesh.Materials[j] = Prototype.Mesh.Materials[j]; Object.Mesh.Materials[j].Color.R = (byte)Math.Round((double)Prototype.Mesh.Materials[j].Color.R * Brightness); Object.Mesh.Materials[j].Color.G = (byte)Math.Round((double)Prototype.Mesh.Materials[j].Color.G * Brightness); Object.Mesh.Materials[j].Color.B = (byte)Math.Round((double)Prototype.Mesh.Materials[j].Color.B * Brightness); } const double minBlockLength = 20.0; if (BlockLength < minBlockLength) { BlockLength = BlockLength * Math.Ceiling(minBlockLength / BlockLength); } if (AccurateObjectDisposal) { Object.StartingDistance += (float)TrackPosition; Object.EndingDistance += (float)TrackPosition; double z = BlockLength * Math.Floor(TrackPosition / BlockLength); StartingDistance = Math.Min(z - BlockLength, (double)Object.StartingDistance); EndingDistance = Math.Max(z + 2.0 * BlockLength, (double)Object.EndingDistance); Object.StartingDistance = (float)(BlockLength * Math.Floor(StartingDistance / BlockLength)); Object.EndingDistance = (float)(BlockLength * Math.Ceiling(EndingDistance / BlockLength)); } else { Object.StartingDistance = (float)StartingDistance; Object.EndingDistance = (float)EndingDistance; } if (BlockLength != 0.0) { checked { Object.GroupIndex = (short)Mod(Math.Floor(Object.StartingDistance / BlockLength), Math.Ceiling(Interface.CurrentOptions.ViewingDistance / BlockLength)); } } }
/* Projectile * Sign * Wall * ConnectedWall * MoneyChanger * CharacterChanger * Stalagmite * NameChanger * GuildRegister * GuildChronicle * GuildBoard * CaveWall * Player * Dye * ClosedVaultChest * ClosedVaultChestGold * Merchant * GuildHallPortal * SpiderWeb * GuildMerchant * Portal * Equipment * Container * GameObject * Character */ public static Entity Resolve(short id) { var tr = new Random(); var node = XmlDatas.TypeToElement[id]; var type = node.Element("Class").Value; switch (type) { case "Projectile": throw new Exception("Projectile should not instantiated using Entity.Resolve"); case "Sign": return(new Sign(id)); case "Wall": return(new Wall(id, node)); case "ConnectedWall": case "CaveWall": return(new ConnectedObject(id)); case "GameObject": case "CharacterChanger": case "MoneyChanger": case "NameChanger": case "Alchemy": return(new StaticObject(id, StaticObject.GetHP(node), true, false, true)); case "GuildRegister": case "GuildChronicle": case "GuildBoard": return(new StaticObject(id, null, false, false, false)); case "Container": return(new Container(node)); case "Player": throw new Exception("Player should not instantiated using Entity.Resolve"); case "Character": //Other characters means enemy return(new Enemy(id)); case "Portal": return(new Portal(id, null)); case "ClosedVaultChest": // Has to be empty! case "ClosedVaultChestGold": // Has to be empty! case "VaultChest": // Has to be empty! case "SlotsMachine": // Has to be empty! case "Merchant": return(new Merchants(id)); case "GuildMerchant": return(new GuildMerchant(id)); case "GuildHallPortal": return(new StaticObject(id, null, false, false, false)); default: Console.WriteLine("Not supported type: " + type); return(new Entity(id)); } }
internal static void OptimizeObject(StaticObject Prototype, bool PreserveVertices) { if (Prototype == null) return; int v = Prototype.Mesh.Vertices.Length; int m = Prototype.Mesh.Materials.Length; int f = Prototype.Mesh.Faces.Length; if (f >= Interface.CurrentOptions.ObjectOptimizationBasicThreshold) return; // eliminate invalid faces and reduce incomplete faces for (int i = 0; i < f; i++) { int type = Prototype.Mesh.Faces[i].Flags & World.MeshFace.FaceTypeMask; bool keep; if (type == World.MeshFace.FaceTypeTriangles) { keep = Prototype.Mesh.Faces[i].Vertices.Length >= 3; if (keep) { int n = (Prototype.Mesh.Faces[i].Vertices.Length / 3) * 3; if (Prototype.Mesh.Faces[i].Vertices.Length != n) { Array.Resize<World.MeshFaceVertex>(ref Prototype.Mesh.Faces[i].Vertices, n); } } } else if (type == World.MeshFace.FaceTypeQuads) { keep = Prototype.Mesh.Faces[i].Vertices.Length >= 4; if (keep) { int n = Prototype.Mesh.Faces[i].Vertices.Length & ~3; if (Prototype.Mesh.Faces[i].Vertices.Length != n) { Array.Resize<World.MeshFaceVertex>(ref Prototype.Mesh.Faces[i].Vertices, n); } } } else if (type == World.MeshFace.FaceTypeQuadStrip) { keep = Prototype.Mesh.Faces[i].Vertices.Length >= 4; if (keep) { int n = Prototype.Mesh.Faces[i].Vertices.Length & ~1; if (Prototype.Mesh.Faces[i].Vertices.Length != n) { Array.Resize<World.MeshFaceVertex>(ref Prototype.Mesh.Faces[i].Vertices, n); } } } else { keep = Prototype.Mesh.Faces[i].Vertices.Length >= 3; } if (!keep) { for (int j = i; j < f - 1; j++) { Prototype.Mesh.Faces[j] = Prototype.Mesh.Faces[j + 1]; } f--; i--; } } // eliminate unused vertices if (!PreserveVertices) { for (int i = 0; i < v; i++) { bool keep = false; for (int j = 0; j < f; j++) { for (int k = 0; k < Prototype.Mesh.Faces[j].Vertices.Length; k++) { if (Prototype.Mesh.Faces[j].Vertices[k].Index == i) { keep = true; break; } } if (keep) { break; } } if (!keep) { for (int j = 0; j < f; j++) { for (int k = 0; k < Prototype.Mesh.Faces[j].Vertices.Length; k++) { if (Prototype.Mesh.Faces[j].Vertices[k].Index > i) { Prototype.Mesh.Faces[j].Vertices[k].Index--; } } } for (int j = i; j < v - 1; j++) { Prototype.Mesh.Vertices[j] = Prototype.Mesh.Vertices[j + 1]; } v--; i--; } } } // eliminate duplicate vertices if (!PreserveVertices) { for (int i = 0; i < v - 1; i++) { for (int j = i + 1; j < v; j++) { if (Prototype.Mesh.Vertices[i] == Prototype.Mesh.Vertices[j]) { for (int k = 0; k < f; k++) { for (int h = 0; h < Prototype.Mesh.Faces[k].Vertices.Length; h++) { if (Prototype.Mesh.Faces[k].Vertices[h].Index == j) { Prototype.Mesh.Faces[k].Vertices[h].Index = (ushort)i; } else if (Prototype.Mesh.Faces[k].Vertices[h].Index > j) { Prototype.Mesh.Faces[k].Vertices[h].Index--; } } } for (int k = j; k < v - 1; k++) { Prototype.Mesh.Vertices[k] = Prototype.Mesh.Vertices[k + 1]; } v--; j--; } } } } // eliminate unused materials bool[] materialUsed = new bool[m]; for (int i = 0; i < f; i++) { materialUsed[Prototype.Mesh.Faces[i].Material] = true; } for (int i = 0; i < m; i++) { if (!materialUsed[i]) { for (int j = 0; j < f; j++) { if (Prototype.Mesh.Faces[j].Material > i) { Prototype.Mesh.Faces[j].Material--; } } for (int j = i; j < m - 1; j++) { Prototype.Mesh.Materials[j] = Prototype.Mesh.Materials[j + 1]; materialUsed[j] = materialUsed[j + 1]; } m--; i--; } } // eliminate duplicate materials for (int i = 0; i < m - 1; i++) { for (int j = i + 1; j < m; j++) { if (Prototype.Mesh.Materials[i] == Prototype.Mesh.Materials[j]) { for (int k = 0; k < f; k++) { if (Prototype.Mesh.Faces[k].Material == j) { Prototype.Mesh.Faces[k].Material = (ushort)i; } else if (Prototype.Mesh.Faces[k].Material > j) { Prototype.Mesh.Faces[k].Material--; } } for (int k = j; k < m - 1; k++) { Prototype.Mesh.Materials[k] = Prototype.Mesh.Materials[k + 1]; } m--; j--; } } } // structure optimization if (!PreserveVertices & f < Interface.CurrentOptions.ObjectOptimizationFullThreshold) { // create TRIANGLES and QUADS from POLYGON for (int i = 0; i < f; i++) { int type = Prototype.Mesh.Faces[i].Flags & World.MeshFace.FaceTypeMask; if (type == World.MeshFace.FaceTypePolygon) { if (Prototype.Mesh.Faces[i].Vertices.Length == 3) { unchecked { Prototype.Mesh.Faces[i].Flags &= (byte)~World.MeshFace.FaceTypeMask; Prototype.Mesh.Faces[i].Flags |= World.MeshFace.FaceTypeTriangles; } } else if (Prototype.Mesh.Faces[i].Vertices.Length == 4) { unchecked { Prototype.Mesh.Faces[i].Flags &= (byte)~World.MeshFace.FaceTypeMask; Prototype.Mesh.Faces[i].Flags |= World.MeshFace.FaceTypeQuads; } } } } // decomposit TRIANGLES and QUADS for (int i = 0; i < f; i++) { int type = Prototype.Mesh.Faces[i].Flags & World.MeshFace.FaceTypeMask; if (type == World.MeshFace.FaceTypeTriangles) { if (Prototype.Mesh.Faces[i].Vertices.Length > 3) { int n = (Prototype.Mesh.Faces[i].Vertices.Length - 3) / 3; while (f + n > Prototype.Mesh.Faces.Length) { Array.Resize<World.MeshFace>(ref Prototype.Mesh.Faces, Prototype.Mesh.Faces.Length << 1); } for (int j = 0; j < n; j++) { Prototype.Mesh.Faces[f + j].Vertices = new World.MeshFaceVertex[3]; for (int k = 0; k < 3; k++) { Prototype.Mesh.Faces[f + j].Vertices[k] = Prototype.Mesh.Faces[i].Vertices[3 + 3 * j + k]; } Prototype.Mesh.Faces[f + j].Material = Prototype.Mesh.Faces[i].Material; Prototype.Mesh.Faces[f + j].Flags = Prototype.Mesh.Faces[i].Flags; unchecked { Prototype.Mesh.Faces[i].Flags &= (byte)~World.MeshFace.FaceTypeMask; Prototype.Mesh.Faces[i].Flags |= World.MeshFace.FaceTypeTriangles; } } Array.Resize<World.MeshFaceVertex>(ref Prototype.Mesh.Faces[i].Vertices, 3); f += n; } } else if (type == World.MeshFace.FaceTypeQuads) { if (Prototype.Mesh.Faces[i].Vertices.Length > 4) { int n = (Prototype.Mesh.Faces[i].Vertices.Length - 4) >> 2; while (f + n > Prototype.Mesh.Faces.Length) { Array.Resize<World.MeshFace>(ref Prototype.Mesh.Faces, Prototype.Mesh.Faces.Length << 1); } for (int j = 0; j < n; j++) { Prototype.Mesh.Faces[f + j].Vertices = new World.MeshFaceVertex[4]; for (int k = 0; k < 4; k++) { Prototype.Mesh.Faces[f + j].Vertices[k] = Prototype.Mesh.Faces[i].Vertices[4 + 4 * j + k]; } Prototype.Mesh.Faces[f + j].Material = Prototype.Mesh.Faces[i].Material; Prototype.Mesh.Faces[f + j].Flags = Prototype.Mesh.Faces[i].Flags; unchecked { Prototype.Mesh.Faces[i].Flags &= (byte)~World.MeshFace.FaceTypeMask; Prototype.Mesh.Faces[i].Flags |= World.MeshFace.FaceTypeQuads; } } Array.Resize<World.MeshFaceVertex>(ref Prototype.Mesh.Faces[i].Vertices, 4); f += n; } } } // optimize for TRIANGLE_STRIP int index = -1; while (true) { // add TRIANGLES to TRIANGLE_STRIP for (int i = 0; i < f; i++) { if (index == i | index == -1) { int type = Prototype.Mesh.Faces[i].Flags & World.MeshFace.FaceTypeMask; if (type == World.MeshFace.FaceTypeTriangleStrip) { int face = Prototype.Mesh.Faces[i].Flags & World.MeshFace.Face2Mask; for (int j = 0; j < f; j++) { int type2 = Prototype.Mesh.Faces[j].Flags & World.MeshFace.FaceTypeMask; int face2 = Prototype.Mesh.Faces[j].Flags & World.MeshFace.Face2Mask; if (type2 == World.MeshFace.FaceTypeTriangles & face == face2) { if (Prototype.Mesh.Faces[i].Material == Prototype.Mesh.Faces[j].Material) { bool keep = true; for (int k = 0; k < 3; k++) { int l = (k + 1) % 3; int n = Prototype.Mesh.Faces[i].Vertices.Length; if (Prototype.Mesh.Faces[i].Vertices[0] == Prototype.Mesh.Faces[j].Vertices[k] & Prototype.Mesh.Faces[i].Vertices[1] == Prototype.Mesh.Faces[j].Vertices[l]) { Array.Resize<World.MeshFaceVertex>(ref Prototype.Mesh.Faces[i].Vertices, n + 1); for (int h = n; h >= 1; h--) { Prototype.Mesh.Faces[i].Vertices[h] = Prototype.Mesh.Faces[i].Vertices[h - 1]; } Prototype.Mesh.Faces[i].Vertices[0] = Prototype.Mesh.Faces[j].Vertices[(k + 2) % 3]; keep = false; } else if (Prototype.Mesh.Faces[i].Vertices[n - 1] == Prototype.Mesh.Faces[j].Vertices[l] & Prototype.Mesh.Faces[i].Vertices[n - 2] == Prototype.Mesh.Faces[j].Vertices[k]) { Array.Resize<World.MeshFaceVertex>(ref Prototype.Mesh.Faces[i].Vertices, n + 1); Prototype.Mesh.Faces[i].Vertices[n] = Prototype.Mesh.Faces[j].Vertices[(k + 2) % 3]; keep = false; } if (!keep) { break; } } if (!keep) { for (int k = j; k < f - 1; k++) { Prototype.Mesh.Faces[k] = Prototype.Mesh.Faces[k + 1]; } if (j < i) { i--; } f--; j--; } } } } } } } // join TRIANGLES into new TRIANGLE_STRIP index = -1; for (int i = 0; i < f - 1; i++) { int type = Prototype.Mesh.Faces[i].Flags & World.MeshFace.FaceTypeMask; if (type == World.MeshFace.FaceTypeTriangles) { int face = Prototype.Mesh.Faces[i].Flags & World.MeshFace.Face2Mask; for (int j = i + 1; j < f; j++) { int type2 = Prototype.Mesh.Faces[j].Flags & World.MeshFace.FaceTypeMask; int face2 = Prototype.Mesh.Faces[j].Flags & World.MeshFace.Face2Mask; if (type2 == World.MeshFace.FaceTypeTriangles & face == face2) { if (Prototype.Mesh.Faces[i].Material == Prototype.Mesh.Faces[j].Material) { for (int ik = 0; ik < 3; ik++) { int il = (ik + 1) % 3; for (int jk = 0; jk < 3; jk++) { int jl = (jk + 1) % 3; if (Prototype.Mesh.Faces[i].Vertices[ik] == Prototype.Mesh.Faces[j].Vertices[jl] & Prototype.Mesh.Faces[i].Vertices[il] == Prototype.Mesh.Faces[j].Vertices[jk]) { unchecked { Prototype.Mesh.Faces[i].Flags &= (byte)~World.MeshFace.FaceTypeMask; Prototype.Mesh.Faces[i].Flags |= World.MeshFace.FaceTypeTriangleStrip; } Prototype.Mesh.Faces[i].Vertices = new World.MeshFaceVertex[] { Prototype.Mesh.Faces[i].Vertices[(ik + 2) % 3], Prototype.Mesh.Faces[i].Vertices[ik], Prototype.Mesh.Faces[i].Vertices[il], Prototype.Mesh.Faces[j].Vertices[(jk + 2) % 3] }; for (int k = j; k < f - 1; k++) { Prototype.Mesh.Faces[k] = Prototype.Mesh.Faces[k + 1]; } f--; index = i; break; } } if (index >= 0) break; } } } if (index >= 0) break; } } } if (index == -1) break; } // optimize for QUAD_STRIP index = -1; while (true) { // add QUADS to QUAD_STRIP for (int i = 0; i < f; i++) { if (index == i | index == -1) { int type = Prototype.Mesh.Faces[i].Flags & World.MeshFace.FaceTypeMask; if (type == World.MeshFace.FaceTypeQuadStrip) { int face = Prototype.Mesh.Faces[i].Flags & World.MeshFace.Face2Mask; for (int j = 0; j < f; j++) { int type2 = Prototype.Mesh.Faces[j].Flags & World.MeshFace.FaceTypeMask; int face2 = Prototype.Mesh.Faces[j].Flags & World.MeshFace.Face2Mask; if (type2 == World.MeshFace.FaceTypeQuads & face == face2) { if (Prototype.Mesh.Faces[i].Material == Prototype.Mesh.Faces[j].Material) { bool keep = true; for (int k = 0; k < 4; k++) { int l = (k + 1) & 3; int n = Prototype.Mesh.Faces[i].Vertices.Length; if (Prototype.Mesh.Faces[i].Vertices[0] == Prototype.Mesh.Faces[j].Vertices[l] & Prototype.Mesh.Faces[i].Vertices[1] == Prototype.Mesh.Faces[j].Vertices[k]) { Array.Resize<World.MeshFaceVertex>(ref Prototype.Mesh.Faces[i].Vertices, n + 2); for (int h = n + 1; h >= 2; h--) { Prototype.Mesh.Faces[i].Vertices[h] = Prototype.Mesh.Faces[i].Vertices[h - 2]; } Prototype.Mesh.Faces[i].Vertices[0] = Prototype.Mesh.Faces[j].Vertices[(k + 2) & 3]; Prototype.Mesh.Faces[i].Vertices[1] = Prototype.Mesh.Faces[j].Vertices[(k + 3) & 3]; keep = false; } else if (Prototype.Mesh.Faces[i].Vertices[n - 1] == Prototype.Mesh.Faces[j].Vertices[l] & Prototype.Mesh.Faces[i].Vertices[n - 2] == Prototype.Mesh.Faces[j].Vertices[k]) { Array.Resize<World.MeshFaceVertex>(ref Prototype.Mesh.Faces[i].Vertices, n + 2); Prototype.Mesh.Faces[i].Vertices[n] = Prototype.Mesh.Faces[j].Vertices[(k + 3) & 3]; Prototype.Mesh.Faces[i].Vertices[n + 1] = Prototype.Mesh.Faces[j].Vertices[(k + 2) & 3]; keep = false; } if (!keep) { break; } } if (!keep) { for (int k = j; k < f - 1; k++) { Prototype.Mesh.Faces[k] = Prototype.Mesh.Faces[k + 1]; } if (j < i) { i--; } f--; j--; } } } } } } } // join QUADS into new QUAD_STRIP index = -1; for (int i = 0; i < f - 1; i++) { int type = Prototype.Mesh.Faces[i].Flags & World.MeshFace.FaceTypeMask; if (type == World.MeshFace.FaceTypeQuads) { int face = Prototype.Mesh.Faces[i].Flags & World.MeshFace.Face2Mask; for (int j = i + 1; j < f; j++) { int type2 = Prototype.Mesh.Faces[j].Flags & World.MeshFace.FaceTypeMask; int face2 = Prototype.Mesh.Faces[j].Flags & World.MeshFace.Face2Mask; if (type2 == World.MeshFace.FaceTypeQuads & face == face2) { if (Prototype.Mesh.Faces[i].Material == Prototype.Mesh.Faces[j].Material) { for (int ik = 0; ik < 4; ik++) { int il = (ik + 1) & 3; for (int jk = 0; jk < 4; jk++) { int jl = (jk + 1) & 3; if (Prototype.Mesh.Faces[i].Vertices[ik] == Prototype.Mesh.Faces[j].Vertices[jl] & Prototype.Mesh.Faces[i].Vertices[il] == Prototype.Mesh.Faces[j].Vertices[jk]) { unchecked { Prototype.Mesh.Faces[i].Flags &= (byte)~World.MeshFace.FaceTypeMask; Prototype.Mesh.Faces[i].Flags |= World.MeshFace.FaceTypeQuadStrip; } Prototype.Mesh.Faces[i].Vertices = new World.MeshFaceVertex[] { Prototype.Mesh.Faces[i].Vertices[(ik + 2) & 3], Prototype.Mesh.Faces[i].Vertices[(ik + 3) & 3], Prototype.Mesh.Faces[i].Vertices[il], Prototype.Mesh.Faces[i].Vertices[ik], Prototype.Mesh.Faces[j].Vertices[(jk + 3) & 3], Prototype.Mesh.Faces[j].Vertices[(jk + 2) & 3] }; for (int k = j; k < f - 1; k++) { Prototype.Mesh.Faces[k] = Prototype.Mesh.Faces[k + 1]; } f--; index = i; break; } } if (index >= 0) break; } } } if (index >= 0) break; } } } if (index == -1) break; } // join TRIANGLES, join QUADS for (int i = 0; i < f - 1; i++) { int type = Prototype.Mesh.Faces[i].Flags & World.MeshFace.FaceTypeMask; if (type == World.MeshFace.FaceTypeTriangles | type == World.MeshFace.FaceTypeQuads) { int face = Prototype.Mesh.Faces[i].Flags & World.MeshFace.Face2Mask; for (int j = i + 1; j < f; j++) { int type2 = Prototype.Mesh.Faces[j].Flags & World.MeshFace.FaceTypeMask; int face2 = Prototype.Mesh.Faces[j].Flags & World.MeshFace.Face2Mask; if (type == type2 & face == face2) { if (Prototype.Mesh.Faces[i].Material == Prototype.Mesh.Faces[j].Material) { int n = Prototype.Mesh.Faces[i].Vertices.Length; Array.Resize<World.MeshFaceVertex>(ref Prototype.Mesh.Faces[i].Vertices, n + Prototype.Mesh.Faces[j].Vertices.Length); for (int k = 0; k < Prototype.Mesh.Faces[j].Vertices.Length; k++) { Prototype.Mesh.Faces[i].Vertices[n + k] = Prototype.Mesh.Faces[j].Vertices[k]; } for (int k = j; k < f - 1; k++) { Prototype.Mesh.Faces[k] = Prototype.Mesh.Faces[k + 1]; } f--; j--; } } } } } } // finalize arrays if (v != Prototype.Mesh.Vertices.Length) { Array.Resize<World.Vertex>(ref Prototype.Mesh.Vertices, v); } if (m != Prototype.Mesh.Materials.Length) { Array.Resize<World.MeshMaterial>(ref Prototype.Mesh.Materials, m); } if (f != Prototype.Mesh.Faces.Length) { Array.Resize<World.MeshFace>(ref Prototype.Mesh.Faces, f); } }
internal static StaticObject ReadObject(string FileName) { currentFolder = System.IO.Path.GetDirectoryName(FileName); currentFile = FileName; rootMatrix = Matrix4D.NoTransformation; #if !DEBUG try { #endif XFileParser parser = new XFileParser(System.IO.File.ReadAllBytes(FileName)); Scene scene = parser.GetImportedData(); StaticObject obj = new StaticObject(Plugin.currentHost); MeshBuilder builder = new MeshBuilder(Plugin.currentHost); // Global foreach (var mesh in scene.GlobalMeshes) { MeshBuilder(ref obj, ref builder, mesh); } if (scene.RootNode != null) { // Root Node if (scene.RootNode.TrafoMatrix != Matrix4D.Zero) { rootMatrix = ConvertMatrix(scene.RootNode.TrafoMatrix); } foreach (var mesh in scene.RootNode.Meshes) { MeshBuilder(ref obj, ref builder, mesh); } // Children Node foreach (var node in scene.RootNode.Children) { ChildrenNode(ref obj, ref builder, node); } } builder.Apply(ref obj); obj.Mesh.CreateNormals(); if (rootMatrix != Matrix4D.NoTransformation) { for (int i = 0; i < obj.Mesh.Vertices.Length; i++) { obj.Mesh.Vertices[i].Coordinates.Transform(rootMatrix); } } return(obj); #if !DEBUG } catch (Exception e) { Plugin.currentHost.AddMessage(MessageType.Error, false, e.Message + " in " + FileName); return(null); } #endif }
void drawEditorWindow(int id) { BoxNoBorder = new GUIStyle(GUI.skin.box); BoxNoBorder.normal.background = null; BoxNoBorder.normal.textColor = Color.white; DeadButton = new GUIStyle(GUI.skin.button); DeadButton.normal.background = null; DeadButton.hover.background = null; DeadButton.active.background = null; DeadButton.focused.background = null; DeadButton.normal.textColor = Color.yellow; DeadButton.hover.textColor = Color.white; DeadButton.active.textColor = Color.yellow; DeadButton.focused.textColor = Color.yellow; DeadButton.fontSize = 14; DeadButton.fontStyle = FontStyle.Normal; DeadButton2 = new GUIStyle(GUI.skin.button); DeadButton2.normal.background = null; DeadButton2.hover.background = null; DeadButton2.active.background = null; DeadButton2.focused.background = null; DeadButton2.normal.textColor = Color.white; DeadButton2.hover.textColor = Color.green; DeadButton2.active.textColor = Color.white; DeadButton2.focused.textColor = Color.white; DeadButton2.fontSize = 14; DeadButton2.fontStyle = FontStyle.Bold; DeadButton3 = new GUIStyle(GUI.skin.button); DeadButton3.normal.background = null; DeadButton3.hover.background = null; DeadButton3.active.background = null; DeadButton3.focused.background = null; DeadButton3.normal.textColor = Color.white; DeadButton3.hover.textColor = Color.white; DeadButton3.active.textColor = Color.white; DeadButton3.focused.textColor = Color.white; DeadButton3.fontSize = 13; DeadButton3.fontStyle = FontStyle.Bold; DeadButtonRed = new GUIStyle(GUI.skin.button); DeadButtonRed.normal.background = null; DeadButtonRed.hover.background = null; DeadButtonRed.active.background = null; DeadButtonRed.focused.background = null; DeadButtonRed.normal.textColor = Color.red; DeadButtonRed.hover.textColor = Color.yellow; DeadButtonRed.active.textColor = Color.red; DeadButtonRed.focused.textColor = Color.red; DeadButtonRed.fontSize = 12; DeadButtonRed.fontStyle = FontStyle.Bold; string smessage = ""; GUILayout.BeginHorizontal(); { GUI.enabled = false; GUILayout.Button("-KK-", DeadButton, GUILayout.Height(21)); GUILayout.FlexibleSpace(); GUILayout.Button("Statics Editor", DeadButton, GUILayout.Height(21)); GUILayout.FlexibleSpace(); GUI.enabled = true; if (GUILayout.Button("X", DeadButtonRed, GUILayout.Height(21))) { KerbalKonstructs.instance.ToggleEditor(); } } GUILayout.EndHorizontal(); GUILayout.Space(1); GUILayout.Box(tHorizontalSep, BoxNoBorder, GUILayout.Height(4)); GUILayout.Space(2); GUILayout.BeginHorizontal(); { if (foldedIn) { tFolded = tFoldOut; } if (!foldedIn) { tFolded = tFoldIn; } if (GUILayout.Button(tFolded, GUILayout.Height(23), GUILayout.Width(23))) { if (foldedIn) { foldedIn = false; } else { foldedIn = true; } } GUI.enabled = !creatingInstance; sButtonText = ""; fButtonWidth = 0f; if (foldedIn) { fButtonWidth = 50f; } else { fButtonWidth = 110f; } if (foldedIn) { sButtonText = "New"; } else { sButtonText = "Spawn New"; } if (GUILayout.Button("" + sButtonText, GUILayout.Height(23), GUILayout.Width(fButtonWidth))) { EditorGUI.CloseEditors(); creatingInstance = true; showLocal = false; } GUILayout.Space(5); GUI.enabled = creatingInstance || showLocal; if (foldedIn) { sButtonText = "All"; } else { sButtonText = "All Instances"; } if (GUILayout.Button("" + sButtonText, GUILayout.Width(fButtonWidth), GUILayout.Height(23))) { EditorGUI.CloseEditors(); creatingInstance = false; showLocal = false; KerbalKonstructs.instance.DeletePreviewObject(); KerbalKonstructs.instance.disableAllInstanceEditing = bDisableEditingSetting; } GUI.enabled = true; GUILayout.Space(2); GUI.enabled = creatingInstance || !showLocal; if (foldedIn) { sButtonText = "Local"; } else { sButtonText = "Local Instances"; } if (GUILayout.Button("" + sButtonText, GUILayout.Width(fButtonWidth), GUILayout.Height(23))) { EditorGUI.CloseEditors(); creatingInstance = false; showLocal = true; KerbalKonstructs.instance.DeletePreviewObject(); } GUI.enabled = true; GUILayout.FlexibleSpace(); if (GUILayout.Button(new GUIContent("Save", "Save all new and edited instances."), GUILayout.Width(fButtonWidth - 10), GUILayout.Height(23))) { KerbalKonstructs.instance.saveObjects(); smessage = "Saved all changes to all objects."; MiscUtils.HUDMessage(smessage, 10, 2); } } GUILayout.EndHorizontal(); if (!foldedIn) { if (creatingInstance) { GUILayout.BeginHorizontal(); GUILayout.Space(15); if (GUILayout.Button("Category", DeadButton, GUILayout.Width(110), GUILayout.Height(23))) { if (bSortCategory) { bSortCategory = false; } else { bSortCategory = true; } } GUILayout.Space(5); if (GUILayout.Button("Title", DeadButton, GUILayout.Height(23))) { if (bSortTitle) { bSortTitle = false; } else { bSortTitle = true; } } GUILayout.FlexibleSpace(); GUILayout.Button("Mesh", DeadButton, GUILayout.Width(140), GUILayout.Height(23)); GUILayout.Space(15); GUILayout.EndHorizontal(); } } bool showStatic = false; scrollPos = GUILayout.BeginScrollView(scrollPos); if (creatingInstance) { lStaticModels = KerbalKonstructs.instance.getStaticDB().getModels(); if (bSortCategory) { lStaticModels.Sort(delegate(StaticModel a, StaticModel b) { return(((string)a.getSetting("category")).CompareTo((string)b.getSetting("category"))); }); } if (bSortTitle) { lStaticModels.Sort(delegate(StaticModel a, StaticModel b) { return(((string)a.getSetting("title")).CompareTo((string)b.getSetting("title"))); }); } foreach (StaticModel model in lStaticModels) { if (titlefilterset == "" && categoryfilterset == "") { showStatic = true; } if (titlefilterset != "") { sTitleHolder = (string)model.getSetting("title"); if (sTitleHolder.Contains(titlefilterset)) { showStatic = true; } else { showStatic = false; } } if (categoryfilterset != "") { sCategoryHolder = (string)model.getSetting("category"); if (sCategoryHolder.Contains(categoryfilterset)) { showStatic = true; } else { showStatic = false; } } if (categoryfilterset != "" && titlefilterset != "") { sTitleHolder = (string)model.getSetting("title"); sCategoryHolder = (string)model.getSetting("category"); if (sCategoryHolder.Contains(categoryfilterset) && sTitleHolder.Contains(titlefilterset)) { showStatic = true; } else { showStatic = false; } } if (showStatic) { GUILayout.BeginHorizontal(); if (!foldedIn) { if (GUILayout.Button(new GUIContent("" + model.getSetting("category"), "Filter"), DeadButton, GUILayout.Width(110), GUILayout.Height(23))) { categoryfilter = (string)model.getSetting("category"); categoryfilterset = categoryfilter; titlefilterset = titlefilter; } //GUILayout.FlexibleSpace(); GUILayout.Space(5); } if (GUILayout.Button(new GUIContent("" + "" + model.getSetting("title"), "Spawn an instance of this static."), DeadButton2, GUILayout.Height(23))) { EditorGUI.CloseEditors(); KerbalKonstructs.instance.DeletePreviewObject(); KerbalKonstructs.instance.bDisablePositionEditing = false; spawnInstance(model); smessage = "Spawned " + model.getSetting("title"); MiscUtils.HUDMessage(smessage, 10, 2); } if (!foldedIn) { GUILayout.FlexibleSpace(); if (GUILayout.Button(new GUIContent(" " + model.getSetting("mesh") + " ", "Edit Model Config"), DeadButton, GUILayout.Width(140), GUILayout.Height(23))) { KerbalKonstructs.instance.selectedModel = model; KerbalKonstructs.instance.showModelInfo = true; } } GUILayout.EndHorizontal(); GUILayout.Space(2); } } } if (!creatingInstance) { foreach (StaticObject obj in KerbalKonstructs.instance.getStaticDB().getAllStatics()) { bool isLocal = true; if (showLocal) { if (obj.pqsCity.sphere == FlightGlobals.currentMainBody.pqsController) { var dist = Vector3.Distance(FlightGlobals.ActiveVessel.GetTransform().position, obj.gameObject.transform.position); isLocal = dist < localRange; } else { isLocal = false; } } string sGroupHolder = ""; if (!showLocal) { if (groupfilterset != "") { sGroupHolder = (string)obj.getSetting("Group"); if (!sGroupHolder.Contains(groupfilterset)) { isLocal = false; } } } string sLaunchType = ""; if (isLocal) { GUILayout.BeginHorizontal(); if (!foldedIn) { GUILayout.Button("" + obj.getSetting("Group"), DeadButton3, GUILayout.Width(120), GUILayout.Height(23)); sLaunchType = (string)obj.getSetting("Category"); if (sLaunchType == "Runway" || sLaunchType == "Helipad") { GUILayout.Button(tSPH, DeadButton3, GUILayout.Width(23), GUILayout.Height(23)); } else { if (sLaunchType == "RocketPad") { GUILayout.Button(tVAB, DeadButton3, GUILayout.Width(23), GUILayout.Height(23)); } else { if (sLaunchType == "Other" && obj.settings.ContainsKey("LaunchSiteName")) { GUILayout.Button(tANY, DeadButton3, GUILayout.Width(23), GUILayout.Height(23)); } else { GUILayout.Button("", DeadButton3, GUILayout.Width(23), GUILayout.Height(23)); } } } } //GUI.enabled = (obj != selectedObject); if (GUILayout.Button(new GUIContent("" + obj.model.getSetting("title"), "Edit this instance."), GUILayout.Height(23))) { KerbalKonstructs.instance.bDisablePositionEditing = false; enableColliders = true; EditorGUI.CloseEditors(); if (selectedObject != null) { selectedObjectPrevious = selectedObject; Color highlightColor = new Color(0, 0, 0, 0); obj.HighlightObject(highlightColor); } if (snapTargetInstance == obj) { snapTargetInstance = null; KerbalKonstructs.instance.snapTargetInstance = null; } if (!KerbalKonstructs.instance.disableAllInstanceEditing) { KerbalKonstructs.instance.selectObject(obj, false, true, false); } else { if (!showLocal) { KerbalKonstructs.instance.bDisablePositionEditing = true; KerbalKonstructs.instance.selectObject(obj, false, false, false); } else { KerbalKonstructs.instance.selectObject(obj, false, true, false); } } //obj.selectObject(false); Color highlightColor2 = XKCDColors.Green_Yellow; obj.HighlightObject(highlightColor2); } //GUI.enabled = true; if (showLocal) { GUI.enabled = (snapTargetInstance != obj && obj != selectedObject); if (GUILayout.Button(new GUIContent(tFocus, "Set as snap target."), GUILayout.Height(23), GUILayout.Width(23))) { if (snapTargetInstance != null) { snapTargetInstancePrevious = snapTargetInstance; Color highlightColor3 = new Color(0, 0, 0, 0); snapTargetInstance.HighlightObject(highlightColor3); } snapTargetInstance = obj; KerbalKonstructs.instance.setSnapTarget(obj); Color highlightColor4 = XKCDColors.RedPink; obj.HighlightObject(highlightColor4); } GUI.enabled = true; } GUILayout.EndHorizontal(); GUILayout.Space(2); } } } GUILayout.EndScrollView(); GUI.enabled = true; if (!foldedIn) { if (creatingInstance) { GUILayout.BeginHorizontal(); GUILayout.Label("Filter by "); GUILayout.Label(" Category:"); categoryfilter = GUILayout.TextField(categoryfilter, 30, GUILayout.Width(90)); if (GUILayout.Button(new GUIContent(tSearch, "Apply Filter."), GUILayout.Width(23), GUILayout.Height(23))) { categoryfilterset = categoryfilter; titlefilterset = titlefilter; } if (GUILayout.Button(new GUIContent(tCancelSearch, "Remove Filter."), GUILayout.Width(23), GUILayout.Height(23))) { categoryfilter = ""; categoryfilterset = ""; } GUILayout.Label(" Title:"); titlefilter = GUILayout.TextField(titlefilter, 30, GUILayout.Width(90)); if (GUILayout.Button(new GUIContent(tSearch, "Apply Filter."), GUILayout.Width(23), GUILayout.Height(23))) { categoryfilterset = categoryfilter; titlefilterset = titlefilter; } if (GUILayout.Button(new GUIContent(tCancelSearch, "Remove Filter."), GUILayout.Width(23), GUILayout.Height(23))) { titlefilter = ""; titlefilterset = ""; } GUILayout.EndHorizontal(); } } if (!foldedIn) { if (!showLocal && !creatingInstance) { GUILayout.BeginHorizontal(); { GUILayout.Label("Filter by Group:", GUILayout.Width(140)); //GUILayout.FlexibleSpace(); groupfilter = GUILayout.TextField(groupfilter, 40, GUILayout.Width(140)); if (GUILayout.Button(new GUIContent(tSearch, "Apply Filter."), GUILayout.Width(23), GUILayout.Height(23))) { groupfilterset = groupfilter; } if (GUILayout.Button(new GUIContent(tCancelSearch, "Remove Filter."), GUILayout.Width(23), GUILayout.Height(23))) { groupfilter = ""; groupfilterset = ""; } } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); { GUILayout.Label("Pack Name: ", GUILayout.Width(140)); //GUILayout.FlexibleSpace(); sPackName = GUILayout.TextField(sPackName, 30, GUILayout.Width(140)); //GUILayout.FlexibleSpace(); GUI.enabled = (sPackName != "" && groupfilter != ""); if (GUILayout.Button("Export Group")) { //Validate the groupfilter to see if it is a Group name bool bValidGroupName = false; foreach (StaticObject obj in KerbalKonstructs.instance.getStaticDB().getAllStatics()) { if ((string)obj.getSetting("Group") == groupfilter) { bValidGroupName = true; break; } } if (bValidGroupName) { KerbalKonstructs.instance.exportCustomInstances(sPackName, "", groupfilter); smessage = "Exported custom instances to GameData/KerbalKonstructs/ExportedInstances/" + sPackName + "/" + groupfilter; MiscUtils.HUDMessage(smessage, 10, 2); } else { smessage = "Group filter is not a valid Group name. Please filter with a complete and valid Group name before exporting a group."; MiscUtils.HUDMessage(smessage, 20, 2); } } GUI.enabled = true; GUI.enabled = (sPackName != ""); if (GUILayout.Button("Export All")) { KerbalKonstructs.instance.exportCustomInstances(sPackName, "All"); smessage = "Exported all custom instances to GameData/KerbalKonstructs/ExportedInstances/" + sPackName + "/"; MiscUtils.HUDMessage(smessage, 10, 2); } GUI.enabled = true; } GUILayout.EndHorizontal(); if (!KerbalKonstructs.instance.disableAllInstanceEditing) { GUILayout.BeginHorizontal(); if (GUILayout.Button("Disable Camera Focus/Position Editing", GUILayout.Height(23))) { KerbalKonstructs.instance.disableAllInstanceEditing = true; bDisableEditingSetting = true; } GUILayout.Button(tCross, DeadButton, GUILayout.Height(23), GUILayout.Width(23)); GUILayout.EndHorizontal(); } else { GUILayout.BeginHorizontal(); if (GUILayout.Button("Disable Camera Focus/Position Editing", GUILayout.Height(23))) { KerbalKonstructs.instance.disableAllInstanceEditing = false; bDisableEditingSetting = false; } GUILayout.Button(tTick, DeadButton, GUILayout.Height(23), GUILayout.Width(23)); GUILayout.EndHorizontal(); } } } if (showLocal) { GUILayout.BeginHorizontal(); if (!foldedIn) { GUILayout.Label("Local:"); } GUI.enabled = false; GUILayout.Label(localRange.ToString("0") + " m", GUILayout.Width(50)); GUI.enabled = showLocal; if (GUILayout.Button("-", GUILayout.Width(25))) { if (localRange < 5000) { } else { localRange = localRange / 2; } } if (GUILayout.Button("+", GUILayout.Width(25))) { if (localRange > 79999) { } else { localRange = localRange * 2; } } GUI.enabled = true; GUILayout.FlexibleSpace(); if (!foldedIn) { GUILayout.Label("Group:"); } else { GUILayout.Label("Group"); } // GUILayout.Space(5); GUI.enabled = showLocal; if (!foldedIn) { customgroup = GUILayout.TextField(customgroup, 25, GUILayout.Width(125)); } else { customgroup = GUILayout.TextField(customgroup, 25, GUILayout.Width(45)); } GUI.enabled = true; GUI.enabled = showLocal; if (!foldedIn) { sButtonText = "Set as Group"; } else { sButtonText = "Set"; } if (!foldedIn) { fButtonWidth = 100; } else { fButtonWidth = 35; } if (GUILayout.Button("" + sButtonText, GUILayout.Width(fButtonWidth))) { setLocalsGroup(customgroup, localRange); smessage = "Set group as " + customgroup; MiscUtils.HUDMessage(smessage, 10, 2); } GUI.enabled = true; GUILayout.EndHorizontal(); } GUILayout.Space(1); GUILayout.Box(tHorizontalSep, BoxNoBorder, GUILayout.Height(4)); GUILayout.Space(2); if (GUI.tooltip != "") { var labelSize = GUI.skin.GetStyle("Label").CalcSize(new GUIContent(GUI.tooltip)); GUI.Box(new Rect(Event.current.mousePosition.x - (25 + (labelSize.x / 2)), Event.current.mousePosition.y - 40, labelSize.x + 10, labelSize.y + 5), GUI.tooltip); } GUI.DragWindow(new Rect(0, 0, 10000, 10000)); }
private static void MeshBuilder(ref StaticObject obj, ref MeshBuilder builder, AssimpNET.X.Mesh mesh) { if (builder.Vertices.Length != 0) { builder.Apply(ref obj); builder = new MeshBuilder(Plugin.currentHost); } int nVerts = mesh.Positions.Count; if (nVerts == 0) { //Some null objects contain an empty mesh Plugin.currentHost.AddMessage(MessageType.Warning, false, "nVertices should be greater than zero in Mesh " + mesh.Name); } int v = builder.Vertices.Length; Array.Resize(ref builder.Vertices, v + nVerts); for (int i = 0; i < nVerts; i++) { builder.Vertices[v + i] = new Vertex(mesh.Positions[i].X, mesh.Positions[i].Y, mesh.Positions[i].Z); } int nFaces = mesh.PosFaces.Count; int f = builder.Faces.Length; Array.Resize(ref builder.Faces, f + nFaces); for (int i = 0; i < nFaces; i++) { int fVerts = mesh.PosFaces[i].Indices.Count; if (nFaces == 0) { throw new Exception("fVerts must be greater than zero"); } builder.Faces[f + i] = new MeshFace(); builder.Faces[f + i].Vertices = new MeshFaceVertex[fVerts]; for (int j = 0; j < fVerts; j++) { builder.Faces[f + i].Vertices[j].Index = (ushort)mesh.PosFaces[i].Indices[j]; } } int nMaterials = mesh.Materials.Count; int nFaceIndices = mesh.FaceMaterials.Count; for (int i = 0; i < nFaceIndices; i++) { int fMaterial = (int)mesh.FaceMaterials[i]; builder.Faces[i].Material = (ushort)(fMaterial + 1); } for (int i = 0; i < nMaterials; i++) { int m = builder.Materials.Length; Array.Resize(ref builder.Materials, m + 1); builder.Materials[m] = new OpenBveApi.Objects.Material(); builder.Materials[m].Color = new Color32((byte)(255 * mesh.Materials[i].Diffuse.R), (byte)(255 * mesh.Materials[i].Diffuse.G), (byte)(255 * mesh.Materials[i].Diffuse.B), (byte)(255 * mesh.Materials[i].Diffuse.A)); double mPower = mesh.Materials[i].SpecularExponent; //TODO: Unsure what this does... Color24 mSpecular = new Color24((byte)mesh.Materials[i].Specular.R, (byte)mesh.Materials[i].Specular.G, (byte)mesh.Materials[i].Specular.B); builder.Materials[m].EmissiveColor = new Color24((byte)(255 * mesh.Materials[i].Emissive.R), (byte)(255 * mesh.Materials[i].Emissive.G), (byte)(255 * mesh.Materials[i].Emissive.B)); builder.Materials[m].EmissiveColorUsed = true; //TODO: Check exact behaviour builder.Materials[m].TransparentColor = Color24.Black; //TODO: Check, also can we optimise which faces have the transparent color set? builder.Materials[m].TransparentColorUsed = true; if (mesh.Materials[i].Textures.Count > 0) { builder.Materials[m].DaytimeTexture = OpenBveApi.Path.CombineFile(currentFolder, mesh.Materials[i].Textures[0].Name); if (!System.IO.File.Exists(builder.Materials[m].DaytimeTexture)) { Plugin.currentHost.AddMessage(MessageType.Error, true, "Texure " + builder.Materials[m].DaytimeTexture + " was not found in file " + currentFile); builder.Materials[m].DaytimeTexture = null; } } } if (mesh.TexCoords.Length > 0 && mesh.TexCoords[0] != null) { int nCoords = mesh.TexCoords[0].Count; for (int i = 0; i < nCoords; i++) { builder.Vertices[i].TextureCoordinates = new Vector2(mesh.TexCoords[0][i].X, mesh.TexCoords[0][i].Y); } } int nNormals = mesh.Normals.Count; Vector3[] normals = new Vector3[nNormals]; for (int i = 0; i < nNormals; i++) { normals[i] = new Vector3(mesh.Normals[i].X, mesh.Normals[i].Y, mesh.Normals[i].Z); normals[i].Normalize(); } int nFaceNormals = mesh.NormFaces.Count; if (nFaceNormals > builder.Faces.Length) { throw new Exception("nFaceNormals must match the number of faces in the mesh"); } for (int i = 0; i < nFaceNormals; i++) { int nVertexNormals = mesh.NormFaces[i].Indices.Count; if (nVertexNormals > builder.Faces[i].Vertices.Length) { throw new Exception("nVertexNormals must match the number of verticies in the face"); } for (int j = 0; j < nVertexNormals; j++) { builder.Faces[i].Vertices[j].Normal = normals[(int)mesh.NormFaces[i].Indices[j]]; } } int nVertexColors = (int)mesh.NumColorSets; for (int i = 0; i < nVertexColors; i++) { builder.Vertices[i] = new ColoredVertex((Vertex)builder.Vertices[i], new Color128(mesh.Colors[0][i].R, mesh.Colors[0][i].G, mesh.Colors[0][i].B, mesh.Colors[0][i].A)); } }
public void drawRacingWindow(int windowID) { BoxNoBorder = new GUIStyle(GUI.skin.box); BoxNoBorder.normal.background = null; BoxNoBorder.normal.textColor = Color.white; DeadButton = new GUIStyle(GUI.skin.button); DeadButton.normal.background = null; DeadButton.hover.background = null; DeadButton.active.background = null; DeadButton.focused.background = null; DeadButton.normal.textColor = Color.white; DeadButton.hover.textColor = Color.white; DeadButton.active.textColor = Color.white; DeadButton.focused.textColor = Color.white; DeadButton.fontSize = 14; DeadButton.fontStyle = FontStyle.Bold; DeadButtonRed = new GUIStyle(GUI.skin.button); DeadButtonRed.normal.background = null; DeadButtonRed.hover.background = null; DeadButtonRed.active.background = null; DeadButtonRed.focused.background = null; DeadButtonRed.normal.textColor = Color.red; DeadButtonRed.hover.textColor = Color.yellow; DeadButtonRed.active.textColor = Color.red; DeadButtonRed.focused.textColor = Color.red; DeadButtonRed.fontSize = 12; DeadButtonRed.fontStyle = FontStyle.Bold; GUILayout.BeginHorizontal(); { GUI.enabled = false; GUILayout.Button("-KK-", DeadButton, GUILayout.Height(16)); GUILayout.FlexibleSpace(); GUILayout.Button("Air-Racing", DeadButton, GUILayout.Height(16)); GUILayout.FlexibleSpace(); GUI.enabled = true; if (GUILayout.Button("X", DeadButtonRed, GUILayout.Height(16))) { ResetRace(); KerbalKonstructs.instance.showRacingApp = false; runningRace = false; } } GUILayout.EndHorizontal(); GUILayout.Space(1); GUILayout.Box(tHorizontalSep, BoxNoBorder, GUILayout.Height(4)); if (!racing) { GUILayout.Box("Cross a start line to begin a race."); if (!started) { StartLine = NavUtils.GetNearestFacility(FlightGlobals.ActiveVessel.GetTransform().position, "RaceStart"); if (StartLine != null) { fDistToStart = StartLine.GetDistanceToObject(FlightGlobals.ActiveVessel.GetTransform().position); if (fDistToStart < 150) { dStartTime = Planetarium.GetUniversalTime(); MiscUtils.HUDMessage("!!! GO GO GO !!!", 10, 0); started = true; racing = true; } if (fDistToStart < 200) { GUILayout.Box("!!!!!! RACE ON! GO GO GO !!!!!!"); } if (fDistToStart >= 200) { GUILayout.Box("Distance to Start Line: " + fDistToStart.ToString("#0.00") + " m"); } } else { GUILayout.Box("Cannot find any start lines."); } } } if (racing) { if (!finished && started) { dTimeSinceStart = Planetarium.GetUniversalTime() - dStartTime; fTimeMins = (int)dTimeSinceStart / 60; fTimeSecs = (float)(dTimeSinceStart - (fTimeMins * 60)); GUILayout.Box("Race Time: " + fTimeMins.ToString("#0") + " minutes " + fTimeSecs.ToString("#0.00") + " seconds "); if (fNextGate > 0) { StaticObject soNextGate = GetNextGate(StartLine, fNextGate); if (soNextGate != null) { GUILayout.Box("Next Gate: " + fNextGate); fDistToGate = GetDistanceToGate(soNextGate, FlightGlobals.ActiveVessel.GetTransform().position); fDistBetween = (GetGateWidth(soNextGate) / 2) + 10; if (fDistToGate > fDistBetween) { GUILayout.Box("Distance to Next Gate: " + fDistToGate.ToString("#0.0") + " m"); } else { MiscUtils.HUDMessage("!!! GATE " + fNextGate.ToString() + " CLEAR !!!", 10, 0); fNextGate = fNextGate + 1; } } else { fNextGate = 0; } } else { GUILayout.Box("Final Stretch!"); } if (fNextGate == 0) { FinishLine = NavUtils.GetNearestFacility(FlightGlobals.ActiveVessel.GetTransform().position, "RaceFinish"); if (FinishLine != null) { fDistToFinish = FinishLine.GetDistanceToObject(FlightGlobals.ActiveVessel.GetTransform().position); GUILayout.Box("Distance to Finish Line: " + fDistToFinish.ToString("#0.0") + " m"); if (fDistToFinish < 150) { finished = true; started = false; } } else { GUILayout.Box("Cannot find any finish lines."); } } } if (finished) { GUILayout.Box("!!!!! FINISH LINE !!!!!"); if (dFinishTime == 0) { dFinishTime = Planetarium.GetUniversalTime() - dStartTime; MiscUtils.HUDMessage("!!! FINISHED !!!", 10, 0); } fTimeMins = (int)dFinishTime / 60; fTimeSecs = (float)(dFinishTime - (fTimeMins * 60)); GUILayout.Box("Race Time: " + fTimeMins.ToString("#0") + " minutes " + fTimeSecs.ToString("#0.00") + " seconds "); if (GUILayout.Button("Save Race Results", GUILayout.Height(22))) { MiscUtils.HUDMessage("Feature still WIP", 10, 3); } if (GUILayout.Button("Race Again!", GUILayout.Height(22))) { ResetRace(); } } } GUILayout.Space(5); if (GUILayout.Button("I'm done racing!", GUILayout.Height(22))) { ResetRace(); KerbalKonstructs.instance.showRacingApp = false; runningRace = false; } GUILayout.FlexibleSpace(); GUILayout.Box(tHorizontalSep, BoxNoBorder, GUILayout.Height(4)); GUILayout.Space(3); GUI.DragWindow(new Rect(0, 0, 10000, 10000)); }
public void drawIcons() { displayingTooltip = false; MapObject target = PlanetariumCamera.fetch.target; if (target.type == MapObject.MapObjectType.CELESTIALBODY) { // Do tracking stations first foreach (StaticObject obj in KerbalKonstructs.instance.getStaticDB().getAllStatics()) { bool display2 = false; if ((string)obj.getSetting("FacilityType") == "TrackingStation") { if (!isOccluded(obj.gameObject.transform.position, target.celestialBody)) { if (MiscUtils.isCareerGame()) { //PersistenceUtils.loadStaticPersistence(obj); string openclosed2 = (string)obj.getSetting("OpenCloseState"); // To do manage open and close state of tracking stations if (KerbalKonstructs.instance.mapShowOpenT) // && openclosed == "Open") { display2 = true; } if (!KerbalKonstructs.instance.mapShowClosed && openclosed2 == "Closed") { display2 = false; } if (!KerbalKonstructs.instance.mapShowOpen && openclosed2 == "Open") { display2 = false; } } else { // Not a career game } if (display2) { Vector3 pos = MapView.MapCamera.camera.WorldToScreenPoint(ScaledSpace.LocalToScaledSpace(obj.gameObject.transform.position)); Rect screenRect2 = new Rect((pos.x - 8), (Screen.height - pos.y) - 8, 16, 16); Graphics.DrawTexture(screenRect2, TrackingStationIcon); if (screenRect2.Contains(Event.current.mousePosition) && !displayingTooltip) { CelestialBody cPlanetoid = (CelestialBody)obj.getSetting("CelestialBody"); var objectpos2 = cPlanetoid.transform.InverseTransformPoint(obj.gameObject.transform.position); var dObjectLat2 = NavUtils.GetLatitude(objectpos2); var dObjectLon2 = NavUtils.GetLongitude(objectpos2); var disObjectLat2 = dObjectLat2 * 180 / Math.PI; var disObjectLon2 = dObjectLon2 * 180 / Math.PI; if (disObjectLon2 < 0) { disObjectLon2 = disObjectLon2 + 360; } //Only display one tooltip at a time displayMapIconToolTip("Tracking Station " + "\n(Lat." + disObjectLat2.ToString("#0.00") + "/ Lon." + disObjectLon2.ToString("#0.00") + ")", pos); // TO DO Display Lat and Lon in tooltip too if (Event.current.type == EventType.mouseDown && Event.current.button == 0) { //MiscUtils.HUDMessage("Selected base is " + sToolTip + ".", 5f, 3); Debug.Log("KK: Selected station in map"); float sTrackAngle = (float)obj.getSetting("TrackingAngle"); Debug.Log("KK: Before save load " + sTrackAngle.ToString()); float sTrackRange = (float)obj.getSetting("TrackingShort"); Debug.Log("KK: Before save load " + sTrackRange.ToString()); //PersistenceUtils.saveStaticPersistence(obj); PersistenceUtils.loadStaticPersistence(obj); float sTrackAngle2 = (float)obj.getSetting("TrackingAngle"); Debug.Log("KK: After save load " + sTrackAngle2.ToString()); float sTrackRange2 = (float)obj.getSetting("TrackingShort"); Debug.Log("KK: After save load " + sTrackRange2.ToString()); selectedFacility = obj; FacilityManager.setSelectedFacility(obj); KerbalKonstructs.instance.showFacilityManager = true; //EditorGUI.setTargetSite(selectedSite); } } else { // Mouse is not over tooltip } } else { // Filter set to not display } } else { // is occluded } } else { // Not a tracking station } } //end foreach // Then do launchsites List <LaunchSite> sites = LaunchSiteManager.getLaunchSites(); foreach (LaunchSite site in sites) { bool display = false; PSystemSetup.SpaceCenterFacility facility = PSystemSetup.Instance.GetSpaceCenterFacility(site.name); if (facility != null) { PSystemSetup.SpaceCenterFacility.SpawnPoint sp = facility.GetSpawnPoint(site.name); if (sp != null) { if (facility.facilityPQS == target.celestialBody.pqsController) { if (!isOccluded(sp.GetSpawnPointTransform().position, target.celestialBody)) { Vector3 pos = MapView.MapCamera.camera.WorldToScreenPoint(ScaledSpace.LocalToScaledSpace(sp.GetSpawnPointTransform().position)); Rect screenRect = new Rect((pos.x - 8), (Screen.height - pos.y) - 8, 16, 16); string openclosed = site.openclosestate; string category = site.category; if (KerbalKonstructs.instance.mapShowHelipads && category == "Helipad") { display = true; } if (KerbalKonstructs.instance.mapShowOther && category == "Other") { display = true; } if (KerbalKonstructs.instance.mapShowRocketbases && category == "RocketPad") { display = true; } if (KerbalKonstructs.instance.mapShowRunways && category == "Runway") { display = true; } if (display && MiscUtils.isCareerGame()) { if (!KerbalKonstructs.instance.mapShowOpen && openclosed == "Open") { display = false; } if (!KerbalKonstructs.instance.mapShowClosed && openclosed == "Closed") { display = false; } if (KerbalKonstructs.instance.disableDisplayClosed && openclosed == "Closed") { display = false; } } if (display) { if (site.icon != null) { Graphics.DrawTexture(screenRect, site.icon); } else { switch (site.type) { case SiteType.VAB: Graphics.DrawTexture(screenRect, VABIcon); break; case SiteType.SPH: Graphics.DrawTexture(screenRect, SPHIcon); break; default: Graphics.DrawTexture(screenRect, ANYIcon); break; } } // Tooltip if (screenRect.Contains(Event.current.mousePosition) && !displayingTooltip) { //Only display one tooltip at a time string sToolTip = ""; sToolTip = site.name; if (site.name == "Runway") { sToolTip = "KSC Runway"; } if (site.name == "LaunchPad") { sToolTip = "KSC LaunchPad"; } displayMapIconToolTip(sToolTip, pos); // Select a base by clicking on the icon if (Event.current.type == EventType.mouseDown && Event.current.button == 0) { MiscUtils.HUDMessage("Selected base is " + sToolTip + ".", 5f, 3); BaseManager.setSelectedSite(site); selectedSite = site; NavGuidanceSystem.setTargetSite(selectedSite); KerbalKonstructs.instance.showBaseManager = true; } } } } } } } } } }
private void Init(Client psr) { AccountId = psr.Account.AccountId; PlayerOwnerName = psr.Account.Name; List <IntPoint> vaultChestPosition = new List <IntPoint>(); List <IntPoint> giftChestPosition = new List <IntPoint>(); IntPoint spawn = new IntPoint(0, 0); int w = Map.Width; int h = Map.Height; for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { WmapTile tile = Map[x, y]; if (tile.Region == TileRegion.Spawn) { spawn = new IntPoint(x, y); } else if (tile.Region == TileRegion.Vault) { vaultChestPosition.Add(new IntPoint(x, y)); } else if (tile.Region == TileRegion.Gifting_Chest) { giftChestPosition.Add(new IntPoint(x, y)); } } } vaultChestPosition.Sort((x, y) => Comparer <int> .Default.Compare( (x.X - spawn.X) * (x.X - spawn.X) + (x.Y - spawn.Y) * (x.Y - spawn.Y), (y.X - spawn.X) * (y.X - spawn.X) + (y.Y - spawn.Y) * (y.Y - spawn.Y))); List <VaultChest> chests = psr.Account.Vault.Chests; if (psr.Account.Gifts != null) { List <GiftChest> giftChests = new List <GiftChest>(); GiftChest c = new GiftChest(); c.Items = new List <Item>(8); bool wasLastElse = false; int[] gifts = psr.Account.Gifts.ToArray(); gifts.Shuffle(); using (Database db = new Database()) { for (int i = 0; i < gifts.Count(); i++) { Item newGift = db.getSerialInfo(gifts[i], Manager.GameData); if (c.Items.Count < 8) { c.Items.Add(newGift); wasLastElse = false; } else { giftChests.Add(c); c = new GiftChest(); c.Items = new List <Item>(8); c.Items.Add(newGift); wasLastElse = true; } } } if (!wasLastElse) { giftChests.Add(c); } foreach (GiftChest chest in giftChests) { if (giftChestPosition.Count == 0) { break; } while (chest.Items.Count < 8) { chest.Items.Add(null); } OneWayContainer con = new OneWayContainer(Manager, 0x0744, null, false); List <Item> inv = chest.Items; for (int j = 0; j < 8; j++) { con.Inventory[j] = inv[j]; } con.Move(giftChestPosition[0].X + 0.5f, giftChestPosition[0].Y + 0.5f); EnterWorld(con); giftChestPosition.RemoveAt(0); } } foreach (VaultChest t in chests) { if (vaultChestPosition.Count == 0) { break; } Container con = new Container(Manager, 0x0504, null, false); Item[] inv; using (Database db = new Database()) { inv = db.getSerialInfo(t.Items, Manager.GameData); }; for (int j = 0; j < 8; j++) { con.Inventory[j] = inv[j]; } con.Move(vaultChestPosition[0].X + 0.5f, vaultChestPosition[0].Y + 0.5f); EnterWorld(con); vaultChestPosition.RemoveAt(0); _vaultChests[new Tuple <Container, VaultChest>(con, t)] = con.UpdateCount; } foreach (IntPoint i in giftChestPosition) { StaticObject x = new StaticObject(Manager, 0x0743, null, true, false, false); x.Move(i.X + 0.5f, i.Y + 0.5f); EnterWorld(x); } foreach (IntPoint i in vaultChestPosition) { SellableObject x = new SellableObject(Manager, 0x0505); x.Move(i.X + 0.5f, i.Y + 0.5f); EnterWorld(x); } }
internal void CreatePrimaryRail(Block currentBlock, Block nextBlock, Vector3 pos, Transformation RailTransformation, double StartingDistance, double EndingDistance, string FileName) { if (SecondaryRail == Form.SecondaryRailStub) { if (!Structure.FormL.ContainsKey(FormType)) { Plugin.CurrentHost.AddMessage(MessageType.Error, false, "FormStructureIndex references a FormL not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + "."); } else { Structure.FormL[FormType].CreateObject(pos, RailTransformation, StartingDistance, EndingDistance, StartingDistance); if (RoofType > 0) { if (!Structure.RoofL.ContainsKey(RoofType)) { Plugin.CurrentHost.AddMessage(MessageType.Error, false, "RoofStructureIndex references a RoofL not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + "."); } else { Structure.RoofL[RoofType].CreateObject(pos, RailTransformation, StartingDistance, EndingDistance, StartingDistance); } } } } else if (SecondaryRail == Form.SecondaryRailL) { if (!Structure.FormL.ContainsKey(FormType)) { Plugin.CurrentHost.AddMessage(MessageType.Error, false, "FormStructureIndex references a FormL not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + "."); } else { Structure.FormL[FormType].CreateObject(pos, RailTransformation, StartingDistance, EndingDistance, StartingDistance); } if (!Structure.FormCL.ContainsKey(FormType)) { Plugin.CurrentHost.AddMessage(MessageType.Error, false, "FormStructureIndex references a FormCL not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + "."); } else { Plugin.CurrentHost.CreateStaticObject((StaticObject)Structure.FormCL[FormType], pos, RailTransformation, Transformation.NullTransformation, 0.0, StartingDistance, EndingDistance, StartingDistance, 1.0); } if (RoofType > 0) { if (!Structure.RoofL.ContainsKey(RoofType)) { Plugin.CurrentHost.AddMessage(MessageType.Error, false, "RoofStructureIndex references a RoofL not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + "."); } else { Structure.RoofL[RoofType].CreateObject(pos, RailTransformation, StartingDistance, EndingDistance, StartingDistance); } if (!Structure.RoofCL.ContainsKey(RoofType)) { Plugin.CurrentHost.AddMessage(MessageType.Error, false, "RoofStructureIndex references a RoofCL not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + "."); } else { Plugin.CurrentHost.CreateStaticObject((StaticObject)Structure.RoofCL[RoofType], pos, RailTransformation, Transformation.NullTransformation, 0.0, StartingDistance, EndingDistance, StartingDistance, 1.0); } } } else if (SecondaryRail == Form.SecondaryRailR) { if (!Structure.FormR.ContainsKey(FormType)) { Plugin.CurrentHost.AddMessage(MessageType.Error, false, "FormStructureIndex references a FormR not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + "."); } else { Structure.FormR[FormType].CreateObject(pos, RailTransformation, StartingDistance, EndingDistance, StartingDistance); } if (!Structure.FormCR.ContainsKey(FormType)) { Plugin.CurrentHost.AddMessage(MessageType.Error, false, "FormStructureIndex references a FormCR not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + "."); } else { Plugin.CurrentHost.CreateStaticObject((StaticObject)Structure.FormCR[FormType], pos, RailTransformation, Transformation.NullTransformation, 0.0, StartingDistance, EndingDistance, StartingDistance, 1.0); } if (RoofType > 0) { if (!Structure.RoofR.ContainsKey(RoofType)) { Plugin.CurrentHost.AddMessage(MessageType.Error, false, "RoofStructureIndex references a RoofR not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + "."); } else { Structure.RoofR[RoofType].CreateObject(pos, RailTransformation, StartingDistance, EndingDistance, StartingDistance); } if (!Structure.RoofCR.ContainsKey(RoofType)) { Plugin.CurrentHost.AddMessage(MessageType.Error, false, "RoofStructureIndex references a RoofCR not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + "."); } else { Plugin.CurrentHost.CreateStaticObject((StaticObject)Structure.RoofCR[RoofType], pos, RailTransformation, Transformation.NullTransformation, 0.0, StartingDistance, EndingDistance, StartingDistance, 1.0); } } } else if (SecondaryRail > 0) { int p = PrimaryRail; double px0 = p > 0 ? currentBlock.Rails[p].RailStart.X : 0.0; double px1 = p > 0 ? nextBlock.Rails[p].RailEnd.X : 0.0; int s = SecondaryRail; if (s < 0 || !currentBlock.Rails.ContainsKey(s) || !currentBlock.Rails[s].RailStarted) { Plugin.CurrentHost.AddMessage(MessageType.Error, false, "RailIndex2 is out of range in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName); } else { double d0 = currentBlock.Rails[s].RailStart.X - px0; double d1 = currentBlock.Rails[s].RailEnd.X - px1; if (d0 < 0.0) { if (!Structure.FormL.ContainsKey(FormType)) { Plugin.CurrentHost.AddMessage(MessageType.Error, false, "FormStructureIndex references a FormL not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + "."); } else { Structure.FormL[FormType].CreateObject(pos, RailTransformation, StartingDistance, EndingDistance, StartingDistance); } if (!Structure.FormCL.ContainsKey(FormType)) { Plugin.CurrentHost.AddMessage(MessageType.Error, false, "FormStructureIndex references a FormCL not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + "."); } else { StaticObject FormC = (StaticObject)Structure.FormCL[FormType].Transform(d0, d1); Plugin.CurrentHost.CreateStaticObject(FormC, pos, RailTransformation, Transformation.NullTransformation, 0.0, StartingDistance, EndingDistance, StartingDistance, 1.0); } if (RoofType > 0) { if (!Structure.RoofL.ContainsKey(RoofType)) { Plugin.CurrentHost.AddMessage(MessageType.Error, false, "RoofStructureIndex references a RoofL not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + "."); } else { Structure.RoofL[RoofType].CreateObject(pos, RailTransformation, StartingDistance, EndingDistance, StartingDistance); } if (!Structure.RoofCL.ContainsKey(RoofType)) { Plugin.CurrentHost.AddMessage(MessageType.Error, false, "RoofStructureIndex references a RoofCL not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + "."); } else { StaticObject RoofC = (StaticObject)Structure.RoofCL[RoofType].Transform(d0, d1); Plugin.CurrentHost.CreateStaticObject(RoofC, pos, RailTransformation, Transformation.NullTransformation, 0.0, StartingDistance, EndingDistance, StartingDistance, 1.0); } } } else if (d0 > 0.0) { if (!Structure.FormR.ContainsKey(FormType)) { Plugin.CurrentHost.AddMessage(MessageType.Error, false, "FormStructureIndex references a FormR not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + "."); } else { Structure.FormR[FormType].CreateObject(pos, RailTransformation, StartingDistance, EndingDistance, StartingDistance); } if (!Structure.FormCR.ContainsKey(FormType)) { Plugin.CurrentHost.AddMessage(MessageType.Error, false, "FormStructureIndex references a FormCR not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + "."); } else { StaticObject FormC = (StaticObject)Structure.FormCR[FormType].Transform(d0, d1); Plugin.CurrentHost.CreateStaticObject(FormC, pos, RailTransformation, Transformation.NullTransformation, 0.0, StartingDistance, EndingDistance, StartingDistance, 1.0); } if (RoofType > 0) { if (!Structure.RoofR.ContainsKey(RoofType)) { Plugin.CurrentHost.AddMessage(MessageType.Error, false, "RoofStructureIndex references a RoofR not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + "."); } else { Structure.RoofR[RoofType].CreateObject(pos, RailTransformation, StartingDistance, EndingDistance, StartingDistance); } if (!Structure.RoofCR.ContainsKey(RoofType)) { Plugin.CurrentHost.AddMessage(MessageType.Error, false, "RoofStructureIndex references a RoofCR not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + "."); } else { StaticObject RoofC = (StaticObject)Structure.RoofCR[RoofType].Transform(d0, d1); Plugin.CurrentHost.CreateStaticObject(RoofC, pos, RailTransformation, Transformation.NullTransformation, 0.0, StartingDistance, EndingDistance, StartingDistance, 1.0); } } } } } }
public static void CacheHangaredCraft(StaticObject obj) { string sInStorage = (string)obj.getSetting("InStorage"); string sInStorage2 = (string)obj.getSetting("TargetID"); string sInStorage3 = (string)obj.getSetting("TargetType"); foreach (Vessel vVesselStored in FlightGlobals.Vessels) { if (vVesselStored == null) { continue; } if (!vVesselStored.loaded) { continue; } if (vVesselStored.vesselType == VesselType.SpaceObject) { continue; } if (vVesselStored.vesselType == VesselType.Debris) { continue; } if (vVesselStored.vesselType == VesselType.EVA) { continue; } if (vVesselStored.vesselType == VesselType.Flag) { continue; } if (vVesselStored.vesselType == VesselType.Unknown) { continue; } string sHangarSpace = "None"; // If a vessel is hangared if (vVesselStored.id.ToString() == sInStorage) { sHangarSpace = "InStorage"; } if (vVesselStored.id.ToString() == sInStorage2) { sHangarSpace = "TargetID"; } if (vVesselStored.id.ToString() == sInStorage3) { sHangarSpace = "TargetType"; } if (sHangarSpace != "None") { if (vVesselStored == FlightGlobals.ActiveVessel) { // Craft has been taken control // Empty the hangar obj.setSetting(sHangarSpace, "None"); PersistenceUtils.saveStaticPersistence(obj); } else { // Hide the vessel - it is in the hangar if (vVesselStored != null) { foreach (Part p in vVesselStored.Parts) { if (p != null && p.gameObject != null) { p.gameObject.SetActive(false); } else { continue; } } vVesselStored.MakeInactive(); vVesselStored.enabled = false; if (vVesselStored.loaded) { vVesselStored.Unload(); } } } } } }
// clone object internal static StaticObject CloneObject(StaticObject Prototype) { if (Prototype == null) return null; return CloneObject(Prototype, null, null); }
/// <summary>Creates a static object within the world of the host application, and returns the ObjectManager ID</summary> /// <param name="Prototype">The prototype (un-transformed) static object</param> /// <param name="LocalTransformation"> /// <para>The local transformation to apply in order to rotate the model</para> /// <para>NOTE: Only used for object disposal calcs</para> /// </param> /// <param name="Rotate">The rotation matrix to apply</param> /// <param name="Translate">The translation matrix to apply</param> /// <param name="AccurateObjectDisposalZOffset">The offset for accurate Z-disposal</param> /// <param name="StartingDistance">The absolute route based starting distance for the object</param> /// <param name="EndingDistance">The absolute route based ending distance for the object</param> /// <param name="TrackPosition">The absolute route based track position</param> /// <param name="Brightness">The brightness value at this track position</param> /// <returns>The index to the created object, or -1 if this call fails</returns> public virtual int CreateStaticObject(StaticObject Prototype, Transformation LocalTransformation, Matrix4D Rotate, Matrix4D Translate, double AccurateObjectDisposalZOffset, double StartingDistance, double EndingDistance, double TrackPosition, double Brightness) { return(-1); }
/// <summary>Creates a clone of the specified object.</summary> /// <param name="Prototype">The prototype.</param> /// <param name="DaytimeTexture">The replacement daytime texture, or a null reference to keep the texture of the prototype.</param> /// <param name="NighttimeTexture">The replacement nighttime texture, or a null reference to keep the texture of the prototype.</param> /// <returns></returns> internal static StaticObject CloneObject(StaticObject Prototype, Textures.Texture DaytimeTexture, Textures.Texture NighttimeTexture) { if (Prototype == null) return null; StaticObject Result = new StaticObject(); Result.StartingDistance = Prototype.StartingDistance; Result.EndingDistance = Prototype.EndingDistance; Result.Dynamic = Prototype.Dynamic; // vertices Result.Mesh.Vertices = new World.Vertex[Prototype.Mesh.Vertices.Length]; for (int j = 0; j < Prototype.Mesh.Vertices.Length; j++) { Result.Mesh.Vertices[j] = Prototype.Mesh.Vertices[j]; } // faces Result.Mesh.Faces = new World.MeshFace[Prototype.Mesh.Faces.Length]; for (int j = 0; j < Prototype.Mesh.Faces.Length; j++) { Result.Mesh.Faces[j].Flags = Prototype.Mesh.Faces[j].Flags; Result.Mesh.Faces[j].Material = Prototype.Mesh.Faces[j].Material; Result.Mesh.Faces[j].Vertices = new World.MeshFaceVertex[Prototype.Mesh.Faces[j].Vertices.Length]; for (int k = 0; k < Prototype.Mesh.Faces[j].Vertices.Length; k++) { Result.Mesh.Faces[j].Vertices[k] = Prototype.Mesh.Faces[j].Vertices[k]; } } // materials Result.Mesh.Materials = new World.MeshMaterial[Prototype.Mesh.Materials.Length]; for (int j = 0; j < Prototype.Mesh.Materials.Length; j++) { Result.Mesh.Materials[j] = Prototype.Mesh.Materials[j]; if (DaytimeTexture != null) { Result.Mesh.Materials[j].DaytimeTexture = DaytimeTexture; } else { Result.Mesh.Materials[j].DaytimeTexture = Prototype.Mesh.Materials[j].DaytimeTexture; } if (DaytimeTexture != null) { Result.Mesh.Materials[j].NighttimeTexture = NighttimeTexture; } else { Result.Mesh.Materials[j].NighttimeTexture = Prototype.Mesh.Materials[j].NighttimeTexture; } } return Result; }
public override int CreateStaticObject(StaticObject Prototype, Transformation AuxTransformation, Matrix4D Rotate, Matrix4D Translate, double AccurateObjectDisposalZOffset, double StartingDistance, double EndingDistance, double TrackPosition, double Brightness) { return(Program.Renderer.CreateStaticObject(Prototype, AuxTransformation, Rotate, Translate, Program.CurrentRoute.AccurateObjectDisposal, AccurateObjectDisposalZOffset, StartingDistance, EndingDistance, Program.CurrentRoute.BlockLength, TrackPosition, Brightness)); }
// create dynamic object internal static int CreateDynamicObject() { int a = ObjectsUsed; if (a >= Objects.Length) { Array.Resize<StaticObject>(ref Objects, Objects.Length << 1); } Objects[a] = new StaticObject(); Objects[a].Mesh.Faces = new World.MeshFace[] { }; Objects[a].Mesh.Materials = new World.MeshMaterial[] { }; Objects[a].Mesh.Vertices = new World.Vertex[] { }; Objects[a].Dynamic = true; ObjectsUsed++; return a; }
/// <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); }
// create static object internal static int CreateStaticObject(StaticObject Prototype, Vector3 Position, World.Transformation BaseTransformation, World.Transformation AuxTransformation, bool AccurateObjectDisposal, double StartingDistance, double EndingDistance, double BlockLength, double TrackPosition) { return CreateStaticObject(Prototype, Position, BaseTransformation, AuxTransformation, AccurateObjectDisposal, 0.0, StartingDistance, EndingDistance, BlockLength, TrackPosition, 1.0, false); }
public static void createLaunchSite(StaticObject obj) { if (obj.settings.ContainsKey("LaunchSiteName") && obj.gameObject.transform.Find((string)obj.getSetting("LaunchPadTransform")) != null) { // Debug.Log("KK: Creating launch site " + obj.getSetting("LaunchSiteName")); obj.gameObject.transform.name = (string)obj.getSetting("LaunchSiteName"); obj.gameObject.name = (string)obj.getSetting("LaunchSiteName"); // Debug.Log("KK: Get CelBody"); CelestialBody CelBody = (CelestialBody)obj.getSetting("CelestialBody"); // Debug.Log("KK: CelBody is " + CelBody); var objectpos = CelBody.transform.InverseTransformPoint(obj.gameObject.transform.position); var dObjectLat = NavUtils.GetLatitude(objectpos); var dObjectLon = NavUtils.GetLongitude(objectpos); var disObjectLat = dObjectLat * 180 / Math.PI; var disObjectLon = dObjectLon * 180 / Math.PI; if (disObjectLon < 0) { disObjectLon = disObjectLon + 360; } // Debug.Log("KK: disObjectLat is " + disObjectLat); // Debug.Log("KK: disObjecton is " + disObjectLon); obj.setSetting("RefLatitude", (float)disObjectLat); obj.setSetting("RefLongitude", (float)disObjectLon); // Debug.Log("KK: RefLatitude and RefLongitude set"); foreach (FieldInfo fi in PSystemSetup.Instance.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance)) { if (fi.FieldType.Name == "SpaceCenterFacility[]") { PSystemSetup.SpaceCenterFacility[] facilities = (PSystemSetup.SpaceCenterFacility[])fi.GetValue(PSystemSetup.Instance); if (PSystemSetup.Instance.GetSpaceCenterFacility((string)obj.getSetting("LaunchSiteName")) == null) { PSystemSetup.SpaceCenterFacility newFacility = new PSystemSetup.SpaceCenterFacility(); newFacility.name = "FacilityName"; newFacility.facilityName = (string)obj.getSetting("LaunchSiteName"); newFacility.facilityPQS = ((CelestialBody)obj.getSetting("CelestialBody")).pqsController; newFacility.facilityTransformName = obj.gameObject.name; newFacility.pqsName = ((CelestialBody)obj.getSetting("CelestialBody")).pqsController.name; PSystemSetup.SpaceCenterFacility.SpawnPoint spawnPoint = new PSystemSetup.SpaceCenterFacility.SpawnPoint(); spawnPoint.name = (string)obj.getSetting("LaunchSiteName"); spawnPoint.spawnTransformURL = (string)obj.getSetting("LaunchPadTransform"); newFacility.spawnPoints = new PSystemSetup.SpaceCenterFacility.SpawnPoint[1]; newFacility.spawnPoints[0] = spawnPoint; PSystemSetup.SpaceCenterFacility[] newFacilities = new PSystemSetup.SpaceCenterFacility[facilities.Length + 1]; for (int i = 0; i < facilities.Length; ++i) { newFacilities[i] = facilities[i]; } newFacilities[newFacilities.Length - 1] = newFacility; fi.SetValue(PSystemSetup.Instance, newFacilities); facilities = newFacilities; bool RTEnabled = false; Texture logo = null; Texture icon = null; if (obj.settings.ContainsKey("LaunchSiteLogo")) { logo = GameDatabase.Instance.GetTexture(obj.model.path + "/" + obj.getSetting("LaunchSiteLogo"), false); } if (logo == null) { logo = defaultLaunchSiteLogo; } if (obj.settings.ContainsKey("LaunchSiteIcon")) { icon = GameDatabase.Instance.GetTexture(obj.model.path + "/" + obj.getSetting("LaunchSiteIcon"), false); } if (obj.settings.ContainsKey("RemoteTechGroundstation")) { RTEnabled = Convert.ToBoolean(obj.getSetting("RemoteTechGroundstation")); } // TODO This is still hard-code and needs to use the API properly // ASH 12112014 - Added career open close costs launchSites.Add(new LaunchSite((string)obj.getSetting("LaunchSiteName"), (obj.settings.ContainsKey("LaunchSiteAuthor")) ? (string)obj.getSetting("LaunchSiteAuthor") : (string)obj.model.getSetting("author"), (SiteType)obj.getSetting("LaunchSiteType"), logo, icon, (string)obj.getSetting("LaunchSiteDescription"), (string)obj.getSetting("Category"), (float)obj.getSetting("OpenCost"), (float)obj.getSetting("CloseValue"), "Closed", (float)obj.getSetting("RefLongitude"), (float)obj.getSetting("RefLatitude"), (float)obj.getSetting("RadiusOffset"), (obj.settings.ContainsKey("LaunchSiteLength")) ? (float)obj.getSetting("LaunchSiteLength") : (float)obj.model.getSetting("DefaultLaunchSiteLength"), (obj.settings.ContainsKey("LaunchSiteWidth")) ? (float)obj.getSetting("LaunchSiteWidth") : (float)obj.model.getSetting("DefaultLaunchSiteWidth"), (float)obj.getSetting("LaunchRefund"), (float)obj.getSetting("RecoveryFactor"), (float)obj.getSetting("RecoveryRange"), obj.gameObject, RTEnabled, newFacility )); // Debug.Log("KK: Created launch site \"" + newFacility.name + "\" with transform " + obj.getSetting("LaunchSiteName") + "/" + obj.getSetting("LaunchPadTransform")); } else { Debug.Log("KK: Launch site " + obj.getSetting("LaunchSiteName") + " already exists."); } } } MethodInfo updateSitesMI = PSystemSetup.Instance.GetType().GetMethod("SetupFacilities", BindingFlags.NonPublic | BindingFlags.Instance); if (updateSitesMI == null) { Debug.Log("KK: You are screwed. Failed to find SetupFacilities()."); } else { updateSitesMI.Invoke(PSystemSetup.Instance, null); } if (obj.gameObject != null) { CustomSpaceCenter.CreateFromLaunchsite((string)obj.getSetting("LaunchSiteName"), obj.gameObject); } } else { Debug.Log("KK: Launch pad transform \"" + obj.getSetting("LaunchPadTransform") + "\" missing for " + obj.getSetting("LaunchSiteName")); } }
public static void ReadLevelFile(string folderPath) { int rows = -1; int cols = -1; int[,] level; IndexPair playerPosition; int monstersCount = -1; EscapeRunner.View.MapLoader.Monster[] monsters; int bombsCount = -1; EscapeRunner.View.MapLoader.StaticObject[] bombs; int coinsCount = -1; EscapeRunner.View.MapLoader.StaticObject[] coins; int bulletsCount = -1; EscapeRunner.View.MapLoader.StaticObject[] bullets; StreamReader reader = new StreamReader(folderPath); /*string json = reader.ReadToEnd(); var things = JsonConvert.DeserializeObject(json, new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.None }); Wrapper wrapper = (Wrapper)things; Debugger.Break();*/ // read player position string line = reader.ReadLine(); if (line != null) { int[] points = Array.ConvertAll(line.Substring(24, (line.Length - 26)).Split(','), s => int.Parse(s)); playerPosition = new IndexPair(points[0], points[1]); MapLoader.PlayerStartLocation = playerPosition; } line = reader.ReadLine(); // read monsters count line = reader.ReadLine(); if (line != null) { monstersCount = Convert.ToInt32(line.Substring(20, (line.Length - 21))); } line = reader.ReadLine(); // read monsters locations if (monstersCount > 0) { line = reader.ReadLine(); monsters = new Monster[monstersCount]; int counter = 0; while ((line = reader.ReadLine()) != null) { if (counter < monstersCount) { line = line.Substring(2, (line.Length - 3)); if (counter != (monstersCount - 1)) line = line.Substring(0, (line.Length - 2)); int[] points = Array.ConvertAll(line.Split(','), s => int.Parse(s)); Point start = new Point(points[0], points[1]); Point end = new Point(points[2], points[3]); monsters[counter] = new Monster(start, end); counter++; } else { break; } } MapLoader.MonstersCount = monstersCount; MapLoader.Monsters = monsters; } line = reader.ReadLine(); // read bombs locations line = reader.ReadLine(); if (line != null) { bombsCount = Convert.ToInt32(line.Substring(17, (line.Length - 18))); } line = reader.ReadLine(); if (bombsCount > 0) { line = reader.ReadLine(); bombs = new StaticObject[bombsCount]; int counter = 0; while ((line = reader.ReadLine()) != null) { if (counter < bombsCount) { line = line.Substring(2, (line.Length - 3)); if (counter != (bombsCount - 1)) line = line.Substring(0, (line.Length - 2)); int[] points = Array.ConvertAll(line.Split(','), s => int.Parse(s)); Point start = new Point(points[0], points[1]); bombs[counter] = new StaticObject(start); counter++; } else { break; } } MapLoader.BombsCount = bombsCount; MapLoader.Bombs = bombs; } line = reader.ReadLine(); // read coins locations line = reader.ReadLine(); if (line != null) { coinsCount = Convert.ToInt32(line.Substring(17, (line.Length - 18))); } line = reader.ReadLine(); if (coinsCount > 0) { line = reader.ReadLine(); coins = new StaticObject[coinsCount]; int counter = 0; while ((line = reader.ReadLine()) != null) { if (counter < coinsCount) { line = line.Substring(2, (line.Length - 3)); if (counter != (coinsCount - 1)) line = line.Substring(0, (line.Length - 2)); int[] points = Array.ConvertAll(line.Split(','), s => int.Parse(s)); Point start = new Point(points[0], points[1]); coins[counter] = new StaticObject(start); counter++; } else { break; } } MapLoader.CoinsCount = coinsCount; MapLoader.Coins = coins; } line = reader.ReadLine(); // read bullets locations line = reader.ReadLine(); if (line != null) { bulletsCount = Convert.ToInt32(line.Substring(19, (line.Length - 20))); } line = reader.ReadLine(); if (coinsCount > 0) { line = reader.ReadLine(); bullets = new StaticObject[bulletsCount]; int counter = 0; while ((line = reader.ReadLine()) != null) { if (counter < bulletsCount) { line = line.Substring(2, (line.Length - 3)); if (counter != (bulletsCount - 1)) line = line.Substring(0, (line.Length - 2)); int[] points = Array.ConvertAll(line.Split(','), s => int.Parse(s)); Point start = new Point(points[0], points[1]); bullets[counter] = new StaticObject(start); counter++; } else { break; } } MapLoader.BulletsCount = bulletsCount; MapLoader.Bullets = bullets; } line = reader.ReadLine(); // read map dimensions line = reader.ReadLine(); if (line != null) { cols = Convert.ToInt32(line.Substring(10, (line.Length - 11))); } line = reader.ReadLine(); if (line != null) { rows = Convert.ToInt32(line.Substring(10, (line.Length - 11))); } // read level if (rows > 0 && cols > 0) { line = reader.ReadLine(); line = reader.ReadLine(); level = new int[rows, cols]; int counter = 0; while ((line = reader.ReadLine()) != null) { if (counter < rows) { line = line.Substring(2, (line.Length - 3)); if (counter != (rows - 1)) line = line.Substring(0, (line.Length - 2)); int counter2 = 0; string[] lines = line.Split(','); foreach (var item in lines) { if (counter2 < cols) level[counter, counter2++] = int.Parse(item); } counter++; //level[counter++] = Array.ConvertAll(line.Split(','), s => int.Parse(s)); } else { break; } } MapLoader.level = level; } reader.Close(); }