renderTree method

  1. @override
void renderTree(
  1. Canvas canvas
)
override

Implementation

@override
void renderTree(Canvas canvas) {
  final componentLights =
      _visibleLight.where(_isLightRenderable).toList(growable: false);
  final lightSources = _lightSources
      .where((light) => light.enabled && _isLightSourceVisible(light))
      .toList(growable: false);

  if (componentLights.isEmpty && lightSources.isEmpty) {
    if (_debug) {
      _renderDebug(canvas, const [], _resolveOccluders());
    }
    return;
  }

  final occluders =
      componentLights.any((light) => light.lighting.config!.castShadows) ||
              lightSources.any((light) => light.config.castShadows)
          ? _resolveOccluders()
          : const <LightingOccluder>[];

  final additive = <_PendingLight>[];
  final cutout = <_PendingLight>[];

  for (final light in componentLights) {
    final config = light.lighting.config!;
    final pending = _resolveLight(
      config: config,
      center: light.absoluteCenter + config.align,
      angle: light.lighting.angle,
      occluders: occluders,
    );
    if (pending == null) {
      continue;
    }
    (config.mode == LightingMode.additive ? additive : cutout).add(pending);
  }

  for (final light in lightSources) {
    final config = light.config;
    final pending = _resolveLight(
      config: config,
      center: light.position + config.align,
      angle: light.angle,
      occluders: occluders,
    );
    if (pending == null) {
      continue;
    }
    (config.mode == LightingMode.additive ? additive : cutout).add(pending);
  }

  // Additive lights are composited *below* the ambient darkness, so the
  // ambient color darkens them instead of the light being painted on top of
  // the night color.
  if (additive.isNotEmpty) {
    canvas.saveLayer(bounds, paint);
    canvas.save();
    _applyCameraTransform(canvas);

    for (final light in additive) {
      _renderLight(canvas, light, cutout: false);
    }

    canvas.restore();
    canvas.restore();
  }

  // A cutout light only makes sense when there is ambient darkness to erase.
  if (_containColor) {
    canvas.saveLayer(bounds, paint);
    canvas.drawColor(color!, BlendMode.dstATop);
    canvas.save();
    _applyCameraTransform(canvas);

    for (final light in cutout) {
      _renderLight(canvas, light, cutout: true);
    }

    canvas.restore();
    canvas.restore();
  }

  if (_debug) {
    _renderDebug(canvas, [...additive, ...cutout], occluders);
  }
}