| 989 | } |
| 990 | |
| 991 | MovementController::CollisionSeparation MovementController::collisionSeparate(List<CollisionPoly>& collisionPolys, PolyF const& poly, |
| 992 | bool ignorePlatforms, float maximumPlatformCorrection, Vec2F const& sortCenter, bool upward, float separationTolerance) { |
| 993 | |
| 994 | CollisionSeparation separation = {}; |
| 995 | separation.collisionKind = CollisionKind::None; |
| 996 | bool intersects = false; |
| 997 | |
| 998 | for (auto& cp : collisionPolys) |
| 999 | cp.sortDistance = vmagSquared(cp.sortPosition - sortCenter); |
| 1000 | |
| 1001 | sort(collisionPolys, [](auto const& a, auto const& b) { |
| 1002 | return a.sortDistance < b.sortDistance; |
| 1003 | }); |
| 1004 | |
| 1005 | PolyF::IntersectResult intersectResult; |
| 1006 | PolyF correctedPoly = poly; |
| 1007 | RectF correctedBoundBox = correctedPoly.boundBox(); |
| 1008 | for (auto const& cp : collisionPolys) { |
| 1009 | if ((ignorePlatforms && cp.collisionKind == CollisionKind::Platform) || !correctedBoundBox.intersects(cp.polyBounds, false)) |
| 1010 | continue; |
| 1011 | |
| 1012 | if (upward) |
| 1013 | intersectResult = correctedPoly.directionalSatIntersection(cp.poly, Vec2F(0, 1), false); |
| 1014 | else if (cp.collisionKind == CollisionKind::Platform) |
| 1015 | intersectResult = correctedPoly.directionalSatIntersection(cp.poly, Vec2F(0, 1), true); |
| 1016 | else |
| 1017 | intersectResult = correctedPoly.satIntersection(cp.poly); |
| 1018 | |
| 1019 | if (cp.collisionKind == CollisionKind::Platform && intersectResult.intersects) { |
| 1020 | if (intersectResult.overlap[1] <= 0 || intersectResult.overlap[1] > maximumPlatformCorrection) |
| 1021 | intersectResult.intersects = false; |
| 1022 | } |
| 1023 | |
| 1024 | if (intersectResult.intersects) { |
| 1025 | intersects = true; |
| 1026 | correctedPoly.translate(intersectResult.overlap); |
| 1027 | correctedBoundBox = correctedPoly.boundBox(); |
| 1028 | separation.correction += intersectResult.overlap; |
| 1029 | if (cp.movingCollisionId) |
| 1030 | separation.movingCollisionId = cp.movingCollisionId; |
| 1031 | separation.collisionKind = maxOrNullCollision(separation.collisionKind, cp.collisionKind); |
| 1032 | } |
| 1033 | } |
| 1034 | |
| 1035 | separation.solutionFound = true; |
| 1036 | float separationToleranceSquared = square(separationTolerance); |
| 1037 | if (intersects) { |
| 1038 | for (auto const& cp : collisionPolys) { |
| 1039 | if (cp.collisionKind == CollisionKind::Platform || !correctedBoundBox.intersects(cp.polyBounds, false)) |
| 1040 | continue; |
| 1041 | |
| 1042 | intersectResult = correctedPoly.satIntersection(cp.poly); |
| 1043 | if (intersectResult.intersects && intersectResult.overlap.magnitudeSquared() > separationToleranceSquared) { |
| 1044 | separation.collisionKind = maxOrNullCollision(separation.collisionKind, cp.collisionKind); |
| 1045 | separation.solutionFound = false; |
| 1046 | break; |
| 1047 | } |
| 1048 | } |
nothing calls this directly
no test coverage detected