godotengine / godot-proposals

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

Give properties a block for export logic #2080

Closed cgbeutler closed 2 years ago

cgbeutler commented 3 years ago

Describe the project you are working on

Plugin with lots of variable exports.

Describe the problem or limitation you are having in your project

When exporting, it's sometimes nice to have a bit of logic. The editor will do this occasionally. (For example, when changing one value in the inspector, other properties will sometimes get shown/hid.) Godot can currently do this with the _get_property_list, _get, and _set virtual functions.

Overriding _get_property_list, _get, and _set gets kinda... gross. It can bloat fast and can separate properties from their logic. These functions were somewhat patterned after the C++ code. With GDScript, the _get and _set functions are, in a way, able to be short-cut with getters and setters. The only way to short-cut _get_property_list is to use export annotations, which lack logic. This means that if you need any logic for an export, you'll have to give up a lot of sort-cut syntax and override _get_property_list, _get, and _set.

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

I propose adding a third item to the setter/getter stuff called export. This would allow properties to have logic when exporting, much like you can do in _get_property_list. If this new export block returns null, then the property is skipped. If it returns an ExportProperty object or a dictionary (in a similar form to what _get_property_list uses), then it is exported. (I would prefer using a new ExportProperty object, so I can have auto-completion.)

In short, adding an export block to a property adds logic while keeping the code attached to the property it relates to.

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

In v4 it would probably look something like this:

# Optional item is only exported if the condition is true
var __optional_item = null
var optional_item:
    export:  return null  if not some_condition else  ResourceExport.new("Texture")
    get:  return __optional_item
    set(value):  __optional_item = value

This would allow some logic to exist on the property for exporting.

I would love to see actual objects be what you return from the function, but I could also see just using a dictionary like what is used in _get_property_list.

var optional_item:
    export:
        if some_condition:  return { type = TYPE_OBJECT, hint = PROPERTY_HINT_RESOURCE_TYPE }
        return null
    ...

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

This enhancement is not necessary. At the end of the day, the current options with @export and _get_property_list do work. If this proposal doesn't happen, I'll live.

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

It would require changes to GDScript itself

cgbeutler commented 3 years ago

Also, I realize a ton of work was just done to add @export annotations, so I understand if diving back into that discussion would cause too much ptsd... I may be a little too late to the table.

Calinou commented 3 years ago

I fear the solution proposed here can easily get too complex. On top of that, it adds new GDScript keywords, which we really aim to avoid now that we have annotations. To each problem, its own solution.

Instead, I think we should aim to expose a simpler way to:

In practice, this is often what you need 90% of the time.

Calinou commented 2 years ago

Closing due to lack of support (see the lack of comments here and reactions on OP).