godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.11k stars 69 forks source link

Add functions to clamp a point to a Rect2, Rect2i or AABB #9224

Open JUSTCAMH opened 6 months ago

JUSTCAMH commented 6 months ago

Describe the project you are working on

A metroidvania game

Describe the problem or limitation you are having in your project

I've got a Rect2 which represents a room in my game. I wish to clamp the camera and various other objects to be within the Rect2.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

Add a function to Rect2, Rect2i and AABB which takes in a point (Vector2 for Rect2, Vector2i for Rect2i, Vector3 for AABB) and returns a point that is clamped to be within or on the edge of the bounds. If the given point is inside the bounds, it'd return back the point unchanged. If the point is outside, it would be clamped to a face / edge / corner of the bounds.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

See above.

If this enhancement will not be used often, can it be worked around with a few lines of script?

This can be achieved by clamping the individual axes of the point to be within the bounds. However this is quite tedious to write out in gdscript, as one must consider the size and offset of the bounds, and do so on 2-3 axes.

Is there a reason why this should be core and not an add-on in the asset library?

Rect2, Rect2i and AABBs are all core. This feels like something that should be possible out of the box

AThousandShips commented 6 months ago

Does vec2.clamp(rect2.position, rect2.end) not work?

JUSTCAMH commented 6 months ago

I hadn’t found this, yes this does achieve what I was looking for, thanks! I feel that this function still does make sense to have for Rects and AABBs, but if you disagree then this can be closed.

goatchurchprime commented 2 weeks ago

I too got stuck on this problem, and found the answer here in this ticket because I was looking in the wrong place in the docs.

The clamp() functions are completely consistent in the order of their parameters: clamp(value, min, max), or value.clamp(min, max) if the value is not a primitive type.

However, when I had a Vector2 and a Rect I immediately got it the wrong way round and was frustratingly looking for Rect.clamp(Vector2). I would not have made this mistake had the function been called clamp_by().

If this is a common enough mistake, maybe we should put a hint in the docs for Rect.

AThousandShips commented 2 weeks ago

There is no clamping method with Rect so there's no method to call clamp_by or method to get confused?