private void collect_type_in_children <T>(SOCollection groupSO, bool bVisibleOnly, List <T> collection) where T : class { foreach (var child in groupSO.GetChildren()) { if (child is T) { if (bVisibleOnly == false || SceneUtil.IsVisible(child)) { collection.Add(child as T); } } if (child is SOCollection) { collect_type_in_children(child as SOCollection, bVisibleOnly, collection); } } }
/// <summary> /// Find SceneObjects of a given type. If bSelected == true, only considers selected /// SOs. By default will descend into groups. /// </summary> public List <T> FindSceneObjectsOfType <T>(bool bSelected = false, bool bDescendGroups = true, bool bVisibleOnly = false) where T : class { List <T> result = new List <T>(); List <SceneObject> source = (bSelected) ? vSelected : vObjects; foreach (var so in source) { if (so is T) { if (bVisibleOnly == false || SceneUtil.IsVisible(so)) { result.Add(so as T); } } if (bDescendGroups && so is SOCollection) { collect_type_in_children(so as SOCollection, bVisibleOnly, result); } } return(result); }
public virtual ExportStatus Export(FScene scene, string filename) { int[] vertexMap = new int[2048]; // temp List <WriteMesh> vMeshes = new List <WriteMesh>(); if (WriteFaceGroups) { throw new Exception("SceneMeshExporter.Export: writing face groups has not yet been implemented!"); } // extract all the mesh data we want to export foreach (SceneObject so in scene.SceneObjects) { if (so.IsTemporary || so.IsSurface == false || SceneUtil.IsVisible(so) == false) { continue; } if (SOFilterF != null && SOFilterF(so) == false) { continue; } // if this SO has an internal mesh we can just copy, use it if (so is DMeshSO) { DMeshSO meshSO = so as DMeshSO; // todo: flags // make a copy of mesh DMesh3 m = new DMesh3(meshSO.Mesh, true); // transform to scene coords and swap left/right foreach (int vid in m.VertexIndices()) { Vector3f v = (Vector3f)m.GetVertex(vid); v = SceneTransforms.ObjectToScene(meshSO, v); v = UnityUtil.SwapLeftRight(v); m.SetVertex(vid, v); } m.ReverseOrientation(); vMeshes.Add(new WriteMesh(m, so.Name)); } // Look for lower-level fGameObject items to export. By default // this is anything with a MeshFilter, override CollectGOChildren // or use GOFilterF to add restrictions List <fGameObject> vExports = CollectGOChildren(so); if (vExports.Count > 0) { SimpleMesh m = new SimpleMesh(); m.Initialize(WriteNormals, WriteVertexColors, WriteUVs, WriteFaceGroups); int groupCounter = 1; foreach (fGameObject childgo in vExports) { if (GOFilterF != null && GOFilterF(so, childgo) == false) { continue; } if (AppendGOMesh(childgo, m, vertexMap, scene, groupCounter)) { groupCounter++; } } vMeshes.Add(new WriteMesh(m, so.Name)); } } // ok, we are independent of Scene now and can write in bg thread if (WriteInBackgroundThreads) { ExportStatus status = new ExportStatus() { Exporter = this, IsComputing = true }; WriteOptions useOptions = Options; useOptions.ProgressFunc = (cur, max) => { status.Progress = cur; status.MaxProgress = max; }; BackgroundWriteThread t = new BackgroundWriteThread() { Meshes = vMeshes, options = useOptions, Filename = filename, CompletionF = (result) => { LastWriteStatus = result.code; LastErrorMessage = result.message; status.LastErrorMessage = result.message; status.Ok = (result.code == IOCode.Ok); status.IsComputing = false; if (BackgroundWriteCompleteF != null) { BackgroundWriteCompleteF(this, status); } } }; t.Start(); return(status); } else { IOWriteResult result = StandardMeshWriter.WriteFile(filename, vMeshes, Options); LastWriteStatus = result.code; LastErrorMessage = result.message; return(new ExportStatus() { Exporter = this, IsComputing = false, Ok = (result.code == IOCode.Ok), LastErrorMessage = result.message }); } }