public static DataStructures.GameData.GameData GetGameDataFromFiles(IEnumerable<string> files) { var gd = new DataStructures.GameData.GameData(); foreach (var d in files.Select(GetGameDataFromFile)) { gd.MapSizeHigh = d.MapSizeHigh; gd.MapSizeLow = d.MapSizeLow; gd.Classes.AddRange(d.Classes); } gd.CreateDependencies(); return gd; }
public static DataStructures.GameData.GameData GetGameDataFromFiles(IEnumerable <string> files) { var gd = new DataStructures.GameData.GameData(); foreach (var d in files.Select(GetGameDataFromFile)) { gd.MapSizeHigh = d.MapSizeHigh; gd.MapSizeLow = d.MapSizeLow; gd.Classes.AddRange(d.Classes); gd.MaterialExclusions.AddRange(d.MaterialExclusions); } gd.CreateDependencies(); gd.RemoveDuplicates(); return(gd); }
private DataStructures.GameData.GameData Parse(IEnumerable <LexObject> lex) { var gd = new DataStructures.GameData.GameData(); var iterator = lex.GetEnumerator(); while (true) { if (!iterator.MoveNext()) { break; } if (iterator.Current.Type == LexType.At) { ParseAt(gd, iterator); } } return(gd); }
public DataStructures.GameData.GameData GetGameDataFromFiles(IEnumerable <string> files) { var gd = new DataStructures.GameData.GameData(); foreach (var f in files.Where(IsValidForFile)) { var provider = new FgdProvider(); var d = provider.OpenFile(f); gd.MapSizeHigh = d.MapSizeHigh; gd.MapSizeLow = d.MapSizeLow; gd.Classes.AddRange(d.Classes); gd.MaterialExclusions.AddRange(d.MaterialExclusions); } gd.CreateDependencies(); gd.RemoveDuplicates(); return(gd); }
protected abstract void SaveToStream(Stream stream, DataStructures.MapObjects.Map map, DataStructures.GameData.GameData gameData, TextureCollection textureCollection);
protected virtual void SaveToFile(string filename, DataStructures.MapObjects.Map map, DataStructures.GameData.GameData gameData, TextureCollection textureCollection) { using (var strm = new FileStream(filename, FileMode.Create, FileAccess.Write)) { SaveToStream(strm, map, gameData, textureCollection); } }
public static void SaveMapToFile(string filename, DataStructures.MapObjects.Map map, DataStructures.GameData.GameData gameData, TextureCollection textureCollection = null) { var provider = RegisteredProviders.FirstOrDefault(p => p.IsValidForFileName(filename)); if (provider != null) { provider.SaveToFile(filename, map, gameData, textureCollection); return; } throw new ProviderNotFoundException("No map provider was found for this file format."); }
private void ParseAt(DataStructures.GameData.GameData gd, IEnumerator <LexObject> iterator) { iterator.MoveNext(); var type = iterator.Current.Value; if (type.Equals("include", StringComparison.InvariantCultureIgnoreCase)) { Expect(iterator, LexType.String); if (CurrentFile != null) { var filename = iterator.Current.GetValue(); var path = Path.GetDirectoryName(CurrentFile) ?? ""; var incfile = Path.Combine(path, filename); var current = CurrentFile; var incgd = GetGameDataFromFile(incfile); CurrentFile = current; if (!gd.Includes.Any(x => String.Equals(x, filename, StringComparison.InvariantCultureIgnoreCase))) { gd.Includes.Add(filename); } // Merge the included gamedata into the current one gd.MapSizeHigh = Math.Max(incgd.MapSizeHigh, gd.MapSizeHigh); gd.MapSizeLow = Math.Min(incgd.MapSizeLow, gd.MapSizeLow); gd.Includes.AddRange(incgd.Includes.Where(x => !gd.Includes.Contains(x))); gd.Classes.AddRange(incgd.Classes.Where(x => !gd.Classes.Any(y => String.Equals(x.Name, y.Name, StringComparison.InvariantCultureIgnoreCase)))); gd.AutoVisgroups.AddRange(incgd.AutoVisgroups.Where(x => !gd.AutoVisgroups.Any(y => String.Equals(x.Name, y.Name, StringComparison.InvariantCultureIgnoreCase)))); gd.MaterialExclusions.AddRange(incgd.MaterialExclusions.Where(x => !gd.MaterialExclusions.Any(y => String.Equals(x, y, StringComparison.InvariantCultureIgnoreCase)))); } else { throw new ProviderException("Unable to include a file when not reading from a file."); } } else if (type.Equals("mapsize", StringComparison.InvariantCultureIgnoreCase)) { Expect(iterator, LexType.OpenParen); Expect(iterator, LexType.Value); gd.MapSizeLow = Int32.Parse(iterator.Current.Value); Expect(iterator, LexType.Comma); Expect(iterator, LexType.Value); gd.MapSizeHigh = Int32.Parse(iterator.Current.Value); Expect(iterator, LexType.CloseParen); } else if (type.Equals("materialexclusion", StringComparison.InvariantCultureIgnoreCase)) { Expect(iterator, LexType.OpenBracket); iterator.MoveNext(); while (iterator.Current.Type != LexType.CloseBracket) { Assert(iterator.Current, iterator.Current.IsValueOrString(), "Expected value type, got " + iterator.Current.Type + "."); var exclusion = iterator.Current.GetValue(); gd.MaterialExclusions.Add(exclusion); iterator.MoveNext(); } } else if (type.Equals("autovisgroup", StringComparison.InvariantCultureIgnoreCase)) { Expect(iterator, LexType.Equals); iterator.MoveNext(); Assert(iterator.Current, iterator.Current.IsValueOrString(), "Expected value type, got " + iterator.Current.Type + "."); var sectionName = iterator.Current.GetValue(); var sect = new AutoVisgroupSection { Name = sectionName }; Expect(iterator, LexType.OpenBracket); iterator.MoveNext(); while (iterator.Current.Type != LexType.CloseBracket) { Assert(iterator.Current, iterator.Current.IsValueOrString(), "Expected value type, got " + iterator.Current.Type + "."); var groupName = iterator.Current.GetValue(); var grp = new AutoVisgroup { Name = groupName }; Expect(iterator, LexType.OpenBracket); iterator.MoveNext(); while (iterator.Current.Type != LexType.CloseBracket) { Assert(iterator.Current, iterator.Current.IsValueOrString(), "Expected value type, got " + iterator.Current.Type + "."); var entity = iterator.Current.GetValue(); grp.EntityNames.Add(entity); iterator.MoveNext(); } sect.Groups.Add(grp); } gd.AutoVisgroups.Add(sect); } else { // Parsing: // @TypeClass name(param, param) name() var ct = ParseClassType(type, iterator.Current); var gdo = new GameDataObject("", "", ct); iterator.MoveNext(); while (iterator.Current.Type == LexType.Value) { // Parsing: // @TypeClass {name(param, param) name()} var name = iterator.Current.Value; var bh = new Behaviour(name); iterator.MoveNext(); if (iterator.Current.Type == LexType.Value) { // Allow for the following (first seen in hl2 base): // @PointClass {halfgridsnap} base(Targetname) continue; } Assert(iterator.Current, iterator.Current.Type == LexType.OpenParen, "Unexpected " + iterator.Current.Type); iterator.MoveNext(); while (iterator.Current.Type != LexType.CloseParen) { // Parsing: // name({param, param}) if (iterator.Current.Type != LexType.Comma) { Assert(iterator.Current, iterator.Current.Type == LexType.Value || iterator.Current.Type == LexType.String, "Unexpected " + iterator.Current.Type + "."); var value = iterator.Current.Value; if (iterator.Current.Type == LexType.String) { value = value.Trim('"'); } bh.Values.Add(value); } iterator.MoveNext(); } Assert(iterator.Current, iterator.Current.Type == LexType.CloseParen, "Unexpected " + iterator.Current.Type); // Treat base behaviour as a special case if (bh.Name == "base") { gdo.BaseClasses.AddRange(bh.Values); } else { gdo.Behaviours.Add(bh); } iterator.MoveNext(); } // = class_name : "Descr" + "iption" [ Assert(iterator.Current, iterator.Current.Type == LexType.Equals, "Expected equals, got " + iterator.Current.Type); Expect(iterator, LexType.Value); gdo.Name = iterator.Current.Value; iterator.MoveNext(); if (iterator.Current.Type == LexType.Colon) { // Parsing: // : {"Descr" + "iption"} [ iterator.MoveNext(); gdo.Description = ParsePlusString(iterator); } Assert(iterator.Current, iterator.Current.Type == LexType.OpenBracket, "Unexpected " + iterator.Current.Type); // Parsing: // name(type) : "Desc" : "Default" : "Long Desc" = [ ... ] // input name(type) : "Description" // output name(type) : "Description" iterator.MoveNext(); while (iterator.Current.Type != LexType.CloseBracket) { Assert(iterator.Current, iterator.Current.Type == LexType.Value, "Unexpected " + iterator.Current.Type); var pt = iterator.Current.Value; if (pt == "input" || pt == "output") // IO { // input name(type) : "Description" var io = new IO(); Expect(iterator, LexType.Value); io.IOType = (IOType)Enum.Parse(typeof(IOType), pt, true); io.Name = iterator.Current.Value; Expect(iterator, LexType.OpenParen); Expect(iterator, LexType.Value); io.VariableType = ParseVariableType(iterator.Current); Expect(iterator, LexType.CloseParen); iterator.MoveNext(); // if not colon, this will be the value of the next io/property, or close if (iterator.Current.Type == LexType.Colon) { iterator.MoveNext(); io.Description = ParsePlusString(iterator); } gdo.InOuts.Add(io); } else // Property { Expect(iterator, LexType.OpenParen); Expect(iterator, LexType.Value); var vartype = ParseVariableType(iterator.Current); Expect(iterator, LexType.CloseParen); var prop = new Property(pt, vartype); iterator.MoveNext(); // if not colon or equals, this will be the value of the next io/property, or close if (iterator.Current.Type == LexType.Value) { // Check for additional flags on the property // e.g.: name(type) readonly : "This is a read only value" // name(type) report : "This value will show in the entity report" switch (iterator.Current.Value) { case "readonly": prop.ReadOnly = true; iterator.MoveNext(); break; case "report": prop.ShowInEntityReport = true; iterator.MoveNext(); break; } } do // Using do/while(false) so I can break out - reduces nesting. { // Short description if (iterator.Current.Type != LexType.Colon) { break; } iterator.MoveNext(); prop.ShortDescription = ParsePlusString(iterator); // Default value if (iterator.Current.Type != LexType.Colon) { break; } iterator.MoveNext(); if (iterator.Current.Type != LexType.Colon) // Allow for ': :' structure (no default) { if (iterator.Current.Type == LexType.String) { prop.DefaultValue = iterator.Current.Value.Trim('"'); } else { Assert(iterator.Current, iterator.Current.Type == LexType.Value, "Unexpected " + iterator.Current.Type); prop.DefaultValue = iterator.Current.Value; } iterator.MoveNext(); } // Long description if (iterator.Current.Type != LexType.Colon) { break; } iterator.MoveNext(); prop.Description = ParsePlusString(iterator); } while (false); if (iterator.Current.Type == LexType.Equals) { Expect(iterator, LexType.OpenBracket); // Parsing property options: // value : description // value : description : 0 iterator.MoveNext(); while (iterator.Current.IsValueOrString()) { var opt = new Option { Key = iterator.Current.GetValue() }; Expect(iterator, LexType.Colon); // Some FGDs use values for property descriptions instead of strings iterator.MoveNext(); Assert(iterator.Current, iterator.Current.IsValueOrString(), "Choices value must be value or string type."); if (iterator.Current.Type == LexType.String) { opt.Description = ParsePlusString(iterator); } else { opt.Description = iterator.Current.GetValue(); iterator.MoveNext(); // ParsePlusString moves next once it's complete, need to do the same here } prop.Options.Add(opt); if (iterator.Current.Type != LexType.Colon) { continue; } Expect(iterator, LexType.Value); opt.On = iterator.Current.Value == "1"; iterator.MoveNext(); } Assert(iterator.Current, iterator.Current.Type == LexType.CloseBracket, "Unexpected " + iterator.Current.Type); iterator.MoveNext(); } gdo.Properties.Add(prop); } } Assert(iterator.Current, iterator.Current.Type == LexType.CloseBracket, "Unexpected " + iterator.Current.Type); gd.Classes.Add(gdo); } }
private DataStructures.GameData.GameData Parse(IEnumerable<LexObject> lex) { var gd = new DataStructures.GameData.GameData(); var iterator = lex.GetEnumerator(); while (true) { if (!iterator.MoveNext()) break; if (iterator.Current.Type == LexType.At) { ParseAt(gd, iterator); } } return gd; }
protected override void SaveToStream(Stream stream, DataStructures.MapObjects.Map map, DataStructures.GameData.GameData gameData, TextureCollection textureCollection) { var groups = new List <Group>(); var solids = new List <Solid>(); var ents = new List <Entity>(); FlattenTree(map.WorldSpawn, solids, ents, groups); var fvi = FileVersionInfo.GetVersionInfo(typeof(VmfProvider).Assembly.Location); var versioninfo = new GenericStructure("versioninfo"); versioninfo.AddProperty("editorname", "CBRE"); versioninfo.AddProperty("editorversion", fvi.ProductMajorPart.ToString() + "." + fvi.ProductMinorPart.ToString()); versioninfo.AddProperty("editorbuild", fvi.ProductBuildPart.ToString()); versioninfo.AddProperty("mapversion", map.Version.ToString()); versioninfo.AddProperty("formatversion", "100"); versioninfo.AddProperty("prefab", "0"); var visgroups = new GenericStructure("visgroups"); foreach (var visgroup in map.Visgroups.OrderBy(x => x.ID).Where(x => !x.IsAutomatic)) { visgroups.Children.Add(WriteVisgroup(visgroup)); } var viewsettings = new GenericStructure("viewsettings"); viewsettings.AddProperty("bSnapToGrid", map.SnapToGrid ? "1" : "0"); viewsettings.AddProperty("bShowGrid", map.Show2DGrid ? "1" : "0"); viewsettings.AddProperty("bShow3DGrid", map.Show3DGrid ? "1" : "0"); viewsettings.AddProperty("nGridSpacing", map.GridSpacing.ToString()); viewsettings.AddProperty("bIgnoreGrouping", map.IgnoreGrouping ? "1" : "0"); viewsettings.AddProperty("bHideFaceMask", map.HideFaceMask ? "1" : "0"); viewsettings.AddProperty("bHideNullTextures", map.HideNullTextures ? "1" : "0"); viewsettings.AddProperty("bTextureLock", map.TextureLock ? "1" : "0"); viewsettings.AddProperty("bTextureScalingLock", map.TextureScalingLock ? "1" : "0"); var world = WriteWorld(map, solids, groups); var entities = ents.OrderBy(x => x.ID).Select(WriteEntity).ToList(); var cameras = new GenericStructure("cameras"); cameras.AddProperty("activecamera", map.Cameras.IndexOf(map.ActiveCamera).ToString()); foreach (var cam in map.Cameras) { var camera = new GenericStructure("camera"); camera.AddProperty("position", "[" + FormatCoordinate(cam.EyePosition) + "]"); camera.AddProperty("look", "[" + FormatCoordinate(cam.LookPosition) + "]"); cameras.Children.Add(camera); } var cordon = new GenericStructure("cordon"); cordon.AddProperty("mins", map.CordonBounds.Start.ToString()); cordon.AddProperty("maxs", map.CordonBounds.End.ToString()); cordon.AddProperty("active", map.Cordon ? "1" : "0"); using (var sw = new StreamWriter(stream)) { versioninfo.PrintToStream(sw); visgroups.PrintToStream(sw); viewsettings.PrintToStream(sw); world.PrintToStream(sw); entities.ForEach(e => e.PrintToStream(sw)); cameras.PrintToStream(sw); cordon.PrintToStream(sw); } }
protected override void SaveToStream(Stream stream, DataStructures.MapObjects.Map map, DataStructures.GameData.GameData gameData, TextureCollection textureCollection) { throw new NotImplementedException("don't save to 3dw, ew"); }
protected override void SaveToStream(Stream stream, DataStructures.MapObjects.Map map, DataStructures.GameData.GameData gameData, TextureCollection textureCollection) { BinaryWriter writer = new BinaryWriter(stream); writer.WriteFixedLengthString(Encoding.ASCII, 3, "CBR"); writer.Write(revision); // Lightmaps bool lightmapped = textureCollection != null && textureCollection.Lightmaps[0] != null; if (lightmapped) { writer.Write((byte)Lightmapped.Fully); // TODO: Determine changes from last render for (int i = 0; i < 4; i++) { long prevPos = writer.Seek(0, SeekOrigin.Current); writer.Write(0); writer.Flush(); textureCollection.Lightmaps[i].Save(stream, ImageFormat.Png); int imageOffset = (int)(writer.Seek(0, SeekOrigin.Current) - prevPos); writer.Seek(-imageOffset, SeekOrigin.Current); writer.Write(imageOffset - sizeof(int)); writer.Seek(0, SeekOrigin.End); } } else { writer.Write((byte)Lightmapped.No); } // Texture dictionary Dictionary <string, int> texDic = new Dictionary <string, int>(); StringBuilder texBuilder = new StringBuilder(); int texCount = 0; IEnumerator <string> textures = map.GetAllTextures().GetEnumerator(); while (textures.MoveNext()) { texBuilder.Append(textures.Current); texBuilder.Append('\0'); texDic.Add(textures.Current, texCount); texCount++; } writer.Write(texCount); writer.WriteFixedLengthString(Encoding.UTF8, texBuilder.Length, texBuilder.ToString()); // Solids List <MapObject> solids = map.WorldSpawn.Find(x => x is Solid); writer.Write(solids.Count); foreach (Solid s in solids) { writer.Write(s.Faces.Count); foreach (Face f in s.Faces) { writer.Write(texDic[f.Texture.Name]); writer.WriteCoordinate(f.Texture.UAxis); writer.WriteCoordinate(f.Texture.VAxis); writer.Write(f.Texture.XShift); writer.Write(f.Texture.YShift); writer.Write(f.Texture.XScale); writer.Write(f.Texture.YScale); writer.Write(f.Texture.Rotation); writer.Write(f.Vertices.Count); foreach (Vertex v in f.Vertices) { writer.WriteCoordinate(v.Location); if (lightmapped) { writer.Write(v.LMU); writer.Write(v.LMV); writer.Write((float)v.TextureU); writer.Write((float)v.TextureV); } } } } // Entities ISet <string> foundEntityTypes = new HashSet <string>(); List <GameDataObject> entityTypes = new List <GameDataObject>(); List <MapObject> entites = map.WorldSpawn.Find(x => x is Entity && x.ClassName != ""); foreach (Entity e in entites) { Console.WriteLine(e.ClassName); Console.WriteLine(e.GameData.Name); if (!foundEntityTypes.Contains(e.ClassName)) { GameDataObject gdo = gameData.Classes.Find(x => x.Name == e.ClassName); entityTypes.Add(gdo); foundEntityTypes.Add(gdo.Name); } } // Move brush entities to front entityTypes.Sort((x, y) => (x.ClassType == ClassType.Solid ? -1 : 0)); // For later use with groups Dictionary <Entity, int> entityIndices = new Dictionary <Entity, int>(); int entityIndicesCounter = 0; bool reachedRegular = false; foreach (GameDataObject gdo in entityTypes) { if (!reachedRegular && gdo.ClassType != ClassType.Solid) { reachedRegular = true; writer.WriteNullTerminatedString(""); } writer.WriteNullTerminatedString(gdo.Name); foreach (DataStructures.GameData.Property p in gdo.Properties) { writer.Write((byte)p.VariableType); writer.WriteNullTerminatedString(p.Name); // Switch from brush to regular entities } writer.Write((byte)255); // Property end byte // Entries List <MapObject> entitiesOfType = entites.FindAll(x => x.ClassName == gdo.Name); writer.Write(entitiesOfType.Count); foreach (Entity e in entitiesOfType) { entityIndices.Add(e, entityIndicesCounter++); if (e.GameData.ClassType == ClassType.Solid) { IEnumerable <MapObject> children = e.GetChildren(); writer.Write(children.Count()); foreach (MapObject mo in children) { int index = solids.FindIndex(x => x == mo); writer.Write(index); } } for (int i = 0; i < gdo.Properties.Count; i++) { DataStructures.MapObjects.Property property; if (i < e.EntityData.Properties.Count && gdo.Properties[i].Name == e.EntityData.Properties[i].Key) { property = e.EntityData.Properties[i]; } else { property = e.EntityData.Properties.Find(x => x.Key == gdo.Properties[i].Name); if (property == null) { property = new DataStructures.MapObjects.Property(); property.Key = gdo.Properties[i].Name; property.Value = gdo.Properties[i].DefaultValue; } } switch (gdo.Properties[i].VariableType) { case VariableType.Bool: writer.Write(property.Value == "Yes"); break; case VariableType.Color255: writer.WriteRGBAColour(property.GetColour(Color.Black)); break; case VariableType.Float: writer.Write(float.Parse(property.Value)); break; case VariableType.Integer: writer.Write(int.Parse(property.Value)); break; case VariableType.String: // TODO: Implement dictionary. writer.WriteNullTerminatedString(property.Value); break; case VariableType.Vector: writer.WriteCoordinate(property.GetCoordinate(Coordinate.Zero)); break; case VariableType.Choices: bool found = false; for (int j = 0; j < gdo.Properties[i].Options.Count; j++) { if (property.Value == gdo.Properties[i].Options[j].Key) { writer.Write((byte)j); found = true; break; } } if (!found) { writer.Write((byte)255); } break; } } } } writer.WriteNullTerminatedString(""); // CBRE ONLY // Visgroup dictionary // TODO: Visgroup IDs to indices Stack <IEnumerator <Visgroup> > visStack = new Stack <IEnumerator <Visgroup> >(); visStack.Push(map.Visgroups.GetEnumerator()); while (visStack.Count > 0) { IEnumerator <Visgroup> v = visStack.Pop(); while (v.MoveNext()) { if (!v.Current.IsAutomatic) { writer.Write(HIERARCHY_PROCCEED); writer.Write(v.Current.ID); writer.WriteNullTerminatedString(v.Current.Name); if (v.Current.Children.Count != 0) { writer.Write(HIERARCHY_DOWN); visStack.Push(v); v = v.Current.Children.GetEnumerator(); } } } writer.Write(HIERARCHY_UP); } // Solid visgroups foreach (Solid s in map.WorldSpawn.FindAll().OfType <Solid>()) { WriteVisgroups(writer, s); } // Entity visgroups foreach (GameDataObject entityType in entityTypes) { foreach (Entity e in entites.FindAll(x => x.ClassName == entityType.Name)) { WriteVisgroups(writer, e); } } // Groups IEnumerable <Group> groups = map.WorldSpawn.GetChildren().OfType <Group>(); writer.Write(groups.Count()); foreach (Group g in groups) { Stack <IEnumerator <MapObject> > groupStack = new Stack <IEnumerator <MapObject> >(); groupStack.Push(g.GetChildren().GetEnumerator()); while (groupStack.Count > 0) { IEnumerator <MapObject> gg = groupStack.Pop(); while (gg.MoveNext()) { if (gg.Current is Group) { writer.Write(HIERARCHY_DOWN); groupStack.Push(gg); gg = gg.Current.GetChildren().GetEnumerator(); } else if (gg.Current is Entity) { writer.Write(IDENTIFIER_ENTITY); writer.Write(entityIndices[(Entity)gg.Current]); } else { writer.Write(IDENTIFIER_SOLID); writer.Write(solids.FindIndex(x => x == gg.Current)); } } writer.Write(HIERARCHY_UP); } } stream.Close(); }