Пример #1
0
        /// <summary>
        /// Function to load the associated sprite texture based on the project metadata.
        /// </summary>
        /// <param name="graphics">The graphics interface to use when looking up or creating the texture.</param>
        /// <param name="fileSystem">The file system containing the file to load.</param>
        /// <param name="metadata">The metadata for the project.</param>
        /// <param name="imagePath">The path to the image.</param>
        /// <param name="usage">The intended usage for the texture.</param>
        /// <param name="codecs">The list of available codecs.</param>
        /// <returns>A new texture containing the sprite texture data.</returns>
        private static GorgonTexture2D GetTexture(GorgonGraphics graphics, IGorgonFileSystem fileSystem, IProjectMetadata metadata, string imagePath, ResourceUsage usage, IReadOnlyDictionary <string, IGorgonImageCodec> codecs)
        {
            bool shouldConvertToPremultiplied = false;

            // First, check to see if this texture isn't already loaded into memory.
            GorgonTexture2D texture = graphics.LocateResourcesByName <GorgonTexture2D>(imagePath).FirstOrDefault();

            if (texture != null)
            {
                return(texture);
            }

            if (!metadata.ProjectItems.TryGetValue(imagePath, out ProjectItemMetadata textureMetadata))
            {
                return(null);
            }

            if (textureMetadata.Attributes.TryGetValue("PremultipliedAlpha", out string isPremultiplied))
            {
#pragma warning disable CA1806 // Do not ignore method results
                bool.TryParse(isPremultiplied, out shouldConvertToPremultiplied);
#pragma warning restore CA1806 // Do not ignore method results
            }

            if ((!textureMetadata.Attributes.TryGetValue(CommonEditorConstants.ContentTypeAttr, out string contentType)) ||
                (!string.Equals(contentType, CommonEditorContentTypes.ImageType, StringComparison.OrdinalIgnoreCase)) ||
                (!textureMetadata.Attributes.TryGetValue("ImageCodec", out string imageCodecTypeName)) ||
                (!codecs.TryGetValue(imageCodecTypeName, out IGorgonImageCodec codec)))
            {
                return(null);
            }

            IGorgonVirtualFile file = fileSystem.GetFile(imagePath);

            if (file == null)
            {
                return(null);
            }

            using (Stream fileStream = file.OpenStream())
            {
                texture = GorgonTexture2D.FromStream(graphics, fileStream, codec, file.Size, new GorgonTexture2DLoadOptions
                {
                    ConvertToPremultipliedAlpha = shouldConvertToPremultiplied,
                    IsTextureCube = false,
                    Name          = file.FullPath,
                    Binding       = TextureBinding.ShaderResource,
                    Usage         = (((usage & ResourceUsage.None) == ResourceUsage.None) || ((usage & ResourceUsage.Staging) == ResourceUsage.Staging)) ? ResourceUsage.Default : usage
                });
            }

            return(texture);
        }
Пример #2
0
        /// <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);
        }
Пример #3
0
        /// <summary>
        /// Function to read a texture from the JSON data.
        /// </summary>
        /// <param name="reader">The JSON reader to use.</param>
        /// <param name="textureName">The name of the texture.</param>
        /// <returns></returns>
        public GorgonTexture2DView ReadTexture(JsonReader reader, out string textureName)
        {
            textureName = string.Empty;

            if ((reader.TokenType != JsonToken.StartObject) ||
                (_graphics == null))
            {
                return(null);
            }

            int?         texWidth       = null;
            int?         texHeight      = null;
            int?         texMipCount    = null;
            int?         texArrayCount  = null;
            BufferFormat?texFormat      = null;
            int?         viewMipStart   = null;
            int?         viewMipCount   = null;
            int?         viewArrayStart = null;
            int?         viewArrayCount = null;
            BufferFormat?viewFormat     = null;

            while ((reader.Read()) && (reader.TokenType != JsonToken.EndObject))
            {
                if (reader.TokenType != JsonToken.PropertyName)
                {
                    continue;
                }

                switch (reader.Value.ToString())
                {
                case "name":
                    textureName = reader.ReadAsString();
                    break;

                case "texWidth":
                    texWidth = reader.ReadAsInt32();
                    break;

                case "texHeight":
                    texHeight = reader.ReadAsInt32();
                    break;

                case "texFormat":
                    texFormat = (BufferFormat?)reader.ReadAsInt32();
                    break;

                case "texArrayCount":
                    texArrayCount = reader.ReadAsInt32();
                    break;

                case "texMipCount":
                    texMipCount = reader.ReadAsInt32();
                    break;

                case "arrayStart":
                    viewArrayStart = reader.ReadAsInt32();
                    break;

                case "arrayCount":
                    viewArrayCount = reader.ReadAsInt32();
                    break;

                case "mipStart":
                    viewMipStart = reader.ReadAsInt32();
                    break;

                case "mipCount":
                    viewMipCount = reader.ReadAsInt32();
                    break;

                case "format":
                    viewFormat = (BufferFormat?)reader.ReadAsInt32();
                    break;
                }
            }

            if ((string.IsNullOrWhiteSpace(textureName)) ||
                (texWidth == null) ||
                (texHeight == null) ||
                (texFormat == null) ||
                (texArrayCount == null) ||
                (texMipCount == null) ||
                (viewArrayStart == null) ||
                (viewArrayCount == null) ||
                (viewMipStart == null) ||
                (viewMipCount == null) ||
                (viewFormat == null))
            {
                if (string.IsNullOrWhiteSpace(textureName))
                {
                    _graphics?.Log.Print("Attempted to load a texture from JSON data, but texture was not in memory and name is unknown, or JSON texture data is not in the correct format.",
                                         LoggingLevel.Verbose);
                }

                return(null);
            }

            if (_override != null)
            {
                return(_override);
            }

            GorgonTexture2D texture = _graphics?.LocateResourcesByName <GorgonTexture2D>(textureName)
                                      .FirstOrDefault(item => (item.Width == texWidth) &&
                                                      (item.Height == texHeight) &&
                                                      (item.Format == texFormat) &&
                                                      (item.MipLevels == texMipCount) &&
                                                      (item.ArrayCount == texArrayCount));

            return(texture?.GetShaderResourceView(viewFormat.Value, viewMipStart.Value, viewMipCount.Value, viewArrayStart.Value, viewArrayCount.Value));
        }
Пример #4
0
        /// <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, GorgonChunkReader reader, GorgonTexture2DView overrideTexture)
        {
            var sprite = new GorgonSprite();

            if (!reader.HasChunk(FileHeader))
            {
                throw new GorgonException(GorgonResult.CannotRead, Resources.GOR2DIO_ERR_INVALID_HEADER);
            }

            reader.Begin(FileHeader);
            reader.Begin(SpriteDataChunk);

            sprite.Anchor = reader.Read <DX.Vector2>();
            sprite.Size   = reader.Read <DX.Size2F>();
            sprite.Anchor = new DX.Vector2(sprite.Anchor.X / sprite.Size.Width, sprite.Anchor.Y / sprite.Size.Height);

            sprite.HorizontalFlip = reader.ReadBoolean();
            sprite.VerticalFlip   = reader.ReadBoolean();

            // Read vertex colors.
            sprite.CornerColors.UpperLeft  = reader.Read <GorgonColor>();
            sprite.CornerColors.UpperRight = reader.Read <GorgonColor>();
            sprite.CornerColors.LowerLeft  = reader.Read <GorgonColor>();
            sprite.CornerColors.LowerRight = reader.Read <GorgonColor>();

            // Write vertex offsets.
            sprite.CornerOffsets.UpperLeft  = new DX.Vector3(reader.Read <DX.Vector2>(), 0);
            sprite.CornerOffsets.UpperRight = new DX.Vector3(reader.Read <DX.Vector2>(), 0);
            sprite.CornerOffsets.LowerLeft  = new DX.Vector3(reader.Read <DX.Vector2>(), 0);
            sprite.CornerOffsets.LowerRight = new DX.Vector3(reader.Read <DX.Vector2>(), 0);

            reader.End();

            // Read rendering information.
            reader.Begin(RenderDataChunk);

            // Culling mode is not per-sprite anymore.
            reader.SkipBytes(Unsafe.SizeOf <CullingMode>());
            sprite.AlphaTest = reader.Read <GorgonRangeF>();

            // Blending values are not per-sprite anymore.
            // Depth/stencil values are not per-sprite anymore.
            reader.SkipBytes(91);
            reader.End();

            // Read texture information.
            reader.Begin(TextureDataChunk);
            GorgonColor borderColor = reader.Read <GorgonColor>();

            TextureWrap         hWrap       = ConvertV2TextureWrapToTextureAddress(reader.Read <int>());
            TextureWrap         vWrap       = ConvertV2TextureWrapToTextureAddress(reader.Read <int>());
            SampleFilter        filter      = ConvertV2TextureFilterToFilter(reader.Read <TextureFilter>());
            string              textureName = reader.ReadString();
            GorgonTexture2DView textureView;

            // Bind the texture (if we have one bound to this sprite) if it's already loaded, otherwise defer it.
            if ((!string.IsNullOrEmpty(textureName)) && (overrideTexture == null))
            {
                GorgonTexture2D texture = graphics.LocateResourcesByName <GorgonTexture2D>(textureName).FirstOrDefault();

                // If we used the editor build to sprite, the path to the texture is stored in the name instead of just the name.
                // So let's try and strip out the path information and extension and try again.
                if (texture == null)
                {
                    textureName = Path.GetFileNameWithoutExtension(textureName);
                    texture     = graphics.LocateResourcesByName <GorgonTexture2D>(textureName).FirstOrDefault();
                }

                textureView = texture?.GetShaderResourceView();
            }
            else
            {
                textureView = overrideTexture;
            }

            sprite.TextureRegion = reader.ReadRectangleF();

            if (textureView != null)
            {
                // V2 used black transparent by default, so convert it to our default so we can keep from creating unnecessary states.
                if (borderColor == GorgonColor.BlackTransparent)
                {
                    borderColor = GorgonColor.White;
                }

                sprite.Texture        = textureView;
                sprite.TextureSampler = CreateSamplerState(graphics, filter, borderColor, hWrap, vWrap);
            }

            reader.End();
            reader.End();

            return(sprite);
        }