componentsAtLocation<T> method

Iterable<Component> componentsAtLocation<T>(
  1. T locationContext,
  2. List<T>? nestedContexts,
  3. T? transformContext(
    1. CoordinateTransform,
    2. T
    ),
  4. bool checkContains(
    1. Component,
    2. T
    ),
)

This is a generic implementation of componentsAtPoint; refer to those docs for context.

This will find components intersecting a given location context T. The context can be a single point or a more complicated structure. How to interpret the structure T is determined by the provided lambdas, transformContext and checkContains.

A simple choice of T would be a simple point (i.e. Vector2). In that case transformContext needs to be able to transform a Vector2 on the parent coordinate space into the coordinate space of a provided CoordinateTransform; and checkContains must be able to determine if a given Component "contains" the Vector2 (the definition of "contains" will vary and shall be determined by the nature of the chosen location context T).

Implementation

Iterable<Component> componentsAtLocation<T>(
  T locationContext,
  List<T>? nestedContexts,
  T? Function(CoordinateTransform, T) transformContext,
  bool Function(Component, T) checkContains,
) sync* {
  nestedContexts?.add(locationContext);
  if (_children != null) {
    for (final child in _children!.reversed()) {
      if (child is IgnoreEvents && child.ignoreEvents) {
        continue;
      }
      T? childPoint = locationContext;
      if (child is CoordinateTransform) {
        childPoint = transformContext(
          child as CoordinateTransform,
          locationContext,
        );
      }
      if (childPoint != null) {
        yield* child.componentsAtLocation(
          childPoint,
          nestedContexts,
          transformContext,
          checkContains,
        );
      }
    }
  }
  final shouldIgnoreEvents =
      this is IgnoreEvents && (this as IgnoreEvents).ignoreEvents;
  if (checkContains(this, locationContext) && !shouldIgnoreEvents) {
    yield this;
  }
  nestedContexts?.removeLast();
}