Beispiel #1
0
 /// <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);
        }