Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ability to dynamically hide exported variables in the inspector #1056

Closed
PLyczkowski opened this issue Jun 14, 2020 · 12 comments
Closed

Ability to dynamically hide exported variables in the inspector #1056

PLyczkowski opened this issue Jun 14, 2020 · 12 comments

Comments

@PLyczkowski
Copy link

Describe the project you are working on:

This could help in any game project.

Describe the problem or limitation you are having in your project:

The inspector currently shows all exported variables, irregardless of whether they have any effect in current setup or not.

Example:

image

Here Illustration Texture and Custom Display fields have an effect only when certain modes are chosen in the Display Mode field.
Having them displayed anyway creates confusion, for example for the game content creators (non-programmers).

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

This feature would allow to add logic to scripts that would dynamically control the visibility of exported variables in the Inspector.

Describe how your proposal will work, with code, pseudocode, mockups, and/or diagrams:

Here is some pseudocode:

tool
extends Node

export(Enums.EntityDisplayModes) var display_mode = Enums.EntityDisplayModes.MODE_ICON

# This will be shown if display_mode is icon
export var icon_border
export var icon_texture

# This will be shown if display_mode is card
export var card_border
export var card_texture

export(bool) var has_special_frame = false

# This will be shown if has_special_frame is true
export(Color) var special_frame_color

func _init():
  if Engine.is_editor_hint():
    if display_mode = Enums.EntityDisplayModes.MODE_ICON:
      hide_property("card_border")
      hide_property("card_texture")
    elif display_mode = Enums.EntityDisplayModes.MODE_CARD:
      hide_property("icon_border")
      hide_property("icon_texture")
      
    if !has_special_frame:
      hide_property("special_frame_color")

This enhancement could also be extended to allow for foldable sections of exported variables.

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

No.

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

Afaik this can't be done using add-ons.

@PLyczkowski
Copy link
Author

This enhancement has also been discussed here: godotengine/godot#5988

@Calinou
Copy link
Member

Calinou commented Jun 14, 2020

This can be done manually by overriding the _get_property_list() method instead of using the export syntax.

Still, since GDScript is being rewritten with an annotation system, it makes sense to make foldable sections accessible with an easier syntax.

@bmolyneaux
Copy link

@Calinou AFAIK that solution doesn't help in the case that you want to hide properties from an inherited base class.

For example, let's say I want to create a new node type which extends AudioStreamPlayer to randomly play one of an array of AudioStreams. I effectively want to replace the stream property of the base class with a new streams array property. However, both properties will be displayed in the inspector, even though the original stream property should no longer be set by the user.

My chosen workaround for this is to override _set() to prevent setting the base class's stream property and push an appropriate warning. (I would prefer to implement this as a custom AudioStream resource instead of an AudioStreamPlayer, but that has another set of issues)

If this is too off-topic, but something that could still be considered, I can file a separate issue.

@aXu-AP
Copy link

aXu-AP commented May 31, 2022

I think following syntax would be simple and understandable (altough extra export may sound redundant):

@export_if(condition)
@export
var hideable_property = "Can you see me?"

Alternatively invert it (@hide_if(condition)).

@setzer22
Copy link

setzer22 commented Jun 28, 2022

This can be done manually by overriding the _get_property_list() method instead of using the export syntax.

Still, since GDScript is being rewritten with an annotation system, it makes sense to make foldable sections accessible with an easier syntax.

I was looking for a workaround to this issue and stumbled upon this comment. It's worth noting that the link shared by @Calinou is pointing to latest, and that section is now gone (because latest points to Godot 4 docs). Here's the right link for 3.5 😄 https://docs.godotengine.org/en/3.5/tutorials/scripting/gdscript/gdscript_exports.html#advanced-exports

@CyanSlinky
Copy link

So I'm currently trying to hide an export variable based on a condition, do I still need to use _get_property_list() in Godot 4 or is there an alternative? would be nice if there was something like "@export_if(condition)" or similar like @aXu-AP was suggesting.

@YuriSizov
Copy link
Contributor

You still need to use _get_property_list() in Godot 4.

@CyanSlinky
Copy link

Would it be possible to introduce something like "@hide_if(condition)" and "@show_if(condition)" that could be used alongside "@export"? or an "@export_if(condition)"?

@YuriSizov
Copy link
Contributor

YuriSizov commented Mar 22, 2023

Well, this is what this proposal about. It's still open, so it's still possible. Whether it will, and in which form, I can't tell you. Nobody tried implementing it yet. And it hasn't been discussed by the area maintainers whether it makes sense and whether the proposed syntax makes sense.

@KoBeWi
Copy link
Member

KoBeWi commented May 17, 2023

I think this proposal will be resolved once godotengine/godot#75778 is merged. You will be able to do

func _validate_property(property):
    if property.name == "hide_me_if_something" and something:
        property.usage &= ~PROPERTY_USAGE_EDITOR

@KoBeWi
Copy link
Member

KoBeWi commented Oct 24, 2023

The aforementioned PR was merged.
@PLyczkowski Can you check if the new functionality in 4.2 solves your problem?

@PLyczkowski
Copy link
Author

With the above merge this is how the original example can be done:

@tool
extends Node

@export var display_mode := Enums.EntityDisplayModes.MODE_ICON:
	set(value):
		display_mode = value
		notify_property_list_changed()

# This will be shown if display_mode is icon
@export var icon_border
@export var icon_texture

# This will be shown if display_mode is card
@export var card_border
@export var card_texture

@export var has_special_frame := false:
	set(value):
		has_special_frame = value
		notify_property_list_changed()

# This will be shown if has_special_frame is true
@export var special_frame_color: Color

func _validate_property(property: Dictionary):
	if property.name in ["icon_border", "icon_texture"] and display_mode != Enums.EntityDisplayModes.MODE_ICON:
		property.usage = PROPERTY_USAGE_NO_EDITOR
	elif property.name in ["card_border", "card_texture"] and display_mode != Enums.EntityDisplayModes.MODE_CARD:
		property.usage = PROPERTY_USAGE_NO_EDITOR
	elif property.name in ["special_frame_color"] and not has_special_frame:
		property.usage = PROPERTY_USAGE_NO_EDITOR

An exported var can also be set to not be editable with PROPERTY_USAGE_READONLY

With this this proposal can be closed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants