TilemapPropertyValue.cs 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. using System;
  2. using System.Runtime.InteropServices;
  3. using Microsoft.Xna.Framework;
  4. namespace MonoGame.Extended.Tilemaps
  5. {
  6. /// <summary>
  7. /// Represents a custom property value that can be of various types.
  8. /// </summary>
  9. public readonly struct TilemapPropertyValue
  10. {
  11. [StructLayout(LayoutKind.Explicit)]
  12. private readonly struct ValueData
  13. {
  14. [FieldOffset(0)] public readonly int Int32;
  15. [FieldOffset(0)] public readonly float Single;
  16. [FieldOffset(0)] public readonly bool Boolean;
  17. [FieldOffset(0)] public readonly uint ColorPackedValue;
  18. public ValueData(int value) => Int32 = value;
  19. public ValueData(float value) => Single = value;
  20. public ValueData(bool value) => Boolean = value;
  21. public ValueData(uint value) => ColorPackedValue = value;
  22. }
  23. private readonly ValueData _valueData;
  24. private readonly string _stringValue;
  25. /// <summary>
  26. /// Gets the type of this property value.
  27. /// </summary>
  28. public TilemapPropertyType Type { get; }
  29. private TilemapPropertyValue(TilemapPropertyType type, ValueData valueData, string stringValue = null)
  30. {
  31. Type = type;
  32. _valueData = valueData;
  33. _stringValue = stringValue;
  34. }
  35. #region Factory Methods
  36. /// <summary>
  37. /// Creates a string property value.
  38. /// </summary>
  39. /// <param name="value">The string value.</param>
  40. /// <returns>A property value containing the string.</returns>
  41. public static TilemapPropertyValue CreateString(string value)
  42. {
  43. return new TilemapPropertyValue(TilemapPropertyType.String, default, value);
  44. }
  45. /// <summary>
  46. /// Creates an integer property value.
  47. /// </summary>
  48. /// <param name="value">The integer value.</param>
  49. /// <returns>A property value containing the integer.</returns>
  50. public static TilemapPropertyValue CreateInt(int value)
  51. {
  52. return new TilemapPropertyValue(TilemapPropertyType.Int, new ValueData(value));
  53. }
  54. /// <summary>
  55. /// Creates a float property value.
  56. /// </summary>
  57. /// <param name="value">The float value.</param>
  58. /// <returns>A property value containing the float.</returns>
  59. public static TilemapPropertyValue CreateFloat(float value)
  60. {
  61. return new TilemapPropertyValue(TilemapPropertyType.Float, new ValueData(value));
  62. }
  63. /// <summary>
  64. /// Creates a boolean property value.
  65. /// </summary>
  66. /// <param name="value">The boolean value.</param>
  67. /// <returns>A property value containing the boolean.</returns>
  68. public static TilemapPropertyValue CreateBool(bool value)
  69. {
  70. return new TilemapPropertyValue(TilemapPropertyType.Bool, new ValueData(value));
  71. }
  72. /// <summary>
  73. /// Creates a color property value.
  74. /// </summary>
  75. /// <param name="value">The color value.</param>
  76. /// <returns>A property value containing the color.</returns>
  77. public static TilemapPropertyValue CreateColor(Color value)
  78. {
  79. return new TilemapPropertyValue(TilemapPropertyType.Color, new ValueData(value.PackedValue));
  80. }
  81. /// <summary>
  82. /// Creates a file path property value.
  83. /// </summary>
  84. /// <param name="path">The file path.</param>
  85. /// <returns>A property value containing the file path.</returns>
  86. public static TilemapPropertyValue CreateFile(string path)
  87. {
  88. return new TilemapPropertyValue(TilemapPropertyType.File, default, path);
  89. }
  90. /// <summary>
  91. /// Creates an object reference property value.
  92. /// </summary>
  93. /// <param name="objectId">The object reference ID.</param>
  94. /// <returns>A property value containing the object ID.</returns>
  95. public static TilemapPropertyValue CreateObject(int objectId)
  96. {
  97. return new TilemapPropertyValue(TilemapPropertyType.Object, new ValueData(objectId));
  98. }
  99. #endregion
  100. #region Type-safe Accessors
  101. /// <summary>
  102. /// Gets the value as a string.
  103. /// </summary>
  104. /// <returns>The string value.</returns>
  105. /// <exception cref="InvalidOperationException">The property type is not <see cref="TilemapPropertyType.String"/></exception>
  106. public string AsString()
  107. {
  108. if (Type != TilemapPropertyType.String)
  109. throw new InvalidOperationException($"Cannot access property of type {Type} as String");
  110. return _stringValue;
  111. }
  112. /// <summary>
  113. /// Gets the value as an integer.
  114. /// </summary>
  115. /// <returns>The integer value.</returns>
  116. /// <exception cref="InvalidOperationException">The property type is not <see cref="TilemapPropertyType.Int"/></exception>
  117. public int AsInt()
  118. {
  119. if (Type != TilemapPropertyType.Int)
  120. throw new InvalidOperationException($"Cannot access property of type {Type} as Int.");
  121. return _valueData.Int32;
  122. }
  123. /// <summary>
  124. /// Gets the value as a float.
  125. /// </summary>
  126. /// <returns>The float value.</returns>
  127. /// <exception cref="InvalidOperationException">The property type is not <see cref="TilemapPropertyType.Float"/></exception>
  128. public float AsFloat()
  129. {
  130. if (Type != TilemapPropertyType.Float)
  131. throw new InvalidOperationException($"Cannot access property of type {Type} as Float.");
  132. return _valueData.Single;
  133. }
  134. /// <summary>
  135. /// Gets the value as a boolean.
  136. /// </summary>
  137. /// <returns>The bool value.</returns>
  138. /// <exception cref="InvalidOperationException">The property type is not <see cref="TilemapPropertyType.Bool"/></exception>
  139. public bool AsBool()
  140. {
  141. if (Type != TilemapPropertyType.Bool)
  142. throw new InvalidOperationException($"Cannot access property of type {Type} as Bool.");
  143. return _valueData.Boolean;
  144. }
  145. /// <summary>
  146. /// Gets the value as a color.
  147. /// </summary>
  148. /// <returns>The color value.</returns>
  149. /// <exception cref="InvalidOperationException">The property type is not <see cref="TilemapPropertyType.Color"/></exception>
  150. public Color AsColor()
  151. {
  152. if (Type != TilemapPropertyType.Color)
  153. throw new InvalidOperationException($"Cannot access property of type {Type} as Color.");
  154. return new Color(_valueData.ColorPackedValue);
  155. }
  156. /// <summary>
  157. /// Gets the value as a file path.
  158. /// </summary>
  159. /// <returns>The file path.</returns>
  160. /// <exception cref="InvalidOperationException">The property type is not <see cref="TilemapPropertyType.File"/></exception>
  161. public string AsFile()
  162. {
  163. if (Type != TilemapPropertyType.File)
  164. throw new InvalidOperationException($"Cannot access property of type {Type} as File.");
  165. return _stringValue;
  166. }
  167. /// <summary>
  168. /// Gets the value as an object reference ID.
  169. /// </summary>
  170. /// <returns>The object ID.</returns>
  171. /// <exception cref="InvalidOperationException">The property type is not <see cref="TilemapPropertyType.Object"/></exception>
  172. public int AsObject()
  173. {
  174. if (Type != TilemapPropertyType.Object)
  175. throw new InvalidOperationException($"Cannot access property of type {Type} as Object.");
  176. return _valueData.Int32;
  177. }
  178. #endregion
  179. }
  180. }