# Utility extensions

<Badge tone="type">static class</Badge> <Badge>extension helpers</Badge>

This page groups the SDK's broadly-used helper types: the `Extensions` static class (identification, camera-info accessors, Core↔Unity math conversion, logging) and four standalone utilities — `ObjectFieldExtensions`, `TextureExtensions`, `AnimationTimer`, and `BiDictionary<T1,T2>`.

:::note[Units]
All spatial conversions on this page are in **meters** (Unity world-space). The `ToUnity`/`ToCore` helpers convert between AR 51 `Core` math types and Unity types without rescaling — both sides are meters.
:::

## Extensions

<Badge tone="type">static class</Badge>

```csharp
public static class Extensions
```

**Namespace:** `AR51.Unity.SDK`

The SDK's broadly-used extension helpers. This page documents the members app developers call: skeleton identification, camera-info accessors, `Core`↔Unity math conversion, and logging. Array/marshalling helpers (`ToArray`, `ToVector3`, `ToMatrix4x4`, `ToVector3Array`, `ToMatrix4x4Array`, `EfficientReverse`, `ReadExact`, …) are also public but are low-level transport plumbing.

### IsIdentified

<ApiBody kind="method" tags="static, extension">

```csharp
public static bool IsIdentified(this SkeletonReply skeletonReply);
```

Returns `true` when the skeleton has been matched to a known entity — i.e. its `EntityId` is non-null, non-empty, and not `"-1"`. Use it to filter to recognized people; [`SkeletonConsumer`](/docs/sdk-api/unity-api/classes/skeletonconsumer)'s `IgnoreUnidentified` uses this internally.

<Returns type="bool">`true` if the skeleton is matched to a known entity</Returns>

<Example inferred>

```csharp
// Only react to recognized people
if (skeletonReply.IsIdentified())
    DoSomethingWith(skeletonReply.EntityId);
```

</Example>

</ApiBody>

### GetEndpoint

<ApiBody kind="method" tags="static, extension">

```csharp
public static string GetEndpoint(this ComponentDescriptor c);
```

Formats a component descriptor's address as `"ip:port"` — the string form the services connect with.

<Returns type="string">the endpoint as `"ip:port"`</Returns>

</ApiBody>

### Camera-info accessors

<ApiBody kind="method" tags="static, extension">

```csharp
public static Matrix4x4 GetIntrisic(this CvsCameraInfo info);     // intrinsic 4x4
public static Matrix4x4 GetExtrinsic(this CvsCameraInfo info);    // extrinsic (world pose), handedness-corrected
public static float     GetVerticalFOV(this CvsCameraInfo info);  // degrees
public static float     GetHorizontalFOV(this CvsCameraInfo info);// degrees
```

Derive the usable camera matrices and field-of-view from a [`CvsCameraInfo`](/docs/sdk-api/unity-api/classes/camerafeedclient). `GetExtrinsic` returns the camera's world pose with handedness already corrected for Unity; the FOV accessors return **degrees**.

</ApiBody>

### Core ↔ Unity conversion

<ApiBody kind="method" tags="static, extension">

```csharp
// Core → Unity (positions in meters)
public static Vector3    ToUnity(this AR51.Mocap.Filters.Double3 v);  // meters, double→float
public static Color      ToUnity(this Core.Color color);
public static Vector2    ToUnity(this Core.Vector2 v);
public static Vector3    ToUnity(this Core.Vector3 v);
public static Quaternion ToUnity(this Core.Quaternion v);
public static Bounds     ToUnity(this Bound2D bounds);

// Unity → Core
public static Core.Color      ToCore(this Color c);
public static Core.Vector2    ToCore(this Vector2 v);
public static Core.Vector3    ToCore(this Vector3 v);
public static Core.Vector4    ToCore(this Vector4 v);
public static Core.Quaternion ToCore(this Quaternion q);

// Color helpers
public static Color Parse(this Color _, string colorName);  // named CSS-ish colors → Color (Color.clear if unknown)
public static Color FromUInt(this Color _, uint hex);       // 0xAARRGGBB → Color
```

Convert between AR 51 `Core` math types and Unity types. Positions are in **meters** on both sides — no rescaling is applied. `Parse` maps a named color (returning `Color.clear` if the name is unknown); `FromUInt` builds a color from a packed `0xAARRGGBB` value.

<Example inferred>

```csharp
// Core mocap position → Unity world-space (meters)
Vector3 wrist = coreWrist.ToUnity();

// Packed hex → Color
Color accent = default(Color).FromUInt(0xFF33AAFF);   // ARGB
```

</Example>

</ApiBody>

### Log / LogWarning / LogError

<ApiBody kind="method" tags="static, extension">

```csharp
public static void Log(this object sender, string msg, /* [Caller*] */ ...);
public static void LogWarning(this object sender, string msg, ...);
public static void LogError(this object sender, string msg, ...);
public static void Log(this MonoBehaviour sender, string msg, ...);
```

Context-aware logging extensions. They auto-prefix each message with `File.Method[line]` (captured via `[Caller*]` attributes) — prefer them over hand-written context strings. Available on any `object` (and a `MonoBehaviour` overload).

<Example inferred>

```csharp
this.Log("connected");          // → "MyBehaviour.Start[42] connected"
this.LogError("stream dropped");
```

</Example>

</ApiBody>

## ObjectFieldExtensions

<Badge tone="type">static class</Badge>

```csharp
public static class ObjectFieldExtensions
```

**Namespace:** `AR51.Unity.SDK`

Reflection get/set of a field **or** property by name. Includes non-public members by default (`DefaultFlags = BindingFlags.NonPublic | BindingFlags.Public`).

```csharp
public const BindingFlags DefaultFlags = BindingFlags.NonPublic | BindingFlags.Public;
public static T    GetValue<T>(this object owner, string fieldName, BindingFlags flags = DefaultFlags);
public static void SetValue(this object owner, string fieldName, object value, BindingFlags flags = DefaultFlags);
```

⚠️ `GetValue` returns `default(T)` if the member isn't found (no exception); `SetValue` logs a warning on failure. Reflection-based access is for advanced/interop scenarios — prefer the typed API where one exists.

<Example inferred>

```csharp
// Read a private field by name
float smoothing = consumer.GetValue<float>("_smoothingFactor");
consumer.SetValue("_smoothingFactor", 0.9f);
```

</Example>

## TextureExtensions

<Badge tone="type">static class</Badge>

```csharp
public static class TextureExtensions
```

**Namespace:** `AR51.Unity.SDK`

GPU-assisted texture resampling and JPG encoding.

```csharp
public static Texture2D Resample(this Texture source, int width, int height,
    TextureFormat textureFormat = TextureFormat.RGBA32, bool mipChain = true, bool linear = false);
public static Texture2D ResampleTo(this Texture source, Texture2D target, RenderTexture renderTexture = null);
public static byte[]    EncodeToJPG(this Texture source, ref Texture2D target, int width, int height, int quality = 70);
```

`width`/`height` are in **pixels**; `quality` is **0–100** (default `70`). `Resample` returns a new `Texture2D`; `ResampleTo` blits into an existing `target`. `EncodeToJPG` resizes (clamped to the source dimensions) into `target` and returns the JPG bytes.

<Example inferred>

```csharp
// Resize a camera frame and encode at quality 85
Texture2D thumb = null;
byte[] jpg = cameraFrame.EncodeToJPG(ref thumb, 640, 360, quality: 85);
```

</Example>

## AnimationTimer

<Badge tone="type">class</Badge>

```csharp
public class AnimationTimer
```

**Namespace:** `AR51.Unity.SDK`

A lightweight fixed-duration timer driven by `Time.time`. Construct it with a duration in seconds, then poll `Factor`/`SmoothFactor` each frame to drive an animation.

<div className="apiPropTable">

| Member | Type | Description |
|---|---|---|
| `StartTime` | `float` | capture time when the timer was created (seconds), read-only |
| `Duration` | `float` | configured duration in **seconds**, read-only |
| `ElapsedTime` | `float` | seconds since `StartTime` |
| `Factor` | `float` | linear progress, **0–1** |
| `SmoothFactor` | `float` | smoothstep progress, **0–1** |
| `IsRunning` | `bool` | `true` while `ElapsedTime < Duration` |

</div>

```csharp
public AnimationTimer(float duration);   // duration in seconds
```

<Example inferred>

```csharp
var fade = new AnimationTimer(0.5f);   // half-second fade
// ...each frame:
material.color = Color.Lerp(from, to, fade.SmoothFactor);
if (!fade.IsRunning) { /* done */ }
```

</Example>

## BiDictionary&lt;T1,T2&gt;

<Badge tone="type">BiDictionary&lt;T1,T2&gt;</Badge> <Badge>global namespace</Badge>

```csharp
public class BiDictionary<T1, T2> : IDictionary<T1, T2>
```

**Namespace:** *global* (no namespace)

A bidirectional dictionary: look up by key in **either** direction. Implements `IDictionary<T1,T2>` plus mirrored overloads keyed by `T2`. Both the key and the value must be unique — each side is a real dictionary.

```csharp
public T2 this[T1 key] { get; set; }
public T1 this[T2 key] { get; set; }
public void Add(T1 key, T2 value);              // (+ T2 / KeyValuePair overloads, both directions)
public bool ContainsKey(T1 key);  public bool ContainsKey(T2 key);
public bool TryGetValue(T1 key, out T2 value);  public bool TryGetValue(T2 key, out T1 value);
public bool Remove(T1 key);  public bool Remove(T2 key);
public ICollection<T1> Keys { get; }  public ICollection<T2> Values { get; }
public int Count { get; }  public bool IsReadOnly { get; }
public void Clear();
```

⚠️ Because both sides are unique dictionaries, `T1` and `T2` should be distinct types — otherwise the overloads keyed by `T1` vs `T2` are ambiguous to the compiler.

<Example inferred>

```csharp
var map = new BiDictionary<string, int>();
map.Add("alice", 1);
int id   = map["alice"];   // forward
string n = map[1];          // reverse
```

</Example>

## See also

- [`SkeletonConsumer`](/docs/sdk-api/unity-api/classes/skeletonconsumer) — uses `IsIdentified` internally for `IgnoreUnidentified`
- [`CameraFeedClient`](/docs/sdk-api/unity-api/classes/camerafeedclient) — owns the `CvsCameraInfo` the camera accessors read from
- [`ServiceManager`](/docs/sdk-api/unity-api/classes/servicemanager) — resolves the `ComponentDescriptor` whose endpoint `GetEndpoint` formats
- [Recording &amp; playback](/docs/sdk-api/unity-api/classes/recording-playback) — keyframe utilities in the same area
- [Class index](/docs/sdk-api/unity-api/classes) — all Unity SDK types
