/// <summary> /// Initializes a new instance of the InvalidContentException class with the specified error message, the identity of the content throwing the exception, and a reference to the inner exception that is the cause of this exception. /// </summary> /// <param name="message">A message that describes the error.</param> /// <param name="contentIdentity">Information about the content item that caused this error, including the file name. In some cases, a location within the file (of the problem) is specified.</param> /// <param name="innerException">The exception that is the cause of the current exception. If innerException is not a null reference, the current exception is raised in a catch block that handles the inner exception.</param> public InvalidContentException( string message, ContentIdentity contentIdentity, Exception innerException ) : base(message, innerException) { ContentIdentity = contentIdentity; }
/// <summary> /// Initializes a new instance of ExternalReference, specifying the file path relative to another content item. /// </summary> /// <param name="filename">The name of the referenced file.</param> /// <param name="relativeToContent">The content that the path specified in filename is relative to.</param> public ExternalReference(string filename, ContentIdentity relativeToContent) { if (string.IsNullOrEmpty(filename)) { throw new ArgumentNullException(nameof(filename)); } if (relativeToContent == null) { throw new ArgumentNullException(nameof(relativeToContent)); } if (string.IsNullOrEmpty(relativeToContent.SourceFilename)) { throw new ArgumentNullException("relativeToContent.SourceFilename"); } // The intermediate serializer from XNA has the external reference // path walking up to the content project directory and then back // down to the asset path. We don't appear to have any way to do // that from here, so we'll work with the absolute path and let the // higher level process sort out any relative paths they need. var basePath = Path.GetDirectoryName(relativeToContent.SourceFilename); Filename = PathHelper.Normalize(Path.GetFullPath(Path.Combine(basePath, filename))); }
internal static TextureContent Import(string filename, ContentImporterContext context) { var identity = new ContentIdentity(filename); TextureContent output = null; using (var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read)) using (var reader = new BinaryReader(fileStream)) { // Signature ("DDS ") if (reader.ReadByte() != 0x44 || reader.ReadByte() != 0x44 || reader.ReadByte() != 0x53 || reader.ReadByte() != 0x20) { throw new ContentLoadException("Invalid file signature"); } var header = new DdsHeader { // Read DDS_HEADER dwSize = reader.ReadUInt32() }; if (header.dwSize != 124) { throw new ContentLoadException("Invalid DDS_HEADER dwSize value"); } header.dwFlags = (Ddsd)reader.ReadUInt32(); header.dwHeight = reader.ReadUInt32(); header.dwWidth = reader.ReadUInt32(); header.dwPitchOrLinearSize = reader.ReadUInt32(); header.dwDepth = reader.ReadUInt32(); header.dwMipMapCount = reader.ReadUInt32(); // The next 11 DWORDs are reserved and unused for (int i = 0; i < 11; ++i) { reader.ReadUInt32(); } // Read DDS_PIXELFORMAT header.ddspf.dwSize = reader.ReadUInt32(); if (header.ddspf.dwSize != 32) { throw new ContentLoadException("Invalid DDS_PIXELFORMAT dwSize value"); } header.ddspf.dwFlags = (Ddpf)reader.ReadUInt32(); header.ddspf.dwFourCC = (FourCC)reader.ReadUInt32(); header.ddspf.dwRgbBitCount = reader.ReadUInt32(); header.ddspf.dwRBitMask = reader.ReadUInt32(); header.ddspf.dwGBitMask = reader.ReadUInt32(); header.ddspf.dwBBitMask = reader.ReadUInt32(); header.ddspf.dwABitMask = reader.ReadUInt32(); // Continue reading DDS_HEADER header.dwCaps = (DdsCaps)reader.ReadUInt32(); header.dwCaps2 = (DdsCaps2)reader.ReadUInt32(); reader.ReadUInt32(); // dwCaps3 unused reader.ReadUInt32(); // dwCaps4 unused reader.ReadUInt32(); // dwReserved2 unused // Check for the existence of the DDS_HEADER_DXT10 struct next if (header.ddspf.dwFlags == Ddpf.FourCC && header.ddspf.dwFourCC == FourCC.Dx10) { throw new ContentLoadException("Unsupported DDS_HEADER_DXT10 struct found"); } int faceCount = 1; int mipMapCount = (int)(header.dwCaps.HasFlag(DdsCaps.MipMap) ? header.dwMipMapCount : 1); if (header.dwCaps2.HasFlag(DdsCaps2.Cubemap)) { if (!header.dwCaps2.HasFlag(DdsCaps2.CubemapAllFaces)) { throw new ContentLoadException("Incomplete cubemap in DDS file"); } faceCount = 6; output = new TextureCubeContent() { Identity = identity }; } else { output = new Texture2DContent() { Identity = identity }; } var format = GetSurfaceFormat(ref header.ddspf, out bool rbSwap); for (int f = 0; f < faceCount; ++f) { int w = (int)header.dwWidth; int h = (int)header.dwHeight; var mipMaps = new MipmapChain(); for (int m = 0; m < mipMapCount; ++m) { var content = CreateBitmapContent(format, w, h); var byteCount = GetBitmapSize(format, w, h); // A 24-bit format is slightly different if (header.ddspf.dwRgbBitCount == 24) { byteCount = 3 * w * h; } var bytes = reader.ReadBytes(byteCount); if (rbSwap) { switch (format) { case SurfaceFormat.Bgr565: ByteSwapBGR565(bytes); break; case SurfaceFormat.Bgra4444: ByteSwapBGRA4444(bytes); break; case SurfaceFormat.Bgra5551: ByteSwapBGRA5551(bytes); break; case SurfaceFormat.Rgba32: if (header.ddspf.dwRgbBitCount == 32) { ByteSwapRGBX(bytes); } else if (header.ddspf.dwRgbBitCount == 24) { ByteSwapRGB(bytes); } break; } } if ((format == SurfaceFormat.Rgba32) && header.ddspf.dwFlags.HasFlag(Ddpf.Rgb) && !header.ddspf.dwFlags.HasFlag(Ddpf.AlphaPixels)) { // Fill or add alpha with opaque if (header.ddspf.dwRgbBitCount == 32) { ByteFillAlpha(bytes); } else if (header.ddspf.dwRgbBitCount == 24) { ByteExpandAlpha(ref bytes); } } content.SetPixelData(bytes); mipMaps.Add(content); w = Math.Max(1, w / 2); h = Math.Max(1, h / 2); } output.Faces[f] = mipMaps; } } return(output); }