/// <summary> /// Function to retrieve the name of the associated texture. /// </summary> /// <param name="stream">The stream containing the texture data.</param> /// <returns>The name of the texture associated with the sprite, or <b>null</b> if no texture was found.</returns> protected override string OnGetAssociatedTextureName(Stream stream) { GorgonChunkFileReader reader = null; GorgonBinaryReader binReader = null; try { reader = new GorgonChunkFileReader(stream, new[] { CurrentFileHeader }); reader.Open(); if (!IsReadableChunkFile(reader)) { return(null); } // No texture data in this file. if (!reader.Chunks.Contains(TextureData)) { return(null); } binReader = reader.OpenChunk(TextureData); string result = binReader.ReadString(); reader.CloseChunk(); return(result); } finally { binReader?.Dispose(); reader?.Close(); } }
/// <summary> /// Function to determine if the data in a stream is readable by this codec. /// </summary> /// <param name="stream">The stream containing the data.</param> /// <returns><b>true</b> if the data can be read, or <b>false</b> if not.</returns> protected override bool OnIsReadable(Stream stream) { using (var reader = new GorgonBinaryReader(stream, true)) { // If we don't have at least 10 bytes, then this file is not valid. if ((stream.Length - stream.Position) < 16) { return(false); } string headerVersion = reader.ReadString(); if ((!headerVersion.StartsWith("GORSPR", StringComparison.OrdinalIgnoreCase)) || (headerVersion.Length < 7) || (headerVersion.Length > 9)) { return(false); } // Get the version information. switch (headerVersion.ToUpperInvariant()) { case "GORSPR1": case "GORSPR1.1": case "GORSPR1.2": return(true); default: return(false); } } }
/// <summary> /// Function to read the sprite data from a stream. /// </summary> /// <param name="stream">The stream containing the sprite.</param> /// <param name="byteCount">The number of bytes to read from the stream.</param> /// <param name="overrideTexture">[Optional] The texture to assign to the sprite instead of the texture associated with the name stored in the file.</param> /// <returns>A new <see cref="GorgonSprite"/>.</returns> protected override GorgonSprite OnReadFromStream(Stream stream, int byteCount, GorgonTexture2DView overrideTexture) { using (var reader = new GorgonBinaryReader(stream, true)) { // We don't need the byte count here. return(LoadSprite(Graphics, reader, overrideTexture)); } }
/// <summary> /// Function to load the texture information. /// </summary> /// <param name="reader">The reader containing the texture information.</param> /// <param name="overrideTexture">The texture to assign to the sprite instead of the texture associated with the name stored in the file.</param> /// <param name="textureOffset">The texture transform offset.</param> /// <param name="textureScale">The texture transform scale.</param> /// <param name="textureArrayIndex">The texture array index.</param> /// <returns>The texture attached to the sprite.</returns> private GorgonTexture2DView LoadTexture(GorgonBinaryReader reader, GorgonTexture2DView overrideTexture, out DX.Vector2 textureOffset, out DX.Vector2 textureScale, out int textureArrayIndex) { // Write out as much info about the texture as we can so we can look it up based on these values when loading. string textureName = reader.ReadString(); textureOffset = DX.Vector2.Zero; textureScale = DX.Vector2.One; textureArrayIndex = 0; if (string.IsNullOrWhiteSpace(textureName)) { return(null); } reader.ReadValue(out textureOffset); reader.ReadValue(out textureScale); reader.ReadValue(out textureArrayIndex); reader.ReadValue(out int textureWidth); reader.ReadValue(out int textureHeight); reader.ReadValue(out BufferFormat textureFormat); reader.ReadValue(out int textureArrayCount); reader.ReadValue(out int textureMipCount); GorgonTexture2D texture = null; // Locate the texture resource. if (overrideTexture == null) { texture = Renderer.Graphics.LocateResourcesByName <GorgonTexture2D>(textureName) .FirstOrDefault(item => item.Width == textureWidth && item.Height == textureHeight && item.Format == textureFormat && item.ArrayCount == textureArrayCount && item.MipLevels == textureMipCount); if (texture == null) { textureOffset = DX.Vector2.Zero; textureScale = DX.Vector2.One; textureArrayIndex = 0; return(null); } } reader.ReadValue(out int viewArrayIndex); reader.ReadValue(out int viewArrayCount); reader.ReadValue(out int viewMipSlice); reader.ReadValue(out int viewMipCount); reader.ReadValue(out BufferFormat viewFormat); return(overrideTexture ?? texture.GetShaderResourceView(viewFormat, viewMipSlice, viewMipCount, viewArrayIndex, viewArrayCount)); }
/// <summary> /// Function to determine if the chunk file is a readable file. /// </summary> /// <param name="reader">The chunk file reader to use.</param> /// <returns><b>true</b> if the chunk file is readable, or <b>false</b> if not.</returns> private bool IsReadableChunkFile(GorgonChunkFileReader reader) { if ((!reader.Chunks.Contains(VersionData)) || (!reader.Chunks.Contains(AnimationData))) { return(false); } using (GorgonBinaryReader binReader = reader.OpenChunk(VersionData)) { var fileVersion = new Version(binReader.ReadByte(), binReader.ReadByte()); reader.CloseChunk(); return(Version.Equals(fileVersion)); } }
/// <summary> /// Function to determine if the data in a stream is readable by this codec. /// </summary> /// <param name="stream">The stream containing the data.</param> /// <returns><b>true</b> if the data can be read, or <b>false</b> if not.</returns> protected override bool OnIsReadable(Stream stream) { using (var reader = new GorgonBinaryReader(stream, true)) { if ((stream.Length - stream.Position) < sizeof(ulong) * 2) { return(false); } ulong chunkHeader = reader.ReadUInt64(); // Skip the size, we don't need it. reader.ReadUInt32(); ulong chunkFileData = reader.ReadUInt64(); return((chunkHeader == FileHeader.ChunkID()) && (chunkFileData == SpriteDataChunk.ChunkID())); } }
/// <summary> /// Function to retrieve the name of the associated texture. /// </summary> /// <param name="stream">The stream containing the texture data.</param> /// <returns>The name of the texture associated with the sprite, or <b>null</b> if no texture was found.</returns> protected override string OnGetAssociatedTextureName(Stream stream) { using (var reader = new GorgonBinaryReader(stream, true)) { string headerVersion = reader.ReadString(); if ((!headerVersion.StartsWith("GORSPR", StringComparison.OrdinalIgnoreCase)) || (headerVersion.Length < 7) || (headerVersion.Length > 9)) { return(null); } // Get the version information. switch (headerVersion.ToUpperInvariant()) { case "GORSPR1": case "GORSPR1.1": case "GORSPR1.2": break; default: return(null); } // We don't need the sprite name. reader.ReadString(); // Find out if we have an image. if (!reader.ReadBoolean()) { return(null); } reader.ReadBoolean(); return(reader.ReadString()); } }
/// <summary> /// Function to read the animation data from a stream. /// </summary> /// <param name="stream">The stream containing the animation.</param> /// <param name="byteCount">The number of bytes to read from the stream.</param> /// <returns>A new <see cref="IGorgonAnimation"/>.</returns> protected override IGorgonAnimation OnReadFromStream(Stream stream, int byteCount) { var builder = new GorgonAnimationBuilder(); var reader = new GorgonChunkFileReader(stream, new[] { CurrentFileHeader }); GorgonBinaryReader binReader = null; try { reader.Open(); binReader = reader.OpenChunk(AnimationData); string name = binReader.ReadString(); float length = binReader.ReadSingle(); bool isLooped = binReader.ReadBoolean(); int loopCount = binReader.ReadInt32(); reader.CloseChunk(); int keyCount; if (reader.Chunks.Contains(PositionData)) { binReader = reader.OpenChunk(PositionData); builder.PositionInterpolationMode(binReader.ReadValue <TrackInterpolationMode>()); keyCount = binReader.ReadInt32(); IGorgonTrackKeyBuilder <GorgonKeyVector3> track = builder.EditPositions(); for (int i = 0; i < keyCount; ++i) { track.SetKey(new GorgonKeyVector3(binReader.ReadSingle(), binReader.ReadValue <DX.Vector3>())); } track.EndEdit(); reader.CloseChunk(); } if (reader.Chunks.Contains(ScaleData)) { binReader = reader.OpenChunk(ScaleData); builder.ScaleInterpolationMode(binReader.ReadValue <TrackInterpolationMode>()); keyCount = binReader.ReadInt32(); IGorgonTrackKeyBuilder <GorgonKeyVector3> track = builder.EditScale(); for (int i = 0; i < keyCount; ++i) { track.SetKey(new GorgonKeyVector3(binReader.ReadSingle(), binReader.ReadValue <DX.Vector3>())); } track.EndEdit(); reader.CloseChunk(); } if (reader.Chunks.Contains(RotationData)) { binReader = reader.OpenChunk(RotationData); builder.RotationInterpolationMode(binReader.ReadValue <TrackInterpolationMode>()); keyCount = binReader.ReadInt32(); IGorgonTrackKeyBuilder <GorgonKeyVector3> track = builder.EditRotation(); for (int i = 0; i < keyCount; ++i) { track.SetKey(new GorgonKeyVector3(binReader.ReadSingle(), binReader.ReadValue <DX.Vector3>())); } track.EndEdit(); reader.CloseChunk(); } if (reader.Chunks.Contains(SizeData)) { binReader = reader.OpenChunk(SizeData); builder.SizeInterpolationMode(binReader.ReadValue <TrackInterpolationMode>()); keyCount = binReader.ReadInt32(); IGorgonTrackKeyBuilder <GorgonKeyVector3> track = builder.EditSize(); for (int i = 0; i < keyCount; ++i) { track.SetKey(new GorgonKeyVector3(binReader.ReadSingle(), binReader.ReadValue <DX.Vector3>())); } track.EndEdit(); reader.CloseChunk(); } if (reader.Chunks.Contains(BoundsData)) { binReader = reader.OpenChunk(BoundsData); builder.RotationInterpolationMode(binReader.ReadValue <TrackInterpolationMode>()); keyCount = binReader.ReadInt32(); IGorgonTrackKeyBuilder <GorgonKeyRectangle> track = builder.EditRectangularBounds(); for (int i = 0; i < keyCount; ++i) { track.SetKey(new GorgonKeyRectangle(binReader.ReadSingle(), binReader.ReadValue <DX.RectangleF>())); } track.EndEdit(); reader.CloseChunk(); } if (reader.Chunks.Contains(ColorData)) { binReader = reader.OpenChunk(ColorData); builder.RotationInterpolationMode(binReader.ReadValue <TrackInterpolationMode>()); keyCount = binReader.ReadInt32(); IGorgonTrackKeyBuilder <GorgonKeyGorgonColor> track = builder.EditColors(); for (int i = 0; i < keyCount; ++i) { track.SetKey(new GorgonKeyGorgonColor(binReader.ReadSingle(), binReader.ReadValue <GorgonColor>())); } track.EndEdit(); reader.CloseChunk(); } IGorgonAnimation result; if (!reader.Chunks.Contains(TextureData)) { result = builder.Build(name, length); result.IsLooped = isLooped; result.LoopCount = loopCount; return(result); } binReader = reader.OpenChunk(TextureData); keyCount = binReader.ReadInt32(); IGorgonTrackKeyBuilder <GorgonKeyTexture2D> textureTrack = builder.Edit2DTexture(); for (int i = 0; i < keyCount; ++i) { float time = binReader.ReadSingle(); byte hasTexture = binReader.ReadByte(); GorgonTexture2DView texture = null; string textureName = string.Empty; if (hasTexture != 0) { texture = LoadTexture(binReader, out textureName); if ((texture == null) && (string.IsNullOrWhiteSpace(textureName))) { Renderer.Log.Print("Attempted to load a texture from the data, but the texture was not in memory and the name is unknown.", LoggingLevel.Verbose); continue; } } if ((texture == null) && (hasTexture != 0)) { textureTrack.SetKey(new GorgonKeyTexture2D(time, textureName, binReader.ReadValue <DX.RectangleF>(), binReader.ReadInt32())); } else { textureTrack.SetKey(new GorgonKeyTexture2D(time, texture, binReader.ReadValue <DX.RectangleF>(), binReader.ReadInt32())); } } textureTrack.EndEdit(); reader.CloseChunk(); result = builder.Build(name, length); result.IsLooped = isLooped; result.LoopCount = loopCount; return(result); } finally { binReader?.Dispose(); reader.Close(); } }
/// <summary> /// Function to load a version 1.x Gorgon sprite. /// </summary> /// <param name="graphics">The graphics interface used to create states.</param> /// <param name="reader">Binary reader to use to read in the data.</param> /// <param name="overrideTexture">The texture to assign to the sprite instead of the texture associated with the name stored in the file.</param> /// <returns>The sprite from the stream data.</returns> private static GorgonSprite LoadSprite(GorgonGraphics graphics, GorgonBinaryReader reader, GorgonTexture2DView overrideTexture) { Version version; string imageName = string.Empty; string headerVersion = reader.ReadString(); if ((!headerVersion.StartsWith("GORSPR", StringComparison.OrdinalIgnoreCase)) || (headerVersion.Length < 7) || (headerVersion.Length > 9)) { throw new GorgonException(GorgonResult.CannotRead, Resources.GOR2DIO_ERR_INVALID_HEADER); } var sprite = new GorgonSprite(); // Get the version information. switch (headerVersion.ToUpperInvariant()) { case "GORSPR1": version = new Version(1, 0); break; case "GORSPR1.1": version = new Version(1, 1); break; case "GORSPR1.2": version = new Version(1, 2); break; default: throw new GorgonException(GorgonResult.CannotRead, string.Format(Resources.GOR2DIO_ERR_VERSION_MISMATCH, headerVersion)); } // We don't need the sprite name. reader.ReadString(); // Find out if we have an image. if (reader.ReadBoolean()) { bool isRenderTarget = reader.ReadBoolean(); imageName = reader.ReadString(); // We won't be supporting reading render targets from sprites in this version. if (isRenderTarget) { // Skip the target data. reader.ReadInt32(); reader.ReadInt32(); reader.ReadInt32(); reader.ReadBoolean(); reader.ReadBoolean(); } } // We don't use "inherited" values anymore. But we need them because // the file doesn't include inherited data. bool InheritAlphaMaskFunction = reader.ReadBoolean(); bool InheritAlphaMaskValue = reader.ReadBoolean(); bool InheritBlending = reader.ReadBoolean(); bool InheritHorizontalWrapping = reader.ReadBoolean(); bool InheritSmoothing = reader.ReadBoolean(); bool InheritStencilCompare = reader.ReadBoolean(); bool InheritStencilEnabled = reader.ReadBoolean(); bool InheritStencilFailOperation = reader.ReadBoolean(); bool InheritStencilMask = reader.ReadBoolean(); bool InheritStencilPassOperation = reader.ReadBoolean(); bool InheritStencilReference = reader.ReadBoolean(); bool InheritStencilZFailOperation = reader.ReadBoolean(); bool InheritVerticalWrapping = reader.ReadBoolean(); bool InheritDepthBias = true; bool InheritDepthTestFunction = true; bool InheritDepthWriteEnabled = true; // Get version 1.1 fields. if ((version.Major == 1) && (version.Minor >= 1)) { InheritDepthBias = reader.ReadBoolean(); InheritDepthTestFunction = reader.ReadBoolean(); InheritDepthWriteEnabled = reader.ReadBoolean(); } // Get the size of the sprite. sprite.Size = new DX.Size2F(reader.ReadSingle(), reader.ReadSingle()); // Older versions of the sprite object used pixel space for their texture coordinates. We will have to // fix up these coordinates into texture space once we have a texture loaded. At this point, there's no guarantee // that the texture was loaded safely, so we'll have to defer it until later. // Also, older versions used the size the determine the area on the texture to cover. So use the size to // get the texture bounds. var textureOffset = new DX.Vector2(reader.ReadSingle(), reader.ReadSingle()); // Read the anchor. // Gorgon v3 anchors are relative, so we need to convert them based on our sprite size. sprite.Anchor = new DX.Vector2(reader.ReadSingle() / sprite.Size.Width, reader.ReadSingle() / sprite.Size.Height); // Get vertex offsets. sprite.CornerOffsets.UpperLeft = new DX.Vector3(reader.ReadSingle(), reader.ReadSingle(), 0); sprite.CornerOffsets.UpperRight = new DX.Vector3(reader.ReadSingle(), reader.ReadSingle(), 0); sprite.CornerOffsets.LowerRight = new DX.Vector3(reader.ReadSingle(), reader.ReadSingle(), 0); sprite.CornerOffsets.LowerLeft = new DX.Vector3(reader.ReadSingle(), reader.ReadSingle(), 0); // Get vertex colors. sprite.CornerColors.UpperLeft = new GorgonColor(reader.ReadInt32()); sprite.CornerColors.UpperRight = new GorgonColor(reader.ReadInt32()); sprite.CornerColors.LowerLeft = new GorgonColor(reader.ReadInt32()); sprite.CornerColors.LowerRight = new GorgonColor(reader.ReadInt32()); // Skip shader information. Version 1.0 had shader information attached to the sprite. if ((version.Major == 1) && (version.Minor < 1)) { if (reader.ReadBoolean()) { reader.ReadString(); reader.ReadBoolean(); if (reader.ReadBoolean()) { reader.ReadString(); } } } // We no longer have an alpha mask function. if (!InheritAlphaMaskFunction) { reader.ReadInt32(); } if (!InheritAlphaMaskValue) { // Direct 3D 9 used a value from 0..255 for alpha masking, we use // a scalar value so convert to a scalar. sprite.AlphaTest = new GorgonRangeF(0.0f, reader.ReadInt32() / 255.0f); } // Set the blending mode. if (!InheritBlending) { // Skip the blending mode. We don't use it per-sprite. reader.ReadInt32(); reader.ReadInt32(); reader.ReadInt32(); } // Get alpha blending mode. if ((version.Major == 1) && (version.Minor >= 2)) { // Skip the blending mode information. We don't use it per-sprite. reader.ReadInt32(); reader.ReadInt32(); } TextureWrap hWrap = TextureWrap.Clamp; TextureWrap vWrap = TextureWrap.Clamp; SampleFilter filter = SampleFilter.MinMagMipLinear; GorgonColor samplerBorder = GorgonColor.White; // Get horizontal wrapping mode. if (!InheritHorizontalWrapping) { hWrap = ConvertImageAddressToTextureAddress(reader.ReadInt32()); } // Get smoothing mode. if (!InheritSmoothing) { filter = ConvertSmoothingToFilter(reader.ReadInt32()); } // Get stencil stuff. if (!InheritStencilCompare) { // We don't use depth/stencil info per sprite anymore. reader.ReadInt32(); } if (!InheritStencilEnabled) { // We don't enable stencil in the same way anymore, so skip this value. reader.ReadBoolean(); } if (!InheritStencilFailOperation) { // We don't use depth/stencil info per sprite anymore. reader.ReadInt32(); } if (!InheritStencilMask) { // We don't use depth/stencil info per sprite anymore. reader.ReadInt32(); } if (!InheritStencilPassOperation) { // We don't use depth/stencil info per sprite anymore. reader.ReadInt32(); } if (!InheritStencilReference) { // We don't use depth/stencil info per sprite anymore. reader.ReadInt32(); } if (!InheritStencilZFailOperation) { // We don't use depth/stencil info per sprite anymore. reader.ReadInt32(); } // Get vertical wrapping mode. if (!InheritVerticalWrapping) { vWrap = ConvertImageAddressToTextureAddress(reader.ReadInt32()); } // Get depth info. if ((version.Major == 1) && (version.Minor >= 1)) { if (!InheritDepthBias) { // Depth bias values are quite different on D3D9 than they are on D3D11, so skip this. reader.ReadSingle(); } if (!InheritDepthTestFunction) { // We don't use depth/stencil info per sprite anymore. reader.ReadInt32(); } if (!InheritDepthWriteEnabled) { // We don't use depth/stencil info per sprite anymore. reader.ReadBoolean(); } samplerBorder = new GorgonColor(reader.ReadInt32()); // The border in the older version defaults to black. To make it more performant, reverse this value to white. if (samplerBorder == GorgonColor.Black) { samplerBorder = GorgonColor.White; } } // Get flipped flags. sprite.HorizontalFlip = reader.ReadBoolean(); sprite.VerticalFlip = reader.ReadBoolean(); GorgonTexture2DView textureView; // Bind the texture (if we have one bound to this sprite) if it's already loaded, otherwise defer it. if ((!string.IsNullOrEmpty(imageName)) && (overrideTexture == null)) { GorgonTexture2D texture = graphics.LocateResourcesByName <GorgonTexture2D>(imageName).FirstOrDefault(); textureView = texture?.GetShaderResourceView(); } else { textureView = overrideTexture; } // If we cannot load the image, then fall back to the standard coordinates. if (textureView == null) { sprite.TextureRegion = new DX.RectangleF(0, 0, 1, 1); } else { sprite.TextureRegion = new DX.RectangleF(textureOffset.X / textureView.Width, textureOffset.Y / textureView.Height, sprite.Size.Width / textureView.Width, sprite.Size.Height / textureView.Height); sprite.TextureSampler = CreateSamplerState(graphics, filter, samplerBorder, hWrap, vWrap); } sprite.Texture = textureView; return(sprite); }
/// <summary> /// Function to read the sprite data from a stream. /// </summary> /// <param name="stream">The stream containing the sprite.</param> /// <param name="byteCount">The number of bytes to read from the stream.</param> /// <param name="overrideTexture">The texture to assign to the sprite instead of the texture associated with the name stored in the file.</param> /// <returns>A new <see cref="GorgonPolySprite"/>.</returns> protected override GorgonPolySprite OnReadFromStream(Stream stream, int byteCount, GorgonTexture2DView overrideTexture) { var reader = new GorgonChunkFileReader(stream, new[] { CurrentFileHeader }); GorgonBinaryReader binReader = null; var sprite = new GorgonPolySpriteBuilder(Renderer); try { reader.Open(); binReader = reader.OpenChunk(SpriteData); sprite.Anchor(binReader.ReadValue <DX.Vector2>()); // If we do not have alpha test information, then skip writing its data. if (binReader.ReadBoolean()) { sprite.AlphaTest(binReader.ReadValue <GorgonRangeF>()); } reader.CloseChunk(); binReader = reader.OpenChunk(VertexData); int vertexCount = binReader.ReadInt32(); for (int i = 0; i < vertexCount; ++i) { sprite.AddVertex(new GorgonPolySpriteVertex(binReader.ReadValue <DX.Vector2>(), binReader.ReadValue <GorgonColor>(), binReader.ReadValue <DX.Vector2>())); } reader.CloseChunk(); if (reader.Chunks.Contains(TextureData)) { binReader = reader.OpenChunk(TextureData); sprite.Texture(LoadTexture(binReader, overrideTexture, out DX.Vector2 textureOffset, out DX.Vector2 textureScale, out int textureArrayIndex)); sprite.TextureArrayIndex(textureArrayIndex); sprite.TextureTransform(textureOffset, textureScale); reader.CloseChunk(); } if (!reader.Chunks.Contains(TextureSamplerData)) { return(sprite.Build()); } var builder = new GorgonSamplerStateBuilder(Renderer.Graphics); binReader = reader.OpenChunk(TextureSamplerData); binReader.ReadValue(out SampleFilter filter); binReader.ReadValue(out GorgonColor borderColor); binReader.ReadValue(out Comparison compareFunc); binReader.ReadValue(out TextureWrap wrapU); binReader.ReadValue(out TextureWrap wrapV); binReader.ReadValue(out TextureWrap wrapW); binReader.ReadValue(out int maxAnisotropy); binReader.ReadValue(out float minLod); binReader.ReadValue(out float maxLod); binReader.ReadValue(out float mipLodBias); reader.CloseChunk(); sprite.TextureSampler(builder.Wrapping(wrapU, wrapV, wrapW, borderColor) .Filter(filter) .ComparisonFunction(compareFunc) .MaxAnisotropy(maxAnisotropy) .MipLevelOfDetail(minLod, maxLod, mipLodBias) .Build()); return(sprite.Build()); } finally { binReader?.Dispose(); reader.Close(); } }
/// <summary> /// Function to read the sprite data from a stream. /// </summary> /// <param name="stream">The stream containing the sprite.</param> /// <param name="byteCount">The number of bytes to read from the stream.</param> /// <param name="overrideTexture">The texture to assign to the sprite instead of the texture associated with the name stored in the file.</param> /// <returns>A new <see cref="GorgonSprite"/>.</returns> protected override GorgonSprite OnReadFromStream(Stream stream, int byteCount, GorgonTexture2DView overrideTexture) { var reader = new GorgonChunkFileReader(stream, new[] { CurrentFileHeader }); GorgonBinaryReader binReader = null; var sprite = new GorgonSprite(); try { reader.Open(); binReader = reader.OpenChunk(SpriteData); sprite.Size = binReader.ReadValue <DX.Size2F>(); sprite.Anchor = binReader.ReadValue <DX.Vector2>(); // If we do not have alpha test information, then skip writing its data. if (binReader.ReadBoolean()) { sprite.AlphaTest = binReader.ReadValue <GorgonRangeF>(); } // Write out corner data. sprite.CornerOffsets.UpperLeft = binReader.ReadValue <DX.Vector3>(); sprite.CornerOffsets.UpperRight = binReader.ReadValue <DX.Vector3>(); sprite.CornerOffsets.LowerLeft = binReader.ReadValue <DX.Vector3>(); sprite.CornerOffsets.LowerRight = binReader.ReadValue <DX.Vector3>(); sprite.CornerColors.UpperLeft = binReader.ReadValue <GorgonColor>(); sprite.CornerColors.UpperRight = binReader.ReadValue <GorgonColor>(); sprite.CornerColors.LowerLeft = binReader.ReadValue <GorgonColor>(); sprite.CornerColors.LowerRight = binReader.ReadValue <GorgonColor>(); reader.CloseChunk(); if (reader.Chunks.Contains(TextureData)) { binReader = reader.OpenChunk(TextureData); sprite.Texture = LoadTexture(binReader, overrideTexture, out DX.RectangleF textureCoordinates, out int textureArrayIndex); sprite.TextureRegion = textureCoordinates; sprite.TextureArrayIndex = textureArrayIndex; reader.CloseChunk(); } if (!reader.Chunks.Contains(TextureSamplerData)) { return(sprite); } var builder = new GorgonSamplerStateBuilder(Renderer.Graphics); binReader = reader.OpenChunk(TextureSamplerData); binReader.ReadValue(out SampleFilter filter); binReader.ReadValue(out GorgonColor borderColor); binReader.ReadValue(out Comparison compareFunc); binReader.ReadValue(out TextureWrap wrapU); binReader.ReadValue(out TextureWrap wrapV); binReader.ReadValue(out TextureWrap wrapW); binReader.ReadValue(out int maxAnisotropy); binReader.ReadValue(out float minLod); binReader.ReadValue(out float maxLod); binReader.ReadValue(out float mipLodBias); reader.CloseChunk(); sprite.TextureSampler = builder.Wrapping(wrapU, wrapV, wrapW, borderColor) .Filter(filter) .ComparisonFunction(compareFunc) .MaxAnisotropy(maxAnisotropy) .MipLevelOfDetail(minLod, maxLod, mipLodBias) .Build(); return(sprite); } finally { binReader?.Dispose(); reader.Close(); } }
/// <summary> /// Function to skip the unnecessary parts of the file and move to the animation section. /// </summary> /// <param name="reader">The binary reader for the stream.</param> /// <param name="version">The version of the sprite.</param> private static void SkipToAnimationSection(GorgonBinaryReader reader, Version version) { // We don't need the sprite name. reader.ReadString(); // Find out if we have an image. if (reader.ReadBoolean()) { bool isRenderTarget = reader.ReadBoolean(); reader.ReadString(); // We won't be supporting reading render targets from sprites in this version. if (isRenderTarget) { // Skip the target data. for (int i = 0; i < 3; ++i) { reader.ReadInt32(); } reader.ReadBoolean(); reader.ReadBoolean(); } } // We don't use "inherited" values anymore. But we need them because // the file doesn't include inherited data. bool InheritAlphaMaskFunction = reader.ReadBoolean(); bool InheritAlphaMaskValue = reader.ReadBoolean(); bool InheritBlending = reader.ReadBoolean(); bool InheritHorizontalWrapping = reader.ReadBoolean(); bool InheritSmoothing = reader.ReadBoolean(); bool InheritStencilCompare = reader.ReadBoolean(); bool InheritStencilEnabled = reader.ReadBoolean(); bool InheritStencilFailOperation = reader.ReadBoolean(); bool InheritStencilMask = reader.ReadBoolean(); bool InheritStencilPassOperation = reader.ReadBoolean(); bool InheritStencilReference = reader.ReadBoolean(); bool InheritStencilZFailOperation = reader.ReadBoolean(); bool InheritVerticalWrapping = reader.ReadBoolean(); bool InheritDepthBias = true; bool InheritDepthTestFunction = true; bool InheritDepthWriteEnabled = true; // Get version 1.1 fields. if ((version.Major == 1) && (version.Minor >= 1)) { InheritDepthBias = reader.ReadBoolean(); InheritDepthTestFunction = reader.ReadBoolean(); InheritDepthWriteEnabled = reader.ReadBoolean(); } // Get the size of the sprite. for (int i = 0; i < 14; ++i) { reader.ReadSingle(); // 0 } // Get vertex colors. for (int i = 0; i < 4; ++i) { reader.ReadInt32(); } // Skip shader information. Version 1.0 had shader information attached to the sprite. if ((version.Major == 1) && (version.Minor < 1)) { if (reader.ReadBoolean()) { reader.ReadString(); reader.ReadBoolean(); if (reader.ReadBoolean()) { reader.ReadString(); } } } // We no longer have an alpha mask function. if (!InheritAlphaMaskFunction) { reader.ReadInt32(); } if (!InheritAlphaMaskValue) { // Direct 3D 9 used a value from 0..255 for alpha masking, we use // a scalar value so convert to a scalar. reader.ReadInt32(); } // Set the blending mode. if (!InheritBlending) { // Skip the blending mode. We don't use it per-sprite. for (int i = 0; i < 3; ++i) { reader.ReadInt32(); } } // Get alpha blending mode. if ((version.Major == 1) && (version.Minor >= 2)) { // Skip the blending mode information. We don't use it per-sprite. reader.ReadInt32(); reader.ReadInt32(); } // Get horizontal wrapping mode. if (!InheritHorizontalWrapping) { reader.ReadInt32(); } // Get smoothing mode. if (!InheritSmoothing) { reader.ReadInt32(); } // Get stencil stuff. if (!InheritStencilCompare) { // We don't use depth/stencil info per sprite anymore. reader.ReadInt32(); } if (!InheritStencilEnabled) { // We don't enable stencil in the same way anymore, so skip this value. reader.ReadBoolean(); } if (!InheritStencilFailOperation) { // We don't use depth/stencil info per sprite anymore. reader.ReadInt32(); } if (!InheritStencilMask) { // We don't use depth/stencil info per sprite anymore. reader.ReadInt32(); } if (!InheritStencilPassOperation) { // We don't use depth/stencil info per sprite anymore. reader.ReadInt32(); } if (!InheritStencilReference) { // We don't use depth/stencil info per sprite anymore. reader.ReadInt32(); } if (!InheritStencilZFailOperation) { // We don't use depth/stencil info per sprite anymore. reader.ReadInt32(); } // Get vertical wrapping mode. if (!InheritVerticalWrapping) { reader.ReadInt32(); } // Get depth info. if ((version.Major == 1) && (version.Minor >= 1)) { if (!InheritDepthBias) { // Depth bias values are quite different on D3D9 than they are on D3D11, so skip this. reader.ReadSingle(); } if (!InheritDepthTestFunction) { // We don't use depth/stencil info per sprite anymore. reader.ReadInt32(); } if (!InheritDepthWriteEnabled) { // We don't use depth/stencil info per sprite anymore. reader.ReadBoolean(); } reader.ReadInt32(); } // Get flipped flags. reader.ReadBoolean(); reader.ReadBoolean(); }
/// <summary> /// Function to read 2D vector data. /// </summary> /// <param name="reader">The reader containing the track data.</param> /// <param name="keyCount">The number of keys to read.</param> /// <returns>A list of track times and vector2 values.</returns> private static IReadOnlyList <(float time, DX.Vector2 value)> ReadVec2(GorgonBinaryReader reader, int keyCount) { var keys = new (float, DX.Vector2)[keyCount];