feat: Promote PathComponent to a standard component - #4050
Conversation
|
Marking as draft since it can't be stacked properly. |
There was a problem hiding this comment.
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
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
fromPathconstructors. - Extends shape and hitbox APIs with
isSolidsupport. - 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.
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.
5e0386e to
6055c4f
Compare
|
Still caught up in deadlines unfortunately... I'll get back to this ASAP, sorry about the delay. |
|
Marking this back as draft, while I atone for my sins. |
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.
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.
…the tolerance argument
…llidablePathComponent
spydon
left a comment
There was a problem hiding this comment.
Thanks for your great work on this!


Description
The
PathComponentclass introduced in PR #4048 is moved fromexamples/lib/commonsintolib/src/geometryin the core package, on suggestion from @spydon, and it gets a hitbox counterpart,PathHitbox, so that the pair mirrorsPolygonComponentandPolygonHitbox.PathComponentrenders aPathand follows each of its closed contours with a polygon, in the same way asPolygonComponent.fromPathfollows 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 takessamplingandtoleranceto control how the contours are followed, andfilterto leave out the polygons that lie inside of the largest one, like the eyes of a face.PathHitboxis aPathComponentwithShapeHitbox, 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 thecollisionTypelike the other hitboxes.PathPathIntersections,PathPolygonIntersectionsandCirclePathIntersectionsare added to the intersection systems.The affected examples are updated accordingly, with a
CollidablePathComponentin the examples that pairs aPathComponentwith aPathHitbox. There is documentation for both classes inshape_components.mdandcollision_detection.md, and tests forPathComponentandPathHitbox.Checklist
docsand added dartdoc comments with///.examplesordocs.Breaking Change?
Related Issues