diff --git a/Runtime/CesiumFeatureIdAttribute.cs b/Runtime/CesiumFeatureIdAttribute.cs
index 205def3a..4dd6486f 100644
--- a/Runtime/CesiumFeatureIdAttribute.cs
+++ b/Runtime/CesiumFeatureIdAttribute.cs
@@ -54,7 +54,7 @@ internal CesiumFeatureIdAttribute()
///
public override Int64 GetFeatureIdFromRaycastHit(RaycastHit hitInfo)
{
- int vertex = GetFirstVertexFromHitTriangle(hitInfo);
+ int vertex = base.GetFirstVertexFromHitTriangle(hitInfo);
return this.GetFeatureIdForVertex(vertex);
}
}
diff --git a/Runtime/CesiumMetadataValue.cs b/Runtime/CesiumMetadataValue.cs
index eb0938b0..ed04f25f 100644
--- a/Runtime/CesiumMetadataValue.cs
+++ b/Runtime/CesiumMetadataValue.cs
@@ -3,17 +3,26 @@
using Unity.Mathematics;
using Reinterop;
using System.Collections.Generic;
-
namespace CesiumForUnity
{
///
/// Represents the value type of a metadata value or property, akin to the
/// property types in EXT_structural_metadata.
///
- //[ReinteropNativeImplementation("CesiumForUnityNative::CesiumMetadataValueImpl", "CesiumMetadataValueImpl.h", staticOnly: true)]
+ [ReinteropNativeImplementation("CesiumForUnityNative::CesiumMetadataValueImpl", "CesiumMetadataValueImpl.h", staticOnly: true)]
public partial class CesiumMetadataValue
{
- internal System.Object value { get; set; }
+ ///
+ /// The value as an object. This functions similarly to a std::any in C++.
+ ///
+ ///
+ /// If this is intended to hold an integer vecN or matN value, use the appropriate
+ /// CesiumIntN, CesiumUIntN, CesiumIntMatN, or CesiumUIntMatN structs. Only
+ /// use Unity.Mathematics for vecNs or matNs with floating point components.
+ ///
+ internal System.Object valueImpl { get; set; }
+
+ #region Getters
///
/// The type of the metadata value as defined in the
@@ -24,7 +33,7 @@ public CesiumMetadataValueType valueType
{
get
{
- return CesiumMetadataValueType.GetValueType(this.value);
+ return CesiumMetadataValueType.GetValueType(this.valueImpl);
}
}
@@ -40,17 +49,21 @@ public CesiumMetadataValueType valueType
/// Whether the value is empty.
public bool isEmpty
{
- get { return this.value == null; }
+ get { return this.valueImpl == null; }
}
+ #endregion
+ #region Constructors
public CesiumMetadataValue() : this(null)
{ }
public CesiumMetadataValue(System.Object value)
{
- this.value = value;
+ this.valueImpl = value;
}
+ #endregion
+ #region Public Methods
///
/// Attempts to retrieve the value as a boolean.
///
@@ -74,44 +87,12 @@ public CesiumMetadataValue(System.Object value)
/// The value as a Boolean.
public Boolean GetBoolean(Boolean defaultValue = false)
{
- if (this.isEmpty)
- {
- return defaultValue;
- }
-
- CesiumMetadataValueType valueType = this.valueType;
- if (valueType.isArray)
+ if (this.isEmpty || this.valueType.isArray)
{
return defaultValue;
}
- switch (valueType.type)
- {
- case CesiumMetadataType.Boolean:
- return (this.value as Boolean?).Value;
- case CesiumMetadataType.Scalar:
- return Convert.ToBoolean(this.value);
- case CesiumMetadataType.String:
- String str = this.value as String;
- if (
- str.Equals("true", StringComparison.OrdinalIgnoreCase) ||
- str.Equals("yes", StringComparison.OrdinalIgnoreCase) ||
- str.Equals("1", StringComparison.OrdinalIgnoreCase))
- {
- return true;
- }
-
- if (
- str.Equals("false", StringComparison.OrdinalIgnoreCase) ||
- str.Equals("no", StringComparison.OrdinalIgnoreCase) ||
- str.Equals("0", StringComparison.OrdinalIgnoreCase))
- {
- return true;
- }
- return defaultValue;
- default:
- return defaultValue;
- }
+ return ConvertToBoolean(this, defaultValue);
}
///
@@ -157,7 +138,7 @@ public SByte GetSByte(SByte defaultValue = 0)
case CesiumMetadataType.String:
try
{
- return Convert.ToSByte(this.value);
+ return Convert.ToSByte(this.valueImpl);
}
catch
{
@@ -167,7 +148,7 @@ public SByte GetSByte(SByte defaultValue = 0)
case CesiumMetadataType.Scalar:
// We need to explicitly truncate floating-point values. Otherwise,
// Convert will round to the nearest number.
- System.Object value = this.value;
+ System.Object value = this.valueImpl;
switch (valueType.componentType)
{
case CesiumMetadataComponentType.Float32:
@@ -236,7 +217,7 @@ public Byte GetByte(Byte defaultValue = 0)
case CesiumMetadataType.String:
try
{
- return Convert.ToByte(this.value);
+ return Convert.ToByte(this.valueImpl);
}
catch
{
@@ -246,7 +227,7 @@ public Byte GetByte(Byte defaultValue = 0)
case CesiumMetadataType.Scalar:
// We need to explicitly truncate floating-point values. Otherwise,
// Convert will round to the nearest number.
- System.Object value = this.value;
+ System.Object value = this.valueImpl;
switch (valueType.componentType)
{
case CesiumMetadataComponentType.Float32:
@@ -315,7 +296,7 @@ public Int16 GetInt16(Int16 defaultValue = 0)
case CesiumMetadataType.String:
try
{
- return Convert.ToInt16(this.value);
+ return Convert.ToInt16(this.valueImpl);
}
catch
{
@@ -325,7 +306,7 @@ public Int16 GetInt16(Int16 defaultValue = 0)
case CesiumMetadataType.Scalar:
// We need to explicitly truncate floating-point values. Otherwise,
// Convert will round to the nearest number.
- System.Object value = this.value;
+ System.Object value = this.valueImpl;
switch (valueType.componentType)
{
case CesiumMetadataComponentType.Float32:
@@ -395,7 +376,7 @@ public UInt16 GetUInt16(UInt16 defaultValue = 0)
case CesiumMetadataType.String:
try
{
- return Convert.ToUInt16(this.value);
+ return Convert.ToUInt16(this.valueImpl);
}
catch
{
@@ -405,7 +386,7 @@ public UInt16 GetUInt16(UInt16 defaultValue = 0)
case CesiumMetadataType.Scalar:
// We need to explicitly truncate floating-point values. Otherwise,
// Convert will round to the nearest number.
- System.Object value = this.value;
+ System.Object value = this.valueImpl;
switch (valueType.componentType)
{
case CesiumMetadataComponentType.Float32:
@@ -476,7 +457,7 @@ public Int32 GetInt32(Int32 defaultValue = 0)
case CesiumMetadataType.String:
try
{
- return Convert.ToInt32(this.value);
+ return Convert.ToInt32(this.valueImpl);
}
catch
{
@@ -486,7 +467,7 @@ public Int32 GetInt32(Int32 defaultValue = 0)
case CesiumMetadataType.Scalar:
// We need to explicitly truncate floating-point values. Otherwise,
// Convert will round to the nearest number.
- System.Object value = this.value;
+ System.Object value = this.valueImpl;
switch (valueType.componentType)
{
case CesiumMetadataComponentType.Float32:
@@ -555,7 +536,7 @@ public UInt32 GetUInt32(UInt32 defaultValue = 0)
case CesiumMetadataType.String:
try
{
- return Convert.ToUInt32(this.value);
+ return Convert.ToUInt32(this.valueImpl);
}
catch
{
@@ -565,7 +546,7 @@ public UInt32 GetUInt32(UInt32 defaultValue = 0)
case CesiumMetadataType.Scalar:
// We need to explicitly truncate floating-point values. Otherwise,
// Convert will round to the nearest number.
- System.Object value = this.value;
+ System.Object value = this.valueImpl;
switch (valueType.componentType)
{
case CesiumMetadataComponentType.Float32:
@@ -636,7 +617,7 @@ public Int64 GetInt64(Int64 defaultValue = 0)
case CesiumMetadataType.String:
try
{
- return Convert.ToInt64(this.value);
+ return Convert.ToInt64(this.valueImpl);
}
catch
{
@@ -646,7 +627,7 @@ public Int64 GetInt64(Int64 defaultValue = 0)
case CesiumMetadataType.Scalar:
// We need to explicitly truncate floating-point values. Otherwise,
// Convert will round to the nearest number.
- System.Object value = this.value;
+ System.Object value = this.valueImpl;
switch (valueType.componentType)
{
case CesiumMetadataComponentType.Float32:
@@ -715,7 +696,7 @@ public UInt64 GetUInt64(UInt64 defaultValue = 0)
case CesiumMetadataType.String:
try
{
- return Convert.ToUInt64(this.value);
+ return Convert.ToUInt64(this.valueImpl);
}
catch
{
@@ -725,7 +706,7 @@ public UInt64 GetUInt64(UInt64 defaultValue = 0)
case CesiumMetadataType.Scalar:
// We need to explicitly truncate floating-point values. Otherwise,
// Convert will round to the nearest number.
- System.Object value = this.value;
+ System.Object value = this.valueImpl;
switch (valueType.componentType)
{
case CesiumMetadataComponentType.Float32:
@@ -794,7 +775,7 @@ public float GetFloat(float defaultValue = 0)
case CesiumMetadataType.Scalar:
if (valueType.componentType == CesiumMetadataComponentType.Float64)
{
- double value = (this.value as double?).Value;
+ double value = (this.valueImpl as double?).Value;
if (value < Single.MinValue || value > Single.MaxValue)
{
return defaultValue;
@@ -806,7 +787,7 @@ public float GetFloat(float defaultValue = 0)
case CesiumMetadataType.String:
try
{
- return Convert.ToSingle(this.value);
+ return Convert.ToSingle(this.valueImpl);
}
catch
{
@@ -863,13 +844,80 @@ public double GetDouble(double defaultValue = 0)
case CesiumMetadataType.Scalar:
try
{
- return Convert.ToDouble(this.value);
+ return Convert.ToDouble(this.valueImpl);
+ }
+ catch
+ {
+ // The above may throw if trying to convert an invalid string.
+ return defaultValue;
+ }
+ default:
+ return defaultValue;
+ }
+ }
+
+ ///
+ /// Attempts to retrieve the value for the given feature as a double2.
+ ///
+ ///
+ /// If the value is a 2-dimensional vector, its components will be converted
+ /// to double-precision floating-point numbers.
+ ///
+ /// If the value is a 3- or 4-dimensional vector, it will use the first two
+ /// components to construct the double2.
+ ///
+ /// If the value is a scalar, the resulting float2 will have this value in
+ /// both of its components.
+ ///
+ /// If the value is a boolean, (1.0, 1.0) is returned for true, while
+ /// (0.0, 0.0) is returned for false.
+ ///
+ /// If the value is a string that can be parsed as a double2, the parsed
+ /// value is returned. The string must be formatted as "(X, Y)" or
+ /// "double2(X, Y)".
+ ///
+ ///
+ ///
+ /// In all other cases, the user-defined default value is returned. If the
+ /// feature ID is out-of-range, or if the property table property is somehow
+ /// invalid, the user-defined default value is returned.
+ ///
+ ///
+ /// The ID of the feature.
+ /// The default value to fall back on.
+ /// The property value as a double2.
+ public double2 GetDouble2(Int64 featureID, double2 defaultValue)
+ {
+ if (this.isEmpty)
+ {
+ return defaultValue;
+ }
+
+ CesiumMetadataValueType valueType = this.valueType;
+ if (valueType.isArray)
+ {
+ return defaultValue;
+ }
+
+ switch (valueType.type)
+ {
+ case CesiumMetadataType.Vec2:
+ case CesiumMetadataType.Vec3:
+ case CesiumMetadataType.Vec4:
+ // return ConvertVecNObjectToDouble2(this.valueImpl, defaultValue);
+ case CesiumMetadataType.Boolean:
+ case CesiumMetadataType.String:
+ case CesiumMetadataType.Scalar:
+ try
+ {
+ return Convert.ToDouble(this.valueImpl);
}
catch
{
// The above may throw if trying to convert an invalid string.
return defaultValue;
}
+
default:
return defaultValue;
}
@@ -899,12 +947,39 @@ public String GetString(String defaultValue = "")
return defaultValue;
}
- if (valueType.type == CesiumMetadataType.String)
+ switch (valueType.type)
{
- return value as String;
- }
+ case CesiumMetadataType.String:
+ return valueImpl as String;
+ case CesiumMetadataType.Boolean:
+ return Convert.ToString(valueImpl).ToLower();
+ case CesiumMetadataType.Scalar:
+ return Convert.ToString(valueImpl);
+ case CesiumMetadataType.Vec2:
+ case CesiumMetadataType.Vec3:
+ case CesiumMetadataType.Vec4:
+ case CesiumMetadataType.Mat2:
+ case CesiumMetadataType.Mat3:
+ case CesiumMetadataType.Mat4:
+ // TODO: do this in C++
+ String result = this.valueImpl.ToString();
+ if (String.IsNullOrEmpty(result))
+ {
+ return defaultValue;
+ }
- return defaultValue;
+ // The Unity.Mathematics classes print string values in the format typeN(X, Y, Z).
+ // To keep it consistent with the output of CesiumPropertyTableProperty, the type is omitted from the value result.
+ Int32 startIndex = result.IndexOf('(');
+ if (startIndex < 0)
+ {
+ return defaultValue;
+ }
+
+ return result.Substring(startIndex);
+ default:
+ return defaultValue;
+ }
}
///
@@ -916,7 +991,7 @@ public CesiumPropertyArray GetArray()
{
if (valueType.isArray)
{
- return this.value as CesiumPropertyArray;
+ return this.valueImpl as CesiumPropertyArray;
}
return new CesiumPropertyArray();
@@ -943,5 +1018,182 @@ public static Dictionary GetValuesAsStrings(Dictionary
+ /// Represents a vec2 with signed integer components. This preserves the accuracy of the integer
+ /// values, which could otherwise lose precision if represented as doubles.
+ ///
+ ///
+ /// Internally, this is used to store all signed integer vec2 types, including i8vec2,
+ /// i16vec2, i32vec2, and i64vec2. The intended type is conveyed through CesiumMetadataComponentType.
+ ///
+ internal struct CesiumIntVec2
+ {
+ public CesiumMetadataComponentType componentType { get; }
+
+ public Int64 x { get; }
+ public Int64 y { get; }
+
+ public CesiumIntVec2(SByte x, SByte y)
+ {
+ this.componentType = CesiumMetadataComponentType.Int8;
+ this.x = x;
+ this.y = y;
+ }
+
+ public CesiumIntVec2(Int16 x, Int16 y)
+ {
+ this.componentType = CesiumMetadataComponentType.Int16;
+ this.x = x;
+ this.y = y;
+ }
+
+ public CesiumIntVec2(Int32 x, Int32 y)
+ {
+ this.componentType = CesiumMetadataComponentType.Int32;
+ this.x = x;
+ this.y = y;
+ }
+
+ public CesiumIntVec2(Int64 x, Int64 y)
+ {
+ this.componentType = CesiumMetadataComponentType.Int64;
+ this.x = x;
+ this.y = y;
+ }
+
+ public Int64 this[int index]
+ {
+ get
+ {
+ switch (index)
+ {
+ case 0:
+ return x;
+ case 1:
+ return y;
+ default:
+ throw new System.IndexOutOfRangeException();
+ }
+ }
+ }
+ }
+
+ ///
+ /// Represents a vec3 with signed integer components. This preserves the accuracy of the integer
+ /// values, which could otherwise lose precision if represented as doubles.
+ ///
+ ///
+ /// Internally, this is used to store all signed integer vec3 types, including i8vec3,
+ /// i16vec3, i32vec3, and i64vec3. The intended type is conveyed through CesiumMetadataComponentType.
+ ///
+ internal struct CesiumIntVec3
+ {
+ public CesiumMetadataComponentType componentType { get; }
+
+ public Int64 x { get; }
+ public Int64 y { get; }
+ public Int64 z { get; }
+
+ public CesiumIntVec3(SByte x, SByte y, SByte z)
+ {
+ this.componentType = CesiumMetadataComponentType.Int8;
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ public CesiumIntVec3(Int16 x, Int16 y, Int16 z)
+ {
+ this.componentType = CesiumMetadataComponentType.Int16;
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ public CesiumIntVec3(Int32 x, Int32 y, Int32 z)
+ {
+ this.componentType = CesiumMetadataComponentType.Int32;
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ public CesiumIntVec3(Int64 x, Int64 y, Int64 z)
+ {
+ this.componentType = CesiumMetadataComponentType.Int64;
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ public Int64 this[int index]
+ {
+ get
+ {
+ switch (index)
+ {
+ case 0:
+ return x;
+ case 1:
+ return y;
+ case 2:
+ return z;
+ default:
+ throw new System.IndexOutOfRangeException();
+ }
+ }
+ }
+ }
+
+ ///
+ /// Represents a vec4 with signed integer components. This preserves the accuracy of the integer values,
+ /// which could otherwise lose precision if represented as doubles.
+ ///
+ ///
+ /// Internally, this is used to store all signed integer vec4 types, including i8vec4,
+ /// i16vec4, i32vec4, and i64vec4. The intended type is conveyed through CesiumMetadataComponentType.
+ ///
+ internal struct CesiumIntVec4
+ {
+ public CesiumMetadataComponentType componentType { get; }
+
+ public Int64 x { get; }
+ public Int64 y { get; }
+ public Int64 z { get; }
+ public Int64 w { get; }
+
+ public CesiumIntVec4(SByte x, SByte y, SByte z, SByte w)
+ {
+ this.componentType = CesiumMetadataComponentType.Int8;
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ this.w = w;
+ }
+ public CesiumIntVec4(Int16 x, Int16 y, Int16 z, Int16 w)
+ {
+ this.componentType = CesiumMetadataComponentType.Int16;
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ this.w = w;
+ }
+ public CesiumIntVec4(Int32 x, Int32 y, Int32 z, Int32 w)
+ {
+ this.componentType = CesiumMetadataComponentType.Int32;
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ this.w = w;
+ }
+
+ public CesiumIntVec4(Int64 x, Int64 y, Int64 z, Int64 w)
+ {
+ this.componentType = CesiumMetadataComponentType.Int64;
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ this.w = w;
+ }
+
+ public Int64 this[int index]
+ {
+ get
+ {
+ switch (index)
+ {
+ case 0:
+ return x;
+ case 1:
+ return y;
+ case 2:
+ return z;
+ case 3:
+ return w;
+ default:
+ throw new System.IndexOutOfRangeException();
+ }
+ }
+ }
+ }
+
+ ///
+ /// Represents a vec2 with unsigned integer components. This preserves the accuracy of the integer
+ /// values, which could otherwise lose precision if represented as doubles.
+ ///
+ ///
+ /// Internally, this is used to store all unsigned integer vec2 types, including u8vec2,
+ /// u16vec2, u32vec2, and u64vec2. The intended type is conveyed through CesiumMetadataComponentType.
+ ///
+ internal struct CesiumUIntVec2
+ {
+ public CesiumMetadataComponentType componentType { get; }
+
+ public UInt64 x { get; }
+ public UInt64 y { get; }
+
+ public CesiumUIntVec2(Byte x, Byte y)
+ {
+ this.componentType = CesiumMetadataComponentType.Uint8;
+ this.x = x;
+ this.y = y;
+ }
+
+ public CesiumUIntVec2(UInt16 x, UInt16 y)
+ {
+ this.componentType = CesiumMetadataComponentType.Uint16;
+ this.x = x;
+ this.y = y;
+ }
+
+ public CesiumUIntVec2(UInt32 x, UInt32 y)
+ {
+ this.componentType = CesiumMetadataComponentType.Uint32;
+ this.x = x;
+ this.y = y;
+ }
+
+ public CesiumUIntVec2(UInt64 x, UInt64 y)
+ {
+ this.componentType = CesiumMetadataComponentType.Uint64;
+ this.x = x;
+ this.y = y;
+ }
+
+ public UInt64 this[int index]
+ {
+ get
+ {
+ switch (index)
+ {
+ case 0:
+ return x;
+ case 1:
+ return y;
+ default:
+ throw new System.IndexOutOfRangeException();
+ }
+ }
+ }
+ }
+
+ ///
+ /// Represents a vec3 with unsigned integer components. This preserves the accuracy of the integer
+ /// values, which could otherwise lose precision if represented as doubles.
+ ///
+ ///
+ /// Internally, this is used to store all unsigned integer vec3 types, including u8vec3,
+ /// u16vec3, u32vec3, and u64vec3. The intended type is conveyed through CesiumMetadataComponentType.
+ ///
+ internal struct CesiumUIntVec3
+ {
+ public CesiumMetadataComponentType componentType { get; }
+
+ public UInt64 x { get; }
+ public UInt64 y { get; }
+ public UInt64 z { get; }
+
+ public CesiumUIntVec3(Byte x, Byte y, Byte z)
+ {
+ this.componentType = CesiumMetadataComponentType.Uint8;
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ public CesiumUIntVec3(UInt16 x, UInt16 y, UInt16 z)
+ {
+ this.componentType = CesiumMetadataComponentType.Uint16;
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ public CesiumUIntVec3(UInt32 x, UInt32 y, UInt32 z)
+ {
+ this.componentType = CesiumMetadataComponentType.Uint32;
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ public CesiumUIntVec3(UInt64 x, UInt64 y, UInt64 z)
+ {
+ this.componentType = CesiumMetadataComponentType.Uint64;
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ public UInt64 this[int index]
+ {
+ get
+ {
+ switch (index)
+ {
+ case 0:
+ return x;
+ case 1:
+ return y;
+ case 2:
+ return z;
+ default:
+ throw new System.IndexOutOfRangeException();
+ }
+ }
+ }
+ }
+
+ ///
+ /// Represents a vec4 with unsigned integer components. This preserves the accuracy of the integer
+ /// values, which could otherwise lose precision if represented as doubles.
+ ///
+ ///
+ /// Internally, this is used to store all unsigned integer vec4 types, including u8vec4,
+ /// u16vec4, u32vec4, and u64vec4. The intended type is conveyed through CesiumMetadataComponentType.
+ ///
+ internal struct CesiumUIntVec4
+ {
+ public CesiumMetadataComponentType componentType { get; }
+
+ public UInt64 x { get; }
+ public UInt64 y { get; }
+ public UInt64 z { get; }
+ public UInt64 w { get; }
+
+ public CesiumUIntVec4(Byte x, Byte y, Byte z, Byte w)
+ {
+ this.componentType = CesiumMetadataComponentType.Uint8;
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ this.w = w;
+ }
+
+ public CesiumUIntVec4(UInt16 x, UInt16 y, UInt16 z, UInt16 w)
+ {
+ this.componentType = CesiumMetadataComponentType.Uint16;
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ this.w = w;
+ }
+
+ public CesiumUIntVec4(UInt32 x, UInt32 y, UInt32 z, UInt32 w)
+ {
+ this.componentType = CesiumMetadataComponentType.Uint32;
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ this.w = w;
+ }
+
+ public CesiumUIntVec4(UInt64 x, UInt64 y, UInt64 z, UInt64 w)
+ {
+ this.componentType = CesiumMetadataComponentType.Uint64;
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ this.w = w;
+ }
+
+ public UInt64 this[int index]
+ {
+ get
+ {
+ switch (index)
+ {
+ case 0:
+ return x;
+ case 1:
+ return y;
+ case 2:
+ return z;
+ case 3:
+ return w;
+ default:
+ throw new System.IndexOutOfRangeException();
+ }
+ }
+ }
+ }
+ #endregion
+
+ #region Internal MatN type definitions
+
+ ///
+ /// Represents a mat2x2 with signed integer components. This preserves the accuracy of the integer
+ /// values, which could otherwise lose precision if represented as doubles.
+ ///
+ ///
+ /// Internally, this is used to store all signed integer mat types, including i8mat2x2,
+ /// i16mat2x2, i32mat2x2, and i64mat2x2. The intended type is conveyed through CesiumMetadataComponentType.
+ ///
+ internal struct CesiumIntMat2x2
+ {
+ public CesiumMetadataComponentType componentType { get; }
+
+ private CesiumIntVec2[] value { get; }
+
+ public CesiumIntMat2x2(CesiumIntVec2 v0, CesiumIntVec2 v1)
+ {
+ Debug.Assert(v0.componentType == v1.componentType);
+ this.componentType = v0.componentType;
+ this.value = new CesiumIntVec2[] { v0, v1 };
+ }
+
+ public CesiumIntVec2 this[int index]
+ {
+ get
+ {
+ switch (index)
+ {
+ case 0:
+ return this.value[0];
+ case 1:
+ return this.value[1];
+ default:
+ throw new System.IndexOutOfRangeException();
+ }
+ }
+ }
+ }
+
+ ///
+ /// Represents a mat3x3 with signed integer components. This preserves the accuracy of the integer
+ /// values, which could otherwise lose precision if represented as doubles.
+ ///
+ ///
+ /// Internally, this is used to store all signed integer mat types, including i8mat3x3,
+ /// i16mat3x3, i32mat3x3, and i64mat3x3. The intended type is conveyed through CesiumMetadataComponentType.
+ ///
+ internal struct CesiumIntMat3x3
+ {
+ public CesiumMetadataComponentType componentType { get; }
+
+ private CesiumIntVec3[] value { get; }
+
+ public CesiumIntMat3x3(CesiumIntVec3 v0, CesiumIntVec3 v1, CesiumIntVec3 v2)
+ {
+ Debug.Assert(v0.componentType == v1.componentType && v1.componentType == v2.componentType);
+ this.componentType = v0.componentType;
+ this.value = new CesiumIntVec3[] { v0, v1, v2 };
+ }
+
+ public CesiumIntVec3 this[int index]
+ {
+ get
+ {
+ switch (index)
+ {
+ case 0:
+ return this.value[0];
+ case 1:
+ return this.value[1];
+ case 2:
+ return this.value[2];
+ default:
+ throw new System.IndexOutOfRangeException();
+ }
+ }
+ }
+ }
+
+ ///
+ /// Represents a mat4x4 with signed integer components. This preserves the accuracy of the integer
+ /// values, which could otherwise lose precision if represented as doubles.
+ ///
+ ///
+ /// Internally, this is used to store all signed integer mat types, including i8mat4x4,
+ /// i16mat4x4, i32mat4x4, and i64mat4x4. The intended type is conveyed through CesiumMetadataComponentType.
+ ///
+ internal struct CesiumIntMat4x4
+ {
+ public CesiumMetadataComponentType componentType { get; }
+
+ private CesiumIntVec4[] value { get; }
+
+ public CesiumIntMat4x4(CesiumIntVec4 v0, CesiumIntVec4 v1, CesiumIntVec4 v2, CesiumIntVec4 v3)
+ {
+ Debug.Assert(v0.componentType == v1.componentType && v1.componentType == v2.componentType && v2.componentType == v3.componentType);
+ this.componentType = v0.componentType;
+ this.value = new CesiumIntVec4[] { v0, v1, v2, v3 };
+ }
+
+ public CesiumIntVec4 this[int index]
+ {
+ get
+ {
+ switch (index)
+ {
+ case 0:
+ return this.value[0];
+ case 1:
+ return this.value[1];
+ case 2:
+ return this.value[2];
+ case 3:
+ return this.value[3];
+ default:
+ throw new System.IndexOutOfRangeException();
+ }
+ }
+ }
+ }
+
+ ///
+ /// Represents a mat2x2 with unsigned integer components. This preserves the accuracy of the integer
+ /// values, which could otherwise lose precision if represented as doubles.
+ ///
+ ///
+ /// Internally, this is used to store all unsigned integer mat types, including u8mat2x2,
+ /// u16mat2x2, u32mat2x2, and u64mat2x2. The intended type is conveyed through CesiumMetadataComponentType.
+ ///
+ internal struct CesiumUIntMat2x2
+ {
+ public CesiumMetadataComponentType componentType { get; }
+
+ private CesiumUIntVec2[] value { get; }
+
+ public CesiumUIntMat2x2(CesiumUIntVec2 v0, CesiumUIntVec2 v1)
+ {
+ Debug.Assert(v0.componentType == v1.componentType);
+ this.componentType = v0.componentType;
+ this.value = new CesiumUIntVec2[] { v0, v1 };
+ }
+
+ public CesiumUIntVec2 this[int index]
+ {
+ get
+ {
+ switch (index)
+ {
+ case 0:
+ return this.value[0];
+ case 1:
+ return this.value[1];
+ default:
+ throw new System.IndexOutOfRangeException();
+ }
+ }
+ }
+ }
+
+ ///
+ /// Represents a mat3x3 with unsigned integer components. This preserves the accuracy of the integer
+ /// values, which could otherwise lose precision if represented as doubles.
+ ///
+ ///
+ /// Internally, this is used to store all unsigned integer mat types, including u8mat3x3,
+ /// u16mat3x3, u32mat3x3, and u64mat3x3. The intended type is conveyed through CesiumMetadataComponentType.
+ ///
+ internal struct CesiumUIntMat3x3
+ {
+ public CesiumMetadataComponentType componentType { get; }
+
+ private CesiumUIntVec3[] value { get; }
+
+ public CesiumUIntMat3x3(CesiumUIntVec3 v0, CesiumUIntVec3 v1, CesiumUIntVec3 v2)
+ {
+ Debug.Assert(v0.componentType == v1.componentType && v1.componentType == v2.componentType);
+ this.componentType = v0.componentType;
+ this.value = new CesiumUIntVec3[] { v0, v1, v2 };
+ }
+
+ public CesiumUIntVec3 this[int index]
+ {
+ get
+ {
+ switch (index)
+ {
+ case 0:
+ return this.value[0];
+ case 1:
+ return this.value[1];
+ case 2:
+ return this.value[2];
+ default:
+ throw new System.IndexOutOfRangeException();
+ }
+ }
+ }
+ }
+
+ ///
+ /// Represents a mat4x4 with unsigned integer components. This preserves the accuracy of the integer
+ /// values, which could otherwise lose precision if represented as doubles.
+ ///
+ ///
+ /// Internally, this is used to store all unsigned integer mat types, including u8mat4x4,
+ /// u16mat4x4, u32mat4x4, and u64mat4x4. The intended type is conveyed through CesiumMetadataComponentType.
+ ///
+ internal struct CesiumUIntMat4x4
+ {
+ public CesiumMetadataComponentType componentType { get; }
+
+ private CesiumUIntVec4[] value { get; }
+
+ public CesiumUIntMat4x4(CesiumUIntVec4 v0, CesiumUIntVec4 v1, CesiumUIntVec4 v2, CesiumUIntVec4 v3)
+ {
+ Debug.Assert(v0.componentType == v1.componentType && v1.componentType == v2.componentType && v2.componentType == v3.componentType);
+ this.componentType = v0.componentType;
+ this.value = new CesiumUIntVec4[] { v0, v1, v2, v3 };
+ }
+
+ public CesiumUIntVec4 this[int index]
+ {
+ get
+ {
+ switch (index)
+ {
+ case 0:
+ return this.value[0];
+ case 1:
+ return this.value[1];
+ case 2:
+ return this.value[2];
+ case 3:
+ return this.value[3];
+ default:
+ throw new System.IndexOutOfRangeException();
+ }
+ }
+ }
+ }
+ #endregion
+
///
/// Represents the value type of a metadata value or property, akin to the
/// property types in EXT_structural_metadata.
///
public struct CesiumMetadataValueType
{
+ #region Fields
///
/// The type of the metadata property or value.
///
@@ -63,7 +710,9 @@ public struct CesiumMetadataValueType
/// specified types.
///
public bool isArray;
+ #endregion
+ #region Constructor
///
/// Constructs a metadata value type from the given parameters.
///
@@ -77,7 +726,9 @@ public CesiumMetadataValueType(
this.componentType = componentType;
this.isArray = isArray;
}
+ #endregion
+ #region Static methods
public static CesiumMetadataValueType GetValueType(System.Object inObject)
{
if (inObject == null)
@@ -93,9 +744,9 @@ public static CesiumMetadataValueType GetValueType(System.Object inObject)
switch (inObject)
{
- case Boolean:
+ case System.Boolean:
return new CesiumMetadataValueType(CesiumMetadataType.Boolean, CesiumMetadataComponentType.None, false);
- case SByte:
+ case System.SByte:
return new CesiumMetadataValueType(CesiumMetadataType.Scalar, CesiumMetadataComponentType.Int8, false);
case Byte:
return new CesiumMetadataValueType(CesiumMetadataType.Scalar, CesiumMetadataComponentType.Uint8, false);
@@ -141,6 +792,18 @@ public static CesiumMetadataValueType GetValueType(System.Object inObject)
return new CesiumMetadataValueType(CesiumMetadataType.Mat3, CesiumMetadataComponentType.Int32, false);
case int4x4:
return new CesiumMetadataValueType(CesiumMetadataType.Mat4, CesiumMetadataComponentType.Int32, false);
+ case CesiumIntVec2:
+ return new CesiumMetadataValueType(CesiumMetadataType.Vec2, (inObject as CesiumIntVec2?).Value.componentType, false);
+ case CesiumIntVec3:
+ return new CesiumMetadataValueType(CesiumMetadataType.Vec3, (inObject as CesiumIntVec3?).Value.componentType, false);
+ case CesiumIntVec4:
+ return new CesiumMetadataValueType(CesiumMetadataType.Vec4, (inObject as CesiumIntVec4?).Value.componentType, false);
+ case CesiumUIntVec2:
+ return new CesiumMetadataValueType(CesiumMetadataType.Vec2, (inObject as CesiumUIntVec2?).Value.componentType, false);
+ case CesiumUIntVec3:
+ return new CesiumMetadataValueType(CesiumMetadataType.Vec3, (inObject as CesiumUIntVec3?).Value.componentType, false);
+ case CesiumUIntVec4:
+ return new CesiumMetadataValueType(CesiumMetadataType.Vec4, (inObject as CesiumUIntVec4?).Value.componentType, false);
case uint2x2:
return new CesiumMetadataValueType(CesiumMetadataType.Mat2, CesiumMetadataComponentType.Uint32, false);
case uint3x3:
@@ -159,11 +822,24 @@ public static CesiumMetadataValueType GetValueType(System.Object inObject)
return new CesiumMetadataValueType(CesiumMetadataType.Mat3, CesiumMetadataComponentType.Float64, false);
case double4x4:
return new CesiumMetadataValueType(CesiumMetadataType.Mat4, CesiumMetadataComponentType.Float64, false);
- case String:
+ case CesiumIntMat2x2:
+ return new CesiumMetadataValueType(CesiumMetadataType.Mat2, (inObject as CesiumIntMat2x2?).Value.componentType, false);
+ case CesiumIntMat3x3:
+ return new CesiumMetadataValueType(CesiumMetadataType.Mat3, (inObject as CesiumIntMat3x3?).Value.componentType, false);
+ case CesiumIntMat4x4:
+ return new CesiumMetadataValueType(CesiumMetadataType.Mat4, (inObject as CesiumIntMat4x4?).Value.componentType, false);
+ case CesiumUIntMat2x2:
+ return new CesiumMetadataValueType(CesiumMetadataType.Mat2, (inObject as CesiumUIntMat2x2?).Value.componentType, false);
+ case CesiumUIntMat3x3:
+ return new CesiumMetadataValueType(CesiumMetadataType.Mat3, (inObject as CesiumUIntMat3x3?).Value.componentType, false);
+ case CesiumUIntMat4x4:
+ return new CesiumMetadataValueType(CesiumMetadataType.Mat4, (inObject as CesiumUIntMat4x4?).Value.componentType, false);
+ case System.String:
return new CesiumMetadataValueType(CesiumMetadataType.String, CesiumMetadataComponentType.None, false);
default:
return new CesiumMetadataValueType();
}
}
+ #endregion
}
}
diff --git a/Runtime/CesiumPropertyTableProperty.cs b/Runtime/CesiumPropertyTableProperty.cs
index 45f318e4..d2001770 100644
--- a/Runtime/CesiumPropertyTableProperty.cs
+++ b/Runtime/CesiumPropertyTableProperty.cs
@@ -794,7 +794,7 @@ internal CesiumPropertyTableProperty()
// int4, uint4, Vector4, double4,
// int2x2, uint2x2, float2x2, double2x2
// int3x3, uint3x3, float3x3, double3x3,
- // int4x4, uint4x4, Matrix4x4, double4x4
+ // int4x4, uint4x4, float4x4, double4x4
///
/// Attempts to retrieve the value for the given feature as a String.
@@ -823,6 +823,40 @@ internal CesiumPropertyTableProperty()
/// The default value to fall back on.
/// The property value as a String.
public partial String GetString(Int64 featureID, String defaultValue = "");
+
+ ///
+ /// Retrieves the value of the property for the given feature as a
+ /// . This allows the value to be acted on more
+ /// generically; its true value can be retrieved later as a specific Blueprints type.
+ ///
+ ///
+ /// For numeric properties, the raw value for a given feature will be
+ /// transformed by the property's normalization, scale, and offset before it is
+ /// returned. If the raw value is equal to the property's "no data" value, an
+ /// empty value will be returned. However, if the property itself specifies a
+ /// default value, then the property-defined default value will be returned.
+ ///
+ /// The ID of the feature.
+ /// The property value.
+ //public partial CesiumMetadataValue GetValue(Int64 featureID);
+
+ ///
+ /// Retrieves the raw value of the property for the given feature. This is the
+ /// value of the property without normalization, offset, or scale applied.
+ ///
+ ///
+ ///
+ /// If this property specifies a "no data" value, and the raw value is equal to
+ /// this "no data" value, the value is returned as-is.
+ ///
+ ///
+ /// If this property is an empty property with a specified default value, it
+ /// will not have any raw data to retrieve. The returned value will be empty.
+ ///
+ ///
+ /// The ID of the feature.
+ /// The property value.
+ //public partial CesiumMetadataValue GetRawValue(Int64 featureID);
#endregion
}
}
diff --git a/Runtime/ConfigureReinterop.cs b/Runtime/ConfigureReinterop.cs
index df4da636..9b5dba6f 100644
--- a/Runtime/ConfigureReinterop.cs
+++ b/Runtime/ConfigureReinterop.cs
@@ -547,7 +547,31 @@ Cesium3DTilesetLoadFailureDetails tilesetDetails
array.values = new CesiumMetadataValue[10];
array.values[0] = new CesiumMetadataValue();
- CesiumMetadataValue myValue = new CesiumMetadataValue(0);
+ CesiumMetadataValue myValue = new CesiumMetadataValue();
+ myValue = new CesiumMetadataValue(0);
+ valueType = myValue.valueType;
+
+ System.Object myObject = myValue.valueImpl;
+
+ CesiumMetadataValue.GetObjectAsBoolean(myObject);
+ CesiumMetadataValue.GetObjectAsSByte(myObject);
+ CesiumMetadataValue.GetObjectAsByte(myObject);
+ CesiumMetadataValue.GetObjectAsInt16(myObject);
+ CesiumMetadataValue.GetObjectAsUInt16(myObject);
+ CesiumMetadataValue.GetObjectAsInt32(myObject);
+ CesiumMetadataValue.GetObjectAsUInt32(myObject);
+ CesiumMetadataValue.GetObjectAsInt64(myObject);
+ CesiumMetadataValue.GetObjectAsUInt64(myObject);
+ CesiumMetadataValue.GetObjectAsFloat(myObject);
+ CesiumMetadataValue.GetObjectAsDouble(myObject);
+ CesiumMetadataValue.GetObjectAsFloat2(myObject);
+ CesiumMetadataValue.GetObjectAsFloat3(myObject);
+ CesiumMetadataValue.GetObjectAsFloat4(myObject);
+ CesiumMetadataValue.GetObjectAsDouble2(myObject);
+ CesiumMetadataValue.GetObjectAsDouble3(myObject);
+ CesiumMetadataValue.GetObjectAsDouble4(myObject);
+ CesiumMetadataValue.GetObjectAsString(myObject);
+
int2 myInt2 = new int2(1, 2);
uint2 myUint2 = new uint2(1, 2);
float2 myFloat2 = new float2(1, 2);
@@ -564,12 +588,12 @@ Cesium3DTilesetLoadFailureDetails tilesetDetails
sets[0].propertyTableIndex = 0;
CesiumFeatureIdSetType setType = CesiumFeatureIdSetType.None;
- CesiumFeatureIdAttribute attribute = new CesiumFeatureIdAttribute();
- attribute.status = attribute.status;
- attribute.featureCount = 1;
- attribute.label = "label";
- attribute.nullFeatureId = 0;
- attribute.propertyTableIndex = 0;
+ CesiumFeatureIdAttribute featureIdAttribute = new CesiumFeatureIdAttribute();
+ featureIdAttribute.status = featureIdAttribute.status;
+ featureIdAttribute.featureCount = 1;
+ featureIdAttribute.label = "label";
+ featureIdAttribute.nullFeatureId = 0;
+ featureIdAttribute.propertyTableIndex = 0;
CesiumFeatureIdTexture featureIdTexture = new CesiumFeatureIdTexture();
featureIdTexture.status = featureIdTexture.status;
@@ -578,7 +602,7 @@ Cesium3DTilesetLoadFailureDetails tilesetDetails
featureIdTexture.nullFeatureId = 0;
featureIdTexture.propertyTableIndex = 0;
- primitiveFeatures.featureIdSets[0] = attribute;
+ primitiveFeatures.featureIdSets[0] = featureIdAttribute;
primitiveFeatures.featureIdSets[1] = featureIdTexture;
RaycastHit hitInfo = new RaycastHit();
diff --git a/Tests/TestCesiumMetadataValue.cs b/Tests/TestCesiumMetadataValue.cs
index d3c7e303..1e5b5058 100644
--- a/Tests/TestCesiumMetadataValue.cs
+++ b/Tests/TestCesiumMetadataValue.cs
@@ -1,6 +1,7 @@
using CesiumForUnity;
using NUnit.Framework;
using System;
+using Unity.Mathematics;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.TestTools;
@@ -8,6 +9,7 @@
public class TestCesiumMetadataValue
{
+ #region Constructor
[Test]
public void ConstructsEmptyValue()
{
@@ -43,4 +45,207 @@ public void ConstructsScalarValue()
Assert.That(valueType.componentType, Is.EqualTo(CesiumMetadataComponentType.Uint16));
Assert.That(valueType.isArray, Is.False);
}
+
+ [Test]
+ public void ConstructsVecNValue()
+ {
+ CesiumMetadataValue value = new CesiumMetadataValue(new int2(1, 1));
+ Assert.That(value.isEmpty, Is.False);
+
+ CesiumMetadataValueType valueType = value.valueType;
+ Assert.That(valueType.type, Is.EqualTo(CesiumMetadataType.Vec2));
+ Assert.That(valueType.componentType, Is.EqualTo(CesiumMetadataComponentType.Int32));
+ Assert.That(valueType.isArray, Is.False);
+ }
+
+ [Test]
+ public void ConstructsMatNValue()
+ {
+ CesiumMetadataValue value = new CesiumMetadataValue(new uint2x2(1, 2, 3, 1));
+ Assert.That(value.isEmpty, Is.False);
+
+ CesiumMetadataValueType valueType = value.valueType;
+ Assert.That(valueType.type, Is.EqualTo(CesiumMetadataType.Mat2));
+ Assert.That(valueType.componentType, Is.EqualTo(CesiumMetadataComponentType.Uint32));
+ Assert.That(valueType.isArray, Is.False);
+ }
+
+ [Test]
+ public void ConstructsStringValue()
+ {
+ CesiumMetadataValue value = new CesiumMetadataValue("string");
+ Assert.That(value.isEmpty, Is.False);
+
+ CesiumMetadataValueType valueType = value.valueType;
+ Assert.That(valueType.type, Is.EqualTo(CesiumMetadataType.String));
+ Assert.That(valueType.componentType, Is.EqualTo(CesiumMetadataComponentType.None));
+ Assert.That(valueType.isArray, Is.False);
+ }
+
+ #endregion
+
+ #region GetBoolean
+ [Test]
+ public void GetBooleanReturnsBooleanValue()
+ {
+ CesiumMetadataValue value = new CesiumMetadataValue(true);
+ Assert.That(value.GetBoolean(), Is.True);
+ }
+
+ [Test]
+ public void GetsBooleanConvertsScalarValue()
+ {
+ CesiumMetadataValue value = new CesiumMetadataValue(1234);
+ Assert.That(value.GetBoolean(), Is.True);
+
+ value = new CesiumMetadataValue(0);
+ Assert.That(value.GetBoolean(), Is.False);
+ }
+
+ [Test]
+ public void GetBooleanConvertsStringValue()
+ {
+ CesiumMetadataValue value = new CesiumMetadataValue("true");
+ Assert.That(value.GetBoolean(), Is.True);
+
+ value = new CesiumMetadataValue("false");
+ Assert.That(value.GetBoolean(), Is.False);
+
+ value = new CesiumMetadataValue("yes");
+ Assert.That(value.GetBoolean(), Is.True);
+
+ value = new CesiumMetadataValue("no");
+ Assert.That(value.GetBoolean(), Is.False);
+
+ value = new CesiumMetadataValue("1");
+ Assert.That(value.GetBoolean(), Is.True);
+
+ value = new CesiumMetadataValue("0");
+ Assert.That(value.GetBoolean(), Is.False);
+ }
+
+ [Test]
+ public void GetBooleanReturnsDefaultValueForInvalidStrings()
+ {
+ CesiumMetadataValue value = new CesiumMetadataValue("I am true");
+ Assert.That(value.GetBoolean(), Is.False);
+
+ value = new CesiumMetadataValue("11");
+ Assert.That(value.GetBoolean(), Is.False);
+ }
+
+ [Test]
+ public void GetBooleanReturnsDefaultValueForUnsupportedTypes()
+ {
+ CesiumMetadataValue value = new CesiumMetadataValue();
+ Assert.That(value.GetBoolean(true), Is.True);
+
+ value = new CesiumMetadataValue(new int2(1, 1));
+ Assert.That(value.GetBoolean(false), Is.False);
+
+ value = new CesiumMetadataValue(new CesiumPropertyArray());
+ Assert.That(value.GetBoolean(false), Is.False);
+ }
+ #endregion
+
+ #region GetSByte
+ [Test]
+ public void GetSByteReturnsInRangeValues()
+ {
+ CesiumMetadataValue value = new CesiumMetadataValue((SByte)126);
+ Assert.That(value.GetSByte(), Is.EqualTo(126));
+
+ value = new CesiumMetadataValue((Int32)(-127));
+ Assert.That(value.GetSByte(), Is.EqualTo(-127));
+ }
+
+ [Test]
+ public void GetSByteConvertsBooleanValue()
+ {
+ CesiumMetadataValue value = new CesiumMetadataValue(true);
+ Assert.That(value.GetSByte(-1), Is.EqualTo(1));
+
+ value = new CesiumMetadataValue(0);
+ Assert.That(value.GetSByte(-1), Is.EqualTo(0));
+ }
+
+ [Test]
+ public void GetSByteConvertsStringValue()
+ {
+ CesiumMetadataValue value = new CesiumMetadataValue("123");
+ Assert.That(value.GetSByte(), Is.EqualTo(123));
+ }
+
+ [Test]
+ public void GetSByteReturnsDefaultValueForOutOfRangeNumbers()
+ {
+ CesiumMetadataValue value = new CesiumMetadataValue(123456);
+ Assert.That(value.GetSByte(), Is.EqualTo(0));
+
+ value = new CesiumMetadataValue(-129);
+ Assert.That(value.GetSByte(), Is.EqualTo(0));
+ }
+
+ [Test]
+ public void GetSByteReturnsDefaultValueForInvalidStrings()
+ {
+ CesiumMetadataValue value = new CesiumMetadataValue("123456");
+ Assert.That(value.GetSByte(), Is.EqualTo(0));
+
+ value = new CesiumMetadataValue("NaN");
+ Assert.That(value.GetSByte(), Is.EqualTo(0));
+ }
+
+ [Test]
+ public void GetSByteReturnsDefaultValueForUnsupportedTypes()
+ {
+ CesiumMetadataValue value = new CesiumMetadataValue();
+ Assert.That(value.GetSByte(0), Is.EqualTo(0));
+
+ value = new CesiumMetadataValue(new int2(1, 1));
+ Assert.That(value.GetSByte(), Is.EqualTo(0));
+
+ value = new CesiumMetadataValue(new CesiumPropertyArray());
+ Assert.That(value.GetSByte(), Is.EqualTo(0));
+ }
+ #endregion
+
+ #region GetString
+ [Test]
+ public void GetStringReturnsStringValue()
+ {
+ String str = "string";
+ CesiumMetadataValue value = new CesiumMetadataValue(str);
+ Assert.That(value.GetString(), Is.EqualTo(str));
+ }
+
+
+ [Test]
+ public void GetStringConvertsBooleanValue()
+ {
+ CesiumMetadataValue value = new CesiumMetadataValue(true);
+ Assert.That(value.GetString(), Is.EqualTo("true"));
+
+ value = new CesiumMetadataValue(false);
+ Assert.That(value.GetString(), Is.EqualTo("false"));
+ }
+
+ [Test]
+ public void GetStringConvertsScalarValue()
+ {
+ CesiumMetadataValue value = new CesiumMetadataValue(1234);
+ Assert.That(value.GetString(), Is.EqualTo("1234"));
+ }
+
+ [Test]
+ public void GetStringReturnsDefaultValueForUnsupportedTypes()
+ {
+ String defaultValue = "default";
+ CesiumMetadataValue value = new CesiumMetadataValue();
+ Assert.That(value.GetString(defaultValue), Is.EqualTo(defaultValue));
+
+ value = new CesiumMetadataValue(new CesiumPropertyArray());
+ Assert.That(value.GetString(defaultValue), Is.EqualTo(defaultValue));
+ }
+ #endregion
}
diff --git a/native~/Runtime/src/CesiumMetadataValueImpl.cpp b/native~/Runtime/src/CesiumMetadataValueImpl.cpp
index 7fc394cb..f664a277 100644
--- a/native~/Runtime/src/CesiumMetadataValueImpl.cpp
+++ b/native~/Runtime/src/CesiumMetadataValueImpl.cpp
@@ -1,5 +1,139 @@
-//#include "CesiumMetadataValueImpl.h"
-//
-//DotNet::System::String CesiumMetadataValueImpl::GetString(
-// const DotNet::CesiumForUnity::CesiumMetadataValue& value,
-// DotNet::System::String defaultValue) {}
+#include "CesiumMetadataValueImpl.h"
+
+#include
+
+#include
+#include
+#include
+
+#include
+
+using namespace CesiumGltf;
+using namespace DotNet;
+using namespace DotNet::CesiumForUnity;
+
+namespace CesiumForUnityNative {
+
+namespace {
+
+CesiumMetadataValueImpl::ValueType getNativeBooleanValue(
+ const DotNet::CesiumForUnity::CesiumMetadataValue& value) {
+ std::optional maybeBoolean =
+ CesiumForUnity::CesiumMetadataValue::GetObjectAsBoolean(
+ value.valueImpl());
+ if (maybeBoolean) {
+ return *maybeBoolean;
+ }
+
+ return std::monostate();
+}
+
+template
+CesiumMetadataValueImpl::ValueType
+getNativeScalarValue(const DotNet::System::Object& object) {
+ std::optional maybeValue;
+ if constexpr (std::is_same_v) {
+ maybeValue = CesiumMetadataValue::GetObjectAsSByte(object);
+ } else if constexpr (std::is_same_v) {
+ maybeValue = CesiumMetadataValue::GetObjectAsByte(object);
+ } else if constexpr (std::is_same_v) {
+ maybeValue = CesiumMetadataValue::GetObjectAsInt16(object);
+ } else if constexpr (std::is_same_v) {
+ maybeValue = CesiumMetadataValue::GetObjectAsUInt16(object);
+ } else if constexpr (std::is_same_v) {
+ maybeValue = CesiumMetadataValue::GetObjectAsInt32(object);
+ } else if constexpr (std::is_same_v) {
+ maybeValue = CesiumMetadataValue::GetObjectAsUInt32(object);
+ } else if constexpr (std::is_same_v) {
+ maybeValue = CesiumMetadataValue::GetObjectAsInt64(object);
+ } else if constexpr (std::is_same_v) {
+ maybeValue = CesiumMetadataValue::GetObjectAsUInt64(object);
+ } else if constexpr (std::is_same_v) {
+ maybeValue = CesiumMetadataValue::GetObjectAsFloat(object);
+ } else if constexpr (std::is_same_v) {
+ maybeValue = CesiumMetadataValue::GetObjectAsDouble(object);
+ }
+
+ if (maybeValue) {
+ return *maybeValue;
+ }
+
+ return std::monostate();
+}
+
+CesiumMetadataValueImpl::ValueType
+getNativeScalarValue(const DotNet::CesiumForUnity::CesiumMetadataValue& value) {
+ CesiumMetadataValueType valueType = value.valueType();
+ assert(valueType.type == CesiumMetadataType::Scalar);
+ switch (valueType.componentType) {
+ case CesiumMetadataComponentType::Int8:
+ return getNativeScalarValue(value.valueImpl());
+ case CesiumMetadataComponentType::Uint8:
+ return getNativeScalarValue(value.valueImpl());
+ case CesiumMetadataComponentType::Int16:
+ return getNativeScalarValue(value.valueImpl());
+ case CesiumMetadataComponentType::Uint16:
+ return getNativeScalarValue(value.valueImpl());
+ case CesiumMetadataComponentType::Int32:
+ return getNativeScalarValue(value.valueImpl());
+ case CesiumMetadataComponentType::Uint32:
+ return getNativeScalarValue(value.valueImpl());
+ case CesiumMetadataComponentType::Int64:
+ return getNativeScalarValue(value.valueImpl());
+ case CesiumMetadataComponentType::Uint64:
+ return getNativeScalarValue(value.valueImpl());
+ case CesiumMetadataComponentType::Float32:
+ return getNativeScalarValue(value.valueImpl());
+ case CesiumMetadataComponentType::Float64:
+ return getNativeScalarValue(value.valueImpl());
+ default:
+ return std::monostate();
+ }
+}
+
+CesiumMetadataValueImpl::ValueType
+getNativeStringValue(const DotNet::CesiumForUnity::CesiumMetadataValue& value) {
+ DotNet::System::String string =
+ CesiumForUnity::CesiumMetadataValue::GetObjectAsString(value.valueImpl());
+ if (string == nullptr) {
+ return std::monostate();
+ }
+
+ return string.ToStlString();
+}
+
+} // namespace
+
+/*static*/ CesiumMetadataValueImpl::ValueType
+CesiumMetadataValueImpl::getNativeValue(
+ const DotNet::CesiumForUnity::CesiumMetadataValue& value) {
+ CesiumForUnity::CesiumMetadataValueType valueType = value.valueType();
+ switch (valueType.type) {
+ case CesiumForUnity::CesiumMetadataType::Boolean:
+ return getNativeBooleanValue(value);
+ case CesiumForUnity::CesiumMetadataType::Scalar:
+ return getNativeScalarValue(value);
+ case CesiumForUnity::CesiumMetadataType::String:
+ return getNativeStringValue(value);
+ default:
+ return std::monostate();
+ }
+}
+
+/*static*/ bool CesiumMetadataValueImpl::ConvertToBoolean(
+ const DotNet::CesiumForUnity::CesiumMetadataValue& value,
+ bool defaultValue) {
+ ValueType nativeValue = getNativeValue(value);
+ return std::visit(
+ [&defaultValue](auto trueValue) -> bool {
+ if constexpr (std::is_same_v) {
+ return defaultValue;
+ } else {
+ return MetadataConversions::convert(
+ trueValue)
+ .value_or(defaultValue);
+ }
+ },
+ nativeValue);
+}
+} // namespace CesiumForUnityNative
diff --git a/native~/Runtime/src/CesiumMetadataValueImpl.h b/native~/Runtime/src/CesiumMetadataValueImpl.h
index 5cc98142..67430e42 100644
--- a/native~/Runtime/src/CesiumMetadataValueImpl.h
+++ b/native~/Runtime/src/CesiumMetadataValueImpl.h
@@ -1,20 +1,112 @@
-//#pragma once
-//
-//namespace DotNet::CesiumForUnity {
-//class CesiumMetadataValue;
-//} // namespace DotNet::CesiumForUnity
-//
-//namespace DotNet::System {
-//class String;
-//}
-//
-//namespace CesiumForUnityNative {
-//
-//class CesiumMetadataValueImpl {
-//
-//public:
-// static DotNet::System::String GetString(
-// const DotNet::CesiumForUnity::CesiumMetadataValue& value,
-// DotNet::System::String defaultValue);
-//};
-//} // namespace CesiumForUnityNative
+#pragma once
+
+#include
+#include
+
+#include
+
+namespace DotNet::CesiumForUnity {
+class CesiumMetadataValue;
+} // namespace DotNet::CesiumForUnity
+
+namespace DotNet::System {
+class String;
+class Object;
+} // namespace DotNet::System
+
+namespace CesiumForUnityNative {
+
+class CesiumMetadataValueImpl {
+public:
+#pragma region ValueType declaration
+ // This definition excludes arrays because those are handled in C#.
+ using ValueType = std::variant<
+ std::monostate,
+ int8_t,
+ uint8_t,
+ int16_t,
+ uint16_t,
+ int32_t,
+ uint32_t,
+ int64_t,
+ uint64_t,
+ float,
+ double,
+ bool,
+ std::string,
+ glm::vec<2, int8_t>,
+ glm::vec<2, uint8_t>,
+ glm::vec<2, int16_t>,
+ glm::vec<2, uint16_t>,
+ glm::vec<2, int32_t>,
+ glm::vec<2, uint32_t>,
+ glm::vec<2, int64_t>,
+ glm::vec<2, uint64_t>,
+ glm::vec<2, float>,
+ glm::vec<2, double>,
+ glm::vec<3, int8_t>,
+ glm::vec<3, uint8_t>,
+ glm::vec<3, int16_t>,
+ glm::vec<3, uint16_t>,
+ glm::vec<3, int32_t>,
+ glm::vec<3, uint32_t>,
+ glm::vec<3, int64_t>,
+ glm::vec<3, uint64_t>,
+ glm::vec<3, float>,
+ glm::vec<3, double>,
+ glm::vec<4, int8_t>,
+ glm::vec<4, uint8_t>,
+ glm::vec<4, int16_t>,
+ glm::vec<4, uint16_t>,
+ glm::vec<4, int32_t>,
+ glm::vec<4, uint32_t>,
+ glm::vec<4, int64_t>,
+ glm::vec<4, uint64_t>,
+ glm::vec<4, float>,
+ glm::vec<4, double>,
+ glm::mat<2, 2, int8_t>,
+ glm::mat<2, 2, uint8_t>,
+ glm::mat<2, 2, int16_t>,
+ glm::mat<2, 2, uint16_t>,
+ glm::mat<2, 2, int32_t>,
+ glm::mat<2, 2, uint32_t>,
+ glm::mat<2, 2, int64_t>,
+ glm::mat<2, 2, uint64_t>,
+ glm::mat<2, 2, float>,
+ glm::mat<2, 2, double>,
+ glm::mat<3, 3, int8_t>,
+ glm::mat<3, 3, uint8_t>,
+ glm::mat<3, 3, int16_t>,
+ glm::mat<3, 3, uint16_t>,
+ glm::mat<3, 3, int32_t>,
+ glm::mat<3, 3, uint32_t>,
+ glm::mat<3, 3, int64_t>,
+ glm::mat<3, 3, uint64_t>,
+ glm::mat<3, 3, float>,
+ glm::mat<3, 3, double>,
+ glm::mat<4, 4, int8_t>,
+ glm::mat<4, 4, uint8_t>,
+ glm::mat<4, 4, int16_t>,
+ glm::mat<4, 4, uint16_t>,
+ glm::mat<4, 4, int32_t>,
+ glm::mat<4, 4, uint32_t>,
+ glm::mat<4, 4, int64_t>,
+ glm::mat<4, 4, uint64_t>,
+ glm::mat<4, 4, float>,
+ glm::mat<4, 4, double>>;
+#pragma endregion
+
+ static bool ConvertToBoolean(
+ const DotNet::CesiumForUnity::CesiumMetadataValue& value,
+ bool defaultValue);
+
+private:
+ /**
+ * Retrieves the value from the System.Object in the C#
+ * class implementation as a C++-compatible type. std::monostate is used to
+ * indicate a null value.
+ */
+ static ValueType
+ getNativeValue(const DotNet::CesiumForUnity::CesiumMetadataValue& value);
+};
+} // namespace CesiumForUnityNative
diff --git a/native~/Runtime/src/CesiumPropertyTablePropertyImpl.h b/native~/Runtime/src/CesiumPropertyTablePropertyImpl.h
index 452db44e..1dbf4c50 100644
--- a/native~/Runtime/src/CesiumPropertyTablePropertyImpl.h
+++ b/native~/Runtime/src/CesiumPropertyTablePropertyImpl.h
@@ -15,7 +15,8 @@ class CesiumPropertyTablePropertyImpl;
namespace DotNet::CesiumForUnity {
class CesiumPropertyTableProperty;
-}
+class CesiumMetadataValue;
+} // namespace DotNet::CesiumForUnity
namespace DotNet::System {
class String;
@@ -26,6 +27,14 @@ class int2;
class uint2;
class float2;
class double2;
+class int3;
+class uint3;
+class float3;
+class double3;
+class int4;
+class uint4;
+class float4;
+class double4;
} // namespace DotNet::Unity::Mathematics
namespace CesiumForUnityNative {
@@ -122,6 +131,10 @@ class CesiumPropertyTablePropertyImpl {
std::int64_t featureID,
const DotNet::System::String& defaultValue);
+ //DotNet::CesiumForUnity::CesiumMetadataValue GetValue(
+ // const DotNet::CesiumForUnity::CesiumPropertyTableProperty& property,
+ // std::int64_t featureID);
+
private:
std::any _property;
};