godot-proposals icon indicating copy to clipboard operation
godot-proposals copied to clipboard

Add `@export_internal` that prevents an exported variable from being edited as a scene instance

Open greenfox1505 opened this issue 1 year ago • 6 comments

Describe the project you are working on

I have scenes whose root nodes contain the bulk of the script which @export lots of nodes that should not be edited outside the original node. For example, a menu might be instantiated in lots of buttons and properties, but you wouldn't want some of those to be modified by something else.

Describe the problem or limitation you are having in your project

A character controller might have internal references to a camera, or a player's model or hands for an FPS. When that character is instanced, those references should not change outside the scope of that scene.

A menu might show or hide elements and we want to set those variables from editor, but when that menu is instanced, those internal references shouldn't change.

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

Either a new @export_internal or an argument to existing exports like @export...(internal=true). When a node is the current root node of a scene, it should display those variables in editor. When it isn't the root node, hide them.

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

image

This camera variable should ONLY be visible when the current scene is the Player. Otherwise, when it is instanced, it should be hidden. The main scene shouldn't need to be able to change the player's camera.

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

I could use @onready var camera:=%Camera2D. Nothing is exposed to inspector. But that breaks when a node is renamed and cannot be easily set from the internal inspector, only in script. If I reuse the same script in a lot of places, that adds an enforcement on node naming, which can be fragile.

I could create a custom editor and flag each of those variables that shouldn't show. This is a large task for such a small button.

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

I don't believe there is currently a way to add @ properties to the engine in add-ons.

greenfox1505 avatar Jul 05 '24 20:07 greenfox1505

You can achieve this with _validate_property(), but the script has to be @tool:

@tool
extends Node2D

@export var variable1: String
@export var variable2: String

func _validate_property(property: Dictionary) -> void:
	if property.usage & PROPERTY_USAGE_SCRIPT_VARIABLE:
		if is_inside_tree() and get_tree().edited_scene_root != self:
			property.usage &= ~PROPERTY_USAGE_EDITOR

KoBeWi avatar Jul 05 '24 20:07 KoBeWi

That's a partial solution. But not every property should be hidden, just the ones I want hidden. A players speed, jumphight, etc should all be exposed. So then I have to keep a list of "hide these". And adding that kind of code to the character controller is very ugly bloat.

It also means I have to add if Engine.is_editor_hint() == true; return to a lot of functions that I only want to run at runtime. Again, adding overhead and bloat to a character controller.

It's a partial solution though.

greenfox1505 avatar Jul 06 '24 21:07 greenfox1505

So then I have to keep a list of "hide these".

You can use @export_custom for that. But yeah, it's only a workaround.

KoBeWi avatar Jul 06 '24 21:07 KoBeWi

Another workaround is to treat the scene root as public, and then place any internal exports on child nodes.

shanayyy avatar Jul 09 '24 01:07 shanayyy

Ah, glad to see I'm not the only one wanting this behavior 😄

I filed a proposal for this kind of behavior a while back, and received some feedback on it: https://github.com/godotengine/godot-proposals/issues/10024

I implemented it as the @export_if_root annotation in Godot itself: https://github.com/godotengine/godot/pull/93528

There didn't seem to be a lot of support for merging it into the engine, unfortunately. My recollection is that Mickeon's suggestion of an addon was the best interim solution, at least, since it didn't require annotating all of the gameplay scripts with @tool and then having to add checking code for editor versus gameplay.

Meorge avatar Jul 10 '24 16:07 Meorge

I am facing the same need here. However I feel like a better approach for this would be to add an additional argument to @export_group

Image

The new signature of the annotation would be : @export_group(name : String, prefix : String = "", internal=false) This would blend nicely in existing design, and avoid additional keywords

Altarick avatar Mar 18 '25 13:03 Altarick