godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.1k stars 69 forks source link

Add "protected" Keyword to GDScript - Prevents Modifying Members in the Inspector at Runtime #10220

Open amarraff opened 1 month ago

amarraff commented 1 month ago

Describe the project you are working on

I have a singleton StatTracker class that loads specific pieces of save data from the user's file. It stores the data for anything in the game to access. StatTracker does this by loading values from the current save file into its own instance of my SaveData class. This is declared in my StatTracker class as: var save_instance:SaveData

Describe the problem or limitation you are having in your project

I want to prevent adjusting the values of save_instance in the inspector at runtime because they are used by the save system. Changing these values in the inspector could directly alter a save file and cause bugs. Ideally, the only thing that should be capable of adjusting these values is the code relevant to them.

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

The functional purpose of this keyword is added safety from developer mistakes. Declaring a "protected" var is identical to declaring a regular var, except it cannot be modified in the inspector at runtime. If applied to a class stored in a var, like in my case, all of its members should be protected.

In my case, this would prevent accidental save data mismatches at runtime. This could also be beneficial when working in teams - it could prevent uninformed team members from causing similar bugs while testing/debugging a project in-editor.

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

protected my_var

Before runtime: Not visible in the inspector. At runtime: Visible in the inspector as a member, but not modifiable.

@export protected my_var:bool

Before runtime: Can be modified in inspector like a regular exported var. At runtime: Visible in the inspector under its appropriate export category (if any), but not modifiable.

If a shorter keyword is desired, "prot" (or something similar) could be used instead of "protected." Or, a different keyword altogether may be more appropriate.

Protected var values would have a text indication in the inspector, to show that they are protected from developer modification. Additional UI changes could be made to indicate a protected var as well, such as darkened text and bool tickboxes. However, changes based on color may conflict with certain themes, so a text indicator seems to be the cleanest approach.

Regular Vars Inspector Appearance:

Screenshot from 2024-07-15 15-51-18

Protected Vars Inspector Appearance:

Protected Var Inspector Examples

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

I don't believe so. I checked the docs, internet, and Godot Café discord, but I didn't find anything that would solve this issue. If there is already a built-in way to achieve what I'm proposing, I'd be grateful for knowledge of it.

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

This suggestion is for improving GDScript functionality out of the box. I assume that new keywords are not eligible to be add-on content.

Meorge commented 1 month ago

This sounds like a neat idea, but I'd be worried about the specific term protected being used to mean this read-only behavior specifically. The C# documentation states that for that language,

protected: Only code in the same class or in a derived class can access this type or member.

There has been discussion of introducing access modifiers to GDScript such as private and public here: https://github.com/godotengine/godot-proposals/issues/641 I feel like if a protected keyword were added, it'd make sense for it to follow the same access rules.

It looks like @export_custom may be coming in 4.3, with which you could try setting the PROPERTY_USAGE_READ_ONLY flag?

amarraff commented 1 month ago

This sounds like a neat idea, but I'd be worried about the specific term protected being used to mean this read-only behavior specifically. The C# documentation states that for that language,

protected: Only code in the same class or in a derived class can access this type or member.

There has been discussion of introducing access modifiers to GDScript such as private and public here: #641 I feel like if a protected keyword were added, it'd make sense for it to follow the same access rules.

It looks like @export_custom may be coming in 4.3, with which you could try setting the PROPERTY_USAGE_READ_ONLY flag?

Thanks for the input! @export_custom combined with a read only flag would only work with exports, but does seem like it'd be a working solution. "Protected" may not be the best word, it just made sense to me (protecting me from my own semantic mistakes lol). A more appropriate keyword that provides this kind of functionality would suffice :smiley:

m21-cerutti commented 1 month ago

An other proposition would an @editor_only annotation, that would add a "(Don't touch)" in a Inspector or be completely read_only in runtime. It is kind of different from @export_custom since it would allow you to change property_usage in editor versus runtime, I don't know if it would be possible with some usage flags. Could lead to the idea of @export_runtime and @export_editor to choose both flags between the two context, but could be boilerplate.