place method
Places item (or the selected one) on hit.
Implementation
Future<UArPlacedItem?> place(UArHitResult hit, {UArPlaceable? item}) async {
final UArPlaceable? placeable = item ?? currentItem;
if (placeable == null || busy) return null;
if (!_matches(hit, placeable.surface)) return null;
final int count = placed.where((UArPlacedItem p) => p.item.id == placeable.id).length;
if (placeable.maxCount > 0 && count >= placeable.maxCount) {
final UArPlacedItem existing = placed.firstWhere((UArPlacedItem p) => p.item.id == placeable.id);
await controller.updateAnchor(existing.anchorId, placementPose(hit));
return existing;
}
if (_o.maxPlacements > 0 && placed.length >= _o.maxPlacements) {
if (!_o.replaceWhenFull) return null;
await remove(placed.first.nodeId);
}
setState(() => busy = true);
try {
final UArAnchor anchor = await controller.addAnchor(placementPose(hit), trackableId: hit.trackableId);
final String nodeId = controller.newId("item");
final UArNode node = placeable.build(nodeId).copyWith(anchorId: anchor.id);
final UArNodeInfo info = await controller.addNode(node);
if (hit.isWall && node.type == UArNodeType.model) {
final UArVector3 offset = UArVector3(0, 0, max(0.005, (info.size.x.abs() + info.size.z.abs()) / 4));
_offsets[nodeId] = offset;
await controller.transformNode(nodeId, position: offset);
}
final UArPlacedItem result = UArPlacedItem(nodeId: nodeId, anchorId: anchor.id, item: placeable, hit: hit, info: info);
placed.add(result);
if (_o.haptics) unawaited(HapticFeedback.lightImpact());
if (_o.selectOnPlace) selectedNode = nodeId;
if (_o.showGestureHint && !_gestureHintShown) {
_gestureHintShown = true;
_showGestureHint = true;
Future<void>.delayed(const Duration(seconds: 4), () {
if (mounted) setState(() => _showGestureHint = false);
});
}
widget.onPlaced?.call(result);
return result;
} on UArException catch (error) {
widget.onError?.call(error);
return null;
} finally {
if (mounted) setState(() => busy = false);
}
}