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

Add @hide_from_dialog and @suffix annotations for GDScript classes #100690

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions core/object/script_language.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,10 @@ class Script : public Resource {
// Scripts are reloaded via the Script Editor when edited in Godot,
// the LSP server when edited in a connected external editor, or
// through EditorFileSystem::_update_script_documentation when updated directly on disk.
bool hide_from_dialog = false;
bool use_custom_suffix = false;
String script_custom_suffix;

virtual bool editor_can_reload_from_file() override { return false; }
void _notification(int p_what);
static void _bind_methods();
Expand Down Expand Up @@ -163,6 +167,10 @@ class Script : public Resource {

virtual MethodInfo get_method_info(const StringName &p_method) const = 0;

virtual bool is_hidden_from_dialog() const { return hide_from_dialog; }
virtual bool is_using_custom_script_suffix() const { return use_custom_suffix; }
virtual String get_script_custom_suffix() const { return script_custom_suffix; }

virtual bool is_tool() const = 0;
virtual bool is_valid() const = 0;
virtual bool is_abstract() const = 0;
Expand Down
17 changes: 15 additions & 2 deletions editor/create_dialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,10 @@ void CreateDialog::_add_type(const StringName &p_type, TypeCategory p_type_categ
}
ERR_FAIL_COND(scr.is_null());

if (scr->is_hidden_from_dialog()) {
return;
}

Ref<Script> base = scr->get_base_script();
if (base.is_null()) {
// Must be a native base type.
Expand All @@ -262,6 +266,11 @@ void CreateDialog::_add_type(const StringName &p_type, TypeCategory p_type_categ
inherits = extends;
inherited_type = TypeCategory::CPP_TYPE;
} else {
// If the base script is hidden from dialog, the child should not appear as well.
if (base->is_hidden_from_dialog()) {
return;
}

inherits = base->get_global_name();

if (inherits == StringName()) {
Expand Down Expand Up @@ -306,8 +315,12 @@ void CreateDialog::_configure_search_option_item(TreeItem *r_item, const StringN
String script_path = ScriptServer::get_global_class_path(p_type);
Ref<Script> scr = ResourceLoader::load(script_path, "Script");
String suffix = script_path.get_file();
if (scr.is_valid() && custom_type_suffixes.has(p_type)) {
suffix = custom_type_suffixes.get(p_type);
if (scr.is_valid()) {
if (custom_type_suffixes.has(p_type)) {
suffix = custom_type_suffixes.get(p_type);
} else if (scr->is_using_custom_script_suffix()) {
suffix = scr->get_script_custom_suffix();
}
}
if (!suffix.is_empty()) {
r_item->set_suffix(0, "(" + suffix + ")");
Expand Down
14 changes: 14 additions & 0 deletions modules/gdscript/doc_classes/@GDScript.xml
Original file line number Diff line number Diff line change
Expand Up @@ -716,6 +716,12 @@
[b]Note:[/b] Avoid storing lambda callables in member variables of [RefCounted]-based classes (e.g. resources), as this can lead to memory leaks. Use only method callables and optionally [method Callable.bind] or [method Callable.unbind].
</description>
</annotation>
<annotation name="@hide_from_dialog">
<return type="void" />
<description>
Hides the current script from all create dialogs, if the current class has a global type name. This does not take effect for a script that has no global type name, as it is generally hidden from the dialogs.
</description>
</annotation>
<annotation name="@icon">
<return type="void" />
<param index="0" name="icon_path" type="String" />
Expand Down Expand Up @@ -771,6 +777,14 @@
[b]Warning:[/b] Currently, due to a bug, scripts are never freed, even if [annotation @static_unload] annotation is used.
</description>
</annotation>
<annotation name="@suffix">
<return type="void" />
<param index="0" name="suffix" type="String" />
<description>
Set a custom suffix for the current script. In a create dialog, if the class has a global type name, this annotation will replace the file name (which is following the type name and quoted in a couple of braces) with the suffix you set.
[b]Note:[/b] An empty suffix is allowed, but it will hide the suffix from all create dialogs.
</description>
</annotation>
<annotation name="@tool">
<return type="void" />
<description>
Expand Down
3 changes: 3 additions & 0 deletions modules/gdscript/gdscript_compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3090,6 +3090,9 @@ void GDScriptCompiler::make_scripts(GDScript *p_script, const GDScriptParser::Cl
p_script->local_name = p_class->identifier ? p_class->identifier->name : StringName();
p_script->global_name = p_class->get_global_name();
p_script->simplified_icon_path = p_class->simplified_icon_path;
p_script->hide_from_dialog = p_class->hide_from_dialog;
p_script->use_custom_suffix = p_class->set_custom_suffix;
p_script->script_custom_suffix = p_class->suffix;

HashMap<StringName, Ref<GDScript>> old_subclasses;

Expand Down
28 changes: 28 additions & 0 deletions modules/gdscript/gdscript_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ GDScriptParser::GDScriptParser() {
register_annotation(MethodInfo("@tool"), AnnotationInfo::SCRIPT, &GDScriptParser::tool_annotation);
register_annotation(MethodInfo("@icon", PropertyInfo(Variant::STRING, "icon_path")), AnnotationInfo::SCRIPT, &GDScriptParser::icon_annotation);
register_annotation(MethodInfo("@static_unload"), AnnotationInfo::SCRIPT, &GDScriptParser::static_unload_annotation);
register_annotation(MethodInfo("@hide_from_dialog"), AnnotationInfo::SCRIPT, &GDScriptParser::hide_from_dialog_annotation);
register_annotation(MethodInfo("@suffix", PropertyInfo(Variant::STRING, "suffix")), AnnotationInfo::SCRIPT, &GDScriptParser::suffix_annotation, varray());
// Onready annotation.
register_annotation(MethodInfo("@onready"), AnnotationInfo::VARIABLE, &GDScriptParser::onready_annotation);
// Export annotations.
Expand Down Expand Up @@ -4285,6 +4287,32 @@ bool GDScriptParser::onready_annotation(AnnotationNode *p_annotation, Node *p_ta
return true;
}

bool GDScriptParser::hide_from_dialog_annotation(AnnotationNode *p_annotation, Node *p_target, ClassNode *p_class) {
ERR_FAIL_COND_V_MSG(p_target->type != Node::CLASS, false, vformat(R"("%s" annotation can only be applied to classes.)", p_annotation->name));
ClassNode *class_node = static_cast<ClassNode *>(p_target);
if (class_node->hide_from_dialog) {
push_error(vformat(R"("%s" annotation can only be used once per script.)", p_annotation->name), p_annotation);
return false;
}
class_node->hide_from_dialog = true;
return true;
}

bool GDScriptParser::suffix_annotation(AnnotationNode *p_annotation, Node *p_target, ClassNode *p_class) {
ERR_FAIL_COND_V_MSG(p_target->type != Node::CLASS, false, vformat(R"("%s" annotation can only be applied to classes.)", p_annotation->name));

ClassNode *class_node = static_cast<ClassNode *>(p_target);
if (class_node->set_custom_suffix) {
push_error(vformat(R"("%s" annotation can only be used once per script.)", p_annotation->name), p_annotation);
return false;
}
class_node->set_custom_suffix = true;

String path = p_annotation->resolved_arguments[0];
class_node->suffix = path;
return true;
}

static String _get_annotation_error_string(const StringName &p_annotation_name, const Vector<Variant::Type> &p_expected_types, const GDScriptParser::DataType &p_provided_type) {
Vector<String> types;
for (int i = 0; i < p_expected_types.size(); i++) {
Expand Down
5 changes: 5 additions & 0 deletions modules/gdscript/gdscript_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -744,6 +744,9 @@ class GDScriptParser {
IdentifierNode *identifier = nullptr;
String icon_path;
String simplified_icon_path;
bool hide_from_dialog = false;
bool set_custom_suffix = false;
String suffix;
Vector<Member> members;
HashMap<StringName, int> members_indices;
ClassNode *outer = nullptr;
Expand Down Expand Up @@ -1510,6 +1513,8 @@ class GDScriptParser {
bool icon_annotation(AnnotationNode *p_annotation, Node *p_target, ClassNode *p_class);
bool static_unload_annotation(AnnotationNode *p_annotation, Node *p_target, ClassNode *p_class);
bool onready_annotation(AnnotationNode *p_annotation, Node *p_target, ClassNode *p_class);
bool hide_from_dialog_annotation(AnnotationNode *p_annotation, Node *p_target, ClassNode *p_class);
bool suffix_annotation(AnnotationNode *p_annotation, Node *p_target, ClassNode *p_class);
template <PropertyHint t_hint, Variant::Type t_type>
bool export_annotations(AnnotationNode *p_annotation, Node *p_target, ClassNode *p_class);
bool export_storage_annotation(AnnotationNode *p_annotation, Node *p_target, ClassNode *p_class);
Expand Down