// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild using System.Collections.Generic; // ReSharper disable once CheckNamespace namespace Kaitai { /// /// Blender is an open source suite for 3D modelling, sculpting, /// animation, compositing, rendering, preparation of assets for its own /// game engine and exporting to others, etc. `.blend` is its own binary /// format that saves whole state of suite: current scene, animations, /// all software settings, extensions, etc. /// /// Internally, .blend format is a hybrid semi-self-descriptive /// format. On top level, it contains a simple header and a sequence of /// file blocks, which more or less follow typical [TLV /// pattern](https://en.wikipedia.org/wiki/Type-length-value). Pre-last /// block would be a structure with code `DNA1`, which is a essentially /// a machine-readable schema of all other structures used in this file. /// public partial class BlendFile : KaitaiStruct { public static BlendFile FromFile(string fileName) { return new BlendFile(new KaitaiStream(fileName)); } public enum PtrSize { Bits64 = 45, Bits32 = 95, } public enum Endian { Be = 86, Le = 118, } public BlendFile(KaitaiStream p__io, KaitaiStruct p__parent = null, BlendFile p__root = null) : base(p__io) { m_parent = p__parent; m_root = p__root ?? this; f_sdnaStructs = false; _read(); } private void _read() { _hdr = new Header(m_io, this, m_root); _blocks = new List(); { var i = 0; while (!m_io.IsEof) { _blocks.Add(new FileBlock(m_io, this, m_root)); i++; } } } /// /// DNA struct contains a `type` (type name), which is specified as /// an index in types table, and sequence of fields. /// public partial class DnaStruct : KaitaiStruct { public static DnaStruct FromFile(string fileName) { return new DnaStruct(new KaitaiStream(fileName)); } public DnaStruct(KaitaiStream p__io, BlendFile.Dna1Body p__parent = null, BlendFile p__root = null) : base(p__io) { m_parent = p__parent; m_root = p__root; f_type = false; _read(); } private void _read() { _idxType = m_io.ReadU2le(); _numFields = m_io.ReadU2le(); _fields = new List(); for (var i = 0; i < NumFields; i++) { _fields.Add(new DnaField(m_io, this, m_root)); } } private bool f_type; private string _type; public string Type { get { if (f_type) return _type; _type = (string)(M_Parent.Types[IdxType]); f_type = true; return _type; } } private ushort _idxType; private ushort _numFields; private List _fields; private BlendFile m_root; private BlendFile.Dna1Body m_parent; public ushort IdxType { get { return _idxType; } } public ushort NumFields { get { return _numFields; } } public List Fields { get { return _fields; } } public BlendFile M_Root { get { return m_root; } } public BlendFile.Dna1Body M_Parent { get { return m_parent; } } } public partial class FileBlock : KaitaiStruct { public static FileBlock FromFile(string fileName) { return new FileBlock(new KaitaiStream(fileName)); } public FileBlock(KaitaiStream p__io, BlendFile p__parent = null, BlendFile p__root = null) : base(p__io) { m_parent = p__parent; m_root = p__root; f_sdnaStruct = false; _read(); } private void _read() { _code = System.Text.Encoding.GetEncoding("ASCII").GetString(m_io.ReadBytes(4)); _lenBody = m_io.ReadU4le(); _memAddr = m_io.ReadBytes(M_Root.Hdr.Psize); _sdnaIndex = m_io.ReadU4le(); _count = m_io.ReadU4le(); switch (Code) { case "DNA1": { __raw_body = m_io.ReadBytes(LenBody); var io___raw_body = new KaitaiStream(__raw_body); _body = new Dna1Body(io___raw_body, this, m_root); break; } default: { _body = m_io.ReadBytes(LenBody); break; } } } private bool f_sdnaStruct; private DnaStruct _sdnaStruct; public DnaStruct SdnaStruct { get { if (f_sdnaStruct) return _sdnaStruct; if (SdnaIndex != 0) { _sdnaStruct = (DnaStruct)(M_Root.SdnaStructs[(int)SdnaIndex]); } f_sdnaStruct = true; return _sdnaStruct; } } private string _code; private uint _lenBody; private byte[] _memAddr; private uint _sdnaIndex; private uint _count; private object _body; private BlendFile m_root; private BlendFile m_parent; private byte[] __raw_body; /// /// Identifier of the file block /// public string Code { get { return _code; } } /// /// Total length of the data after the header of file block /// public uint LenBody { get { return _lenBody; } } /// /// Memory address the structure was located when written to disk /// public byte[] MemAddr { get { return _memAddr; } } /// /// Index of the SDNA structure /// public uint SdnaIndex { get { return _sdnaIndex; } } /// /// Number of structure located in this file-block /// public uint Count { get { return _count; } } public object Body { get { return _body; } } public BlendFile M_Root { get { return m_root; } } public BlendFile M_Parent { get { return m_parent; } } public byte[] M_RawBody { get { return __raw_body; } } } /// /// DNA1, also known as "Structure DNA", is a special block in /// .blend file, which contains machine-readable specifications of /// all other structures used in this .blend file. /// /// Effectively, this block contains: /// /// * a sequence of "names" (strings which represent field names) /// * a sequence of "types" (strings which represent type name) /// * a sequence of "type lengths" /// * a sequence of "structs" (which describe contents of every /// structure, referring to types and names by index) /// /// /// Reference: Source /// public partial class Dna1Body : KaitaiStruct { public static Dna1Body FromFile(string fileName) { return new Dna1Body(new KaitaiStream(fileName)); } public Dna1Body(KaitaiStream p__io, BlendFile.FileBlock p__parent = null, BlendFile p__root = null) : base(p__io) { m_parent = p__parent; m_root = p__root; _read(); } private void _read() { _id = m_io.ReadBytes(4); if (!((KaitaiStream.ByteArrayCompare(Id, new byte[] { 83, 68, 78, 65 }) == 0))) { throw new ValidationNotEqualError(new byte[] { 83, 68, 78, 65 }, Id, M_Io, "/types/dna1_body/seq/0"); } _nameMagic = m_io.ReadBytes(4); if (!((KaitaiStream.ByteArrayCompare(NameMagic, new byte[] { 78, 65, 77, 69 }) == 0))) { throw new ValidationNotEqualError(new byte[] { 78, 65, 77, 69 }, NameMagic, M_Io, "/types/dna1_body/seq/1"); } _numNames = m_io.ReadU4le(); _names = new List(); for (var i = 0; i < NumNames; i++) { _names.Add(System.Text.Encoding.GetEncoding("UTF-8").GetString(m_io.ReadBytesTerm(0, false, true, true))); } _padding1 = m_io.ReadBytes(KaitaiStream.Mod((4 - M_Io.Pos), 4)); _typeMagic = m_io.ReadBytes(4); if (!((KaitaiStream.ByteArrayCompare(TypeMagic, new byte[] { 84, 89, 80, 69 }) == 0))) { throw new ValidationNotEqualError(new byte[] { 84, 89, 80, 69 }, TypeMagic, M_Io, "/types/dna1_body/seq/5"); } _numTypes = m_io.ReadU4le(); _types = new List(); for (var i = 0; i < NumTypes; i++) { _types.Add(System.Text.Encoding.GetEncoding("UTF-8").GetString(m_io.ReadBytesTerm(0, false, true, true))); } _padding2 = m_io.ReadBytes(KaitaiStream.Mod((4 - M_Io.Pos), 4)); _tlenMagic = m_io.ReadBytes(4); if (!((KaitaiStream.ByteArrayCompare(TlenMagic, new byte[] { 84, 76, 69, 78 }) == 0))) { throw new ValidationNotEqualError(new byte[] { 84, 76, 69, 78 }, TlenMagic, M_Io, "/types/dna1_body/seq/9"); } _lengths = new List(); for (var i = 0; i < NumTypes; i++) { _lengths.Add(m_io.ReadU2le()); } _padding3 = m_io.ReadBytes(KaitaiStream.Mod((4 - M_Io.Pos), 4)); _strcMagic = m_io.ReadBytes(4); if (!((KaitaiStream.ByteArrayCompare(StrcMagic, new byte[] { 83, 84, 82, 67 }) == 0))) { throw new ValidationNotEqualError(new byte[] { 83, 84, 82, 67 }, StrcMagic, M_Io, "/types/dna1_body/seq/12"); } _numStructs = m_io.ReadU4le(); _structs = new List(); for (var i = 0; i < NumStructs; i++) { _structs.Add(new DnaStruct(m_io, this, m_root)); } } private byte[] _id; private byte[] _nameMagic; private uint _numNames; private List _names; private byte[] _padding1; private byte[] _typeMagic; private uint _numTypes; private List _types; private byte[] _padding2; private byte[] _tlenMagic; private List _lengths; private byte[] _padding3; private byte[] _strcMagic; private uint _numStructs; private List _structs; private BlendFile m_root; private BlendFile.FileBlock m_parent; public byte[] Id { get { return _id; } } public byte[] NameMagic { get { return _nameMagic; } } public uint NumNames { get { return _numNames; } } public List Names { get { return _names; } } public byte[] Padding1 { get { return _padding1; } } public byte[] TypeMagic { get { return _typeMagic; } } public uint NumTypes { get { return _numTypes; } } public List Types { get { return _types; } } public byte[] Padding2 { get { return _padding2; } } public byte[] TlenMagic { get { return _tlenMagic; } } public List Lengths { get { return _lengths; } } public byte[] Padding3 { get { return _padding3; } } public byte[] StrcMagic { get { return _strcMagic; } } public uint NumStructs { get { return _numStructs; } } public List Structs { get { return _structs; } } public BlendFile M_Root { get { return m_root; } } public BlendFile.FileBlock M_Parent { get { return m_parent; } } } public partial class Header : KaitaiStruct { public static Header FromFile(string fileName) { return new Header(new KaitaiStream(fileName)); } public Header(KaitaiStream p__io, BlendFile p__parent = null, BlendFile p__root = null) : base(p__io) { m_parent = p__parent; m_root = p__root; f_psize = false; _read(); } private void _read() { _magic = m_io.ReadBytes(7); if (!((KaitaiStream.ByteArrayCompare(Magic, new byte[] { 66, 76, 69, 78, 68, 69, 82 }) == 0))) { throw new ValidationNotEqualError(new byte[] { 66, 76, 69, 78, 68, 69, 82 }, Magic, M_Io, "/types/header/seq/0"); } _ptrSizeId = ((BlendFile.PtrSize)m_io.ReadU1()); _endian = ((BlendFile.Endian)m_io.ReadU1()); _version = System.Text.Encoding.GetEncoding("ASCII").GetString(m_io.ReadBytes(3)); } private bool f_psize; private sbyte _psize; /// /// Number of bytes that a pointer occupies /// public sbyte Psize { get { if (f_psize) return _psize; _psize = (sbyte)((PtrSizeId == BlendFile.PtrSize.Bits64 ? 8 : 4)); f_psize = true; return _psize; } } private byte[] _magic; private PtrSize _ptrSizeId; private Endian _endian; private string _version; private BlendFile m_root; private BlendFile m_parent; public byte[] Magic { get { return _magic; } } /// /// Size of a pointer; all pointers in the file are stored in this format /// public PtrSize PtrSizeId { get { return _ptrSizeId; } } /// /// Type of byte ordering used /// public Endian Endian { get { return _endian; } } /// /// Blender version used to save this file /// public string Version { get { return _version; } } public BlendFile M_Root { get { return m_root; } } public BlendFile M_Parent { get { return m_parent; } } } public partial class DnaField : KaitaiStruct { public static DnaField FromFile(string fileName) { return new DnaField(new KaitaiStream(fileName)); } public DnaField(KaitaiStream p__io, BlendFile.DnaStruct p__parent = null, BlendFile p__root = null) : base(p__io) { m_parent = p__parent; m_root = p__root; f_type = false; f_name = false; _read(); } private void _read() { _idxType = m_io.ReadU2le(); _idxName = m_io.ReadU2le(); } private bool f_type; private string _type; public string Type { get { if (f_type) return _type; _type = (string)(M_Parent.M_Parent.Types[IdxType]); f_type = true; return _type; } } private bool f_name; private string _name; public string Name { get { if (f_name) return _name; _name = (string)(M_Parent.M_Parent.Names[IdxName]); f_name = true; return _name; } } private ushort _idxType; private ushort _idxName; private BlendFile m_root; private BlendFile.DnaStruct m_parent; public ushort IdxType { get { return _idxType; } } public ushort IdxName { get { return _idxName; } } public BlendFile M_Root { get { return m_root; } } public BlendFile.DnaStruct M_Parent { get { return m_parent; } } } private bool f_sdnaStructs; private List _sdnaStructs; public List SdnaStructs { get { if (f_sdnaStructs) return _sdnaStructs; _sdnaStructs = (List)(((BlendFile.Dna1Body)(Blocks[(Blocks.Count - 2)].Body)).Structs); f_sdnaStructs = true; return _sdnaStructs; } } private Header _hdr; private List _blocks; private BlendFile m_root; private KaitaiStruct m_parent; public Header Hdr { get { return _hdr; } } public List Blocks { get { return _blocks; } } public BlendFile M_Root { get { return m_root; } } public KaitaiStruct M_Parent { get { return m_parent; } } } }