/// <summary> /// Initialize with no data. /// </summary> public G1Model() { Section = new ResourceSectionHeader { Magic = DataType.Model, Size = -1, Version = SupportedVersion.ToVersionA() }; SectionRoot = new PackedResource(); }
/// <summary> /// Parse G1M from the provided data buffer /// </summary> /// <param name="data"></param> /// <param name="ignoreVersion"></param> /// <param name="parse"></param> public G1Model(Span <byte> data, bool ignoreVersion = true, bool parse = true) { if (!data.Matches(DataType.Model)) { throw new InvalidOperationException("Not an G1M stream"); } Section = MemoryMarshal.Read <ResourceSectionHeader>(data); if (!ignoreVersion && Section.Version.ToVersion() != SupportedVersion) { throw new NotSupportedException($"G1M version {Section.Version.ToVersion()} is not supported!"); } var header = MemoryMarshal.Read <ModelHeader>(data.Slice(0xC)); SectionRoot = new PackedResource(data.Slice(header.HeaderSize, Section.Size - header.HeaderSize), header.SectionCount); // ReSharper disable once ForeachCanBePartlyConvertedToQueryUsingAnotherGetEnumerator foreach (var block in SectionRoot.Sections) { var sectionHeader = MemoryMarshal.Read <ResourceSectionHeader>(block.Span); var dataBlock = block.Span.Slice(SizeHelper.SizeOf <ResourceSectionHeader>()); if (!parse) { Sections.Add(new G1MStub(dataBlock, sectionHeader)); continue; } // ReSharper disable once SwitchExpressionHandlesSomeKnownEnumValuesWithExceptionInDefault var section = sectionHeader.Magic switch { DataType.G1MS => (IKTGLSection) new G1MSkeleton(dataBlock, ignoreVersion, sectionHeader), DataType.G1MF => new G1MFormat(dataBlock, ignoreVersion, sectionHeader), DataType.G1MG => new G1MGeometry(dataBlock, ignoreVersion, sectionHeader), DataType.G1MM => new G1MMatrix(dataBlock, ignoreVersion, sectionHeader), DataType.EXTR => new G1Extra(dataBlock, ignoreVersion, sectionHeader), _ => new G1MStub(dataBlock, sectionHeader) }; Sections.Add(section); } }