mirror of
https://github.com/Ellpeck/MLEM.git
synced 2024-11-22 12:58:33 +01:00
finished the xml documentation for all packages
This commit is contained in:
parent
f12284169e
commit
3f60b2460c
21 changed files with 623 additions and 4 deletions
|
@ -5,14 +5,29 @@ using MLEM.Data.Json;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace MLEM.Data {
|
namespace MLEM.Data {
|
||||||
|
/// <summary>
|
||||||
|
/// A set of extensions for dealing with <see cref="ContentManager"/>
|
||||||
|
/// </summary>
|
||||||
public static class ContentExtensions {
|
public static class ContentExtensions {
|
||||||
|
|
||||||
private static readonly Dictionary<ContentManager, JsonSerializer> Serializers = new Dictionary<ContentManager, JsonSerializer>();
|
private static readonly Dictionary<ContentManager, JsonSerializer> Serializers = new Dictionary<ContentManager, JsonSerializer>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a <see cref="JsonSerializer"/> to the given content manager, which allows <see cref="LoadJson{T}"/> to load JSON-based content.
|
||||||
|
/// Note that <see cref="GetJsonSerializer"/> calls this method implicitly if no serializer exists.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="content">The content manager to add the json serializer to</param>
|
||||||
|
/// <param name="serializer">The json serializer to add</param>
|
||||||
public static void SetJsonSerializer(this ContentManager content, JsonSerializer serializer) {
|
public static void SetJsonSerializer(this ContentManager content, JsonSerializer serializer) {
|
||||||
Serializers[content] = serializer;
|
Serializers[content] = serializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the given content manager's json serializer.
|
||||||
|
/// This method sets a new json serializer using <see cref="SetJsonSerializer"/> if the given content manager does not yet have one.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="content">The content manager whose serializer to get</param>
|
||||||
|
/// <returns>The content manager's serializer</returns>
|
||||||
public static JsonSerializer GetJsonSerializer(this ContentManager content) {
|
public static JsonSerializer GetJsonSerializer(this ContentManager content) {
|
||||||
if (!Serializers.TryGetValue(content, out var serializer)) {
|
if (!Serializers.TryGetValue(content, out var serializer)) {
|
||||||
serializer = JsonConverters.AddAll(new JsonSerializer());
|
serializer = JsonConverters.AddAll(new JsonSerializer());
|
||||||
|
@ -21,11 +36,24 @@ namespace MLEM.Data {
|
||||||
return serializer;
|
return serializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a <see cref="JsonConverter"/> to the given content manager's <see cref="JsonSerializer"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="content">The content manager to add the converter to</param>
|
||||||
|
/// <param name="converter">The converter to add</param>
|
||||||
public static void AddJsonConverter(this ContentManager content, JsonConverter converter) {
|
public static void AddJsonConverter(this ContentManager content, JsonConverter converter) {
|
||||||
var serializer = GetJsonSerializer(content);
|
var serializer = GetJsonSerializer(content);
|
||||||
serializer.Converters.Add(converter);
|
serializer.Converters.Add(converter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Loads any kind of JSON data using the given content manager's <see cref="JsonSerializer"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="content">The content manager to load content with</param>
|
||||||
|
/// <param name="name">The name of the file to load</param>
|
||||||
|
/// <param name="extension">The file extension of the file to load, or ".json" by default</param>
|
||||||
|
/// <typeparam name="T">The type of asset to load</typeparam>
|
||||||
|
/// <returns>The loaded asset</returns>
|
||||||
public static T LoadJson<T>(this ContentManager content, string name, string extension = ".json") {
|
public static T LoadJson<T>(this ContentManager content, string name, string extension = ".json") {
|
||||||
using (var stream = File.OpenText(Path.Combine(content.RootDirectory, name + extension))) {
|
using (var stream = File.OpenText(Path.Combine(content.RootDirectory, name + extension))) {
|
||||||
using (var reader = new JsonTextReader(stream)) {
|
using (var reader = new JsonTextReader(stream)) {
|
||||||
|
|
|
@ -3,12 +3,15 @@ using MLEM.Misc;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace MLEM.Data.Json {
|
namespace MLEM.Data.Json {
|
||||||
|
/// <inheritdoc />
|
||||||
public class Direction2Converter : JsonConverter<Direction2> {
|
public class Direction2Converter : JsonConverter<Direction2> {
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public override void WriteJson(JsonWriter writer, Direction2 value, JsonSerializer serializer) {
|
public override void WriteJson(JsonWriter writer, Direction2 value, JsonSerializer serializer) {
|
||||||
writer.WriteValue(value.ToString());
|
writer.WriteValue(value.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public override Direction2 ReadJson(JsonReader reader, Type objectType, Direction2 existingValue, bool hasExistingValue, JsonSerializer serializer) {
|
public override Direction2 ReadJson(JsonReader reader, Type objectType, Direction2 existingValue, bool hasExistingValue, JsonSerializer serializer) {
|
||||||
Enum.TryParse<Direction2>(reader.Value.ToString(), out var dir);
|
Enum.TryParse<Direction2>(reader.Value.ToString(), out var dir);
|
||||||
return dir;
|
return dir;
|
||||||
|
|
|
@ -4,12 +4,23 @@ using System.Reflection;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace MLEM.Data.Json {
|
namespace MLEM.Data.Json {
|
||||||
|
/// <summary>
|
||||||
|
/// A helper class that stores all of the <see cref="JsonConverter"/> types that are part of MLEM.Data.
|
||||||
|
/// </summary>
|
||||||
public class JsonConverters {
|
public class JsonConverters {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An array of all of the <see cref="JsonConverter"/>s that are part of MLEM.Data
|
||||||
|
/// </summary>
|
||||||
public static readonly JsonConverter[] Converters = typeof(JsonConverters).Assembly.GetExportedTypes()
|
public static readonly JsonConverter[] Converters = typeof(JsonConverters).Assembly.GetExportedTypes()
|
||||||
.Where(t => t.IsSubclassOf(typeof(JsonConverter)))
|
.Where(t => t.IsSubclassOf(typeof(JsonConverter)))
|
||||||
.Select(t => t.GetConstructor(Type.EmptyTypes).Invoke(null)).Cast<JsonConverter>().ToArray();
|
.Select(t => t.GetConstructor(Type.EmptyTypes).Invoke(null)).Cast<JsonConverter>().ToArray();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds all of the <see cref="JsonConverter"/> objects that are part of MLEM.Data to the given <see cref="JsonSerializer"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="serializer">The serializer to add the converters to</param>
|
||||||
|
/// <returns>The given serializer, for chaining</returns>
|
||||||
public static JsonSerializer AddAll(JsonSerializer serializer) {
|
public static JsonSerializer AddAll(JsonSerializer serializer) {
|
||||||
foreach (var converter in Converters)
|
foreach (var converter in Converters)
|
||||||
serializer.Converters.Add(converter);
|
serializer.Converters.Add(converter);
|
||||||
|
|
|
@ -4,12 +4,15 @@ using Microsoft.Xna.Framework;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace MLEM.Data.Json {
|
namespace MLEM.Data.Json {
|
||||||
|
/// <inheritdoc />
|
||||||
public class PointConverter : JsonConverter<Point> {
|
public class PointConverter : JsonConverter<Point> {
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public override void WriteJson(JsonWriter writer, Point value, JsonSerializer serializer) {
|
public override void WriteJson(JsonWriter writer, Point value, JsonSerializer serializer) {
|
||||||
writer.WriteValue(value.X.ToString(CultureInfo.InvariantCulture) + " " + value.Y.ToString(CultureInfo.InvariantCulture));
|
writer.WriteValue(value.X.ToString(CultureInfo.InvariantCulture) + " " + value.Y.ToString(CultureInfo.InvariantCulture));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public override Point ReadJson(JsonReader reader, Type objectType, Point existingValue, bool hasExistingValue, JsonSerializer serializer) {
|
public override Point ReadJson(JsonReader reader, Type objectType, Point existingValue, bool hasExistingValue, JsonSerializer serializer) {
|
||||||
var value = reader.Value.ToString().Split(' ');
|
var value = reader.Value.ToString().Split(' ');
|
||||||
return new Point(int.Parse(value[0], CultureInfo.InvariantCulture), int.Parse(value[1], CultureInfo.InvariantCulture));
|
return new Point(int.Parse(value[0], CultureInfo.InvariantCulture), int.Parse(value[1], CultureInfo.InvariantCulture));
|
||||||
|
|
|
@ -4,17 +4,21 @@ using MLEM.Content;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace MLEM.Data.Json {
|
namespace MLEM.Data.Json {
|
||||||
|
/// <inheritdoc />
|
||||||
public class RawJsonReader : RawContentReader {
|
public class RawJsonReader : RawContentReader {
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public override bool CanRead(Type t) {
|
public override bool CanRead(Type t) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public override object Read(RawContentManager manager, string assetPath, Stream stream, Type t, object existing) {
|
public override object Read(RawContentManager manager, string assetPath, Stream stream, Type t, object existing) {
|
||||||
using (var reader = new JsonTextReader(new StreamReader(stream)))
|
using (var reader = new JsonTextReader(new StreamReader(stream)))
|
||||||
return manager.GetJsonSerializer().Deserialize(reader);
|
return manager.GetJsonSerializer().Deserialize(reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public override string[] GetFileExtensions() {
|
public override string[] GetFileExtensions() {
|
||||||
return new[] {"json"};
|
return new[] {"json"};
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,14 +4,17 @@ using Microsoft.Xna.Framework;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace MLEM.Data.Json {
|
namespace MLEM.Data.Json {
|
||||||
|
/// <inheritdoc />
|
||||||
public class RectangleConverter : JsonConverter<Rectangle> {
|
public class RectangleConverter : JsonConverter<Rectangle> {
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public override void WriteJson(JsonWriter writer, Rectangle value, JsonSerializer serializer) {
|
public override void WriteJson(JsonWriter writer, Rectangle value, JsonSerializer serializer) {
|
||||||
writer.WriteValue(
|
writer.WriteValue(
|
||||||
value.X.ToString(CultureInfo.InvariantCulture) + " " + value.Y.ToString(CultureInfo.InvariantCulture) + " " +
|
value.X.ToString(CultureInfo.InvariantCulture) + " " + value.Y.ToString(CultureInfo.InvariantCulture) + " " +
|
||||||
value.Width.ToString(CultureInfo.InvariantCulture) + " " + value.Height.ToString(CultureInfo.InvariantCulture));
|
value.Width.ToString(CultureInfo.InvariantCulture) + " " + value.Height.ToString(CultureInfo.InvariantCulture));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public override Rectangle ReadJson(JsonReader reader, Type objectType, Rectangle existingValue, bool hasExistingValue, JsonSerializer serializer) {
|
public override Rectangle ReadJson(JsonReader reader, Type objectType, Rectangle existingValue, bool hasExistingValue, JsonSerializer serializer) {
|
||||||
var value = reader.Value.ToString().Split(' ');
|
var value = reader.Value.ToString().Split(' ');
|
||||||
return new Rectangle(
|
return new Rectangle(
|
||||||
|
|
|
@ -4,14 +4,17 @@ using MLEM.Misc;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace MLEM.Data.Json {
|
namespace MLEM.Data.Json {
|
||||||
|
/// <inheritdoc />
|
||||||
public class RectangleFConverter : JsonConverter<RectangleF> {
|
public class RectangleFConverter : JsonConverter<RectangleF> {
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public override void WriteJson(JsonWriter writer, RectangleF value, JsonSerializer serializer) {
|
public override void WriteJson(JsonWriter writer, RectangleF value, JsonSerializer serializer) {
|
||||||
writer.WriteValue(
|
writer.WriteValue(
|
||||||
value.X.ToString(CultureInfo.InvariantCulture) + " " + value.Y.ToString(CultureInfo.InvariantCulture) + " " +
|
value.X.ToString(CultureInfo.InvariantCulture) + " " + value.Y.ToString(CultureInfo.InvariantCulture) + " " +
|
||||||
value.Width.ToString(CultureInfo.InvariantCulture) + " " + value.Height.ToString(CultureInfo.InvariantCulture));
|
value.Width.ToString(CultureInfo.InvariantCulture) + " " + value.Height.ToString(CultureInfo.InvariantCulture));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public override RectangleF ReadJson(JsonReader reader, Type objectType, RectangleF existingValue, bool hasExistingValue, JsonSerializer serializer) {
|
public override RectangleF ReadJson(JsonReader reader, Type objectType, RectangleF existingValue, bool hasExistingValue, JsonSerializer serializer) {
|
||||||
var value = reader.Value.ToString().Split(' ');
|
var value = reader.Value.ToString().Split(' ');
|
||||||
return new RectangleF(
|
return new RectangleF(
|
||||||
|
|
|
@ -4,12 +4,15 @@ using Microsoft.Xna.Framework;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace MLEM.Data.Json {
|
namespace MLEM.Data.Json {
|
||||||
|
/// <inheritdoc />
|
||||||
public class Vector2Converter : JsonConverter<Vector2> {
|
public class Vector2Converter : JsonConverter<Vector2> {
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public override void WriteJson(JsonWriter writer, Vector2 value, JsonSerializer serializer) {
|
public override void WriteJson(JsonWriter writer, Vector2 value, JsonSerializer serializer) {
|
||||||
writer.WriteValue(value.X.ToString(CultureInfo.InvariantCulture) + " " + value.Y.ToString(CultureInfo.InvariantCulture));
|
writer.WriteValue(value.X.ToString(CultureInfo.InvariantCulture) + " " + value.Y.ToString(CultureInfo.InvariantCulture));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public override Vector2 ReadJson(JsonReader reader, Type objectType, Vector2 existingValue, bool hasExistingValue, JsonSerializer serializer) {
|
public override Vector2 ReadJson(JsonReader reader, Type objectType, Vector2 existingValue, bool hasExistingValue, JsonSerializer serializer) {
|
||||||
var value = reader.Value.ToString().Split(' ');
|
var value = reader.Value.ToString().Split(' ');
|
||||||
return new Vector2(float.Parse(value[0], CultureInfo.InvariantCulture), float.Parse(value[1], CultureInfo.InvariantCulture));
|
return new Vector2(float.Parse(value[0], CultureInfo.InvariantCulture), float.Parse(value[1], CultureInfo.InvariantCulture));
|
||||||
|
|
|
@ -5,12 +5,20 @@ using Lidgren.Network;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace MLEM.Data {
|
namespace MLEM.Data {
|
||||||
|
/// <summary>
|
||||||
|
/// A net buffer serializer allows easily writing generic objects into a Lidgren.Network <see cref="NetBuffer"/>.
|
||||||
|
/// It can be used both for serialization of outgoing packets, and deserialization of incoming packets.
|
||||||
|
/// Before serializing and deserializing an object, each of the object's fields has to have a handler. New handlers can be added using <see cref="AddHandler{T}(System.Action{Lidgren.Network.NetBuffer,T},System.Func{Lidgren.Network.NetBuffer,T})"/> or <see cref="AddHandler{T}(Newtonsoft.Json.JsonSerializer)"/>.
|
||||||
|
/// </summary>
|
||||||
public class NetBufferSerializer {
|
public class NetBufferSerializer {
|
||||||
|
|
||||||
private readonly Dictionary<Type, Action<NetBuffer, object>> writeFunctions = new Dictionary<Type, Action<NetBuffer, object>>();
|
private readonly Dictionary<Type, Action<NetBuffer, object>> writeFunctions = new Dictionary<Type, Action<NetBuffer, object>>();
|
||||||
private readonly Dictionary<Type, Func<NetBuffer, object>> readFunctions = new Dictionary<Type, Func<NetBuffer, object>>();
|
private readonly Dictionary<Type, Func<NetBuffer, object>> readFunctions = new Dictionary<Type, Func<NetBuffer, object>>();
|
||||||
private readonly Dictionary<Type, FieldInfo[]> fieldCache = new Dictionary<Type, FieldInfo[]>();
|
private readonly Dictionary<Type, FieldInfo[]> fieldCache = new Dictionary<Type, FieldInfo[]>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a new net buffer serializer with some default serialization and deserialization implementations for various types.
|
||||||
|
/// </summary>
|
||||||
public NetBufferSerializer() {
|
public NetBufferSerializer() {
|
||||||
foreach (var method in typeof(NetBuffer).GetMethods(BindingFlags.Instance | BindingFlags.Public)) {
|
foreach (var method in typeof(NetBuffer).GetMethods(BindingFlags.Instance | BindingFlags.Public)) {
|
||||||
if (method.GetParameters().Length == 0 && method.Name.StartsWith("Read", StringComparison.Ordinal) && method.Name.Substring(4) == method.ReturnType.Name)
|
if (method.GetParameters().Length == 0 && method.Name.StartsWith("Read", StringComparison.Ordinal) && method.Name.Substring(4) == method.ReturnType.Name)
|
||||||
|
@ -28,6 +36,14 @@ namespace MLEM.Data {
|
||||||
this.AddHandler((buffer, o) => buffer.Write(o), buffer => buffer.ReadDirection());
|
this.AddHandler((buffer, o) => buffer.Write(o), buffer => buffer.ReadDirection());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Serializes the given object into the given net buffer.
|
||||||
|
/// Note that each field in the object has to have a handler (<see cref="AddHandler{T}(System.Action{Lidgren.Network.NetBuffer,T},System.Func{Lidgren.Network.NetBuffer,T})"/>)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="buffer">The buffer to serialize into</param>
|
||||||
|
/// <param name="o">The object to serialize</param>
|
||||||
|
/// <param name="flags">The binding flags to search for fields in the object by</param>
|
||||||
|
/// <exception cref="ArgumentException">If any of the object's fields has no writer</exception>
|
||||||
public void Serialize(NetBuffer buffer, object o, BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) {
|
public void Serialize(NetBuffer buffer, object o, BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) {
|
||||||
foreach (var field in this.GetFields(o.GetType(), flags)) {
|
foreach (var field in this.GetFields(o.GetType(), flags)) {
|
||||||
if (!this.writeFunctions.TryGetValue(field.FieldType, out var func))
|
if (!this.writeFunctions.TryGetValue(field.FieldType, out var func))
|
||||||
|
@ -36,6 +52,14 @@ namespace MLEM.Data {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Deserializes the net buffer's content into the given object.
|
||||||
|
/// If this is used for packet serialization, a new instance of the required type has to be created before this method is called.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="buffer">The buffer to read the data from</param>
|
||||||
|
/// <param name="o">The object to serialize into</param>
|
||||||
|
/// <param name="flags">The binding flags to search for fields in the object by</param>
|
||||||
|
/// <exception cref="ArgumentException">If any of the object's fields has no reader</exception>
|
||||||
public void Deserialize(NetBuffer buffer, object o, BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) {
|
public void Deserialize(NetBuffer buffer, object o, BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) {
|
||||||
foreach (var field in this.GetFields(o.GetType(), flags)) {
|
foreach (var field in this.GetFields(o.GetType(), flags)) {
|
||||||
if (!this.readFunctions.TryGetValue(field.FieldType, out var func))
|
if (!this.readFunctions.TryGetValue(field.FieldType, out var func))
|
||||||
|
@ -53,11 +77,23 @@ namespace MLEM.Data {
|
||||||
return fields;
|
return fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a manually created deserialization and serialization handler to this net buffer serializer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="write">The function to write the given object into the net buffer</param>
|
||||||
|
/// <param name="read">The function to read the given object out of the net buffer</param>
|
||||||
|
/// <typeparam name="T">The type that will be serialized and deserialized</typeparam>
|
||||||
public void AddHandler<T>(Action<NetBuffer, T> write, Func<NetBuffer, T> read) {
|
public void AddHandler<T>(Action<NetBuffer, T> write, Func<NetBuffer, T> read) {
|
||||||
this.writeFunctions.Add(typeof(T), (buffer, o) => write(buffer, (T) o));
|
this.writeFunctions.Add(typeof(T), (buffer, o) => write(buffer, (T) o));
|
||||||
this.readFunctions.Add(typeof(T), buffer => read(buffer));
|
this.readFunctions.Add(typeof(T), buffer => read(buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a JSON-based deserialization and serialization handler to this net buffer serializer.
|
||||||
|
/// Objects that are serialized in this way are converted to JSON, and the resulting JSON is compressed.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="serializer">The JSON serializer to use</param>
|
||||||
|
/// <typeparam name="T">The type that will be serialized and deserialized</typeparam>
|
||||||
public void AddHandler<T>(JsonSerializer serializer) {
|
public void AddHandler<T>(JsonSerializer serializer) {
|
||||||
this.AddHandler((buffer, o) => buffer.WriteObject(o, serializer), buffer => buffer.ReadObject<T>(serializer));
|
this.AddHandler((buffer, o) => buffer.WriteObject(o, serializer), buffer => buffer.ReadObject<T>(serializer));
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,33 +9,73 @@ using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Bson;
|
using Newtonsoft.Json.Bson;
|
||||||
|
|
||||||
namespace MLEM.Data {
|
namespace MLEM.Data {
|
||||||
|
/// <summary>
|
||||||
|
/// A set of extensions for dealing with <see cref="NetBuffer"/>.
|
||||||
|
/// </summary>
|
||||||
public static class NetExtensions {
|
public static class NetExtensions {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes a <see cref="Vector2"/> to the given net buffer
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="buffer">The buffer to write to</param>
|
||||||
|
/// <param name="vector">The vector to write</param>
|
||||||
public static void Write(this NetBuffer buffer, Vector2 vector) {
|
public static void Write(this NetBuffer buffer, Vector2 vector) {
|
||||||
buffer.Write(vector.X);
|
buffer.Write(vector.X);
|
||||||
buffer.Write(vector.Y);
|
buffer.Write(vector.Y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads a <see cref="Vector2"/> from the given net buffer
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="buffer">The buffer to read from</param>
|
||||||
|
/// <returns>The read vector</returns>
|
||||||
public static Vector2 ReadVector2(this NetBuffer buffer) {
|
public static Vector2 ReadVector2(this NetBuffer buffer) {
|
||||||
return new Vector2(buffer.ReadFloat(), buffer.ReadFloat());
|
return new Vector2(buffer.ReadFloat(), buffer.ReadFloat());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes a <see cref="Guid"/> to the given net buffer
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="buffer">The buffer to write to</param>
|
||||||
|
/// <param name="guid">The guid to write</param>
|
||||||
public static void Write(this NetBuffer buffer, Guid guid) {
|
public static void Write(this NetBuffer buffer, Guid guid) {
|
||||||
buffer.Write(guid.ToByteArray());
|
buffer.Write(guid.ToByteArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads a <see cref="Guid"/> from the given net buffer
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="buffer">The buffer to read from</param>
|
||||||
|
/// <returns>The read guid</returns>
|
||||||
public static Guid ReadGuid(this NetBuffer buffer) {
|
public static Guid ReadGuid(this NetBuffer buffer) {
|
||||||
return new Guid(buffer.ReadBytes(16));
|
return new Guid(buffer.ReadBytes(16));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes a <see cref="Direction2"/> to the given net buffer
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="buffer">The buffer to write to</param>
|
||||||
|
/// <param name="direction">The direction to write</param>
|
||||||
public static void Write(this NetBuffer buffer, Direction2 direction) {
|
public static void Write(this NetBuffer buffer, Direction2 direction) {
|
||||||
buffer.Write((short) direction);
|
buffer.Write((short) direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads a <see cref="Direction2"/> from the given net buffer
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="buffer">The buffer to read from</param>
|
||||||
|
/// <returns>The read direction</returns>
|
||||||
public static Direction2 ReadDirection(this NetBuffer buffer) {
|
public static Direction2 ReadDirection(this NetBuffer buffer) {
|
||||||
return (Direction2) buffer.ReadInt16();
|
return (Direction2) buffer.ReadInt16();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes a generic object to the given net buffer using a <see cref="JsonSerializer"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="buffer">The buffer to write to</param>
|
||||||
|
/// <param name="obj">The object to write</param>
|
||||||
|
/// <param name="serializer">The JSON serializer to use</param>
|
||||||
|
/// <typeparam name="T">The type of object written</typeparam>
|
||||||
public static void WriteObject<T>(this NetBuffer buffer, T obj, JsonSerializer serializer) {
|
public static void WriteObject<T>(this NetBuffer buffer, T obj, JsonSerializer serializer) {
|
||||||
if (EqualityComparer<T>.Default.Equals(obj, default)) {
|
if (EqualityComparer<T>.Default.Equals(obj, default)) {
|
||||||
buffer.Write(0);
|
buffer.Write(0);
|
||||||
|
@ -50,6 +90,13 @@ namespace MLEM.Data {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads a generic object from the given buffer using a <see cref="JsonSerializer"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="buffer">The buffer to read from</param>
|
||||||
|
/// <param name="serializer">The JSON serializer to use</param>
|
||||||
|
/// <typeparam name="T">The type of object read</typeparam>
|
||||||
|
/// <returns>The read object</returns>
|
||||||
public static T ReadObject<T>(this NetBuffer buffer, JsonSerializer serializer) {
|
public static T ReadObject<T>(this NetBuffer buffer, JsonSerializer serializer) {
|
||||||
var length = buffer.ReadInt32();
|
var length = buffer.ReadInt32();
|
||||||
if (length <= 0)
|
if (length <= 0)
|
||||||
|
|
|
@ -1,12 +1,25 @@
|
||||||
using MonoGame.Extended;
|
using MonoGame.Extended;
|
||||||
|
|
||||||
namespace MLEM.Extended.Extensions {
|
namespace MLEM.Extended.Extensions {
|
||||||
|
/// <summary>
|
||||||
|
/// A set of extension methods that convert MLEM types to MonoGame.Extended types and vice versa.
|
||||||
|
/// </summary>
|
||||||
public static class NumberExtensions {
|
public static class NumberExtensions {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a MLEM <see cref="Misc.RectangleF"/> to a MonoGame.Extended <see cref="RectangleF"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="rect">The rectangle to convert</param>
|
||||||
|
/// <returns>The converted rectangle</returns>
|
||||||
public static RectangleF ToExtended(this Misc.RectangleF rect) {
|
public static RectangleF ToExtended(this Misc.RectangleF rect) {
|
||||||
return new RectangleF(rect.X, rect.Y, rect.Width, rect.Height);
|
return new RectangleF(rect.X, rect.Y, rect.Width, rect.Height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a MonoGame.Extended <see cref="RectangleF"/> to a MLEM <see cref="Misc.RectangleF"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="rect">The rectangle to convert</param>
|
||||||
|
/// <returns>The converted rectangle</returns>
|
||||||
public static Misc.RectangleF ToMlem(this RectangleF rect) {
|
public static Misc.RectangleF ToMlem(this RectangleF rect) {
|
||||||
return new Misc.RectangleF(rect.X, rect.Y, rect.Width, rect.Height);
|
return new Misc.RectangleF(rect.X, rect.Y, rect.Width, rect.Height);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,16 +3,38 @@ using Microsoft.Xna.Framework;
|
||||||
using MonoGame.Extended;
|
using MonoGame.Extended;
|
||||||
|
|
||||||
namespace MLEM.Extended.Extensions {
|
namespace MLEM.Extended.Extensions {
|
||||||
|
/// <summary>
|
||||||
|
/// A set of extension methods for dealing with <see cref="Random"/>
|
||||||
|
/// </summary>
|
||||||
public static class RandomExtensions {
|
public static class RandomExtensions {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a random number in the given range.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="random">The random to use for generation</param>
|
||||||
|
/// <param name="range">The range in which numbers will be generated</param>
|
||||||
|
/// <returns>A number in the given range</returns>
|
||||||
public static int Range(this Random random, Range<int> range) {
|
public static int Range(this Random random, Range<int> range) {
|
||||||
return random.Next(range.Min, range.Max);
|
return random.Next(range.Min, range.Max);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a random number in the given range.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="random">The random to use for generation</param>
|
||||||
|
/// <param name="range">The range in which numbers will be generated</param>
|
||||||
|
/// <returns>A number in the given range</returns>
|
||||||
public static float Range(this Random random, Range<float> range) {
|
public static float Range(this Random random, Range<float> range) {
|
||||||
return random.NextSingle(range.Min, range.Max);
|
return random.NextSingle(range.Min, range.Max);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a random vector whose x and y values are in the given range.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="random">The random to use for generation</param>
|
||||||
|
/// <param name="min">The minimum value for each coordinate</param>
|
||||||
|
/// <param name="max">The maximum value for each coordinate</param>
|
||||||
|
/// <returns>A random vector in the given range</returns>
|
||||||
public static Vector2 NextVector2(this Random random, float min, float max) {
|
public static Vector2 NextVector2(this Random random, float min, float max) {
|
||||||
return new Vector2(random.NextSingle(min, max), random.NextSingle(min, max));
|
return new Vector2(random.NextSingle(min, max), random.NextSingle(min, max));
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,16 +6,22 @@ using MonoGame.Extended;
|
||||||
using MonoGame.Extended.BitmapFonts;
|
using MonoGame.Extended.BitmapFonts;
|
||||||
|
|
||||||
namespace MLEM.Extended.Extensions {
|
namespace MLEM.Extended.Extensions {
|
||||||
|
/// <summary>
|
||||||
|
/// A set of extension methods for dealing with <see cref="SpriteBatch"/> and <see cref="RectangleF"/> in combination.
|
||||||
|
/// </summary>
|
||||||
public static class SpriteBatchExtensions {
|
public static class SpriteBatchExtensions {
|
||||||
|
|
||||||
|
/// <inheritdoc cref="SpriteBatch.Draw(Texture2D,Rectangle,Rectangle?,Color,float,Vector2,SpriteEffects,float)"/>
|
||||||
public static void Draw(this SpriteBatch batch, Texture2D texture, RectangleF destinationRectangle, Rectangle? sourceRectangle, Color color, float rotation, Vector2 origin, SpriteEffects effects, float layerDepth) {
|
public static void Draw(this SpriteBatch batch, Texture2D texture, RectangleF destinationRectangle, Rectangle? sourceRectangle, Color color, float rotation, Vector2 origin, SpriteEffects effects, float layerDepth) {
|
||||||
batch.Draw(texture, destinationRectangle.ToMlem(), sourceRectangle, color, rotation, origin, effects, layerDepth);
|
batch.Draw(texture, destinationRectangle.ToMlem(), sourceRectangle, color, rotation, origin, effects, layerDepth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="SpriteBatch.Draw(Texture2D,Rectangle,Rectangle?,Color)"/>
|
||||||
public static void Draw(this SpriteBatch batch, Texture2D texture, RectangleF destinationRectangle, Rectangle? sourceRectangle, Color color) {
|
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);
|
batch.Draw(texture, destinationRectangle, sourceRectangle, color, 0, Vector2.Zero, SpriteEffects.None, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="SpriteBatch.Draw(Texture2D,Rectangle,Color)"/>
|
||||||
public static void Draw(this SpriteBatch batch, Texture2D texture, RectangleF destinationRectangle, Color color) {
|
public static void Draw(this SpriteBatch batch, Texture2D texture, RectangleF destinationRectangle, Color color) {
|
||||||
batch.Draw(texture, destinationRectangle, null, color);
|
batch.Draw(texture, destinationRectangle, null, color);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,20 +3,43 @@ using MLEM.Textures;
|
||||||
using MonoGame.Extended.TextureAtlases;
|
using MonoGame.Extended.TextureAtlases;
|
||||||
|
|
||||||
namespace MLEM.Extended.Extensions {
|
namespace MLEM.Extended.Extensions {
|
||||||
|
/// <summary>
|
||||||
|
/// A set of extensions for converting texture-related types between MLEM and MonoGame.Extended.
|
||||||
|
/// </summary>
|
||||||
public static class TextureExtensions {
|
public static class TextureExtensions {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a MLEM <see cref="NinePatch"/> to a MonoGame.Extended <see cref="NinePatchRegion2D"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="patch">The nine patch to convert</param>
|
||||||
|
/// <returns>The converted nine patch</returns>
|
||||||
public static NinePatchRegion2D ToExtended(this NinePatch patch) {
|
public static NinePatchRegion2D ToExtended(this NinePatch patch) {
|
||||||
return new NinePatchRegion2D(patch.Region.ToExtended(), patch.Padding.Left.Floor(), patch.Padding.Top.Floor(), patch.Padding.Right.Floor(), patch.Padding.Bottom.Floor());
|
return new NinePatchRegion2D(patch.Region.ToExtended(), patch.Padding.Left.Floor(), patch.Padding.Top.Floor(), patch.Padding.Right.Floor(), patch.Padding.Bottom.Floor());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a MLEM <see cref="TextureRegion"/> to a MonoGame.Extended <see cref="TextureRegion2D"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="region">The nine patch to convert</param>
|
||||||
|
/// <returns>The converted nine patch</returns>
|
||||||
public static TextureRegion2D ToExtended(this TextureRegion region) {
|
public static TextureRegion2D ToExtended(this TextureRegion region) {
|
||||||
return new TextureRegion2D(region.Texture, region.U, region.V, region.Width, region.Height);
|
return new TextureRegion2D(region.Texture, region.U, region.V, region.Width, region.Height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a MonoGame.Extended <see cref="NinePatchRegion2D"/> to a MLEM <see cref="NinePatch"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="patch">The nine patch to convert</param>
|
||||||
|
/// <returns>The converted nine patch</returns>
|
||||||
public static NinePatch ToMlem(this NinePatchRegion2D patch) {
|
public static NinePatch ToMlem(this NinePatchRegion2D patch) {
|
||||||
return new NinePatch(new TextureRegion(patch.Texture, patch.Bounds), patch.LeftPadding, patch.RightPadding, patch.TopPadding, patch.BottomPadding);
|
return new NinePatch(new TextureRegion(patch.Texture, patch.Bounds), patch.LeftPadding, patch.RightPadding, patch.TopPadding, patch.BottomPadding);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a MonoGame.Extended <see cref="TextureRegion2D"/> to a MLEM <see cref="TextureRegion"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="region">The nine patch to convert</param>
|
||||||
|
/// <returns>The converted nine patch</returns>
|
||||||
public static TextureRegion ToMlem(this TextureRegion2D region) {
|
public static TextureRegion ToMlem(this TextureRegion2D region) {
|
||||||
return new TextureRegion(region.Texture, region.Bounds);
|
return new TextureRegion(region.Texture, region.Bounds);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,51 +7,73 @@ using MLEM.Font;
|
||||||
using MonoGame.Extended.BitmapFonts;
|
using MonoGame.Extended.BitmapFonts;
|
||||||
|
|
||||||
namespace MLEM.Extended.Font {
|
namespace MLEM.Extended.Font {
|
||||||
|
/// <inheritdoc/>
|
||||||
public class GenericBitmapFont : GenericFont {
|
public class GenericBitmapFont : GenericFont {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The <see cref="BitmapFont"/> that is being wrapped by this generic font
|
||||||
|
/// </summary>
|
||||||
public readonly BitmapFont Font;
|
public readonly BitmapFont Font;
|
||||||
|
/// <inheritdoc/>
|
||||||
public override GenericFont Bold { get; }
|
public override GenericFont Bold { get; }
|
||||||
|
/// <inheritdoc/>
|
||||||
public override GenericFont Italic { get; }
|
public override GenericFont Italic { get; }
|
||||||
|
/// <inheritdoc/>
|
||||||
public override float LineHeight => this.Font.LineHeight;
|
public override float LineHeight => this.Font.LineHeight;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new generic font using <see cref="BitmapFont"/>.
|
||||||
|
/// Optionally, a bold and italic version of the font can be supplied.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="font">The font to wrap</param>
|
||||||
|
/// <param name="bold">A bold version of the font</param>
|
||||||
|
/// <param name="italic">An italic version of the font</param>
|
||||||
public GenericBitmapFont(BitmapFont font, BitmapFont bold = null, BitmapFont italic = null) {
|
public GenericBitmapFont(BitmapFont font, BitmapFont bold = null, BitmapFont italic = null) {
|
||||||
this.Font = font;
|
this.Font = font;
|
||||||
this.Bold = bold != null ? new GenericBitmapFont(bold) : this;
|
this.Bold = bold != null ? new GenericBitmapFont(bold) : this;
|
||||||
this.Italic = italic != null ? new GenericBitmapFont(italic) : this;
|
this.Italic = italic != null ? new GenericBitmapFont(italic) : this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
public override Vector2 MeasureString(string text) {
|
public override Vector2 MeasureString(string text) {
|
||||||
if (text.Length == 1 && this.SingleCharacterWidthFix(text, out var size))
|
if (text.Length == 1 && this.SingleCharacterWidthFix(text, out var size))
|
||||||
return size;
|
return size;
|
||||||
return this.Font.MeasureString(text);
|
return this.Font.MeasureString(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
public override Vector2 MeasureString(StringBuilder text) {
|
public override Vector2 MeasureString(StringBuilder text) {
|
||||||
if (text.Length == 1 && this.SingleCharacterWidthFix(text.ToString(), out var size))
|
if (text.Length == 1 && this.SingleCharacterWidthFix(text.ToString(), out var size))
|
||||||
return size;
|
return size;
|
||||||
return this.Font.MeasureString(text);
|
return this.Font.MeasureString(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
public override void DrawString(SpriteBatch batch, string text, Vector2 position, Color color) {
|
public override void DrawString(SpriteBatch batch, string text, Vector2 position, Color color) {
|
||||||
batch.DrawString(this.Font, text, position, color);
|
batch.DrawString(this.Font, text, position, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
public override void DrawString(SpriteBatch batch, string text, Vector2 position, Color color, float rotation, Vector2 origin, float scale, SpriteEffects effects, float layerDepth) {
|
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);
|
batch.DrawString(this.Font, text, position, color, rotation, origin, scale, effects, layerDepth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
public override void DrawString(SpriteBatch batch, string text, Vector2 position, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float 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);
|
batch.DrawString(this.Font, text, position, color, rotation, origin, scale, effects, layerDepth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
public override void DrawString(SpriteBatch batch, StringBuilder text, Vector2 position, Color color) {
|
public override void DrawString(SpriteBatch batch, StringBuilder text, Vector2 position, Color color) {
|
||||||
batch.DrawString(this.Font, text, position, color);
|
batch.DrawString(this.Font, text, position, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
public override void DrawString(SpriteBatch batch, StringBuilder text, Vector2 position, Color color, float rotation, Vector2 origin, float scale, SpriteEffects effects, float layerDepth) {
|
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);
|
batch.DrawString(this.Font, text, position, color, rotation, origin, scale, effects, layerDepth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
public override void DrawString(SpriteBatch batch, StringBuilder text, Vector2 position, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float 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);
|
batch.DrawString(this.Font, text, position, color, rotation, origin, scale, effects, layerDepth);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,12 +2,17 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
using MLEM.Cameras;
|
||||||
using MLEM.Extensions;
|
using MLEM.Extensions;
|
||||||
using MLEM.Misc;
|
using MLEM.Misc;
|
||||||
using MonoGame.Extended.Tiled;
|
using MonoGame.Extended.Tiled;
|
||||||
using RectangleF = MonoGame.Extended.RectangleF;
|
using RectangleF = MonoGame.Extended.RectangleF;
|
||||||
|
|
||||||
namespace MLEM.Extended.Tiled {
|
namespace MLEM.Extended.Tiled {
|
||||||
|
/// <summary>
|
||||||
|
/// A tiled map renderer that renders each tile individually, while optionally supplying a depth for each tile.
|
||||||
|
/// Rendering in this manner allows for entities to be behind or in front of buildings based on their y height.
|
||||||
|
/// </summary>
|
||||||
public class IndividualTiledMapRenderer {
|
public class IndividualTiledMapRenderer {
|
||||||
|
|
||||||
private TiledMap map;
|
private TiledMap map;
|
||||||
|
@ -15,11 +20,21 @@ namespace MLEM.Extended.Tiled {
|
||||||
private GetDepth depthFunction;
|
private GetDepth depthFunction;
|
||||||
private List<TiledMapTilesetAnimatedTile> animatedTiles;
|
private List<TiledMapTilesetAnimatedTile> animatedTiles;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new individual tiled map renderer using the given map and depth function
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="map">The map to use</param>
|
||||||
|
/// <param name="depthFunction">The depth function to use</param>
|
||||||
public IndividualTiledMapRenderer(TiledMap map = null, GetDepth depthFunction = null) {
|
public IndividualTiledMapRenderer(TiledMap map = null, GetDepth depthFunction = null) {
|
||||||
if (map != null)
|
if (map != null)
|
||||||
this.SetMap(map, depthFunction);
|
this.SetMap(map, depthFunction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets this individual tiled map renderer's map and depth function
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="map">The map to use</param>
|
||||||
|
/// <param name="depthFunction">The depth function to use</param>
|
||||||
public void SetMap(TiledMap map, GetDepth depthFunction = null) {
|
public void SetMap(TiledMap map, GetDepth depthFunction = null) {
|
||||||
this.map = map;
|
this.map = map;
|
||||||
this.depthFunction = depthFunction ?? ((tile, layer, layerIndex, position) => 0);
|
this.depthFunction = depthFunction ?? ((tile, layer, layerIndex, position) => 0);
|
||||||
|
@ -43,6 +58,12 @@ namespace MLEM.Extended.Tiled {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the rendering information for the tile in the given layer, x and y.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="layerIndex">The index of the layer in <see cref="TiledMap.TileLayers"/></param>
|
||||||
|
/// <param name="x">The x coordinate of the tile</param>
|
||||||
|
/// <param name="y">The y coordinate of the tile</param>
|
||||||
public void UpdateDrawInfo(int layerIndex, int x, int y) {
|
public void UpdateDrawInfo(int layerIndex, int x, int y) {
|
||||||
var layer = this.map.TileLayers[layerIndex];
|
var layer = this.map.TileLayers[layerIndex];
|
||||||
var tile = layer.GetTile(x, y);
|
var tile = layer.GetTile(x, y);
|
||||||
|
@ -57,6 +78,13 @@ namespace MLEM.Extended.Tiled {
|
||||||
this.drawInfos[layerIndex, x, y] = new TileDrawInfo(this, tile, tileset, tilesetTile, pos, depth);
|
this.drawInfos[layerIndex, x, y] = new TileDrawInfo(this, tile, tileset, tilesetTile, pos, depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Draws this individual tiled map renderer.
|
||||||
|
/// Optionally, a frustum can be supplied that determines which positions, in pixel space, are visible at this time. <see cref="Camera"/> provides <see cref="Camera.GetVisibleRectangle"/> for this purpose.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="batch">The sprite batch to use</param>
|
||||||
|
/// <param name="frustum">The area that is visible, in pixel space.</param>
|
||||||
|
/// <param name="drawFunction">The draw function to use, or null for default</param>
|
||||||
public void Draw(SpriteBatch batch, RectangleF? frustum = null, DrawDelegate drawFunction = null) {
|
public void Draw(SpriteBatch batch, RectangleF? frustum = null, DrawDelegate drawFunction = null) {
|
||||||
for (var i = 0; i < this.map.TileLayers.Count; i++) {
|
for (var i = 0; i < this.map.TileLayers.Count; i++) {
|
||||||
if (this.map.TileLayers[i].IsVisible)
|
if (this.map.TileLayers[i].IsVisible)
|
||||||
|
@ -64,6 +92,14 @@ namespace MLEM.Extended.Tiled {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Draws the given layer of this individual tiled map renderer.
|
||||||
|
/// Optionally, a frustum can be supplied that determines which positions, in pixel space, are visible at this time. <see cref="Camera"/> provides <see cref="Camera.GetVisibleRectangle"/> for this purpose.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="batch">The sprite batch to use</param>
|
||||||
|
/// <param name="layerIndex">The index of the layer in <see cref="TiledMap.TileLayers"/></param>
|
||||||
|
/// <param name="frustum">The area that is visible, in pixel space.</param>
|
||||||
|
/// <param name="drawFunction">The draw function to use, or null for default</param>
|
||||||
public void DrawLayer(SpriteBatch batch, int layerIndex, RectangleF? frustum = null, DrawDelegate drawFunction = null) {
|
public void DrawLayer(SpriteBatch batch, int layerIndex, RectangleF? frustum = null, DrawDelegate drawFunction = null) {
|
||||||
var frust = frustum ?? new RectangleF(0, 0, float.MaxValue, float.MaxValue);
|
var frust = frustum ?? new RectangleF(0, 0, float.MaxValue, float.MaxValue);
|
||||||
var minX = Math.Max(0, frust.Left / this.map.TileWidth).Floor();
|
var minX = Math.Max(0, frust.Left / this.map.TileWidth).Floor();
|
||||||
|
@ -79,25 +115,65 @@ namespace MLEM.Extended.Tiled {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Update all of the animated tiles in this individual tiled map renderer
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="time">The game's time</param>
|
||||||
public void UpdateAnimations(GameTime time) {
|
public void UpdateAnimations(GameTime time) {
|
||||||
foreach (var animation in this.animatedTiles)
|
foreach (var animation in this.animatedTiles)
|
||||||
animation.Update(time);
|
animation.Update(time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A delegate method used for <see cref="IndividualTiledMapRenderer.depthFunction"/>.
|
||||||
|
/// The idea is to return a depth (between 0 and 1) for the given tile that determines where in the sprite batch it should be rendererd.
|
||||||
|
/// Note that, for this depth function to take effect, the sprite batch needs to begin with <see cref="SpriteSortMode.FrontToBack"/> or <see cref="SpriteSortMode.BackToFront"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tile">The tile whose depth to get</param>
|
||||||
|
/// <param name="layer">The layer the tile is on</param>
|
||||||
|
/// <param name="layerIndex">The index of the layer in <see cref="TiledMap.TileLayers"/></param>
|
||||||
|
/// <param name="position">The tile position of this tile</param>
|
||||||
public delegate float GetDepth(TiledMapTile tile, TiledMapTileLayer layer, int layerIndex, Point position);
|
public delegate float GetDepth(TiledMapTile tile, TiledMapTileLayer layer, int layerIndex, Point position);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A delegate method used for drawing an <see cref="IndividualTiledMapRenderer"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="batch">The sprite batch to use for drawing</param>
|
||||||
|
/// <param name="info">The <see cref="TileDrawInfo"/> to draw</param>
|
||||||
public delegate void DrawDelegate(SpriteBatch batch, TileDrawInfo info);
|
public delegate void DrawDelegate(SpriteBatch batch, TileDrawInfo info);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A tile draw info contains information about a tile at a given map location.
|
||||||
|
/// It caches a lot of data that is required for drawing a tile efficiently.
|
||||||
|
/// </summary>
|
||||||
public class TileDrawInfo : GenericDataHolder {
|
public class TileDrawInfo : GenericDataHolder {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The renderer used by this info
|
||||||
|
/// </summary>
|
||||||
public readonly IndividualTiledMapRenderer Renderer;
|
public readonly IndividualTiledMapRenderer Renderer;
|
||||||
|
/// <summary>
|
||||||
|
/// The tiled map tile to draw
|
||||||
|
/// </summary>
|
||||||
public readonly TiledMapTile Tile;
|
public readonly TiledMapTile Tile;
|
||||||
|
/// <summary>
|
||||||
|
/// The tileset that <see cref="Tile"/> is on
|
||||||
|
/// </summary>
|
||||||
public readonly TiledMapTileset Tileset;
|
public readonly TiledMapTileset Tileset;
|
||||||
|
/// <summary>
|
||||||
|
/// The tileset tile that corresponds to <see cref="Tile"/>
|
||||||
|
/// </summary>
|
||||||
public readonly TiledMapTilesetTile TilesetTile;
|
public readonly TiledMapTilesetTile TilesetTile;
|
||||||
|
/// <summary>
|
||||||
|
/// The position, in tile space, of <see cref="Tile"/>
|
||||||
|
/// </summary>
|
||||||
public readonly Point Position;
|
public readonly Point Position;
|
||||||
|
/// <summary>
|
||||||
|
/// The depth calculated by the depth function
|
||||||
|
/// </summary>
|
||||||
public readonly float Depth;
|
public readonly float Depth;
|
||||||
|
|
||||||
public TileDrawInfo(IndividualTiledMapRenderer renderer, TiledMapTile tile, TiledMapTileset tileset, TiledMapTilesetTile tilesetTile, Point position, float depth) {
|
internal TileDrawInfo(IndividualTiledMapRenderer renderer, TiledMapTile tile, TiledMapTileset tileset, TiledMapTilesetTile tilesetTile, Point position, float depth) {
|
||||||
this.Renderer = renderer;
|
this.Renderer = renderer;
|
||||||
this.Tile = tile;
|
this.Tile = tile;
|
||||||
this.Tileset = tileset;
|
this.Tileset = tileset;
|
||||||
|
@ -106,6 +182,11 @@ namespace MLEM.Extended.Tiled {
|
||||||
this.Depth = depth;
|
this.Depth = depth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Draws this tile draw info with the default settings.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="batch">The sprite batch to use for drawing</param>
|
||||||
|
/// <param name="drawFunction">The draw function used to draw, or null if there is no override</param>
|
||||||
public void Draw(SpriteBatch batch, DrawDelegate drawFunction) {
|
public void Draw(SpriteBatch batch, DrawDelegate drawFunction) {
|
||||||
if (drawFunction == null) {
|
if (drawFunction == null) {
|
||||||
var region = this.Tileset.GetTextureRegion(this.TilesetTile);
|
var region = this.Tileset.GetTextureRegion(this.TilesetTile);
|
||||||
|
|
|
@ -1,38 +1,62 @@
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
|
using MonoGame.Extended.Tiled;
|
||||||
|
|
||||||
namespace MLEM.Extended.Tiled {
|
namespace MLEM.Extended.Tiled {
|
||||||
|
/// <summary>
|
||||||
|
/// A struct that represents a position on a <see cref="TiledMap"/> with multiple layers.
|
||||||
|
/// </summary>
|
||||||
[DataContract]
|
[DataContract]
|
||||||
public struct LayerPosition {
|
public struct LayerPosition {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the layer that this position is on
|
||||||
|
/// </summary>
|
||||||
[DataMember]
|
[DataMember]
|
||||||
public string Layer;
|
public string Layer;
|
||||||
|
/// <summary>
|
||||||
|
/// The x coordinate of this position
|
||||||
|
/// </summary>
|
||||||
[DataMember]
|
[DataMember]
|
||||||
public int X;
|
public int X;
|
||||||
|
/// <summary>
|
||||||
|
/// The y coordinate of this position
|
||||||
|
/// </summary>
|
||||||
[DataMember]
|
[DataMember]
|
||||||
public int Y;
|
public int Y;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new layer position with the given settings
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="layerName">The layer name</param>
|
||||||
|
/// <param name="x">The x coordinate</param>
|
||||||
|
/// <param name="y">The y coordinate</param>
|
||||||
public LayerPosition(string layerName, int x, int y) {
|
public LayerPosition(string layerName, int x, int y) {
|
||||||
this.Layer = layerName;
|
this.Layer = layerName;
|
||||||
this.X = x;
|
this.X = x;
|
||||||
this.Y = y;
|
this.Y = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Equals(LayerPosition)"/>
|
||||||
public static bool operator ==(LayerPosition left, LayerPosition right) {
|
public static bool operator ==(LayerPosition left, LayerPosition right) {
|
||||||
return left.Equals(right);
|
return left.Equals(right);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Equals(LayerPosition)"/>
|
||||||
public static bool operator !=(LayerPosition left, LayerPosition right) {
|
public static bool operator !=(LayerPosition left, LayerPosition right) {
|
||||||
return !left.Equals(right);
|
return !left.Equals(right);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Equals(object)"/>
|
||||||
public bool Equals(LayerPosition other) {
|
public bool Equals(LayerPosition other) {
|
||||||
return this.Layer == other.Layer && this.X == other.X && this.Y == other.Y;
|
return this.Layer == other.Layer && this.X == other.X && this.Y == other.Y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public override bool Equals(object obj) {
|
public override bool Equals(object obj) {
|
||||||
return obj is LayerPosition other && this.Equals(other);
|
return obj is LayerPosition other && this.Equals(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public override int GetHashCode() {
|
public override int GetHashCode() {
|
||||||
var hashCode = this.Layer.GetHashCode();
|
var hashCode = this.Layer.GetHashCode();
|
||||||
hashCode = (hashCode * 397) ^ this.X;
|
hashCode = (hashCode * 397) ^ this.X;
|
||||||
|
@ -40,6 +64,7 @@ namespace MLEM.Extended.Tiled {
|
||||||
return hashCode;
|
return hashCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public override string ToString() {
|
public override string ToString() {
|
||||||
return $"{nameof(this.Layer)}: {this.Layer}, {nameof(this.X)}: {this.X}, {nameof(this.Y)}: {this.Y}";
|
return $"{nameof(this.Layer)}: {this.Layer}, {nameof(this.X)}: {this.X}, {nameof(this.Y)}: {this.Y}";
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,46 +9,109 @@ using MonoGame.Extended.Tiled;
|
||||||
using ColorExtensions = MLEM.Extensions.ColorExtensions;
|
using ColorExtensions = MLEM.Extensions.ColorExtensions;
|
||||||
|
|
||||||
namespace MLEM.Extended.Tiled {
|
namespace MLEM.Extended.Tiled {
|
||||||
|
/// <summary>
|
||||||
|
/// A set of extensions for dealing with MonoGame.Extended tiled maps
|
||||||
|
/// </summary>
|
||||||
public static class TiledExtensions {
|
public static class TiledExtensions {
|
||||||
|
|
||||||
private static readonly Dictionary<int, TiledMapTilesetTile> StubTilesetTiles = new Dictionary<int, TiledMapTilesetTile>();
|
private static readonly Dictionary<int, TiledMapTilesetTile> StubTilesetTiles = new Dictionary<int, TiledMapTilesetTile>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the property with the given key, or null if there is none.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="properties">The set of properties</param>
|
||||||
|
/// <param name="key">The key by which to get a property</param>
|
||||||
|
/// <returns>The property, or null if there is none</returns>
|
||||||
public static string Get(this TiledMapProperties properties, string key) {
|
public static string Get(this TiledMapProperties properties, string key) {
|
||||||
properties.TryGetValue(key, out var val);
|
properties.TryGetValue(key, out var val);
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a boolean property with the given key, or null if there is none.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="properties">The set of properties</param>
|
||||||
|
/// <param name="key">The key by which to get a property</param>
|
||||||
|
/// <returns>The boolean property, or false if there is none</returns>
|
||||||
public static bool GetBool(this TiledMapProperties properties, string key) {
|
public static bool GetBool(this TiledMapProperties properties, string key) {
|
||||||
bool.TryParse(properties.Get(key), out var val);
|
bool.TryParse(properties.Get(key), out var val);
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a Color property with the given key, or null if there is none.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="properties">The set of properties</param>
|
||||||
|
/// <param name="key">The key by which to get a property</param>
|
||||||
|
/// <returns>The color property</returns>
|
||||||
public static Color GetColor(this TiledMapProperties properties, string key) {
|
public static Color GetColor(this TiledMapProperties properties, string key) {
|
||||||
return ColorExtensions.FromHex(properties.Get(key));
|
return ColorExtensions.FromHex(properties.Get(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a float property with the given key, or null if there is none.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="properties">The set of properties</param>
|
||||||
|
/// <param name="key">The key by which to get a property</param>
|
||||||
|
/// <returns>The float property, or 0 if there is none</returns>
|
||||||
public static float GetFloat(this TiledMapProperties properties, string key) {
|
public static float GetFloat(this TiledMapProperties properties, string key) {
|
||||||
float.TryParse(properties.Get(key), NumberStyles.Number, NumberFormatInfo.InvariantInfo, out var val);
|
float.TryParse(properties.Get(key), NumberStyles.Number, NumberFormatInfo.InvariantInfo, out var val);
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets an int property with the given key, or null if there is none.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="properties">The set of properties</param>
|
||||||
|
/// <param name="key">The key by which to get a property</param>
|
||||||
|
/// <returns>The int property, or 0 if there is none</returns>
|
||||||
public static int GetInt(this TiledMapProperties properties, string key) {
|
public static int GetInt(this TiledMapProperties properties, string key) {
|
||||||
int.TryParse(properties.Get(key), NumberStyles.Number, NumberFormatInfo.InvariantInfo, out var val);
|
int.TryParse(properties.Get(key), NumberStyles.Number, NumberFormatInfo.InvariantInfo, out var val);
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the tileset for the given map tile on the given map.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tile">The tile</param>
|
||||||
|
/// <param name="map">The map the tile is on</param>
|
||||||
|
/// <returns>The tileset that the tile came from</returns>
|
||||||
public static TiledMapTileset GetTileset(this TiledMapTile tile, TiledMap map) {
|
public static TiledMapTileset GetTileset(this TiledMapTile tile, TiledMap map) {
|
||||||
return map.GetTilesetByTileGlobalIdentifier(tile.GlobalIdentifier);
|
return map.GetTilesetByTileGlobalIdentifier(tile.GlobalIdentifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the local tile identifier for the given tiled map tile.
|
||||||
|
/// The local tile identifier is the identifier within the tile's tileset.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tile">The tile whose identifier to get</param>
|
||||||
|
/// <param name="tileset">The tileset the tile is from</param>
|
||||||
|
/// <param name="map">The map the tile is on</param>
|
||||||
|
/// <returns>The local identifier</returns>
|
||||||
public static int GetLocalIdentifier(this TiledMapTile tile, TiledMapTileset tileset, TiledMap map) {
|
public static int GetLocalIdentifier(this TiledMapTile tile, TiledMapTileset tileset, TiledMap map) {
|
||||||
return tile.GlobalIdentifier - map.GetTilesetFirstGlobalIdentifier(tileset);
|
return tile.GlobalIdentifier - map.GetTilesetFirstGlobalIdentifier(tileset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the global tile identifier for the given tiled map tileset tile.
|
||||||
|
/// The global tile identifier is the identifier within all of the tile sets that the map has.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tile">The tile whose global identifier to get</param>
|
||||||
|
/// <param name="tileset">The tileset the tile is from</param>
|
||||||
|
/// <param name="map">The map the tile is on</param>
|
||||||
|
/// <returns>The global identifier</returns>
|
||||||
public static int GetGlobalIdentifier(this TiledMapTilesetTile tile, TiledMapTileset tileset, TiledMap map) {
|
public static int GetGlobalIdentifier(this TiledMapTilesetTile tile, TiledMapTileset tileset, TiledMap map) {
|
||||||
return map.GetTilesetFirstGlobalIdentifier(tileset) + tile.LocalTileIdentifier;
|
return map.GetTilesetFirstGlobalIdentifier(tileset) + tile.LocalTileIdentifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the tileset tile on the given tileset for the given tile.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tileset">The tileset</param>
|
||||||
|
/// <param name="tile">The tile</param>
|
||||||
|
/// <param name="map">The map the tile is on</param>
|
||||||
|
/// <param name="createStub">If a tileset tile has no special properties, there is no pre-made object for it. If this boolean is true, a stub object with no extra data will be created instead of returning null.</param>
|
||||||
|
/// <returns>null if the tile is blank or the tileset tile if there is one or createStub is true</returns>
|
||||||
public static TiledMapTilesetTile GetTilesetTile(this TiledMapTileset tileset, TiledMapTile tile, TiledMap map, bool createStub = true) {
|
public static TiledMapTilesetTile GetTilesetTile(this TiledMapTileset tileset, TiledMapTile tile, TiledMap map, bool createStub = true) {
|
||||||
if (tile.IsBlank)
|
if (tile.IsBlank)
|
||||||
return null;
|
return null;
|
||||||
|
@ -64,6 +127,14 @@ namespace MLEM.Extended.Tiled {
|
||||||
return tilesetTile;
|
return tilesetTile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the tileset tile on the given tileset for the given tile.
|
||||||
|
/// If the tileset is already known, you should use <see cref="GetTilesetTile(MonoGame.Extended.Tiled.TiledMapTileset,MonoGame.Extended.Tiled.TiledMapTile,MonoGame.Extended.Tiled.TiledMap,bool)"/> instead for performance.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tile">The tile</param>
|
||||||
|
/// <param name="map">The map the tile is on</param>
|
||||||
|
/// <param name="createStub">If a tileset tile has no special properties, there is no pre-made object for it. If this boolean is true, a stub object with no extra data will be created instead of returning null.</param>
|
||||||
|
/// <returns>null if the tile is blank or the tileset tile if there is one or createStub is true</returns>
|
||||||
public static TiledMapTilesetTile GetTilesetTile(this TiledMapTile tile, TiledMap map, bool createStub = true) {
|
public static TiledMapTilesetTile GetTilesetTile(this TiledMapTile tile, TiledMap map, bool createStub = true) {
|
||||||
if (tile.IsBlank)
|
if (tile.IsBlank)
|
||||||
return null;
|
return null;
|
||||||
|
@ -71,22 +142,51 @@ namespace MLEM.Extended.Tiled {
|
||||||
return tileset.GetTilesetTile(tile, map, createStub);
|
return tileset.GetTilesetTile(tile, map, createStub);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the layer index of the layer with the given name in the <see cref="TiledMap.Layers"/> array.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="map">The map</param>
|
||||||
|
/// <param name="layerName">The name of the layer</param>
|
||||||
|
/// <returns>The resulting index</returns>
|
||||||
public static int GetTileLayerIndex(this TiledMap map, string layerName) {
|
public static int GetTileLayerIndex(this TiledMap map, string layerName) {
|
||||||
var layer = map.GetLayer<TiledMapTileLayer>(layerName);
|
var layer = map.GetLayer<TiledMapTileLayer>(layerName);
|
||||||
return map.TileLayers.IndexOf(layer);
|
return map.TileLayers.IndexOf(layer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the tiled map tile at the given location on the layer with the given name.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="map">The map</param>
|
||||||
|
/// <param name="layerName">The name of the layer the tile is on</param>
|
||||||
|
/// <param name="x">The x coordinate of the tile</param>
|
||||||
|
/// <param name="y">The y coordinate of the tile</param>
|
||||||
|
/// <returns>The tile at the given location, or default if the layer does not exist</returns>
|
||||||
public static TiledMapTile GetTile(this TiledMap map, string layerName, int x, int y) {
|
public static TiledMapTile GetTile(this TiledMap map, string layerName, int x, int y) {
|
||||||
var layer = map.GetLayer<TiledMapTileLayer>(layerName);
|
var layer = map.GetLayer<TiledMapTileLayer>(layerName);
|
||||||
return layer != null ? layer.GetTile(x, y) : default;
|
return layer != null ? layer.GetTile(x, y) : default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the tiled map tile at the given location to the given global tile identifier.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="map">The map</param>
|
||||||
|
/// <param name="layerName">The name of the layer</param>
|
||||||
|
/// <param name="x">The x coordinate</param>
|
||||||
|
/// <param name="y">The y coordinate</param>
|
||||||
|
/// <param name="globalTile">The tile's global identifier to set</param>
|
||||||
public static void SetTile(this TiledMap map, string layerName, int x, int y, int globalTile) {
|
public static void SetTile(this TiledMap map, string layerName, int x, int y, int globalTile) {
|
||||||
var layer = map.GetLayer<TiledMapTileLayer>(layerName);
|
var layer = map.GetLayer<TiledMapTileLayer>(layerName);
|
||||||
if (layer != null)
|
if (layer != null)
|
||||||
layer.SetTile((ushort) x, (ushort) y, (uint) globalTile);
|
layer.SetTile((ushort) x, (ushort) y, (uint) globalTile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// For an x and y coordinate, returns an enumerable of all of the tiles on each of the map's <see cref="TiledMap.TileLayers"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="map">The map</param>
|
||||||
|
/// <param name="x">The x coordinate</param>
|
||||||
|
/// <param name="y">The y coordinate</param>
|
||||||
|
/// <returns>All of the tiles on the map at the given location</returns>
|
||||||
public static IEnumerable<TiledMapTile> GetTiles(this TiledMap map, int x, int y) {
|
public static IEnumerable<TiledMapTile> GetTiles(this TiledMap map, int x, int y) {
|
||||||
foreach (var layer in map.TileLayers) {
|
foreach (var layer in map.TileLayers) {
|
||||||
var tile = layer.GetTile(x, y);
|
var tile = layer.GetTile(x, y);
|
||||||
|
@ -95,24 +195,59 @@ namespace MLEM.Extended.Tiled {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the tiled map at the given location on the given layer
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="layer">The layer to get the tile from</param>
|
||||||
|
/// <param name="x">The tile's x coordinate</param>
|
||||||
|
/// <param name="y">The tile's y coordinate</param>
|
||||||
|
/// <returns>The tiled map tile at the location, or default if the location is out of bounds</returns>
|
||||||
public static TiledMapTile GetTile(this TiledMapTileLayer layer, int x, int y) {
|
public static TiledMapTile GetTile(this TiledMapTileLayer layer, int x, int y) {
|
||||||
return !layer.IsInBounds(x, y) ? default : layer.GetTile((ushort) x, (ushort) y);
|
return !layer.IsInBounds(x, y) ? default : layer.GetTile((ushort) x, (ushort) y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the area that a tiled map object covers.
|
||||||
|
/// The area returned is in percent, meaning that an area that covers a full tile has a size of 1,1.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="obj">The object whose area to get</param>
|
||||||
|
/// <param name="map">The map</param>
|
||||||
|
/// <param name="position">The position to add to the object's position</param>
|
||||||
|
/// <returns>The area that the tile covers</returns>
|
||||||
public static RectangleF GetArea(this TiledMapObject obj, TiledMap map, Vector2? position = null) {
|
public static RectangleF GetArea(this TiledMapObject obj, TiledMap map, Vector2? position = null) {
|
||||||
var tileSize = map.GetTileSize();
|
var tileSize = map.GetTileSize();
|
||||||
var pos = position ?? Vector2.Zero;
|
var pos = position ?? Vector2.Zero;
|
||||||
return new RectangleF(obj.Position / tileSize + pos, obj.Size / tileSize);
|
return new RectangleF(obj.Position / tileSize + pos, obj.Size / tileSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the width and height of a tile on the given map, as a vector.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="map">The map</param>
|
||||||
|
/// <returns>The width and height of a tile</returns>
|
||||||
public static Vector2 GetTileSize(this TiledMap map) {
|
public static Vector2 GetTileSize(this TiledMap map) {
|
||||||
return new Vector2(map.TileWidth, map.TileHeight);
|
return new Vector2(map.TileWidth, map.TileHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns whether the given position is in the bounds of the layer (that is, if each coordinate is >= 0 and if they are both smaller than the layer's width and height).
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="layer">The layer</param>
|
||||||
|
/// <param name="x">The x coordinate</param>
|
||||||
|
/// <param name="y">The y coordinate</param>
|
||||||
|
/// <returns>Whether the position is in bounds of the layer</returns>
|
||||||
public static bool IsInBounds(this TiledMapTileLayer layer, int x, int y) {
|
public static bool IsInBounds(this TiledMapTileLayer layer, int x, int y) {
|
||||||
return x >= 0 && y >= 0 && x < layer.Width && y < layer.Height;
|
return x >= 0 && y >= 0 && x < layer.Width && y < layer.Height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns all of the objects by the given name, or by the given type, in an object layer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="layer">The layer whose objects to search</param>
|
||||||
|
/// <param name="id">The name or type name of the objects to find</param>
|
||||||
|
/// <param name="searchName">Whether to search object names</param>
|
||||||
|
/// <param name="searchType">Whether to search object types</param>
|
||||||
|
/// <returns>An enumerable of tiled map objects that match the search</returns>
|
||||||
public static IEnumerable<TiledMapObject> GetObjects(this TiledMapObjectLayer layer, string id, bool searchName = true, bool searchType = false) {
|
public static IEnumerable<TiledMapObject> GetObjects(this TiledMapObjectLayer layer, string id, bool searchName = true, bool searchType = false) {
|
||||||
foreach (var obj in layer.Objects) {
|
foreach (var obj in layer.Objects) {
|
||||||
if (searchName && obj.Name == id || searchType && obj.Type == id)
|
if (searchName && obj.Name == id || searchType && obj.Type == id)
|
||||||
|
@ -120,13 +255,27 @@ namespace MLEM.Extended.Tiled {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IEnumerable<TiledMapObject> GetObjects(this TiledMap map, string name, bool searchName = true, bool searchType = false) {
|
/// <summary>
|
||||||
|
/// Returns all of the objects by the given name, or by the given type, on the given map.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="map">The layer whose objects to search</param>
|
||||||
|
/// <param name="id">The name or type name of the objects to find</param>
|
||||||
|
/// <param name="searchName">Whether to search object names</param>
|
||||||
|
/// <param name="searchType">Whether to search object types</param>
|
||||||
|
/// <returns>An enumerable of tiled map objects that match the search</returns>
|
||||||
|
public static IEnumerable<TiledMapObject> GetObjects(this TiledMap map, string id, bool searchName = true, bool searchType = false) {
|
||||||
foreach (var layer in map.ObjectLayers) {
|
foreach (var layer in map.ObjectLayers) {
|
||||||
foreach (var obj in layer.GetObjects(name, searchName, searchType))
|
foreach (var obj in layer.GetObjects(id, searchName, searchType))
|
||||||
yield return obj;
|
yield return obj;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the texture region, as a rectangle, that the given tile uses for rendering.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tileset">The tileset the tile is on</param>
|
||||||
|
/// <param name="tile">The tile</param>
|
||||||
|
/// <returns>The tile's texture region, in pixels.</returns>
|
||||||
public static Rectangle GetTextureRegion(this TiledMapTileset tileset, TiledMapTilesetTile tile) {
|
public static Rectangle GetTextureRegion(this TiledMapTileset tileset, TiledMapTilesetTile tile) {
|
||||||
var id = tile.LocalTileIdentifier;
|
var id = tile.LocalTileIdentifier;
|
||||||
if (tile is TiledMapTilesetAnimatedTile animated)
|
if (tile is TiledMapTilesetAnimatedTile animated)
|
||||||
|
@ -134,6 +283,11 @@ namespace MLEM.Extended.Tiled {
|
||||||
return tileset.GetTileRegion(id);
|
return tileset.GetTileRegion(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a tile's flip settings into <see cref="SpriteEffects"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tile">The tile whose flip settings to convert</param>
|
||||||
|
/// <returns>The tile's flip settings as sprite effects</returns>
|
||||||
public static SpriteEffects GetSpriteEffects(this TiledMapTile tile) {
|
public static SpriteEffects GetSpriteEffects(this TiledMapTile tile) {
|
||||||
var flipping = SpriteEffects.None;
|
var flipping = SpriteEffects.None;
|
||||||
if (tile.IsFlippedHorizontally)
|
if (tile.IsFlippedHorizontally)
|
||||||
|
|
|
@ -9,17 +9,30 @@ using MonoGame.Extended.Tiled;
|
||||||
using RectangleF = MonoGame.Extended.RectangleF;
|
using RectangleF = MonoGame.Extended.RectangleF;
|
||||||
|
|
||||||
namespace MLEM.Extended.Tiled {
|
namespace MLEM.Extended.Tiled {
|
||||||
|
/// <summary>
|
||||||
|
/// A collision handler for a MonoGame.Extended tiled tile map.
|
||||||
|
/// The idea behind this collision handler is that, on the map's tileset, each tile is assigned a certain rectangular area. That area is converted into a collision map that is dealt with in tile units, where each tile's covered area is 1x1 units big.
|
||||||
|
/// </summary>
|
||||||
public class TiledMapCollisions {
|
public class TiledMapCollisions {
|
||||||
|
|
||||||
private TiledMap map;
|
private TiledMap map;
|
||||||
private TileCollisionInfo[,,] collisionInfos;
|
private TileCollisionInfo[,,] collisionInfos;
|
||||||
private CollectCollisions collisionFunction;
|
private CollectCollisions collisionFunction;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new tiled map collision handler for the given map
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="map">The map</param>
|
||||||
public TiledMapCollisions(TiledMap map = null) {
|
public TiledMapCollisions(TiledMap map = null) {
|
||||||
if (map != null)
|
if (map != null)
|
||||||
this.SetMap(map);
|
this.SetMap(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets this collision handler's handled map
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="map">The map</param>
|
||||||
|
/// <param name="collisionFunction">The function used to collect the collision info of a tile, or null for the default handling</param>
|
||||||
public void SetMap(TiledMap map, CollectCollisions collisionFunction = null) {
|
public void SetMap(TiledMap map, CollectCollisions collisionFunction = null) {
|
||||||
this.map = map;
|
this.map = map;
|
||||||
this.collisionFunction = collisionFunction ?? ((collisions, tile) => {
|
this.collisionFunction = collisionFunction ?? ((collisions, tile) => {
|
||||||
|
@ -44,6 +57,12 @@ namespace MLEM.Extended.Tiled {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the collision info for the tile at the given position.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="layerIndex">The index of the tile's layer in <see cref="TiledMap.TileLayers"/></param>
|
||||||
|
/// <param name="x">The tile's x coordinate</param>
|
||||||
|
/// <param name="y">The tile's y coordinate</param>
|
||||||
public void UpdateCollisionInfo(int layerIndex, int x, int y) {
|
public void UpdateCollisionInfo(int layerIndex, int x, int y) {
|
||||||
var layer = this.map.TileLayers[layerIndex];
|
var layer = this.map.TileLayers[layerIndex];
|
||||||
var tile = layer.GetTile(x, y);
|
var tile = layer.GetTile(x, y);
|
||||||
|
@ -55,6 +74,13 @@ namespace MLEM.Extended.Tiled {
|
||||||
this.collisionInfos[layerIndex, x, y] = new TileCollisionInfo(this.map, new Vector2(x, y), tile, layer, tilesetTile, this.collisionFunction);
|
this.collisionInfos[layerIndex, x, y] = new TileCollisionInfo(this.map, new Vector2(x, y), tile, layer, tilesetTile, this.collisionFunction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns an enumerable of tile collision infos that intersect the given area.
|
||||||
|
/// Optionally, a predicate can be supplied that narrows the search.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="area">The area to check for collisions in</param>
|
||||||
|
/// <param name="included">A function that determines if a certain info should be included or not</param>
|
||||||
|
/// <returns>An enumerable of collision infos for that area</returns>
|
||||||
public IEnumerable<TileCollisionInfo> GetCollidingTiles(RectangleF area, Func<TileCollisionInfo, bool> included = null) {
|
public IEnumerable<TileCollisionInfo> GetCollidingTiles(RectangleF area, Func<TileCollisionInfo, bool> included = null) {
|
||||||
var inclusionFunc = included ?? (tile => tile.Collisions.Any(c => c.Intersects(area)));
|
var inclusionFunc = included ?? (tile => tile.Collisions.Any(c => c.Intersects(area)));
|
||||||
var minX = Math.Max(0, area.Left.Floor());
|
var minX = Math.Max(0, area.Left.Floor());
|
||||||
|
@ -74,22 +100,55 @@ namespace MLEM.Extended.Tiled {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns whether there are any colliding tiles in the given area.
|
||||||
|
/// Optionally, a predicate can be supplied that narrows the search.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="area">The area to check for collisions in</param>
|
||||||
|
/// <param name="included">A function that determines if a certain info should be included or not</param>
|
||||||
|
/// <returns>True if there are any colliders in the area, false otherwise</returns>
|
||||||
public bool IsColliding(RectangleF area, Func<TileCollisionInfo, bool> included = null) {
|
public bool IsColliding(RectangleF area, Func<TileCollisionInfo, bool> included = null) {
|
||||||
return this.GetCollidingTiles(area, included).Any();
|
return this.GetCollidingTiles(area, included).Any();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A delegate method used to override the default collision checking behavior.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="collisions">The list of collisions to add to</param>
|
||||||
|
/// <param name="tile">The tile's collision information</param>
|
||||||
public delegate void CollectCollisions(List<RectangleF> collisions, TileCollisionInfo tile);
|
public delegate void CollectCollisions(List<RectangleF> collisions, TileCollisionInfo tile);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A tile collision info stores information about a tile at a given location on a given layer, including its objects and their bounds.
|
||||||
|
/// </summary>
|
||||||
public class TileCollisionInfo : GenericDataHolder {
|
public class TileCollisionInfo : GenericDataHolder {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The map the tile is on
|
||||||
|
/// </summary>
|
||||||
public readonly TiledMap Map;
|
public readonly TiledMap Map;
|
||||||
|
/// <summary>
|
||||||
|
/// The position of the tile, in tile units
|
||||||
|
/// </summary>
|
||||||
public readonly Vector2 Position;
|
public readonly Vector2 Position;
|
||||||
|
/// <summary>
|
||||||
|
/// The tiled map tile
|
||||||
|
/// </summary>
|
||||||
public readonly TiledMapTile Tile;
|
public readonly TiledMapTile Tile;
|
||||||
|
/// <summary>
|
||||||
|
/// The layer that this tile is on
|
||||||
|
/// </summary>
|
||||||
public readonly TiledMapTileLayer Layer;
|
public readonly TiledMapTileLayer Layer;
|
||||||
|
/// <summary>
|
||||||
|
/// The tileset tile for this tile
|
||||||
|
/// </summary>
|
||||||
public readonly TiledMapTilesetTile TilesetTile;
|
public readonly TiledMapTilesetTile TilesetTile;
|
||||||
|
/// <summary>
|
||||||
|
/// The list of colliders for this tile
|
||||||
|
/// </summary>
|
||||||
public readonly List<RectangleF> Collisions;
|
public readonly List<RectangleF> Collisions;
|
||||||
|
|
||||||
public TileCollisionInfo(TiledMap map, Vector2 position, TiledMapTile tile, TiledMapTileLayer layer, TiledMapTilesetTile tilesetTile, CollectCollisions collisionFunction) {
|
internal TileCollisionInfo(TiledMap map, Vector2 position, TiledMapTile tile, TiledMapTileLayer layer, TiledMapTilesetTile tilesetTile, CollectCollisions collisionFunction) {
|
||||||
this.TilesetTile = tilesetTile;
|
this.TilesetTile = tilesetTile;
|
||||||
this.Layer = layer;
|
this.Layer = layer;
|
||||||
this.Tile = tile;
|
this.Tile = tile;
|
||||||
|
|
|
@ -1,9 +1,18 @@
|
||||||
using Coroutine;
|
using Coroutine;
|
||||||
|
|
||||||
namespace MLEM.Startup {
|
namespace MLEM.Startup {
|
||||||
|
/// <summary>
|
||||||
|
/// This class contains a set of events for the coroutine system that are automatically fired in <see cref="MlemGame"/>.
|
||||||
|
/// </summary>
|
||||||
public static class CoroutineEvents {
|
public static class CoroutineEvents {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This event is fired in <see cref="MlemGame.Update"/>
|
||||||
|
/// </summary>
|
||||||
public static readonly Event Update = new Event();
|
public static readonly Event Update = new Event();
|
||||||
|
/// <summary>
|
||||||
|
/// This event is fired in <see cref="MlemGame.Draw"/>
|
||||||
|
/// </summary>
|
||||||
public static readonly Event Draw = new Event();
|
public static readonly Event Draw = new Event();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using Coroutine;
|
using Coroutine;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Content;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
using Microsoft.Xna.Framework.Input;
|
using Microsoft.Xna.Framework.Input;
|
||||||
using MLEM.Input;
|
using MLEM.Input;
|
||||||
|
@ -7,20 +8,54 @@ using MLEM.Ui;
|
||||||
using MLEM.Ui.Style;
|
using MLEM.Ui.Style;
|
||||||
|
|
||||||
namespace MLEM.Startup {
|
namespace MLEM.Startup {
|
||||||
|
/// <summary>
|
||||||
|
/// MlemGame is an extension of MonoGame's default <see cref="Game"/> class.
|
||||||
|
/// It features the default template setup, as well as an <see cref="InputHandler"/>, a <see cref="UiSystem"/> and some additional callback events.
|
||||||
|
/// It also runs all of the <see cref="CoroutineHandler"/> callbacks which can be used through <see cref="CoroutineEvents"/>.
|
||||||
|
/// </summary>
|
||||||
public class MlemGame : Game {
|
public class MlemGame : Game {
|
||||||
|
|
||||||
private static MlemGame instance;
|
private static MlemGame instance;
|
||||||
|
/// <summary>
|
||||||
|
/// The static game instance's input handler
|
||||||
|
/// </summary>
|
||||||
public static InputHandler Input => instance.InputHandler;
|
public static InputHandler Input => instance.InputHandler;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This game's graphics device manager, initialized in the constructor
|
||||||
|
/// </summary>
|
||||||
public readonly GraphicsDeviceManager GraphicsDeviceManager;
|
public readonly GraphicsDeviceManager GraphicsDeviceManager;
|
||||||
|
/// <summary>
|
||||||
|
/// This game's sprite batch
|
||||||
|
/// </summary>
|
||||||
public SpriteBatch SpriteBatch { get; protected set; }
|
public SpriteBatch SpriteBatch { get; protected set; }
|
||||||
|
/// <summary>
|
||||||
|
/// This game's input handler. This can easily be accessed through <see cref="Input"/>.
|
||||||
|
/// </summary>
|
||||||
public InputHandler InputHandler { get; protected set; }
|
public InputHandler InputHandler { get; protected set; }
|
||||||
|
/// <summary>
|
||||||
|
/// This game's ui system
|
||||||
|
/// </summary>
|
||||||
public UiSystem UiSystem { get; protected set; }
|
public UiSystem UiSystem { get; protected set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An event that is invoked in <see cref="LoadContent"/>
|
||||||
|
/// </summary>
|
||||||
public GenericCallback OnLoadContent;
|
public GenericCallback OnLoadContent;
|
||||||
|
/// <summary>
|
||||||
|
/// An event that is invoked in <see cref="Update"/>
|
||||||
|
/// </summary>
|
||||||
public TimeCallback OnUpdate;
|
public TimeCallback OnUpdate;
|
||||||
|
/// <summary>
|
||||||
|
/// An event that is invoked in <see cref="Draw"/>
|
||||||
|
/// </summary>
|
||||||
public TimeCallback OnDraw;
|
public TimeCallback OnDraw;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new MlemGame instance with some default settings
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="windowWidth">The default window width</param>
|
||||||
|
/// <param name="windowHeight">The default window height</param>
|
||||||
public MlemGame(int windowWidth = 1280, int windowHeight = 720) {
|
public MlemGame(int windowWidth = 1280, int windowHeight = 720) {
|
||||||
instance = this;
|
instance = this;
|
||||||
|
|
||||||
|
@ -33,6 +68,7 @@ namespace MLEM.Startup {
|
||||||
this.Content.RootDirectory = "Content";
|
this.Content.RootDirectory = "Content";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override void LoadContent() {
|
protected override void LoadContent() {
|
||||||
this.SpriteBatch = new SpriteBatch(this.GraphicsDevice);
|
this.SpriteBatch = new SpriteBatch(this.GraphicsDevice);
|
||||||
this.InputHandler = new InputHandler();
|
this.InputHandler = new InputHandler();
|
||||||
|
@ -42,6 +78,7 @@ namespace MLEM.Startup {
|
||||||
this.OnLoadContent?.Invoke(this);
|
this.OnLoadContent?.Invoke(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected sealed override void Update(GameTime gameTime) {
|
protected sealed override void Update(GameTime gameTime) {
|
||||||
this.DoUpdate(gameTime);
|
this.DoUpdate(gameTime);
|
||||||
this.OnUpdate?.Invoke(this, gameTime);
|
this.OnUpdate?.Invoke(this, gameTime);
|
||||||
|
@ -49,6 +86,7 @@ namespace MLEM.Startup {
|
||||||
CoroutineHandler.RaiseEvent(CoroutineEvents.Update);
|
CoroutineHandler.RaiseEvent(CoroutineEvents.Update);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected sealed override void Draw(GameTime gameTime) {
|
protected sealed override void Draw(GameTime gameTime) {
|
||||||
this.UiSystem.DrawEarly(gameTime, this.SpriteBatch);
|
this.UiSystem.DrawEarly(gameTime, this.SpriteBatch);
|
||||||
this.DoDraw(gameTime);
|
this.DoDraw(gameTime);
|
||||||
|
@ -57,20 +95,46 @@ namespace MLEM.Startup {
|
||||||
CoroutineHandler.RaiseEvent(CoroutineEvents.Draw);
|
CoroutineHandler.RaiseEvent(CoroutineEvents.Draw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This method is called in <see cref="Draw"/>.
|
||||||
|
/// It is the version that should be overridden by implementors to draw game content.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="gameTime">The game's time</param>
|
||||||
protected virtual void DoDraw(GameTime gameTime) {
|
protected virtual void DoDraw(GameTime gameTime) {
|
||||||
base.Draw(gameTime);
|
base.Draw(gameTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This method is called in <see cref="Update"/>.
|
||||||
|
/// It is the version that should be overridden by implementors to update game content.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="gameTime">The game's time</param>
|
||||||
protected virtual void DoUpdate(GameTime gameTime) {
|
protected virtual void DoUpdate(GameTime gameTime) {
|
||||||
base.Update(gameTime);
|
base.Update(gameTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Static helper method for <see cref="ContentManager.Load{T}"/>.
|
||||||
|
/// This just invokes the game instance's load method.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">The name of the content file to load</param>
|
||||||
|
/// <typeparam name="T">The type of content to load</typeparam>
|
||||||
|
/// <returns>The loaded content</returns>
|
||||||
public static T LoadContent<T>(string name) {
|
public static T LoadContent<T>(string name) {
|
||||||
return instance.Content.Load<T>(name);
|
return instance.Content.Load<T>(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A delegate method used by <see cref="MlemGame.OnLoadContent"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="game">The game in question</param>
|
||||||
public delegate void GenericCallback(MlemGame game);
|
public delegate void GenericCallback(MlemGame game);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A delegate method used by <see cref="MlemGame.OnUpdate"/> and <see cref="MlemGame.OnDraw"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="game">The game in question</param>
|
||||||
|
/// <param name="time">The game's current time</param>
|
||||||
public delegate void TimeCallback(MlemGame game, GameTime time);
|
public delegate void TimeCallback(MlemGame game, GameTime time);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue