diff --git a/MLEM/Animations/SpriteAnimation.cs b/MLEM/Animations/SpriteAnimation.cs
index 405ea80..7fd8b59 100644
--- a/MLEM/Animations/SpriteAnimation.cs
+++ b/MLEM/Animations/SpriteAnimation.cs
@@ -5,10 +5,21 @@ using MLEM.Misc;
using MLEM.Textures;
namespace MLEM.Animations {
+ ///
+ /// A sprite animation that allows for any number of frames that each last any number of seconds
+ ///
public class SpriteAnimation : GenericDataHolder {
private AnimationFrame[] frames;
+ ///
+ /// Returns the at the given index.
+ /// Index ordering is based on the order that animation frames were added in.
+ ///
+ /// The index in the list of animation frames
public AnimationFrame this[int index] => this.frames[index];
+ ///
+ /// The frame that the animation is currently on.
+ ///
public AnimationFrame CurrentFrame {
get {
// we might have overshot the end time by a little bit, so just return the last frame
@@ -24,35 +35,86 @@ namespace MLEM.Animations {
return this.frames[0];
}
}
+ ///
+ /// The texture region that the animation's has
+ ///
public TextureRegion CurrentRegion => this.CurrentFrame.Region;
+ ///
+ /// The total amount of time that this animation has.
+ /// This is auatomatically calculated based on the frame time of each frame.
+ ///
public readonly double TotalTime;
+ ///
+ /// The amount of seconds that the animation has been going on for.
+ /// If is reached, this value resets to 0.
+ ///
public double TimeIntoAnimation { get; private set; }
+ ///
+ /// The finished state of this animation.
+ /// This is only true for longer than a frame if is false.
+ ///
public bool IsFinished { get; private set; }
+ ///
+ /// The name of this animation. This is useful if used in combination with .
+ ///
public string Name;
+ ///
+ /// The speed multiplier that this animation should run with.
+ /// Numbers higher than 1 will increase the speed.
+ ///
public float SpeedMultiplier = 1;
-
+ ///
+ /// Set to false to stop this animation from looping.
+ /// To check if the animation has finished playing, see .
+ ///
public bool IsLooping = true;
- public Completed OnCompleted;
+ ///
+ /// A callback that gets fired when the animation completes.
+ ///
+ public event Completed OnCompleted;
+ ///
+ /// Set this to true to pause the playback of the animation.
+ /// will not continue and the will not change.
+ ///
public bool IsPaused;
+ ///
+ /// Creates a new sprite animation that contains the given frames.
+ ///
+ /// The frames this animation should have
public SpriteAnimation(params AnimationFrame[] frames) {
this.frames = frames;
foreach (var frame in frames)
this.TotalTime += frame.Seconds;
}
+ ///
+ /// Creates a new sprite animation that contains the given texture regions as frames.
+ ///
+ /// The amount of time that each frame should last for
+ /// The texture regions that should make up this animation
public SpriteAnimation(double timePerFrame, params TextureRegion[] regions)
: this(Array.ConvertAll(regions, region => new AnimationFrame(region, timePerFrame))) {
}
+ ///
+ /// Creates a new sprite animation based on the given texture regions in rectangle-based format.
+ ///
+ /// The amount of time that each frame should last for
+ /// The texture that the regions should come from
+ /// The texture regions that should make up this animation
public SpriteAnimation(double timePerFrame, Texture2D texture, params Rectangle[] regions)
: this(timePerFrame, Array.ConvertAll(regions, region => new TextureRegion(texture, region))) {
}
+ ///
+ /// Updates this animation, causing to be increased and the to be updated.
+ ///
+ /// The game's time
public void Update(GameTime time) {
this.SetTime(this.TimeIntoAnimation + time.ElapsedGameTime.TotalSeconds * this.SpeedMultiplier);
}
-
+
internal void SetTime(double totalTime) {
if (this.IsFinished || this.IsPaused)
return;
@@ -67,6 +129,9 @@ namespace MLEM.Animations {
}
}
+ ///
+ /// Restarts this animation from the first frame.
+ ///
public void Restart() {
this.TimeIntoAnimation = 0;
this.IsFinished = false;
@@ -77,11 +142,25 @@ namespace MLEM.Animations {
}
+ ///
+ /// Represents a single frame of a
+ ///
public class AnimationFrame {
+ ///
+ /// The texture region that this frame should render
+ ///
public readonly TextureRegion Region;
+ ///
+ /// The total amount of seconds that this frame should last for
+ ///
public readonly double Seconds;
+ ///
+ /// Creates a new animation frame based on a texture region and a time
+ ///
+ /// The texture region that this frame should render
+ /// The total amount of seconds that this frame should last for
public AnimationFrame(TextureRegion region, double seconds) {
this.Region = region;
this.Seconds = seconds;
diff --git a/MLEM/Animations/SpriteAnimationGroup.cs b/MLEM/Animations/SpriteAnimationGroup.cs
index 53140c0..1dce5df 100644
--- a/MLEM/Animations/SpriteAnimationGroup.cs
+++ b/MLEM/Animations/SpriteAnimationGroup.cs
@@ -5,7 +5,11 @@ using MLEM.Misc;
using MLEM.Textures;
namespace MLEM.Animations {
- public class SpriteAnimationGroup : GenericDataHolder{
+ ///
+ /// Represents a list of objects with a condition and priority attached to them.
+ /// Sprite animation groups can be used if any single entity should have multiple animations (like up, down, left, right standing and running animations) that should be automatically managed.
+ ///
+ public class SpriteAnimationGroup : GenericDataHolder {
private readonly List animations = new List();
private ConditionedAnimation currAnimation;
@@ -20,11 +24,24 @@ namespace MLEM.Animations {
}
set => this.currAnimation = value;
}
+ ///
+ /// The animation that is currently playing
+ ///
public SpriteAnimation CurrentAnimation => this.CurrAnimation?.Animation;
+ ///
+ /// The frame that is displaying
+ ///
public AnimationFrame CurrentFrame => this.CurrentAnimation?.CurrentFrame;
+ ///
+ /// The region that has
+ ///
public TextureRegion CurrentRegion => this.CurrentAnimation?.CurrentRegion;
- public AnimationChanged OnAnimationChanged;
+ ///
+ /// A callback for when the currently displaying animation has changed due to a condition with a higher priority being met.
+ ///
+ public event AnimationChanged OnAnimationChanged;
private bool isDirty;
+ ///
public float SpeedMultiplier {
set {
foreach (var anim in this.animations)
@@ -32,23 +49,36 @@ namespace MLEM.Animations {
}
}
+ ///
+ /// Adds a to this group.
+ ///
+ /// The animation to add
+ /// The condition that needs to be met for this animation to play
+ /// The priority of this animation. The higher the priority, the earlier it is picked for playing.
+ /// This group, for chaining
public SpriteAnimationGroup Add(SpriteAnimation anim, Func condition, int priority = 0) {
this.animations.Add(new ConditionedAnimation(anim, condition, priority));
this.isDirty = true;
return this;
}
+ ///
public void Update(GameTime time) {
this.FindAnimationToPlay();
if (this.CurrAnimation != null)
this.CurrAnimation.Animation.Update(time);
}
+ ///
+ /// Find an animation in this group by name and returns it.
+ ///
+ /// The of the animation
+ /// The animation by that name, or null if there is none
public SpriteAnimation ByName(string name) {
return this.animations.Find(anim => anim.Animation.Name == name)?.Animation;
}
- public void FindAnimationToPlay() {
+ private void FindAnimationToPlay() {
ConditionedAnimation animToPlay = null;
if (this.CurrAnimation != null && this.CurrAnimation.ShouldPlay())
animToPlay = this.CurrAnimation;
diff --git a/MLEM/Cameras/Camera.cs b/MLEM/Cameras/Camera.cs
index 25a544e..35dfcd8 100644
--- a/MLEM/Cameras/Camera.cs
+++ b/MLEM/Cameras/Camera.cs
@@ -5,18 +5,45 @@ using MLEM.Extensions;
using MLEM.Misc;
namespace MLEM.Cameras {
+ ///
+ /// Represents a simple, orthographic 2-dimensional camera that can be moved, scaled and that supports automatic viewport sizing.
+ /// To draw with the camera's positioning and scaling applied, use .
+ ///
public class Camera {
+ ///
+ /// The top-left corner of the camera's viewport.
+ ///
+ ///
public Vector2 Position;
+ ///
+ /// The scale that this camera's should have.
+ ///
public float Scale {
get => this.scale;
set => this.scale = MathHelper.Clamp(value, this.MinScale, this.MaxScale);
}
private float scale = 1;
+ ///
+ /// The minimum that the camera can have
+ ///
public float MinScale = 0;
+ ///
+ /// The maximum that the camera can have
+ ///
public float MaxScale = float.MaxValue;
+ ///
+ /// If this is true, the camera will automatically adapt to changed screen sizes.
+ /// You can use to determine the initial screen size that this camera should base its calculations on.
+ ///
public bool AutoScaleWithScreen;
+ ///
+ ///
+ ///
public Point AutoScaleReferenceSize;
+ ///
+ /// The scale that this camera currently has, based on and if is true.
+ ///
public float ActualScale {
get {
if (!this.AutoScaleWithScreen)
@@ -24,6 +51,10 @@ namespace MLEM.Cameras {
return Math.Min(this.Viewport.Width / (float) this.AutoScaleReferenceSize.X, this.Viewport.Height / (float) this.AutoScaleReferenceSize.Y) * this.Scale;
}
}
+ ///
+ /// The matrix that this camera "sees", based on its position and scale.
+ /// Use this in your calls to render based on the camera's viewport.
+ ///
public Matrix ViewMatrix {
get {
var sc = this.ActualScale;
@@ -33,39 +64,73 @@ namespace MLEM.Cameras {
return Matrix.CreateScale(sc, sc, 1) * Matrix.CreateTranslation(new Vector3(pos, 0));
}
}
+ ///
+ /// The bottom-right corner of the camera's viewport
+ ///
+ ///
public Vector2 Max {
get => this.Position + this.ScaledViewport;
set => this.Position = value - this.ScaledViewport;
}
+ ///
+ /// The center of the camera's viewport, or the position that the camera is looking at.
+ ///
public Vector2 LookingPosition {
get => this.Position + this.ScaledViewport / 2;
set => this.Position = value - this.ScaledViewport / 2;
}
- public Rectangle Viewport => this.graphicsDevice.Viewport.Bounds;
- public Vector2 ScaledViewport => new Vector2(this.Viewport.Width, this.Viewport.Height) / this.ActualScale;
+ private Rectangle Viewport => this.graphicsDevice.Viewport.Bounds;
+ private Vector2 ScaledViewport => new Vector2(this.Viewport.Width, this.Viewport.Height) / this.ActualScale;
private readonly bool roundPosition;
private readonly GraphicsDevice graphicsDevice;
+ ///
+ /// Creates a new camera.
+ ///
+ /// The game's graphics device
+ /// If this is true, the camera's and related properties will be rounded to full integers.
public Camera(GraphicsDevice graphicsDevice, bool roundPosition = true) {
this.graphicsDevice = graphicsDevice;
this.AutoScaleReferenceSize = this.Viewport.Size;
this.roundPosition = roundPosition;
}
+ ///
+ /// Converts a given position in screen space to world space
+ ///
+ /// The position in screen space
+ /// The position in world space
public Vector2 ToWorldPos(Vector2 pos) {
return Vector2.Transform(pos, Matrix.Invert(this.ViewMatrix));
}
+ ///
+ /// Converts a given position in world space to screen space
+ ///
+ /// The position in world space
+ /// The position in camera space
public Vector2 ToCameraPos(Vector2 pos) {
return Vector2.Transform(pos, this.ViewMatrix);
}
+ ///
+ /// Returns the area that this camera can see, in world space.
+ /// This can be useful for culling of tile and other entity renderers.
+ ///
+ /// A rectangle that represents the camera's visible area in world space
public RectangleF GetVisibleRectangle() {
var start = this.ToWorldPos(Vector2.Zero);
return new RectangleF(start, this.ToWorldPos(new Vector2(this.Viewport.Width, this.Viewport.Height)) - start);
}
+ ///
+ /// Forces the camera's bounds into the given min and max positions in world space.
+ /// If the space represented by the given values is smaller than what the camera can see, its position will be forced into the center of the area.
+ ///
+ /// The top left bound, in world space
+ /// The bottom right bound, in world space
+ /// Whether or not the camera's position changed as a result of the constraint
public bool ConstrainWorldBounds(Vector2 min, Vector2 max) {
var lastPos = this.Position;
var visible = this.GetVisibleRectangle();
@@ -89,6 +154,11 @@ namespace MLEM.Cameras {
return !this.Position.Equals(lastPos, 0.001F);
}
+ ///
+ /// Zoom in the camera's view by a given amount, optionally focusing on a given center point.
+ ///
+ /// The amount to zoom in or out by
+ /// The position that should be regarded as the zoom's center, in screen space. The default value is the center.
public void Zoom(float delta, Vector2? zoomCenter = null) {
var center = (zoomCenter ?? this.Viewport.Size.ToVector2() / 2) / this.ActualScale;
var lastScale = this.Scale;
diff --git a/MLEM/Content/RawContentManager.cs b/MLEM/Content/RawContentManager.cs
index c661de9..783f934 100644
--- a/MLEM/Content/RawContentManager.cs
+++ b/MLEM/Content/RawContentManager.cs
@@ -8,6 +8,9 @@ using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
namespace MLEM.Content {
+ ///
+ /// Represents a version of that doesn't load content binary xnb files, but rather as their regular formats.
+ ///
public class RawContentManager : ContentManager, IGameComponent {
private static readonly RawContentReader[] Readers = AppDomain.CurrentDomain.GetAssemblies()
@@ -18,14 +21,29 @@ namespace MLEM.Content {
private readonly List disposableAssets = new List();
+ ///
+ /// The graphics device that this content manager uses
+ ///
public readonly GraphicsDevice GraphicsDevice;
+ ///
+ /// Creates a new content manager with an optionally specified root directory.
+ ///
+ /// The service provider of your game
+ /// The root directory. Defaults to "Content"
public RawContentManager(IServiceProvider serviceProvider, string rootDirectory = "Content") :
base(serviceProvider, rootDirectory) {
if (serviceProvider.GetService(typeof(IGraphicsDeviceService)) is IGraphicsDeviceService s)
this.GraphicsDevice = s.GraphicsDevice;
}
+ ///
+ /// Loads a raw asset with the given name, based on the .
+ /// If the asset was previously loaded using this method, the cached asset is merely returned.
+ ///
+ /// The path and name of the asset to load, without extension.
+ /// The type of asset to load
+ /// The asset, either loaded from the cache, or from disk.
public override T Load(string assetName) {
if (this.LoadedAssets.TryGetValue(assetName, out var ret) && ret is T t)
return t;
diff --git a/MLEM/Content/RawContentReader.cs b/MLEM/Content/RawContentReader.cs
index 1aa1d33..8bad0ed 100644
--- a/MLEM/Content/RawContentReader.cs
+++ b/MLEM/Content/RawContentReader.cs
@@ -2,26 +2,59 @@ using System;
using System.IO;
namespace MLEM.Content {
+ ///
+ /// Represents a way for any kind of raw content file to be read using a
+ ///
public abstract class RawContentReader {
+ ///
+ /// Returns if the given type can be loaded by this content reader
+ ///
+ /// The type of asset
+ /// If can be loaded by this content reader
public abstract bool CanRead(Type t);
+ ///
+ /// Reads the content file from disk and returns it.
+ ///
+ /// The that is loading the asset
+ /// The full path to the asset, starting from the
+ /// A stream that leads to this asset
+ /// The type of asset to load
+ /// If this asset is being reloaded, this value contains the previous version of the asset.
+ /// The loaded asset
public abstract object Read(RawContentManager manager, string assetPath, Stream stream, Type t, object existing);
+ ///
+ /// Represents the list of file extensions that this reader can read from.
+ ///
+ /// The list of valid extensions
public abstract string[] GetFileExtensions();
}
+ ///
public abstract class RawContentReader : RawContentReader {
+ ///
public override bool CanRead(Type t) {
return typeof(T).IsAssignableFrom(t);
}
+ ///
public override object Read(RawContentManager manager, string assetPath, Stream stream, Type t, object existing) {
return this.Read(manager, assetPath, stream, (T) existing);
}
+ ///
+ /// Reads the content file that is represented by our generic type from disk.
+ ///
+ /// The that is loading the asset
+ /// The full path to the asset, starting from the
+ /// A stream that leads to this asset
+ /// The type of asset to load
+ /// If this asset is being reloaded, this value contains the previous version of the asset.
+ /// The loaded asset
protected abstract T Read(RawContentManager manager, string assetPath, Stream stream, T existing);
}
diff --git a/MLEM/Extensions/ColorExtensions.cs b/MLEM/Extensions/ColorExtensions.cs
index dc08131..135c7a1 100644
--- a/MLEM/Extensions/ColorExtensions.cs
+++ b/MLEM/Extensions/ColorExtensions.cs
@@ -5,20 +5,43 @@ using Microsoft.Xna.Framework;
namespace MLEM.Extensions {
public static class ColorExtensions {
+ ///
+ /// Returns an inverted version of the color.
+ ///
+ /// The color to invert
+ /// The inverted color
public static Color Invert(this Color color) {
return new Color(Math.Abs(255 - color.R), Math.Abs(255 - color.G), Math.Abs(255 - color.B), color.A);
}
+ ///
+ /// Parses a hexadecimal number into a color.
+ /// The number should be in the format 0xaarrggbb.
+ ///
+ /// The number to parse
+ /// The resulting color
public static Color FromHex(uint value) {
return new Color((int) (value >> 16 & 0xFF), (int) (value >> 8 & 0xFF), (int) (value >> 0 & 0xFF), (int) (value >> 24 & 0xFF));
}
+ ///
+ /// Parses a hexadecimal string into a color.
+ /// The string can optionally start with a #.
+ ///
+ /// The string to parse
+ /// The resulting color
public static Color FromHex(string value) {
if (value.StartsWith("#"))
value = value.Substring(1);
return FromHex(uint.Parse(value, NumberStyles.HexNumber));
}
+ ///
+ /// Copies the alpha value from into this color.
+ ///
+ /// The color
+ /// The color to copy the alpha from
+ /// The with 's alpha value
public static Color CopyAlpha(this Color color, Color other) {
return color * (other.A / 255F);
}
diff --git a/MLEM/Extensions/GraphicsExtensions.cs b/MLEM/Extensions/GraphicsExtensions.cs
index 3007efa..bd2240f 100644
--- a/MLEM/Extensions/GraphicsExtensions.cs
+++ b/MLEM/Extensions/GraphicsExtensions.cs
@@ -9,6 +9,12 @@ namespace MLEM.Extensions {
private static int lastWidth;
private static int lastHeight;
+ ///
+ /// Sets the graphics device manager to fullscreen, properly taking into account the preferred backbuffer width and height to avoid lower resolutions for higher resolution screens.
+ ///
+ /// The graphics device manager
+ /// True if fullscreen should be enabled, false if disabled
+ /// Thrown when changing out of fullscreen mode before changing into fullscreen mode using this method
public static void SetFullscreen(this GraphicsDeviceManager manager, bool fullscreen) {
manager.IsFullScreen = fullscreen;
if (fullscreen) {
@@ -29,6 +35,10 @@ namespace MLEM.Extensions {
manager.ApplyChanges();
}
+ ///
+ /// Save version of that doesn't reset window size to defaults
+ ///
+ /// The graphics device manager
public static void ApplyChangesSafely(this GraphicsDeviceManager manager) {
// If we don't do this, then applying changes will cause the
// graphics device manager to reset the window size to the
@@ -39,6 +49,11 @@ namespace MLEM.Extensions {
manager.ApplyChanges();
}
+ ///
+ /// Resets preferred width and height back to the window's default bound values.
+ ///
+ /// The graphics device manager
+ /// The window whose bounds to use
public static void ResetWidthAndHeight(this GraphicsDeviceManager manager, GameWindow window) {
var (_, _, width, height) = window.ClientBounds;
manager.PreferredBackBufferWidth = Math.Max(height, width);
@@ -46,6 +61,13 @@ namespace MLEM.Extensions {
manager.ApplyChanges();
}
+ ///
+ /// Starts a new using the specified render target.
+ /// The returned context automatically disposes when used in a using statement, which causes any previously applied render targets to be reapplied automatically.
+ ///
+ /// The graphics device
+ /// The render target to apply
+ ///
public static TargetContext WithRenderTarget(this GraphicsDevice device, RenderTarget2D target) {
return new TargetContext(device, target);
}
diff --git a/MLEM/Extensions/NumberExtensions.cs b/MLEM/Extensions/NumberExtensions.cs
index 447304c..1bddce4 100644
--- a/MLEM/Extensions/NumberExtensions.cs
+++ b/MLEM/Extensions/NumberExtensions.cs
@@ -5,68 +5,115 @@ using MLEM.Misc;
namespace MLEM.Extensions {
public static class NumberExtensions {
+ ///
public static int Floor(this float f) {
return (int) Math.Floor(f);
}
+ ///
public static int Ceil(this float f) {
return (int) Math.Ceiling(f);
}
+ ///
+ /// Checks for decimal equality with a given tolerance.
+ ///
+ /// The first number to equate
+ /// The second number to equate
+ /// The equality tolerance
+ /// Whether or not and are different by at most
public static bool Equals(this float first, float second, float tolerance) {
- return Math.Abs(first- second) <= tolerance;
+ return Math.Abs(first - second) <= tolerance;
}
+ ///
public static bool Equals(this Vector2 first, Vector2 second, float tolerance) {
return Math.Abs(first.X - second.X) <= tolerance && Math.Abs(first.Y - second.Y) <= tolerance;
}
+ ///
public static bool Equals(this Vector3 first, Vector3 second, float tolerance) {
return Math.Abs(first.X - second.X) <= tolerance && Math.Abs(first.Y - second.Y) <= tolerance && Math.Abs(first.Z - second.Z) <= tolerance;
}
+ ///
public static bool Equals(this Vector4 first, Vector4 second, float tolerance) {
return Math.Abs(first.X - second.X) <= tolerance && Math.Abs(first.Y - second.Y) <= tolerance && Math.Abs(first.Z - second.Z) <= tolerance && Math.Abs(first.W - second.W) <= tolerance;
}
+ ///
public static Vector2 Floor(this Vector2 vec) {
return new Vector2(vec.X.Floor(), vec.Y.Floor());
}
+ ///
public static Vector3 Floor(this Vector3 vec) {
return new Vector3(vec.X.Floor(), vec.Y.Floor(), vec.Z.Floor());
}
+ ///
public static Vector4 Floor(this Vector4 vec) {
return new Vector4(vec.X.Floor(), vec.Y.Floor(), vec.Z.Floor(), vec.W.Floor());
}
+ ///
+ /// Multiplies a point by a given scalar.
+ ///
+ /// The point
+ /// The scalar
+ /// The point, multiplied by the scalar memberwise
public static Point Multiply(this Point point, float f) {
return new Point((point.X * f).Floor(), (point.Y * f).Floor());
}
+ ///
+ /// Divides a point by a given scalar.
+ ///
+ /// The point
+ /// The scalar
+ /// The point, divided by the scalar memberwise
public static Point Divide(this Point point, float f) {
return new Point((point.X / f).Floor(), (point.Y / f).Floor());
}
+ ///
+ /// Transforms a point by a given matrix.
+ ///
+ /// The point
+ /// The matrix
+ /// The point, transformed by the matrix
public static Point Transform(this Point position, Matrix matrix) {
return new Point(
(position.X * matrix.M11 + position.Y * matrix.M21 + matrix.M41).Floor(),
(position.X * matrix.M12 + position.Y * matrix.M22 + matrix.M42).Floor());
}
+ ///
+ /// Returns a copy of the given rectangle, moved by the given point.
+ /// The rectangle's size remains unchanged.
+ ///
+ /// The rectangle to move
+ /// The amount to move by
+ /// The moved rectangle
public static Rectangle OffsetCopy(this Rectangle rect, Point offset) {
rect.X += offset.X;
rect.Y += offset.Y;
return rect;
}
+ ///
public static RectangleF OffsetCopy(this RectangleF rect, Vector2 offset) {
rect.X += offset.X;
rect.Y += offset.Y;
return rect;
}
+ ///
+ /// Shrinks the rectangle by the given padding, causing its size to decrease by twice the amount and its position to be moved inwards by the amount.
+ ///
+ /// The rectangle to shrink
+ /// The padding to shrink by
+ /// The shrunk rectangle
public static Rectangle Shrink(this Rectangle rect, Point padding) {
rect.X += padding.X;
rect.Y += padding.Y;
@@ -75,6 +122,7 @@ namespace MLEM.Extensions {
return rect;
}
+ ///
public static RectangleF Shrink(this RectangleF rect, Vector2 padding) {
rect.X += padding.X;
rect.Y += padding.Y;
@@ -83,6 +131,7 @@ namespace MLEM.Extensions {
return rect;
}
+ ///
public static RectangleF Shrink(this RectangleF rect, Padding padding) {
rect.X += padding.Left;
rect.Y += padding.Top;
diff --git a/MLEM/Extensions/RandomExtensions.cs b/MLEM/Extensions/RandomExtensions.cs
index 80be53f..3fec383 100644
--- a/MLEM/Extensions/RandomExtensions.cs
+++ b/MLEM/Extensions/RandomExtensions.cs
@@ -5,14 +5,32 @@ using System.Linq;
namespace MLEM.Extensions {
public static class RandomExtensions {
+ ///
+ /// Gets a random entry from the given list with uniform chance.
+ ///
+ /// The random
+ /// The entries to choose from
+ /// The entries' type
+ /// A random entry
public static T GetRandomEntry(this Random random, params T[] entries) {
return entries[random.Next(entries.Length)];
}
+ ///
public static T GetRandomEntry(this Random random, IList entries) {
return entries[random.Next(entries.Count)];
}
+ ///
+ /// Returns a random entry from the given list based on the specified weight function.
+ /// A higher weight for an entry increases its likeliness of being picked.
+ ///
+ /// The random
+ /// The entries to choose from
+ /// A function that applies weight to each entry
+ /// The entries' type
+ /// A random entry, based on the entries' weight
+ /// If the weight function returns different weights for the same entry
public static T GetRandomWeightedEntry(this Random random, IList entries, Func weightFunc) {
var totalWeight = entries.Sum(weightFunc);
var goalWeight = random.Next(totalWeight);
diff --git a/MLEM/Extensions/SpriteBatchExtensions.cs b/MLEM/Extensions/SpriteBatchExtensions.cs
index 9c79969..71ae5e1 100644
--- a/MLEM/Extensions/SpriteBatchExtensions.cs
+++ b/MLEM/Extensions/SpriteBatchExtensions.cs
@@ -8,6 +8,12 @@ namespace MLEM.Extensions {
private static Texture2D blankTexture;
+ ///
+ /// Returns a 1x1 pixel white texture that can be used for drawing solid color shapes.
+ /// This texture is automatically disposed of when the batch is disposed.
+ ///
+ /// The sprite batch
+ /// A 1x1 pixel white texture
public static Texture2D GetBlankTexture(this SpriteBatch batch) {
if (blankTexture == null) {
blankTexture = new Texture2D(batch.GraphicsDevice, 1, 1);
@@ -22,6 +28,13 @@ namespace MLEM.Extensions {
return blankTexture;
}
+ ///
+ /// Generates a that has a texture with a given color and outline color
+ ///
+ /// The sprite batch
+ /// The fill color of the texture
+ /// The outline color of the texture
+ /// A containing a 3x3 texture with an outline
public static NinePatch GenerateTexture(this SpriteBatch batch, Color color, Color? outlineColor = null) {
var outli = outlineColor ?? Color.Black;
var tex = new Texture2D(batch.GraphicsDevice, 3, 3);
@@ -39,16 +52,19 @@ namespace MLEM.Extensions {
return new NinePatch(tex, 1);
}
+ ///
public static void Draw(this SpriteBatch batch, Texture2D texture, RectangleF destinationRectangle, Rectangle? sourceRectangle, Color color, float rotation, Vector2 origin, SpriteEffects effects, float layerDepth) {
var source = sourceRectangle ?? new Rectangle(0, 0, texture.Width, texture.Height);
var scale = new Vector2(1F / source.Width, 1F / source.Height) * destinationRectangle.Size;
batch.Draw(texture, destinationRectangle.Location, sourceRectangle, color, rotation, origin, scale, effects, layerDepth);
}
+ ///
public static void Draw(this SpriteBatch batch, Texture2D texture, RectangleF destinationRectangle, Rectangle? sourceRectangle, Color color) {
batch.Draw(texture, destinationRectangle, sourceRectangle, color, 0, Vector2.Zero, SpriteEffects.None, 0);
}
+ ///
public static void Draw(this SpriteBatch batch, Texture2D texture, RectangleF destinationRectangle, Color color) {
batch.Draw(texture, destinationRectangle, null, color);
}
diff --git a/MLEM/Font/GenericFont.cs b/MLEM/Font/GenericFont.cs
index 475b516..9b75b55 100644
--- a/MLEM/Font/GenericFont.cs
+++ b/MLEM/Font/GenericFont.cs
@@ -5,38 +5,67 @@ using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace MLEM.Font {
+ ///
+ /// Represents a font with additional abilities.
+ ///
+ ///
public abstract class GenericFont {
+ ///
+ /// The bold version of this font.
+ ///
public abstract GenericFont Bold { get; }
+ ///
+ /// The italic version of this font.
+ ///
public abstract GenericFont Italic { get; }
+ ///
public abstract float LineHeight { get; }
+ ///
public abstract Vector2 MeasureString(string text);
+ ///
public abstract Vector2 MeasureString(StringBuilder text);
+ ///
public abstract void DrawString(SpriteBatch batch, string text, Vector2 position, Color color);
+ ///
public abstract void DrawString(SpriteBatch batch, string text, Vector2 position, Color color, float rotation, Vector2 origin, float scale, SpriteEffects effects, float layerDepth);
+ ///
public abstract void DrawString(SpriteBatch batch, string text, Vector2 position, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float layerDepth);
+ ///
public abstract void DrawString(SpriteBatch batch, StringBuilder text, Vector2 position, Color color);
+ ///
public abstract void DrawString(SpriteBatch batch, StringBuilder text, Vector2 position, Color color, float rotation, Vector2 origin, float scale, SpriteEffects effects, float layerDepth);
+ ///
public abstract void DrawString(SpriteBatch batch, StringBuilder text, Vector2 position, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float layerDepth);
+ ///
+ /// Draws a string with the given text alignment.
+ ///
+ /// The sprite batch to use
+ /// The string to draw
+ /// The position of the top left corner of the string
+ /// The alignment to use
+ /// The color to use
public void DrawString(SpriteBatch batch, string text, Vector2 position, TextAlign align, Color color) {
this.DrawString(batch, text, position, align, color, 0, Vector2.Zero, Vector2.One, SpriteEffects.None, 0);
}
+ ///
public void DrawString(SpriteBatch batch, string text, Vector2 position, TextAlign align, Color color, float rotation, Vector2 origin, float scale, SpriteEffects effects, float layerDepth) {
this.DrawString(batch, text, position, align, color, rotation, origin, new Vector2(scale), effects, layerDepth);
}
+ ///
public void DrawString(SpriteBatch batch, string text, Vector2 position, TextAlign align, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float layerDepth) {
switch (align) {
case TextAlign.Center:
@@ -53,6 +82,16 @@ namespace MLEM.Font {
this.DrawString(batch, text, position, color, rotation, origin, scale, effects, layerDepth);
}
+ ///
+ /// Truncates a string to a given width. If the string's displayed area is larger than the maximum width, the string is cut off.
+ /// Optionally, the string can be cut off a bit sooner, adding the at the end instead.
+ ///
+ /// The text to truncate
+ /// The maximum width, in display pixels based on the font and scale
+ /// The scale to use for width measurements
+ /// If the string should be truncated from the back rather than the front
+ /// The characters to add to the end of the string if it is too long
+ /// The truncated string, or the same string if it is shorter than the maximum width
public string TruncateString(string text, float width, float scale, bool fromBack = false, string ellipsis = "") {
var total = new StringBuilder();
var ellipsisWidth = this.MeasureString(ellipsis).X * scale;
@@ -74,6 +113,14 @@ namespace MLEM.Font {
return total.ToString();
}
+ ///
+ /// Splits a string to a given maximum width, adding newline characters between each line.
+ /// Also splits long words.
+ ///
+ /// The text to split into multiple lines
+ /// The maximum width that each line should have
+ /// The scale to use for width measurements
+ /// The split string, containing newline characters at each new line
public string SplitString(string text, float width, float scale) {
var total = new StringBuilder();
foreach (var line in text.Split('\n')) {
@@ -109,6 +156,12 @@ namespace MLEM.Font {
return total.ToString(0, total.Length - 2);
}
+ ///
+ /// Returns a string made up of the given content characters that is the given length long when displayed.
+ ///
+ /// The width that the string should have if the scale is 1
+ /// The content that the string should contain. Defaults to a space.
+ ///
public string GetWidthString(float width, char content = ' ') {
var strg = content.ToString();
while (this.MeasureString(strg).X < width)
diff --git a/MLEM/Font/GenericSpriteFont.cs b/MLEM/Font/GenericSpriteFont.cs
index a85c94e..68de774 100644
--- a/MLEM/Font/GenericSpriteFont.cs
+++ b/MLEM/Font/GenericSpriteFont.cs
@@ -5,47 +5,66 @@ using Microsoft.Xna.Framework.Graphics;
using MLEM.Extensions;
namespace MLEM.Font {
+ ///
public class GenericSpriteFont : GenericFont {
public readonly SpriteFont Font;
+ ///
public override GenericFont Bold { get; }
+ ///
public override GenericFont Italic { get; }
+ ///
public override float LineHeight => this.Font.LineSpacing;
+ ///
+ /// Creates a new generic font using .
+ /// Optionally, a bold and italic version of the font can be supplied.
+ ///
+ /// The font to wrap
+ /// A bold version of the font
+ /// An italic version of the font
public GenericSpriteFont(SpriteFont font, SpriteFont bold = null, SpriteFont italic = null) {
this.Font = font;
this.Bold = bold != null ? new GenericSpriteFont(bold) : this;
this.Italic = italic != null ? new GenericSpriteFont(italic) : this;
}
+ ///
public override Vector2 MeasureString(string text) {
return this.Font.MeasureString(text);
}
+ ///
public override Vector2 MeasureString(StringBuilder text) {
return this.Font.MeasureString(text);
}
+ ///
public override void DrawString(SpriteBatch batch, string text, Vector2 position, Color color) {
batch.DrawString(this.Font, text, position, color);
}
+ ///
public override void DrawString(SpriteBatch batch, string text, Vector2 position, Color color, float rotation, Vector2 origin, float scale, SpriteEffects effects, float layerDepth) {
batch.DrawString(this.Font, text, position, color, rotation, origin, scale, effects, layerDepth);
}
+ ///
public override void DrawString(SpriteBatch batch, string text, Vector2 position, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float layerDepth) {
batch.DrawString(this.Font, text, position, color, rotation, origin, scale, effects, layerDepth);
}
+ ///
public override void DrawString(SpriteBatch batch, StringBuilder text, Vector2 position, Color color) {
batch.DrawString(this.Font, text, position, color);
}
+ ///
public override void DrawString(SpriteBatch batch, StringBuilder text, Vector2 position, Color color, float rotation, Vector2 origin, float scale, SpriteEffects effects, float layerDepth) {
batch.DrawString(this.Font, text, position, color, rotation, origin, scale, effects, layerDepth);
}
+ ///
public override void DrawString(SpriteBatch batch, StringBuilder text, Vector2 position, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float layerDepth) {
batch.DrawString(this.Font, text, position, color, rotation, origin, scale, effects, layerDepth);
}