| 1866 | } |
| 1867 | |
| 1868 | Node *Node::get_node_or_null(const NodePath &p_path) const { |
| 1869 | ERR_THREAD_GUARD_V(nullptr); |
| 1870 | if (p_path.is_empty()) { |
| 1871 | return nullptr; |
| 1872 | } |
| 1873 | |
| 1874 | ERR_FAIL_COND_V_MSG(!data.tree && p_path.is_absolute(), nullptr, "Can't use get_node() with absolute paths from outside the active scene tree."); |
| 1875 | |
| 1876 | Node *current = nullptr; |
| 1877 | Node *root = nullptr; |
| 1878 | |
| 1879 | if (!p_path.is_absolute()) { |
| 1880 | current = const_cast<Node *>(this); //start from this |
| 1881 | } else { |
| 1882 | root = const_cast<Node *>(this); |
| 1883 | while (root->data.parent) { |
| 1884 | root = root->data.parent; //start from root |
| 1885 | } |
| 1886 | } |
| 1887 | |
| 1888 | for (int i = 0; i < p_path.get_name_count(); i++) { |
| 1889 | StringName name = p_path.get_name(i); |
| 1890 | Node *next = nullptr; |
| 1891 | |
| 1892 | if (name == SNAME(".")) { |
| 1893 | next = current; |
| 1894 | |
| 1895 | } else if (name == SNAME("..")) { |
| 1896 | if (current == nullptr || !current->data.parent) { |
| 1897 | return nullptr; |
| 1898 | } |
| 1899 | |
| 1900 | next = current->data.parent; |
| 1901 | } else if (current == nullptr) { |
| 1902 | if (name == root->get_name()) { |
| 1903 | next = root; |
| 1904 | } |
| 1905 | |
| 1906 | } else if (name.is_node_unique_name()) { |
| 1907 | Node **unique = current->data.owned_unique_nodes.getptr(name); |
| 1908 | if (!unique && current->data.owner) { |
| 1909 | unique = current->data.owner->data.owned_unique_nodes.getptr(name); |
| 1910 | } |
| 1911 | if (!unique) { |
| 1912 | return nullptr; |
| 1913 | } |
| 1914 | next = *unique; |
| 1915 | } else { |
| 1916 | next = nullptr; |
| 1917 | const Node *const *node = current->data.children.getptr(name); |
| 1918 | if (node) { |
| 1919 | next = const_cast<Node *>(*node); |
| 1920 | } else { |
| 1921 | return nullptr; |
| 1922 | } |
| 1923 | } |
| 1924 | current = next; |
| 1925 | } |
no test coverage detected