public void ExportToStream(EndianBinaryWriter writer, WScene scene) { // Build a dictionary which lists unique FourCC's and a list of all relevant actors. var actorCategories = new Dictionary <FourCC, List <SerializableDOMNode> >(); foreach (var child in scene) { var groupNode = child as WDOMGroupNode; if (groupNode == null) { continue; } // If this is an ACTR, SCOB, or TRES group node, we have to dig into it to get the layers. if (groupNode.FourCC == FourCC.ACTR || groupNode.FourCC == FourCC.SCOB || groupNode.FourCC == FourCC.TRES) { foreach (var layer in groupNode.Children) { foreach (var obj in layer.Children) { var actor = obj as SerializableDOMNode; if (actor != null) { AddObjectToDictionary(actor, actorCategories); } } } } else { foreach (var obj in groupNode.Children) { var actor = obj as SerializableDOMNode; if (actor != null) { AddObjectToDictionary(actor, actorCategories); } } } } // Create a chunk header for each one. var chunkHeaders = new List <ChunkHeader>(); foreach (var kvp in actorCategories) { ChunkHeader header = new ChunkHeader(); header.FourCC = kvp.Key; header.ElementCount = kvp.Value.Count; chunkHeaders.Add(header); } long chunkStart = writer.BaseStream.Position; // Write the Header writer.Write(chunkHeaders.Count); for (int i = 0; i < chunkHeaders.Count; i++) { writer.Write((int)0); // Dummy Placeholder values for the Chunk Header. writer.Write((int)0); writer.Write((int)0); } // For each chunk, write the data for that chunk. Before writing the data, get the current offset and update the header. List <SerializableDOMNode>[] dictionaryData = new List <SerializableDOMNode> [actorCategories.Count]; actorCategories.Values.CopyTo(dictionaryData, 0); for (int i = 0; i < chunkHeaders.Count; i++) { ChunkHeader header = chunkHeaders[i]; chunkHeaders[i] = new ChunkHeader(header.FourCC, header.ElementCount, (int)(writer.BaseStream.Position - chunkStart)); List <SerializableDOMNode> actors = dictionaryData[i]; if (header.FourCC == FourCC.RTBL) { SaveRoomTable(actors, writer); continue; } foreach (var actor in actors) { MapActorDescriptor template = Globals.ActorDescriptors.Find(x => x.FourCC == actor.FourCC); if (template == null) { Console.WriteLine("Unsupported FourCC (\"{0}\") for exporting!", actor.FourCC); continue; } actor.PreSave(); actor.Save(writer); //WriteActorToChunk(actor, template, writer); } } // Now that we've written every actor to file we can go back and re-write the headers now that we know their offsets. writer.BaseStream.Position = chunkStart + 0x4; // 0x4 is the offset to the Chunk Headers foreach (var header in chunkHeaders) { writer.WriteFixedString(FourCCConversion.GetStringFromEnum(header.FourCC), 4); // FourCC writer.Write(header.ElementCount); // Number of Entries writer.Write(header.ChunkOffset); // Offset from start of file. } // Seek to the end of the file, and then pad us to 32-byte alignment. writer.BaseStream.Seek(0, SeekOrigin.End); int delta = WMath.Pad16Delta(writer.BaseStream.Position); for (int i = 0; i < delta; i++) { writer.Write((byte)0xFF); } }