Skip to content

feat: Promote PathComponent to a standard component - #4050

Open
adario wants to merge 31 commits into
flame-engine:mainfrom
adario:feat/path-component
Open

adario wants to merge 31 commits into
flame-engine:mainfrom
adario:feat/path-component

Conversation

@adario

@adario adario commented Sep 19, 2026 •

Copy link
Copy Markdown
Contributor

Description

The PathComponent class introduced in PR #4048 is moved from examples/lib/commons into lib/src/geometry in the core package, on suggestion from @spydon, and it gets a hitbox counterpart, PathHitbox, so that the pair mirrors PolygonComponent and PolygonHitbox.

PathComponent renders a Path and follows each of its closed contours with a polygon, in the same way as PolygonComponent.fromPath follows a single contour. The polygons are kept as vertices, not as child components, and they decide whether a point is inside of the component. The constructor takes sampling and tolerance to control how the contours are followed, and filter to leave out the polygons that lie inside of the largest one, like the eyes of a face.

PathHitbox is a PathComponent with ShapeHitbox, and it is a single hitbox: it collides, contains points and is hit by rays as a whole, whichever of its polygons is involved, and it reports one collision to its parent even when several polygons touch the other hitbox. It computes its aabb from all the polygons, a ray hits the nearest polygon, and it takes the collisionType like the other hitboxes. PathPathIntersections, PathPolygonIntersections and CirclePathIntersections are added to the intersection systems.

The affected examples are updated accordingly, with a CollidablePathComponent in the examples that pairs a PathComponent with a PathHitbox. There is documentation for both classes in shape_components.md and collision_detection.md, and tests for PathComponent and PathHitbox.

Checklist

  • I have followed the Contributor Guide when preparing my PR.
  • I have updated/added tests for ALL new/updated/fixed functionality.
  • I have updated/added relevant documentation in docs and added dartdoc comments with ///.
  • I have updated/added relevant examples in examples or docs.

Breaking Change?

  • Yes, this PR is a breaking change.
  • No, this PR is not a breaking change.

Related Issues

@adario
adario marked this pull request as ready for review September 19, 2026 18:26
@adario
adario marked this pull request as draft September 19, 2026 18:30
@adario

adario commented Sep 19, 2026

Copy link
Copy Markdown
Contributor Author

Marking as draft since it can't be stacked properly.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Critical benchmark and ray-intersection regressions, plus unresolved path-contour handling issues, block approval.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 2 High severity · 2 Medium severity

Open (4)
What changed in this PR

Promotes PathComponent into Flame’s core geometry API and adds path-to-polygon conversion, concave ray intersections, and related ecosystem updates.

Changes:

  • Adds path sampling, transformations, and fromPath constructors.
  • Extends shape and hitbox APIs with isSolid support.
  • Updates tests, examples, documentation, reusable fixtures, and benchmarks.
File Reviewed change / note
packages/​flame/​test/​geometry/​polygon_ray_intersection_test.dart Adds convex, concave, and vertex ray-intersection tests.
packages/​flame/​test/​geometry/​polygon_component_from_path_test.dart Tests polygon construction from paths.
packages/​flame/​test/​geometry/​path_component_test.dart Tests PathComponent sizing and filtering.
packages/​flame/​test/​extensions/​rect_test.dart Tests offset bounds.
packages/​flame/​test/​extensions/​path_test.dart Tests path sampling and transformations.
packages/​flame/​test/​extensions/​aabb_test.dart Tests vertex AABB conversion.
packages/​flame/​test/​experimental/​geometry/​shapes/​polygon_test.dart Tests experimental polygon path conversion.
packages/​flame/​test/​collisions/​screen_hibox_test.dart Tests path hitbox containment.
packages/​flame/​lib/​src/​geometry/​shape_intersections.dart Updates polygon intersection documentation.
packages/​flame/​lib/​src/​geometry/​shape_component.dart Adds constructor-level isSolid support.
packages/​flame/​lib/​src/​geometry/​rectangle_component.dart Forwards isSolid.
packages/​flame/​lib/​src/​geometry/​polygon_ray_intersection.dart Adds concave ray parity handling. Critical, 1 vote: vertex crossings can be double-counted, regressing corner raycasts.
packages/​flame/​lib/​src/​geometry/​polygon_component.dart Adds fromPath and isSolid. Moderate, 1 vote: open contours can form unintended triangles or fail.
packages/​flame/​lib/​src/​geometry/​path_component.dart Adds the standard path component. Moderate: open contours can fail hitbox construction (2 votes); contour ordering uses diagonal length instead of area (2 votes); AABB filtering can remove valid concave contours (1 vote); nested contours are incompletely compared (1 vote).
packages/​flame/​lib/​src/​geometry/​circle_component.dart Forwards isSolid.
packages/​flame/​lib/​src/​extensions/​rect.dart Adds offset-bound construction.
packages/​flame/​lib/​src/​extensions/​path.dart Adds path utilities. Nit, 1 vote: unused import creates an unnecessary barrel cycle.
packages/​flame/​lib/​src/​extensions/​offset.dart Adds offset-list conversions.
packages/​flame/​lib/​src/​extensions/​aabb.dart Adds vertex-bound construction.
packages/​flame/​lib/​src/​experimental/​geometry/​shapes/​polygon.dart Adds Polygon.fromPath. Moderate, 1 vote: open contours are silently closed or can assert.
packages/​flame/​lib/​src/​collisions/​hitboxes/​rectangle_hitbox.dart Forwards isSolid.
packages/​flame/​lib/​src/​collisions/​hitboxes/​polygon_hitbox.dart Adds path construction support.
packages/​flame/​lib/​src/​collisions/​hitboxes/​circle_hitbox.dart Forwards isSolid.
packages/​flame/​lib/​geometry.dart Exports PathComponent.
packages/​flame/​lib/​components.dart Exports PathComponent.
packages/​flame/​benchmark/​README.md Documents new benchmarks.
packages/​flame/​benchmark/​ray_intersection_benchmark.dart Adds ray-intersection benchmarks. Critical, 1 vote: hitboxes mounted directly under FlameGame fail because a PositionComponent ancestor is required.
packages/​flame/​benchmark/​path_contour_benchmark.dart Adds contour sampling benchmarks.
packages/​flame/​benchmark/​path_collision_benchmark.dart Adds path collision benchmarks.
packages/​flame/​benchmark/​main.dart Registers benchmarks.
packages/​flame_test/​test/​test_paths_test.dart Tests reusable path fixtures.
packages/​flame_test/​lib/​test_paths.dart Exposes reusable test paths.
packages/​flame_test/​lib/​src/​test_paths.dart Defines reusable path fixtures.
examples/​pubspec.yaml Adds path-related dependencies.
examples/​lib/​stories/​input/​gesture_hitboxes_example.dart Demonstrates path gesture hitboxes. Moderate, 1 vote: the path is sampled redundantly by a discarded hitbox and PathComponent.
examples/​lib/​stories/​experimental/​shapes.dart Demonstrates path-derived experimental shapes.
examples/​lib/​stories/​collision_detection/​raytrace_example.dart Adds path raytrace shapes.
examples/​lib/​stories/​collision_detection/​rays_in_shape_example.dart Adds interactive path ray tests.
examples/​lib/​stories/​collision_detection/​raycast_max_distance_example.dart Adds path raycast targets.
examples/​lib/​stories/​collision_detection/​raycast_light_example.dart Adds path lighting targets.
examples/​lib/​stories/​collision_detection/​raycast_example.dart Adds path raycast targets.
examples/​lib/​stories/​collision_detection/​multiple_shapes_example.dart Adds collidable path shapes.
examples/​lib/​commons/​rounded_rect_component.dart Adds rounded rectangle rendering.
examples/​lib/​commons/​paths.dart Adds shared path helpers.
examples/​lib/​commons/​paths_creation_mixin.dart Adds reusable path creation behavior.
doc/​flame/​components/​shape_components.md Documents path-based shape components.
doc/​flame/​collision_detection.md Documents concave polygon hitboxes.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread packages/flame/benchmark/ray_intersection_benchmark.dart
Comment thread packages/flame/lib/src/geometry/polygon_ray_intersection.dart Outdated
Comment thread packages/flame/lib/src/geometry/path_component.dart Outdated
Comment thread packages/flame/lib/src/geometry/path_component.dart Outdated
PathComponent now lives in src/geometry and it is exported by components.dart: all affected examples now import it from there.
The path_component_test uses the TestPaths to verify both dimensions match and hitboxes filtering.
From Copilot:
path.contours includes open contours, and walkContourAt returns only the endpoints for a line. This unconditionally constructs a PolygonHitbox for every contour, while PolygonComponent requires at least three vertices, so a valid Path with an open contour fails when hitboxes load. Skip or reject non-polygon contours explicitly and document the requirement.
@spydon
spydon force-pushed the feat/path-component branch from 5e0386e to 6055c4f Compare September 21, 2026 17:48
@adario
adario marked this pull request as ready for review September 21, 2026 19:38
Comment thread packages/flame/lib/src/geometry/path_component.dart Outdated
Comment thread packages/flame/lib/src/geometry/path_component.dart Outdated
Comment thread packages/flame/lib/src/geometry/path_component.dart Outdated
Comment thread packages/flame/lib/src/geometry/path_component.dart
Comment thread packages/flame/lib/src/geometry/path_component.dart Outdated
Comment thread packages/flame/lib/src/geometry/path_component.dart Outdated
@adario

adario commented Sep 23, 2026

Copy link
Copy Markdown
Contributor Author

Still caught up in deadlines unfortunately... I'll get back to this ASAP, sorry about the delay.

@adario

adario commented Sep 27, 2026

Copy link
Copy Markdown
Contributor Author

Marking this back as draft, while I atone for my sins.

@adario
adario marked this pull request as draft September 27, 2026 00:59
PathHitbox now uses mixin with ShapeHitbox, with fillParent() throwing like PolygonHitbox; the AABB is computed as an accumulation of the internal PolygonHitbox objects.
PathComponent behaves like PathHitbox, creating PolygonComponent objects (not rendered).
The shape_intersections module now contains classes for path/path, path/polygon and path/circle intersections: the path ones forward to the internal components.
This decides whether the internal PolygonComponent/Hitbox objects are filtered (default true), by keeping only the largest one and only disjoint ones.
The path_component_test in geometry now passes.
…rce file.

fix: PathHitbox.computeAabb() was starting from an invalid AABB: it now starts from the last hitbox one.
feat: Add PathComponent.polygonComponents query.
spell: Add entry in usernames.
adario and others added 9 commits September 28, 2026 00:12
feat: Add pathHitbox accessor in PathComponent.
PolygonComponent exposes the point containment and the clockwise checks as
internal statics, and PolygonRayIntersection exposes the ray intersection
against a vertex list, so that shapes made of several polygons can reuse them.
…tbox a single hitbox

PathComponent no longer adds a PolygonComponent for each contour: it keeps
the vertices of each closed contour, decides containsPoint from them, and
exposes them for intersections, in the same way as PolygonComponent does for
its single contour. The filter leaves out the polygons whose vertices all lie
inside of the largest one, instead of comparing bounding rectangles.

PathHitbox no longer adds PolygonHitbox children either, so it is a single
hitbox that cannot collide with its own parts, which was what kept every
path in MultipleShapesExample permanently colliding. Its aabb starts from the
vertices instead of hulling into the stale box, its ray intersection returns
the nearest hit over all polygons, and it renders its polygons.

The path intersection systems accumulate the intersection points of all the
polygons instead of returning the first non-empty result, and the unused
sampling and tolerance parameters and the TODO comments are gone.
PathHitbox takes the collisionType, and only the position, angle, anchor and
isSolid of the component, like PolygonHitbox does. The isSolid default comes
from ShapeComponent instead of being repeated.
…he other collidables

The path collidable now adds a PathHitbox as its hitbox, so that it is
colored, dragged and thrown exactly like the polygon, rectangle and circle
ones, instead of wrapping a path component with its own callbacks.
CollidablePathComponent no longer passes collisions through, since its
hitbox reports to it directly.
The PathComponent section no longer talks about PolygonHitbox children and
a renderHitboxes parameter, and explains the polygons, the filter and the
open contours instead. The collision detection docs get a PathHitbox section
next to PolygonHitbox.
The tests run with both broadphases and check that the hitbox does not
collide with itself, that it collides with circles, polygons and other paths
through any of its polygons, that it reports one collision and all the
intersection points when several polygons touch, that solid paths enclose
shapes, and that rays hit the nearest polygon.
@adario
adario marked this pull request as ready for review September 28, 2026 12:04
Comment thread examples/lib/commons/collidable_path_component.dart Outdated

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants