/// <summary> /// Imports the specified map into the SabreCSG model. /// </summary> /// <param name="model">The model to import into.</param> /// <param name="map">The map to be imported.</param> /// <param name="scale">The scale modifier.</param> public static void Import(CSGModelBase model, T3dMap map, int scale = 64) { try { model.BeginUpdate(); // create a material searcher to associate materials automatically. MaterialSearcher materialSearcher = new MaterialSearcher(); List <T3dActor> brushes = map.Brushes; Brush[] sabreBrushes = new Brush[brushes.Count]; // iterate through all brush actors. for (int k = 0; k < brushes.Count; k++) { // get the underlying brush data. T3dActor tactor = brushes[k]; T3dBrush tbrush = tactor.Brush; #if UNITY_EDITOR UnityEditor.EditorUtility.DisplayProgressBar("SabreCSG: Importing Unreal Gold Map", "Converting Unreal Brushes To SabreCSG Brushes (" + (k + 1) + " / " + brushes.Count + ")...", k / (float)brushes.Count); #endif // iterate through the brush polygons. Polygon[] polygons = new Polygon[tbrush.Polygons.Count]; for (int i = 0; i < tbrush.Polygons.Count; i++) { T3dPolygon tpolygon = tbrush.Polygons[i]; // find the material in the unity project automatically. Material material = null; if (!string.IsNullOrEmpty(tpolygon.Texture)) { if (tpolygon.Texture.Contains('.')) { // try finding both 'PlayrShp.Ceiling.Hullwk' and 'Hullwk'. string tiny = tpolygon.Texture.Substring(tpolygon.Texture.LastIndexOf('.') + 1); material = materialSearcher.FindMaterial(new string[] { tpolygon.Texture, tiny }); if (material == null) { Debug.Log("SabreCSG: Tried to find material '" + tpolygon.Texture + "' and also as '" + tiny + "' but it couldn't be found in the project."); } } else { // only try finding 'Hullwk'. material = materialSearcher.FindMaterial(new string[] { tpolygon.Texture }); if (material == null) { Debug.Log("SabreCSG: Tried to find material '" + tpolygon.Texture + "' but it couldn't be found in the project."); } } } Vertex[] vertices = new Vertex[tpolygon.Vertices.Count]; for (int j = 0; j < tpolygon.Vertices.Count; j++) { // main-scale // scale around pivot point. Vector3 vertexPosition = ToVector3(tpolygon.Vertices[j]); Vector3 pivot = ToVector3(tactor.PrePivot); Vector3 difference = vertexPosition - pivot; vertexPosition = difference.Multiply(ToVector3Raw(tactor.MainScale)) + pivot; // post-scale vertices[j] = new Vertex(vertexPosition.Multiply(ToVector3Raw(tactor.PostScale)) / (float)scale, ToVector3(tpolygon.Normal), GenerateUV(tpolygon, j, material)); } // detect the polygon flags. bool userExcludeFromFinal = false; if ((tpolygon.Flags & T3dPolygonFlags.Invisible) > 0) { userExcludeFromFinal = true; } polygons[i] = new Polygon(vertices, material, false, userExcludeFromFinal); } // position and rotate the brushes around their pivot point. Transform transform = model.CreateCustomBrush(polygons).transform; transform.position = (ToVector3(tactor.Location) / (float)scale) - (ToVector3(tactor.PrePivot) / (float)scale); Vector3 axis; float angle; T3dRotatorToQuaternion(tactor.Rotation).ToAngleAxis(out angle, out axis); transform.RotateAround(transform.position + (ToVector3(tactor.PrePivot) / (float)scale), axis, angle); PrimitiveBrush brush = transform.GetComponent <PrimitiveBrush>(); sabreBrushes[k] = brush; object value; // detect the brush mode (additive, subtractive). if (tactor.Properties.TryGetValue("CsgOper", out value)) { brush.Mode = (string)value == "CSG_Add" ? CSGMode.Add : CSGMode.Subtract; } // detect special brush flags. if (tactor.Properties.TryGetValue("PolyFlags", out value)) { T3dBrushFlags flags = (T3dBrushFlags)value; if ((flags & T3dBrushFlags.Invisible) > 0) { brush.IsVisible = false; } if ((flags & T3dBrushFlags.NonSolid) > 0) { brush.HasCollision = false; } if ((flags & T3dBrushFlags.SemiSolid) > 0) { brush.IsNoCSG = true; } } // detect single polygons. if (polygons.Length == 1) { brush.IsNoCSG = true; } } // add all new brushes to a group. string title = "Unreal Gold Map"; if (map.Title != "") { title += " '" + map.Title + "'"; } if (map.Author != "") { title += " (" + map.Author + ")"; } GroupBrush groupBrush = new GameObject(title).AddComponent <GroupBrush>(); groupBrush.transform.SetParent(model.transform); for (int i = 0; i < sabreBrushes.Length; i++) { sabreBrushes[i].transform.SetParent(groupBrush.transform); } #if UNITY_EDITOR UnityEditor.EditorUtility.ClearProgressBar(); #endif } catch (Exception) { throw; } finally { model.EndUpdate(); } }
/// <summary> /// Imports the specified Unreal Text file. /// </summary> /// <param name="path">The file path.</param> /// <returns>A <see cref="T3dMap"/> containing the imported map data.</returns> public T3dMap Import(string path) { // create a new map. T3dMap map = new T3dMap(); // open the file for reading. we use streams for additional performance. // it's faster than File.ReadAllLines() as that requires two iterations. using (FileStream stream = new FileStream(path, FileMode.Open)) using (StreamReader reader = new StreamReader(stream)) { // read all the lines from the file. bool inActor = false; T3dActor actor = null; bool inBrush = false; T3dBrush brush = null; bool inPolygon = false; T3dPolygon polygon = null; string line; while (!reader.EndOfStream) { line = reader.ReadLine().Trim(); // if we currently parsing an actor: if (inActor) { if (!inBrush) { // if we done parsing the actor: if (line == "End Actor") { inActor = false; continue; } // try parsing an actor property. string key; object value; if (TryParseProperty(line, out key, out value)) { actor.Properties.Add(key, value); } // make sure we detect brush declarations: if (line.StartsWith("Begin Brush")) { // read the properties of the brush. var properties = ParseKeyValuePairs(line); if (properties.ContainsKey("Name")) { // this is a valid brush model that can be parsed further. inBrush = true; // create a new brush model and add it to the map. brush = new T3dBrush(properties["Name"]); map.BrushModels.Add(brush); continue; } } } // we are currently parsing a brush: else { // if we done parsing the brush: if (line == "End Brush") { inBrush = false; continue; } if (!inPolygon) { // make sure we detect brush polygon declarations: if (line.StartsWith("Begin Polygon")) { inPolygon = true; // create a new brush polygon and add it to the brush. polygon = new T3dPolygon(); brush.Polygons.Add(polygon); // read the properties of the brush polygon. var properties = ParseKeyValuePairs(line); if (properties.ContainsKey("Item")) { polygon.Item = properties["Item"]; } if (properties.ContainsKey("Texture")) { polygon.Texture = properties["Texture"]; } if (properties.ContainsKey("Flags")) { polygon.Flags = (T3dPolygonFlags)Int32.Parse(properties["Flags"]); } } } // we are currently parsing a brush polygon: else { // if we done parsing the brush polygon: if (line == "End Polygon") { inPolygon = false; continue; } if (line.StartsWith("Origin")) { polygon.Origin = ParsePolygonVector(line); } if (line.StartsWith("Normal")) { polygon.Normal = ParsePolygonVector(line); } if (line.StartsWith("TextureU")) { polygon.TextureU = ParsePolygonVector(line); } if (line.StartsWith("TextureV")) { polygon.TextureV = ParsePolygonVector(line); } if (line.StartsWith("Pan")) { int u, v; ParsePolygonUV(line, out u, out v); polygon.PanU = u; polygon.PanV = v; } if (line.StartsWith("Vertex")) { polygon.Vertices.Add(ParsePolygonVector(line)); } } } } // if we are looking for another begin declaration: else { // if we are going to parse an actor: if (line.StartsWith("Begin Actor")) { // read the properties of the actor. var properties = ParseKeyValuePairs(line); if (properties.ContainsKey("Class") && properties.ContainsKey("Name")) { // this is a valid actor that can be parsed further. inActor = true; // create a new actor and add it to the map. actor = new T3dActor(map, properties["Class"], properties["Name"]); map.Actors.Add(actor); continue; } } } } } // return the map data. return(map); }
/// <summary> /// Imports the specified map into the SabreCSG model. /// </summary> /// <param name="model">The model to import into.</param> /// <param name="map">The map to be imported.</param> /// <param name="scale">The scale modifier.</param> public static void Import(CSGModel model, T3dMap map, int scale = 64) { try { model.BeginUpdate(); List <T3dActor> brushes = map.Brushes; Brush[] sabreBrushes = new Brush[brushes.Count]; // iterate through all brush actors. for (int k = 0; k < brushes.Count; k++) { // get the underlying brush data. T3dActor tactor = brushes[k]; T3dBrush tbrush = tactor.Brush; #if UNITY_EDITOR UnityEditor.EditorUtility.DisplayProgressBar("SabreCSG: Importing Unreal Gold Map", "Converting Unreal Brushes To SabreCSG Brushes (" + (k + 1) + " / " + brushes.Count + ")...", k / (float)brushes.Count); #endif // iterate through the brush polygons. Polygon[] polygons = new Polygon[tbrush.Polygons.Count]; for (int i = 0; i < tbrush.Polygons.Count; i++) { T3dPolygon tpolygon = tbrush.Polygons[i]; // find the material in the unity project automatically. Material material = FindMaterial(tpolygon.Texture); Vertex[] vertices = new Vertex[tpolygon.Vertices.Count]; for (int j = 0; j < tpolygon.Vertices.Count; j++) { vertices[j] = new Vertex(ToVector3(tpolygon.Vertices[j]) / (float)scale, ToVector3(tpolygon.Normal), GenerateUV(tpolygon, j, material)); } // detect the polygon flags. bool userExcludeFromFinal = false; if ((tpolygon.Flags & T3dPolygonFlags.Invisible) > 0) { userExcludeFromFinal = true; } polygons[i] = new Polygon(vertices, material, false, userExcludeFromFinal); } // position and rotate the brushes. Transform transform = model.CreateCustomBrush(polygons).transform; transform.position = (ToVector3(tactor.Location) / (float)scale) - (ToVector3(tactor.PrePivot) / (float)scale); Vector3 axis; float angle; T3dRotatorToQuaternion(tactor.Rotation).ToAngleAxis(out angle, out axis); transform.RotateAround(transform.position + (ToVector3(tactor.PrePivot) / (float)scale), axis, angle); PrimitiveBrush brush = transform.GetComponent <PrimitiveBrush>(); sabreBrushes[k] = brush; object value; // detect the brush mode (additive, subtractive). if (tactor.Properties.TryGetValue("CsgOper", out value)) { brush.Mode = (string)value == "CSG_Add" ? CSGMode.Add : CSGMode.Subtract; } // detect special brush flags. if (tactor.Properties.TryGetValue("PolyFlags", out value)) { T3dBrushFlags flags = (T3dBrushFlags)value; if ((flags & T3dBrushFlags.Invisible) > 0) { brush.IsVisible = false; } if ((flags & T3dBrushFlags.NonSolid) > 0) { brush.HasCollision = false; } if ((flags & T3dBrushFlags.SemiSolid) > 0) { brush.IsNoCSG = true; } } // detect single polygons. if (polygons.Length == 1) { brush.IsNoCSG = true; } } // add all new brushes to a group. string title = "Unreal Gold Map"; if (map.Title != "") { title += " '" + map.Title + "'"; } if (map.Author != "") { title += " (" + map.Author + ")"; } GroupBrush groupBrush = new GameObject(title).AddComponent <GroupBrush>(); groupBrush.transform.SetParent(model.transform); for (int i = 0; i < sabreBrushes.Length; i++) { sabreBrushes[i].transform.SetParent(groupBrush.transform); } #if UNITY_EDITOR UnityEditor.EditorUtility.ClearProgressBar(); #endif } catch (Exception) { throw; } finally { model.EndUpdate(); } }