Make a struct with xywh values and a method that returns a Rectangle from it. or just returns the xy part in a new vector2 or point.
mystructvariable.ToRectangle();
mystructvariable.ToVector2();
draw(…, mystructvariable.ToRectangle() …, …);
If you want something more fancy i have a old class that does that as well its pretty big.
But it can do all that stuff and then some you can use it as is or cut out the extra junk…
public class VirtRect
{
#region variables fields
/// <summary>
/// only a couple methods use this were ...
/// its so easy to type a mistake and so hard to track down
/// they throw a exception if a typical mistake or typo is made
/// if this call is set to true that check will not be made but it
/// must be explicity set before each iffy method there is only a couple
/// and they are commented , basically you ignore this unless you want
/// a virtrect with a negative w h by corners
/// </summary>
public static bool allow_A_Unsafe_Operation = false;
private float left = 0.0f; // x
private float top = 0.0f; // y
private float right = 0.0f; // ex
private float bottom = 0.0f; // ey
private float width = 0.0f; // w
private float height = 0.0f; // h
private float center_x = 0.0f; // cx
private float center_y = 0.0f; // cy
#endregion
#region properties
//setters getters
/// <summary>
/// set or get the starting x postition
/// here width can be a negative number
/// moves the rectangle to x the width is preserved
/// right = left + width;
/// center is always left + .5f * width
/// </summary>
public float X
{
get
{
return left;
}
set
{
left = value;
right = left + width;
center_x = width * .5f + left;
}
}
/// <summary>
/// set or get the starting y postition
/// moves the rectangle height is preserved
/// bottom = top + height;
/// here height can be a negative number
/// center is always top + .5f * height
/// </summary>
public float Y
{
get
{
return top;
}
set
{
top = value;
bottom = top + height;
center_y = height * .5f + top;
}
}
/// <summary>
/// set or get the ending x postition
/// here width is preserved left = right - width
/// center x is always left + .5f * width
/// </summary>
public float EX
{
get
{
return right;
}
set
{
right = value;
left = right - width;
//width = right - left;
center_x = width * .5f + left;
}
}
/// <summary>
/// set or get the ending y postition
/// here height is preserved top = right - height
/// center is always top + .5f * height
/// </summary>
public float EY
{
get
{
return bottom;
}
set
{
bottom = value;
top = bottom - height;
//height = bottom - top;
center_y = height * .5f + top;
}
}
/// <summary>
/// set or get
/// a virt rect
/// width is set from right - left
/// center is always left + .5f * width or height respectively
/// </summary>
public float Left
{
get
{
return left;
}
set
{
left = value;
width = right - left;
center_x = width * .5f + left;
}
}
/// <summary>
/// set or get
/// center is always top + .5f * height
/// </summary>
public float Top
{
get
{
return top;
}
set
{
top = value;
height = bottom - top;
center_y = height * .5f + top;
}
}
/// <summary>
/// set or get
/// center x is always left + .5f * width
/// width = right - left;
/// </summary>
public float Right
{
get
{
return right;
}
set
{
right = value;
width = right - left;
center_x = width * .5f + left;
}
}
/// <summary>
/// set or get
/// center is always right + .5f * height respectively
/// height = bottom - top ;
/// </summary>
public float Bottom
{
get
{
return bottom;
}
set
{
bottom = value;
height = bottom - top;
center_y = height * .5f + top;
}
}
/// <summary>
/// set or get width
/// width is added to the left coordinate to find the right
/// the center x is then recalculated
/// </summary>
public float Width
{
get
{
return width;
}
set
{
width = value;
right = left + width;
center_x = width * .5f + left;
}
}
/// <summary>
/// set or get height
/// height is added to the top coordinate to find the bottom
/// the center y is then recalculated
/// </summary>
public float Height
{
get
{
return height;
}
set
{
height = value;
bottom = top + height;
center_y = height * .5f + top;
}
}
/// <summary>
/// normally you dont set the center
/// however if you do in this case
/// the width and height remain unchanged
/// the left right and top bottom coordinates will
/// move with the center though
/// </summary>
public float CenterX
{
get
{
return center_x;
}
set
{
float r = (right - left) * .5f;
left = value - r;
right = value + r;
center_x = value;
}
}
/// <summary>
/// normally you dont set the center
/// however if you do in this case
/// the width and height remain unchanged
/// the left right and top bottom coordinates will
/// move with the center though
/// </summary>
public float CenterY
{
get
{
return center_y;
}
set
{
float r = (bottom - top) * .5f;
top = value - r; // y
bottom = value + r; // ey
center_y = value;
//float d = value - center_y;
//center_y = value;
//top = top + d;
//bottom = bottom + d;
}
}
/// <summary>
/// get set center as a vector 2
/// </summary>
public Vector2 Center
{
get{return new Vector2(center_x,center_y);}
set { CenterX = value.X; CenterY = value.Y; }
}
/// <summary>
/// gets the virtual location as a vector2
/// </summary>
public Vector2 LocationVirt
{
get { return new Vector2(top, left); }
}
/// <summary>
/// gets the screen location as a vector2
/// </summary>
//public Vector2 LocationScreen
//{
// get{return new Vector2((int)(X * (float)(BxEngine.client_screen_width)), (int)(Y * (float)(BxEngine.client_screen_height)));}
//}
// static properties
/// <summary>
/// gets a virtual rectangle zero
/// </summary>
public static VirtRect Zero
{
get
{
return default(VirtRect);
}
}
public static VirtRect Whole
{
get
{
return new VirtRect(0f, 0f, 1f, 1f);
}
}
#endregion
#region constructors and polymorphic constructs methods
/// <summary>
/// Primary constructor
/// creates a new virtrect with zero parameters
/// AS of now this constructor shouldn't be used in favor of VirtRect.Zero
/// so that this can be depreciated however untill i do a bit more test ill leave this in
/// to boot this is a old class allot of my apps use this so it will be a real bitch to do that
/// the reason for this to be depreciated is i need to do so in order to turn this class into a struct
/// which should give me a bit of a boost
/// </summary>
public VirtRect()
{
Left = 0.0f;
Top = 0.0f;
Width = 0.0f;
Height = 0.0f;
}
/// <summary>
/// primary constructor
/// </summary>
/// <param name="x">x left position of rect</param>
/// <param name="y">y right position of rect</param>
/// <param name="w">Width of rect</param>
/// <param name="h">Height of rect</param>
public VirtRect(float x, float y, float w, float h)
{
Left = x;
Top = y;
Width = w;
Height = h;
}
/// <summary>
/// Construct a VirtRect from a normal rectangle
/// </summary>
/// <param name="r">Takes a Rectangle Object</param>
public VirtRect(Rectangle r)
{
Left = r.X;
Top = r.Y;
Width = r.Width;
Height = r.Height;
}
/// <summary>
/// Construct a VirtRect from a normal rectangle and a screen W H to place it as a screen percentage
/// </summary>
/// <param name="r">Takes a Rectangle Object</param>
public VirtRect(Rectangle r, int ofWidth, int ofHeight)
{
Left = (float)(r.X) / (float)(ofWidth);
Top = (float)(r.Y) / (float)(ofHeight);
Width = (float)(r.Width) / (float)(ofWidth);
Height = (float)(r.Height) / (float)(ofHeight);
}
/// <summary>
/// nearly the same as ofwidth height
/// </summary>
/// <param name="_inner_rect"></param>
/// <param name="_of_outer_rectangle"></param>
public VirtRect(Rectangle _inner_rect, Rectangle _of_outer_rectangle)
{
Left = (float)(_inner_rect.X - _of_outer_rectangle.X) / (float)(_of_outer_rectangle.Width);
Top = (float)(_inner_rect.Y - _of_outer_rectangle.Y) / (float)(_of_outer_rectangle.Height);
Width = (float)(_inner_rect.Width) / (float)(_of_outer_rectangle.Width);
Height = (float)(_inner_rect.Height) / (float)(_of_outer_rectangle.Height);
}
// polymorphic constructor methods
/// <summary>
/// Creates a Virtual rectangle Object
/// <para>this allows you to set the virtrect by its corner positions</para>
/// <para>Throws a exception and logs if width or height is negative</para>
/// </summary>
/// <param name="Start_X">Left</param>
/// <param name="Start_Y">Top</param>
/// <param name="End_X">Right</param>
/// <param name="End_Y">Bottom</param>
/// <returns>a new VirtRect object</returns>
public static VirtRect NewVirtRectByCorners(float Start_X, float Start_Y, float End_X, float End_Y)
{
VirtRect n = new VirtRect(Start_X, Start_Y, End_X - Start_X, End_Y - Start_Y);
if (allow_A_Unsafe_Operation == false && (n.width < 0 || n.height < 0)) { BxLog.writeThrownExceptionStackMsg("Error Loged new Virt Rectangle By corners is improperly set"); }
else { allow_A_Unsafe_Operation = false; }
return n;
}
/// <summary>
/// Creates a Virtual rectangle Object
/// using the center as the position from which to create it
/// and useing the Width Height to find the sides of the rectangle
/// </summary>
/// <param name="_centerx">x position to base the rectangle on</param>
/// <param name="_centery">y position to base the rectangle on</param>
/// <param name="_w">half the width +- x = left and right</param>
/// <param name="_h">half the height +- y = top and bottom</param>
/// <returns>a new VirtRect object</returns>
public static VirtRect NewVirtRectByCenterAndWH(float _center_x, float _center_y, float _w, float _h)
{
return new VirtRect(_center_x - (_w * .5f), _center_y - (_h * .5f), _w, _h);
}
// static method
/// <summary>
/// <para>given an outer virt rectangle (b)</para>
/// <para>and a portion of it (vr_in_b) (i)</para>
/// the value returned will be the relation to the virtual screen w,h (1.0,1.0) as
/// <para>vrX = ix * bw + bx ,</para>
/// <para>vrW = iw * bw </para>
/// </summary>
/// <param name="vr_in_b">this vr will be a percentage within b</param>
/// <param name="b">this is a vr in relation to a whole for example e.g. a screen</param>
/// <returns>a new virtual screen rectangle</returns>
public static VirtRect GetVrOfVr(VirtRect vr_in_b, VirtRect b)
{
return new VirtRect
(
vr_in_b.X * b.Width + b.X,
vr_in_b.Y * b.Height + b.Y,
vr_in_b.Width * b.Width,//+ b.X,
vr_in_b.Height * b.Height);//+ b.Y);
}
#endregion
// Class Object Methods
/// <summary>
/// returns a new instance of this virtual rectangle
/// </summary>
/// <returns></returns>
public VirtRect Copy
{
get { return new VirtRect(this.X, this.Y, this.Width, this.Height); }
set { this.X = value.X; this.Y = value.Y; this.Width = value.Width; this.Height = value.Height; }
}
/// <summary>
/// Returns a Rectangle from this Virtual Rectangle
/// note this method rounds down the decimal point
/// </summary>
/// <returns>a Rectangle Class Object</returns>
public Rectangle GetRectangle()
{
return new Rectangle((int)X, (int)Y, (int)Width, (int)Height);
}
/// <summary>
/// <para>this version returns a rectangle based on a width and height value and this virtual rectangle</para>
/// <para>example vr.X = .5 ofwidth = 800 then .5 * 800 = 400 </para>
/// note this method rounds down the decimal point
/// </summary>
/// <param name="ofWidth"></param>
/// <param name="ofHeight"></param>
/// <returns>returns a rectangle</returns>
public Rectangle GetRectangle(int ofWidth, int ofHeight)
{
return new Rectangle((int)(X * ofWidth), (int)(Y * ofHeight), (int)(Width * ofWidth), (int)(Height * ofHeight));
}
/// <summary>
/// <para>Example...use this were...</para>
/// <para> this virtual rectangle represents a portion of another rectangle that you pass to this method</para>
/// <para> this method rounds down the decimal point</para>
/// </summary>
/// <param name="ofRectangle">a rectangle that will be used</param>
/// <returns>a new Rectangle</returns>
public Rectangle GetRectangle(Rectangle ofRectangle)
{
return new Rectangle(
(int)(X * ofRectangle.Width + ofRectangle.X),
(int)(Y * ofRectangle.Height + ofRectangle.Y),
(int)(Width * ofRectangle.Width),
(int)(Height * ofRectangle.Height)
);
}
/// <summary>
/// call to the engien to get a screen rectangle
/// used when the virt rectangle represents a uv portion of the screen itself
/// </summary>
/// <returns></returns>
//public Rectangle GetScreenRectangle()
//{
// return new Rectangle(
// (int)(X * (float)(BxEngine.client_screen_width)),
// (int)(Y * (float)(BxEngine.client_screen_height)),
// (int)(Width * (float)(BxEngine.client_screen_width)),
// (int)(Height* (float)(BxEngine.client_screen_height))
// );
//}
/// <summary>
/// same as getRectangle
/// <para>static general use method</para>
/// <para> allows you to find a new rectangle using the given percentages within the given rectangle</para>
/// </summary>
/// <param name="x">0 to 1</param>
/// <param name="y">0 to 1</param>
/// <param name="ex">0 to 1 typically</param>
/// <param name="ey">0 to 1 typically</param>
/// <param name="rect">the rectangle to base the new rectangle from</param>
/// <returns>a new rectangle based on the floats given for the corners within the inputed rectangle</returns>
public static Rectangle GetRectanglePortionOfRectangle(float x,float y,float ex,float ey,Rectangle rect)
{
return new Rectangle(
(int)(x * rect.Width) + rect.X,
(int)(y * rect.Height) + rect.Y,
(int)((ex - x) * rect.Width),
(int)((ey - y) * rect.Height));
}
/// <summary>
/// inner is a rectangle in a whole texture(0,0,W,H) the rectangle you get back fits on the screen
/// in the same proportion to the rectangle to the texture , that said the rule of thumb is inner rect
/// right bottom should be lower then outer rectangles wh
/// if the _screen_window_rect is just a portion of the screen
/// we get a rectangle that fits in it as though it were a window to the texture itself
///
/// note this method does not ensure the rectangle is in bounds of the texture_pixelsize_rectangle
///
/// EXAMPLE)
/// large rectangle is (0,0,4000,4000) inner is (0,0,4000,4000) the screen is (0,0,800,600)
/// the result returned will be a rectangle the size of the screen
/// (the returned rectangle / divided by the screen rectangle) will give a virtual rectangle of (0,0,1f,1f)
/// </summary>
/// <param name="_inner_texture_rect"></param>
/// <param name="_larger_texture_pixsize_rect"></param>
/// <param name="ScreenRect"></param>
/// <returns></returns>
public static Rectangle GetRectOfTextureRectToScrWindowRectangle(Rectangle _inner_texture_rect, Rectangle _larger_texture_pixsize_rect,Rectangle _screen_window_rect)
{
Rectangle r = new Rectangle
(
(int)(((float)_inner_texture_rect.X / (float)_larger_texture_pixsize_rect.Width) * (float)_screen_window_rect.Width + _screen_window_rect.X),
(int)(((float)_inner_texture_rect.Y / (float)_larger_texture_pixsize_rect.Height) * (float)_screen_window_rect.Height + _screen_window_rect.Y),
(int)(((float)_inner_texture_rect.Width / (float)_larger_texture_pixsize_rect.Width) * (float)_screen_window_rect.Width),
(int)(((float)_inner_texture_rect.Height / (float)_larger_texture_pixsize_rect.Height) * (float)_screen_window_rect.Height)
);
int rx = r.X; int ry = r.Y; int rex = r.Right; int rey = r.Bottom;
if (rx < _screen_window_rect.X) { rx = _screen_window_rect.X; }
if (ry < _screen_window_rect.Y) { ry = _screen_window_rect.Y; }
if (rex < _screen_window_rect.Right) { rex = _screen_window_rect.Right; }
if (rey < _screen_window_rect.Bottom) { rey = _screen_window_rect.Bottom; }
if (rx >= _screen_window_rect.Right) { rx = -1; ry = -1; rex = -1; rey = -1; }
if (ry >= _screen_window_rect.Bottom) { rx = -1; ry = -1; rex = -1; rey = -1; }
if (rex <= _screen_window_rect.X) { rx = -1; ry = -1; rex = -1; rey = -1; }
if (rey <= _screen_window_rect.Y) { rx = -1; ry = -1; rex = -1; rey = -1; }
return new Rectangle(rx, ry, rex, rey);
}
/// <summary>
/// the reverse of getRectOfTextureRectToScrWindowRectangle
/// turns a inner selection rectangle ussualy a mouse drag rectanlge in comparision to a window on screen and turns that into coordinates
/// </summary>
/// <param name="mouse_drag_rect"></param>
/// <param name="screen_window_rect"></param>
/// <param name="texture_rect"></param>
/// <returns></returns>
public static Rectangle GetRectInScrWindowRectToTextureRect(Rectangle mouse_drag_rect,Rectangle screen_window_rect,Rectangle texture_rect)
{
Rectangle r = new Rectangle
(
(int)(Math.Round((float)(texture_rect.Width) * (float)((float)(mouse_drag_rect.X - screen_window_rect.X) / (float)(screen_window_rect.Width)),MidpointRounding.ToEven)),
(int)(Math.Round((float)(texture_rect.Height) * (float)((float)(mouse_drag_rect.Y - screen_window_rect.Y) / (float)(screen_window_rect.Height)),MidpointRounding.ToEven)),
(int)(Math.Round((float)(texture_rect.Width) * (float)((float)(mouse_drag_rect.Width) / (float)(screen_window_rect.Width)),MidpointRounding.ToEven)),
(int)(Math.Round((float)(texture_rect.Height) * (float)((float)(mouse_drag_rect.Height) / (float)(screen_window_rect.Height)), MidpointRounding.ToEven))
);
// if r.width is within 1 of texture_rect width we might want to just set it to the width because floating point rounding errors can
// actually throw off this calculation or maybe there is a math.rounding or something
int rx = r.X; int ry = r.Y; int rex = r.Right; int rey = r.Bottom;
if (rx < texture_rect.X) { rx = texture_rect.X; }
if (ry < texture_rect.Y) { ry = texture_rect.Y; }
if (rex < texture_rect.Right) { rex = texture_rect.Right; }
if (rey < texture_rect.Bottom) { rey = texture_rect.Bottom; }
if (rx >= texture_rect.Right) { rx = -1; ry = -1; rex = -1; rey = -1; }
if (ry >= texture_rect.Bottom) { rx = -1; ry = -1; rex = -1; rey = -1; }
if (rex <= texture_rect.X) { rx = -1; ry = -1; rex = -1; rey = -1; }
if (rey <= texture_rect.Y) { rx = -1; ry = -1; rex = -1; rey = -1; }
return new Rectangle(rx, ry, rex, rey);
}
/// <summary>
/// this is used to check button positions for clicks on them
/// in addition if the click occurs then we set a small pause duration
/// ... this takes a virtual position in relation to a virtrectangle
/// </summary>
/// <param name="p"></param>
/// <returns></returns>
public bool HasWithin(Vector2 vp)
{
if (vp.X > left && vp.X < right && vp.Y > top && vp.Y < bottom)
return true;
else
return false;
}
/// <summary>
/// An overloaded ToString method
/// </summary>
/// <returns></returns>
public override string ToString()
{
return
" [ X=" + X.ToString()+", Y=" + Y.ToString() +" ]" +
"[ CenterX=" + center_x.ToString() + ", CenterY=" + center_y.ToString() + " ]" +
"[ Right=" + Right.ToString() + ", Bottom=" + Bottom.ToString() +" ]" +
"[ Width=" + width.ToString() +", Height=" + height.ToString() + " ]"
;
}
}