i will base the sliding based on where the player wants to go.
Yes, this is exactly what I tried to explain before: it would be better if your function took the destination point as input instead of the velocity. Also, when generating the slide-to position, you should use your existing function ClosestPointOnLine, instead of the new ProjectPointOnLine I used, so that the sphere stops sliding at the end of the line. Otherwise, if the projection of the destination point is outside of the line segment, the player sphere will slide too far, possibly missing other collisions.
Also in my example, during the slide-response, you should call ResolveCollissions repeatedly, each time using the returned x and y values as the new source position (set them as the new px and py values which will be passed to the next ResolveCollissions call), and calculating a new slide-to position based on the existing destination position. You stop calling ResolveCollissions when the position it returns is "almost" identical to the last (px, py) position. By "identical" I mean: when the distance from the currently returned x and y position to the last returned position (which you saved in (px, py)) is smaller than 1.0 (one pixel) for example. I think this will also solve the problem of sliding against the convex corners, but it would probably still be better if you could handle that case by using your algorithm - in the example I attached, this is handled by just pushing the player away from the corner point by 20.0 pixels - I don't like that. This should be used instead of the "slide" boolean parameter I added before.
Also, I think it would be best if you separate the collision response from the collision detection, like you did with the GetClosestCollision function, except GetClosestCollision should always re-calculate and return the closest line & point instead of returning the closest line based on the cached "line.overlap" values. GetClosestCollision should also differentiate between lines and line-endpoints (like in my example), and it should return the closest point on the line, pushed-out along the normal of the line in case of a line collision, or pushed-away along the radius from the line-endpoint in case of a line-endpoint collision. Then, in the collision-response code (which remains in the ResolveCollissions function), you just call GetClosestCollision (the collision-detection code), initially with the source and destination points passed to ResolveCollissions, and then repeatedly with the destination position returned by GetClosestCollision, until GetClosestCollision returns a position that is "almost" identical to the last position like I explained above. Also, GetClosestCollision should return the destination point directly in case there's no collision (it currently returns 0, meaning there was a collision with the line at position 0?).