godotengine / godot-proposals

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

Allow exporting with custom inspectors #5489

Open BanchouBoo opened 2 years ago

BanchouBoo commented 2 years ago

Describe the project you are working on

No specific context, this could be applicable for any project.

Describe the problem or limitation you are having in your project

As it stands, if you want to make a custom inspector involves putting together a whole plugin and targetting specific node types and property names to place the inspector. This is great if you have a very specific tool you're putting together, but if you want a generic custom inspector that you can throw into any project onto any object and any variable, such as the below image from a Unity plugin, this isn't really a good option. The closest you can get is to have an EditorInspectorPlugin with a can_handle function that always returns true, then use a naming convention for variables that want to use that particular inspector, using the example below that could be something like any Vector2 prefixed with minmax_. This, however, is very awkward and not ideal.

image

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

Add a new annotation for arbitrary custom data, e.g. @custom

The annotation can take any number of arguments of arbitrary data, with the first argument being a required String name identifier for that particular annotation. A variable can contain any number of @custom annotations and those are passed to the parse_property function for EditorInspectorPlugins as a dictionary, where the identifier is the key and the rest of the arguments are stored in an array as the value.

This not only makes creating easily resuable custom inspectors much simpler, it also lets users add arbitrary data to a variable for whatever else they might think of.

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

Example for the previous MinMaxSlider Unity plugin:

script.gd

@export @custom("MinMaxSlider", 0.5, 71.7) var var1: Vector2

inspector_plugin.gd

extends EditorInspectorPlugin

const MinMaxSliderInspector = preload("min_max_slider_inspector.gd")

func _can_handle(_object: Variant) -> bool:
    return true

func _parse_property(object: Object, type: int, name: String, hint_type: int, hint_string: String, usage_flags: int, wide: bool, custom: Dictionary):
    if custom.has("MinMaxSlider"):
        var editor : = MinMaxSliderInspector.new(object, custom["MinMaxSlider"][0], custom["MinMaxSlider"][1])
        add_property_editor(name, editor)
        return true
    return false

and now you have a way to throw this inspector onto any Vector2 (or any other type you add support to for this particular inspector)

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

As already stated, the closest work around is awkward to work with as it forces particular naming conventions to get specific inspectors (it also doesn't give you a way to pass arguments along to the custom inspector).

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

Having a universal standard for people to craft portable inspector plugins that people can throw into any project and use is very valuable.

JoNax97 commented 2 years ago

Would it be possible to declare and use custom annotations directly? i.e. writing:

@export @min_max_slider(0.5, 71.7) var var1: Vector2

It would make the syntax much cleaner, and possibly open up other use cases

BanchouBoo commented 2 years ago

Would it be possible to declare and use custom annotations directly? i.e. writing:

@export @min_max_slider(0.5, 71.7) var var1: Vector2

It would make the syntax much cleaner, and possibly open up other use cases

While this is nicer to read and write, it also presumably would require manually registering new annotations, which I feel would lessen the flexibility compared to being able to add any arbitrary string identifier for a custom annotation without registering it first, which also has the benefit (or, depending on context, detriment) of if some plugin that uses a custom gets removed, all your code that uses that annotation doesn't start throwing errors because the annotation is no longer registered, because it doesn't need to be to begin with.

Now, if we could have both that would certainly be ideal, because there are certainly instances where you would want an annotation to throw an error if you're trying to use it when nothing explicitly is set up to register support for it, but that won't always be the case.

Frontrider commented 2 years ago

While this is nicer to read and write, it also presumably would require manually registering new annotations, which I feel would lessen the flexibility compared to being able to add any arbitrary string identifier for a custom annotation without registering it first, which also has the benefit (or, depending on context, detriment) of if some plugin that uses a custom gets removed, all your code that uses that annotation doesn't start throwing errors because the annotation is no longer registered, because it doesn't need to be to begin with.

As far as I read the annotation proposals (the original ones) this can go away when we can finally have custom annotations.