Implemented a literal syntax for NodePaths in GDScript I decided on using godot4's (^). The doc already said it's '@' but that was wrong.

This commit is contained in:
Relintai 2023-09-06 20:45:01 +02:00
parent 5121b0d56b
commit 7fab5e4c25
2 changed files with 33 additions and 23 deletions

View File

@ -5,21 +5,21 @@
</brief_description> </brief_description>
<description> <description>
A pre-parsed relative or absolute path in a scene tree, for use with [method Node.get_node] and similar functions. It can reference a node, a resource within a node, or a property of a node or resource. For instance, [code]"Path2D/PathFollow2D/Sprite:texture:size"[/code] would refer to the [code]size[/code] property of the [code]texture[/code] resource on the node named [code]"Sprite"[/code] which is a child of the other named nodes in the path. A pre-parsed relative or absolute path in a scene tree, for use with [method Node.get_node] and similar functions. It can reference a node, a resource within a node, or a property of a node or resource. For instance, [code]"Path2D/PathFollow2D/Sprite:texture:size"[/code] would refer to the [code]size[/code] property of the [code]texture[/code] resource on the node named [code]"Sprite"[/code] which is a child of the other named nodes in the path.
You will usually just pass a string to [method Node.get_node] and it will be automatically converted, but you may occasionally want to parse a path ahead of time with [NodePath] or the literal syntax [code]@"path"[/code]. Exporting a [NodePath] variable will give you a node selection widget in the properties panel of the editor, which can often be useful. You will usually just pass a string to [method Node.get_node] and it will be automatically converted, but you may occasionally want to parse a path ahead of time with [NodePath] or the literal syntax [code]^"path"[/code]. Exporting a [NodePath] variable will give you a node selection widget in the properties panel of the editor, which can often be useful.
A [NodePath] is composed of a list of slash-separated node names (like a filesystem path) and an optional colon-separated list of "subnames" which can be resources or properties. A [NodePath] is composed of a list of slash-separated node names (like a filesystem path) and an optional colon-separated list of "subnames" which can be resources or properties.
Some examples of NodePaths include the following: Some examples of NodePaths include the following:
[codeblock] [codeblock]
# No leading slash means it is relative to the current node. # No leading slash means it is relative to the current node.
@"A" # Immediate child A ^"A" # Immediate child A
@"A/B" # A's child B ^"A/B" # A's child B
@"." # The current node. ^"." # The current node.
@".." # The parent node. ^".." # The parent node.
@"../C" # A sibling node C. ^"../C" # A sibling node C.
@"../.." # The grandparent node. ^"../.." # The grandparent node.
# A leading slash means it is absolute from the SceneTree. # A leading slash means it is absolute from the SceneTree.
@"/root" # Equivalent to get_tree().get_root(). ^"/root" # Equivalent to get_tree().get_root().
@"/root/Main" # If your main scene's root node were named "Main". ^"/root/Main" # If your main scene's root node were named "Main".
@"/root/MyAutoload" # If you have an autoloaded node or scene. ^"/root/MyAutoload" # If you have an autoloaded node or scene.
[/codeblock] [/codeblock]
[b]Note:[/b] In the editor, [NodePath] properties are automatically updated when moving, renaming or deleting a node in the scene tree, but they are never updated at runtime. [b]Note:[/b] In the editor, [NodePath] properties are automatically updated when moving, renaming or deleting a node in the scene tree, but they are never updated at runtime.
</description> </description>

View File

@ -547,6 +547,7 @@ void GDScriptTokenizerText::_advance() {
} }
while (true) { while (true) {
bool is_string_name = false; bool is_string_name = false;
bool is_node_path = false;
StringMode string_mode = STRING_DOUBLE_QUOTE; StringMode string_mode = STRING_DOUBLE_QUOTE;
switch (GETCHAR(0)) { switch (GETCHAR(0)) {
@ -733,14 +734,13 @@ void GDScriptTokenizerText::_advance() {
case '$': case '$':
_make_token(TK_DOLLAR); //for the get_node() shortener _make_token(TK_DOLLAR); //for the get_node() shortener
break; break;
case '^': { case '%': {
if (GETCHAR(1) == '=') { if (GETCHAR(1) == '=') {
_make_token(TK_OP_ASSIGN_BIT_XOR); _make_token(TK_OP_ASSIGN_MOD);
INCPOS(1); INCPOS(1);
} else { } else {
_make_token(TK_OP_BIT_XOR); _make_token(TK_OP_MOD);
} }
} break; } break;
case '~': case '~':
_make_token(TK_OP_BIT_INVERT); _make_token(TK_OP_BIT_INVERT);
@ -800,21 +800,29 @@ void GDScriptTokenizerText::_advance() {
_make_token(TK_OP_SUB); _make_token(TK_OP_SUB);
} }
} break; } break;
case '%': { case '^': {
if (GETCHAR(1) == '=') { if (GETCHAR(1) == '=') {
_make_token(TK_OP_ASSIGN_MOD); _make_token(TK_OP_ASSIGN_BIT_XOR);
INCPOS(1); INCPOS(1);
break;
} else if (GETCHAR(1) == '"' || GETCHAR(1) == '\'') {
INCPOS(1);
is_node_path = true;
FALLTHROUGH;
} else { } else {
_make_token(TK_OP_MOD); _make_token(TK_OP_BIT_XOR);
break;
}
} }
} break;
case '@': case '@':
if (!is_node_path) {
if (CharType(GETCHAR(1)) != '"' && CharType(GETCHAR(1)) != '\'') { if (CharType(GETCHAR(1)) != '"' && CharType(GETCHAR(1)) != '\'') {
_make_error("Unexpected '@'"); _make_error("Unexpected '@'");
return; return;
} }
INCPOS(1); INCPOS(1);
is_string_name = true; is_string_name = true;
}
FALLTHROUGH; FALLTHROUGH;
case '\'': case '\'':
case '"': { case '"': {
@ -944,6 +952,8 @@ void GDScriptTokenizerText::_advance() {
if (is_string_name) { if (is_string_name) {
_make_constant(StringName(str)); _make_constant(StringName(str));
} else if (is_node_path) {
_make_constant(NodePath(str));
} else { } else {
_make_constant(str); _make_constant(str);
} }