update method

  1. @override
void update(
  1. double deltaSeconds
)
override

Called once per frame while the component is mounted, enabled, and loaded. deltaSeconds is the elapsed time since the previous tick. A traversal visits each component at most once. Removing this component or an earlier sibling is safe. A component inserted before the current traversal position starts on the next frame. Reordering component or child lists during traversal is unsupported.

Implementation

@override
void update(double deltaSeconds) {
  if (!_initialized) onMount();
  if (deltaSeconds <= 0.0) return;

  final rawPivot = _currentRawPivotWorld;

  // 1. Position lag smoothing (exponential)
  if (enablePositionLag && positionLagSpeed > 0.0) {
    final t = 1.0 - math.exp(-positionLagSpeed * deltaSeconds);
    _smoothedPivotWorld =
        _smoothedPivotWorld + (rawPivot - _smoothedPivotWorld) * t;
  } else {
    _smoothedPivotWorld = rawPivot;
  }

  final currentYaw = effectiveYaw;
  final currentPitch = effectivePitch.clamp(-1.4, 1.4);

  // 2. Occlusion query from pivot along boom direction toward desired eye
  final unoccludedEye = _computeEyePosition(
    _smoothedPivotWorld,
    currentYaw,
    currentPitch,
    targetLength,
  );
  final rayDir = (unoccludedEye - _smoothedPivotWorld).normalized();
  final ray = vm.Ray.originDirection(_smoothedPivotWorld, rayDir);

  var desiredLength = targetLength;
  final hit = raycastNode(
    _rootNode,
    ray,
    maxDistance: targetLength,
    layerMask: layerMask,
    where: (n) => !_isExcluded(n),
  );
  if (hit != null && hit.distance < targetLength) {
    desiredLength = math.max(minLength, hit.distance - probeRadius);
  }

  // Smoothly compress or expand current length
  if (desiredLength < currentLength) {
    currentLength = desiredLength;
  } else {
    final t = (1.0 - math.exp(-12.0 * deltaSeconds)).clamp(0.0, 1.0);
    currentLength = currentLength + (desiredLength - currentLength) * t;
  }

  // 3. Compute final camera socket transform
  _updateSocketTransform();

  // 4. Update child camera node converting world socket to local space
  if (cameraNode != null) {
    final camParent = cameraNode!.parent;
    if (camParent != null) {
      final invParent = camParent.globalTransform.clone()..invert();
      cameraNode!.localTransform = invParent * _cachedSocketTransform;
    } else {
      cameraNode!.localTransform = _cachedSocketTransform;
    }
  }
}