godot icon indicating copy to clipboard operation
godot copied to clipboard

sort_custom cannot use static functions in another class

Open MichaelMacha opened this issue 2 years ago • 1 comments

Godot version

v4.0.stable.official [92bee43ad]

System information

Linux Mint

Issue description

When using a static function in a custom utility class, Array's sort_custom operator cannot find the function when used as a parameter—even when the editor itself readily sees it.

In my example, I have this class:

class_name Utils

static func less_x(v1: Vector2, v2: Vector2) -> bool:
	return v1.x < v2.x

static func less_y(v1: Vector2, v2: Vector2) -> bool:
	return v1.y < v2.y

static func index_to_xy(width: int, height: int) -> Vector2:
	return Vector2(height % width, height / width)

In my main file, I have an array of Vector2s called poly_partial. The following code, my first attempt, does not work:

poly_partial.sort_custom(Utils.less_x if is_even else Utils.less_y)

It returns the error "Cannot find member "less_x" in base "Utils"". This is in spite of the fact that GDScript readily highlighted it as an option while typing it in.

I thought it might be a lamba-like operator issue, so I also tried this as an experiment:

poly_partial.sort_custom(Utils.less_x)

I get the same behavior.

Instantiating Utils, and then using the method, does work.

var utils := Utils.new()
poly_partial.sort_custom(utils.less_x if is_even else utils.less_y)

This runs entirely without issue, even with the static modifier on the functions.

This doesn't feel like intentional behavior to me.

Steps to reproduce

(More or less outlined in the description)

Minimal reproduction project

BasicDungeonGenerator.zip

MichaelMacha avatar Mar 05 '23 16:03 MichaelMacha

I think Callables just don't support static methods (yet, see this PR #71644, although it doesn't implement it for GDScript).

I tried this workaround

var utils = Utils as Script
poly_partial.sort_custom(utils.less_x if is_even else utils.less_y)

And it doesn't work. const variables can be accessed this way, but not static methods.

KoBeWi avatar Mar 05 '23 16:03 KoBeWi

Interesting. That would explain how GDScript could identify my function in the editor, but the runtime couldn't find it. Static methods don't belong to a specific object, so the object is referenced as null. I do believe that the error message itself could, at minimum, be more specific, though.

In truth there are plenty of ways I can get around this call with a basic if statement and an inline, but for more complicated sort methods it would be almost vital. In the past (3.x) I could use the old sort_custom with a reference to an object or class, and then the function name as a string, and it worked fine.

Would this qualify as a regression?

MichaelMacha avatar Mar 05 '23 22:03 MichaelMacha

ok so apparently this works

poly_partial.sort_custom(Callable(Utils, "less_x") if is_even else Callable(Utils, "less_x"))

So this is not a regression, the syntax just changed.

Still, static functions should be available as static members of the class, so there is a bug/missing functionality here.

KoBeWi avatar Mar 06 '23 00:03 KoBeWi

Duplicate of #41919.

dalexeev avatar Jun 09 '23 06:06 dalexeev