/// <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 GorgonChunkReader(stream)) { if (!reader.HasChunk(FileHeader)) { throw new GorgonException(GorgonResult.CannotRead, Resources.GOR2DIO_ERR_INVALID_HEADER); } reader.Begin(FileHeader); reader.Begin(SpriteDataChunk); reader.SkipBytes(DX.Vector2.SizeInBytes + Unsafe.SizeOf <DX.Size2F>() + (sizeof(bool) * 2) + (GorgonColor.SizeInBytes * 4) + (DX.Vector2.SizeInBytes * 4)); reader.End(); // Read rendering information. reader.Begin(RenderDataChunk); reader.SkipBytes(Unsafe.SizeOf <CullingMode>() + Unsafe.SizeOf <GorgonRangeF>() + 91); reader.End(); // Read texture information. reader.Begin(TextureDataChunk); reader.SkipBytes(GorgonColor.SizeInBytes + (sizeof(int) * 2) + Unsafe.SizeOf <TextureFilter>()); return(reader.ReadString()); } }
/// <summary> /// Function to load an animation from a stream. /// </summary> /// <param name="stream">Stream to load from.</param> /// <returns>The animation in the stream.</returns> /// <exception cref="System.ArgumentNullException">Thrown when the <paramref name="stream"/> parameter is NULL (Nothing in VB.Net).</exception> /// <exception cref="System.ArgumentException">Thrown when the stream parameter does not contain a Gorgon animation file. /// <para>-or-</para> /// <para>Thrown when the name of the animation is already present in the controller animation collection.</para> /// <para>-or-</para> /// <para>Thrown when a track type cannot be associated with a property on the object type that the controller was declared with.</para> /// </exception> /// <exception cref="System.InvalidCastException">Thrown when the animation being loaded is for a different type than the controller was declared with.</exception> public GorgonAnimation <T> FromStream(Stream stream) { GorgonAnimation <T> animation; GorgonDebug.AssertNull(stream, "stream"); using (var chunk = new GorgonChunkReader(stream)) { // Get the header. chunk.Begin(AnimationVersion); chunk.Begin("ANIMDATA"); // Get the type data. string typeString = chunk.ReadString(); if (typeString != AnimatedObjectType.FullName) { throw new InvalidCastException(string.Format(Resources.GORANM_ANIMATION_TYPE_MISMATCH, typeString, AnimatedObjectType.FullName)); } // Get the name. string animationName = chunk.ReadString(); if (Contains(animationName)) { throw new ArgumentException(string.Format(Resources.GORANM_ANIMATION_ALREADY_EXISTS, animationName), "stream"); } animation = new GorgonAnimation <T>(this, animationName, chunk.ReadFloat()) { IsLooped = chunk.ReadBoolean() }; chunk.End(); // Get all the tracks. while (chunk.HasChunk("TRCKDATA")) { chunk.Begin("TRCKDATA"); string trackName = chunk.ReadString(); // Get the name of the track. if (!animation.Tracks.Contains(trackName)) { throw new ArgumentException( string.Format(Resources.GORANM_TRACK_TYPE_DOES_NOT_EXIST, trackName, AnimatedObjectType.FullName), "stream"); } animation.Tracks[trackName].FromChunk(chunk); chunk.End(); } } Add(animation); return(animation); }
/// <summary> /// Function to read a font from a stream. /// </summary> /// <param name="name">Name of the font object.</param> /// <param name="stream">Stream to read from.</param> /// <param name="missingTextureFunction">[Optional] A function that is called if a required user defined texture has not been loaded for the font.</param> /// <returns>The font in the stream.</returns> /// <remarks> /// The fonts will not store user defined glyph textures, in order to facilitate the loading of the textures the users must either load the texture /// before loading the font or specify a callback method in the <paramref name="missingTextureFunction"/> parameter. This function will pass a name /// for the texture and will expect a texture to be returned. If NULL is returned, then an exception will be raised. /// <para>Fonts may only be created on the immediate context.</para></remarks> /// <exception cref="System.ArgumentNullException">Thrown when the <paramref name="stream"/> or the <paramref name="name"/> parameters are NULL.</exception> /// <exception cref="System.ArgumentException">Thrown if the name parameter is an empty string. /// <para>-or-</para> /// <para>Thrown if the font uses external textures, but the stream is not a file stream.</para></exception> /// <exception cref="GorgonLibrary.GorgonException">Thrown if the font cannot be read. /// <para>-or-</para> /// <para>Thrown if the graphics context is deferred.</para> /// </exception> public GorgonFont FromStream(string name, Stream stream, Func <string, Size, GorgonTexture2D> missingTextureFunction = null) { if (string.IsNullOrWhiteSpace(name)) { throw new ArgumentException(Resources.GORGFX_PARAMETER_MUST_NOT_BE_EMPTY, "name"); } if (stream == null) { throw new ArgumentNullException("stream"); } if (stream.Length == 0) { throw new ArgumentException(Resources.GORGFX_PARAMETER_MUST_NOT_BE_EMPTY, "stream"); } var font = new GorgonFont(_graphics, name, new GorgonFontSettings()); using (var chunk = new GorgonChunkReader(stream)) { chunk.Begin(GorgonFont.FileHeader); font.ReadFont(chunk, missingTextureFunction); } _graphics.AddTrackedObject(font); return(font); }
/// <summary> /// Function to read the track data from a data chunk. /// </summary> /// <param name="chunk">Chunk to read.</param> internal void FromChunk(GorgonChunkReader chunk) { InterpolationMode = chunk.Read <TrackInterpolationMode>(); // Load all key frames from this track. while (chunk.HasChunk("KEYFRAME")) { IKeyFrame key = MakeKey(); chunk.Begin("KEYFRAME"); key.FromChunk(chunk); chunk.End(); KeyFrames.Add(key); } }
/// <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); }
/// <summary> /// Function to read the renderable data from a stream. /// </summary> /// <param name="stream">Open file stream containing the renderable data.</param> /// <exception cref="System.ArgumentNullException">Thrown when the <paramref name="stream" /> parameter is NULL (Nothing in VB.Net).</exception> /// <exception cref="System.IO.IOException">Thrown when the stream parameter is not opened for reading data.</exception> /// <exception cref="GorgonLibrary.GorgonException">Thrown when the data in the stream does not contain valid renderable data, or contains a newer version of the renderable than Gorgon can handle.</exception> void IPersistedRenderable.Load(Stream stream) { if (stream == null) { throw new ArgumentNullException("stream"); } if (!stream.CanRead) { throw new IOException(Resources.GOR2D_STREAM_WRITE_ONLY); } GorgonChunkReader chunk = null; // Read the sprite in. try { chunk = new GorgonChunkReader(stream); if (!chunk.HasChunk(FileHeader)) { // The old format doesn't use the chunker. chunk.Dispose(); chunk = null; // Check to see if it's an older version of the Gorgon sprite data. using (var oldReader = new GorgonBinaryReader(stream, true)) { GorgonV1SpriteReader.LoadSprite(this, oldReader); return; } } // Read in the file header. chunk.Begin(FileHeader); chunk.Begin("SPRTDATA"); Anchor = chunk.Read <Vector2>(); Size = chunk.Read <Vector2>(); HorizontalFlip = chunk.ReadBoolean(); VerticalFlip = chunk.ReadBoolean(); // Read vertex colors. for (int i = 0; i < Vertices.Length; i++) { Vertices[i].Color = chunk.Read <GorgonColor>(); } // Write vertex offsets. chunk.ReadRange(_offsets); chunk.End(); // Read rendering information. chunk.Begin("RNDRDATA"); CullingMode = chunk.Read <CullingMode>(); AlphaTestValues = chunk.Read <GorgonRangeF>(); Blending.AlphaOperation = chunk.Read <BlendOperation>(); Blending.BlendOperation = chunk.Read <BlendOperation>(); Blending.BlendFactor = chunk.Read <GorgonColor>(); Blending.DestinationAlphaBlend = chunk.Read <BlendType>(); Blending.DestinationBlend = chunk.Read <BlendType>(); Blending.SourceAlphaBlend = chunk.Read <BlendType>(); Blending.SourceBlend = chunk.Read <BlendType>(); Blending.WriteMask = chunk.Read <ColorWriteMaskFlags>(); DepthStencil.BackFace.ComparisonOperator = chunk.Read <ComparisonOperator>(); DepthStencil.BackFace.DepthFailOperation = chunk.Read <StencilOperation>(); DepthStencil.BackFace.FailOperation = chunk.Read <StencilOperation>(); DepthStencil.BackFace.PassOperation = chunk.Read <StencilOperation>(); DepthStencil.FrontFace.ComparisonOperator = chunk.Read <ComparisonOperator>(); DepthStencil.FrontFace.DepthFailOperation = chunk.Read <StencilOperation>(); DepthStencil.FrontFace.FailOperation = chunk.Read <StencilOperation>(); DepthStencil.FrontFace.PassOperation = chunk.Read <StencilOperation>(); DepthStencil.DepthBias = chunk.ReadInt32(); DepthStencil.DepthComparison = chunk.Read <ComparisonOperator>(); DepthStencil.StencilReference = chunk.ReadInt32(); DepthStencil.IsDepthWriteEnabled = chunk.ReadBoolean(); DepthStencil.StencilReadMask = chunk.ReadByte(); DepthStencil.StencilReadMask = chunk.ReadByte(); chunk.End(); // Read collider information. if (chunk.HasChunk("COLLIDER")) { chunk.Begin("COLLIDER"); Type colliderType = Type.GetType(chunk.ReadString()); Debug.Assert(colliderType != null, "Collider is NULL!!"); var collider = (Gorgon2DCollider)Activator.CreateInstance(colliderType); collider.ReadFromChunk(chunk); chunk.End(); } // Read texture information. chunk.Begin("TXTRDATA"); TextureSampler.BorderColor = chunk.Read <GorgonColor>(); TextureSampler.HorizontalWrapping = chunk.Read <TextureAddressing>(); TextureSampler.VerticalWrapping = chunk.Read <TextureAddressing>(); TextureSampler.TextureFilter = chunk.Read <TextureFilter>(); DeferredTextureName = chunk.ReadString(); TextureRegion = chunk.ReadRectangleF(); } finally { if (chunk != null) { chunk.Dispose(); } } }