@@ -999,7 +999,7 @@ namespace FarseerPhysics.Dynamics
|
|||||||
if (body == null)
|
if (body == null)
|
||||||
throw new ArgumentNullException("body");
|
throw new ArgumentNullException("body");
|
||||||
if (body.World != this)
|
if (body.World != this)
|
||||||
throw new ArgumentException("You are removing a body that is not in the simulation.", "body");
|
throw new ArgumentException($"You are removing a body that is not in the simulation (userdata: {body.UserData?.ToString() ?? "null"}).", "body");
|
||||||
|
|
||||||
#if USE_AWAKE_BODY_SET
|
#if USE_AWAKE_BODY_SET
|
||||||
Debug.Assert(!AwakeBodySet.Contains(body));
|
Debug.Assert(!AwakeBodySet.Contains(body));
|
||||||
@@ -1034,6 +1034,7 @@ namespace FarseerPhysics.Dynamics
|
|||||||
body.DestroyProxies();
|
body.DestroyProxies();
|
||||||
for (int i = 0; i < body.FixtureList.Count; i++)
|
for (int i = 0; i < body.FixtureList.Count; i++)
|
||||||
{
|
{
|
||||||
|
body.FixtureList[i].UserData = null;
|
||||||
if (FixtureRemoved != null)
|
if (FixtureRemoved != null)
|
||||||
FixtureRemoved(this, body, body.FixtureList[i]);
|
FixtureRemoved(this, body, body.FixtureList[i]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,9 @@
|
|||||||
// file 'LICENSE.txt', which is part of this source code package.
|
// file 'LICENSE.txt', which is part of this source code package.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace Microsoft.Xna.Framework.Graphics
|
namespace Microsoft.Xna.Framework.Graphics
|
||||||
@@ -25,15 +28,58 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class SpriteBatch : GraphicsResource, ISpriteBatch
|
public class SpriteBatch : GraphicsResource, ISpriteBatch
|
||||||
{
|
{
|
||||||
|
public struct EffectWithParams
|
||||||
|
{
|
||||||
|
private static readonly Dictionary<Type, MethodInfo> parameterSetters;
|
||||||
|
private static readonly object[] setterParams = new object[1];
|
||||||
|
|
||||||
|
static EffectWithParams()
|
||||||
|
{
|
||||||
|
parameterSetters = new Dictionary<Type, MethodInfo>();
|
||||||
|
foreach (var method in typeof(EffectParameter).GetMethods())
|
||||||
|
{
|
||||||
|
if (method.Name.Equals("SetValue", StringComparison.InvariantCulture)
|
||||||
|
&& method.GetParameters() is { Length: 1 } parameters)
|
||||||
|
{
|
||||||
|
var type = parameters[0].ParameterType;
|
||||||
|
parameterSetters[type] = method;
|
||||||
|
foreach (var derived in Assembly.GetAssembly(type).GetTypes().Where(t => t.IsSubclassOf(type)))
|
||||||
|
{
|
||||||
|
parameterSetters[derived] = method;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Effect Effect;
|
||||||
|
public Dictionary<string, object> Params;
|
||||||
|
|
||||||
|
public EffectWithParams(Effect effect, Dictionary<string, object> parameters = null)
|
||||||
|
{
|
||||||
|
Effect = effect;
|
||||||
|
Params = parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Apply()
|
||||||
|
{
|
||||||
|
foreach (var (paramName, paramValue) in Params)
|
||||||
|
{
|
||||||
|
setterParams[0] = paramValue;
|
||||||
|
parameterSetters[paramValue.GetType()].Invoke(Effect.Parameters[paramName], setterParams);
|
||||||
|
}
|
||||||
|
Effect.CurrentTechnique.Passes[0].Apply();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#region Private Fields
|
#region Private Fields
|
||||||
readonly SpriteBatcher _batcher;
|
readonly SpriteBatcher _batcher;
|
||||||
|
|
||||||
SpriteSortMode _sortMode;
|
SpriteSortMode _sortMode;
|
||||||
BlendState _blendState;
|
BlendState _blendState;
|
||||||
SamplerState _samplerState;
|
SamplerState _samplerState;
|
||||||
DepthStencilState _depthStencilState;
|
DepthStencilState _depthStencilState;
|
||||||
RasterizerState _rasterizerState;
|
RasterizerState _rasterizerState;
|
||||||
Effect _effect;
|
EffectWithParams _effect;
|
||||||
bool _beginCalled;
|
bool _beginCalled;
|
||||||
|
|
||||||
Effect _spriteEffect;
|
Effect _spriteEffect;
|
||||||
@@ -60,7 +106,7 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
if (graphicsDevice == null)
|
if (graphicsDevice == null)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException ("graphicsDevice", FrameworkResources.ResourceCreationWhenDeviceIsNull);
|
throw new ArgumentNullException ("graphicsDevice", FrameworkResources.ResourceCreationWhenDeviceIsNull);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.GraphicsDevice = graphicsDevice;
|
this.GraphicsDevice = graphicsDevice;
|
||||||
|
|
||||||
@@ -107,7 +153,7 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
_samplerState = samplerState ?? SamplerState.LinearClamp;
|
_samplerState = samplerState ?? SamplerState.LinearClamp;
|
||||||
_depthStencilState = depthStencilState ?? DepthStencilState.None;
|
_depthStencilState = depthStencilState ?? DepthStencilState.None;
|
||||||
_rasterizerState = rasterizerState ?? RasterizerState.CullCounterClockwise;
|
_rasterizerState = rasterizerState ?? RasterizerState.CullCounterClockwise;
|
||||||
_effect = effect;
|
_effect = new EffectWithParams(effect);
|
||||||
_matrix = transformMatrix;
|
_matrix = transformMatrix;
|
||||||
|
|
||||||
// Setup things now so a user can change them.
|
// Setup things now so a user can change them.
|
||||||
@@ -119,6 +165,11 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
_beginCalled = true;
|
_beginCalled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the current effect.
|
||||||
|
/// </summary>
|
||||||
|
public Effect GetCurrentEffect() => _effect.Effect;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Flushes all batched text and sprites to the screen.
|
/// Flushes all batched text and sprites to the screen.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -132,18 +183,31 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
|
|
||||||
if (_sortMode != SpriteSortMode.Immediate)
|
if (_sortMode != SpriteSortMode.Immediate)
|
||||||
Setup();
|
Setup();
|
||||||
|
|
||||||
_batcher.DrawBatch(_sortMode, _effect);
|
_batcher.DrawBatch(_sortMode, _spritePass);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Setup()
|
/// <summary>
|
||||||
|
/// Swaps the current effect.
|
||||||
|
/// </summary>
|
||||||
|
public void SwapEffect(Effect effect = null, Dictionary<string, object> parameters = null)
|
||||||
|
{
|
||||||
|
_effect = new EffectWithParams(effect, parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SwapEffect(EffectWithParams effectWithParams)
|
||||||
|
{
|
||||||
|
_effect = effectWithParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Setup()
|
||||||
{
|
{
|
||||||
var gd = GraphicsDevice;
|
var gd = GraphicsDevice;
|
||||||
gd.BlendState = _blendState;
|
gd.BlendState = _blendState;
|
||||||
gd.DepthStencilState = _depthStencilState;
|
gd.DepthStencilState = _depthStencilState;
|
||||||
gd.RasterizerState = _rasterizerState;
|
gd.RasterizerState = _rasterizerState;
|
||||||
gd.SamplerStates[0] = _samplerState;
|
gd.SamplerStates[0] = _samplerState;
|
||||||
|
|
||||||
var vp = gd.Viewport;
|
var vp = gd.Viewport;
|
||||||
if ((vp.Width != _lastViewport.Width) || (vp.Height != _lastViewport.Height))
|
if ((vp.Width != _lastViewport.Width) || (vp.Height != _lastViewport.Height))
|
||||||
{
|
{
|
||||||
@@ -169,7 +233,7 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
|
|
||||||
_spritePass.Apply();
|
_spritePass.Apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckValid(Texture2D texture)
|
void CheckValid(Texture2D texture)
|
||||||
{
|
{
|
||||||
if (texture == null)
|
if (texture == null)
|
||||||
@@ -279,6 +343,7 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
{
|
{
|
||||||
var item = _batcher.CreateBatchItem();
|
var item = _batcher.CreateBatchItem();
|
||||||
item.Texture = texture;
|
item.Texture = texture;
|
||||||
|
item.Effect = _effect;
|
||||||
|
|
||||||
item.SortKey = sortKey;
|
item.SortKey = sortKey;
|
||||||
|
|
||||||
@@ -315,6 +380,7 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
|
|
||||||
var item = _batcher.CreateBatchItem();
|
var item = _batcher.CreateBatchItem();
|
||||||
item.Texture = texture;
|
item.Texture = texture;
|
||||||
|
item.Effect = _effect;
|
||||||
|
|
||||||
// set SortKey based on SpriteSortMode.
|
// set SortKey based on SpriteSortMode.
|
||||||
switch ( _sortMode )
|
switch ( _sortMode )
|
||||||
@@ -332,9 +398,9 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
item.SortKey = -layerDepth;
|
item.SortKey = -layerDepth;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
origin = origin * scale;
|
origin = origin * scale;
|
||||||
|
|
||||||
float w, h;
|
float w, h;
|
||||||
if (sourceRectangle.HasValue)
|
if (sourceRectangle.HasValue)
|
||||||
{
|
{
|
||||||
@@ -353,7 +419,7 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
_texCoordTL = Vector2.Zero;
|
_texCoordTL = Vector2.Zero;
|
||||||
_texCoordBR = Vector2.One;
|
_texCoordBR = Vector2.One;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((effects & SpriteEffects.FlipVertically) != 0)
|
if ((effects & SpriteEffects.FlipVertically) != 0)
|
||||||
{
|
{
|
||||||
var temp = _texCoordBR.Y;
|
var temp = _texCoordBR.Y;
|
||||||
@@ -366,7 +432,7 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
_texCoordBR.X = _texCoordTL.X;
|
_texCoordBR.X = _texCoordTL.X;
|
||||||
_texCoordTL.X = temp;
|
_texCoordTL.X = temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rotation == 0f)
|
if (rotation == 0f)
|
||||||
{
|
{
|
||||||
item.Set(position.X - origin.X,
|
item.Set(position.X - origin.X,
|
||||||
@@ -393,7 +459,7 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
_texCoordBR,
|
_texCoordBR,
|
||||||
layerDepth);
|
layerDepth);
|
||||||
}
|
}
|
||||||
|
|
||||||
FlushIfNeeded();
|
FlushIfNeeded();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -444,9 +510,10 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
float layerDepth)
|
float layerDepth)
|
||||||
{
|
{
|
||||||
CheckValid(texture);
|
CheckValid(texture);
|
||||||
|
|
||||||
var item = _batcher.CreateBatchItem();
|
var item = _batcher.CreateBatchItem();
|
||||||
item.Texture = texture;
|
item.Texture = texture;
|
||||||
|
item.Effect = _effect;
|
||||||
|
|
||||||
// set SortKey based on SpriteSortMode.
|
// set SortKey based on SpriteSortMode.
|
||||||
switch ( _sortMode )
|
switch ( _sortMode )
|
||||||
@@ -478,7 +545,7 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
else
|
else
|
||||||
origin.X = origin.X * (float)destinationRectangle.Width * texture.TexelWidth;
|
origin.X = origin.X * (float)destinationRectangle.Width * texture.TexelWidth;
|
||||||
if(srcRect.Height != 0)
|
if(srcRect.Height != 0)
|
||||||
origin.Y = origin.Y * (float)destinationRectangle.Height / (float)srcRect.Height;
|
origin.Y = origin.Y * (float)destinationRectangle.Height / (float)srcRect.Height;
|
||||||
else
|
else
|
||||||
origin.Y = origin.Y * (float)destinationRectangle.Height * texture.TexelHeight;
|
origin.Y = origin.Y * (float)destinationRectangle.Height * texture.TexelHeight;
|
||||||
}
|
}
|
||||||
@@ -486,11 +553,11 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
{
|
{
|
||||||
_texCoordTL = Vector2.Zero;
|
_texCoordTL = Vector2.Zero;
|
||||||
_texCoordBR = Vector2.One;
|
_texCoordBR = Vector2.One;
|
||||||
|
|
||||||
origin.X = origin.X * (float)destinationRectangle.Width * texture.TexelWidth;
|
origin.X = origin.X * (float)destinationRectangle.Width * texture.TexelWidth;
|
||||||
origin.Y = origin.Y * (float)destinationRectangle.Height * texture.TexelHeight;
|
origin.Y = origin.Y * (float)destinationRectangle.Height * texture.TexelHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((effects & SpriteEffects.FlipVertically) != 0)
|
if ((effects & SpriteEffects.FlipVertically) != 0)
|
||||||
{
|
{
|
||||||
var temp = _texCoordBR.Y;
|
var temp = _texCoordBR.Y;
|
||||||
@@ -539,7 +606,7 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
{
|
{
|
||||||
if (_sortMode == SpriteSortMode.Immediate)
|
if (_sortMode == SpriteSortMode.Immediate)
|
||||||
{
|
{
|
||||||
_batcher.DrawBatch(_sortMode, _effect);
|
_batcher.DrawBatch(_sortMode, _spritePass);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -553,10 +620,11 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
public void Draw (Texture2D texture, Vector2 position, Rectangle? sourceRectangle, Color color)
|
public void Draw (Texture2D texture, Vector2 position, Rectangle? sourceRectangle, Color color)
|
||||||
{
|
{
|
||||||
CheckValid(texture);
|
CheckValid(texture);
|
||||||
|
|
||||||
var item = _batcher.CreateBatchItem();
|
var item = _batcher.CreateBatchItem();
|
||||||
item.Texture = texture;
|
item.Texture = texture;
|
||||||
|
item.Effect = _effect;
|
||||||
|
|
||||||
// set SortKey based on SpriteSortMode.
|
// set SortKey based on SpriteSortMode.
|
||||||
item.SortKey = _sortMode == SpriteSortMode.Texture ? texture.SortingKey : 0;
|
item.SortKey = _sortMode == SpriteSortMode.Texture ? texture.SortingKey : 0;
|
||||||
|
|
||||||
@@ -600,13 +668,14 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
public void Draw (Texture2D texture, Rectangle destinationRectangle, Rectangle? sourceRectangle, Color color)
|
public void Draw (Texture2D texture, Rectangle destinationRectangle, Rectangle? sourceRectangle, Color color)
|
||||||
{
|
{
|
||||||
CheckValid(texture);
|
CheckValid(texture);
|
||||||
|
|
||||||
var item = _batcher.CreateBatchItem();
|
var item = _batcher.CreateBatchItem();
|
||||||
item.Texture = texture;
|
item.Texture = texture;
|
||||||
|
item.Effect = _effect;
|
||||||
|
|
||||||
// set SortKey based on SpriteSortMode.
|
// set SortKey based on SpriteSortMode.
|
||||||
item.SortKey = _sortMode == SpriteSortMode.Texture ? texture.SortingKey : 0;
|
item.SortKey = _sortMode == SpriteSortMode.Texture ? texture.SortingKey : 0;
|
||||||
|
|
||||||
if (sourceRectangle.HasValue)
|
if (sourceRectangle.HasValue)
|
||||||
{
|
{
|
||||||
var srcRect = sourceRectangle.GetValueOrDefault();
|
var srcRect = sourceRectangle.GetValueOrDefault();
|
||||||
@@ -629,7 +698,7 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
_texCoordTL,
|
_texCoordTL,
|
||||||
_texCoordBR,
|
_texCoordBR,
|
||||||
0);
|
0);
|
||||||
|
|
||||||
FlushIfNeeded();
|
FlushIfNeeded();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -642,13 +711,14 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
public void Draw (Texture2D texture, Vector2 position, Color color)
|
public void Draw (Texture2D texture, Vector2 position, Color color)
|
||||||
{
|
{
|
||||||
CheckValid(texture);
|
CheckValid(texture);
|
||||||
|
|
||||||
var item = _batcher.CreateBatchItem();
|
var item = _batcher.CreateBatchItem();
|
||||||
item.Texture = texture;
|
item.Texture = texture;
|
||||||
|
item.Effect = _effect;
|
||||||
|
|
||||||
// set SortKey based on SpriteSortMode.
|
// set SortKey based on SpriteSortMode.
|
||||||
item.SortKey = _sortMode == SpriteSortMode.Texture ? texture.SortingKey : 0;
|
item.SortKey = _sortMode == SpriteSortMode.Texture ? texture.SortingKey : 0;
|
||||||
|
|
||||||
item.Set(position.X,
|
item.Set(position.X,
|
||||||
position.Y,
|
position.Y,
|
||||||
texture.Width,
|
texture.Width,
|
||||||
@@ -670,13 +740,14 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
public void Draw(Texture2D texture, Rectangle destinationRectangle, Color color)
|
public void Draw(Texture2D texture, Rectangle destinationRectangle, Color color)
|
||||||
{
|
{
|
||||||
CheckValid(texture);
|
CheckValid(texture);
|
||||||
|
|
||||||
var item = _batcher.CreateBatchItem();
|
var item = _batcher.CreateBatchItem();
|
||||||
item.Texture = texture;
|
item.Texture = texture;
|
||||||
|
item.Effect = _effect;
|
||||||
|
|
||||||
// set SortKey based on SpriteSortMode.
|
// set SortKey based on SpriteSortMode.
|
||||||
item.SortKey = _sortMode == SpriteSortMode.Texture ? texture.SortingKey : 0;
|
item.SortKey = _sortMode == SpriteSortMode.Texture ? texture.SortingKey : 0;
|
||||||
|
|
||||||
item.Set(destinationRectangle.X,
|
item.Set(destinationRectangle.X,
|
||||||
destinationRectangle.Y,
|
destinationRectangle.Y,
|
||||||
destinationRectangle.Width,
|
destinationRectangle.Width,
|
||||||
@@ -685,7 +756,7 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
Vector2.Zero,
|
Vector2.Zero,
|
||||||
Vector2.One,
|
Vector2.One,
|
||||||
0);
|
0);
|
||||||
|
|
||||||
FlushIfNeeded();
|
FlushIfNeeded();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -699,7 +770,7 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
public unsafe void DrawString (SpriteFont spriteFont, string text, Vector2 position, Color color)
|
public unsafe void DrawString (SpriteFont spriteFont, string text, Vector2 position, Color color)
|
||||||
{
|
{
|
||||||
CheckValid(spriteFont, text);
|
CheckValid(spriteFont, text);
|
||||||
|
|
||||||
float sortKey = (_sortMode == SpriteSortMode.Texture) ? spriteFont.Texture.SortingKey : 0;
|
float sortKey = (_sortMode == SpriteSortMode.Texture) ? spriteFont.Texture.SortingKey : 0;
|
||||||
|
|
||||||
var offset = Vector2.Zero;
|
var offset = Vector2.Zero;
|
||||||
@@ -720,7 +791,7 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
firstGlyphOfLine = true;
|
firstGlyphOfLine = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var currentGlyphIndex = spriteFont.GetGlyphIndexOrDefault(c);
|
var currentGlyphIndex = spriteFont.GetGlyphIndexOrDefault(c);
|
||||||
var pCurrentGlyph = pGlyphs + currentGlyphIndex;
|
var pCurrentGlyph = pGlyphs + currentGlyphIndex;
|
||||||
|
|
||||||
@@ -737,15 +808,16 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
offset.X += spriteFont.Spacing + pCurrentGlyph->LeftSideBearing;
|
offset.X += spriteFont.Spacing + pCurrentGlyph->LeftSideBearing;
|
||||||
}
|
}
|
||||||
|
|
||||||
var p = offset;
|
var p = offset;
|
||||||
p.X += pCurrentGlyph->Cropping.X;
|
p.X += pCurrentGlyph->Cropping.X;
|
||||||
p.Y += pCurrentGlyph->Cropping.Y;
|
p.Y += pCurrentGlyph->Cropping.Y;
|
||||||
p += position;
|
p += position;
|
||||||
|
|
||||||
var item = _batcher.CreateBatchItem();
|
var item = _batcher.CreateBatchItem();
|
||||||
item.Texture = spriteFont.Texture;
|
item.Texture = spriteFont.Texture;
|
||||||
|
item.Effect = _effect;
|
||||||
item.SortKey = sortKey;
|
item.SortKey = sortKey;
|
||||||
|
|
||||||
_texCoordTL.X = pCurrentGlyph->BoundsInTexture.X * spriteFont.Texture.TexelWidth;
|
_texCoordTL.X = pCurrentGlyph->BoundsInTexture.X * spriteFont.Texture.TexelWidth;
|
||||||
_texCoordTL.Y = pCurrentGlyph->BoundsInTexture.Y * spriteFont.Texture.TexelHeight;
|
_texCoordTL.Y = pCurrentGlyph->BoundsInTexture.Y * spriteFont.Texture.TexelHeight;
|
||||||
_texCoordBR.X = (pCurrentGlyph->BoundsInTexture.X + pCurrentGlyph->BoundsInTexture.Width) * spriteFont.Texture.TexelWidth;
|
_texCoordBR.X = (pCurrentGlyph->BoundsInTexture.X + pCurrentGlyph->BoundsInTexture.Width) * spriteFont.Texture.TexelWidth;
|
||||||
@@ -759,7 +831,7 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
_texCoordTL,
|
_texCoordTL,
|
||||||
_texCoordBR,
|
_texCoordBR,
|
||||||
0);
|
0);
|
||||||
|
|
||||||
offset.X += pCurrentGlyph->Width + pCurrentGlyph->RightSideBearing;
|
offset.X += pCurrentGlyph->Width + pCurrentGlyph->RightSideBearing;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -804,7 +876,7 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float layerDepth)
|
float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float layerDepth)
|
||||||
{
|
{
|
||||||
CheckValid(spriteFont, text);
|
CheckValid(spriteFont, text);
|
||||||
|
|
||||||
float sortKey = 0;
|
float sortKey = 0;
|
||||||
// set SortKey based on SpriteSortMode.
|
// set SortKey based on SpriteSortMode.
|
||||||
switch (_sortMode)
|
switch (_sortMode)
|
||||||
@@ -831,7 +903,7 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
if (flippedVert || flippedHorz)
|
if (flippedVert || flippedHorz)
|
||||||
{
|
{
|
||||||
Vector2 size;
|
Vector2 size;
|
||||||
|
|
||||||
var source = new SpriteFont.CharacterSource(text);
|
var source = new SpriteFont.CharacterSource(text);
|
||||||
spriteFont.MeasureString(ref source, out size);
|
spriteFont.MeasureString(ref source, out size);
|
||||||
|
|
||||||
@@ -847,7 +919,7 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
flipAdjustment.Y = spriteFont.LineSpacing - size.Y;
|
flipAdjustment.Y = spriteFont.LineSpacing - size.Y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Matrix transformation = Matrix.Identity;
|
Matrix transformation = Matrix.Identity;
|
||||||
float cos = 0, sin = 0;
|
float cos = 0, sin = 0;
|
||||||
if (rotation == 0)
|
if (rotation == 0)
|
||||||
@@ -866,7 +938,7 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
transformation.M21 = (flippedVert ? -scale.Y : scale.Y) * (-sin);
|
transformation.M21 = (flippedVert ? -scale.Y : scale.Y) * (-sin);
|
||||||
transformation.M22 = (flippedVert ? -scale.Y : scale.Y) * cos;
|
transformation.M22 = (flippedVert ? -scale.Y : scale.Y) * cos;
|
||||||
transformation.M41 = (((flipAdjustment.X - origin.X) * transformation.M11) + (flipAdjustment.Y - origin.Y) * transformation.M21) + position.X;
|
transformation.M41 = (((flipAdjustment.X - origin.X) * transformation.M11) + (flipAdjustment.Y - origin.Y) * transformation.M21) + position.X;
|
||||||
transformation.M42 = (((flipAdjustment.X - origin.X) * transformation.M12) + (flipAdjustment.Y - origin.Y) * transformation.M22) + position.Y;
|
transformation.M42 = (((flipAdjustment.X - origin.X) * transformation.M12) + (flipAdjustment.Y - origin.Y) * transformation.M22) + position.Y;
|
||||||
}
|
}
|
||||||
|
|
||||||
var offset = Vector2.Zero;
|
var offset = Vector2.Zero;
|
||||||
@@ -916,15 +988,16 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
|
|
||||||
Vector2.Transform(ref p, ref transformation, out p);
|
Vector2.Transform(ref p, ref transformation, out p);
|
||||||
|
|
||||||
var item = _batcher.CreateBatchItem();
|
var item = _batcher.CreateBatchItem();
|
||||||
item.Texture = spriteFont.Texture;
|
item.Texture = spriteFont.Texture;
|
||||||
|
item.Effect = _effect;
|
||||||
item.SortKey = sortKey;
|
item.SortKey = sortKey;
|
||||||
|
|
||||||
_texCoordTL.X = pCurrentGlyph->BoundsInTexture.X * spriteFont.Texture.TexelWidth;
|
_texCoordTL.X = pCurrentGlyph->BoundsInTexture.X * spriteFont.Texture.TexelWidth;
|
||||||
_texCoordTL.Y = pCurrentGlyph->BoundsInTexture.Y * spriteFont.Texture.TexelHeight;
|
_texCoordTL.Y = pCurrentGlyph->BoundsInTexture.Y * spriteFont.Texture.TexelHeight;
|
||||||
_texCoordBR.X = (pCurrentGlyph->BoundsInTexture.X + pCurrentGlyph->BoundsInTexture.Width) * spriteFont.Texture.TexelWidth;
|
_texCoordBR.X = (pCurrentGlyph->BoundsInTexture.X + pCurrentGlyph->BoundsInTexture.Width) * spriteFont.Texture.TexelWidth;
|
||||||
_texCoordBR.Y = (pCurrentGlyph->BoundsInTexture.Y + pCurrentGlyph->BoundsInTexture.Height) * spriteFont.Texture.TexelHeight;
|
_texCoordBR.Y = (pCurrentGlyph->BoundsInTexture.Y + pCurrentGlyph->BoundsInTexture.Height) * spriteFont.Texture.TexelHeight;
|
||||||
|
|
||||||
if ((effects & SpriteEffects.FlipVertically) != 0)
|
if ((effects & SpriteEffects.FlipVertically) != 0)
|
||||||
{
|
{
|
||||||
var temp = _texCoordBR.Y;
|
var temp = _texCoordBR.Y;
|
||||||
@@ -964,7 +1037,7 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
_texCoordBR,
|
_texCoordBR,
|
||||||
layerDepth);
|
layerDepth);
|
||||||
}
|
}
|
||||||
|
|
||||||
offset.X += pCurrentGlyph->Width + pCurrentGlyph->RightSideBearing;
|
offset.X += pCurrentGlyph->Width + pCurrentGlyph->RightSideBearing;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -982,7 +1055,7 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
public unsafe void DrawString (SpriteFont spriteFont, StringBuilder text, Vector2 position, Color color)
|
public unsafe void DrawString (SpriteFont spriteFont, StringBuilder text, Vector2 position, Color color)
|
||||||
{
|
{
|
||||||
CheckValid(spriteFont, text);
|
CheckValid(spriteFont, text);
|
||||||
|
|
||||||
float sortKey = (_sortMode == SpriteSortMode.Texture) ? spriteFont.Texture.SortingKey : 0;
|
float sortKey = (_sortMode == SpriteSortMode.Texture) ? spriteFont.Texture.SortingKey : 0;
|
||||||
|
|
||||||
var offset = Vector2.Zero;
|
var offset = Vector2.Zero;
|
||||||
@@ -1020,15 +1093,16 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
offset.X += spriteFont.Spacing + pCurrentGlyph->LeftSideBearing;
|
offset.X += spriteFont.Spacing + pCurrentGlyph->LeftSideBearing;
|
||||||
}
|
}
|
||||||
|
|
||||||
var p = offset;
|
var p = offset;
|
||||||
p.X += pCurrentGlyph->Cropping.X;
|
p.X += pCurrentGlyph->Cropping.X;
|
||||||
p.Y += pCurrentGlyph->Cropping.Y;
|
p.Y += pCurrentGlyph->Cropping.Y;
|
||||||
p += position;
|
p += position;
|
||||||
|
|
||||||
var item = _batcher.CreateBatchItem();
|
var item = _batcher.CreateBatchItem();
|
||||||
item.Texture = spriteFont.Texture;
|
item.Texture = spriteFont.Texture;
|
||||||
|
item.Effect = _effect;
|
||||||
item.SortKey = sortKey;
|
item.SortKey = sortKey;
|
||||||
|
|
||||||
_texCoordTL.X = pCurrentGlyph->BoundsInTexture.X * spriteFont.Texture.TexelWidth;
|
_texCoordTL.X = pCurrentGlyph->BoundsInTexture.X * spriteFont.Texture.TexelWidth;
|
||||||
_texCoordTL.Y = pCurrentGlyph->BoundsInTexture.Y * spriteFont.Texture.TexelHeight;
|
_texCoordTL.Y = pCurrentGlyph->BoundsInTexture.Y * spriteFont.Texture.TexelHeight;
|
||||||
_texCoordBR.X = (pCurrentGlyph->BoundsInTexture.X + pCurrentGlyph->BoundsInTexture.Width) * spriteFont.Texture.TexelWidth;
|
_texCoordBR.X = (pCurrentGlyph->BoundsInTexture.X + pCurrentGlyph->BoundsInTexture.Width) * spriteFont.Texture.TexelWidth;
|
||||||
@@ -1087,7 +1161,7 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float layerDepth)
|
float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float layerDepth)
|
||||||
{
|
{
|
||||||
CheckValid(spriteFont, text);
|
CheckValid(spriteFont, text);
|
||||||
|
|
||||||
float sortKey = 0;
|
float sortKey = 0;
|
||||||
// set SortKey based on SpriteSortMode.
|
// set SortKey based on SpriteSortMode.
|
||||||
switch (_sortMode)
|
switch (_sortMode)
|
||||||
@@ -1129,7 +1203,7 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
flipAdjustment.Y = spriteFont.LineSpacing - size.Y;
|
flipAdjustment.Y = spriteFont.LineSpacing - size.Y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Matrix transformation = Matrix.Identity;
|
Matrix transformation = Matrix.Identity;
|
||||||
float cos = 0, sin = 0;
|
float cos = 0, sin = 0;
|
||||||
if (rotation == 0)
|
if (rotation == 0)
|
||||||
@@ -1148,7 +1222,7 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
transformation.M21 = (flippedVert ? -scale.Y : scale.Y) * (-sin);
|
transformation.M21 = (flippedVert ? -scale.Y : scale.Y) * (-sin);
|
||||||
transformation.M22 = (flippedVert ? -scale.Y : scale.Y) * cos;
|
transformation.M22 = (flippedVert ? -scale.Y : scale.Y) * cos;
|
||||||
transformation.M41 = (((flipAdjustment.X - origin.X) * transformation.M11) + (flipAdjustment.Y - origin.Y) * transformation.M21) + position.X;
|
transformation.M41 = (((flipAdjustment.X - origin.X) * transformation.M11) + (flipAdjustment.Y - origin.Y) * transformation.M21) + position.X;
|
||||||
transformation.M42 = (((flipAdjustment.X - origin.X) * transformation.M12) + (flipAdjustment.Y - origin.Y) * transformation.M22) + position.Y;
|
transformation.M42 = (((flipAdjustment.X - origin.X) * transformation.M12) + (flipAdjustment.Y - origin.Y) * transformation.M22) + position.Y;
|
||||||
}
|
}
|
||||||
|
|
||||||
var offset = Vector2.Zero;
|
var offset = Vector2.Zero;
|
||||||
@@ -1197,16 +1271,17 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
p.Y += pCurrentGlyph->Cropping.Y;
|
p.Y += pCurrentGlyph->Cropping.Y;
|
||||||
|
|
||||||
Vector2.Transform(ref p, ref transformation, out p);
|
Vector2.Transform(ref p, ref transformation, out p);
|
||||||
|
|
||||||
var item = _batcher.CreateBatchItem();
|
var item = _batcher.CreateBatchItem();
|
||||||
item.Texture = spriteFont.Texture;
|
item.Texture = spriteFont.Texture;
|
||||||
|
item.Effect = _effect;
|
||||||
item.SortKey = sortKey;
|
item.SortKey = sortKey;
|
||||||
|
|
||||||
_texCoordTL.X = pCurrentGlyph->BoundsInTexture.X * (float)spriteFont.Texture.TexelWidth;
|
_texCoordTL.X = pCurrentGlyph->BoundsInTexture.X * (float)spriteFont.Texture.TexelWidth;
|
||||||
_texCoordTL.Y = pCurrentGlyph->BoundsInTexture.Y * (float)spriteFont.Texture.TexelHeight;
|
_texCoordTL.Y = pCurrentGlyph->BoundsInTexture.Y * (float)spriteFont.Texture.TexelHeight;
|
||||||
_texCoordBR.X = (pCurrentGlyph->BoundsInTexture.X + pCurrentGlyph->BoundsInTexture.Width) * (float)spriteFont.Texture.TexelWidth;
|
_texCoordBR.X = (pCurrentGlyph->BoundsInTexture.X + pCurrentGlyph->BoundsInTexture.Width) * (float)spriteFont.Texture.TexelWidth;
|
||||||
_texCoordBR.Y = (pCurrentGlyph->BoundsInTexture.Y + pCurrentGlyph->BoundsInTexture.Height) * (float)spriteFont.Texture.TexelHeight;
|
_texCoordBR.Y = (pCurrentGlyph->BoundsInTexture.Y + pCurrentGlyph->BoundsInTexture.Height) * (float)spriteFont.Texture.TexelHeight;
|
||||||
|
|
||||||
if ((effects & SpriteEffects.FlipVertically) != 0)
|
if ((effects & SpriteEffects.FlipVertically) != 0)
|
||||||
{
|
{
|
||||||
var temp = _texCoordBR.Y;
|
var temp = _texCoordBR.Y;
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
internal class SpriteBatchItem : IComparable<SpriteBatchItem>
|
internal class SpriteBatchItem : IComparable<SpriteBatchItem>
|
||||||
{
|
{
|
||||||
public Texture2D Texture;
|
public Texture2D Texture;
|
||||||
|
public SpriteBatch.EffectWithParams Effect;
|
||||||
public float SortKey;
|
public float SortKey;
|
||||||
|
|
||||||
public VertexPositionColorTexture vertexTL;
|
public VertexPositionColorTexture vertexTL;
|
||||||
@@ -20,7 +21,7 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
vertexTL = new VertexPositionColorTexture();
|
vertexTL = new VertexPositionColorTexture();
|
||||||
vertexTR = new VertexPositionColorTexture();
|
vertexTR = new VertexPositionColorTexture();
|
||||||
vertexBL = new VertexPositionColorTexture();
|
vertexBL = new VertexPositionColorTexture();
|
||||||
vertexBR = new VertexPositionColorTexture();
|
vertexBR = new VertexPositionColorTexture();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Set ( float x, float y, float dx, float dy, float w, float h, float sin, float cos, Color color, Vector2 texCoordTL, Vector2 texCoordBR, float depth )
|
public void Set ( float x, float y, float dx, float dy, float w, float h, float sin, float cos, Color color, Vector2 texCoordTL, Vector2 texCoordBR, float depth )
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
/// This class handles the queueing of batch items into the GPU by creating the triangle tesselations
|
/// This class handles the queueing of batch items into the GPU by creating the triangle tesselations
|
||||||
/// that are used to draw the sprite textures. This class supports int.MaxValue number of sprites to be
|
/// that are used to draw the sprite textures. This class supports int.MaxValue number of sprites to be
|
||||||
/// batched and will process them into short.MaxValue groups (strided by 6 for the number of vertices
|
/// batched and will process them into short.MaxValue groups (strided by 6 for the number of vertices
|
||||||
/// sent to the GPU).
|
/// sent to the GPU).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal class SpriteBatcher
|
internal class SpriteBatcher
|
||||||
{
|
{
|
||||||
@@ -68,7 +68,7 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reuse a previously allocated SpriteBatchItem from the item pool.
|
/// Reuse a previously allocated SpriteBatchItem from the item pool.
|
||||||
/// if there is none available grow the pool and initialize new items.
|
/// if there is none available grow the pool and initialize new items.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
@@ -143,12 +143,8 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
/// overflow the 16 bit array indices for vertices.
|
/// overflow the 16 bit array indices for vertices.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="sortMode">The type of depth sorting desired for the rendering.</param>
|
/// <param name="sortMode">The type of depth sorting desired for the rendering.</param>
|
||||||
/// <param name="effect">The custom effect to apply to the drawn geometry</param>
|
public unsafe void DrawBatch(SpriteSortMode sortMode, EffectPass defaultSpritePass)
|
||||||
public unsafe void DrawBatch(SpriteSortMode sortMode, Effect effect)
|
|
||||||
{
|
{
|
||||||
if (effect != null && effect.IsDisposed)
|
|
||||||
throw new ObjectDisposedException("effect");
|
|
||||||
|
|
||||||
// nothing to do
|
// nothing to do
|
||||||
if (_batchItemCount == 0)
|
if (_batchItemCount == 0)
|
||||||
return;
|
return;
|
||||||
@@ -180,6 +176,7 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
var startIndex = 0;
|
var startIndex = 0;
|
||||||
var index = 0;
|
var index = 0;
|
||||||
Texture2D tex = null;
|
Texture2D tex = null;
|
||||||
|
SpriteBatch.EffectWithParams effect = default;
|
||||||
|
|
||||||
int numBatchesToProcess = batchCount;
|
int numBatchesToProcess = batchCount;
|
||||||
if (numBatchesToProcess > MaxBatchSize)
|
if (numBatchesToProcess > MaxBatchSize)
|
||||||
@@ -196,12 +193,24 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
{
|
{
|
||||||
SpriteBatchItem item = _batchItemList[batchIndex];
|
SpriteBatchItem item = _batchItemList[batchIndex];
|
||||||
// if the texture changed, we need to flush and bind the new texture
|
// if the texture changed, we need to flush and bind the new texture
|
||||||
var shouldFlush = !ReferenceEquals(item.Texture, tex);
|
var shouldFlush =
|
||||||
|
!ReferenceEquals(item.Texture, tex)
|
||||||
|
|| !ReferenceEquals(item.Effect.Effect, effect.Effect)
|
||||||
|
|| !ReferenceEquals(item.Effect.Params, effect.Params);
|
||||||
if (shouldFlush)
|
if (shouldFlush)
|
||||||
{
|
{
|
||||||
FlushVertexArray(startIndex, index, effect, tex);
|
FlushVertexArray(startIndex, index, effect.Effect, tex);
|
||||||
|
|
||||||
tex = item.Texture;
|
tex = item.Texture;
|
||||||
|
effect = item.Effect;
|
||||||
|
if (effect.Effect is null || effect.Params is null)
|
||||||
|
{
|
||||||
|
defaultSpritePass.Apply();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
effect.Apply();
|
||||||
|
}
|
||||||
startIndex = index = 0;
|
startIndex = index = 0;
|
||||||
vertexArrayPtr = vertexArrayFixedPtr;
|
vertexArrayPtr = vertexArrayFixedPtr;
|
||||||
_device.Textures[0] = tex;
|
_device.Textures[0] = tex;
|
||||||
@@ -215,15 +224,16 @@ namespace Microsoft.Xna.Framework.Graphics
|
|||||||
|
|
||||||
// Release the texture.
|
// Release the texture.
|
||||||
item.Texture = null;
|
item.Texture = null;
|
||||||
|
item.Effect = default;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// flush the remaining vertexArray data
|
// flush the remaining vertexArray data
|
||||||
FlushVertexArray(startIndex, index, effect, tex);
|
FlushVertexArray(startIndex, index, effect.Effect, tex);
|
||||||
// Update our batch count to continue the process of culling down
|
// Update our batch count to continue the process of culling down
|
||||||
// large batches
|
// large batches
|
||||||
batchCount -= numBatchesToProcess;
|
batchCount -= numBatchesToProcess;
|
||||||
}
|
}
|
||||||
// return items to the pool.
|
// return items to the pool.
|
||||||
_batchItemCount = 0;
|
_batchItemCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,551 @@
|
|||||||
|
// MIT License - Copyright (C) The Mono.Xna Team
|
||||||
|
// This file is subject to the terms and conditions defined in
|
||||||
|
// file 'LICENSE.txt', which is part of this source code package.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Microsoft.Xna.Framework
|
||||||
|
{
|
||||||
|
public struct RectangleF : IEquatable<RectangleF>
|
||||||
|
{
|
||||||
|
#region Private Fields
|
||||||
|
|
||||||
|
private static RectangleF emptyRectangle = new RectangleF();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Public Fields
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The x coordinate of the top-left corner of this <see cref="RectangleF"/>.
|
||||||
|
/// </summary>
|
||||||
|
|
||||||
|
public float X;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The y coordinate of the top-left corner of this <see cref="RectangleF"/>.
|
||||||
|
/// </summary>
|
||||||
|
|
||||||
|
public float Y;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The width of this <see cref="RectangleF"/>.
|
||||||
|
/// </summary>
|
||||||
|
|
||||||
|
public float Width;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The height of this <see cref="RectangleF"/>.
|
||||||
|
/// </summary>
|
||||||
|
|
||||||
|
public float Height;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Public Properties
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a <see cref="RectangleF"/> with X=0, Y=0, Width=0, Height=0.
|
||||||
|
/// </summary>
|
||||||
|
public static RectangleF Empty
|
||||||
|
{
|
||||||
|
get { return emptyRectangle; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the x coordinate of the left edge of this <see cref="RectangleF"/>.
|
||||||
|
/// </summary>
|
||||||
|
public float Left
|
||||||
|
{
|
||||||
|
get { return this.X; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the x coordinate of the right edge of this <see cref="RectangleF"/>.
|
||||||
|
/// </summary>
|
||||||
|
public float Right
|
||||||
|
{
|
||||||
|
get { return (this.X + this.Width); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the y coordinate of the top edge of this <see cref="RectangleF"/>.
|
||||||
|
/// </summary>
|
||||||
|
public float Top
|
||||||
|
{
|
||||||
|
get { return this.Y; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the y coordinate of the bottom edge of this <see cref="RectangleF"/>.
|
||||||
|
/// </summary>
|
||||||
|
public float Bottom
|
||||||
|
{
|
||||||
|
get { return (this.Y + this.Height); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether or not this <see cref="RectangleF"/> has a <see cref="Width"/> and
|
||||||
|
/// <see cref="Height"/> of 0, and a <see cref="Location"/> of (0, 0).
|
||||||
|
/// </summary>
|
||||||
|
public bool IsEmpty
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return ((((this.Width == 0) && (this.Height == 0)) && (this.X == 0)) && (this.Y == 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The top-left coordinates of this <see cref="RectangleF"/>.
|
||||||
|
/// </summary>
|
||||||
|
public Vector2 Location
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return new Vector2(this.X, this.Y);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
X = value.X;
|
||||||
|
Y = value.Y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The width-height coordinates of this <see cref="RectangleF"/>.
|
||||||
|
/// </summary>
|
||||||
|
public Vector2 Size
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return new Vector2(this.Width, this.Height);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
Width = value.X;
|
||||||
|
Height = value.Y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A <see cref="Point"/> located in the center of this <see cref="RectangleF"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// If <see cref="Width"/> or <see cref="Height"/> is an odd number,
|
||||||
|
/// the center point will be rounded down.
|
||||||
|
/// </remarks>
|
||||||
|
public Vector2 Center
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return new Vector2(this.X + (this.Width / 2f), this.Y + (this.Height / 2f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Internal Properties
|
||||||
|
|
||||||
|
internal string DebugDisplayString
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return string.Concat(
|
||||||
|
this.X, " ",
|
||||||
|
this.Y, " ",
|
||||||
|
this.Width, " ",
|
||||||
|
this.Height
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new instance of <see cref="RectangleF"/> struct, with the specified
|
||||||
|
/// position, width, and height.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x">The x coordinate of the top-left corner of the created <see cref="RectangleF"/>.</param>
|
||||||
|
/// <param name="y">The y coordinate of the top-left corner of the created <see cref="RectangleF"/>.</param>
|
||||||
|
/// <param name="width">The width of the created <see cref="RectangleF"/>.</param>
|
||||||
|
/// <param name="height">The height of the created <see cref="RectangleF"/>.</param>
|
||||||
|
public RectangleF(float x, float y, float width, float height)
|
||||||
|
{
|
||||||
|
this.X = x;
|
||||||
|
this.Y = y;
|
||||||
|
this.Width = width;
|
||||||
|
this.Height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new instance of <see cref="RectangleF"/> struct, with the specified
|
||||||
|
/// location and size.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="location">The x and y coordinates of the top-left corner of the created <see cref="RectangleF"/>.</param>
|
||||||
|
/// <param name="size">The width and height of the created <see cref="RectangleF"/>.</param>
|
||||||
|
public RectangleF(Vector2 location, Vector2 size)
|
||||||
|
{
|
||||||
|
this.X = location.X;
|
||||||
|
this.Y = location.Y;
|
||||||
|
this.Width = size.X;
|
||||||
|
this.Height = size.Y;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Operators
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Compares whether two <see cref="RectangleF"/> instances are equal.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"><see cref="RectangleF"/> instance on the left of the equal sign.</param>
|
||||||
|
/// <param name="b"><see cref="RectangleF"/> instance on the right of the equal sign.</param>
|
||||||
|
/// <returns><c>true</c> if the instances are equal; <c>false</c> otherwise.</returns>
|
||||||
|
public static bool operator ==(RectangleF a, RectangleF b)
|
||||||
|
{
|
||||||
|
return ((a.X == b.X) && (a.Y == b.Y) && (a.Width == b.Width) && (a.Height == b.Height));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Compares whether two <see cref="RectangleF"/> instances are not equal.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"><see cref="RectangleF"/> instance on the left of the not equal sign.</param>
|
||||||
|
/// <param name="b"><see cref="RectangleF"/> instance on the right of the not equal sign.</param>
|
||||||
|
/// <returns><c>true</c> if the instances are not equal; <c>false</c> otherwise.</returns>
|
||||||
|
public static bool operator !=(RectangleF a, RectangleF b)
|
||||||
|
{
|
||||||
|
return !(a == b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator RectangleF(Rectangle r) => new RectangleF(r.X, r.Y, r.Width, r.Height);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Public Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets whether or not the provided coordinates lie within the bounds of this <see cref="RectangleF"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x">The x coordinate of the point to check for containment.</param>
|
||||||
|
/// <param name="y">The y coordinate of the point to check for containment.</param>
|
||||||
|
/// <returns><c>true</c> if the provided coordinates lie inside this <see cref="RectangleF"/>; <c>false</c> otherwise.</returns>
|
||||||
|
public bool Contains(int x, int y)
|
||||||
|
{
|
||||||
|
return ((((this.X <= x) && (x < (this.X + this.Width))) && (this.Y <= y)) && (y < (this.Y + this.Height)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets whether or not the provided coordinates lie within the bounds of this <see cref="RectangleF"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x">The x coordinate of the point to check for containment.</param>
|
||||||
|
/// <param name="y">The y coordinate of the point to check for containment.</param>
|
||||||
|
/// <returns><c>true</c> if the provided coordinates lie inside this <see cref="RectangleF"/>; <c>false</c> otherwise.</returns>
|
||||||
|
public bool Contains(float x, float y)
|
||||||
|
{
|
||||||
|
return ((((this.X <= x) && (x < (this.X + this.Width))) && (this.Y <= y)) && (y < (this.Y + this.Height)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets whether or not the provided <see cref="Point"/> lies within the bounds of this <see cref="RectangleF"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The coordinates to check for inclusion in this <see cref="RectangleF"/>.</param>
|
||||||
|
/// <returns><c>true</c> if the provided <see cref="Point"/> lies inside this <see cref="RectangleF"/>; <c>false</c> otherwise.</returns>
|
||||||
|
public bool Contains(Point value)
|
||||||
|
{
|
||||||
|
return ((((this.X <= value.X) && (value.X < (this.X + this.Width))) && (this.Y <= value.Y)) && (value.Y < (this.Y + this.Height)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets whether or not the provided <see cref="Point"/> lies within the bounds of this <see cref="RectangleF"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The coordinates to check for inclusion in this <see cref="RectangleF"/>.</param>
|
||||||
|
/// <param name="result"><c>true</c> if the provided <see cref="Point"/> lies inside this <see cref="RectangleF"/>; <c>false</c> otherwise. As an output parameter.</param>
|
||||||
|
public void Contains(ref Point value, out bool result)
|
||||||
|
{
|
||||||
|
result = ((((this.X <= value.X) && (value.X < (this.X + this.Width))) && (this.Y <= value.Y)) && (value.Y < (this.Y + this.Height)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets whether or not the provided <see cref="Vector2"/> lies within the bounds of this <see cref="RectangleF"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The coordinates to check for inclusion in this <see cref="RectangleF"/>.</param>
|
||||||
|
/// <returns><c>true</c> if the provided <see cref="Vector2"/> lies inside this <see cref="RectangleF"/>; <c>false</c> otherwise.</returns>
|
||||||
|
public bool Contains(Vector2 value)
|
||||||
|
{
|
||||||
|
return ((((this.X <= value.X) && (value.X < (this.X + this.Width))) && (this.Y <= value.Y)) && (value.Y < (this.Y + this.Height)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets whether or not the provided <see cref="Vector2"/> lies within the bounds of this <see cref="RectangleF"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The coordinates to check for inclusion in this <see cref="RectangleF"/>.</param>
|
||||||
|
/// <param name="result"><c>true</c> if the provided <see cref="Vector2"/> lies inside this <see cref="RectangleF"/>; <c>false</c> otherwise. As an output parameter.</param>
|
||||||
|
public void Contains(ref Vector2 value, out bool result)
|
||||||
|
{
|
||||||
|
result = ((((this.X <= value.X) && (value.X < (this.X + this.Width))) && (this.Y <= value.Y)) && (value.Y < (this.Y + this.Height)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets whether or not the provided <see cref="RectangleF"/> lies within the bounds of this <see cref="RectangleF"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The <see cref="RectangleF"/> to check for inclusion in this <see cref="RectangleF"/>.</param>
|
||||||
|
/// <returns><c>true</c> if the provided <see cref="RectangleF"/>'s bounds lie entirely inside this <see cref="RectangleF"/>; <c>false</c> otherwise.</returns>
|
||||||
|
public bool Contains(RectangleF value)
|
||||||
|
{
|
||||||
|
return ((((this.X <= value.X) && ((value.X + value.Width) <= (this.X + this.Width))) && (this.Y <= value.Y)) && ((value.Y + value.Height) <= (this.Y + this.Height)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets whether or not the provided <see cref="RectangleF"/> lies within the bounds of this <see cref="RectangleF"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The <see cref="RectangleF"/> to check for inclusion in this <see cref="RectangleF"/>.</param>
|
||||||
|
/// <param name="result"><c>true</c> if the provided <see cref="RectangleF"/>'s bounds lie entirely inside this <see cref="RectangleF"/>; <c>false</c> otherwise. As an output parameter.</param>
|
||||||
|
public void Contains(ref RectangleF value, out bool result)
|
||||||
|
{
|
||||||
|
result = ((((this.X <= value.X) && ((value.X + value.Width) <= (this.X + this.Width))) && (this.Y <= value.Y)) && ((value.Y + value.Height) <= (this.Y + this.Height)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Compares whether current instance is equal to specified <see cref="Object"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="obj">The <see cref="Object"/> to compare.</param>
|
||||||
|
/// <returns><c>true</c> if the instances are equal; <c>false</c> otherwise.</returns>
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
return (obj is RectangleF) && this == ((RectangleF)obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Compares whether current instance is equal to specified <see cref="RectangleF"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="other">The <see cref="RectangleF"/> to compare.</param>
|
||||||
|
/// <returns><c>true</c> if the instances are equal; <c>false</c> otherwise.</returns>
|
||||||
|
public bool Equals(RectangleF other)
|
||||||
|
{
|
||||||
|
return this == other;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the hash code of this <see cref="RectangleF"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Hash code of this <see cref="RectangleF"/>.</returns>
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
unchecked
|
||||||
|
{
|
||||||
|
var hash = 17;
|
||||||
|
hash = hash * 23 + X.GetHashCode();
|
||||||
|
hash = hash * 23 + Y.GetHashCode();
|
||||||
|
hash = hash * 23 + Width.GetHashCode();
|
||||||
|
hash = hash * 23 + Height.GetHashCode();
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adjusts the edges of this <see cref="RectangleF"/> by specified horizontal and vertical amounts.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="horizontalAmount">Value to adjust the left and right edges.</param>
|
||||||
|
/// <param name="verticalAmount">Value to adjust the top and bottom edges.</param>
|
||||||
|
public void Inflate(int horizontalAmount, int verticalAmount)
|
||||||
|
{
|
||||||
|
X -= horizontalAmount;
|
||||||
|
Y -= verticalAmount;
|
||||||
|
Width += horizontalAmount * 2;
|
||||||
|
Height += verticalAmount * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adjusts the edges of this <see cref="RectangleF"/> by specified horizontal and vertical amounts.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="horizontalAmount">Value to adjust the left and right edges.</param>
|
||||||
|
/// <param name="verticalAmount">Value to adjust the top and bottom edges.</param>
|
||||||
|
public void Inflate(float horizontalAmount, float verticalAmount)
|
||||||
|
{
|
||||||
|
X -= (float)horizontalAmount;
|
||||||
|
Y -= (float)verticalAmount;
|
||||||
|
Width += (float)horizontalAmount * 2;
|
||||||
|
Height += (float)verticalAmount * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adjusts the edges of this <see cref="RectangleF"/> by specified horizontal and vertical amounts.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="amount">Value to adjust the edges.</param>
|
||||||
|
public void Inflate(Vector2 amount)
|
||||||
|
{
|
||||||
|
Inflate(amount.X, amount.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets whether or not the other <see cref="RectangleF"/> intersects with this rectangle.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The other rectangle for testing.</param>
|
||||||
|
/// <returns><c>true</c> if other <see cref="RectangleF"/> intersects with this rectangle; <c>false</c> otherwise.</returns>
|
||||||
|
public bool Intersects(RectangleF value)
|
||||||
|
{
|
||||||
|
return value.Left < Right &&
|
||||||
|
Left < value.Right &&
|
||||||
|
value.Top < Bottom &&
|
||||||
|
Top < value.Bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets whether or not the other <see cref="RectangleF"/> intersects with this rectangle.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The other rectangle for testing.</param>
|
||||||
|
/// <param name="result"><c>true</c> if other <see cref="RectangleF"/> intersects with this rectangle; <c>false</c> otherwise. As an output parameter.</param>
|
||||||
|
public void Intersects(ref RectangleF value, out bool result)
|
||||||
|
{
|
||||||
|
result = value.Left < Right &&
|
||||||
|
Left < value.Right &&
|
||||||
|
value.Top < Bottom &&
|
||||||
|
Top < value.Bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new <see cref="RectangleF"/> that contains overlapping region of two other rectangles.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value1">The first <see cref="RectangleF"/>.</param>
|
||||||
|
/// <param name="value2">The second <see cref="RectangleF"/>.</param>
|
||||||
|
/// <returns>Overlapping region of the two rectangles.</returns>
|
||||||
|
public static RectangleF Intersect(RectangleF value1, RectangleF value2)
|
||||||
|
{
|
||||||
|
RectangleF rectangle;
|
||||||
|
Intersect(ref value1, ref value2, out rectangle);
|
||||||
|
return rectangle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new <see cref="RectangleF"/> that contains overlapping region of two other rectangles.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value1">The first <see cref="RectangleF"/>.</param>
|
||||||
|
/// <param name="value2">The second <see cref="RectangleF"/>.</param>
|
||||||
|
/// <param name="result">Overlapping region of the two rectangles as an output parameter.</param>
|
||||||
|
public static void Intersect(ref RectangleF value1, ref RectangleF value2, out RectangleF result)
|
||||||
|
{
|
||||||
|
if (value1.Intersects(value2))
|
||||||
|
{
|
||||||
|
float right_side = MathF.Min(value1.X + value1.Width, value2.X + value2.Width);
|
||||||
|
float left_side = MathF.Max(value1.X, value2.X);
|
||||||
|
float top_side = MathF.Max(value1.Y, value2.Y);
|
||||||
|
float bottom_side = MathF.Min(value1.Y + value1.Height, value2.Y + value2.Height);
|
||||||
|
result = new RectangleF(left_side, top_side, right_side - left_side, bottom_side - top_side);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = new RectangleF(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Changes the <see cref="Location"/> of this <see cref="RectangleF"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="offsetX">The x coordinate to add to this <see cref="RectangleF"/>.</param>
|
||||||
|
/// <param name="offsetY">The y coordinate to add to this <see cref="RectangleF"/>.</param>
|
||||||
|
public void Offset(int offsetX, int offsetY)
|
||||||
|
{
|
||||||
|
X += offsetX;
|
||||||
|
Y += offsetY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Changes the <see cref="Location"/> of this <see cref="RectangleF"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="offsetX">The x coordinate to add to this <see cref="RectangleF"/>.</param>
|
||||||
|
/// <param name="offsetY">The y coordinate to add to this <see cref="RectangleF"/>.</param>
|
||||||
|
public void Offset(float offsetX, float offsetY)
|
||||||
|
{
|
||||||
|
X += (float)offsetX;
|
||||||
|
Y += (float)offsetY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Changes the <see cref="Location"/> of this <see cref="RectangleF"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="amount">The x and y components to add to this <see cref="RectangleF"/>.</param>
|
||||||
|
public void Offset(Point amount)
|
||||||
|
{
|
||||||
|
X += amount.X;
|
||||||
|
Y += amount.Y;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Changes the <see cref="Location"/> of this <see cref="RectangleF"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="amount">The x and y components to add to this <see cref="RectangleF"/>.</param>
|
||||||
|
public void Offset(Vector2 amount)
|
||||||
|
{
|
||||||
|
X += (float)amount.X;
|
||||||
|
Y += (float)amount.Y;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a <see cref="String"/> representation of this <see cref="RectangleF"/> in the format:
|
||||||
|
/// {X:[<see cref="X"/>] Y:[<see cref="Y"/>] Width:[<see cref="Width"/>] Height:[<see cref="Height"/>]}
|
||||||
|
/// </summary>
|
||||||
|
/// <returns><see cref="String"/> representation of this <see cref="RectangleF"/>.</returns>
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return "{X:" + X + " Y:" + Y + " Width:" + Width + " Height:" + Height + "}";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new <see cref="RectangleF"/> that completely contains two other rectangles.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value1">The first <see cref="RectangleF"/>.</param>
|
||||||
|
/// <param name="value2">The second <see cref="RectangleF"/>.</param>
|
||||||
|
/// <returns>The union of the two rectangles.</returns>
|
||||||
|
public static RectangleF Union(RectangleF value1, RectangleF value2)
|
||||||
|
{
|
||||||
|
float x = MathF.Min(value1.X, value2.X);
|
||||||
|
float y = MathF.Min(value1.Y, value2.Y);
|
||||||
|
return new RectangleF(x, y,
|
||||||
|
Math.Max(value1.Right, value2.Right) - x,
|
||||||
|
Math.Max(value1.Bottom, value2.Bottom) - y);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new <see cref="RectangleF"/> that completely contains two other rectangles.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value1">The first <see cref="RectangleF"/>.</param>
|
||||||
|
/// <param name="value2">The second <see cref="RectangleF"/>.</param>
|
||||||
|
/// <param name="result">The union of the two rectangles as an output parameter.</param>
|
||||||
|
public static void Union(ref RectangleF value1, ref RectangleF value2, out RectangleF result)
|
||||||
|
{
|
||||||
|
result.X = Math.Min(value1.X, value2.X);
|
||||||
|
result.Y = Math.Min(value1.Y, value2.Y);
|
||||||
|
result.Width = Math.Max(value1.Right, value2.Right) - result.X;
|
||||||
|
result.Height = Math.Max(value1.Bottom, value2.Bottom) - result.Y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddPoint(Point point)
|
||||||
|
{
|
||||||
|
if (point.X < X)
|
||||||
|
{
|
||||||
|
Width += X - point.X;
|
||||||
|
X = point.X;
|
||||||
|
}
|
||||||
|
else if (point.X > Right)
|
||||||
|
{
|
||||||
|
Width += point.X - Right;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (point.Y < Y)
|
||||||
|
{
|
||||||
|
Height += Y - point.Y;
|
||||||
|
Y = point.Y;
|
||||||
|
}
|
||||||
|
else if (point.Y > Bottom)
|
||||||
|
{
|
||||||
|
Height += point.Y - Bottom;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user