# Adapters

<Badge tone="type">C++ interfaces + template factory</Badge> <Badge>C++ only</Badge>

The adapter layer is how a platform/device integration **feeds** hand-tracking and play-area data into the SDK, and how game code **reads** it back. There are two pure-C++ interfaces — [`IHandsAdapter`](#ihandsadapter) and [`IBoundaryAdapter`](#iboundaryadapter) — and a template registry, [`AdapterFactory<TAdapter>`](#adapterfactorytadapter), with two concrete factories, [`HandsAdapterFactory`](#handsadapterfactory) and [`BoundaryAdapterFactory`](#boundaryadapterfactory).

Everything on this page is **C++ only**. None of these types is a UE `UINTERFACE` and none is Blueprint-exposed. An integration subclasses an interface and registers an instance with the matching factory; game code calls the factory's `GetAdapter()` to obtain the active adapter for the current platform.

:::caution[Units & space]
Unreal Engine uses **centimeters** for position and **degrees** for rotation; the AR 51 native domain uses **meters**. Positions returned by these adapters are documented as **UE centimeters**. ⚠️ Confirm whether the SDK converts AR 51 meters → UE cm at the adapter boundary, or whether the caller receives raw native units. For [`IBoundaryAdapter::GetPoints`](#ihandsadapter--iboundaryadapter-method-details) the exact space (world vs tracking) and whether points are 2D-on-floor or full 3D is also unverified.
:::

## IHandsAdapter

<Badge tone="type">pure C++ interface</Badge> <Badge>C++ only</Badge> <Badge>`AR51SDK_API`</Badge>

```cpp
class AR51SDK_API IHandsAdapter
```

An abstract interface a platform/device integration implements to feed hand-tracking data into the SDK. **Not** a UE `UINTERFACE` — no Blueprint exposure. Game code consumes it (typically via [`HandsAdapterFactory::GetAdapter()`](#handsadapterfactory)) and reads the per-hand joint sets. Joints are returned as [`HandJointInfo`](/docs/sdk-api/unreal-api/classes/handjointinfo) — empty or zero-confidence entries indicate no tracking.

### IHandsAdapter method summary

| Method | Returns | |
|---|---|---|
| [`GetSourceDevice`](#getsourcedevice) | `FString` | <Badge>C++ only</Badge> · virtual, has default |
| [`GetRightJointInfos`](#getrightjointinfos--getleftjointinfos) | [`TArray<HandJointInfo>`](/docs/sdk-api/unreal-api/classes/handjointinfo) | <Badge>C++ only</Badge> · pure virtual |
| [`GetLeftJointInfos`](#getrightjointinfos--getleftjointinfos) | [`TArray<HandJointInfo>`](/docs/sdk-api/unreal-api/classes/handjointinfo) | <Badge>C++ only</Badge> · pure virtual |

## IBoundaryAdapter

<Badge tone="type">pure C++ interface</Badge> <Badge>C++ only</Badge> <Badge>`AR51SDK_API`</Badge>

```cpp
class AR51SDK_API IBoundaryAdapter
```

An abstract interface that supplies the play-area / guardian boundary polygon. **Not** a UE `UINTERFACE`. Game code consumes it via [`BoundaryAdapterFactory::GetAdapter()`](#boundaryadapterfactory); an integration implements it to provide the boundary geometry for its platform.

### IBoundaryAdapter method summary

| Method | Returns | |
|---|---|---|
| [`GetBoundaryName`](#getboundaryname) | `FString` | <Badge>C++ only</Badge> · virtual, has default |
| [`GetPoints`](#getpoints) | `TArray<FVector>` | <Badge>C++ only</Badge> · pure virtual · ⚠️ UE cm |

## IHandsAdapter / IBoundaryAdapter method details

### GetSourceDevice

<ApiBody kind="method" tags="C++ only, virtual">

```cpp
virtual FString GetSourceDevice() const;
```

Name of the tracking source. The default implementation returns `"NoSource"`; override it to identify the device/backend providing hand data.

<Returns type="FString">the source device/backend name, or `"NoSource"` if not overridden</Returns>

</ApiBody>

### GetRightJointInfos / GetLeftJointInfos

<ApiBody kind="method" tags="C++ only, pure virtual">

```cpp
virtual TArray<HandJointInfo> GetRightJointInfos() = 0;
virtual TArray<HandJointInfo> GetLeftJointInfos() = 0;
```

The current right-hand and left-hand joint sets. Both are **pure virtual** — an implementation must provide them. Empty arrays or zero-confidence [`HandJointInfo`](/docs/sdk-api/unreal-api/classes/handjointinfo) entries indicate the hand is not currently tracked.

<Returns type="TArray<HandJointInfo>" typeHref="/docs/sdk-api/unreal-api/classes/handjointinfo">the joint set for that hand; empty / zero-confidence when untracked. Positions are **UE cm** ⚠️</Returns>

<Example inferred>

```cpp
if (IHandsAdapter* Hands = HandsAdapterFactory::GetAdapter())
{
    const TArray<HandJointInfo> Right = Hands->GetRightJointInfos();
    // Gate on whole-hand confidence, then read positions (UE cm):
    const TArray<FVector> Pts = HandJointInfo::GetConfidentPositions(Right, 0.5f);
    if (Pts.Num() == 0)
        UE_LOG(LogTemp, Verbose, TEXT("Right hand not confidently tracked"));
}
```

</Example>

</ApiBody>

### GetBoundaryName

<ApiBody kind="method" tags="C++ only, virtual">

```cpp
virtual FString GetBoundaryName() const;
```

Boundary identifier. The default implementation returns `"Native Default Boundary"`; override to name the boundary source.

<Returns type="FString">the boundary name, or `"Native Default Boundary"` if not overridden</Returns>

</ApiBody>

### GetPoints

<ApiBody kind="method" tags="C++ only, pure virtual">

```cpp
virtual TArray<FVector> GetPoints() const = 0;
```

The boundary polygon as an ordered list of points — typically a floor-plane loop. **Pure virtual.**

<Returns type="TArray<FVector>">the ordered boundary points, in **UE cm** ⚠️ — space (world vs tracking) and whether the loop is 2D-on-floor (Z=0) or full 3D is unverified</Returns>

<Example inferred>

```cpp
if (IBoundaryAdapter* Boundary = BoundaryAdapterFactory::GetAdapter())
{
    const TArray<FVector> Loop = Boundary->GetPoints();   // UE cm ⚠️
    for (int32 i = 0; i < Loop.Num(); ++i)
        DrawDebugLine(GetWorld(), Loop[i], Loop[(i + 1) % Loop.Num()], FColor::Green);
}
```

</Example>

</ApiBody>

## AdapterFactory&lt;TAdapter&gt;

<Badge tone="type">template base class</Badge> <Badge>C++ only</Badge> <Badge>header-only</Badge>

```cpp
template<typename TAdapter>
class AdapterFactory
```

A per-adapter-type singleton registry keyed by [platform](/docs/sdk-api/unreal-api/utilities-platform#eplatformtypes). Game code calls the static `GetAdapter()` accessors to obtain the active adapter; integrations call `Register` / `RegisterAllPlatforms` to publish their implementations. Not Blueprint-exposed. The two concrete factories ([`HandsAdapterFactory`](#handsadapterfactory), [`BoundaryAdapterFactory`](#boundaryadapterfactory)) inherit this full static API.

Lookup precedence: an adapter registered via [`RegisterAllPlatforms`](#register--registerallplatforms) wins for **every** platform, taking precedence over per-platform entries.

:::note[Internal — not documented]
A `GetAdapter(AR51::PlatformType)` overload also exists, but it takes the internal `AR51::PlatformType` (wire/proto) enum and is **internal**. Public callers should use the [`EPlatformTypes`](/docs/sdk-api/unreal-api/utilities-platform#eplatformtypes) overload or the [no-arg `GetAdapter()`](#getadapter). The `EmptyHandsAdapter` platform fallback and the `AR51::PlatformType` ↔ `EPlatformTypes` converters are also internal.
:::

### AdapterFactory method summary

**Static**

| Method | Returns | |
|---|---|---|
| [`Clear`](#clear) | `void` | <Badge>C++ only</Badge> |
| [`GetAdapter(platform)`](#getadapterplatform) | `TAdapter*` | <Badge>C++ only</Badge> |
| [`GetAdapter()`](#getadapter) | `TAdapter*` | <Badge>C++ only</Badge> · resolves platform from `AAR51SDK` |
| [`Register`](#register--registerallplatforms) | `void` | <Badge>C++ only</Badge> |
| [`RegisterAllPlatforms`](#register--registerallplatforms) | `void` | <Badge>C++ only</Badge> |

### Clear

<ApiBody kind="method" tags="static, C++ only">

```cpp
static void Clear();
```

Drops all registered adapters — both the per-platform map and the all-platform override.

</ApiBody>

### GetAdapter(platform)

<ApiBody kind="method" tags="static, C++ only">

```cpp
static TAdapter* GetAdapter(EPlatformTypes platform);
```

Returns the adapter registered for a specific UE-facing platform, or `nullptr` if none is registered (an all-platform override, if present, still wins).

<Params>
<Param name="platform" type="EPlatformTypes">the target platform (see [`EPlatformTypes`](/docs/sdk-api/unreal-api/utilities-platform#eplatformtypes))</Param>
</Params>

<Returns type="TAdapter*">the adapter for that platform, or `nullptr`</Returns>

</ApiBody>

### GetAdapter

<ApiBody kind="method" tags="static, C++ only">

```cpp
static TAdapter* GetAdapter();
```

The normal game-side entry point. Resolves the current platform from the in-level SDK actor — `AAR51SDK::Instance()->Platform` (an [`EPlatformTypes`](/docs/sdk-api/unreal-api/utilities-platform#eplatformtypes)) — and returns the adapter registered for it. Logs an error and returns `nullptr` if no [`AAR51SDK`](/docs/sdk-api/unreal-api/classes/aar51sdk) actor is present in the level.

<Returns type="TAdapter*">the adapter for the running platform, or `nullptr` if no SDK actor exists</Returns>

<Example inferred>

```cpp
// HandsAdapterFactory and BoundaryAdapterFactory inherit this:
if (IHandsAdapter* Hands = HandsAdapterFactory::GetAdapter())
    UE_LOG(LogTemp, Log, TEXT("Hands source: %s"), *Hands->GetSourceDevice());
```

</Example>

</ApiBody>

### Register / RegisterAllPlatforms

<ApiBody kind="method" tags="static, C++ only">

```cpp
static void Register(AR51::PlatformType platform, TAdapter* adapter);
static void RegisterAllPlatforms(TAdapter* adapter);
```

Publish an adapter into the registry. `Register` binds one adapter to a single platform — a `null` adapter is ignored (logged), and re-registering a platform overrides the previous entry (logged). `RegisterAllPlatforms` registers a single adapter that wins for **every** platform, taking precedence over per-platform entries during lookup.

<Params>
<Param name="platform" type="AR 51::PlatformType">the platform key (⚠️ internal wire enum — the `EPlatformTypes` lookup overloads are the public read path)</Param>
<Param name="adapter" type="TAdapter*">the adapter instance to register</Param>
</Params>

</ApiBody>

## HandsAdapterFactory

<Badge tone="type">concrete factory</Badge> <Badge>C++ only</Badge>

```cpp
class HandsAdapterFactory : public AdapterFactory<IHandsAdapter>
```

The factory for [`IHandsAdapter`](#ihandsadapter). Inherits the full static API from [`AdapterFactory<TAdapter>`](#adapterfactorytadapter). Call `HandsAdapterFactory::GetAdapter()` to obtain the active hands adapter for the running platform.

## BoundaryAdapterFactory

<Badge tone="type">concrete factory</Badge> <Badge>C++ only</Badge>

```cpp
class BoundaryAdapterFactory : public AdapterFactory<IBoundaryAdapter>
```

The factory for [`IBoundaryAdapter`](#iboundaryadapter). Inherits the full static API from [`AdapterFactory<TAdapter>`](#adapterfactorytadapter). Call `BoundaryAdapterFactory::GetAdapter()` to obtain the active boundary adapter for the running platform.

## See also

- [`HandJointInfo`](/docs/sdk-api/unreal-api/classes/handjointinfo) — the per-joint pose struct returned by `IHandsAdapter`
- [`EPlatformTypes`](/docs/sdk-api/unreal-api/utilities-platform#eplatformtypes) — the platform enum used to key the registry
- [`AAR51SDK`](/docs/sdk-api/unreal-api/classes/aar51sdk) — supplies the `Platform` that the no-arg `GetAdapter()` resolves against
- [Hands, controllers, boundary & anchors](/docs/sdk-api/unreal-api/hands-boundary-anchors) — the area overview, data model, and anchor components
- [Class index](/docs/sdk-api/unreal-api/classes) — all Unreal SDK types
