Sign in to follow this  
Armigus2

Texture Atlas User Control

Recommended Posts

My goal here is to display a Texture2d, in whole or in part, inside a custom user control on a form. The control code is
[source lang = "C#"]
using Microsoft.Xna.Framework.Graphics;
using System.IO;
using SysDraw = System.Drawing;

namespace TeraEditor
{
    public partial class AtlasView : UserControl
    {
        #region Members & Properties
        private Rectangle zone;
        public Rectangle Zone
        {
            get { return zone; }
            set { zone = value; }
        }

        private Point mapSize, pos;

        public Point MapSize
        {
            get { return mapSize; }
            set { mapSize = value; }
        }

        public Point Pos
        {
            get { return pos; }
            set { pos = value; }
        }

        private int index;
        public int Index
        {
            get { return index; }
            set { index = value; }
        }
        #endregion

        #region Code

        public AtlasView()
        {
            InitializeComponent();
        }

        public void SetTexture(Texture2D tex)
        {
            MemoryStream mem = new MemoryStream();
            Color[] imgData = new Color[zone.Height * zone.Width];
            tex.GetData<Color>(0, zone, imgData, 0, imgData.Length);
            
            // TODO: copy the data to the stream

            ImageBox.Image = SysDraw.Image.FromStream(mem);
        }
        #endregion
    }
}


1. MemoryStream reads a byte array and imgData is a Color array. Is a conversion or serialization feasible? 2. Am I really taking the right approach to this in the first place? My main screen is really a form contained within my Game object. Therefore I have access to such things as RenderTarget2D and SpriteBatch. Could I simply set a RenderTarget, draw the texture/subtexture on it via a SpriteBatch, then set up a panel in the form as the target to draw to via GraphicsDevice.Present(form.PanelHandle); 3. How about a StreamWriter?
public void SetTexture(Texture2D tex)
{
  MemoryStream mem = new MemoryStream();
  StreamWriter writer = new StreamWriter(mem);
  Color[] imgData = new Color[zone.Height * zone.Width];
  tex.GetData&lt;Color&gt;(0, zone, imgData, 0, imgData.Length);
  writer.Write(imgData.ToString());
            
  ImageBox.Image = SysDraw.Image.FromStream(mem);
}

I could just as easily make the stream and writer objects private members of the control and initialize them on creation. [Edited by - Armigus2 on September 13, 2009 12:04:44 PM]

Share this post


Link to post
Share on other sites
Well I definitely wouldn't save the Texture to a file....that's just a waste. Copying it to a MemoryStream works I guess...although you could just create a Bitmap and set the image data directly.

Another option is to call GraphicsDevice.Present and specify the Handle of your Control...this will cause the GraphicsDevice to copy the backbuffer to that Control.

Also just an FYI...if you're going to post code here you'll probably want to use the "code" or "source" tags. See the FAQ.

Share this post


Link to post
Share on other sites
I fixed the code segments in the post, but my StreamWriter has hit a wall.

Image.FromStream doesn't recognize the MemoryStream as set up. I am now going all out with option 2 (RenderTarget). The user control is superfluous at this point and has been discarded.

The form has two panels (main and texture), scroll bars on the texture panel, and a toggle button (CheckBox). The texture is rendered on a simple, small grid that I want to draw on a separate render target, then output to the texture panel.

Any ideas for a Draw game method that does both? Code so far:
[source lang = "C#"]
using SysForm = System.Windows.Forms;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

using TeraLibrary.Components;
using System;

namespace TeraEditor
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class TestEditor : Game
{
GraphicsDeviceManager graphics;
EditorForm form;
InputManager input;
GridMap map;
TextureMap legend;
CameraDolly mapCam, texCam;

public TestEditor()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
this.IsMouseVisible = true;
input = new InputManager(this);
mapCam = new CameraDolly(this);
map = new GridMap(this, 71, 51);
legend = new TextureMap(this, 5, 5);
}

/// <summary>
/// Allows the game to perform any initialization it needs to before starting to run.
/// This is where it can query for any required services and load any non-graphic
/// related content. Calling base.Initialize will enumerate through any components
/// and initialize them as well.
/// </summary>
protected override void Initialize()
{
map.FxFile = "TextureMap";
legend.FxFile = "TextureAtlas";
input.AssignControl("Exit", Keys.Escape);
input.AssignControl("Wire", Keys.Z);
//input.AssignControl("Select", "Keyboard.JustPressed.X");
input.AssignControl("Pitch", Keys.Up, Keys.Down);
input.AssignControl("Yaw", Keys.Right, Keys.Left);
input.AssignControl("Move", Keys.W, Keys.S);
input.AssignControl("Pan", Keys.A, Keys.D);
input.AssignControl("Zoom", Keys.Q, Keys.E);
base.Initialize();
SysForm.Form window = (SysForm.Form)SysForm.Form.FromHandle(this.Window.Handle);
window.Shown += new EventHandler(window_Shown);
form = new EditorForm();
PresentationParameters newParams = GraphicsDevice.PresentationParameters;
newParams.BackBufferWidth = form.GameWidth;
newParams.BackBufferHeight = form.GameHeight;
GraphicsDevice.Reset(newParams);
form.HandleDestroyed += new EventHandler(form_HandleDestroyed);
form.Show();
}

void form_HandleDestroyed(object sender, EventArgs e)
{
Exit();
}

void window_Shown(object sender, EventArgs e)
{
((SysForm.Form)sender).Hide();
}

/// <summary>
/// LoadContent will be called once per game and is the place to load
/// all of your content.
/// </summary>
protected override void LoadContent()
{
}

/// <summary>
/// UnloadContent will be called once per game and is the place to unload
/// all content.
/// </summary>
protected override void UnloadContent()
{
}

/// <summary>
/// Allows the game to run logic such as updating the world,
/// checking for collisions, gathering input, and playing audio.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (input.ControlState(PlayerIndex.One,"Exit") != 0)
this.Exit();
base.Update(gameTime);
}

/// <summary>
/// This is called when the game should draw itself.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CadetBlue);

base.Draw(gameTime);

GraphicsDevice.Present(form.EditHandle);
}
}
}


Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this