hitTestNode function

bool hitTestNode(
  1. Offset point,
  2. SceneNode node
)

Returns true if point hits node in scene coordinates.

Implementation

bool hitTestNode(Offset point, SceneNode node) {
  if (!node.isVisible || !node.isSelectable) return false;

  switch (node.type) {
    case NodeType.image:
    case NodeType.text:
    case NodeType.rect:
      final inverse = node.transform.invert();
      if (inverse == null) {
        return hitTestRect(point, node.boundsWorld);
      }
      final localPoint = inverse.applyToPoint(point);
      final paddingScene = node.hitPadding + kHitSlop;
      final paddingX =
          paddingScene *
          math.sqrt(inverse.a * inverse.a + inverse.c * inverse.c);
      final paddingY =
          paddingScene *
          math.sqrt(inverse.b * inverse.b + inverse.d * inverse.d);
      final bounds = node.localBounds;
      return Rect.fromLTRB(
        bounds.left - paddingX,
        bounds.top - paddingY,
        bounds.right + paddingX,
        bounds.bottom + paddingY,
      ).contains(localPoint);
    case NodeType.path:
      final pathNode = node as PathNode;
      if (pathNode.fillColor != null) {
        final padding = pathNode.hitPadding + kHitSlop;
        if (!pathNode.boundsWorld.inflate(padding).contains(point)) {
          return false;
        }
        final localPath = pathNode.buildLocalPath();
        if (localPath == null) return false;
        final inverse = pathNode.transform.invert();
        if (inverse == null) return false;
        final localPoint = inverse.applyToPoint(point);
        return localPath.contains(localPoint);
      }
      if (pathNode.strokeColor != null) {
        final effectiveStrokeWidth =
            pathNode.strokeWidth * _maxAxisScaleAbs(pathNode.transform);
        final padding =
            effectiveStrokeWidth / 2 + pathNode.hitPadding + kHitSlop;
        return pathNode.boundsWorld.inflate(padding).contains(point);
      }
      return false;
    case NodeType.line:
      final line = node as LineNode;
      final inverse = line.transform.invert();
      if (inverse == null) return false;
      final localPoint = inverse.applyToPoint(point);
      return hitTestLine(localPoint, line.start, line.end, line.thickness);
    case NodeType.stroke:
      final stroke = node as StrokeNode;
      final inverse = stroke.transform.invert();
      if (inverse == null) return false;
      final localPoint = inverse.applyToPoint(point);
      return hitTestStroke(
        localPoint,
        stroke.points,
        stroke.thickness,
        hitPadding: stroke.hitPadding,
      );
  }
}