Skip to content

Commit

Permalink
GDScript: Add @export_custom annotation
Browse files Browse the repository at this point in the history
Allows setting any arbitrary hint, hint string, and usage flags.
Useful for more complex hints or potential future hints not
available as a dedicated annotation.
  • Loading branch information
vnen committed Mar 7, 2024
1 parent 24f7750 commit 8e52045
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 0 deletions.
12 changes: 12 additions & 0 deletions modules/gdscript/doc_classes/@GDScript.xml
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,18 @@
[/codeblock]
</description>
</annotation>
<annotation name="@export_custom">
<return type="void" />
<param index="0" name="hint" type="int" enum="PropertyHint" />
<param index="1" name="hint_string" type="String" />
<param index="2" name="usage" type="int" enum="PropertyUsageFlags" is_bitfield="true" default="6" />
<description>
Allows you to set a custom hint, hint string, and usage flags for the exported property. Note that there's no validation done in GDScript, it will just pass the hint along to the editor.
[codeblock]
@export_custom(PROPERTY_HINT_NONE, "suffix:m") var suffix: Vector3
[/codeblock]
</description>
</annotation>
<annotation name="@export_dir">
<return type="void" />
<description>
Expand Down
25 changes: 25 additions & 0 deletions modules/gdscript/gdscript_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ GDScriptParser::GDScriptParser() {
register_annotation(MethodInfo("@export_flags_3d_physics"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_LAYERS_3D_PHYSICS, Variant::INT>);
register_annotation(MethodInfo("@export_flags_3d_navigation"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_LAYERS_3D_NAVIGATION, Variant::INT>);
register_annotation(MethodInfo("@export_flags_avoidance"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_LAYERS_AVOIDANCE, Variant::INT>);
register_annotation(MethodInfo("@export_custom", PropertyInfo(Variant::INT, "hint", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_CLASS_IS_ENUM, "PropertyHint"), PropertyInfo(Variant::STRING, "hint_string"), PropertyInfo(Variant::INT, "usage", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_CLASS_IS_BITFIELD, "PropertyUsageFlags")), AnnotationInfo::VARIABLE, &GDScriptParser::export_custom_annotation, varray(PROPERTY_USAGE_DEFAULT));
// Export grouping annotations.
register_annotation(MethodInfo("@export_category", PropertyInfo(Variant::STRING, "name")), AnnotationInfo::STANDALONE, &GDScriptParser::export_group_annotations<PROPERTY_USAGE_CATEGORY>);
register_annotation(MethodInfo("@export_group", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::STRING, "prefix")), AnnotationInfo::STANDALONE, &GDScriptParser::export_group_annotations<PROPERTY_USAGE_GROUP>, varray(""));
Expand Down Expand Up @@ -4328,6 +4329,30 @@ bool GDScriptParser::export_annotations(const AnnotationNode *p_annotation, Node
return true;
}

bool GDScriptParser::export_custom_annotation(const AnnotationNode *p_annotation, Node *p_node, ClassNode *p_class) {
ERR_FAIL_COND_V_MSG(p_node->type != Node::VARIABLE, false, vformat(R"("%s" annotation can only be applied to variables.)", p_annotation->name));
ERR_FAIL_COND_V_MSG(p_annotation->resolved_arguments.size() < 2, false, R"(Annotation "@export_custom" requires 2 arguments.)");

VariableNode *variable = static_cast<VariableNode *>(p_node);
if (variable->exported) {
push_error(vformat(R"(Annotation "%s" cannot be used with another "@export" annotation.)", p_annotation->name), p_annotation);
return false;
}

variable->exported = true;

DataType export_type = variable->get_datatype();

variable->export_info.type = export_type.builtin_type;
variable->export_info.hint = static_cast<PropertyHint>(p_annotation->resolved_arguments[0].operator int64_t());
variable->export_info.hint_string = p_annotation->resolved_arguments[1];

if (p_annotation->resolved_arguments.size() >= 3) {
variable->export_info.usage = p_annotation->resolved_arguments[2].operator int64_t();
}
return true;
}

template <PropertyUsageFlags t_usage>
bool GDScriptParser::export_group_annotations(const AnnotationNode *p_annotation, Node *p_target, ClassNode *p_class) {
AnnotationNode *annotation = const_cast<AnnotationNode *>(p_annotation);
Expand Down
1 change: 1 addition & 0 deletions modules/gdscript/gdscript_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -1482,6 +1482,7 @@ class GDScriptParser {
bool onready_annotation(const AnnotationNode *p_annotation, Node *p_target, ClassNode *p_class);
template <PropertyHint t_hint, Variant::Type t_type>
bool export_annotations(const AnnotationNode *p_annotation, Node *p_target, ClassNode *p_class);
bool export_custom_annotation(const AnnotationNode *p_annotation, Node *p_target, ClassNode *p_class);
template <PropertyUsageFlags t_usage>
bool export_group_annotations(const AnnotationNode *p_annotation, Node *p_target, ClassNode *p_class);
bool warning_annotations(const AnnotationNode *p_annotation, Node *p_target, ClassNode *p_class);
Expand Down

0 comments on commit 8e52045

Please sign in to comment.