示例#1
0
        private void WriteFolderBlocks(BinaryWriterEx bw, FolderEntry folder)
        {
            var allChilds      = folder.GetEntryHierarchy().ToList();
            var totalFilesSize = allChilds.OfType <FileEntry>().Sum(x => x.FileSize);
            var folderBlock    = new LIFFBlock
            {
                BlockHeader = 1,
                BlockType   = 3,
                BlockSize   = ((allChilds.Count() + 1) * LIFFBLOCK_SIZE) + (int)totalFilesSize
            };

            bw.WriteStruct(folderBlock);

            foreach (var entry in folder.Entries.OrderBy(x => x.Name))
            {
                if (entry is FileEntry file)
                {
                    var fileBlock = new LIFFBlock
                    {
                        BlockHeader = 1,
                        BlockType   = 4,
                        Spacing2    = 1,
                        BlockSize   = LIFFBLOCK_SIZE + (int)file.FileSize
                    };
                    bw.WriteStruct(fileBlock);
                    var fileStream = file.GetStream();
                    //fileStream.CopyTo(bw.BaseStream, 4096);

                    byte[] buffer    = new byte[4096];
                    int    bytesRead = 0;
                    while (bytesRead < file.FileSize)
                    {
                        int b = fileStream.Read(buffer, 0, buffer.Length);
                        bytesRead += b;
                        bw.Write(buffer, 0, b);
                        if (b == 0)
                        {
                            break;
                        }
                    }
                }
                else
                {
                    WriteFolderBlocks(bw, (FolderEntry)entry);
                }
            }
        }
示例#2
0
        public void WriteToStream(Stream stream)
        {
            if (stream == BaseStream)
            {
                throw new InvalidOperationException("Cannot overwrite the same stream.");
            }

            using (var bw = new BinaryWriterEx(stream, true))
            {
                bw.DefaultEndian = Endianness.BigEndian;
                var header = LIFFHeader.Default;
                bw.WriteStruct(header);
                long rootBlockPos = stream.Position;
                var  rootBlock    = new LIFFBlock
                {
                    BlockHeader = 1,
                    BlockType   = 1,
                };
                bw.WriteStruct(rootBlock);
                var contentBlock = new LIFFBlock
                {
                    BlockHeader = 1,
                    BlockType   = 2,
                    Spacing2    = 1,
                    BlockSize   = 26
                };
                bw.WriteStruct(contentBlock);
                bw.WriteInt16(1);
                bw.WriteInt32(0);

                WriteFolderBlocks(bw, RootFolder);

                long hierarchyBlockPos = stream.Position;
                var  hierarchyBlock    = new LIFFBlock
                {
                    BlockHeader = 1,
                    BlockType   = 5,
                    Spacing2    = 1
                };
                bw.WriteStruct(hierarchyBlock);

                WriteFolderEntries(bw, RootFolder);
                hierarchyBlock.BlockSize = (int)(stream.Position - hierarchyBlockPos);
                stream.Position          = hierarchyBlockPos;
                bw.WriteStruct(hierarchyBlock);

                rootBlock.BlockSize = (int)(stream.Length - rootBlockPos);
                stream.Position     = rootBlockPos;
                bw.WriteStruct(rootBlock);

                header.FileSize = (int)stream.Length;
                stream.Position = 0;
                bw.WriteStruct(header);
            }
        }
示例#3
0
        private void WriteFolderEntries(BinaryWriterEx bw, FolderEntry folder)
        {
            var allChilds = folder.GetEntryHierarchy().ToList();

            var folderEntry = new LIFFFolderEntry()
            {
                EntryType  = 1,
                Filename   = folder.IsRootDirectory ? null : folder.Name,
                EntryCount = folder.Entries.Count,
                Reserved1  = folder.IsRootDirectory ? 0 : 7,
                BlockSize  = 20
            };

            bw.WriteStruct(folderEntry);

            foreach (var entry in folder.Entries.OrderBy(x => x.Name))
            {
                if (entry is FileEntry file)
                {
                    var fileEntry = new LIFFFileEntry()
                    {
                        EntryType = 2,
                        Filename  = file.Name,
                        FileSize  = (int)file.FileSize + LIFFBLOCK_SIZE,
                        Reserved1 = 7,
                        Created   = file.CreatedDate.ToFileTime(),
                        Modified  = file.ModifiedDate.ToFileTime(),
                        Accessed  = file.AccessedDate.ToFileTime()
                    };
                    bw.WriteStruct(fileEntry);
                }
                else
                {
                    WriteFolderEntries(bw, (FolderEntry)entry);
                }
            }
        }
示例#4
0
        public static void WriteMeshFile(Stream stream, MESH_FILE meshFile)
        {
            using (var bw = new BinaryWriterEx(stream, Encoding.UTF8, true))
            {
                bw.WriteStruct(meshFile.Header);
                void WriteVector3(Vector3 v)
                {
                    bw.WriteSingle(v.X);
                    bw.WriteSingle(v.Y);
                    bw.WriteSingle(v.Z);
                }

                void WriteVector2(Vector2 v)
                {
                    bw.WriteSingle(v.X);
                    bw.WriteSingle(v.Y);
                }

                foreach (var pos in meshFile.Geometry.Positions)
                {
                    WriteVector3(pos);
                }

                foreach (var norm in meshFile.Geometry.Normals)
                {
                    WriteVector3(norm);
                }

                if (meshFile.Geometry.UVs != null && meshFile.Geometry.UVs.Length > 0)
                {
                    foreach (var uv in meshFile.Geometry.UVs)
                    {
                        WriteVector2(uv);
                    }
                }

                for (int i = 0; i < meshFile.Header.IndexCount; i++)
                {
                    bw.WriteInt32(meshFile.Geometry.Indices[i].VertexIndex);
                }


                //Round Edge Shader Data
                {
                    var allShaderData = meshFile.RoundEdgeShaderData.SelectMany(x => x.Coords).ToList();

                    bw.WriteInt32(allShaderData.Count * 2);
                    foreach (var shaderCoord in allShaderData)
                    {
                        WriteVector2(shaderCoord);
                    }

                    for (int i = 0; i < meshFile.Header.IndexCount; i++)
                    {
                        bw.WriteInt32(meshFile.Geometry.Indices[i].REShaderOffset);
                    }
                }

                //Average Normals
                {
                    bw.WriteInt32(meshFile.AverageNormals.Length + 1);
                    WriteVector3(new Vector3(83, 0, 0));

                    foreach (var avgNorm in meshFile.AverageNormals)
                    {
                        WriteVector3(avgNorm);
                    }

                    for (int i = 0; i < meshFile.Header.IndexCount; i++)
                    {
                        bw.WriteInt32(meshFile.Geometry.Indices[i].AverageNormalIndex);
                    }
                }

                if (meshFile.Geometry.Bones != null && meshFile.Geometry.Bones.Length > 0)
                {
                    //TODO: If flexible alternate meshes are supported, improve this code to include alternate meshes bones
                    //      and a way to retrieve the correct offsets in WriteCullingInfo

                    var allBones     = meshFile.Geometry.Bones.SelectMany(x => x.BoneWeights).ToList();
                    int boneDataSize = (allBones.Count * 8) + (meshFile.Header.VertexCount * 4);
                    bw.WriteInt32(boneDataSize);

                    var dataOffsets = new List <int>();
                    int totalOffset = 0;

                    for (int i = 0; i < meshFile.Header.VertexCount; i++)
                    {
                        var vertexBones = meshFile.Geometry.Bones[i];
                        bw.WriteInt32(vertexBones.BoneWeights.Length);
                        for (int j = 0; j < vertexBones.BoneWeights.Length; j++)
                        {
                            bw.WriteInt32(vertexBones.BoneWeights[j].BoneID);
                            bw.WriteSingle(vertexBones.BoneWeights[j].Weight);
                        }
                        //bone count (4 bytes) + bones data (id + weight = 8 bytes)
                        dataOffsets.Add(totalOffset);
                        totalOffset += 4 + (vertexBones.BoneWeights.Length * 8);
                    }

                    for (int i = 0; i < meshFile.Header.VertexCount; i++)
                    {
                        bw.WriteInt32(dataOffsets[i]);
                    }
                }

                //Mesh Culling Info
                {
                    bw.WriteInt32(meshFile.Cullings.Length);
                    WriteSizedBlock(bw, () =>
                    {
                        for (int i = 0; i < meshFile.Cullings.Length; i++)
                        {
                            WriteCullingInfo(bw, meshFile.Cullings[i]);
                        }
                    }, false);
                }
            }
        }