private void LoadVisgroups(MapFile map, SerialisedObject so) { var vis = new Visgroup(); LoadVisgroupsRecursive(so, vis); map.Visgroups.AddRange(vis.Children); }
private void LoadVisgroups(Map map, SerialisedObject visgroups) { if (visgroups == null) { return; } foreach (var vg in visgroups.Children.Where(x => x.Name?.ToLower() == "visgroup")) { var v = new Visgroup { Name = vg.Get("name", ""), ID = vg.Get("visgroupid", -1), Colour = vg.GetColor("color"), Visible = true }; if (v.Colour.GetBrightness() < 0.001f) { v.Colour = Colour.GetRandomBrushColour(); } if (v.ID < 0) { continue; } map.Data.Add(v); } }
private void ReadVisgroups(Map map, BinaryReader br) { var list = new List <Visgroup>(); var numVisgroups = br.ReadInt32(); for (var i = 0; i < numVisgroups; i++) { var vis = new Visgroup { Name = br.ReadFixedLengthString(Encoding.ASCII, 128), Colour = br.ReadRGBAColour(), ID = br.ReadInt32(), Visible = br.ReadBoolean() }; vis.Colour = Color.FromArgb(255, vis.Colour); map.NumberGenerator.Seed("Visgroup", vis.ID); br.ReadBytes(3); list.Add(vis); } // Get rid of zero groups foreach (var vg in list.Where(x => x.ID == 0)) { vg.ID = map.NumberGenerator.Next("Visgroup"); } map.Data.AddRange(list); }
private void AddNode(TreeNode parent, Visgroup visgroup, Func <Visgroup, string> getCheckState) { if (!ShowHidden && visgroup is AutoVisgroup && ((AutoVisgroup)visgroup).IsHidden) { return; } if (HideAutomatic && visgroup.IsAutomatic) { return; } var node = new TreeNode(visgroup.Name) { StateImageKey = getCheckState(visgroup) + (DisableAutomatic && visgroup.IsAutomatic ? "Disabled" : ""), BackColor = visgroup.Colour, Tag = visgroup.ID }; if (parent == null) { VisgroupTree.Nodes.Add(node); } else { parent.Nodes.Add(node); } foreach (var vg in Sort(visgroup.Children)) { AddNode(node, vg, getCheckState); } }
private static IEnumerable <Visgroup> ReadVisgroups(BinaryReader br) { var list = new List <Visgroup>(); var numVisgroups = br.ReadInt32(); for (var i = 0; i < numVisgroups; i++) { var vis = new Visgroup { Name = br.ReadFixedLengthString(Encoding.UTF8, 128), Colour = br.ReadRGBAColour(), ID = br.ReadInt32(), Visible = br.ReadBoolean() }; vis.Colour = Color.FromArgb(255, vis.Colour); br.ReadBytes(3); list.Add(vis); } // Get rid of zero groups foreach (var vg in list.Where(x => x.ID == 0)) { vg.ID = list.Max(x => x.ID) + 1; } return(list); }
public void VisgroupCreateNew() { using (var qf = new QuickForm("Create New Visgroup") { UseShortcutKeys = true }.TextBox("Name").CheckBox("Add selection to visgroup", true).OkCancel()) { if (qf.ShowDialog() != DialogResult.OK) { return; } var ids = _document.Map.Visgroups.Where(x => !x.IsAutomatic).Select(x => x.ID).ToList(); var id = Math.Max(1, ids.Any() ? ids.Max() + 1 : 1); var name = qf.String("Name"); if (String.IsNullOrWhiteSpace(name)) { name = "Visgroup " + id.ToString(); } var vg = new Visgroup { ID = id, Colour = Colour.GetRandomLightColour(), Name = name, Visible = true }; IAction action = new CreateEditDeleteVisgroups(new[] { vg }, new Visgroup[0], new Visgroup[0]); if (qf.Bool("Add selection to visgroup") && !_document.Selection.IsEmpty()) { action = new ActionCollection(action, new EditObjectVisgroups(_document.Selection.GetSelectedObjects(), new[] { id }, new int[0])); } _document.PerformAction("Create visgroup", action); } }
private static GenericStructure WriteVisgroup(Visgroup visgroup) { var ret = new GenericStructure("visgroup"); ret["name"] = visgroup.Name; ret["visgroupid"] = visgroup.ID.ToString(CultureInfo.InvariantCulture); ret["color"] = FormatColor(visgroup.Colour); return(ret); }
private static Visgroup ReadVisgroup(GenericStructure visgroup) { var v = new Visgroup { Name = visgroup["name"], ID = visgroup.PropertyInteger("visgroupid"), Colour = visgroup.PropertyColour("color", Colour.GetRandomBrushColour()), Visible = true }; return(v); }
private void LoadVisgroupsRecursive(SerialisedObject so, Visgroup parent) { foreach (var vg in so.Children.Where(x => string.Equals(x.Name, "visgroup", StringComparison.InvariantCultureIgnoreCase))) { var v = new Visgroup { Name = vg.Get("name", ""), ID = vg.Get("visgroupid", -1), Color = vg.GetColor("color"), Visible = true }; LoadVisgroupsRecursive(vg, v); parent.Children.Add(v); } }
static void ReadVisgroups(MapFile map, BinaryReader br) { int numVisgroups = br.ReadInt32(); for (int i = 0; i < numVisgroups; i++) { Visgroup vis = new Visgroup { Name = ReadString(br), ID = br.ReadInt32(), Color = br.ReadRGBAColour(), Visible = br.ReadBoolean() }; map.Visgroups.Add(vis); } }
private void AddGroup(object sender, EventArgs e) { var newGroup = new Visgroup { ID = GetNewID(), Colour = Colour.GetRandomLightColour(), Name = "New Group", Visible = true }; _visgroups.Add(newGroup); UpdateVisgroups(); VisgroupPanel.SetSelectedVisgroup(newGroup.ID); GroupName.SelectAll(); GroupName.Focus(); }
static void ReadVisgroups(MapFile map, BinaryReader br) { int numVisgroups = br.ReadInt32(); for (int i = 0; i < numVisgroups; i++) { Visgroup vis = new Visgroup { Name = br.ReadFixedLengthString(Encoding.ASCII, 128), Color = br.ReadRGBAColour(), ID = br.ReadInt32(), Visible = br.ReadBoolean() }; br.ReadBytes(3); map.Visgroups.Add(vis); } }
private static IEnumerable <Visgroup> ReadVisgroups(BinaryReader br) { var numVisgroups = br.ReadInt32(); for (var i = 0; i < numVisgroups; i++) { var vis = new Visgroup { Name = br.ReadFixedLengthString(Encoding.UTF8, 128), Colour = br.ReadRGBAColour(), ID = br.ReadInt32(), Visible = br.ReadBoolean() }; vis.Colour = Color.FromArgb(255, vis.Colour); br.ReadBytes(3); yield return(vis); } }
protected override DataStructures.MapObjects.Map GetFromStream(Stream stream, IEnumerable <string> modelDirs, out Image[] lightmaps) { lightmaps = null; var map = new DataStructures.MapObjects.Map(); map.CordonBounds = new Box(Coordinate.One * -16384, Coordinate.One * 16384); BinaryReader br = new BinaryReader(stream); //header UInt16 mapVersion = br.ReadUInt16(); byte mapFlags = br.ReadByte(); Int32 nameCount = br.ReadInt32(); Int32 nameOffset = br.ReadInt32(); Int32 objectCount = br.ReadInt32(); Int32 objectOffset = br.ReadInt32(); //get names, needed to understand the objects List <string> names = new List <string>(); br.BaseStream.Seek(nameOffset, SeekOrigin.Begin); for (int i = 0; i < nameCount; i++) { string name = br.ReadNullTerminatedString(); names.Add(name); } //now we can parse the object table List <string> materials = new List <string>(); List <Tuple <int, string> > meshReferences = new List <Tuple <int, string> >(); Dictionary <int, Group> groups = new Dictionary <int, Group>(); Dictionary <int, int> visgroups = new Dictionary <int, int>(); br.BaseStream.Seek(objectOffset, SeekOrigin.Begin); long objectStartPos = br.BaseStream.Position; for (int i = 0; i < objectCount; i++) { int index = br.ReadInt32() - 1; int size = br.ReadInt32(); string name = null; if (index >= 0 && index < names.Count) { name = names[index]; } if (name == "group") { byte flags = br.ReadByte(); Int32 groupIndex = br.ReadInt32(); Group newGroup = new Group(map.IDGenerator.GetNextObjectID()); newGroup.SetParent(map.WorldSpawn); groups.Add(i, newGroup); } else if (name == "visgroup") { byte flags = br.ReadByte(); string groupName = names[br.ReadInt32() - 1]; byte colorR = br.ReadByte(); byte colorG = br.ReadByte(); byte colorB = br.ReadByte(); Visgroup newGroup = new Visgroup() { Name = groupName, ID = visgroups.Count + 1 }; newGroup.Colour = System.Drawing.Color.FromArgb(colorR, colorG, colorB); map.Visgroups.Add(newGroup); visgroups.Add(i, newGroup.ID); } else if (name == "meshreference") { byte flags = br.ReadByte(); Int32 groupNameInd = br.ReadInt32() - 1; Int32 objectNameInd = br.ReadInt32() - 1; byte limbCount = br.ReadByte(); meshReferences.Add(new Tuple <int, string>(i, names[objectNameInd])); } else if (name == "material") { byte materialFlags = br.ReadByte(); Int32 groupIndex = br.ReadInt32(); string objectName = names[br.ReadInt32() - 1]; Int32 extensionNameIndex = -1; if ((materialFlags & 2) != 0) { extensionNameIndex = br.ReadInt32(); //TODO: what the heck is this } materials.Add(objectName); } else { br.BaseStream.Seek(size, SeekOrigin.Current); } } br.BaseStream.Position = objectStartPos; for (int i = 0; i < objectCount; i++) { int index = br.ReadInt32() - 1; int size = br.ReadInt32(); string name = null; if (index >= 0 && index < names.Count) { name = names[index]; } if (name == "mesh") { Property newProperty; long startPos = br.BaseStream.Position; byte flags = br.ReadByte(); Entity entity = new Entity(map.IDGenerator.GetNextObjectID()); entity.ClassName = "model"; entity.EntityData.Name = "model"; entity.Colour = Colour.GetDefaultEntityColour(); Int32 keyCount = br.ReadInt32(); for (int j = 0; j < keyCount; j++) { Int32 keyNameInd = br.ReadInt32() - 1; Int32 keyValueInd = br.ReadInt32() - 1; if (names[keyNameInd] != "classname") { newProperty = new Property(); newProperty.Key = names[keyNameInd]; newProperty.Value = names[keyValueInd]; if (newProperty.Key == "file") { newProperty.Value = System.IO.Path.GetFileNameWithoutExtension(newProperty.Value); } entity.EntityData.Properties.Add(newProperty); } } Int32 groupIndex = br.ReadInt32() - 1; Int32 visgroupIndex = br.ReadInt32() - 1; if (visgroups.ContainsKey(visgroupIndex)) { entity.Visgroups.Add(visgroups[visgroupIndex]); } byte red = br.ReadByte(); byte green = br.ReadByte(); byte blue = br.ReadByte(); Int32 meshRefIndex = br.ReadInt32() - 1; float x = br.ReadSingle(); float z = br.ReadSingle(); float y = br.ReadSingle(); if (entity != null) { entity.Origin = new Coordinate((decimal)x, (decimal)y, (decimal)z); } if (entity.EntityData.GetPropertyValue("file") == null) { newProperty = new Property(); newProperty.Key = "file"; newProperty.Value = meshReferences.Find(q => q.Item1 == meshRefIndex).Item2; entity.EntityData.Properties.Add(newProperty); } float pitch = br.ReadSingle(); float yaw = br.ReadSingle(); float roll = br.ReadSingle(); newProperty = new Property(); newProperty.Key = "angles"; newProperty.Value = pitch.ToString() + " " + yaw.ToString() + " " + roll.ToString(); entity.EntityData.Properties.Add(newProperty); float xScale = 1.0f; float yScale = 1.0f; float zScale = 1.0f; if ((flags & 1) == 0) { xScale = br.ReadSingle(); yScale = br.ReadSingle(); zScale = br.ReadSingle(); } newProperty = new Property(); newProperty.Key = "scale"; newProperty.Value = xScale.ToString() + " " + yScale.ToString() + " " + zScale.ToString(); entity.EntityData.Properties.Add(newProperty); br.BaseStream.Position += size - (br.BaseStream.Position - startPos); entity.UpdateBoundingBox(); if (groups.ContainsKey(groupIndex)) { entity.SetParent(groups[groupIndex]); } else { entity.SetParent(map.WorldSpawn); } } else if (name == "entity") { byte flags = br.ReadByte(); float x = br.ReadSingle(); float z = br.ReadSingle(); float y = br.ReadSingle(); Entity entity = new Entity(map.IDGenerator.GetNextObjectID()); entity.Colour = Colour.GetDefaultEntityColour(); entity.Origin = new Coordinate((decimal)x, (decimal)y, (decimal)z); Int32 keyCount = br.ReadInt32(); for (int j = 0; j < keyCount; j++) { Int32 keyNameInd = br.ReadInt32() - 1; Int32 keyValueInd = br.ReadInt32() - 1; if (names[keyNameInd] == "classname") { entity.ClassName = names[keyValueInd]; entity.EntityData.Name = names[keyValueInd]; } else { Property newProperty = new Property(); newProperty.Key = names[keyNameInd]; newProperty.Value = names[keyValueInd]; entity.EntityData.Properties.Add(newProperty); } } Int32 groupIndex = br.ReadInt32() - 1; Int32 visgroupIndex = br.ReadInt32() - 1; if (visgroups.ContainsKey(visgroupIndex)) { entity.Visgroups.Add(visgroups[visgroupIndex]); } entity.UpdateBoundingBox(); if (groups.ContainsKey(groupIndex)) { entity.SetParent(groups[groupIndex]); } else { entity.SetParent(map.WorldSpawn); } } else if (name == "brush") { bool invisibleCollision = false; byte brushFlags = br.ReadByte(); //TODO: ??? Int32 keys = br.ReadInt32(); for (int j = 0; j < keys; j++) { Int32 keyNameInd = br.ReadInt32(); Int32 keyValueInd = br.ReadInt32(); string keyName = names[keyNameInd - 1]; if (keyName.Equals("classname", StringComparison.OrdinalIgnoreCase)) { string keyValue = names[keyValueInd - 1]; if (keyValue.Equals("field_hit", StringComparison.OrdinalIgnoreCase)) { invisibleCollision = true; } } } Int32 groupIndex = br.ReadInt32() - 1; Int32 visgroupIndex = br.ReadInt32() - 1; byte red = br.ReadByte(); byte green = br.ReadByte(); byte blue = br.ReadByte(); List <Coordinate> vertices = new List <Coordinate>(); byte vertexCount = br.ReadByte(); for (int j = 0; j < vertexCount; j++) { decimal x = (decimal)br.ReadSingle(); decimal z = (decimal)br.ReadSingle(); decimal y = (decimal)br.ReadSingle(); vertices.Add(new Coordinate(x, y, z)); } List <Face> faces = new List <Face>(); byte faceCount = br.ReadByte(); for (int j = 0; j < faceCount; j++) { byte faceFlags = br.ReadByte(); //TODO: maybe we need these unused bits for something idk decimal planeEq0 = (decimal)br.ReadSingle(); decimal planeEq1 = (decimal)br.ReadSingle(); decimal planeEq2 = (decimal)br.ReadSingle(); decimal planeEq3 = (decimal)br.ReadSingle(); decimal texPosX = (decimal)br.ReadSingle(); decimal texPosY = (decimal)br.ReadSingle(); decimal texScaleX = (decimal)br.ReadSingle(); decimal texScaleY = (decimal)br.ReadSingle(); float texRotX = br.ReadSingle(); float texRotY = br.ReadSingle(); decimal uTexPlane0 = (decimal)br.ReadSingle(); decimal uTexPlane1 = (decimal)br.ReadSingle(); decimal uTexPlane2 = (decimal)br.ReadSingle(); decimal uTexPlane3 = (decimal)br.ReadSingle(); decimal vTexPlane0 = (decimal)br.ReadSingle(); decimal vTexPlane1 = (decimal)br.ReadSingle(); decimal vTexPlane2 = (decimal)br.ReadSingle(); decimal vTexPlane3 = (decimal)br.ReadSingle(); float luxelSize = br.ReadSingle(); Int32 smoothGroupInd = br.ReadInt32(); Int32 materialInd = br.ReadInt32() - 1; Int32 lightmapInd = -1; if ((faceFlags & 16) != 0) { lightmapInd = br.ReadInt32(); } byte indexCount = br.ReadByte(); List <byte> vertsInFace = new List <byte>(); for (int k = 0; k < indexCount; k++) { byte vertIndex = br.ReadByte(); vertsInFace.Add(vertIndex); float texCoordX = br.ReadSingle(); float texCoordY = br.ReadSingle(); float lmCoordX = 0.0f; float lmCoordY = 0.0f; if ((faceFlags & 16) != 0) { lmCoordX = br.ReadSingle(); lmCoordY = br.ReadSingle(); } } Coordinate norm = new Coordinate(planeEq0, planeEq2, planeEq1); if (Math.Abs((float)norm.LengthSquared()) > 0.001f) { if (Math.Abs((double)norm.LengthSquared() - 1) > 0.001) { throw new Exception(norm.LengthSquared().ToString()); } Face newFace = new Face(map.IDGenerator.GetNextFaceID()); foreach (byte vertInd in vertsInFace) { newFace.Vertices.Insert(0, new Vertex(vertices[vertInd], newFace)); } newFace.Plane = new Plane(newFace.Vertices[0].Location, newFace.Vertices[1].Location, newFace.Vertices[2].Location); newFace.UpdateBoundingBox(); Coordinate uNorm = new Coordinate(uTexPlane0, uTexPlane2, uTexPlane1).Normalise(); Coordinate vNorm = new Coordinate(vTexPlane0, vTexPlane2, vTexPlane1).Normalise(); if (Math.Abs((double)(uNorm.LengthSquared() - vNorm.LengthSquared())) > 0.001) { throw new Exception(uNorm.LengthSquared().ToString() + " " + vNorm.LengthSquared().ToString()); } newFace.Texture.Name = (faceFlags & 4) != 0 ? "tooltextures/remove_face" : invisibleCollision ? "tooltextures/invisible_collision" : materials[materialInd]; newFace.AlignTextureToWorld(); newFace.Texture.UAxis = uNorm * (decimal)Math.Cos(-texRotX * Math.PI / 180.0) + vNorm * (decimal)Math.Sin(-texRotX * Math.PI / 180.0); newFace.Texture.VAxis = vNorm * (decimal)Math.Cos(-texRotX * Math.PI / 180.0) - uNorm * (decimal)Math.Sin(-texRotX * Math.PI / 180.0); //huh????? if (Math.Abs(texScaleX) < 0.0001m) { if (Math.Abs(texScaleY) < 0.0001m) { texScaleX = 1m; texScaleY = 1m; } else { texScaleX = texScaleY; } } else if (Math.Abs(texScaleY) < 0.0001m) { texScaleY = texScaleX; } newFace.Texture.XScale = texScaleX / 2; newFace.Texture.YScale = texScaleY / 2; newFace.Texture.XShift = -texPosX * 2 / texScaleX; newFace.Texture.YShift = texPosY * 2 / texScaleY; newFace.Texture.Rotation = (decimal)texRotX; //seriously, what the F**K??????????? if ((texRotX - texRotY) > 120.0f) { newFace.Texture.XScale *= -1m; newFace.Texture.YScale *= -1m; newFace.Texture.Rotation -= 180m; newFace.Texture.UAxis = -newFace.Texture.UAxis; } else if ((texRotY - texRotX) > 120.0f) { newFace.Texture.XScale *= -1m; newFace.Texture.YScale *= -1m; newFace.Texture.Rotation -= 180m; newFace.Texture.VAxis = -newFace.Texture.VAxis; } newFace.Transform(new UnitScale(Coordinate.One, newFace.BoundingBox.Center), TransformFlags.None); faces.Add(newFace); } } Solid newSolid = new Solid(map.IDGenerator.GetNextObjectID()); foreach (Face face in faces) { face.Parent = newSolid; newSolid.Faces.Add(face); } if (visgroups.ContainsKey(visgroupIndex)) { newSolid.Visgroups.Add(visgroups[visgroupIndex]); } newSolid.Colour = Colour.GetRandomBrushColour(); newSolid.UpdateBoundingBox(); MapObject parent = map.WorldSpawn; if (groups.ContainsKey(groupIndex)) { parent = groups[groupIndex]; } if (newSolid.IsValid()) { newSolid.SetParent(parent); newSolid.Transform(new UnitScale(Coordinate.One, newSolid.BoundingBox.Center), TransformFlags.None); } else { var offset = newSolid.BoundingBox.Center; // Not a valid solid, decompose into tetrahedrons/etc foreach (var face in faces) { var polygon = new Polygon(face.Vertices.Select(x => x.Location)); if (!polygon.IsValid() || !polygon.IsConvex()) { // tetrahedrons foreach (var triangle in face.GetTrianglesReversed()) { var tf = new Face(map.IDGenerator.GetNextFaceID()); tf.Plane = new Plane(triangle[0].Location, triangle[1].Location, triangle[2].Location); tf.Vertices.AddRange(triangle.Select(x => new Vertex(x.Location, tf))); tf.Texture = face.Texture.Clone(); tf.UpdateBoundingBox(); newSolid = SolidifyFace(map, tf, offset); newSolid.SetParent(parent); newSolid.UpdateBoundingBox(); newSolid.Transform(new UnitScale(Coordinate.One, newSolid.BoundingBox.Center), TransformFlags.None); } } else { // cone/pyramid/whatever newSolid = SolidifyFace(map, face, offset); newSolid.SetParent(parent); newSolid.UpdateBoundingBox(); newSolid.Transform(new UnitScale(Coordinate.One, newSolid.BoundingBox.Center), TransformFlags.None); } } } } else { if (name == "terrain") { MapProvider.warnings = "This map contains displacements, which are currently not supported. The map will appear incomplete."; } br.BaseStream.Seek(size, SeekOrigin.Current); } } return(map); }
protected override DataStructures.MapObjects.Map GetFromStream(Stream stream, IEnumerable <string> modelDirs, out Image[] lightmaps) { BinaryReader reader = new BinaryReader(stream); if (reader.ReadFixedLengthString(Encoding.ASCII, 3) != "CBR") { throw new ProviderException("CBR file is corrupted/invalid!"); } uint revision = reader.ReadUInt32(); // Lightmaps bool lightmapped = reader.ReadByte() > (byte)Lightmapped.No; if (lightmapped) { lightmaps = new Image[4]; for (int i = 0; i < 4; i++) { lightmaps[i] = Image.FromStream(new MemoryStream(reader.ReadBytes(reader.ReadInt32()))); } } else { lightmaps = null; } // Texture dictionary int texSize = reader.ReadInt32(); string[] textures = new string[texSize]; for (int i = 0; i < texSize; i++) { textures[i] = reader.ReadNullTerminatedString(); } DataStructures.MapObjects.Map map = new DataStructures.MapObjects.Map(); map.WorldSpawn = new World(map.IDGenerator.GetNextObjectID()); // Solids List <MapObject> solids = new List <MapObject>(); int solidCount = reader.ReadInt32(); for (int i = 0; i < solidCount; i++) { Solid s = new Solid(map.IDGenerator.GetNextObjectID()); s.Colour = Colour.GetRandomBrushColour(); int faceCount = reader.ReadInt32(); for (int j = 0; j < faceCount; j++) { Face f = new Face(map.IDGenerator.GetNextFaceID()); f.Colour = s.Colour; f.Texture.Name = textures[reader.ReadInt32()]; f.Texture.UAxis = reader.ReadCoordinate(); f.Texture.VAxis = reader.ReadCoordinate(); f.Texture.XShift = reader.ReadDecimal(); f.Texture.YShift = reader.ReadDecimal(); f.Texture.XScale = reader.ReadDecimal(); f.Texture.YScale = reader.ReadDecimal(); f.Texture.Rotation = reader.ReadDecimal(); int vertexCount = reader.ReadInt32(); for (int k = 0; k < vertexCount; k++) { Vertex v = new Vertex(reader.ReadCoordinate(), f); if (lightmapped) { v.LMU = reader.ReadSingle(); v.LMV = reader.ReadSingle(); v.TextureU = (decimal)reader.ReadSingle(); v.TextureV = (decimal)reader.ReadSingle(); } f.Vertices.Add(v); } f.Plane = new Plane(f.Vertices[0].Location, f.Vertices[1].Location, f.Vertices[2].Location); f.Parent = s; s.Faces.Add(f); f.UpdateBoundingBox(); } s.SetParent(map.WorldSpawn, false); s.UpdateBoundingBox(false); solids.Add(s); } // Entities List <MapObject> entities = new List <MapObject>(0); string read; bool isStillSolid = true; for (int i = 0; i < 2; i++) { while ((read = reader.ReadNullTerminatedString()) != "") { List <Property> properties = new List <Property>(); byte propertyType; while ((propertyType = reader.ReadByte()) != 255) { properties.Add(new Property() { name = reader.ReadNullTerminatedString(), type = (VariableType)propertyType }); } // Entries int entitiesOfType = reader.ReadInt32(); entities.Capacity += entitiesOfType; for (int j = 0; j < entitiesOfType; j++) { Entity e = new Entity(map.IDGenerator.GetNextObjectID()); e.Colour = Colour.GetDefaultEntityColour(); e.ClassName = read; e.EntityData.Name = read; if (isStillSolid) { int entitySolids = reader.ReadInt32(); for (int k = 0; k < entitySolids; k++) { solids[reader.ReadInt32()].SetParent(e); } } e.SetParent(map.WorldSpawn); foreach (Property property in properties) { string propertyVal; switch (property.type) { case VariableType.Bool: propertyVal = reader.ReadBoolean() ? "Yes" : "No"; break; case VariableType.Color255: propertyVal = DataStructures.MapObjects.Property.FromColor(reader.ReadRGBAColour()); break; case VariableType.Float: propertyVal = reader.ReadSingle().ToString(); break; case VariableType.Integer: propertyVal = reader.ReadInt32().ToString(); break; case VariableType.String: propertyVal = reader.ReadNullTerminatedString(); break; case VariableType.Vector: propertyVal = DataStructures.MapObjects.Property.FromCoordinate(reader.ReadCoordinate()); break; case VariableType.Choices: // TODO: Bullshit throw new NotImplementedException(); default: propertyVal = ""; break; } e.EntityData.SetPropertyValue(property.name, propertyVal); } e.UpdateBoundingBox(); entities.Add(e); } } isStillSolid = false; } // CBRE ONLY // Visgroup dictionary Visgroup currentParentVisgroup = null; while (true) { byte hierarchyControl; Visgroup newGroup = null; while ((hierarchyControl = reader.ReadByte()) == HIERARCHY_PROCCEED) { newGroup = new Visgroup(); newGroup.Colour = Colour.GetRandomBrushColour(); newGroup.ID = reader.ReadInt32(); newGroup.Name = reader.ReadNullTerminatedString(); if (currentParentVisgroup != null) { newGroup.Parent = currentParentVisgroup; currentParentVisgroup.Children.Add(newGroup); } else { map.Visgroups.Add(newGroup); } } if (hierarchyControl == HIERARCHY_DOWN) { currentParentVisgroup = newGroup; } else if (currentParentVisgroup != null) { currentParentVisgroup = currentParentVisgroup.Parent; } else { break; } } // Solid visgroups foreach (Solid mo in solids) { ReadVisgroups(reader, mo); } // Entity visgroups foreach (Entity e in entities) { ReadVisgroups(reader, e); } // Groups int directWorldGroups = reader.ReadInt32(); for (int i = 0; i < directWorldGroups; i++) { Group currentParentGroup = new Group(map.IDGenerator.GetNextObjectID()); currentParentGroup.SetParent(map.WorldSpawn); while (true) { byte hierarchyControl; while ((hierarchyControl = reader.ReadByte()) > HIERARCHY_UP) { if (hierarchyControl == IDENTIFIER_ENTITY) { entities[reader.ReadInt32()].SetParent(currentParentGroup); } else { solids[reader.ReadInt32()].SetParent(currentParentGroup); } } if (hierarchyControl == HIERARCHY_DOWN) { Group newGroup = new Group(map.IDGenerator.GetNextObjectID()); newGroup.SetParent(currentParentGroup); currentParentGroup = newGroup; } else if (currentParentGroup.Parent != map.WorldSpawn) { currentParentGroup = (Group)currentParentGroup.Parent; } else { break; } } } stream.Close(); return(map); }