godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.16k stars 97 forks source link

Add useful Vector2, Vector2i, Vector3, Vector3i comparison functions #3414

Open briansemrau opened 3 years ago

briansemrau commented 3 years ago

Describe the project you are working on

I'm working on a project where I frequently compare coordinates and bounds. I need to know if a coordinate is within or outside a multidimensional range.

Describe the problem or limitation you are having in your project

In vector variant types, the current comparison operators <, >, <=, >= are only useful for sorting algorithms. They have no geometric meaning, which is unintuitive for a type representing a geometric vector, point, or range. There is (nearly) no purpose in having them available in GDScript.

If I want to check if (-1, 0, 2) < (10, 10, 10), I have to implement my own comparison operator. This is cumbersome and repetitive.

This is the current (generally useless) implementation:

bool Vector3i::operator<(const Vector3i &p_v) const {
    if (x == p_v.x) {
        if (y == p_v.y) {
            return z < p_v.z;
        } else {
            return y < p_v.y;
        }
    } else {
        return x < p_v.x;
    }
}

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

Add the following functions to all vector variant types:

This gives meaningful comparison operators to use in scripts. If I want to know if a value is out of range, I can use v.any_greater_than_or_equal(bounds).

(Note: some of these function are the logical inverse of others, so they all don't necessarily need to be implemented. E.g. all_greater_than!any_less_than_or_equal.)

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

func all_greater_than(v1: Vector2, v2: Vector2):
    return v1.x > v2.x and v1.y > v2.y
func any_greater_than(v1: Vector2, v2: Vector2):
    return v1.x > v2.x or v1.y > v2.y

etc.

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

A few dozen lines of code can implement these functions in script.

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

This improves the usability of Vector variant types by providing geometric comparisons.

datapaganism commented 3 years ago

You are essentially looking for member functions like these? I have quickly mocked them based on your requirements, while there are logically equivalent ones, I would say that it cause more headaches debugging if we call a similar function and negate it.

bool all_greater_than(const Vector2 &p_vector2) const;
bool Vector2::all_greater_than(const Vector2 &p_vector2) const {
    return (x > p_vector2.x) && (y > p_vector2.y);
}

bool all_greater_than_or_equal(const Vector2 &p_vector2) const;
bool Vector2::all_greater_than_or_equal(const Vector2 &p_vector2) const {
    return (x >= p_vector2.x) && (y >= p_vector2.y);
}

bool all_less_than(const Vector2 &p_vector2) const;
bool Vector2::all_less_than(const Vector2 &p_vector2) const {
    return (x < p_vector2.x) && (y < p_vector2.y);
}

bool all_less_than_or_equal(const Vector2 &p_vector2) const;
bool Vector2::all_less_than_or_equal(const Vector2 &p_vector2) const {
    return (x <= p_vector2.x) && (y <= p_vector2.y);
}

bool any_greater_than(const Vector2 &p_vector2) const;
bool Vector2::any_greater_than(const Vector2 &p_vector2) const {
    return (x > p_vector2.x) || (y > p_vector2.y);
}

bool any_greater_than_or_equal(const Vector2 &p_vector2) const;
bool Vector2::any_greater_than_or_equal(const Vector2 &p_vector2) const {
    return (x >= p_vector2.x) || (y >= p_vector2.y);
}

bool any_less_than(const Vector2 &p_vector2) const;
bool Vector2::any_less_than(const Vector2 &p_vector2) const {
    return (x < p_vector2.x) || (y < p_vector2.y);
}

bool any_less_than_or_equal(const Vector2 &p_vector2) const;
bool Vector2::any_less_than_or_equal(const Vector2 &p_vector2) const {
    return (x <= p_vector2.x) || (y <= p_vector2.y);
}
briansemrau commented 3 years ago

@datapaganism Yup, those all look correct.

For this proposal I'll additionally mention that suggestions would be appreciated for less verbose, but equally meaningful function names (if even possible). Simply replacing the existing comparison operators with the all_... functions is an option, but would certainly need strong approval.

datapaganism commented 3 years ago

@briansemrau I have added you to a repo containing the implementations in a branch