/// <summary> /// Function to read a keyframe from a chunk. /// </summary> /// <param name="chunk">Chunk to read from.</param> void IKeyFrame.FromChunk(GorgonChunkReader chunk) { Value = null; Time = chunk.ReadFloat(); bool hasTexture = chunk.ReadBoolean(); // Get the texture region we're using. TextureRegion = chunk.ReadRectangleF(); if (!hasTexture) { return; } // Get our texture name. _textureName = chunk.ReadString(); // Read in our texture information. _settings = new GorgonTexture2DSettings { ArrayCount = chunk.ReadInt32(), Format = chunk.Read <BufferFormat>(), Size = chunk.ReadSize(), IsTextureCube = chunk.ReadBoolean(), MipCount = chunk.ReadInt32(), Multisampling = new GorgonMultisampling(chunk.ReadInt32(), chunk.ReadInt32()), Usage = BufferUsage.Default, ShaderViewFormat = BufferFormat.Unknown }; // Defer load the texture. GetTexture(); }
/// <summary> /// Function to create 2D Gorgon image data from a single System.Drawing.Image. /// </summary> /// <param name="wic">Windows Imaging Component interface to use.</param> /// <param name="image">An image to convert.</param> /// <param name="options">Options for conversion.</param> /// <returns>The converted image data.</returns> public static GorgonImageData Create2DImageDataFromImage(GorgonWICImage wic, Image image, GorgonGDIOptions options) { if (options.Format == BufferFormat.Unknown) { options.Format = GetBufferFormat(image.PixelFormat); } if (options.Format == BufferFormat.Unknown) { throw new GorgonException(GorgonResult.FormatNotSupported, string.Format(Resources.GORGFX_FORMAT_NOT_SUPPORTED, image.PixelFormat)); } if (options.Width < 1) { options.Width = image.Width; } if (options.Height < 1) { options.Height = image.Height; } // Specify 0 to generate a full mip chain. options.MipCount = options.MipCount < 1 ? GorgonImageData.GetMaxMipCount(options.Width, options.Height) : options.MipCount.Min(GorgonImageData.GetMaxMipCount(options.Width, options.Height)); // Create our settings. var settings = new GorgonTexture2DSettings { Width = options.Width, Height = options.Height, MipCount = options.MipCount, ArrayCount = 1, Format = options.Format, AllowUnorderedAccessViews = options.AllowUnorderedAccess, ShaderViewFormat = options.ViewFormat, Usage = options.Usage }; // Create our image data. var data = new GorgonImageData(settings); // Using the image, convert to a WIC bitmap object. using (Bitmap bitmap = wic.CreateWICImageFromImage(image)) { for (int mipLevel = 0; mipLevel < options.MipCount; mipLevel++) { var buffer = data.Buffers[mipLevel]; wic.AddWICBitmapToImageData(bitmap, options.Filter, options.Dither, buffer, options.UseClipping); } } return(data); }
/// <summary> /// Initializes a new instance of the <see cref="GorgonKeyTexture2D" /> struct. /// </summary> /// <param name="time">The time for the key frame.</param> /// <param name="value">The value to apply to the key frame.</param> /// <param name="region">Region on the texture to update.</param> public GorgonKeyTexture2D(float time, GorgonTexture2D value, RectangleF region) { Time = time; _dataType = typeof(GorgonTexture2D); Value = value; TextureRegion = region; if (value != null) { _textureName = value.Name; _settings = value.Settings; } else { // We didn't specify a texture, so don't defer it for later. _textureName = string.Empty; _settings = null; } }
/// <summary> /// Function to read the meta data for the image. /// </summary> /// <param name="stream">Stream containing the image data.</param> /// <returns>An image settings object containing information about the image.</returns> private static IImageSettings ReadMetaData(Stream stream) { if (!stream.CanRead) { throw new ArgumentException(@"Stream is write only.", "stream"); } if (stream.Position + TvHeader.SizeInBytes >= stream.Length) { throw new EndOfStreamException(); } // We only support 2D images with the tv format. var settings = new GorgonTexture2DSettings(); TvHeader header; // Load the header for the image. using (var reader = new GorgonBinaryReader(stream, true)) { header = reader.ReadValue <TvHeader>(); } // Ensure we've got the correct data. if (header.MagicValueData != MagicValue) { throw new ArgumentException(@"The image data is not a tv image.", "stream"); } // Ensure the width/height are valid. if ((header.Width < 0) || (header.Height < 0)) { throw new ArgumentException(@"The image in this stream has an invalid width/height.", "stream"); } settings.Width = header.Width; settings.Height = header.Height; settings.Format = BufferFormat.R8G8B8A8_UIntNormal; return(settings); }
/// <summary> /// Function to retrieve the texture if it's not assigned. /// </summary> /// <returns>TRUE if the texture was found, FALSE if not.</returns> internal bool GetTexture() { if (!string.IsNullOrEmpty(_textureName)) { // Copy to local values because LINQ doesn't seem to work with members // of a struct. string textureName = _textureName; GorgonTexture2DSettings settings = _settings; // Our texture is deferred, so we need to find it in the graphics object tracked // object list. // In order to do that, we need to find all graphics objects first: var graphics = Gorgon.GetTrackedObjectsOfType <GorgonGraphics>(); // We have no graphics, then we can't do display a texture anyway, so throw an exception. if (graphics.Count == 0) { throw new GorgonException(GorgonResult.NotInitialized, Resources.GORANM_KEYFRAME_TEXTURE_NOGFX); } var textures = (from graphicsObject in graphics from graphicsTexture in graphicsObject.GetTrackedObjectsOfType <GorgonTexture2D>() select graphicsTexture).ToArray(); // Then, we begin our search by looking at -all- the texture information we have: Value = (from graphicsTexture in textures where (string.Equals(graphicsTexture.Name, textureName, StringComparison.OrdinalIgnoreCase)) && (graphicsTexture.Settings.ArrayCount == settings.ArrayCount) && (graphicsTexture.Settings.Format == settings.Format) && (graphicsTexture.Settings.Height == settings.Height) && (graphicsTexture.Settings.Width == settings.Width) && (graphicsTexture.Settings.IsTextureCube == settings.IsTextureCube) && (graphicsTexture.Settings.MipCount == settings.MipCount) && (graphicsTexture.Settings.Multisampling == settings.Multisampling) select graphicsTexture).FirstOrDefault(); // ReSharper disable ConvertIfStatementToNullCoalescingExpression if (Value == null) { // That one failed, so just try and look it up by name, width, height and format. Value = (from graphicsTexture in textures where (string.Equals(graphicsTexture.Name, textureName, StringComparison.OrdinalIgnoreCase)) && (graphicsTexture.Settings.Format == settings.Format) && (graphicsTexture.Settings.Height == settings.Height) && (graphicsTexture.Settings.Width == settings.Width) select graphicsTexture).FirstOrDefault() ?? (from graphicsTexture in textures where (string.Equals(graphicsTexture.Name, textureName, StringComparison.OrdinalIgnoreCase)) select graphicsTexture).FirstOrDefault(); } // ReSharper restore ConvertIfStatementToNullCoalescingExpression } // We have our texture, stop deferring. if (Value == null) { return(false); } _textureName = string.Empty; return(true); }
/// <summary> /// Function to read in the DDS header from a stream. /// </summary> /// <param name="stream">Stream containing the data.</param> /// <param name="conversionFlags">Flags for conversion.</param> /// <returns>New image settings.</returns> private IImageSettings ReadHeader(GorgonDataStream stream, out TGAConversionFlags conversionFlags) { IImageSettings settings = new GorgonTexture2DSettings(); conversionFlags = TGAConversionFlags.None; // Get the header for the file. var header = stream.Read <TGAHeader>(); if ((header.ColorMapType != 0) || (header.ColorMapLength != 0) || (header.Width <= 0) || (header.Height <= 0) || ((header.Descriptor & TGADescriptor.Interleaved2Way) == TGADescriptor.Interleaved2Way) || ((header.Descriptor & TGADescriptor.Interleaved4Way) == TGADescriptor.Interleaved4Way)) { throw new IOException(string.Format(Resources.GORGFX_IMAGE_FILE_INCORRECT_DECODER, Codec)); } settings.MipCount = 1; settings.ArrayCount = 1; switch (header.ImageType) { case TGAImageType.TrueColor: case TGAImageType.TrueColorRLE: switch (header.BPP) { case 16: settings.Format = BufferFormat.B5G5R5A1_UIntNormal; break; case 24: case 32: settings.Format = BufferFormat.R8G8B8A8_UIntNormal; if (header.BPP == 24) { conversionFlags |= TGAConversionFlags.Expand; } break; } if (header.ImageType == TGAImageType.TrueColorRLE) { conversionFlags |= TGAConversionFlags.RLE; } break; case TGAImageType.BlackAndWhite: case TGAImageType.BlackAndWhiteRLE: if (header.BPP == 8) { settings.Format = BufferFormat.R8_UIntNormal; } else { throw new IOException(string.Format(Resources.GORGFX_FORMAT_NOT_SUPPORTED, header.ImageType)); } if (header.ImageType == TGAImageType.BlackAndWhiteRLE) { conversionFlags |= TGAConversionFlags.RLE; } break; default: throw new IOException(string.Format(Resources.GORGFX_FORMAT_NOT_SUPPORTED, header.ImageType)); } settings.Width = header.Width; settings.Height = header.Height; if ((header.Descriptor & TGADescriptor.InvertX) == TGADescriptor.InvertX) { conversionFlags |= TGAConversionFlags.InvertX; } if ((header.Descriptor & TGADescriptor.InvertY) == TGADescriptor.InvertY) { conversionFlags |= TGAConversionFlags.InvertY; } if (header.IDLength <= 0) { return(settings); } // Skip these bytes. for (int i = 0; i < header.IDLength; i++) { stream.ReadByte(); } return(settings); }
/// <summary> /// Function to create 2D Gorgon image data from multiple single System.Drawing.Images. /// </summary> /// <param name="wic">Windows Imaging Component interface to use.</param> /// <param name="images">Images to convert.</param> /// <param name="options">Options for conversion.</param> /// <returns>The converted image data.</returns> public static GorgonImageData Create2DImageDataFromImages(GorgonWICImage wic, IList <Image> images, GorgonGDIOptions options) { if (options.Format == BufferFormat.Unknown) { options.Format = GetBufferFormat(images[0].PixelFormat); } if (options.Format == BufferFormat.Unknown) { throw new GorgonException(GorgonResult.FormatNotSupported, string.Format(Resources.GORGFX_FORMAT_NOT_SUPPORTED, images[0].PixelFormat)); } if (images.Any(item => item.PixelFormat != images[0].PixelFormat)) { throw new GorgonException(GorgonResult.CannotCreate, string.Format(Resources.GORGFX_IMAGE_MUST_BE_SAME_FORMAT, images[0].PixelFormat)); } if (options.Width < 1) { options.Width = images[0].Width; } if (options.Height < 1) { options.Height = images[0].Height; } if (options.ArrayCount < 1) { options.ArrayCount = 1; } options.MipCount = options.MipCount < 1 ? 1 : options.MipCount.Min(GorgonImageData.GetMaxMipCount(options.Width, options.Height)); // Create our settings. var settings = new GorgonTexture2DSettings { Width = options.Width, Height = options.Height, MipCount = options.MipCount, ArrayCount = options.ArrayCount, Format = options.Format, AllowUnorderedAccessViews = options.AllowUnorderedAccess, ShaderViewFormat = options.ViewFormat, Usage = options.Usage }; if ((options.ArrayCount * options.MipCount) > images.Count) { throw new GorgonException(GorgonResult.CannotCreate, Resources.GORGFX_IMAGE_MIPCOUNT_ARRAYCOUNT_TOO_LARGE); } // Create our image data. var data = new GorgonImageData(settings); for (int array = 0; array < data.Settings.ArrayCount; array++) { for (int mipLevel = 0; mipLevel < data.Settings.MipCount; mipLevel++) { var image = images[array * data.Settings.MipCount + mipLevel]; if (image == null) { continue; } // Using the image, convert to a WIC bitmap object. using (var bitmap = wic.CreateWICImageFromImage(image)) { var buffer = data.Buffers[mipLevel, array]; wic.AddWICBitmapToImageData(bitmap, options.Filter, options.Dither, buffer, options.UseClipping); } } } return(data); }
/// <summary> /// Raises the <see cref="E:System.Windows.Forms.Form.Load"></see> event. /// </summary> /// <param name="e">An <see cref="T:System.EventArgs"></see> that contains the event data.</param> protected override void OnLoad(EventArgs e) { base.OnLoad(e); try { // Load the plug-in assembly. Gorgon.PlugIns.LoadPlugInAssembly(Program.PlugInPath + "Gorgon.Input.Raw.DLL"); // Create the factory. _input = GorgonInputFactory.CreateInputFactory("GorgonLibrary.Input.GorgonRawPlugIn"); // Create mouse, keyboard and joystick interfaces. _keyboard = _input.CreateKeyboard(this); _mouse = _input.CreatePointingDevice(this); _joystickList = new GorgonJoystick[_input.JoystickDevices.Count]; // Create each joystick interface. for (int i = 0; i < _joystickList.Length; i++) { _joystickList[i] = _input.CreateJoystick(this, _input.JoystickDevices[i].Name); } // Create the graphics interface. _graphics = new GorgonGraphics(); _screen = _graphics.Output.CreateSwapChain("Screen", new GorgonSwapChainSettings { Size = Settings.Default.Resolution, Format = BufferFormat.R8G8B8A8_UIntNormal, IsWindowed = Settings.Default.IsWindowed }); // For the backup image. Used to make it as large as the monitor that we're on. Screen currentScreen = Screen.FromHandle(Handle); // Relocate the window to the center of the screen. Location = new Point(currentScreen.Bounds.Left + (currentScreen.WorkingArea.Width / 2) - ClientSize.Width / 2, currentScreen.Bounds.Top + (currentScreen.WorkingArea.Height / 2) - ClientSize.Height / 2); // Create the 2D renderer. _2D = _graphics.Output.Create2DRenderer(_screen); // Create the text font. _font = _graphics.Fonts.CreateFont("Arial_9pt", new GorgonFontSettings { FontFamilyName = "Arial", FontStyle = FontStyle.Bold, AntiAliasingMode = FontAntiAliasMode.AntiAlias, FontHeightMode = FontHeightMode.Points, Size = 9.0f }); // Enable the mouse. Cursor = Cursors.Cross; _mouse.Enabled = true; _mouse.Exclusive = false; _mouse.PointingDeviceDown += MouseInput; _mouse.PointingDeviceMove += MouseInput; _mouse.PointingDeviceWheelMove += _mouse_PointingDeviceWheelMove; // Enable the keyboard. _keyboard.Enabled = true; _keyboard.Exclusive = false; _keyboard.KeyDown += _keyboard_KeyDown; // Create text sprite. _messageSprite = _2D.Renderables.CreateText("Message", _font, "Using mouse and keyboard."); _messageSprite.Color = Color.Black; // Create a back buffer. _backBuffer = _graphics.Output.CreateRenderTarget("BackBuffer", new GorgonRenderTarget2DSettings { Width = _screen.Settings.Width, Height = _screen.Settings.Height, Format = BufferFormat.R8G8B8A8_UIntNormal }); _backBuffer.Clear(Color.White); var settings = new GorgonTexture2DSettings { Width = currentScreen.Bounds.Width, Height = currentScreen.Bounds.Height, Format = BufferFormat.R8G8B8A8_UIntNormal, Usage = BufferUsage.Staging }; // Clear our backup image to white to match our primary screen. _backupImage = _graphics.Textures.CreateTexture("Backup", settings); using (var textureData = _backupImage.Lock(BufferLockFlags.Write)) { textureData.Data.Fill(0xFF); } // Set the mouse range and position. Cursor.Position = PointToScreen(new Point(Settings.Default.Resolution.Width / 2, Settings.Default.Resolution.Height / 2)); _mouse.SetPosition(Settings.Default.Resolution.Width / 2, Settings.Default.Resolution.Height / 2); _mouse.SetPositionRange(0, 0, Settings.Default.Resolution.Width, Settings.Default.Resolution.Height); // Set gorgon events. _screen.AfterStateTransition += (sender, args) => { OnResizeEnd(EventArgs.Empty); // Reposition after a state change. if (!args.IsWindowed) { return; } Screen monitor = Screen.FromHandle(Handle); Location = new Point(monitor.Bounds.Left + (monitor.WorkingArea.Width / 2) - args.Width / 2, monitor.Bounds.Top + (monitor.WorkingArea.Height / 2) - args.Height / 2); Cursor.Position = PointToScreen(Point.Round(_mouse.Position)); }; Gorgon.ApplicationIdleLoopMethod = Gorgon_Idle; } catch (Exception ex) { GorgonException.Catch(ex, () => GorgonDialogs.ErrorBox(this, ex)); Gorgon.Quit(); } }