initializeParticles method

void initializeParticles(
  1. Path path,
  2. SpoilerConfig config, {
  3. List<Rect>? rects,
})

Initializes the particle system with necessary bounds and configuration.

path: The area where particles can exist (e.g. text outlines). config: Configuration for speed, density, color, etc. rects: Optional explicit list of rectangles (e.g. for individual words). If provided, this is preferred for shader rendering to ensure precise per-rect shapes.

Implementation

void initializeParticles(Path path, SpoilerConfig config,
    {List<Rect>? rects}) {
  final previousShaderPath = _config.shaderConfig?.customShaderPath;
  final nextShaderPath = config.shaderConfig?.customShaderPath;

  // Ensure maxParticleSize is valid
  assert(config.particleConfig.maxParticleSize >= 1,
      'maxParticleSize must be >= 1');
  _config = config;
  _spoilerRects = rects ?? [];
  _cachedClipPath = null; // Invalidate cache

  if (_spoilerPath != path) {
    _spoilerPath.reset();
    if (config.maskConfig != null) {
      final newPath = Path.combine(
        config.maskConfig!.maskOperation,
        path,
        config.maskConfig!.maskPath.shift(
          config.maskConfig!.offset,
        ),
      );
      _spoilerPath.addPath(newPath, Offset.zero);
    } else {
      _spoilerPath.addPath(path, Offset.zero);
    }
    _spoilerBounds = _spoilerPath.getBounds();
  }

  // If rects weren't provided, try to approximate them from path bounds
  if (_spoilerRects.isEmpty) {
    // Fallback: use subPaths derived rects
    final subPaths = _spoilerPath.subPaths;
    _encapsulatedPaths = subPaths.toList();
    _spoilerRects = _encapsulatedPaths.map((p) => p.getBounds()).toList();
  }

  _initFadeIfNeeded();

  // If shader changed (or removed), allow re-init and fall back to atlas while loading.
  if (previousShaderPath != nextShaderPath) {
    _shaderInitAttempted = false;
    if (_drawer is ShaderSpoilerDrawer || nextShaderPath == null) {
      _drawer = AtlasSpoilerDrawer();
    }
  }

  // Ensure we are using Atlas drawer initially or if config changes
  final subPaths = _spoilerPath.subPaths;
  _encapsulatedPaths = subPaths.toList();

  if (_drawer is! ShaderSpoilerDrawer) {
    if (_drawer is! AtlasSpoilerDrawer) {
      _drawer = AtlasSpoilerDrawer();
    }
    (_drawer as AtlasSpoilerDrawer).initializeParticles(
      paths: subPaths,
      config: _config,
    );
  }

  _isEnabled = config.isEnabled;
  _startParticleAnimationIfNeeded();

  // Attempt to switch to shader if configured
  if (_config.shaderConfig?.customShaderPath != null) {
    _initShaderIfNeeded();
  }
}