godotengine / godot-proposals

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

[C#] Add support for custom converters to extend the Export attribute's functionalities #7581

Open Mrcubix opened 1 year ago

Mrcubix commented 1 year ago

Describe the project you are working on

Working on a remake of a game that contains many entities, part of which being buildables, either defenses or building with no offensive abilities.

Some of them have a build time associated with them, ideally i would want to set that in the editor.

Describe the problem or limitation you are having in your project

Godot API's Export Attribute does not support any of the usual time related types such as TimeSpan or DateTime, forcing the use of primitives which are not ideal in my case.

Godot does not seem to provide a type like TimeSpan.

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

When supported, Users would be able to use their own converters to convert a type into something the editor can use, We would then be able to provide our own control through plugins or the attribute itself through a second parameter.

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

Users will be able to declare a converter, a control & a property as follow :

public class TimeSpanConverter : GodotExportConverter
{
    public Variant? Convert(object? value, Type type, PropertyHint hintType, string hintString, PropertyUsageFlags usageFlags, bool wide)
    {
        if (value is TimeSpan timeSpan)
            return timeSpan.Ticks;
        else
            return null;
    }

    public object? ConvertBack(Variant? value, Type type, PropertyHint hintType, string hintString, PropertyUsageFlags usageFlags, bool wide)
    {
        if (object is long convertedTimeSpan)
            return TimeSpan.FromTicks(convertedTimeSpan);
        else
            return null;
    }
}

public partial class TimeSpanControl : Control
{
    // Build a custom control that would be used in the Export section of the inspector
    // We would also need to either format the value in a specific way or set the value of each inputs
    // ...
}

public partial class SomeObject
{
    [Export(Converter = TimeSpanConverter, Control = TimeSpanControl)]
    public virtual TimeSpan BuildTime { get; set; }

    [Export]
    public virtual long SomeOtherProperty { get; set; }
}

Meanwhile, in the inspector, the property would appear as defined in the control.

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

This property can either be replaced by a primitive, such as a long, or a string that has to be formatted in a specific way to make it not crash on launch which could easily be broken.

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

What i want cannot be added using plugins as of now.

I'm sure there are other developers out there that use types that are not natively compatible with the Export attribute and would ideally want to be able to create their own converter.

This would make it easier to handle types like TimeSpan in my case.

tpaksu commented 1 week ago

Bumping this, I think removing the sealed keyword from the ExportAttribute class may be enough to do these kind of things, because it will enable us to extend from the ExportAttribute, and use our own tags on the exported properties. I was trying to make Godot save some values as encrypted (with a local key) on the .tscn files, so I don't mistakenly post them to GitHub for example. And I thought this can be done with a new ExportEncrypted attribute.