using System; using System.Runtime.InteropServices; using Microsoft.Xna.Framework; namespace MonoGame.Extended.Tilemaps { /// /// Represents a custom property value that can be of various types. /// public readonly struct TilemapPropertyValue { [StructLayout(LayoutKind.Explicit)] private readonly struct ValueData { [FieldOffset(0)] public readonly int Int32; [FieldOffset(0)] public readonly float Single; [FieldOffset(0)] public readonly bool Boolean; [FieldOffset(0)] public readonly uint ColorPackedValue; public ValueData(int value) => Int32 = value; public ValueData(float value) => Single = value; public ValueData(bool value) => Boolean = value; public ValueData(uint value) => ColorPackedValue = value; } private readonly ValueData _valueData; private readonly string _stringValue; /// /// Gets the type of this property value. /// public TilemapPropertyType Type { get; } private TilemapPropertyValue(TilemapPropertyType type, ValueData valueData, string stringValue = null) { Type = type; _valueData = valueData; _stringValue = stringValue; } #region Factory Methods /// /// Creates a string property value. /// /// The string value. /// A property value containing the string. public static TilemapPropertyValue CreateString(string value) { return new TilemapPropertyValue(TilemapPropertyType.String, default, value); } /// /// Creates an integer property value. /// /// The integer value. /// A property value containing the integer. public static TilemapPropertyValue CreateInt(int value) { return new TilemapPropertyValue(TilemapPropertyType.Int, new ValueData(value)); } /// /// Creates a float property value. /// /// The float value. /// A property value containing the float. public static TilemapPropertyValue CreateFloat(float value) { return new TilemapPropertyValue(TilemapPropertyType.Float, new ValueData(value)); } /// /// Creates a boolean property value. /// /// The boolean value. /// A property value containing the boolean. public static TilemapPropertyValue CreateBool(bool value) { return new TilemapPropertyValue(TilemapPropertyType.Bool, new ValueData(value)); } /// /// Creates a color property value. /// /// The color value. /// A property value containing the color. public static TilemapPropertyValue CreateColor(Color value) { return new TilemapPropertyValue(TilemapPropertyType.Color, new ValueData(value.PackedValue)); } /// /// Creates a file path property value. /// /// The file path. /// A property value containing the file path. public static TilemapPropertyValue CreateFile(string path) { return new TilemapPropertyValue(TilemapPropertyType.File, default, path); } /// /// Creates an object reference property value. /// /// The object reference ID. /// A property value containing the object ID. public static TilemapPropertyValue CreateObject(int objectId) { return new TilemapPropertyValue(TilemapPropertyType.Object, new ValueData(objectId)); } #endregion #region Type-safe Accessors /// /// Gets the value as a string. /// /// The string value. /// The property type is not public string AsString() { if (Type != TilemapPropertyType.String) throw new InvalidOperationException($"Cannot access property of type {Type} as String"); return _stringValue; } /// /// Gets the value as an integer. /// /// The integer value. /// The property type is not public int AsInt() { if (Type != TilemapPropertyType.Int) throw new InvalidOperationException($"Cannot access property of type {Type} as Int."); return _valueData.Int32; } /// /// Gets the value as a float. /// /// The float value. /// The property type is not public float AsFloat() { if (Type != TilemapPropertyType.Float) throw new InvalidOperationException($"Cannot access property of type {Type} as Float."); return _valueData.Single; } /// /// Gets the value as a boolean. /// /// The bool value. /// The property type is not public bool AsBool() { if (Type != TilemapPropertyType.Bool) throw new InvalidOperationException($"Cannot access property of type {Type} as Bool."); return _valueData.Boolean; } /// /// Gets the value as a color. /// /// The color value. /// The property type is not public Color AsColor() { if (Type != TilemapPropertyType.Color) throw new InvalidOperationException($"Cannot access property of type {Type} as Color."); return new Color(_valueData.ColorPackedValue); } /// /// Gets the value as a file path. /// /// The file path. /// The property type is not public string AsFile() { if (Type != TilemapPropertyType.File) throw new InvalidOperationException($"Cannot access property of type {Type} as File."); return _stringValue; } /// /// Gets the value as an object reference ID. /// /// The object ID. /// The property type is not public int AsObject() { if (Type != TilemapPropertyType.Object) throw new InvalidOperationException($"Cannot access property of type {Type} as Object."); return _valueData.Int32; } #endregion } }