Finding the area of a texture after scaling

I would like to draw my scene at a fixed resolution, and then scale it whatever size the GraphicDevice.ViewPort is. I have resolved that by drawing to a RenderTarget2D first, and then drawing that render target to the backbuffer. The issue I have now is finding the scaled area of a texture to check whether or not the mouse is within it’s boundaries. Does anyone know how to do that, or am I going about this wrong? Thanks to anyone who replies.

Example:

GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
RenderTarget2D RenderTarget;
Texture2D Button;
Texture2D ImageNone;
Texture2D ImageHover;
Rectangle Source;
Rectangle Destination;
Rectangle Area;

public Game1()
{
    graphics = new GraphicsDeviceManager(this);
    Content.RootDirectory = "Content";
    graphics.IsFullScreen = true;
    this.IsMouseVisible = true;
}

protected override void LoadContent()
{
    spriteBatch = new SpriteBatch(GraphicsDevice);

    ImageNone = Content.Load<Texture2D>("buttonStock1");
    ImageHover = Content.Load<Texture2D>("buttonStock1h");
    Source = new Rectangle(0, 0, ImageNone.Width, ImageNone.Height);
    RenderTarget = new RenderTarget2D(GraphicsDevice, 1920, 1080);
}

protected override void Update(GameTime gameTime)
{
    if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || 
        Keyboard.GetState().IsKeyDown(Keys.Escape))
        Exit();

    // Destination will be set X, Y, Width and Height for the 1920x1080 resolution RenderTarget
    Destination = new Rectangle(400, 300, ImageNone.Width, ImageNone.Height);

    // Area = what would the new area of Destination/Button be when scaled to the GraphicsDevice.Viewport so we can check of the mouse is within it's boundaries?

    var mouseState = Mouse.GetState();
    if (Area.Contains(mouseState.X, mouseState.Y))
    {
        Button = ImageHover;
    }
    else
    {
        Button = ImageNone;
    }
    base.Update(gameTime);
}

protected override void Draw(GameTime gameTime)
{
    GraphicsDevice.SetRenderTarget(RenderTarget); // set render target to a fixed sized target
    GraphicsDevice.Clear(Color.CornflowerBlue);

    spriteBatch.Begin();
    spriteBatch.Draw(Button, Destination, Source, Color.White);
    spriteBatch.End();

    GraphicsDevice.SetRenderTarget(null); // set render target back to the backbuffer

    spriteBatch.Begin();
    spriteBatch.Draw(RenderTarget, new Rectangle(0, 0, GraphicsDevice.Viewport.Width, 
        GraphicsDevice.Viewport.Height), Color.White);
    spriteBatch.End();

    base.Draw(gameTime);
}

You need to know what the scale factor was and then convert the mouse coordinates.

So if your scene is say 400x300 and the screen resolution is 800x600, your scale factor is 2 (the image is rendered twice as high and twice as wide).

So if the user clicks on 100, 100 this is actually 50, 50 in your scene. So you need to divide the ‘real’ mouse coordinates by the scale factor in each direction.

virtualX = mouseX * (viewportWide / sceneWide);
virtualY = mouseY * (viewportHigh / sceneHigh);

You can then use these new coordinate to check button presses within your scene etc.

Hope this helps.

1 Like

@jonathanmcc, thank you!! That set me on the right path. This is what I used:

var mouseState = Mouse.GetState();
var virtualX = Convert.ToSingle(mouseState.X) * Convert.ToSingle(RenderTarget.Width) / Convert.ToSingle(GraphicsDevice.Viewport.Width);
var virtualY = Convert.ToSingle(mouseState.Y) * Convert.ToSingle(RenderTarget.Height) / Convert.ToSingle(GraphicsDevice.Viewport.Height); 

And it seems to working great.

1 Like