summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/linux_builds.yml12
-rw-r--r--core/templates/hashfuncs.h175
-rw-r--r--core/variant/variant.cpp96
-rw-r--r--doc/classes/NavigationAgent2D.xml4
-rw-r--r--doc/classes/NavigationAgent3D.xml4
-rw-r--r--doc/classes/NavigationRegion2D.xml4
-rw-r--r--doc/classes/NavigationRegion3D.xml4
-rw-r--r--doc/classes/NavigationServer2D.xml30
-rw-r--r--doc/classes/NavigationServer3D.xml30
-rw-r--r--doc/classes/PopupMenu.xml15
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp47
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.h2
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp76
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.h2
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp25
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.h21
-rw-r--r--drivers/gles3/shaders/canvas.glsl10
-rw-r--r--drivers/gles3/shaders/scene.glsl24
-rw-r--r--drivers/gles3/storage/mesh_storage.cpp270
-rw-r--r--drivers/gles3/storage/mesh_storage.h1
-rw-r--r--editor/editor_path.cpp2
-rw-r--r--editor/editor_properties_array_dict.cpp2
-rw-r--r--editor/plugins/input_event_editor_plugin.cpp3
-rw-r--r--editor/project_converter_3_to_4.cpp3811
-rw-r--r--editor/project_converter_3_to_4.h83
-rw-r--r--editor/scene_tree_dock.cpp2
-rw-r--r--main/main.cpp29
-rw-r--r--misc/dist/shell/_godot.zsh-completion2
-rw-r--r--misc/dist/shell/godot.bash-completion2
-rw-r--r--misc/dist/shell/godot.fish2
-rw-r--r--modules/gdscript/gdscript_compiler.cpp93
-rw-r--r--modules/gdscript/tests/scripts/parser/features/match_dictionary.gd43
-rw-r--r--modules/gdscript/tests/scripts/parser/features/match_dictionary.out15
-rw-r--r--modules/gdscript/tests/scripts/parser/features/match_multiple_patterns_with_array.gd26
-rw-r--r--modules/gdscript/tests/scripts/parser/features/match_multiple_patterns_with_array.out9
-rw-r--r--modules/gridmap/grid_map.cpp8
-rw-r--r--modules/gridmap/grid_map.h2
-rw-r--r--modules/navigation/godot_navigation_server.cpp12
-rw-r--r--modules/navigation/godot_navigation_server.h6
-rw-r--r--modules/navigation/nav_map.cpp6
-rw-r--r--modules/navigation/nav_map.h2
-rw-r--r--modules/navigation/nav_region.cpp8
-rw-r--r--modules/navigation/nav_region.h6
-rw-r--r--modules/openxr/openxr_api.cpp6
-rw-r--r--modules/openxr/openxr_api.h6
-rw-r--r--modules/text_server_adv/text_server_adv.cpp2
-rw-r--r--modules/text_server_adv/text_server_adv.h2
-rw-r--r--modules/text_server_fb/text_server_fb.cpp2
-rw-r--r--modules/text_server_fb/text_server_fb.h2
-rw-r--r--scene/2d/navigation_agent_2d.cpp22
-rw-r--r--scene/2d/navigation_agent_2d.h6
-rw-r--r--scene/2d/navigation_region_2d.cpp14
-rw-r--r--scene/2d/navigation_region_2d.h4
-rw-r--r--scene/3d/navigation_agent_3d.cpp22
-rw-r--r--scene/3d/navigation_agent_3d.h6
-rw-r--r--scene/3d/navigation_region_3d.cpp14
-rw-r--r--scene/3d/navigation_region_3d.h4
-rw-r--r--scene/gui/popup_menu.cpp9
-rw-r--r--scene/gui/popup_menu.h3
-rw-r--r--servers/navigation_server_2d.cpp10
-rw-r--r--servers/navigation_server_2d.h6
-rw-r--r--servers/navigation_server_3d.cpp6
-rw-r--r--servers/navigation_server_3d.h6
63 files changed, 4652 insertions, 526 deletions
diff --git a/.github/workflows/linux_builds.yml b/.github/workflows/linux_builds.yml
index 338278f461..3df4409041 100644
--- a/.github/workflows/linux_builds.yml
+++ b/.github/workflows/linux_builds.yml
@@ -28,6 +28,7 @@ jobs:
doc-test: true
bin: "./bin/godot.linuxbsd.opt.tools.64.mono"
build-mono: true
+ proj-conv: true
artifact: true
- name: Editor with doubles and GCC sanitizers (target=debug, tools=yes, float=64, tests=yes, use_asan=yes, use_ubsan=yes)
@@ -147,6 +148,17 @@ jobs:
curr="$(pwd)/libvk_swiftshader.so"
sed -i "s|PATH_TO_CHANGE|$curr|" vk_swiftshader_icd.json
+ # Test 3.x -> 4.x project converter
+ - name: Test project converter
+ if: ${{ matrix.proj-conv }}
+ run: |
+ mkdir converter_test
+ cd converter_test
+ touch project.godot
+ ../${{ matrix.bin }} --headless --audio-driver Dummy --validate-conversion-3to4
+ cd ..
+ rm converter_test -rf
+
# Download and extract zip archive with project, folder is renamed to be able to easy change used project
- name: Download test project
if: ${{ matrix.proj-test }}
diff --git a/core/templates/hashfuncs.h b/core/templates/hashfuncs.h
index 1330d55270..98ff7fa4ce 100644
--- a/core/templates/hashfuncs.h
+++ b/core/templates/hashfuncs.h
@@ -56,7 +56,7 @@
* @param C String
* @return 32-bits hashcode
*/
-static inline uint32_t hash_djb2(const char *p_cstr) {
+static _FORCE_INLINE_ uint32_t hash_djb2(const char *p_cstr) {
const unsigned char *chr = (const unsigned char *)p_cstr;
uint32_t hash = 5381;
uint32_t c;
@@ -68,7 +68,7 @@ static inline uint32_t hash_djb2(const char *p_cstr) {
return hash;
}
-static inline uint32_t hash_djb2_buffer(const uint8_t *p_buff, int p_len, uint32_t p_prev = 5381) {
+static _FORCE_INLINE_ uint32_t hash_djb2_buffer(const uint8_t *p_buff, int p_len, uint32_t p_prev = 5381) {
uint32_t hash = p_prev;
for (int i = 0; i < p_len; i++) {
@@ -78,7 +78,7 @@ static inline uint32_t hash_djb2_buffer(const uint8_t *p_buff, int p_len, uint32
return hash;
}
-static inline uint32_t hash_djb2_one_32(uint32_t p_in, uint32_t p_prev = 5381) {
+static _FORCE_INLINE_ uint32_t hash_djb2_one_32(uint32_t p_in, uint32_t p_prev = 5381) {
return ((p_prev << 5) + p_prev) + p_in;
}
@@ -89,7 +89,7 @@ static inline uint32_t hash_djb2_one_32(uint32_t p_in, uint32_t p_prev = 5381) {
* @param p_int - 64-bit unsigned integer key to be hashed
* @return unsigned 32-bit value representing hashcode
*/
-static inline uint32_t hash_one_uint64(const uint64_t p_int) {
+static _FORCE_INLINE_ uint32_t hash_one_uint64(const uint64_t p_int) {
uint64_t v = p_int;
v = (~v) + (v << 18); // v = (v << 18) - v - 1;
v = v ^ (v >> 31);
@@ -100,7 +100,72 @@ static inline uint32_t hash_one_uint64(const uint64_t p_int) {
return uint32_t(v);
}
-static inline uint32_t hash_djb2_one_float(double p_in, uint32_t p_prev = 5381) {
+// Murmurhash3 32-bit version.
+// All MurmurHash versions are public domain software, and the author disclaims all copyright to their code.
+
+static _FORCE_INLINE_ uint32_t rotl32(uint32_t x, int8_t r) {
+ return (x << r) | (x >> (32 - r));
+}
+
+static _FORCE_INLINE_ uint32_t fmix32(uint32_t h) {
+ h ^= h >> 16;
+ h *= 0x85ebca6b;
+ h ^= h >> 13;
+ h *= 0xc2b2ae35;
+ h ^= h >> 16;
+
+ return h;
+}
+
+static _FORCE_INLINE_ uint32_t hash_murmur3_32(const void *key, int length, const uint32_t seed = 0x7F07C65) {
+ // Although not required, this is a random prime number.
+ const uint8_t *data = (const uint8_t *)key;
+ const int nblocks = length / 4;
+
+ uint32_t h1 = seed;
+
+ const uint32_t c1 = 0xcc9e2d51;
+ const uint32_t c2 = 0x1b873593;
+
+ const uint32_t *blocks = (const uint32_t *)(data + nblocks * 4);
+
+ for (int i = -nblocks; i; i++) {
+ uint32_t k1 = blocks[i];
+
+ k1 *= c1;
+ k1 = rotl32(k1, 15);
+ k1 *= c2;
+
+ h1 ^= k1;
+ h1 = rotl32(h1, 13);
+ h1 = h1 * 5 + 0xe6546b64;
+ }
+
+ const uint8_t *tail = (const uint8_t *)(data + nblocks * 4);
+
+ uint32_t k1 = 0;
+
+ switch (length & 3) {
+ case 3:
+ k1 ^= tail[2] << 16;
+ [[fallthrough]];
+ case 2:
+ k1 ^= tail[1] << 8;
+ [[fallthrough]];
+ case 1:
+ k1 ^= tail[0];
+ k1 *= c1;
+ k1 = rotl32(k1, 15);
+ k1 *= c2;
+ h1 ^= k1;
+ };
+
+ // Finalize with additional bit mixing.
+ h1 ^= length;
+ return fmix32(h1);
+}
+
+static _FORCE_INLINE_ uint32_t hash_djb2_one_float(double p_in, uint32_t p_prev = 5381) {
union {
double d;
uint64_t i;
@@ -119,7 +184,7 @@ static inline uint32_t hash_djb2_one_float(double p_in, uint32_t p_prev = 5381)
}
template <class T>
-static inline uint32_t make_uint32_t(T p_in) {
+static _FORCE_INLINE_ uint32_t make_uint32_t(T p_in) {
union {
T t;
uint32_t _u32;
@@ -129,7 +194,7 @@ static inline uint32_t make_uint32_t(T p_in) {
return _u._u32;
}
-static inline uint64_t hash_djb2_one_float_64(double p_in, uint64_t p_prev = 5381) {
+static _FORCE_INLINE_ uint64_t hash_djb2_one_float_64(double p_in, uint64_t p_prev = 5381) {
union {
double d;
uint64_t i;
@@ -147,12 +212,12 @@ static inline uint64_t hash_djb2_one_float_64(double p_in, uint64_t p_prev = 538
return ((p_prev << 5) + p_prev) + u.i;
}
-static inline uint64_t hash_djb2_one_64(uint64_t p_in, uint64_t p_prev = 5381) {
+static _FORCE_INLINE_ uint64_t hash_djb2_one_64(uint64_t p_in, uint64_t p_prev = 5381) {
return ((p_prev << 5) + p_prev) + p_in;
}
template <class T>
-static inline uint64_t make_uint64_t(T p_in) {
+static _FORCE_INLINE_ uint64_t make_uint64_t(T p_in) {
union {
T t;
uint64_t _u64;
@@ -167,78 +232,40 @@ template <class T>
class Ref;
struct HashMapHasherDefault {
- static _FORCE_INLINE_ uint32_t hash(const String &p_string) { return p_string.hash(); }
- static _FORCE_INLINE_ uint32_t hash(const char *p_cstr) { return hash_djb2(p_cstr); }
- static _FORCE_INLINE_ uint32_t hash(const uint64_t p_int) { return hash_one_uint64(p_int); }
- static _FORCE_INLINE_ uint32_t hash(const ObjectID &p_id) { return hash_one_uint64(p_id); }
-
- static _FORCE_INLINE_ uint32_t hash(const int64_t p_int) { return hash(uint64_t(p_int)); }
- static _FORCE_INLINE_ uint32_t hash(const float p_float) { return hash_djb2_one_float(p_float); }
- static _FORCE_INLINE_ uint32_t hash(const double p_double) { return hash_djb2_one_float(p_double); }
- static _FORCE_INLINE_ uint32_t hash(const uint32_t p_int) { return p_int; }
- static _FORCE_INLINE_ uint32_t hash(const int32_t p_int) { return (uint32_t)p_int; }
- static _FORCE_INLINE_ uint32_t hash(const uint16_t p_int) { return p_int; }
- static _FORCE_INLINE_ uint32_t hash(const int16_t p_int) { return (uint32_t)p_int; }
- static _FORCE_INLINE_ uint32_t hash(const uint8_t p_int) { return p_int; }
- static _FORCE_INLINE_ uint32_t hash(const int8_t p_int) { return (uint32_t)p_int; }
- static _FORCE_INLINE_ uint32_t hash(const wchar_t p_wchar) { return (uint32_t)p_wchar; }
- static _FORCE_INLINE_ uint32_t hash(const char16_t p_uchar) { return (uint32_t)p_uchar; }
- static _FORCE_INLINE_ uint32_t hash(const char32_t p_uchar) { return (uint32_t)p_uchar; }
- static _FORCE_INLINE_ uint32_t hash(const RID &p_rid) { return hash_one_uint64(p_rid.get_id()); }
-
- static _FORCE_INLINE_ uint32_t hash(const StringName &p_string_name) { return p_string_name.hash(); }
- static _FORCE_INLINE_ uint32_t hash(const NodePath &p_path) { return p_path.hash(); }
-
+ // Generic hash function for any type.
template <class T>
static _FORCE_INLINE_ uint32_t hash(const T *p_pointer) { return hash_one_uint64((uint64_t)p_pointer); }
template <class T>
static _FORCE_INLINE_ uint32_t hash(const Ref<T> &p_ref) { return hash_one_uint64((uint64_t)p_ref.operator->()); }
- static _FORCE_INLINE_ uint32_t hash(const Vector2i &p_vec) {
- uint32_t h = hash_djb2_one_32(p_vec.x);
- return hash_djb2_one_32(p_vec.y, h);
- }
- static _FORCE_INLINE_ uint32_t hash(const Vector3i &p_vec) {
- uint32_t h = hash_djb2_one_32(p_vec.x);
- h = hash_djb2_one_32(p_vec.y, h);
- return hash_djb2_one_32(p_vec.z, h);
- }
-
- static _FORCE_INLINE_ uint32_t hash(const Vector2 &p_vec) {
- uint32_t h = hash_djb2_one_float(p_vec.x);
- return hash_djb2_one_float(p_vec.y, h);
- }
- static _FORCE_INLINE_ uint32_t hash(const Vector3 &p_vec) {
- uint32_t h = hash_djb2_one_float(p_vec.x);
- h = hash_djb2_one_float(p_vec.y, h);
- return hash_djb2_one_float(p_vec.z, h);
- }
-
- static _FORCE_INLINE_ uint32_t hash(const Rect2i &p_rect) {
- uint32_t h = hash_djb2_one_32(p_rect.position.x);
- h = hash_djb2_one_32(p_rect.position.y, h);
- h = hash_djb2_one_32(p_rect.size.x, h);
- return hash_djb2_one_32(p_rect.size.y, h);
- }
-
- static _FORCE_INLINE_ uint32_t hash(const Rect2 &p_rect) {
- uint32_t h = hash_djb2_one_float(p_rect.position.x);
- h = hash_djb2_one_float(p_rect.position.y, h);
- h = hash_djb2_one_float(p_rect.size.x, h);
- return hash_djb2_one_float(p_rect.size.y, h);
- }
-
- static _FORCE_INLINE_ uint32_t hash(const AABB &p_aabb) {
- uint32_t h = hash_djb2_one_float(p_aabb.position.x);
- h = hash_djb2_one_float(p_aabb.position.y, h);
- h = hash_djb2_one_float(p_aabb.position.z, h);
- h = hash_djb2_one_float(p_aabb.size.x, h);
- h = hash_djb2_one_float(p_aabb.size.y, h);
- return hash_djb2_one_float(p_aabb.size.z, h);
- }
+ static _FORCE_INLINE_ uint32_t hash(const String &p_string) { return p_string.hash(); }
+ static _FORCE_INLINE_ uint32_t hash(const char *p_cstr) { return hash_djb2(p_cstr); }
+ static _FORCE_INLINE_ uint32_t hash(const wchar_t p_wchar) { return fmix32(p_wchar); }
+ static _FORCE_INLINE_ uint32_t hash(const char16_t p_uchar) { return fmix32(p_uchar); }
+ static _FORCE_INLINE_ uint32_t hash(const char32_t p_uchar) { return fmix32(p_uchar); }
+ static _FORCE_INLINE_ uint32_t hash(const RID &p_rid) { return hash_one_uint64(p_rid.get_id()); }
+ static _FORCE_INLINE_ uint32_t hash(const StringName &p_string_name) { return p_string_name.hash(); }
+ static _FORCE_INLINE_ uint32_t hash(const NodePath &p_path) { return p_path.hash(); }
+ static _FORCE_INLINE_ uint32_t hash(const ObjectID &p_id) { return hash_one_uint64(p_id); }
- //static _FORCE_INLINE_ uint32_t hash(const void* p_ptr) { return uint32_t(uint64_t(p_ptr))*(0x9e3779b1L); }
+ static _FORCE_INLINE_ uint32_t hash(const uint64_t p_int) { return hash_one_uint64(p_int); }
+ static _FORCE_INLINE_ uint32_t hash(const int64_t p_int) { return hash_one_uint64(p_int); }
+ static _FORCE_INLINE_ uint32_t hash(const float p_float) { return hash_djb2_one_float(p_float); }
+ static _FORCE_INLINE_ uint32_t hash(const double p_double) { return hash_djb2_one_float(p_double); }
+ static _FORCE_INLINE_ uint32_t hash(const uint32_t p_int) { return fmix32(p_int); }
+ static _FORCE_INLINE_ uint32_t hash(const int32_t p_int) { return fmix32(p_int); }
+ static _FORCE_INLINE_ uint32_t hash(const uint16_t p_int) { return fmix32(p_int); }
+ static _FORCE_INLINE_ uint32_t hash(const int16_t p_int) { return fmix32(p_int); }
+ static _FORCE_INLINE_ uint32_t hash(const uint8_t p_int) { return fmix32(p_int); }
+ static _FORCE_INLINE_ uint32_t hash(const int8_t p_int) { return fmix32(p_int); }
+ static _FORCE_INLINE_ uint32_t hash(const Vector2i &p_vec) { return hash_murmur3_32(&p_vec, sizeof(Vector2i)); }
+ static _FORCE_INLINE_ uint32_t hash(const Vector3i &p_vec) { return hash_murmur3_32(&p_vec, sizeof(Vector3i)); }
+ static _FORCE_INLINE_ uint32_t hash(const Vector2 &p_vec) { return hash_murmur3_32(&p_vec, sizeof(Vector2)); }
+ static _FORCE_INLINE_ uint32_t hash(const Vector3 &p_vec) { return hash_murmur3_32(&p_vec, sizeof(Vector3)); }
+ static _FORCE_INLINE_ uint32_t hash(const Rect2i &p_rect) { return hash_murmur3_32(&p_rect, sizeof(Rect2i)); }
+ static _FORCE_INLINE_ uint32_t hash(const Rect2 &p_rect) { return hash_murmur3_32(&p_rect, sizeof(Rect2)); }
+ static _FORCE_INLINE_ uint32_t hash(const AABB &p_aabb) { return hash_murmur3_32(&p_aabb, sizeof(AABB)); }
};
template <typename T>
diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp
index 2b4e777865..aa640924e4 100644
--- a/core/variant/variant.cpp
+++ b/core/variant/variant.cpp
@@ -2788,106 +2788,50 @@ uint32_t Variant::recursive_hash(int recursion_count) const {
// math types
case VECTOR2: {
- uint32_t hash = hash_djb2_one_float(reinterpret_cast<const Vector2 *>(_data._mem)->x);
- return hash_djb2_one_float(reinterpret_cast<const Vector2 *>(_data._mem)->y, hash);
+ return hash_murmur3_32(reinterpret_cast<const Vector2 *>(_data._mem), sizeof(Vector2));
} break;
case VECTOR2I: {
- uint32_t hash = hash_djb2_one_32((uint32_t) reinterpret_cast<const Vector2i *>(_data._mem)->x);
- return hash_djb2_one_32((uint32_t) reinterpret_cast<const Vector2i *>(_data._mem)->y, hash);
+ return hash_murmur3_32(reinterpret_cast<const Vector2i *>(_data._mem), sizeof(Vector2i));
} break;
case RECT2: {
- uint32_t hash = hash_djb2_one_float(reinterpret_cast<const Rect2 *>(_data._mem)->position.x);
- hash = hash_djb2_one_float(reinterpret_cast<const Rect2 *>(_data._mem)->position.y, hash);
- hash = hash_djb2_one_float(reinterpret_cast<const Rect2 *>(_data._mem)->size.x, hash);
- return hash_djb2_one_float(reinterpret_cast<const Rect2 *>(_data._mem)->size.y, hash);
+ return hash_murmur3_32(reinterpret_cast<const Rect2 *>(_data._mem), sizeof(Rect2));
} break;
case RECT2I: {
- uint32_t hash = hash_djb2_one_32((uint32_t) reinterpret_cast<const Rect2i *>(_data._mem)->position.x);
- hash = hash_djb2_one_32((uint32_t) reinterpret_cast<const Rect2i *>(_data._mem)->position.y, hash);
- hash = hash_djb2_one_32((uint32_t) reinterpret_cast<const Rect2i *>(_data._mem)->size.x, hash);
- return hash_djb2_one_32((uint32_t) reinterpret_cast<const Rect2i *>(_data._mem)->size.y, hash);
+ return hash_murmur3_32(reinterpret_cast<const Rect2i *>(_data._mem), sizeof(Rect2i));
} break;
case TRANSFORM2D: {
- uint32_t hash = 5831;
- for (int i = 0; i < 3; i++) {
- for (int j = 0; j < 2; j++) {
- hash = hash_djb2_one_float(_data._transform2d->columns[i][j], hash);
- }
- }
-
- return hash;
+ return hash_murmur3_32(reinterpret_cast<const Transform2D *>(_data._transform2d), sizeof(Transform2D));
} break;
case VECTOR3: {
- uint32_t hash = hash_djb2_one_float(reinterpret_cast<const Vector3 *>(_data._mem)->x);
- hash = hash_djb2_one_float(reinterpret_cast<const Vector3 *>(_data._mem)->y, hash);
- return hash_djb2_one_float(reinterpret_cast<const Vector3 *>(_data._mem)->z, hash);
+ return hash_murmur3_32(reinterpret_cast<const Vector3 *>(_data._mem), sizeof(Vector3));
} break;
case VECTOR3I: {
- uint32_t hash = hash_djb2_one_32((uint32_t) reinterpret_cast<const Vector3i *>(_data._mem)->x);
- hash = hash_djb2_one_32((uint32_t) reinterpret_cast<const Vector3i *>(_data._mem)->y, hash);
- return hash_djb2_one_32((uint32_t) reinterpret_cast<const Vector3i *>(_data._mem)->z, hash);
+ return hash_murmur3_32(reinterpret_cast<const Vector3i *>(_data._mem), sizeof(Vector3i));
} break;
case PLANE: {
- uint32_t hash = hash_djb2_one_float(reinterpret_cast<const Plane *>(_data._mem)->normal.x);
- hash = hash_djb2_one_float(reinterpret_cast<const Plane *>(_data._mem)->normal.y, hash);
- hash = hash_djb2_one_float(reinterpret_cast<const Plane *>(_data._mem)->normal.z, hash);
- return hash_djb2_one_float(reinterpret_cast<const Plane *>(_data._mem)->d, hash);
-
+ return hash_murmur3_32(reinterpret_cast<const Plane *>(_data._mem), sizeof(Plane));
} break;
case AABB: {
- uint32_t hash = 5831;
- for (int i = 0; i < 3; i++) {
- hash = hash_djb2_one_float(_data._aabb->position[i], hash);
- hash = hash_djb2_one_float(_data._aabb->size[i], hash);
- }
-
- return hash;
-
+ return hash_murmur3_32(_data._aabb, sizeof(AABB));
} break;
case QUATERNION: {
- uint32_t hash = hash_djb2_one_float(reinterpret_cast<const Quaternion *>(_data._mem)->x);
- hash = hash_djb2_one_float(reinterpret_cast<const Quaternion *>(_data._mem)->y, hash);
- hash = hash_djb2_one_float(reinterpret_cast<const Quaternion *>(_data._mem)->z, hash);
- return hash_djb2_one_float(reinterpret_cast<const Quaternion *>(_data._mem)->w, hash);
-
+ return hash_murmur3_32(reinterpret_cast<const Quaternion *>(_data._mem), sizeof(Quaternion));
} break;
case BASIS: {
- uint32_t hash = 5831;
- for (int i = 0; i < 3; i++) {
- for (int j = 0; j < 3; j++) {
- hash = hash_djb2_one_float(_data._basis->rows[i][j], hash);
- }
- }
-
- return hash;
-
+ return hash_murmur3_32(_data._basis, sizeof(Basis));
} break;
case TRANSFORM3D: {
- uint32_t hash = 5831;
- for (int i = 0; i < 3; i++) {
- for (int j = 0; j < 3; j++) {
- hash = hash_djb2_one_float(_data._transform3d->basis.rows[i][j], hash);
- }
- hash = hash_djb2_one_float(_data._transform3d->origin[i], hash);
- }
-
- return hash;
-
+ return hash_murmur3_32(_data._transform3d, sizeof(Transform3D));
} break;
-
// misc types
case COLOR: {
- uint32_t hash = hash_djb2_one_float(reinterpret_cast<const Color *>(_data._mem)->r);
- hash = hash_djb2_one_float(reinterpret_cast<const Color *>(_data._mem)->g, hash);
- hash = hash_djb2_one_float(reinterpret_cast<const Color *>(_data._mem)->b, hash);
- return hash_djb2_one_float(reinterpret_cast<const Color *>(_data._mem)->a, hash);
-
+ return hash_murmur3_32(reinterpret_cast<const Color *>(_data._mem), sizeof(Color));
} break;
case RID: {
- return hash_djb2_one_64(reinterpret_cast<const ::RID *>(_data._mem)->get_id());
+ return hash_one_uint64(reinterpret_cast<const ::RID *>(_data._mem)->get_id());
} break;
case OBJECT: {
- return hash_djb2_one_64(make_uint64_t(_get_obj().obj));
+ return hash_one_uint64(make_uint64_t(_get_obj().obj));
} break;
case STRING_NAME: {
return reinterpret_cast<const StringName *>(_data._mem)->hash();
@@ -2918,7 +2862,7 @@ uint32_t Variant::recursive_hash(int recursion_count) const {
int len = arr.size();
if (likely(len)) {
const uint8_t *r = arr.ptr();
- return hash_djb2_buffer((uint8_t *)&r[0], len);
+ return hash_murmur3_32((uint8_t *)&r[0], len);
} else {
return hash_djb2_one_64(0);
}
@@ -2929,7 +2873,7 @@ uint32_t Variant::recursive_hash(int recursion_count) const {
int len = arr.size();
if (likely(len)) {
const int32_t *r = arr.ptr();
- return hash_djb2_buffer((uint8_t *)&r[0], len * sizeof(int32_t));
+ return hash_murmur3_32((uint8_t *)&r[0], len * sizeof(int32_t));
} else {
return hash_djb2_one_64(0);
}
@@ -2940,7 +2884,7 @@ uint32_t Variant::recursive_hash(int recursion_count) const {
int len = arr.size();
if (likely(len)) {
const int64_t *r = arr.ptr();
- return hash_djb2_buffer((uint8_t *)&r[0], len * sizeof(int64_t));
+ return hash_murmur3_32((uint8_t *)&r[0], len * sizeof(int64_t));
} else {
return hash_djb2_one_64(0);
}
@@ -2952,7 +2896,7 @@ uint32_t Variant::recursive_hash(int recursion_count) const {
if (likely(len)) {
const float *r = arr.ptr();
- return hash_djb2_buffer((uint8_t *)&r[0], len * sizeof(float));
+ return hash_murmur3_32((uint8_t *)&r[0], len * sizeof(float));
} else {
return hash_djb2_one_float(0.0);
}
@@ -2964,7 +2908,7 @@ uint32_t Variant::recursive_hash(int recursion_count) const {
if (likely(len)) {
const double *r = arr.ptr();
- return hash_djb2_buffer((uint8_t *)&r[0], len * sizeof(double));
+ return hash_murmur3_32((uint8_t *)&r[0], len * sizeof(double));
} else {
return hash_djb2_one_float(0.0);
}
diff --git a/doc/classes/NavigationAgent2D.xml b/doc/classes/NavigationAgent2D.xml
index c04e7bf1f7..0ac9513464 100644
--- a/doc/classes/NavigationAgent2D.xml
+++ b/doc/classes/NavigationAgent2D.xml
@@ -108,8 +108,8 @@
<member name="max_speed" type="float" setter="set_max_speed" getter="get_max_speed" default="200.0">
The maximum speed that an agent can move.
</member>
- <member name="navigable_layers" type="int" setter="set_navigable_layers" getter="get_navigable_layers" default="1">
- A bitfield determining what layers of navigation regions this agent will use to calculate path. Changing it runtime will clear current navigation path and generate new one, according to new layers.
+ <member name="navigation_layers" type="int" setter="set_navigation_layers" getter="get_navigation_layers" default="1">
+ A bitfield determining what navigation layers of navigation regions this agent will use to calculate path. Changing it runtime will clear current navigation path and generate new one, according to new navigation layers.
</member>
<member name="neighbor_dist" type="float" setter="set_neighbor_dist" getter="get_neighbor_dist" default="500.0">
The distance to search for other agents.
diff --git a/doc/classes/NavigationAgent3D.xml b/doc/classes/NavigationAgent3D.xml
index 91d7aabc34..cc45a43ffc 100644
--- a/doc/classes/NavigationAgent3D.xml
+++ b/doc/classes/NavigationAgent3D.xml
@@ -114,8 +114,8 @@
<member name="max_speed" type="float" setter="set_max_speed" getter="get_max_speed" default="10.0">
The maximum speed that an agent can move.
</member>
- <member name="navigable_layers" type="int" setter="set_navigable_layers" getter="get_navigable_layers" default="1">
- A bitfield determining what layers of navigation regions this agent will use to calculate path. Changing it runtime will clear current navigation path and generate new one, according to new layers.
+ <member name="navigation_layers" type="int" setter="set_navigation_layers" getter="get_navigation_layers" default="1">
+ A bitfield determining what navigation layers of navigation regions this NavigationAgent will use to calculate path. Changing it runtime will clear current navigation path and generate new one, according to new navigation layers.
</member>
<member name="neighbor_dist" type="float" setter="set_neighbor_dist" getter="get_neighbor_dist" default="50.0">
The distance to search for other agents.
diff --git a/doc/classes/NavigationRegion2D.xml b/doc/classes/NavigationRegion2D.xml
index 542aa8f619..62e64f2a3c 100644
--- a/doc/classes/NavigationRegion2D.xml
+++ b/doc/classes/NavigationRegion2D.xml
@@ -28,8 +28,8 @@
<member name="enter_cost" type="float" setter="set_enter_cost" getter="get_enter_cost" default="0.0">
When pathfinding enters this regions navmesh from another regions navmesh the [code]enter_cost[/code] value is added to the path distance for determining the shortest path.
</member>
- <member name="layers" type="int" setter="set_layers" getter="get_layers" default="1">
- A bitfield determining all layers the region belongs to. These layers can be checked upon when requesting a path with [method NavigationServer2D.map_get_path].
+ <member name="navigation_layers" type="int" setter="set_navigation_layers" getter="get_navigation_layers" default="1">
+ A bitfield determining all navigation layers the region belongs to. These navigation layers can be checked upon when requesting a path with [method NavigationServer2D.map_get_path].
</member>
<member name="navpoly" type="NavigationPolygon" setter="set_navigation_polygon" getter="get_navigation_polygon">
The [NavigationPolygon] resource to use.
diff --git a/doc/classes/NavigationRegion3D.xml b/doc/classes/NavigationRegion3D.xml
index e45bca7f8b..3af7fe5c97 100644
--- a/doc/classes/NavigationRegion3D.xml
+++ b/doc/classes/NavigationRegion3D.xml
@@ -35,8 +35,8 @@
<member name="enter_cost" type="float" setter="set_enter_cost" getter="get_enter_cost" default="0.0">
When pathfinding enters this regions navmesh from another regions navmesh the [code]enter_cost[/code] value is added to the path distance for determining the shortest path.
</member>
- <member name="layers" type="int" setter="set_layers" getter="get_layers" default="1">
- A bitfield determining all layers the region belongs to. These layers can be checked upon when requesting a path with [method NavigationServer3D.map_get_path].
+ <member name="navigation_layers" type="int" setter="set_navigation_layers" getter="get_navigation_layers" default="1">
+ A bitfield determining all navigation layers the region belongs to. These navigation layers can be checked upon when requesting a path with [method NavigationServer3D.map_get_path].
</member>
<member name="navmesh" type="NavigationMesh" setter="set_navigation_mesh" getter="get_navigation_mesh">
The [NavigationMesh] resource to use.
diff --git a/doc/classes/NavigationServer2D.xml b/doc/classes/NavigationServer2D.xml
index cd9f54caaa..220c12ce7f 100644
--- a/doc/classes/NavigationServer2D.xml
+++ b/doc/classes/NavigationServer2D.xml
@@ -8,7 +8,7 @@
Maps are made up of regions, which are made of navigation polygons. Together, they define the navigable areas in the 2D world.
[b]Note:[/b] Most NavigationServer changes take effect after the next physics frame and not immediately. This includes all changes made to maps, regions or agents by navigation related Nodes in the SceneTree or made through scripts.
For two regions to be connected to each other, they must share a similar edge. An edge is considered connected to another if both of its two vertices are at a distance less than [code]edge_connection_margin[/code] to the respective other edge's vertex.
- You may assign navigation layers to regions with [method NavigationServer2D.region_set_layers], which then can be checked upon when requesting a path with [method NavigationServer2D.map_get_path]. This allows allowing or forbidding some areas to 2D objects.
+ You may assign navigation layers to regions with [method NavigationServer2D.region_set_navigation_layers], which then can be checked upon when requesting a path with [method NavigationServer2D.map_get_path]. This allows allowing or forbidding some areas to 2D objects.
To use the collision avoidance system, you may use agents. You can set an agent's target velocity, then the servers will emit a callback with a modified velocity.
[b]Note:[/b] The collision avoidance system ignores regions. Using the modified velocity as-is might lead to pushing and agent outside of a navigable area. This is a limitation of the collision avoidance system, any more complex situation may require the use of the physics engine.
This server keeps tracks of any call and executes them during the sync phase. This means that you can request any change to the map, using any thread, without worrying.
@@ -176,9 +176,9 @@
<argument index="1" name="origin" type="Vector2" />
<argument index="2" name="destination" type="Vector2" />
<argument index="3" name="optimize" type="bool" />
- <argument index="4" name="layers" type="int" default="1" />
+ <argument index="4" name="navigation_layers" type="int" default="1" />
<description>
- Returns the navigation path to reach the destination from the origin. [code]layers[/code] is a bitmask of all region layers that are allowed to be in the path.
+ Returns the navigation path to reach the destination from the origin. [code]navigation_layers[/code] is a bitmask of all region navigation layers that are allowed to be in the path.
</description>
</method>
<method name="map_get_regions" qualifiers="const">
@@ -255,18 +255,18 @@
Returns the [code]enter_cost[/code] of this [code]region[/code].
</description>
</method>
- <method name="region_get_layers" qualifiers="const">
- <return type="int" />
+ <method name="region_get_map" qualifiers="const">
+ <return type="RID" />
<argument index="0" name="region" type="RID" />
<description>
- Returns the region's layers.
+ Returns the navigation map [RID] the requested [code]region[/code] is currently assigned to.
</description>
</method>
- <method name="region_get_map" qualifiers="const">
- <return type="RID" />
+ <method name="region_get_navigation_layers" qualifiers="const">
+ <return type="int" />
<argument index="0" name="region" type="RID" />
<description>
- Returns the navigation map [RID] the requested [code]region[/code] is currently assigned to.
+ Returns the region's navigation layers.
</description>
</method>
<method name="region_get_travel_cost" qualifiers="const">
@@ -284,20 +284,20 @@
Sets the [code]enter_cost[/code] for this [code]region[/code].
</description>
</method>
- <method name="region_set_layers" qualifiers="const">
+ <method name="region_set_map" qualifiers="const">
<return type="void" />
<argument index="0" name="region" type="RID" />
- <argument index="1" name="layers" type="int" />
+ <argument index="1" name="map" type="RID" />
<description>
- Set the region's layers. This allows selecting regions from a path request (when using [method NavigationServer2D.map_get_path]).
+ Sets the map for the region.
</description>
</method>
- <method name="region_set_map" qualifiers="const">
+ <method name="region_set_navigation_layers" qualifiers="const">
<return type="void" />
<argument index="0" name="region" type="RID" />
- <argument index="1" name="map" type="RID" />
+ <argument index="1" name="navigation_layers" type="int" />
<description>
- Sets the map for the region.
+ Set the region's navigation layers. This allows selecting regions from a path request (when using [method NavigationServer2D.map_get_path]).
</description>
</method>
<method name="region_set_navpoly" qualifiers="const">
diff --git a/doc/classes/NavigationServer3D.xml b/doc/classes/NavigationServer3D.xml
index 9ef0f0d631..d2eef49cfd 100644
--- a/doc/classes/NavigationServer3D.xml
+++ b/doc/classes/NavigationServer3D.xml
@@ -8,7 +8,7 @@
Maps are made up of regions, which are made of navigation meshes. Together, they define the navigable areas in the 3D world.
[b]Note:[/b] Most NavigationServer changes take effect after the next physics frame and not immediately. This includes all changes made to maps, regions or agents by navigation related Nodes in the SceneTree or made through scripts.
For two regions to be connected to each other, they must share a similar edge. An edge is considered connected to another if both of its two vertices are at a distance less than [code]edge_connection_margin[/code] to the respective other edge's vertex.
- You may assign navigation layers to regions with [method NavigationServer3D.region_set_layers], which then can be checked upon when requesting a path with [method NavigationServer3D.map_get_path]. This allows allowing or forbidding some areas to 3D objects.
+ You may assign navigation layers to regions with [method NavigationServer3D.region_set_navigation_layers], which then can be checked upon when requesting a path with [method NavigationServer3D.map_get_path]. This allows allowing or forbidding some areas to 3D objects.
To use the collision avoidance system, you may use agents. You can set an agent's target velocity, then the servers will emit a callback with a modified velocity.
[b]Note:[/b] The collision avoidance system ignores regions. Using the modified velocity as-is might lead to pushing and agent outside of a navigable area. This is a limitation of the collision avoidance system, any more complex situation may require the use of the physics engine.
This server keeps tracks of any call and executes them during the sync phase. This means that you can request any change to the map, using any thread, without worrying.
@@ -194,9 +194,9 @@
<argument index="1" name="origin" type="Vector3" />
<argument index="2" name="destination" type="Vector3" />
<argument index="3" name="optimize" type="bool" />
- <argument index="4" name="layers" type="int" default="1" />
+ <argument index="4" name="navigation_layers" type="int" default="1" />
<description>
- Returns the navigation path to reach the destination from the origin. [code]layers[/code] is a bitmask of all region layers that are allowed to be in the path.
+ Returns the navigation path to reach the destination from the origin. [code]navigation_layers[/code] is a bitmask of all region navigation layers that are allowed to be in the path.
</description>
</method>
<method name="map_get_regions" qualifiers="const">
@@ -305,18 +305,18 @@
Returns the [code]enter_cost[/code] of this [code]region[/code].
</description>
</method>
- <method name="region_get_layers" qualifiers="const">
- <return type="int" />
+ <method name="region_get_map" qualifiers="const">
+ <return type="RID" />
<argument index="0" name="region" type="RID" />
<description>
- Returns the region's layers.
+ Returns the navigation map [RID] the requested [code]region[/code] is currently assigned to.
</description>
</method>
- <method name="region_get_map" qualifiers="const">
- <return type="RID" />
+ <method name="region_get_navigation_layers" qualifiers="const">
+ <return type="int" />
<argument index="0" name="region" type="RID" />
<description>
- Returns the navigation map [RID] the requested [code]region[/code] is currently assigned to.
+ Returns the region's navigation layers.
</description>
</method>
<method name="region_get_travel_cost" qualifiers="const">
@@ -334,20 +334,20 @@
Sets the [code]enter_cost[/code] for this [code]region[/code].
</description>
</method>
- <method name="region_set_layers" qualifiers="const">
+ <method name="region_set_map" qualifiers="const">
<return type="void" />
<argument index="0" name="region" type="RID" />
- <argument index="1" name="layers" type="int" />
+ <argument index="1" name="map" type="RID" />
<description>
- Set the region's layers. This allows selecting regions from a path request (when using [method NavigationServer3D.map_get_path]).
+ Sets the map for the region.
</description>
</method>
- <method name="region_set_map" qualifiers="const">
+ <method name="region_set_navigation_layers" qualifiers="const">
<return type="void" />
<argument index="0" name="region" type="RID" />
- <argument index="1" name="map" type="RID" />
+ <argument index="1" name="navigation_layers" type="int" />
<description>
- Sets the map for the region.
+ Set the region's navigation layers. This allows selecting regions from a path request (when using [method NavigationServer3D.map_get_path]).
</description>
</method>
<method name="region_set_navmesh" qualifiers="const">
diff --git a/doc/classes/PopupMenu.xml b/doc/classes/PopupMenu.xml
index bf80aa94a5..eb2b681071 100644
--- a/doc/classes/PopupMenu.xml
+++ b/doc/classes/PopupMenu.xml
@@ -201,6 +201,13 @@
Returns the accelerator of the item at the given [code]index[/code]. Accelerators are special combinations of keys that activate the item, no matter which control is focused.
</description>
</method>
+ <method name="get_item_horizontal_offset" qualifiers="const">
+ <return type="int" />
+ <argument index="0" name="index" type="int" />
+ <description>
+ Returns the horizontal offset of the item at the given [code]index[/code].
+ </description>
+ </method>
<method name="get_item_icon" qualifiers="const">
<return type="Texture2D" />
<argument index="0" name="index" type="int" />
@@ -395,6 +402,14 @@
Enables/disables the item at the given [code]index[/code]. When it is disabled, it can't be selected and its action can't be invoked.
</description>
</method>
+ <method name="set_item_horizontal_offset">
+ <return type="void" />
+ <argument index="0" name="index" type="int" />
+ <argument index="1" name="offset" type="int" />
+ <description>
+ Sets the horizontal offset of the item at the given [code]index[/code].
+ </description>
+ </method>
<method name="set_item_icon">
<return type="void" />
<argument index="0" name="index" type="int" />
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp
index 32d279a635..d41c844d1d 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.cpp
+++ b/drivers/gles3/rasterizer_canvas_gles3.cpp
@@ -689,6 +689,10 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
_bind_instance_data_buffer(1);
glBindVertexArray(pb->vertex_array);
+ if (pb->color_disabled) {
+ glVertexAttrib4f(RS::ARRAY_COLOR, pb->color.r, pb->color.g, pb->color.b, pb->color.a);
+ }
+
if (pb->index_buffer != 0) {
glDrawElements(prim[polygon->primitive], pb->count, GL_UNSIGNED_INT, nullptr);
} else {
@@ -698,6 +702,11 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
state.fences[state.current_buffer] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
state.current_buffer = (state.current_buffer + 1) % state.canvas_instance_data_buffers.size();
+
+ if (pb->color_disabled) {
+ // Reset so this doesn't pollute other draw calls.
+ glVertexAttrib4f(RS::ARRAY_COLOR, 1.0, 1.0, 1.0, 1.0);
+ }
} break;
case Item::Command::TYPE_PRIMITIVE: {
@@ -758,7 +767,6 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
GLuint multimesh_buffer = 0;
uint32_t multimesh_stride = 0;
uint32_t multimesh_color_offset = 0;
- uint32_t multimesh_custom_data_offset = 0;
bool multimesh_uses_color = false;
bool multimesh_uses_custom_data = false;
@@ -788,7 +796,6 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
multimesh_buffer = mesh_storage->multimesh_get_gl_buffer(multimesh);
multimesh_stride = mesh_storage->multimesh_get_stride(multimesh);
multimesh_color_offset = mesh_storage->multimesh_get_color_offset(multimesh);
- multimesh_custom_data_offset = mesh_storage->multimesh_get_custom_data_offset(multimesh);
multimesh_uses_color = mesh_storage->multimesh_uses_colors(multimesh);
multimesh_uses_custom_data = mesh_storage->multimesh_uses_custom_data(multimesh);
}
@@ -854,22 +861,17 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
if (instance_count > 1) {
// Bind instance buffers.
glBindBuffer(GL_ARRAY_BUFFER, multimesh_buffer);
- glEnableVertexAttribArray(5);
- glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(0));
- glVertexAttribDivisor(5, 1);
- glEnableVertexAttribArray(6);
- glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(4 * 4));
- glVertexAttribDivisor(6, 1);
-
- if (multimesh_uses_color) {
- glEnableVertexAttribArray(7);
- glVertexAttribPointer(7, 4, GL_FLOAT, GL_FALSE, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(multimesh_color_offset * sizeof(float)));
- glVertexAttribDivisor(7, 1);
- }
- if (multimesh_uses_custom_data) {
- glEnableVertexAttribArray(8);
- glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(multimesh_custom_data_offset * sizeof(float)));
- glVertexAttribDivisor(8, 1);
+ glEnableVertexAttribArray(1);
+ glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(0));
+ glVertexAttribDivisor(1, 1);
+ glEnableVertexAttribArray(2);
+ glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(4 * 4));
+ glVertexAttribDivisor(2, 1);
+
+ if (multimesh_uses_color || multimesh_uses_custom_data) {
+ glEnableVertexAttribArray(5);
+ glVertexAttribIPointer(5, 4, GL_UNSIGNED_INT, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(multimesh_color_offset * sizeof(float)));
+ glVertexAttribDivisor(5, 1);
}
}
@@ -1268,11 +1270,7 @@ RendererCanvasRender::PolygonID RasterizerCanvasGLES3::request_polygon(const Vec
}
// Next add colors
- if (p_colors.size() == 1) {
- glDisableVertexAttribArray(RS::ARRAY_COLOR);
- Color m = p_colors[0];
- glVertexAttrib4f(RS::ARRAY_COLOR, m.r, m.g, m.b, m.a);
- } else if ((uint32_t)p_colors.size() == vertex_count) {
+ if ((uint32_t)p_colors.size() == vertex_count) {
glEnableVertexAttribArray(RS::ARRAY_COLOR);
glVertexAttribPointer(RS::ARRAY_COLOR, 4, GL_FLOAT, GL_FALSE, stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(base_offset * sizeof(float)));
@@ -1287,7 +1285,8 @@ RendererCanvasRender::PolygonID RasterizerCanvasGLES3::request_polygon(const Vec
base_offset += 4;
} else {
glDisableVertexAttribArray(RS::ARRAY_COLOR);
- glVertexAttrib4f(RS::ARRAY_COLOR, 1.0, 1.0, 1.0, 1.0);
+ pb.color_disabled = true;
+ pb.color = p_colors.size() == 1 ? p_colors[0] : Color(1.0, 1.0, 1.0, 1.0);
}
if ((uint32_t)p_uvs.size() == vertex_count) {
diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h
index 31e82401f9..bf13c91e1c 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.h
+++ b/drivers/gles3/rasterizer_canvas_gles3.h
@@ -238,6 +238,8 @@ public:
GLuint vertex_array;
GLuint index_buffer;
int count;
+ bool color_disabled = false;
+ Color color;
};
struct {
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index 3fe0ae4876..94ae8ecc8a 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -491,7 +491,7 @@ void RasterizerSceneGLES3::_geometry_instance_update(GeometryInstance *p_geometr
}
}
- ginstance->instance_count = 1;
+ ginstance->instance_count = -1;
} break;
@@ -2200,6 +2200,7 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
GLES3::SceneMaterialData *prev_material_data = nullptr;
GLES3::SceneShaderData *prev_shader = nullptr;
GeometryInstanceGLES3 *prev_inst = nullptr;
+ SceneShaderGLES3::ShaderVariant prev_variant = SceneShaderGLES3::ShaderVariant::MODE_COLOR;
SceneShaderGLES3::ShaderVariant shader_variant = SceneShaderGLES3::MODE_COLOR; // Assigned to silence wrong -Wmaybe-initialized.
@@ -2386,12 +2387,11 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
prev_vertex_array_gl = vertex_array_gl;
}
- bool use_index_buffer = false;
+ bool use_index_buffer = index_array_gl != 0;
if (prev_index_array_gl != index_array_gl) {
if (index_array_gl != 0) {
// Bind index each time so we can use LODs
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_array_gl);
- use_index_buffer = true;
}
prev_index_array_gl = index_array_gl;
}
@@ -2406,8 +2406,13 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
prev_material_data = material_data;
}
- if (prev_shader != shader) {
- material_storage->shaders.scene_shader.version_bind_shader(shader->version, shader_variant);
+ SceneShaderGLES3::ShaderVariant instance_variant = shader_variant;
+ if (inst->instance_count > 0) {
+ instance_variant = SceneShaderGLES3::ShaderVariant(1 + int(shader_variant));
+ }
+
+ if (prev_shader != shader || prev_variant != instance_variant) {
+ material_storage->shaders.scene_shader.version_bind_shader(shader->version, instance_variant);
float opaque_prepass_threshold = 0.0;
if (p_pass_mode == PASS_MODE_DEPTH) {
opaque_prepass_threshold = 0.99;
@@ -2415,33 +2420,69 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
opaque_prepass_threshold = 0.1;
}
- material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::OPAQUE_PREPASS_THRESHOLD, opaque_prepass_threshold, shader->version, shader_variant);
+ material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::OPAQUE_PREPASS_THRESHOLD, opaque_prepass_threshold, shader->version, instance_variant);
prev_shader = shader;
+ prev_variant = instance_variant;
}
- if (prev_inst != inst) {
+ if (prev_inst != inst || prev_shader != shader || prev_variant != instance_variant) {
// Rebind the light indices.
- material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::OMNI_LIGHT_COUNT, inst->omni_light_count, shader->version, shader_variant);
- material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::SPOT_LIGHT_COUNT, inst->spot_light_count, shader->version, shader_variant);
+ material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::OMNI_LIGHT_COUNT, inst->omni_light_count, shader->version, instance_variant);
+ material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::SPOT_LIGHT_COUNT, inst->spot_light_count, shader->version, instance_variant);
if (inst->omni_light_count) {
- glUniform1uiv(material_storage->shaders.scene_shader.version_get_uniform(SceneShaderGLES3::OMNI_LIGHT_INDICES, shader->version, shader_variant), inst->omni_light_count, inst->omni_light_gl_cache.ptr());
+ glUniform1uiv(material_storage->shaders.scene_shader.version_get_uniform(SceneShaderGLES3::OMNI_LIGHT_INDICES, shader->version, instance_variant), inst->omni_light_count, inst->omni_light_gl_cache.ptr());
}
if (inst->spot_light_count) {
- glUniform1uiv(material_storage->shaders.scene_shader.version_get_uniform(SceneShaderGLES3::SPOT_LIGHT_INDICES, shader->version, shader_variant), inst->spot_light_count, inst->spot_light_gl_cache.ptr());
+ glUniform1uiv(material_storage->shaders.scene_shader.version_get_uniform(SceneShaderGLES3::SPOT_LIGHT_INDICES, shader->version, instance_variant), inst->spot_light_count, inst->spot_light_gl_cache.ptr());
}
prev_inst = inst;
}
- material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::WORLD_TRANSFORM, world_transform, shader->version, shader_variant);
-
- if (use_index_buffer) {
- glDrawElements(primitive_gl, mesh_storage->mesh_surface_get_vertices_drawn_count(mesh_surface), mesh_storage->mesh_surface_get_index_type(mesh_surface), 0);
+ material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::WORLD_TRANSFORM, world_transform, shader->version, instance_variant);
+ if (inst->instance_count > 0) {
+ // Using MultiMesh.
+ // Bind instance buffers.
+
+ GLuint multimesh_buffer = mesh_storage->multimesh_get_gl_buffer(inst->data->base);
+ glBindBuffer(GL_ARRAY_BUFFER, multimesh_buffer);
+ uint32_t multimesh_stride = mesh_storage->multimesh_get_stride(inst->data->base);
+ glEnableVertexAttribArray(12);
+ glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(0));
+ glVertexAttribDivisor(12, 1);
+ glEnableVertexAttribArray(13);
+ glVertexAttribPointer(13, 4, GL_FLOAT, GL_FALSE, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(4 * 4));
+ glVertexAttribDivisor(13, 1);
+ glEnableVertexAttribArray(14);
+ glVertexAttribPointer(14, 4, GL_FLOAT, GL_FALSE, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(4 * 8));
+ glVertexAttribDivisor(14, 1);
+
+ if (mesh_storage->multimesh_uses_colors(inst->data->base) || mesh_storage->multimesh_uses_custom_data(inst->data->base)) {
+ glEnableVertexAttribArray(15);
+ glVertexAttribIPointer(15, 4, GL_UNSIGNED_INT, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(mesh_storage->multimesh_get_color_offset(inst->data->base) * sizeof(float)));
+ glVertexAttribDivisor(15, 1);
+ }
+ if (use_index_buffer) {
+ glDrawElementsInstanced(primitive_gl, mesh_storage->mesh_surface_get_vertices_drawn_count(mesh_surface), mesh_storage->mesh_surface_get_index_type(mesh_surface), 0, inst->instance_count);
+ } else {
+ glDrawArraysInstanced(primitive_gl, 0, mesh_storage->mesh_surface_get_vertices_drawn_count(mesh_surface), inst->instance_count);
+ }
} else {
- glDrawArrays(primitive_gl, 0, mesh_storage->mesh_surface_get_vertices_drawn_count(mesh_surface));
+ // Using regular Mesh.
+ if (use_index_buffer) {
+ glDrawElements(primitive_gl, mesh_storage->mesh_surface_get_vertices_drawn_count(mesh_surface), mesh_storage->mesh_surface_get_index_type(mesh_surface), 0);
+ } else {
+ glDrawArrays(primitive_gl, 0, mesh_storage->mesh_surface_get_vertices_drawn_count(mesh_surface));
+ }
+ }
+ if (inst->instance_count > 0) {
+ glDisableVertexAttribArray(12);
+ glDisableVertexAttribArray(13);
+ glDisableVertexAttribArray(14);
+ glDisableVertexAttribArray(15);
}
}
}
@@ -2811,6 +2852,9 @@ void sky() {
#ifdef GLES_OVER_GL
glEnable(_EXT_TEXTURE_CUBE_MAP_SEAMLESS);
#endif
+
+ // MultiMesh may read from color when color is disabled, so make sure that the color defaults to white instead of black;
+ glVertexAttrib4f(RS::ARRAY_COLOR, 1.0, 1.0, 1.0, 1.0);
}
RasterizerSceneGLES3::~RasterizerSceneGLES3() {
diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h
index f76861bc90..308ef36fa1 100644
--- a/drivers/gles3/rasterizer_scene_gles3.h
+++ b/drivers/gles3/rasterizer_scene_gles3.h
@@ -277,7 +277,7 @@ private:
int32_t shader_parameters_offset = -1;
uint32_t layer_mask = 1;
- uint32_t instance_count = 0;
+ int32_t instance_count = 0;
RID mesh_instance;
bool can_sdfgi = false;
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index 012cda953c..bbe4d92856 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/drivers/gles3/rasterizer_storage_gles3.cpp
@@ -38,6 +38,8 @@
#include "rasterizer_scene_gles3.h"
#include "servers/rendering/shader_language.h"
+/* MISC */
+
void RasterizerStorageGLES3::base_update_dependency(RID p_base, DependencyTracker *p_instance) {
if (GLES3::MeshStorage::get_singleton()->owns_mesh(p_base)) {
GLES3::Mesh *mesh = GLES3::MeshStorage::get_singleton()->get_mesh(p_base);
@@ -54,6 +56,29 @@ void RasterizerStorageGLES3::base_update_dependency(RID p_base, DependencyTracke
}
}
+Vector<uint8_t> RasterizerStorageGLES3::buffer_get_data(GLenum p_target, GLuint p_buffer, uint32_t p_buffer_size) {
+ Vector<uint8_t> ret;
+ ret.resize(p_buffer_size);
+ glBindBuffer(p_target, p_buffer);
+
+#if defined(__EMSCRIPTEN__)
+ {
+ uint8_t *w = ret.ptrw();
+ glGetBufferSubData(p_target, 0, p_buffer_size, w);
+ }
+#else
+ void *data = glMapBufferRange(p_target, 0, p_buffer_size, GL_MAP_READ_BIT);
+ ERR_FAIL_NULL_V(data, Vector<uint8_t>());
+ {
+ uint8_t *w = ret.ptrw();
+ memcpy(w, data, p_buffer_size);
+ }
+ glUnmapBuffer(p_target);
+#endif
+ glBindBuffer(p_target, 0);
+ return ret;
+}
+
/* VOXEL GI API */
RID RasterizerStorageGLES3::voxel_gi_allocate() {
diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h
index 7ac3db4537..981080f6a5 100644
--- a/drivers/gles3/rasterizer_storage_gles3.h
+++ b/drivers/gles3/rasterizer_storage_gles3.h
@@ -98,6 +98,9 @@ public:
}
}
+ // Buffer size is specified in bytes
+ static Vector<uint8_t> buffer_get_data(GLenum p_target, GLuint p_buffer, uint32_t p_buffer_size);
+
struct Resources {
GLuint mipmap_blur_fbo;
GLuint mipmap_blur_color;
@@ -295,28 +298,10 @@ public:
return String();
}
- //bool validate_framebuffer(); // Validate currently bound framebuffer, does not touch global state
- String get_framebuffer_error(GLenum p_status);
-
RasterizerStorageGLES3();
~RasterizerStorageGLES3();
};
-inline String RasterizerStorageGLES3::get_framebuffer_error(GLenum p_status) {
-#if defined(DEBUG_ENABLED) && defined(GLES_OVER_GL)
- if (p_status == GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT) {
- return "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT";
- } else if (p_status == GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT) {
- return "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT";
- } else if (p_status == GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER) {
- return "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER";
- } else if (p_status == GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER) {
- return "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER";
- }
-#endif
- return itos(p_status);
-}
-
#endif // GLES3_ENABLED
#endif // RASTERIZER_STORAGE_OPENGL_H
diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl
index 9c426dd3ef..4df818cd4c 100644
--- a/drivers/gles3/shaders/canvas.glsl
+++ b/drivers/gles3/shaders/canvas.glsl
@@ -23,10 +23,9 @@ layout(location = 11) in vec4 weight_attrib;
#ifdef USE_INSTANCING
-layout(location = 5) in highp vec4 instance_xform0;
-layout(location = 6) in highp vec4 instance_xform1;
-layout(location = 7) in lowp vec4 instance_color;
-layout(location = 8) in highp vec4 instance_custom_data;
+layout(location = 1) in highp vec4 instance_xform0;
+layout(location = 2) in highp vec4 instance_xform1;
+layout(location = 5) in highp uvec4 instance_color_custom_data; // Color packed into xy, custom_data packed into zw for compatibility with 3D
#endif
@@ -98,8 +97,9 @@ void main() {
vec4 bone_weights = weight_attrib;
#ifdef USE_INSTANCING
+ vec4 instance_color = vec4(unpackHalf2x16(instance_color_custom_data.x), unpackHalf2x16(instance_color_custom_data.y));
color *= instance_color;
- instance_custom = instance_custom_data;
+ instance_custom = vec4(unpackHalf2x16(instance_color_custom_data.z), unpackHalf2x16(instance_color_custom_data.w));
#endif
#else
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
index fbea4bdbe4..4f2be8bf60 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -2,8 +2,11 @@
#[modes]
mode_color = #define BASE_PASS
+mode_color_instancing = #define BASE_PASS \n#define USE_INSTANCING
mode_additive = #define USE_ADDITIVE_LIGHTING
+mode_additive_instancing = #define USE_ADDITIVE_LIGHTING \n#define USE_INSTANCING
mode_depth = #define MODE_RENDER_DEPTH
+mode_depth_instancing = #define MODE_RENDER_DEPTH \n#define USE_INSTANCING
#[specializations]
@@ -43,8 +46,6 @@ ARRAY_CUSTOM2 = 8,
ARRAY_CUSTOM3 = 9,
ARRAY_BONES = 10, // RGBA16UI (x2 if 8 weights)
ARRAY_WEIGHTS = 11, // RGBA16UNORM (x2 if 8 weights)
-ARRAY_INDEX = 12, // 16 or 32 bits depending on length > 0xFFFF.
-ARRAY_MAX = 13
*/
/* INPUT ATTRIBS */
@@ -96,6 +97,13 @@ layout(location = 10) in uvec4 bone_attrib;
layout(location = 11) in vec4 weight_attrib;
#endif
+#ifdef USE_INSTANCING
+layout(location = 12) in highp vec4 instance_xform0;
+layout(location = 13) in highp vec4 instance_xform1;
+layout(location = 14) in highp vec4 instance_xform2;
+layout(location = 15) in highp uvec4 instance_color_custom_data; // Color packed into xy, Custom data into zw.
+#endif
+
layout(std140) uniform GlobalVariableData { //ubo:1
vec4 global_variables[MAX_GLOBAL_VARIABLES];
};
@@ -195,6 +203,10 @@ void main() {
highp vec3 vertex = vertex_attrib;
highp mat4 model_matrix = world_transform;
+#ifdef USE_INSTANCING
+ highp mat4 m = mat4(instance_xform0, instance_xform1, instance_xform2, vec4(0.0, 0.0, 0.0, 1.0));
+ model_matrix = model_matrix * transpose(m);
+#endif
#ifdef NORMAL_USED
vec3 normal = normal_attrib * 2.0 - 1.0;
@@ -209,6 +221,10 @@ void main() {
#if defined(COLOR_USED)
color_interp = color_attrib;
+#ifdef USE_INSTANCING
+ vec4 instance_color = vec4(unpackHalf2x16(instance_color_custom_data.x), unpackHalf2x16(instance_color_custom_data.y));
+ color_interp *= instance_color;
+#endif
#endif
#if defined(UV_USED)
@@ -229,7 +245,11 @@ void main() {
highp mat4 projection_matrix = scene_data.projection_matrix;
highp mat4 inv_projection_matrix = scene_data.inv_projection_matrix;
+#ifdef USE_INSTANCING
+ vec4 instance_custom = vec4(unpackHalf2x16(instance_color_custom_data.z), unpackHalf2x16(instance_color_custom_data.w));
+#else
vec4 instance_custom = vec4(0.0);
+#endif
// Using world coordinates
#if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED)
diff --git a/drivers/gles3/storage/mesh_storage.cpp b/drivers/gles3/storage/mesh_storage.cpp
index 822be25337..5aa82bfcc1 100644
--- a/drivers/gles3/storage/mesh_storage.cpp
+++ b/drivers/gles3/storage/mesh_storage.cpp
@@ -31,6 +31,7 @@
#ifdef GLES3_ENABLED
#include "mesh_storage.h"
+#include "../rasterizer_storage_gles3.h"
#include "material_storage.h"
using namespace GLES3;
@@ -230,6 +231,7 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); //unbind
s->lods[i].edge_length = p_surface.lods[i].edge_length;
s->lods[i].index_count = p_surface.lods[i].index_data.size() / (is_index_16 ? 2 : 4);
+ s->lods[i].index_buffer_size = p_surface.lods[i].index_data.size();
}
}
}
@@ -333,48 +335,10 @@ RS::SurfaceData MeshStorage::mesh_get_surface(RID p_mesh, int p_surface) const {
RS::SurfaceData sd;
sd.format = s.format;
- {
- Vector<uint8_t> ret;
- ret.resize(s.vertex_buffer_size);
- glBindBuffer(GL_ARRAY_BUFFER, s.vertex_buffer);
-
-#if defined(__EMSCRIPTEN__)
- {
- uint8_t *w = ret.ptrw();
- glGetBufferSubData(GL_ARRAY_BUFFER, 0, s.vertex_buffer_size, w);
- }
-#else
- void *data = glMapBufferRange(GL_ARRAY_BUFFER, 0, s.vertex_buffer_size, GL_MAP_READ_BIT);
- ERR_FAIL_NULL_V(data, RS::SurfaceData());
- {
- uint8_t *w = ret.ptrw();
- memcpy(w, data, s.vertex_buffer_size);
- }
- glUnmapBuffer(GL_ARRAY_BUFFER);
-#endif
- sd.vertex_data = ret;
- }
+ sd.vertex_data = RasterizerStorageGLES3::buffer_get_data(GL_ARRAY_BUFFER, s.vertex_buffer, s.vertex_buffer_size);
if (s.attribute_buffer != 0) {
- Vector<uint8_t> ret;
- ret.resize(s.attribute_buffer_size);
- glBindBuffer(GL_ARRAY_BUFFER, s.attribute_buffer);
-
-#if defined(__EMSCRIPTEN__)
- {
- uint8_t *w = ret.ptrw();
- glGetBufferSubData(GL_ARRAY_BUFFER, 0, s.attribute_buffer_size, w);
- }
-#else
- void *data = glMapBufferRange(GL_ARRAY_BUFFER, 0, s.attribute_buffer_size, GL_MAP_READ_BIT);
- ERR_FAIL_NULL_V(data, RS::SurfaceData());
- {
- uint8_t *w = ret.ptrw();
- memcpy(w, data, s.attribute_buffer_size);
- }
- glUnmapBuffer(GL_ARRAY_BUFFER);
-#endif
- sd.attribute_data = ret;
+ sd.attribute_data = RasterizerStorageGLES3::buffer_get_data(GL_ARRAY_BUFFER, s.attribute_buffer, s.attribute_buffer_size);
}
sd.vertex_count = s.vertex_count;
@@ -382,33 +346,14 @@ RS::SurfaceData MeshStorage::mesh_get_surface(RID p_mesh, int p_surface) const {
sd.primitive = s.primitive;
if (sd.index_count) {
- Vector<uint8_t> ret;
- ret.resize(s.index_buffer_size);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s.index_buffer);
-
-#if defined(__EMSCRIPTEN__)
- {
- uint8_t *w = ret.ptrw();
- glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, s.index_buffer_size, w);
- }
-#else
- void *data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, s.index_buffer_size, GL_MAP_READ_BIT);
- ERR_FAIL_NULL_V(data, RS::SurfaceData());
- {
- uint8_t *w = ret.ptrw();
- memcpy(w, data, s.index_buffer_size);
- }
- glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
-#endif
- sd.index_data = ret;
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ sd.index_data = RasterizerStorageGLES3::buffer_get_data(GL_ELEMENT_ARRAY_BUFFER, s.index_buffer, s.index_buffer_size);
}
sd.aabb = s.aabb;
for (uint32_t i = 0; i < s.lod_count; i++) {
RS::SurfaceData::LOD lod;
lod.edge_length = s.lods[i].edge_length;
- //lod.index_data = RD::get_singleton()->buffer_get_data(s.lods[i].index_buffer);
+ lod.index_data = RasterizerStorageGLES3::buffer_get_data(GL_ELEMENT_ARRAY_BUFFER, s.lods[i].index_buffer, s.lods[i].index_buffer_size);
sd.lods.push_back(lod);
}
@@ -723,17 +668,6 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V
for (int i = 0; i < RS::ARRAY_INDEX; i++) {
if (!attribs[i].enabled) {
glDisableVertexAttribArray(i);
- if (s->format & RS::ARRAY_FLAG_USE_2D_VERTICES) {
- if (i == RS::ARRAY_COLOR) {
- glVertexAttrib4f(i, 1, 1, 1, 1);
- } else if (i == RS::ARRAY_TEX_UV) {
- glVertexAttrib2f(i, 1, 1);
- } else if (i == RS::ARRAY_BONES) {
- glVertexAttrib4f(i, 1, 1, 1, 1);
- } else if (i == RS::ARRAY_WEIGHTS) {
- glVertexAttrib4f(i, 1, 1, 1, 1);
- }
- }
continue;
}
if (i <= RS::ARRAY_TANGENT) {
@@ -949,8 +883,8 @@ void MeshStorage::multimesh_allocate_data(RID p_multimesh, int p_instances, RS::
multimesh->uses_colors = p_use_colors;
multimesh->color_offset_cache = p_transform_format == RS::MULTIMESH_TRANSFORM_2D ? 8 : 12;
multimesh->uses_custom_data = p_use_custom_data;
- multimesh->custom_data_offset_cache = multimesh->color_offset_cache + (p_use_colors ? 4 : 0);
- multimesh->stride_cache = multimesh->custom_data_offset_cache + (p_use_custom_data ? 4 : 0);
+ multimesh->custom_data_offset_cache = multimesh->color_offset_cache + (p_use_colors ? 2 : 0);
+ multimesh->stride_cache = multimesh->custom_data_offset_cache + (p_use_custom_data ? 2 : 0);
multimesh->buffer_set = false;
multimesh->data_cache = Vector<float>();
@@ -977,7 +911,7 @@ int MeshStorage::multimesh_get_instance_count(RID p_multimesh) const {
void MeshStorage::multimesh_set_mesh(RID p_multimesh, RID p_mesh) {
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_COND(!multimesh);
- if (multimesh->mesh == p_mesh) {
+ if (multimesh->mesh == p_mesh || p_mesh.is_null()) {
return;
}
multimesh->mesh = p_mesh;
@@ -990,13 +924,12 @@ void MeshStorage::multimesh_set_mesh(RID p_multimesh, RID p_mesh) {
//we have a data cache, just mark it dirty
_multimesh_mark_all_dirty(multimesh, false, true);
} else if (multimesh->instances) {
- //need to re-create AABB unfortunately, calling this has a penalty
+ // Need to re-create AABB. Unfortunately, calling this has a penalty.
if (multimesh->buffer_set) {
- // TODO add a function to RasterizerStorage to get data from a buffer
- //Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer);
- //const uint8_t *r = buffer.ptr();
- //const float *data = (const float *)r;
- //_multimesh_re_create_aabb(multimesh, data, multimesh->instances);
+ Vector<uint8_t> buffer = RasterizerStorageGLES3::buffer_get_data(GL_ARRAY_BUFFER, multimesh->buffer, multimesh->instances * multimesh->stride_cache * sizeof(float));
+ const uint8_t *r = buffer.ptr();
+ const float *data = (const float *)r;
+ _multimesh_re_create_aabb(multimesh, data, multimesh->instances);
}
}
@@ -1017,10 +950,11 @@ void MeshStorage::_multimesh_make_local(MultiMesh *multimesh) const {
float *w = multimesh->data_cache.ptrw();
if (multimesh->buffer_set) {
- //Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer);
+ Vector<uint8_t> buffer = RasterizerStorageGLES3::buffer_get_data(GL_ARRAY_BUFFER, multimesh->buffer, multimesh->instances * multimesh->stride_cache * sizeof(float));
+
{
- // const uint8_t *r = buffer.ptr();
- // memcpy(w, r, buffer.size());
+ const uint8_t *r = buffer.ptr();
+ memcpy(w, r, buffer.size());
}
} else {
memset(w, 0, (size_t)multimesh->instances * multimesh->stride_cache * sizeof(float));
@@ -1186,14 +1120,12 @@ void MeshStorage::multimesh_instance_set_color(RID p_multimesh, int p_index, con
_multimesh_make_local(multimesh);
{
+ // Colors are packed into 2 floats.
float *w = multimesh->data_cache.ptrw();
float *dataptr = w + p_index * multimesh->stride_cache + multimesh->color_offset_cache;
-
- dataptr[0] = p_color.r;
- dataptr[1] = p_color.g;
- dataptr[2] = p_color.b;
- dataptr[3] = p_color.a;
+ uint16_t val[4] = { Math::make_half_float(p_color.r), Math::make_half_float(p_color.g), Math::make_half_float(p_color.b), Math::make_half_float(p_color.a) };
+ memcpy(dataptr, val, 2 * 4);
}
_multimesh_mark_dirty(multimesh, p_index, false);
@@ -1211,11 +1143,8 @@ void MeshStorage::multimesh_instance_set_custom_data(RID p_multimesh, int p_inde
float *w = multimesh->data_cache.ptrw();
float *dataptr = w + p_index * multimesh->stride_cache + multimesh->custom_data_offset_cache;
-
- dataptr[0] = p_color.r;
- dataptr[1] = p_color.g;
- dataptr[2] = p_color.b;
- dataptr[3] = p_color.a;
+ uint16_t val[4] = { Math::make_half_float(p_color.r), Math::make_half_float(p_color.g), Math::make_half_float(p_color.b), Math::make_half_float(p_color.a) };
+ memcpy(dataptr, val, 2 * 4);
}
_multimesh_mark_dirty(multimesh, p_index, false);
@@ -1306,11 +1235,12 @@ Color MeshStorage::multimesh_instance_get_color(RID p_multimesh, int p_index) co
const float *r = multimesh->data_cache.ptr();
const float *dataptr = r + p_index * multimesh->stride_cache + multimesh->color_offset_cache;
-
- c.r = dataptr[0];
- c.g = dataptr[1];
- c.b = dataptr[2];
- c.a = dataptr[3];
+ uint16_t raw_data[4];
+ memcpy(raw_data, dataptr, 2 * 4);
+ c.r = Math::half_to_float(raw_data[0]);
+ c.g = Math::half_to_float(raw_data[1]);
+ c.b = Math::half_to_float(raw_data[2]);
+ c.a = Math::half_to_float(raw_data[3]);
}
return c;
@@ -1329,11 +1259,12 @@ Color MeshStorage::multimesh_instance_get_custom_data(RID p_multimesh, int p_ind
const float *r = multimesh->data_cache.ptr();
const float *dataptr = r + p_index * multimesh->stride_cache + multimesh->custom_data_offset_cache;
-
- c.r = dataptr[0];
- c.g = dataptr[1];
- c.b = dataptr[2];
- c.a = dataptr[3];
+ uint16_t raw_data[4];
+ memcpy(raw_data, dataptr, 2 * 4);
+ c.r = Math::half_to_float(raw_data[0]);
+ c.g = Math::half_to_float(raw_data[1]);
+ c.b = Math::half_to_float(raw_data[2]);
+ c.a = Math::half_to_float(raw_data[3]);
}
return c;
@@ -1342,19 +1273,66 @@ Color MeshStorage::multimesh_instance_get_custom_data(RID p_multimesh, int p_ind
void MeshStorage::multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) {
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_COND(!multimesh);
- ERR_FAIL_COND(p_buffer.size() != (multimesh->instances * (int)multimesh->stride_cache));
- {
+ if (multimesh->uses_colors || multimesh->uses_custom_data) {
+ // Color and custom need to be packed so copy buffer to data_cache and pack.
+
+ _multimesh_make_local(multimesh);
+ multimesh->data_cache = p_buffer;
+
+ float *w = multimesh->data_cache.ptrw();
+ uint32_t old_stride = multimesh->xform_format == RS::MULTIMESH_TRANSFORM_2D ? 8 : 12;
+ old_stride += multimesh->uses_colors ? 4 : 0;
+ old_stride += multimesh->uses_custom_data ? 4 : 0;
+ for (int i = 0; i < multimesh->instances; i++) {
+ {
+ float *dataptr = w + i * old_stride;
+ float *newptr = w + i * multimesh->stride_cache;
+ float vals[8] = { dataptr[0], dataptr[1], dataptr[2], dataptr[3], dataptr[4], dataptr[5], dataptr[6], dataptr[7] };
+ memcpy(newptr, vals, 8 * 4);
+ }
+
+ if (multimesh->xform_format == RS::MULTIMESH_TRANSFORM_3D) {
+ float *dataptr = w + i * old_stride + 8;
+ float *newptr = w + i * multimesh->stride_cache + 8;
+ float vals[8] = { dataptr[0], dataptr[1], dataptr[2], dataptr[3] };
+ memcpy(newptr, vals, 4 * 4);
+ }
+
+ if (multimesh->uses_colors) {
+ float *dataptr = w + i * old_stride + (multimesh->xform_format == RS::MULTIMESH_TRANSFORM_2D ? 8 : 12);
+ float *newptr = w + i * multimesh->stride_cache + multimesh->color_offset_cache;
+ uint16_t val[4] = { Math::make_half_float(dataptr[0]), Math::make_half_float(dataptr[1]), Math::make_half_float(dataptr[2]), Math::make_half_float(dataptr[3]) };
+ memcpy(newptr, val, 2 * 4);
+ }
+ if (multimesh->uses_custom_data) {
+ float *dataptr = w + i * old_stride + (multimesh->xform_format == RS::MULTIMESH_TRANSFORM_2D ? 8 : 12) + (multimesh->uses_colors ? 4 : 0);
+ float *newptr = w + i * multimesh->stride_cache + multimesh->custom_data_offset_cache;
+ uint16_t val[4] = { Math::make_half_float(dataptr[0]), Math::make_half_float(dataptr[1]), Math::make_half_float(dataptr[2]), Math::make_half_float(dataptr[3]) };
+ memcpy(newptr, val, 2 * 4);
+ }
+ }
+
+ multimesh->data_cache.resize(multimesh->instances * (int)multimesh->stride_cache);
+ const float *r = multimesh->data_cache.ptr();
+ glBindBuffer(GL_ARRAY_BUFFER, multimesh->buffer);
+ glBufferData(GL_ARRAY_BUFFER, multimesh->data_cache.size() * sizeof(float), r, GL_STATIC_DRAW);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ } else {
+ // Only Transform is being used, so we can upload directly.
+ ERR_FAIL_COND(p_buffer.size() != (multimesh->instances * (int)multimesh->stride_cache));
const float *r = p_buffer.ptr();
glBindBuffer(GL_ARRAY_BUFFER, multimesh->buffer);
glBufferData(GL_ARRAY_BUFFER, p_buffer.size() * sizeof(float), r, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
- multimesh->buffer_set = true;
}
- if (multimesh->data_cache.size()) {
+ multimesh->buffer_set = true;
+
+ if (multimesh->data_cache.size() || multimesh->uses_colors || multimesh->uses_custom_data) {
//if we have a data cache, just update it
- multimesh->data_cache = p_buffer;
+ multimesh->data_cache = multimesh->data_cache;
{
//clear dirty since nothing will be dirty anymore
uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
@@ -1367,7 +1345,7 @@ void MeshStorage::multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_b
_multimesh_mark_all_dirty(multimesh, false, true); //update AABB
} else if (multimesh->mesh.is_valid()) {
//if we have a mesh set, we need to re-generate the AABB from the new data
- const float *data = p_buffer.ptr();
+ const float *data = multimesh->data_cache.ptr();
_multimesh_re_create_aabb(multimesh, data, multimesh->instances);
multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
@@ -1377,22 +1355,71 @@ void MeshStorage::multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_b
Vector<float> MeshStorage::multimesh_get_buffer(RID p_multimesh) const {
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_COND_V(!multimesh, Vector<float>());
+ Vector<float> ret;
if (multimesh->buffer == 0) {
return Vector<float>();
} else if (multimesh->data_cache.size()) {
- return multimesh->data_cache;
+ ret = multimesh->data_cache;
} else {
- //get from memory
+ // Buffer not cached, so fetch from GPU memory. This can be a stalling operation, avoid whenever possible.
- //Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer);
- Vector<float> ret;
+ Vector<uint8_t> buffer = RasterizerStorageGLES3::buffer_get_data(GL_ARRAY_BUFFER, multimesh->buffer, multimesh->instances * multimesh->stride_cache * sizeof(float));
ret.resize(multimesh->instances * multimesh->stride_cache);
- //{
- // float *w = ret.ptrw();
- // const uint8_t *r = buffer.ptr();
- // memcpy(w, r, buffer.size());
- //}
+ {
+ float *w = ret.ptrw();
+ const uint8_t *r = buffer.ptr();
+ memcpy(w, r, buffer.size());
+ }
+ }
+ if (multimesh->uses_colors || multimesh->uses_custom_data) {
+ // Need to decompress buffer.
+ uint32_t new_stride = multimesh->xform_format == RS::MULTIMESH_TRANSFORM_2D ? 8 : 12;
+ new_stride += multimesh->uses_colors ? 4 : 0;
+ new_stride += multimesh->uses_custom_data ? 4 : 0;
+
+ Vector<float> decompressed;
+ decompressed.resize(multimesh->instances * (int)new_stride);
+ float *w = decompressed.ptrw();
+ const float *r = ret.ptr();
+ for (int i = 0; i < multimesh->instances; i++) {
+ {
+ float *newptr = w + i * new_stride;
+ const float *oldptr = r + i * multimesh->stride_cache;
+ float vals[8] = { oldptr[0], oldptr[1], oldptr[2], oldptr[3], oldptr[4], oldptr[5], oldptr[6], oldptr[7] };
+ memcpy(newptr, vals, 8 * 4);
+ }
+
+ if (multimesh->xform_format == RS::MULTIMESH_TRANSFORM_3D) {
+ float *newptr = w + i * new_stride + 8;
+ const float *oldptr = r + i * multimesh->stride_cache + 8;
+ float vals[8] = { oldptr[0], oldptr[1], oldptr[2], oldptr[3] };
+ memcpy(newptr, vals, 4 * 4);
+ }
+
+ if (multimesh->uses_colors) {
+ float *newptr = w + i * new_stride + (multimesh->xform_format == RS::MULTIMESH_TRANSFORM_2D ? 8 : 12);
+ const float *oldptr = r + i * multimesh->stride_cache + multimesh->color_offset_cache;
+ uint16_t raw_data[4];
+ memcpy(raw_data, oldptr, 2 * 4);
+ newptr[0] = Math::half_to_float(raw_data[0]);
+ newptr[1] = Math::half_to_float(raw_data[1]);
+ newptr[2] = Math::half_to_float(raw_data[2]);
+ newptr[3] = Math::half_to_float(raw_data[3]);
+ }
+ if (multimesh->uses_custom_data) {
+ float *newptr = w + i * new_stride + (multimesh->xform_format == RS::MULTIMESH_TRANSFORM_2D ? 8 : 12) + (multimesh->uses_colors ? 4 : 0);
+ const float *oldptr = r + i * multimesh->stride_cache + multimesh->custom_data_offset_cache;
+ uint16_t raw_data[4];
+ memcpy(raw_data, oldptr, 2 * 4);
+ newptr[0] = Math::half_to_float(raw_data[0]);
+ newptr[1] = Math::half_to_float(raw_data[1]);
+ newptr[2] = Math::half_to_float(raw_data[2]);
+ newptr[3] = Math::half_to_float(raw_data[3]);
+ }
+ }
+ return decompressed;
+ } else {
return ret;
}
}
@@ -1439,7 +1466,7 @@ void MeshStorage::_update_dirty_multimeshes() {
if (multimesh->data_cache_used_dirty_regions > 32 || multimesh->data_cache_used_dirty_regions > visible_region_count / 2) {
// If there too many dirty regions, or represent the majority of regions, just copy all, else transfer cost piles up too much
glBindBuffer(GL_ARRAY_BUFFER, multimesh->buffer);
- glBufferData(GL_ARRAY_BUFFER, MIN(visible_region_count * region_size, multimesh->instances * (uint32_t)multimesh->stride_cache * (uint32_t)sizeof(float)), data, GL_STATIC_DRAW);
+ glBufferData(GL_ARRAY_BUFFER, MIN(visible_region_count * region_size, multimesh->instances * multimesh->stride_cache * sizeof(float)), data, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
} else {
// Not that many regions? update them all
@@ -1463,8 +1490,7 @@ void MeshStorage::_update_dirty_multimeshes() {
multimesh->data_cache_used_dirty_regions = 0;
}
- if (multimesh->aabb_dirty) {
- //aabb is dirty..
+ if (multimesh->aabb_dirty && multimesh->mesh.is_valid()) {
_multimesh_re_create_aabb(multimesh, data, visible_instances);
multimesh->aabb_dirty = false;
multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
diff --git a/drivers/gles3/storage/mesh_storage.h b/drivers/gles3/storage/mesh_storage.h
index 068aa2fe40..3bb7061413 100644
--- a/drivers/gles3/storage/mesh_storage.h
+++ b/drivers/gles3/storage/mesh_storage.h
@@ -90,6 +90,7 @@ struct Mesh {
struct LOD {
float edge_length = 0.0;
uint32_t index_count = 0;
+ uint32_t index_buffer_size = 0;
GLuint index_buffer;
};
diff --git a/editor/editor_path.cpp b/editor/editor_path.cpp
index 8747128962..6453db3b0b 100644
--- a/editor/editor_path.cpp
+++ b/editor/editor_path.cpp
@@ -72,7 +72,7 @@ void EditorPath::_add_children_to_popup(Object *p_obj, int p_depth) {
int index = sub_objects_menu->get_item_count();
sub_objects_menu->add_icon_item(icon, proper_name, objects.size());
- sub_objects_menu->set_item_h_offset(index, p_depth * 10 * EDSCALE);
+ sub_objects_menu->set_item_horizontal_offset(index, p_depth * 10 * EDSCALE);
objects.push_back(obj->get_instance_id());
_add_children_to_popup(obj, p_depth + 1);
diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp
index f47c6e298b..f1a3fe0c57 100644
--- a/editor/editor_properties_array_dict.cpp
+++ b/editor/editor_properties_array_dict.cpp
@@ -347,6 +347,7 @@ void EditorPropertyArray::update_property() {
prop->set_object_and_property(object.ptr(), prop_name);
prop->set_label(itos(i + offset));
prop->set_selectable(false);
+ prop->set_use_folding(is_using_folding());
prop->connect("property_changed", callable_mp(this, &EditorPropertyArray::_property_changed));
prop->connect("object_id_selected", callable_mp(this, &EditorPropertyArray::_object_id_selected));
prop->set_h_size_flags(SIZE_EXPAND_FILL);
@@ -1006,6 +1007,7 @@ void EditorPropertyDictionary::update_property() {
} else {
EditorPropertyResource *editor = memnew(EditorPropertyResource);
editor->setup(object.ptr(), prop_name, "Resource");
+ editor->set_use_folding(is_using_folding());
prop = editor;
}
diff --git a/editor/plugins/input_event_editor_plugin.cpp b/editor/plugins/input_event_editor_plugin.cpp
index fb0e260388..2acd0fca6e 100644
--- a/editor/plugins/input_event_editor_plugin.cpp
+++ b/editor/plugins/input_event_editor_plugin.cpp
@@ -84,8 +84,7 @@ InputEventConfigContainer::InputEventConfigContainer() {
input_event_text->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
add_child(input_event_text);
- open_config_button = memnew(Button);
- open_config_button->set_text(TTR("Configure"));
+ open_config_button = EditorInspector::create_inspector_action_button(TTR("Configure"));
open_config_button->connect("pressed", callable_mp(this, &InputEventConfigContainer::_configure_pressed));
add_child(open_config_button);
diff --git a/editor/project_converter_3_to_4.cpp b/editor/project_converter_3_to_4.cpp
new file mode 100644
index 0000000000..515d09c3fc
--- /dev/null
+++ b/editor/project_converter_3_to_4.cpp
@@ -0,0 +1,3811 @@
+/*************************************************************************/
+/* project_converter_3_to_4.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "project_converter_3_to_4.h"
+
+#include "modules/modules_enabled.gen.h"
+
+#ifdef MODULE_REGEX_ENABLED
+#include "modules/regex/regex.h"
+
+#include "core/os/time.h"
+#include "core/templates/hash_map.h"
+#include "core/templates/list.h"
+
+const int ERROR_CODE = 77;
+const int CONVERSION_MAX_FILE_SIZE = 1024 * 1024 * 4; // 4 MB
+
+static const char *enum_renames[][2] = {
+ //// constants
+ { "TYPE_COLOR_ARRAY", "TYPE_PACKED_COLOR_ARRAY" },
+ { "TYPE_FLOAT64_ARRAY", "TYPE_PACKED_FLOAT64_ARRAY" },
+ { "TYPE_INT64_ARRAY", "TYPE_PACKED_INT64_ARRAY" },
+ { "TYPE_INT_ARRAY", "TYPE_PACKED_INT32_ARRAY" },
+ { "TYPE_QUAT", "TYPE_QUATERNION" },
+ { "TYPE_RAW_ARRAY", "TYPE_PACKED_BYTE_ARRAY" },
+ { "TYPE_REAL", "TYPE_FLOAT" },
+ { "TYPE_REAL_ARRAY", "TYPE_PACKED_FLOAT32_ARRAY" },
+ { "TYPE_STRING_ARRAY", "TYPE_PACKED_STRING_ARRAY" },
+ { "TYPE_TRANSFORM", "TYPE_TRANSFORM3D" },
+ { "TYPE_VECTOR2_ARRAY", "TYPE_PACKED_VECTOR2_ARRAY" },
+ { "TYPE_VECTOR3_ARRAY", "TYPE_PACKED_VECTOR3_ARRAY" },
+
+ // {"FLAG_MAX", "PARTICLE_FLAG_MAX"}, // CPUParticles2D - used in more classes
+ { "ALIGN_BEGIN", "ALIGNMENT_BEGIN" }, //AspectRatioContainer
+ { "ALIGN_CENTER", "ALIGNMENT_CENTER" }, //AspectRatioContainer
+ { "ALIGN_END", "ALIGNMENT_END" }, //AspectRatioContainer
+ { "ARRAY_COMPRESS_BASE", "ARRAY_COMPRESS_FLAGS_BASE" }, // Mesh
+ { "ARVR_AR", "XR_AR" }, // XRInterface
+ { "ARVR_EXCESSIVE_MOTION", "XR_EXCESSIVE_MOTION" }, // XRInterface
+ { "ARVR_EXTERNAL", "XR_EXTERNAL" }, // XRInterface
+ { "ARVR_INSUFFICIENT_FEATURES", "XR_INSUFFICIENT_FEATURES" }, // XRInterface
+ { "ARVR_MONO", "XR_MONO" }, // XRInterface
+ { "ARVR_NONE", "XR_NONE" }, // XRInterface
+ { "ARVR_NORMAL_TRACKING", "XR_NORMAL_TRACKING" }, // XRInterface
+ { "ARVR_NOT_TRACKING", "XR_NOT_TRACKING" }, // XRInterface
+ { "ARVR_STEREO", "XR_STEREO" }, // XRInterface
+ { "ARVR_UNKNOWN_TRACKING", "XR_UNKNOWN_TRACKING" }, // XRInterface
+ { "BAKE_ERROR_INVALID_MESH", "BAKE_ERROR_MESHES_INVALID" }, // LightmapGI
+ { "BODY_MODE_CHARACTER", "BODY_MODE_DYNAMIC" }, // PhysicsServer2D
+ { "BODY_MODE_DYNAMIC_LOCKED", "BODY_MODE_DYNAMIC_LINEAR" }, // PhysicsServer3D
+ { "BUTTON_LEFT", "MOUSE_BUTTON_LEFT" }, // Globals
+ { "BUTTON_MASK_LEFT", "MOUSE_BUTTON_MASK_LEFT" }, // Globals
+ { "BUTTON_MASK_MIDDLE", "MOUSE_BUTTON_MASK_MIDDLE" }, // Globals
+ { "BUTTON_MASK_RIGHT", "MOUSE_BUTTON_MASK_RIGHT" }, // Globals
+ { "BUTTON_MASK_XBUTTON1", "MOUSE_BUTTON_MASK_XBUTTON1" }, // Globals
+ { "BUTTON_MASK_XBUTTON2", "MOUSE_BUTTON_MASK_XBUTTON2" }, // Globals
+ { "BUTTON_MIDDLE", "MOUSE_BUTTON_MIDDLE" }, // Globals
+ { "BUTTON_RIGHT", "MOUSE_BUTTON_RIGHT" }, // Globals
+ { "BUTTON_WHEEL_DOWN", "MOUSE_BUTTON_WHEEL_DOWN" }, // Globals
+ { "BUTTON_WHEEL_LEFT", "MOUSE_BUTTON_WHEEL_LEFT" }, // Globals
+ { "BUTTON_WHEEL_RIGHT", "MOUSE_BUTTON_WHEEL_RIGHT" }, // Globals
+ { "BUTTON_WHEEL_UP", "MOUSE_BUTTON_WHEEL_UP" }, // Globals
+ { "BUTTON_XBUTTON1", "MOUSE_BUTTON_XBUTTON1" }, // Globals
+ { "BUTTON_XBUTTON2", "MOUSE_BUTTON_XBUTTON2" }, // Globals
+ { "CLEAR_MODE_ONLY_NEXT_FRAME", "CLEAR_MODE_ONCE" }, // SubViewport
+ { "COMPRESS_PVRTC4", "COMPRESS_PVRTC1_4" }, // Image
+ { "CUBEMAP_BACK", "CUBEMAP_LAYER_BACK" }, // RenderingServer
+ { "CUBEMAP_BOTTOM", "CUBEMAP_LAYER_BOTTOM" }, // RenderingServer
+ { "CUBEMAP_FRONT", "CUBEMAP_LAYER_FRONT" }, // RenderingServer
+ { "CUBEMAP_LEFT", "CUBEMAP_LAYER_LEFT" }, // RenderingServer
+ { "CUBEMAP_RIGHT", "CUBEMAP_LAYER_RIGHT" }, // RenderingServer
+ { "CUBEMAP_TOP", "CUBEMAP_LAYER_TOP" }, // RenderingServer
+ { "DAMPED_STRING_DAMPING", "DAMPED_SPRING_DAMPING" }, // PhysicsServer2D
+ { "DAMPED_STRING_REST_LENGTH", "DAMPED_SPRING_REST_LENGTH" }, // PhysicsServer2D
+ { "DAMPED_STRING_STIFFNESS", "DAMPED_SPRING_STIFFNESS" }, // PhysicsServer2D
+ { "FLAG_ALIGN_Y_TO_VELOCITY", "PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY" }, // CPUParticles2D
+ { "FLAG_DISABLE_Z", "PARTICLE_FLAG_DISABLE_Z" }, // CPUParticles2D
+ { "FLAG_ROTATE_Y", "PARTICLE_FLAG_ROTATE_Y" }, // CPUParticles2D
+ { "FLAG_USE_BAKED_LIGHT", "GI_MODE_BAKED" }, // GeometryInstance3D
+ { "FORMAT_PVRTC2", "FORMAT_PVRTC1_2" }, // Image
+ { "FORMAT_PVRTC2A", "FORMAT_PVRTC1_2A" }, // Image
+ { "FORMAT_PVRTC4", "FORMAT_PVRTC1_4" }, // Image
+ { "FORMAT_PVRTC4A", "FORMAT_PVRTC1_4A" }, // Image
+ { "INSTANCE_LIGHTMAP_CAPTURE", "INSTANCE_LIGHTMAP" }, // RenderingServer
+ { "JOINT_6DOF", "JOINT_TYPE_6DOF" }, // PhysicsServer3D
+ { "JOINT_CONE_TWIST", "JOINT_TYPE_CONE_TWIST" }, // PhysicsServer3D
+ { "JOINT_DAMPED_SPRING", "JOINT_TYPE_DAMPED_SPRING" }, // PhysicsServer2D
+ { "JOINT_GROOVE", "JOINT_TYPE_GROOVE" }, // PhysicsServer2D
+ { "JOINT_HINGE", "JOINT_TYPE_HINGE" }, // PhysicsServer3D
+ { "JOINT_PIN", "JOINT_TYPE_PIN" }, // PhysicsServer2D
+ { "JOINT_SLIDER", "JOINT_TYPE_SLIDER" }, // PhysicsServer3D
+ { "KEY_CONTROL", "KEY_CTRL" }, // Globals
+ { "LOOP_PING_PONG", "LOOP_PINGPONG" }, //AudioStreamSample
+ { "MATH_RAND", "MATH_RANDF_RANGE" }, // VisualScriptBuiltinFunc
+ { "MATH_RANDOM", "MATH_RANDI_RANGE" }, // VisualScriptBuiltinFunc
+ { "MATH_STEPIFY", "MATH_STEP_DECIMALS" }, // VisualScriptBuiltinFunc
+ { "MODE_CHARACTER", "MODE_DYNAMIC_LOCKED" }, // RigidBody2D, RigidBody3D
+ { "MODE_OPEN_ANY", "FILE_MODE_OPEN_ANY" }, // FileDialog
+ { "MODE_OPEN_DIR", "FILE_MODE_OPEN_DIR" }, // FileDialog
+ { "MODE_OPEN_FILE", "FILE_MODE_OPEN_FILE" }, // FileDialog
+ { "MODE_OPEN_FILES", "FILE_MODE_OPEN_FILES" }, // FileDialog
+ { "MODE_RIGID", "MODE_DYNAMIC" }, // RigidBody2D, RigidBody3D
+ { "MODE_SAVE_FILE", "FILE_MODE_SAVE_FILE" }, // FileDialog
+ { "NOTIFICATION_APP_PAUSED", "NOTIFICATION_APPLICATION_PAUSED" }, // MainLoop
+ { "NOTIFICATION_APP_RESUMED", "NOTIFICATION_APPLICATION_RESUMED" }, // MainLoop
+ { "NOTIFICATION_PATH_CHANGED", "NOTIFICATION_PATH_RENAMED" }, //Node
+ { "NOTIFICATION_WM_FOCUS_IN", "NOTIFICATION_APPLICATION_FOCUS_IN" }, // MainLoop
+ { "NOTIFICATION_WM_FOCUS_OUT", "NOTIFICATION_APPLICATION_FOCUS_OUT" }, // MainLoop
+ { "NOTIFICATION_WM_UNFOCUS_REQUEST", "NOTIFICATION_WM_WINDOW_FOCUS_OUT" }, //Node
+ { "PAUSE_MODE_INHERIT", "PROCESS_MODE_INHERIT" }, // Node
+ { "PAUSE_MODE_PROCESS", "PROCESS_MODE_ALWAYS" }, // Node
+ { "PAUSE_MODE_STOP", "PROCESS_MODE_PAUSABLE" }, // Node
+ { "RENDER_DRAW_CALLS_IN_FRAME", "RENDER_TOTAL_DRAW_CALLS_IN_FRAME" }, // Performance
+ { "RENDER_OBJECTS_IN_FRAME", "RENDER_TOTAL_OBJECTS_IN_FRAME" }, // Performance
+ { "SIDE_BOTTOM", "MARGIN_BOTTOM" }, // Globals
+ { "SIDE_LEFT", "MARGIN_LEFT" }, // Globals
+ { "SIDE_RIGHT", "MARGIN_RIGHT" }, // Globals
+ { "SIDE_TOP", "MARGIN_TOP" }, // Globals
+ { "TEXTURE_TYPE_2D_ARRAY", "TEXTURE_LAYERED_2D_ARRAY" }, // RenderingServer
+ { "TEXTURE_TYPE_CUBEMAP", "TEXTURE_LAYERED_CUBEMAP_ARRAY" }, // RenderingServer
+ { "TRACKER_LEFT_HAND", "TRACKER_HAND_LEFT" }, // XRPositionalTracker
+ { "TRACKER_RIGHT_HAND", "TRACKER_HAND_RIGHT" }, // XRPositionalTracker
+ { "TYPE_NORMALMAP", "TYPE_NORMAL_MAP" }, // VisualShaderNodeCubemap
+
+ /// enums
+ { "AlignMode", "AlignmentMode" }, //AspectRatioContainer
+ { "AnimationProcessMode", "AnimationProcessCallback" }, // AnimationTree, AnimationPlayer
+ { "Camera2DProcessMode", "Camera2DProcessCallback" }, // Camera2D
+ { "CubeMapSide", "CubeMapLayer" }, // RenderingServer
+ { "DampedStringParam", "DampedSpringParam" }, // PhysicsServer2D
+ { "FFT_Size", "FFTSize" }, // AudioEffectPitchShift,AudioEffectSpectrumAnalyzer
+ { "PauseMode", "ProcessMode" }, // Node
+ { "TimerProcessMode", "TimerProcessCallback" }, // Timer
+ { "Tracking_status", "TrackingStatus" }, // XRInterface
+ { nullptr, nullptr },
+};
+
+static const char *gdscript_function_renames[][2] = {
+ // { "_set_name", "get_tracker_name"}, // XRPositionalTracker - CameraFeed use this
+ // { "_unhandled_input", "_unhandled_key_input"}, // BaseButton, ViewportContainer broke Node, FileDialog,SubViewportContainer
+ // { "create_gizmo", "_create_gizmo"}, // EditorNode3DGizmoPlugin - may be used
+ // { "get_dependencies", "_get_dependencies" }, // ResourceFormatLoader broke ResourceLoader
+ // { "get_extents", "get_size" }, // BoxShape, RectangleShape broke Decal, VoxelGI, GPUParticlesCollisionBox, GPUParticlesCollisionSDF, GPUParticlesCollisionHeightField, GPUParticlesAttractorBox, GPUParticlesAttractorVectorField, FogVolume
+ // { "get_h_offset", "get_drag_horizontal_offset"}, // Camera2D, broke PathFollow, Camera
+ // { "get_mode", "get_file_mode"}, // FileDialog broke Panel, Shader, CSGPolygon, Tilemap
+ // { "get_motion", "get_travel"}, // PhysicsTestMotionResult2D broke ParalaxLayer
+ // { "get_name", "get_tracker_name"}, // XRPositionalTracker broke OS, Node
+ // { "get_network_connected_peers", "get_peers"}, // MultiplayerAPI broke SceneTree
+ // { "get_network_peer", "has_multiplayer_peer"}, // MultiplayerAPI broke SceneTree
+ // { "get_network_unique_id", "get_unique_id"}, // MultiplayerAPI broke SceneTree
+ // { "get_offset", "get_position_offset" }, // GraphNode broke Gradient
+ // { "get_peer_port", "get_peer" }, // ENetMultiplayerPeer broke WebSocketServer
+ // { "get_process_mode", "get_process_callback" }, // ClippedCamera3D broke Node, Sky
+ // { "get_render_info", "get_rendering_info" }, // RenderingServer broke Viewport
+ // { "get_type", "get_tracker_type"}, // XRPositionalTracker broke GLTFAccessor, GLTFLight
+ // { "get_v_offset", "get_drag_vertical_offset"}, // Camera2D, broke PathFollow, Camera
+ // { "has_network_peer", "has_multiplayer_peer"}, // MultiplayerAPI broke SceneTree
+ // { "instance", "instantiate" }, // PackedScene, ClassDB - Broke FileSystemDock signal and also tscn files - [instance=ExtResource( 17 )] - this is implemented as custom rule
+ // { "is_listening", "is_bound"}, // PacketPeerUDP broke TCPServer, UDPServer
+ // { "is_refusing_new_network_connections", "is_refusing_new_connections"}, // MultiplayerAPI broke SceneTree
+ // { "is_valid", "has_valid_event" }, // Shortcut broke e.g. Callable
+ // { "listen", "bound"}, // PacketPeerUDP broke TCPServer, UDPServer
+ // { "load", "_load"}, // ResourceFormatLoader broke ConfigFile, Image, StreamTexture2D
+ // { "make_current", "set_current" }, // Camera2D broke Camera3D, Listener2D
+ // { "process", "_process" }, // AnimationNode - This word is commonly used
+ // { "save", "_save"}, // ResourceFormatLoader broke ConfigFile, Image, StreamTexture2D
+ // { "set_autowrap", "set_autowrap_mode" }, // AcceptDialog broke Label - Cyclic Rename
+ // { "set_color", "surface_set_color"}, // ImmediateMesh broke Light2D, Theme, SurfaceTool
+ // { "set_event", "set_shortcut" }, // BaseButton - Cyclic Rename
+ // { "set_extents", "set_size"}, // BoxShape, RectangleShape broke ReflectionProbe
+ // { "set_flag", "set_particle_flag"}, // ParticlesMaterial broke Window, HingeJoint3D
+ // { "set_h_offset", "set_drag_horizontal_offset" }, // Camera2D broke Camera3D, PathFollow3D, PathFollow2D
+ // { "set_margin", "set_offset" }, // Control broke Shape3D, AtlasTexture
+ // { "set_mode", "set_mode_file_mode" }, // FileDialog broke Panel, Shader, CSGPolygon, Tilemap
+ // { "set_normal", "surface_set_normal"}, // ImmediateGeometry broke SurfaceTool, WorldMarginShape2D
+ // { "set_process_mode", "set_process_callback" }, // AnimationTree broke Node, Tween, Sky
+ // { "set_refuse_new_network_connections", "set_refuse_new_connections"}, // MultiplayerAPI broke SceneTree
+ // { "set_uv", "surface_set_uv" }, // ImmediateMesh broke Polygon2D
+ // { "set_v_offset", "set_drag_vertical_offset" }, // Camera2D broke Camera3D, PathFollow3D, PathFollow2D
+ // {"get_points","get_points_id"},// Astar, broke Line2D, Convexpolygonshape
+ // {"get_v_scroll","get_v_scroll_bar"},//ItemList, broke TextView
+ { "RenderingServer", "get_tab_alignment" }, // Tab
+ { "_about_to_show", "_about_to_popup" }, // ColorPickerButton
+ { "_get_configuration_warning", "_get_configuration_warnings" }, // Node
+ { "_set_current", "set_current" }, // Camera2D
+ { "_set_editor_description", "set_editor_description" }, // Node
+ { "_toplevel_raise_self", "_top_level_raise_self" }, // CanvasItem
+ { "_update_wrap_at", "_update_wrap_at_column" }, // TextEdit
+ { "add_animation", "add_animation_library" }, // AnimationPlayer
+ { "add_cancel", "add_cancel_button" }, // AcceptDialog
+ { "add_central_force", "add_constant_central_force" }, //RigidDynamicBody2D
+ { "add_child_below_node", "add_sibling" }, // Node
+ { "add_color_override", "add_theme_color_override" }, // Control
+ { "add_constant_override", "add_theme_constant_override" }, // Control
+ { "add_font_override", "add_theme_font_override" }, // Control
+ { "add_force", "add_constant_force" }, //RigidDynamicBody2D
+ { "add_icon_override", "add_theme_icon_override" }, // Control
+ { "add_scene_import_plugin", "add_scene_format_importer_plugin" }, //EditorPlugin
+ { "add_stylebox_override", "add_theme_stylebox_override" }, // Control
+ { "add_torque", "add_constant_torque" }, //RigidDynamicBody2D
+ { "bind_child_node_to_bone", "set_bone_children" }, // Skeleton3D
+ { "bumpmap_to_normalmap", "bump_map_to_normal_map" }, // Image
+ { "can_be_hidden", "_can_be_hidden" }, // EditorNode3DGizmoPlugin
+ { "can_drop_data_fw", "_can_drop_data_fw" }, // ScriptEditor
+ { "can_generate_small_preview", "_can_generate_small_preview" }, // EditorResourcePreviewGenerator
+ { "can_instance", "can_instantiate" }, // PackedScene, Script
+ { "canvas_light_set_scale", "canvas_light_set_texture_scale" }, // RenderingServer
+ { "center_viewport_to_cursor", "center_viewport_to_caret" }, // TextEdit
+ { "clip_polygons_2d", "clip_polygons" }, // Geometry2D
+ { "clip_polyline_with_polygon_2d", "clip_polyline_with_polygon" }, //Geometry2D
+ { "commit_handle", "_commit_handle" }, // EditorNode3DGizmo
+ { "convex_hull_2d", "convex_hull" }, // Geometry2D
+ { "cursor_get_blink_speed", "get_caret_blink_speed" }, // TextEdit
+ { "cursor_get_column", "get_caret_column" }, // TextEdit
+ { "cursor_get_line", "get_caret_line" }, // TextEdit
+ { "cursor_set_blink_enabled", "set_caret_blink_enabled" }, // TextEdit
+ { "cursor_set_blink_speed", "set_caret_blink_speed" }, // TextEdit
+ { "cursor_set_column", "set_caret_column" }, // TextEdit
+ { "cursor_set_line", "set_caret_line" }, // TextEdit
+ { "damped_spring_joint_create", "joint_make_damped_spring" }, // PhysicsServer2D
+ { "damped_string_joint_get_param", "damped_spring_joint_get_param" }, // PhysicsServer2D
+ { "damped_string_joint_set_param", "damped_spring_joint_set_param" }, // PhysicsServer2D
+ { "delete_char_at_cursor", "delete_char_at_caret" }, // LineEdit
+ { "deselect_items", "deselect_all" }, // FileDialog
+ { "drop_data_fw", "_drop_data_fw" }, // ScriptEditor
+ { "exclude_polygons_2d", "exclude_polygons" }, // Geometry2D
+ { "find_scancode_from_string", "find_keycode_from_string" }, // OS
+ { "forward_canvas_draw_over_viewport", "_forward_canvas_draw_over_viewport" }, // EditorPlugin
+ { "forward_canvas_force_draw_over_viewport", "_forward_canvas_force_draw_over_viewport" }, // EditorPlugin
+ { "forward_canvas_gui_input", "_forward_canvas_gui_input" }, // EditorPlugin
+ { "forward_spatial_draw_over_viewport", "_forward_3d_draw_over_viewport" }, // EditorPlugin
+ { "forward_spatial_force_draw_over_viewport", "_forward_3d_force_draw_over_viewport" }, // EditorPlugin
+ { "forward_spatial_gui_input", "_forward_3d_gui_input" }, // EditorPlugin
+ { "generate_from_path", "_generate_from_path" }, // EditorResourcePreviewGenerator
+ { "generate_small_preview_automatically", "_generate_small_preview_automatically" }, // EditorResourcePreviewGenerator
+ { "get_action_list", "action_get_events" }, // InputMap
+ { "get_alt", "is_alt_pressed" }, // InputEventWithModifiers
+ { "get_animation_process_mode", "get_process_callback" }, // AnimationPlayer
+ { "get_applied_force", "get_constant_force" }, //RigidDynamicBody2D
+ { "get_applied_torque", "get_constant_torque" }, //RigidDynamicBody2D
+ { "get_audio_bus", "get_audio_bus_name" }, // Area3D
+ { "get_bound_child_nodes_to_bone", "get_bone_children" }, // Skeleton3D
+ { "get_camera", "get_camera_3d" }, // Viewport -> this is also convertable to get_camera_2d, broke GLTFNode
+ { "get_cancel", "get_cancel_button" }, // ConfirmationDialog
+ { "get_caption", "_get_caption" }, // AnimationNode
+ { "get_cast_to", "get_target_position" }, // RayCast2D, RayCast3D
+ { "get_child_by_name", "_get_child_by_name" }, // AnimationNode
+ { "get_child_nodes", "_get_child_nodes" }, // AnimationNode
+ { "get_closest_point_to_segment_2d", "get_closest_point_to_segment" }, // Geometry2D
+ { "get_closest_point_to_segment_uncapped_2d", "get_closest_point_to_segment_uncapped" }, // Geometry2D
+ { "get_closest_points_between_segments_2d", "get_closest_point_to_segment" }, // Geometry2D
+ { "get_collision_layer_bit", "get_collision_layer_value" }, // CSGShape3D and a lot of others like GridMap
+ { "get_collision_mask_bit", "get_collision_mask_value" }, // CSGShape3D and a lot of others like GridMap
+ { "get_color_types", "get_color_type_list" }, // Theme
+ { "get_command", "is_command_pressed" }, // InputEventWithModifiers
+ { "get_constant_types", "get_constant_type_list" }, // Theme
+ { "get_control", "is_ctrl_pressed" }, // InputEventWithModifiers
+ { "get_cull_mask_bit", "get_cull_mask_value" }, // Camera3D
+ { "get_cursor_position", "get_caret_column" }, // LineEdit
+ { "get_d", "get_distance" }, // LineShape2D
+ { "get_drag_data_fw", "_get_drag_data_fw" }, // ScriptEditor
+ { "get_editor_viewport", "get_viewport" }, // EditorPlugin
+ { "get_enabled_focus_mode", "get_focus_mode" }, // BaseButton
+ { "get_endian_swap", "is_big_endian" }, // File
+ { "get_error_string", "get_error_message" }, // JSON
+ { "get_focus_neighbour", "get_focus_neighbor" }, // Control
+ { "get_font_types", "get_font_type_list" }, // Theme
+ { "get_frame_color", "get_color" }, // ColorRect
+ { "get_global_rate_scale", "get_playback_speed_scale" }, // AudioServer
+ { "get_gravity_distance_scale", "get_gravity_point_distance_scale" }, //Area2D
+ { "get_gravity_vector", "get_gravity_direction" }, //Area2D
+ { "get_h_scrollbar", "get_h_scroll_bar" }, //ScrollContainer
+ { "get_hand", "get_tracker_hand" }, // XRPositionalTracker
+ { "get_handle_name", "_get_handle_name" }, // EditorNode3DGizmo
+ { "get_handle_value", "_get_handle_value" }, // EditorNode3DGizmo
+ { "get_icon_align", "get_icon_alignment" }, // Button
+ { "get_icon_types", "get_icon_type_list" }, // Theme
+ { "get_idle_frames", "get_process_frames" }, // Engine
+ { "get_import_options", "_get_import_options" }, // EditorImportPlugin
+ { "get_import_order", "_get_import_order" }, // EditorImportPlugin
+ { "get_importer_name", "_get_importer_name" }, // EditorImportPlugin
+ { "get_interior_ambient", "get_ambient_color" }, // ReflectionProbe
+ { "get_interior_ambient_energy", "get_ambient_color_energy" }, // ReflectionProbe
+ { "get_iterations_per_second", "get_physics_ticks_per_second" }, // Engine
+ { "get_last_mouse_speed", "get_last_mouse_velocity" }, // Input
+ { "get_layer_mask_bit", "get_layer_mask_value" }, // VisualInstance3D
+ { "get_len", "get_length" }, // File
+ { "get_max_atlas_size", "get_max_texture_size" }, // LightmapGI
+ { "get_metakey", "is_meta_pressed" }, // InputEventWithModifiers
+ { "get_mid_height", "get_height" }, // CapsuleMesh
+ { "get_motion_remainder", "get_remainder" }, // PhysicsTestMotionResult2D
+ { "get_network_connected_peers", "get_peers" }, // Multiplayer API
+ { "get_network_master", "get_multiplayer_authority" }, // Node
+ { "get_network_peer", "get_multiplayer_peer" }, // Multiplayer API
+ { "get_network_unique_id", "get_unique_id" }, // Multiplayer API
+ { "get_ok", "get_ok_button" }, // AcceptDialog
+ { "get_option_visibility", "_get_option_visibility" }, // EditorImportPlugin
+ { "get_parameter_default_value", "_get_parameter_default_value" }, // AnimationNode
+ { "get_parameter_list", "_get_parameter_list" }, // AnimationNode
+ { "get_parent_spatial", "get_parent_node_3d" }, // Node3D
+ { "get_physical_scancode", "get_physical_keycode" }, // InputEventKey
+ { "get_physical_scancode_with_modifiers", "get_physical_keycode_with_modifiers" }, // InputEventKey
+ { "get_plugin_icon", "_get_plugin_icon" }, // EditorPlugin
+ { "get_plugin_name", "_get_plugin_name" }, // EditorPlugin
+ { "get_preset_count", "_get_preset_count" }, // EditorImportPlugin
+ { "get_preset_name", "_get_preset_name" }, // EditorImportPlugin
+ { "get_recognized_extensions", "_get_recognized_extensions" }, // ResourceFormatLoader, EditorImportPlugin broke ResourceSaver
+ { "get_render_info", "get_rendering_info" }, // RenderingServer
+ { "get_render_targetsize", "get_render_target_size" }, // XRInterface
+ { "get_resource_type", "_get_resource_type" }, // ResourceFormatLoader
+ { "get_result", "get_data" }, //JSON
+ { "get_rpc_sender_id", "get_remote_sender_id" }, // Multiplayer API
+ { "get_save_extension", "_get_save_extension" }, // EditorImportPlugin
+ { "get_scancode", "get_keycode" }, // InputEventKey
+ { "get_scancode_string", "get_keycode_string" }, // OS
+ { "get_scancode_with_modifiers", "get_keycode_with_modifiers" }, // InputEventKey
+ { "get_shift", "is_shift_pressed" }, // InputEventWithModifiers
+ { "get_size_override", "get_size_2d_override" }, // SubViewport
+ { "get_slips_on_slope", "get_slide_on_slope" }, // SeparationRayShape2D, SeparationRayShape3D
+ { "get_space_override_mode", "get_gravity_space_override_mode" }, // Area2D
+ { "get_speed", "get_velocity" }, // InputEventMouseMotion
+ { "get_stylebox_types", "get_stylebox_type_list" }, // Theme
+ { "get_surface_material", "get_surface_override_material" }, // MeshInstance3D broke ImporterMesh
+ { "get_surface_material_count", "get_surface_override_material_count" }, // MeshInstance3D
+ { "get_tab_disabled", "is_tab_disabled" }, // Tab
+ { "get_tab_hidden", "is_tab_hidden" }, // Tab
+ { "get_text_align", "get_text_alignment" }, // Button
+ { "get_theme_item_types", "get_theme_item_type_list" }, // Theme
+ { "get_timer_process_mode", "get_timer_process_callback" }, // Timer
+ { "get_translation", "get_position" }, // Node3D broke GLTFNode which is used rarely
+ { "get_use_in_baked_light", "is_baking_navigation" }, // GridMap
+ { "get_used_cells_by_id", "get_used_cells" }, // TileMap
+ { "get_v_scrollbar", "get_v_scroll_bar" }, //ScrollContainer
+ { "get_visible_name", "_get_visible_name" }, // EditorImportPlugin
+ { "get_window_layout", "_get_window_layout" }, // EditorPlugin
+ { "get_word_under_cursor", "get_word_under_caret" }, // TextEdit
+ { "get_world", "get_world_3d" }, // Viewport, Spatial
+ { "get_zfar", "get_far" }, // Camera3D broke GLTFCamera
+ { "get_znear", "get_near" }, // Camera3D broke GLTFCamera
+ { "groove_joint_create", "joint_make_groove" }, // PhysicsServer2D
+ { "handle_menu_selected", "_handle_menu_selected" }, // EditorResourcePicker
+ { "handles_type", "_handles_type" }, // ResourceFormatLoader
+ { "has_color", "has_theme_color" }, // Control broke Theme
+ { "has_color_override", "has_theme_color_override" }, // Control broke Theme
+ { "has_constant", "has_theme_constant" }, // Control
+ { "has_constant_override", "has_theme_constant_override" }, // Control
+ { "has_filter", "_has_filter" }, // AnimationNode
+ { "has_font", "has_theme_font" }, // Control broke Theme
+ { "has_font_override", "has_theme_font_override" }, // Control
+ { "has_icon", "has_theme_icon" }, // Control broke Theme
+ { "has_icon_override", "has_theme_icon_override" }, // Control
+ { "has_main_screen", "_has_main_screen" }, // EditorPlugin
+ { "has_network_peer", "has_multiplayer_peer" }, // Multiplayer API
+ { "has_stylebox", "has_theme_stylebox" }, // Control broke Theme
+ { "has_stylebox_override", "has_theme_stylebox_override" }, // Control
+ { "http_escape", "uri_encode" }, // String
+ { "http_unescape", "uri_decode" }, // String
+ { "import_animation_from_other_importer", "_import_animation" }, //EditorSceneFormatImporter
+ { "import_scene_from_other_importer", "_import_scene" }, //EditorSceneFormatImporter
+ { "instance_set_surface_material", "instance_set_surface_override_material" }, // RenderingServer
+ { "intersect_polygons_2d", "intersect_polygons" }, // Geometry2D
+ { "intersect_polyline_with_polygon_2d", "intersect_polyline_with_polygon" }, // Geometry2D
+ { "is_a_parent_of", "is_ancestor_of" }, // Node
+ { "is_commiting_action", "is_committing_action" }, // UndoRedo
+ { "is_doubleclick", "is_double_click" }, // InputEventMouseButton
+ { "is_h_drag_enabled", "is_drag_horizontal_enabled" }, // Camera2D
+ { "is_handle_highlighted", "_is_handle_highlighted" }, // EditorNode3DGizmo, EditorNode3DGizmoPlugin
+ { "is_network_master", "is_multiplayer_authority" }, // Node
+ { "is_network_server", "is_server" }, // Multiplayer API
+ { "is_normalmap", "is_normal_map" }, // NoiseTexture
+ { "is_refusing_new_network_connections", "is_refusing_new_connections" }, // Multiplayer API
+ { "is_region", "is_region_enabled" }, // Sprite2D
+ { "is_scancode_unicode", "is_keycode_unicode" }, // OS
+ { "is_selectable_when_hidden", "_is_selectable_when_hidden" }, // EditorNode3DGizmoPlugin
+ { "is_set_as_toplevel", "is_set_as_top_level" }, // CanvasItem
+ { "is_shortcut", "matches_event" }, // Shortcut
+ { "is_size_override_stretch_enabled", "is_size_2d_override_stretch_enabled" }, // SubViewport
+ { "is_sort_enabled", "is_y_sort_enabled" }, // Node2D
+ { "is_static_body", "is_able_to_sleep" }, // PhysicalBone3D - TODO - not sure
+ { "is_v_drag_enabled", "is_drag_vertical_enabled" }, // Camera2D
+ { "joint_create_cone_twist", "joint_make_cone_twist" }, // PhysicsServer3D
+ { "joint_create_generic_6dof", "joint_make_generic_6dof" }, // PhysicsServer3D
+ { "joint_create_hinge", "joint_make_hinge" }, // PhysicsServer3D
+ { "joint_create_pin", "joint_make_pin" }, // PhysicsServer3D
+ { "joint_create_slider", "joint_make_slider" }, // PhysicsServer3D
+ { "line_intersects_line_2d", "line_intersects_line" }, // Geometry2D
+ { "load_from_globals", "load_from_project_settings" }, // InputMap
+ { "make_convex_from_brothers", "make_convex_from_siblings" }, // CollisionShape3D
+ { "merge_polygons_2d", "merge_polygons" }, // Geometry2D
+ { "mesh_surface_get_format", "mesh_surface_get_format_attribute_stride" }, // RenderingServer
+ { "mesh_surface_update_region", "mesh_surface_update_attribute_region" }, // RenderingServer
+ { "move_to_bottom", "move_after" }, // Skeleton3D
+ { "move_to_top", "move_before" }, // Skeleton3D
+ { "multimesh_allocate", "multimesh_allocate_data" }, // RenderingServer
+ { "normalmap_to_xy", "normal_map_to_xy" }, // Image
+ { "offset_polygon_2d", "offset_polygon" }, // Geometry2D
+ { "offset_polyline_2d", "offset_polyline" }, // Geometry2D
+ { "percent_decode", "uri_decode" }, // String
+ { "percent_encode", "uri_encode" }, // String
+ { "pin_joint_create", "joint_make_pin" }, // PhysicsServer2D
+ { "popup_centered_minsize", "popup_centered_clamped" }, // Window
+ { "post_import", "_post_import" }, // EditorScenePostImport
+ { "print_stray_nodes", "print_orphan_nodes" }, // Node
+ { "property_list_changed_notify", "notify_property_list_changed" }, // Object
+ { "recognize", "_recognize" }, // ResourceFormatLoader
+ { "regen_normalmaps", "regen_normal_maps" }, // ArrayMesh
+ { "remove", "remove_at" }, // Array, broke Directory
+ { "remove_animation", "remove_animation_library" }, // AnimationPlayer
+ { "remove_color_override", "remove_theme_color_override" }, // Control
+ { "remove_constant_override", "remove_theme_constant_override" }, // Control
+ { "remove_font_override", "remove_theme_font_override" }, // Control
+ { "remove_scene_import_plugin", "remove_scene_format_importer_plugin" }, //EditorPlugin
+ { "remove_stylebox_override", "remove_theme_stylebox_override" }, // Control
+ { "rename_animation", "rename_animation_library" }, // AnimationPlayer
+ { "rename_dependencies", "_rename_dependencies" }, // ResourceFormatLoader
+ { "save_external_data", "_save_external_data" }, // EditorPlugin
+ { "segment_intersects_segment_2d", "segment_intersects_segment" }, // Geometry2D
+ { "set_adjustment_enable", "set_adjustment_enabled" }, // Environment
+ { "set_alt", "set_alt_pressed" }, // InputEventWithModifiers
+ { "set_anchor_and_margin", "set_anchor_and_offset" }, // Control
+ { "set_anchors_and_margins_preset", "set_anchors_and_offsets_preset" }, // Control
+ { "set_animation_process_mode", "set_process_callback" }, // AnimationPlayer
+ { "set_as_bulk_array", "set_buffer" }, // MultiMesh
+ { "set_as_normalmap", "set_as_normal_map" }, // NoiseTexture
+ { "set_as_toplevel", "set_as_top_level" }, // CanvasItem
+ { "set_audio_bus", "set_audio_bus_name" }, // Area3D
+ { "set_autowrap", "set_autowrap_mode" }, // Label broke AcceptDialog
+ { "set_cast_to", "set_target_position" }, // RayCast2D, RayCast3D
+ { "set_collision_layer_bit", "set_collision_layer_value" }, // CSGShape3D and a lot of others like GridMap
+ { "set_collision_mask_bit", "set_collision_mask_value" }, // CSGShape3D and a lot of others like GridMap
+ { "set_column_min_width", "set_column_custom_minimum_width" }, // Tree
+ { "set_command", "set_command_pressed" }, // InputEventWithModifiers
+ { "set_control", "set_ctrl_pressed" }, // InputEventWithModifiers
+ { "set_create_options", "_set_create_options" }, // EditorResourcePicker
+ { "set_cull_mask_bit", "set_cull_mask_value" }, // Camera3D
+ { "set_cursor_position", "set_caret_column" }, // LineEdit
+ { "set_d", "set_distance" }, // WorldMarginShape2D
+ { "set_doubleclick", "set_double_click" }, // InputEventMouseButton
+ { "set_enabled_focus_mode", "set_focus_mode" }, // BaseButton
+ { "set_endian_swap", "set_big_endian" }, // File
+ { "set_expand_to_text_length", "set_expand_to_text_length_enabled" }, // LineEdit
+ { "set_focus_neighbour", "set_focus_neighbor" }, // Control
+ { "set_frame_color", "set_color" }, // ColorRect
+ { "set_global_rate_scale", "set_playback_speed_scale" }, // AudioServer
+ { "set_gravity_distance_scale", "set_gravity_point_distance_scale" }, // Area2D
+ { "set_gravity_vector", "set_gravity_direction" }, // Area2D
+ { "set_h_drag_enabled", "set_drag_horizontal_enabled" }, // Camera2D
+ { "set_icon_align", "set_icon_alignment" }, // Button
+ { "set_interior_ambient", "set_ambient_color" }, // ReflectionProbe
+ { "set_interior_ambient_energy", "set_ambient_color_energy" }, // ReflectionProbe
+ { "set_is_initialized", "_is_initialized" }, // XRInterface
+ { "set_is_primary", "set_primary" }, // XRInterface
+ { "set_iterations_per_second", "set_physics_ticks_per_second" }, // Engine
+ { "set_layer_mask_bit", "set_layer_mask_value" }, // VisualInstance3D
+ { "set_margins_preset", "set_offsets_preset" }, // Control
+ { "set_max_atlas_size", "set_max_texture_size" }, // LightmapGI
+ { "set_metakey", "set_meta_pressed" }, // InputEventWithModifiers
+ { "set_mid_height", "set_height" }, // CapsuleMesh
+ { "set_network_master", "set_multiplayer_authority" }, // Node
+ { "set_network_peer", "set_multiplayer_peer" }, // Multiplayer API
+ { "set_physical_scancode", "set_physical_keycode" }, // InputEventKey
+ { "set_refuse_new_network_connections", "set_refuse_new_connections" }, // Multiplayer API
+ { "set_region", "set_region_enabled" }, // Sprite2D, Sprite broke AtlasTexture
+ { "set_region_filter_clip", "set_region_filter_clip_enabled" }, // Sprite2D
+ { "set_rotate", "set_rotates" }, // PathFollow2D
+ { "set_scancode", "set_keycode" }, // InputEventKey
+ { "set_shift", "set_shift_pressed" }, // InputEventWithModifiers
+ { "set_size_override", "set_size_2d_override" }, // SubViewport broke ImageTexture
+ { "set_size_override_stretch", "set_size_2d_override_stretch" }, // SubViewport
+ { "set_slips_on_slope", "set_slide_on_slope" }, // SeparationRayShape2D, SeparationRayShape3D
+ { "set_sort_enabled", "set_y_sort_enabled" }, // Node2D
+ { "set_space_override_mode", "set_gravity_space_override_mode" }, // Area2D
+ { "set_speed", "set_velocity" }, // InputEventMouseMotion
+ { "set_ssao_edge_sharpness", "set_ssao_sharpness" }, // Environment
+ { "set_surface_material", "set_surface_override_material" }, // MeshInstance3D broke ImporterMesh
+ { "set_tab_align", "set_tab_alignment" }, //TabContainer
+ { "set_tangent", "surface_set_tangent" }, // ImmediateGeometry broke SurfaceTool
+ { "set_text_align", "set_text_alignment" }, // Button
+ { "set_timer_process_mode", "set_timer_process_callback" }, // Timer
+ { "set_tonemap_auto_exposure", "set_tonemap_auto_exposure_enabled" }, // Environment
+ { "set_translation", "set_position" }, // Node3D - this broke GLTFNode which is used rarely
+ { "set_uv2", "surface_set_uv2" }, // ImmediateMesh broke Surffacetool
+ { "set_v_drag_enabled", "set_drag_vertical_enabled" }, // Camera2D
+ { "set_valign", "set_vertical_alignment" }, // Label
+ { "set_window_layout", "_set_window_layout" }, // EditorPlugin
+ { "set_zfar", "set_far" }, // Camera3D broke GLTFCamera
+ { "set_znear", "set_near" }, // Camera3D broke GLTFCamera
+ { "shortcut_match", "is_match" }, // InputEvent
+ { "skeleton_allocate", "skeleton_allocate_data" }, // RenderingServer
+ { "surface_update_region", "surface_update_attribute_region" }, // ArrayMesh
+ { "targeting_method", "tween_method" }, // Tween
+ { "targeting_property", "tween_property" }, // Tween
+ { "track_remove_key_at_position", "track_remove_key_at_time" }, // Animation
+ { "triangulate_delaunay_2d", "triangulate_delaunay" }, // Geometry2D
+ { "unbind_child_node_from_bone", "remove_bone_child" }, // Skeleton3D
+ { "unselect", "deselect" }, // ItemList
+ { "unselect_all", "deselect_all" }, // ItemList
+ { "update_configuration_warning", "update_configuration_warnings" }, // Node
+ { "update_gizmo", "update_gizmos" }, // Node3D
+ { "viewport_set_use_arvr", "viewport_set_use_xr" }, // RenderingServer
+ { "warp_mouse_position", "warp_mouse" }, // Input
+
+ // Builtin types
+ // { "empty", "is_empty" }, // Array - Used as custom rule // Be careful, this will be used everywhere
+ { "clamped", "clamp" }, // Vector2 // Be careful, this will be used everywhere
+ { "get_rotation_quat", "get_rotation_quaternion" }, // Basis
+ { "grow_margin", "grow_side" }, // Rect2
+ { "invert", "reverse" }, // Array - TODO check // Be careful, this will be used everywhere
+ { "is_abs_path", "is_absolute_path" }, // String
+ { "is_valid_integer", "is_valid_int" }, // String
+ { "linear_interpolate", "lerp" }, // Color
+ { "to_ascii", "to_ascii_buffer" }, // String
+ { "to_utf8", "to_utf8_buffer" }, // String
+ { "to_wchar", "to_utf32_buffer" }, // String // TODO - utf32 or utf16?
+
+ // Globals
+ { "rand_range", "randf_range" },
+ { "stepify", "snapped" },
+
+ { nullptr, nullptr },
+};
+
+// gdscript_function_renames clone with CamelCase
+static const char *csharp_function_renames[][2] = {
+ // { "_SetName", "GetTrackerName"}, // XRPositionalTracker - CameraFeed use this
+ // { "_UnhandledInput", "_UnhandledKeyInput"}, // BaseButton, ViewportContainer broke Node, FileDialog,SubViewportContainer
+ // { "CreateGizmo", "_CreateGizmo"}, // EditorNode3DGizmoPlugin - may be used
+ // { "GetDependencies", "_GetDependencies" }, // ResourceFormatLoader broke ResourceLoader
+ // { "GetExtents", "GetSize" }, // BoxShape, RectangleShape broke Decal, VoxelGI, GPUParticlesCollisionBox, GPUParticlesCollisionSDF, GPUParticlesCollisionHeightField, GPUParticlesAttractorBox, GPUParticlesAttractorVectorField, FogVolume
+ // { "GetHOffset", "GetDragHorizontalOffset"}, // Camera2D, broke PathFollow, Camera
+ // { "GetMode", "GetFileMode"}, // FileDialog broke Panel, Shader, CSGPolygon, Tilemap
+ // { "GetMotion", "GetTravel"}, // PhysicsTestMotionResult2D broke ParalaxLayer
+ // { "GetName", "GetTrackerName"}, // XRPositionalTracker broke OS, Node
+ // { "GetNetworkConnectedPeers", "GetPeers"}, // MultiplayerAPI broke SceneTree
+ // { "GetNetworkPeer", "HasMultiplayerPeer"}, // MultiplayerAPI broke SceneTree
+ // { "GetNetworkUniqueId", "GetUniqueId"}, // MultiplayerAPI broke SceneTree
+ // { "GetOffset", "GetPositionOffset" }, // GraphNode broke Gradient
+ // { "GetPeerPort", "GetPeer" }, // ENetMultiplayerPeer broke WebSocketServer
+ // { "GetProcessMode", "GetProcessCallback" }, // ClippedCamera3D broke Node, Sky
+ // { "GetRenderInfo", "GetRenderingInfo" }, // RenderingServer broke Viewport
+ // { "GetType", "GetTrackerType"}, // XRPositionalTracker broke GLTFAccessor, GLTFLight
+ // { "GetVOffset", "GetDragVerticalOffset"}, // Camera2D, broke PathFollow, Camera
+ // { "HasNetworkPeer", "HasMultiplayerPeer"}, // MultiplayerAPI broke SceneTree
+ // { "Instance", "Instantiate" }, // PackedScene, ClassDB - Broke FileSystemDock signal and also tscn files - [instance=ExtResource( 17 )] - this is implemented as custom rule
+ // { "IsListening", "IsBound"}, // PacketPeerUDP broke TCPServer, UDPServer
+ // { "IsRefusingNewNetworkConnections", "IsRefusingNewConnections"}, // MultiplayerAPI broke SceneTree
+ // { "IsValid", "HasValidEvent" }, // Shortcut broke e.g. Callable
+ // { "Listen", "Bound"}, // PacketPeerUDP broke TCPServer, UDPServer
+ // { "Load", "_Load"}, // ResourceFormatLoader broke ConfigFile, Image, StreamTexture2D
+ // { "MakeCurrent", "SetCurrent" }, // Camera2D broke Camera3D, Listener2D
+ // { "Process", "_Process" }, // AnimationNode - This word is commonly used
+ // { "Save", "_Save"}, // ResourceFormatLoader broke ConfigFile, Image, StreamTexture2D
+ // { "SetAutowrap", "SetAutowrapMode" }, // AcceptDialog broke Label - Cyclic Rename
+ // { "SetColor", "SurfaceSetColor"}, // ImmediateMesh broke Light2D, Theme, SurfaceTool
+ // { "SetEvent", "SetShortcut" }, // BaseButton - Cyclic Rename
+ // { "SetExtents", "SetSize"}, // BoxShape, RectangleShape broke ReflectionProbe
+ // { "SetFlag", "SetParticleFlag"}, // ParticlesMaterial broke Window, HingeJoint3D
+ // { "SetHOffset", "SetDragHorizontalOffset" }, // Camera2D broke Camera3D, PathFollow3D, PathFollow2D
+ // { "SetMargin", "SetOffset" }, // Control broke Shape3D, AtlasTexture
+ // { "SetMode", "SetModeFileMode" }, // FileDialog broke Panel, Shader, CSGPolygon, Tilemap
+ // { "SetNormal", "SurfaceSetNormal"}, // ImmediateGeometry broke SurfaceTool, WorldMarginShape2D
+ // { "SetProcessMode", "SetProcessCallback" }, // AnimationTree broke Node, Tween, Sky
+ // { "SetRefuseNewNetworkConnections", "SetRefuseNewConnections"}, // MultiplayerAPI broke SceneTree
+ // { "SetUv", "SurfaceSetUv" }, // ImmediateMesh broke Polygon2D
+ // { "SetVOffset", "SetDragVerticalOffset" }, // Camera2D broke Camera3D, PathFollow3D, PathFollow2D
+ // {"GetPoints","GetPointsId"},// Astar, broke Line2D, Convexpolygonshape
+ // {"GetVScroll","GetVScrollBar"},//ItemList, broke TextView
+ { "RenderingServer", "GetTabAlignment" }, // Tab
+ { "_AboutToShow", "_AboutToPopup" }, // ColorPickerButton
+ { "_GetConfigurationWarning", "_GetConfigurationWarnings" }, // Node
+ { "_SetCurrent", "SetCurrent" }, // Camera2D
+ { "_SetEditorDescription", "SetEditorDescription" }, // Node
+ { "_ToplevelRaiseSelf", "_TopLevelRaiseSelf" }, // CanvasItem
+ { "_UpdateWrapAt", "_UpdateWrapAtColumn" }, // TextEdit
+ { "AddAnimation", "AddAnimationLibrary" }, // AnimationPlayer
+ { "AddCancel", "AddCancelButton" }, // AcceptDialog
+ { "AddCentralForce", "AddConstantCentralForce" }, //RigidDynamicBody2D
+ { "AddChildBelowNode", "AddSibling" }, // Node
+ { "AddColorOverride", "AddThemeColorOverride" }, // Control
+ { "AddConstantOverride", "AddThemeConstantOverride" }, // Control
+ { "AddFontOverride", "AddThemeFontOverride" }, // Control
+ { "AddForce", "AddConstantForce" }, //RigidDynamicBody2D
+ { "AddIconOverride", "AddThemeIconOverride" }, // Control
+ { "AddSceneImportPlugin", "AddSceneFormatImporterPlugin" }, //EditorPlugin
+ { "AddStyleboxOverride", "AddThemeStyleboxOverride" }, // Control
+ { "AddTorque", "AddConstantTorque" }, //RigidDynamicBody2D
+ { "BindChildNodeToBone", "SetBoneChildren" }, // Skeleton3D
+ { "BumpmapToNormalmap", "BumpMapToNormalMap" }, // Image
+ { "CanBeHidden", "_CanBeHidden" }, // EditorNode3DGizmoPlugin
+ { "CanDropDataFw", "_CanDropDataFw" }, // ScriptEditor
+ { "CanGenerateSmallPreview", "_CanGenerateSmallPreview" }, // EditorResourcePreviewGenerator
+ { "CanInstance", "CanInstantiate" }, // PackedScene, Script
+ { "CanvasLightSetScale", "CanvasLightSetTextureScale" }, // RenderingServer
+ { "CenterViewportToCursor", "CenterViewportToCaret" }, // TextEdit
+ { "ClipPolygons2d", "ClipPolygons" }, // Geometry2D
+ { "ClipPolylineWithPolygon2d", "ClipPolylineWithPolygon" }, //Geometry2D
+ { "CommitHandle", "_CommitHandle" }, // EditorNode3DGizmo
+ { "ConvexHull2d", "ConvexHull" }, // Geometry2D
+ { "CursorGetBlinkSpeed", "GetCaretBlinkSpeed" }, // TextEdit
+ { "CursorGetColumn", "GetCaretColumn" }, // TextEdit
+ { "CursorGetLine", "GetCaretLine" }, // TextEdit
+ { "CursorSetBlinkEnabled", "SetCaretBlinkEnabled" }, // TextEdit
+ { "CursorSetBlinkSpeed", "SetCaretBlinkSpeed" }, // TextEdit
+ { "CursorSetColumn", "SetCaretColumn" }, // TextEdit
+ { "CursorSetLine", "SetCaretLine" }, // TextEdit
+ { "DampedSpringJointCreate", "JointMakeDampedSpring" }, // PhysicsServer2D
+ { "DampedStringJointGetParam", "DampedSpringJointGetParam" }, // PhysicsServer2D
+ { "DampedStringJointSetParam", "DampedSpringJointSetParam" }, // PhysicsServer2D
+ { "DeleteCharAtCursor", "DeleteCharAtCaret" }, // LineEdit
+ { "DeselectItems", "DeselectAll" }, // FileDialog
+ { "DropDataFw", "_DropDataFw" }, // ScriptEditor
+ { "ExcludePolygons2d", "ExcludePolygons" }, // Geometry2D
+ { "FindScancodeFromString", "FindKeycodeFromString" }, // OS
+ { "ForwardCanvasDrawOverViewport", "_ForwardCanvasDrawOverViewport" }, // EditorPlugin
+ { "ForwardCanvasForceDrawOverViewport", "_ForwardCanvasForceDrawOverViewport" }, // EditorPlugin
+ { "ForwardCanvasGuiInput", "_ForwardCanvasGuiInput" }, // EditorPlugin
+ { "ForwardSpatialDrawOverViewport", "_Forward3dDrawOverViewport" }, // EditorPlugin
+ { "ForwardSpatialForceDrawOverViewport", "_Forward3dForceDrawOverViewport" }, // EditorPlugin
+ { "ForwardSpatialGuiInput", "_Forward3dGuiInput" }, // EditorPlugin
+ { "GenerateFromPath", "_GenerateFromPath" }, // EditorResourcePreviewGenerator
+ { "GenerateSmallPreviewAutomatically", "_GenerateSmallPreviewAutomatically" }, // EditorResourcePreviewGenerator
+ { "GetActionList", "ActionGetEvents" }, // InputMap
+ { "GetAlt", "IsAltPressed" }, // InputEventWithModifiers
+ { "GetAnimationProcessMode", "GetProcessCallback" }, // AnimationPlayer
+ { "GetAppliedForce", "GetConstantForce" }, //RigidDynamicBody2D
+ { "GetAppliedTorque", "GetConstantTorque" }, //RigidDynamicBody2D
+ { "GetAudioBus", "GetAudioBusName" }, // Area3D
+ { "GetBoundChildNodesToBone", "GetBoneChildren" }, // Skeleton3D
+ { "GetCamera", "GetCamera3d" }, // Viewport -> this is also convertable to getCamera2d, broke GLTFNode
+ { "GetCancel", "GetCancelButton" }, // ConfirmationDialog
+ { "GetCaption", "_GetCaption" }, // AnimationNode
+ { "GetCastTo", "GetTargetPosition" }, // RayCast2D, RayCast3D
+ { "GetChildByName", "_GetChildByName" }, // AnimationNode
+ { "GetChildNodes", "_GetChildNodes" }, // AnimationNode
+ { "GetClosestPointToSegment2d", "GetClosestPointToSegment" }, // Geometry2D
+ { "GetClosestPointToSegmentUncapped2d", "GetClosestPointToSegmentUncapped" }, // Geometry2D
+ { "GetClosestPointsBetweenSegments2d", "GetClosestPointToSegment" }, // Geometry2D
+ { "GetCollisionLayerBit", "GetCollisionLayerValue" }, // CSGShape3D and a lot of others like GridMap
+ { "GetCollisionMaskBit", "GetCollisionMaskValue" }, // CSGShape3D and a lot of others like GridMap
+ { "GetColorTypes", "GetColorTypeList" }, // Theme
+ { "GetCommand", "IsCommandPressed" }, // InputEventWithModifiers
+ { "GetConstantTypes", "GetConstantTypeList" }, // Theme
+ { "GetControl", "IsCtrlPressed" }, // InputEventWithModifiers
+ { "GetCullMaskBit", "GetCullMaskValue" }, // Camera3D
+ { "GetCursorPosition", "GetCaretColumn" }, // LineEdit
+ { "GetD", "GetDistance" }, // LineShape2D
+ { "GetDragDataFw", "_GetDragDataFw" }, // ScriptEditor
+ { "GetEditorViewport", "GetViewport" }, // EditorPlugin
+ { "GetEnabledFocusMode", "GetFocusMode" }, // BaseButton
+ { "GetEndianSwap", "IsBigEndian" }, // File
+ { "GetErrorString", "GetErrorMessage" }, // JSON
+ { "GetFocusNeighbour", "GetFocusNeighbor" }, // Control
+ { "GetFontTypes", "GetFontTypeList" }, // Theme
+ { "GetFrameColor", "GetColor" }, // ColorRect
+ { "GetGlobalRateScale", "GetPlaybackSpeedScale" }, // AudioServer
+ { "GetGravityDistanceScale", "GetGravityPointDistanceScale" }, //Area2D
+ { "GetGravityVector", "GetGravityDirection" }, //Area2D
+ { "GetHScrollbar", "GetHScrollBar" }, //ScrollContainer
+ { "GetHand", "GetTrackerHand" }, // XRPositionalTracker
+ { "GetHandleName", "_GetHandleName" }, // EditorNode3DGizmo
+ { "GetHandleValue", "_GetHandleValue" }, // EditorNode3DGizmo
+ { "GetIconAlign", "GetIconAlignment" }, // Button
+ { "GetIconTypes", "GetIconTypeList" }, // Theme
+ { "GetIdleFrames", "GetProcessFrames" }, // Engine
+ { "GetImportOptions", "_GetImportOptions" }, // EditorImportPlugin
+ { "GetImportOrder", "_GetImportOrder" }, // EditorImportPlugin
+ { "GetImporterName", "_GetImporterName" }, // EditorImportPlugin
+ { "GetInteriorAmbient", "GetAmbientColor" }, // ReflectionProbe
+ { "GetInteriorAmbientEnergy", "GetAmbientColorEnergy" }, // ReflectionProbe
+ { "GetIterationsPerSecond", "GetPhysicsTicksPerSecond" }, // Engine
+ { "GetLastMouseSpeed", "GetLastMouseVelocity" }, // Input
+ { "GetLayerMaskBit", "GetLayerMaskValue" }, // VisualInstance3D
+ { "GetLen", "GetLength" }, // File
+ { "GetMaxAtlasSize", "GetMaxTextureSize" }, // LightmapGI
+ { "GetMetakey", "IsMetaPressed" }, // InputEventWithModifiers
+ { "GetMidHeight", "GetHeight" }, // CapsuleMesh
+ { "GetMotionRemainder", "GetRemainder" }, // PhysicsTestMotionResult2D
+ { "GetNetworkConnectedPeers", "GetPeers" }, // Multiplayer API
+ { "GetNetworkMaster", "GetMultiplayerAuthority" }, // Node
+ { "GetNetworkPeer", "GetMultiplayerPeer" }, // Multiplayer API
+ { "GetNetworkUniqueId", "GetUniqueId" }, // Multiplayer API
+ { "GetOk", "GetOkButton" }, // AcceptDialog
+ { "GetOptionVisibility", "_GetOptionVisibility" }, // EditorImportPlugin
+ { "GetParameterDefaultValue", "_GetParameterDefaultValue" }, // AnimationNode
+ { "GetParameterList", "_GetParameterList" }, // AnimationNode
+ { "GetParentSpatial", "GetParentNode3d" }, // Node3D
+ { "GetPhysicalScancode", "GetPhysicalKeycode" }, // InputEventKey
+ { "GetPhysicalScancodeWithModifiers", "GetPhysicalKeycodeWithModifiers" }, // InputEventKey
+ { "GetPluginIcon", "_GetPluginIcon" }, // EditorPlugin
+ { "GetPluginName", "_GetPluginName" }, // EditorPlugin
+ { "GetPresetCount", "_GetPresetCount" }, // EditorImportPlugin
+ { "GetPresetName", "_GetPresetName" }, // EditorImportPlugin
+ { "GetRecognizedExtensions", "_GetRecognizedExtensions" }, // ResourceFormatLoader, EditorImportPlugin broke ResourceSaver
+ { "GetRenderInfo", "GetRenderingInfo" }, // RenderingServer
+ { "GetRenderTargetsize", "GetRenderTargetSize" }, // XRInterface
+ { "GetResourceType", "_GetResourceType" }, // ResourceFormatLoader
+ { "GetResult", "GetData" }, //JSON
+ { "GetRpcSenderId", "GetRemoteSenderId" }, // Multiplayer API
+ { "GetSaveExtension", "_GetSaveExtension" }, // EditorImportPlugin
+ { "GetScancode", "GetKeycode" }, // InputEventKey
+ { "GetScancodeString", "GetKeycodeString" }, // OS
+ { "GetScancodeWithModifiers", "GetKeycodeWithModifiers" }, // InputEventKey
+ { "GetShift", "IsShiftPressed" }, // InputEventWithModifiers
+ { "GetSizeOverride", "GetSize2dOverride" }, // SubViewport
+ { "GetSlipsOnSlope", "GetSlideOnSlope" }, // SeparationRayShape2D, SeparationRayShape3D
+ { "GetSpaceOverrideMode", "GetGravitySpaceOverrideMode" }, // Area2D
+ { "GetSpeed", "GetVelocity" }, // InputEventMouseMotion
+ { "GetStyleboxTypes", "GetStyleboxTypeList" }, // Theme
+ { "GetSurfaceMaterial", "GetSurfaceOverrideMaterial" }, // MeshInstance3D broke ImporterMesh
+ { "GetSurfaceMaterialCount", "GetSurfaceOverrideMaterialCount" }, // MeshInstance3D
+ { "GetTabDisabled", "IsTabDisabled" }, // Tab
+ { "GetTabHidden", "IsTabHidden" }, // Tab
+ { "GetTextAlign", "GetTextAlignment" }, // Button
+ { "GetThemeItemTypes", "GetThemeItemTypeList" }, // Theme
+ { "GetTimerProcessMode", "GetTimerProcessCallback" }, // Timer
+ { "GetTranslation", "GetPosition" }, // Node3D broke GLTFNode which is used rarely
+ { "GetUseInBakedLight", "IsBakingNavigation" }, // GridMap
+ { "GetUsedCellsById", "GetUsedCells" }, // TileMap
+ { "GetVScrollbar", "GetVScrollBar" }, //ScrollContainer
+ { "GetVisibleName", "_GetVisibleName" }, // EditorImportPlugin
+ { "GetWindowLayout", "_GetWindowLayout" }, // EditorPlugin
+ { "GetWordUnderCursor", "GetWordUnderCaret" }, // TextEdit
+ { "GetWorld", "GetWorld3d" }, // Viewport, Spatial
+ { "GetZfar", "GetFar" }, // Camera3D broke GLTFCamera
+ { "GetZnear", "GetNear" }, // Camera3D broke GLTFCamera
+ { "GrooveJointCreate", "JointMakeGroove" }, // PhysicsServer2D
+ { "HandleMenuSelected", "_HandleMenuSelected" }, // EditorResourcePicker
+ { "HandlesType", "_HandlesType" }, // ResourceFormatLoader
+ { "HasColor", "HasThemeColor" }, // Control broke Theme
+ { "HasColorOverride", "HasThemeColorOverride" }, // Control broke Theme
+ { "HasConstant", "HasThemeConstant" }, // Control
+ { "HasConstantOverride", "HasThemeConstantOverride" }, // Control
+ { "HasFilter", "_HasFilter" }, // AnimationNode
+ { "HasFont", "HasThemeFont" }, // Control broke Theme
+ { "HasFontOverride", "HasThemeFontOverride" }, // Control
+ { "HasIcon", "HasThemeIcon" }, // Control broke Theme
+ { "HasIconOverride", "HasThemeIconOverride" }, // Control
+ { "HasMainScreen", "_HasMainScreen" }, // EditorPlugin
+ { "HasNetworkPeer", "HasMultiplayerPeer" }, // Multiplayer API
+ { "HasStylebox", "HasThemeStylebox" }, // Control broke Theme
+ { "HasStyleboxOverride", "HasThemeStyleboxOverride" }, // Control
+ { "HttpEscape", "UriEncode" }, // String
+ { "HttpUnescape", "UriDecode" }, // String
+ { "ImportAnimationFromOtherImporter", "_ImportAnimation" }, //EditorSceneFormatImporter
+ { "ImportSceneFromOtherImporter", "_ImportScene" }, //EditorSceneFormatImporter
+ { "InstanceSetSurfaceMaterial", "InstanceSetSurfaceOverrideMaterial" }, // RenderingServer
+ { "IntersectPolygons2d", "IntersectPolygons" }, // Geometry2D
+ { "IntersectPolylineWithPolygon2d", "IntersectPolylineWithPolygon" }, // Geometry2D
+ { "IsAParentOf", "IsAncestorOf" }, // Node
+ { "IsCommitingAction", "IsCommittingAction" }, // UndoRedo
+ { "IsDoubleclick", "IsDoubleClick" }, // InputEventMouseButton
+ { "IsHDragEnabled", "IsDragHorizontalEnabled" }, // Camera2D
+ { "IsHandleHighlighted", "_IsHandleHighlighted" }, // EditorNode3DGizmo, EditorNode3DGizmoPlugin
+ { "IsNetworkMaster", "IsMultiplayerAuthority" }, // Node
+ { "IsNetworkServer", "IsServer" }, // Multiplayer API
+ { "IsNormalmap", "IsNormalMap" }, // NoiseTexture
+ { "IsRefusingNewNetworkConnections", "IsRefusingNewConnections" }, // Multiplayer API
+ { "IsRegion", "IsRegionEnabled" }, // Sprite2D
+ { "IsScancodeUnicode", "IsKeycodeUnicode" }, // OS
+ { "IsSelectableWhenHidden", "_IsSelectableWhenHidden" }, // EditorNode3DGizmoPlugin
+ { "IsSetAsToplevel", "IsSetAsTopLevel" }, // CanvasItem
+ { "IsShortcut", "MatchesEvent" }, // Shortcut
+ { "IsSizeOverrideStretchEnabled", "IsSize2dOverrideStretchEnabled" }, // SubViewport
+ { "IsSortEnabled", "IsYSortEnabled" }, // Node2D
+ { "IsStaticBody", "IsAbleToSleep" }, // PhysicalBone3D - TODO - not sure
+ { "IsVDragEnabled", "IsDragVerticalEnabled" }, // Camera2D
+ { "JointCreateConeTwist", "JointMakeConeTwist" }, // PhysicsServer3D
+ { "JointCreateGeneric6dof", "JointMakeGeneric6dof" }, // PhysicsServer3D
+ { "JointCreateHinge", "JointMakeHinge" }, // PhysicsServer3D
+ { "JointCreatePin", "JointMakePin" }, // PhysicsServer3D
+ { "JointCreateSlider", "JointMakeSlider" }, // PhysicsServer3D
+ { "LineIntersectsLine2d", "LineIntersectsLine" }, // Geometry2D
+ { "LoadFromGlobals", "LoadFromProjectSettings" }, // InputMap
+ { "MakeConvexFromBrothers", "MakeConvexFromSiblings" }, // CollisionShape3D
+ { "MergePolygons2d", "MergePolygons" }, // Geometry2D
+ { "MeshSurfaceGetFormat", "MeshSurfaceGetFormatAttributeStride" }, // RenderingServer
+ { "MeshSurfaceUpdateRegion", "MeshSurfaceUpdateAttributeRegion" }, // RenderingServer
+ { "MoveToBottom", "MoveAfter" }, // Skeleton3D
+ { "MoveToTop", "MoveBefore" }, // Skeleton3D
+ { "MultimeshAllocate", "MultimeshAllocateData" }, // RenderingServer
+ { "NormalmapToXy", "NormalMapToXy" }, // Image
+ { "OffsetPolygon2d", "OffsetPolygon" }, // Geometry2D
+ { "OffsetPolyline2d", "OffsetPolyline" }, // Geometry2D
+ { "PercentDecode", "UriDecode" }, // String
+ { "PercentEncode", "UriEncode" }, // String
+ { "PinJointCreate", "JointMakePin" }, // PhysicsServer2D
+ { "PopupCenteredMinsize", "PopupCenteredClamped" }, // Window
+ { "PostImport", "_PostImport" }, // EditorScenePostImport
+ { "PrintStrayNodes", "PrintOrphanNodes" }, // Node
+ { "PropertyListChangedNotify", "NotifyPropertyListChanged" }, // Object
+ { "Recognize", "_Recognize" }, // ResourceFormatLoader
+ { "RegenNormalmaps", "RegenNormalMaps" }, // ArrayMesh
+ { "Remove", "RemoveAt" }, // Array, broke Directory
+ { "RemoveAnimation", "RemoveAnimationLibrary" }, // AnimationPlayer
+ { "RemoveColorOverride", "RemoveThemeColorOverride" }, // Control
+ { "RemoveConstantOverride", "RemoveThemeConstantOverride" }, // Control
+ { "RemoveFontOverride", "RemoveThemeFontOverride" }, // Control
+ { "RemoveSceneImportPlugin", "RemoveSceneFormatImporterPlugin" }, //EditorPlugin
+ { "RemoveStyleboxOverride", "RemoveThemeStyleboxOverride" }, // Control
+ { "RenameAnimation", "RenameAnimationLibrary" }, // AnimationPlayer
+ { "RenameDependencies", "_RenameDependencies" }, // ResourceFormatLoader
+ { "SaveExternalData", "_SaveExternalData" }, // EditorPlugin
+ { "SegmentIntersectsSegment2d", "SegmentIntersectsSegment" }, // Geometry2D
+ { "SetAdjustmentEnable", "SetAdjustmentEnabled" }, // Environment
+ { "SetAlt", "SetAltPressed" }, // InputEventWithModifiers
+ { "SetAnchorAndMargin", "SetAnchorAndOffset" }, // Control
+ { "SetAnchorsAndMarginsPreset", "SetAnchorsAndOffsetsPreset" }, // Control
+ { "SetAnimationProcessMode", "SetProcessCallback" }, // AnimationPlayer
+ { "SetAsBulkArray", "SetBuffer" }, // MultiMesh
+ { "SetAsNormalmap", "SetAsNormalMap" }, // NoiseTexture
+ { "SetAsToplevel", "SetAsTopLevel" }, // CanvasItem
+ { "SetAudioBus", "SetAudioBusName" }, // Area3D
+ { "SetAutowrap", "SetAutowrapMode" }, // Label broke AcceptDialog
+ { "SetCastTo", "SetTargetPosition" }, // RayCast2D, RayCast3D
+ { "SetCollisionLayerBit", "SetCollisionLayerValue" }, // CSGShape3D and a lot of others like GridMap
+ { "SetCollisionMaskBit", "SetCollisionMaskValue" }, // CSGShape3D and a lot of others like GridMap
+ { "SetColumnMinWidth", "SetColumnCustomMinimumWidth" }, // Tree
+ { "SetCommand", "SetCommandPressed" }, // InputEventWithModifiers
+ { "SetControl", "SetCtrlPressed" }, // InputEventWithModifiers
+ { "SetCreateOptions", "_SetCreateOptions" }, // EditorResourcePicker
+ { "SetCullMaskBit", "SetCullMaskValue" }, // Camera3D
+ { "SetCursorPosition", "SetCaretColumn" }, // LineEdit
+ { "SetD", "SetDistance" }, // WorldMarginShape2D
+ { "SetDoubleclick", "SetDoubleClick" }, // InputEventMouseButton
+ { "SetEnabledFocusMode", "SetFocusMode" }, // BaseButton
+ { "SetEndianSwap", "SetBigEndian" }, // File
+ { "SetExpandToTextLength", "SetExpandToTextLengthEnabled" }, // LineEdit
+ { "SetFocusNeighbour", "SetFocusNeighbor" }, // Control
+ { "SetFrameColor", "SetColor" }, // ColorRect
+ { "SetGlobalRateScale", "SetPlaybackSpeedScale" }, // AudioServer
+ { "SetGravityDistanceScale", "SetGravityPointDistanceScale" }, // Area2D
+ { "SetGravityVector", "SetGravityDirection" }, // Area2D
+ { "SetHDragEnabled", "SetDragHorizontalEnabled" }, // Camera2D
+ { "SetIconAlign", "SetIconAlignment" }, // Button
+ { "SetInteriorAmbient", "SetAmbientColor" }, // ReflectionProbe
+ { "SetInteriorAmbientEnergy", "SetAmbientColorEnergy" }, // ReflectionProbe
+ { "SetIsInitialized", "_IsInitialized" }, // XRInterface
+ { "SetIsPrimary", "SetPrimary" }, // XRInterface
+ { "SetIterationsPerSecond", "SetPhysicsTicksPerSecond" }, // Engine
+ { "SetLayerMaskBit", "SetLayerMaskValue" }, // VisualInstance3D
+ { "SetMarginsPreset", "SetOffsetsPreset" }, // Control
+ { "SetMaxAtlasSize", "SetMaxTextureSize" }, // LightmapGI
+ { "SetMetakey", "SetMetaPressed" }, // InputEventWithModifiers
+ { "SetMidHeight", "SetHeight" }, // CapsuleMesh
+ { "SetNetworkMaster", "SetMultiplayerAuthority" }, // Node
+ { "SetNetworkPeer", "SetMultiplayerPeer" }, // Multiplayer API
+ { "SetPhysicalScancode", "SetPhysicalKeycode" }, // InputEventKey
+ { "SetRefuseNewNetworkConnections", "SetRefuseNewConnections" }, // Multiplayer API
+ { "SetRegion", "SetRegionEnabled" }, // Sprite2D, Sprite broke AtlasTexture
+ { "SetRegionFilterClip", "SetRegionFilterClipEnabled" }, // Sprite2D
+ { "SetRotate", "SetRotates" }, // PathFollow2D
+ { "SetScancode", "SetKeycode" }, // InputEventKey
+ { "SetShift", "SetShiftPressed" }, // InputEventWithModifiers
+ { "SetSizeOverride", "SetSize2dOverride" }, // SubViewport broke ImageTexture
+ { "SetSizeOverrideStretch", "SetSize2dOverrideStretch" }, // SubViewport
+ { "SetSlipsOnSlope", "SetSlideOnSlope" }, // SeparationRayShape2D, SeparationRayShape3D
+ { "SetSortEnabled", "SetYSortEnabled" }, // Node2D
+ { "SetSpaceOverrideMode", "SetGravitySpaceOverrideMode" }, // Area2D
+ { "SetSpeed", "SetVelocity" }, // InputEventMouseMotion
+ { "SetSsaoEdgeSharpness", "SetSsaoSharpness" }, // Environment
+ { "SetSurfaceMaterial", "SetSurfaceOverrideMaterial" }, // MeshInstance3D broke ImporterMesh
+ { "SetTabAlign", "SetTabAlignment" }, //TabContainer
+ { "SetTangent", "SurfaceSetTangent" }, // ImmediateGeometry broke SurfaceTool
+ { "SetTextAlign", "SetTextAlignment" }, // Button
+ { "SetTimerProcessMode", "SetTimerProcessCallback" }, // Timer
+ { "SetTonemapAutoExposure", "SetTonemapAutoExposureEnabled" }, // Environment
+ { "SetTranslation", "SetPosition" }, // Node3D - this broke GLTFNode which is used rarely
+ { "SetUv2", "SurfaceSetUv2" }, // ImmediateMesh broke Surffacetool
+ { "SetVDragEnabled", "SetDragVerticalEnabled" }, // Camera2D
+ { "SetValign", "SetVerticalAlignment" }, // Label
+ { "SetWindowLayout", "_SetWindowLayout" }, // EditorPlugin
+ { "SetZfar", "SetFar" }, // Camera3D broke GLTFCamera
+ { "SetZnear", "SetNear" }, // Camera3D broke GLTFCamera
+ { "ShortcutMatch", "IsMatch" }, // InputEvent
+ { "SkeletonAllocate", "SkeletonAllocateData" }, // RenderingServer
+ { "SurfaceUpdateRegion", "SurfaceUpdateAttributeRegion" }, // ArrayMesh
+ { "TargetingMethod", "TweenMethod" }, // Tween
+ { "TargetingProperty", "TweenProperty" }, // Tween
+ { "TrackRemoveKeyAtPosition", "TrackRemoveKeyAtTime" }, // Animation
+ { "TriangulateDelaunay2d", "TriangulateDelaunay" }, // Geometry2D
+ { "UnbindChildNodeFromBone", "RemoveBoneChild" }, // Skeleton3D
+ { "Unselect", "Deselect" }, // ItemList
+ { "UnselectAll", "DeselectAll" }, // ItemList
+ { "UpdateConfigurationWarning", "UpdateConfigurationWarnings" }, // Node
+ { "UpdateGizmo", "UpdateGizmos" }, // Node3D
+ { "ViewportSetUseArvr", "ViewportSetUseXr" }, // RenderingServer
+ { "WarpMousePosition", "WarpMouse" }, // Input
+
+ // Builtin types
+ // { "Empty", "IsEmpty" }, // Array - Used as custom rule // Be careful, this will be used everywhere
+ { "Clamped", "Clamp" }, // Vector2 // Be careful, this will be used everywhere
+ { "GetRotationQuat", "GetRotationQuaternion" }, // Basis
+ { "GrowMargin", "GrowSide" }, // Rect2
+ { "Invert", "Reverse" }, // Array - TODO check // Be careful, this will be used everywhere
+ { "IsAbsPath", "IsAbsolutePath" }, // String
+ { "IsValidInteger", "IsValidInt" }, // String
+ { "LinearInterpolate", "Lerp" }, // Color
+ { "ToAscii", "ToAsciiBuffer" }, // String
+ { "ToUtf8", "ToUtf8Buffer" }, // String
+ { "ToWchar", "ToUtf32Buffer" }, // String // TODO - utf32 or utf16?
+
+ // Globals
+ { "RandRange", "RandfRange" },
+ { "Stepify", "Snapped" },
+
+ { nullptr, nullptr },
+};
+
+// Some needs to be disabled, because users can use this names as variables
+static const char *gdscript_properties_renames[][2] = {
+ // // { "d", "distance" }, //WorldMarginShape2D - TODO, looks that polish letters ą ę are treaten as space, not as letter, so `będą` are renamed to `będistanceą`
+ // // {"alt","alt_pressed"}, // This may broke a lot of comments and user variables
+ // // {"command","command_pressed"},// This may broke a lot of comments and user variables
+ // // {"control","ctrl_pressed"},// This may broke a lot of comments and user variables
+ // // {"extends","size"}, // BoxShape3D, LightmapGI broke ReflectionProbe
+ // // {"meta","meta_pressed"},// This may broke a lot of comments and user variables
+ // // {"pause_mode","process_mode"}, // Node - Cyclic rename, look for others
+ // // {"rotate","rotates"}, // PathFollow2D - probably function exists with same name
+ // // {"shift","shift_pressed"},// This may broke a lot of comments and user variables
+ // { "autowrap", "autowrap_mode" }, // Label
+ // { "cast_to", "target_position" }, // RayCast2D, RayCast3D
+ // { "doubleclick", "double_click" }, // InputEventMouseButton
+ // { "group", "button_group" }, // BaseButton
+ // { "process_mode", "process_callback" }, // AnimationTree, Camera2D
+ // { "scancode", "keycode" }, // InputEventKey
+ // { "toplevel", "top_level" }, // Node
+ // { "window_title", "title" }, // Window
+ // { "wrap_enabled", "wrap_mode" }, // TextEdit
+ // { "zfar", "far" }, // Camera3D
+ // { "znear", "near" }, // Camera3D
+ { "as_normalmap", "as_normal_map" }, // NoiseTexture
+ { "bbcode_text", "text" }, // RichTextLabel
+ { "caret_moving_by_right_click", "caret_move_on_right_click" }, // TextEdit
+ { "caret_position", "caret_column" }, // LineEdit
+ { "check_vadjust", "check_v_adjust" }, // Theme
+ { "close_h_ofs", "close_h_offset" }, // Theme
+ { "close_v_ofs", "close_v_offset" }, // Theme
+ { "commentfocus", "comment_focus" }, // Theme
+ { "drag_margin_bottom", "drag_bottom_margin" }, // Camera2D
+ { "drag_margin_h_enabled", "drag_horizontal_enabled" }, // Camera2D
+ { "drag_margin_left", "drag_left_margin" }, // Camera2D
+ { "drag_margin_right", "drag_right_margin" }, // Camera2D
+ { "drag_margin_top", "drag_top_margin" }, // Camera2D
+ { "drag_margin_v_enabled", "drag_vertical_enabled" }, // Camera2D
+ { "enabled_focus_mode", "focus_mode" }, // BaseButton - Removed
+ { "extra_spacing_bottom", "spacing_bottom" }, // Font
+ { "extra_spacing_top", "spacing_top" }, // Font
+ { "focus_neighbour_bottom", "focus_neighbor_bottom" }, // Control
+ { "focus_neighbour_left", "focus_neighbor_left" }, // Control
+ { "focus_neighbour_right", "focus_neighbor_right" }, // Control
+ { "focus_neighbour_top", "focus_neighbor_top" }, // Control
+ { "global_rate_scale", "playback_speed_scale" }, // AudioServer
+ { "gravity_distance_scale", "gravity_point_distance_scale" }, // Area2D
+ { "gravity_vec", "gravity_direction" }, // Area2D
+ { "hseparation", "h_separation" }, // Theme
+ { "iterations_per_second", "physics_ticks_per_second" }, // Engine
+ { "margin_bottom", "offset_bottom" }, // Control broke NinePatchRect, StyleBox
+ { "margin_left", "offset_left" }, // Control broke NinePatchRect, StyleBox
+ { "margin_right", "offset_right" }, // Control broke NinePatchRect, StyleBox
+ { "margin_top", "offset_top" }, // Control broke NinePatchRect, StyleBox
+ { "mid_height", "height" }, // CapsuleMesh
+ { "offset_h", "drag_horizontal_offset" }, // Camera2D
+ { "offset_v", "drag_vertical_offset" }, // Camera2D
+ { "ofs", "offset" }, // Theme
+ { "out_of_range_mode", "max_polyphony" }, // AudioStreamPlayer3D
+ { "pause_mode", "process_mode" }, // Node
+ { "physical_scancode", "physical_keycode" }, // InputEventKey
+ { "popup_exclusive", "exclusive" }, // Window
+ { "refuse_new_network_connections", "refuse_new_connections" }, // MultiplayerAPI
+ { "region_filter_clip", "region_filter_clip_enabled" }, // Sprite2D
+ { "selectedframe", "selected_frame" }, // Theme
+ { "size_override_stretch", "size_2d_override_stretch" }, // SubViewport
+ { "slips_on_slope", "slide_on_slope" }, // SeparationRayShape2D
+ { "ss_reflections_depth_tolerance", "ssr_depth_tolerance" }, // Environment
+ { "ss_reflections_enabled", "ssr_enabled" }, // Environment
+ { "ss_reflections_fade_in", "ssr_fade_in" }, // Environment
+ { "ss_reflections_fade_out", "ssr_fade_out" }, // Environment
+ { "ss_reflections_max_steps", "ssr_max_steps" }, // Environment
+ { "state_machine_selectedframe", "state_machine_selected_frame" }, // Theme
+ { "syntax_highlighting", "syntax_highlighter" }, // TextEdit
+ { "tab_align", "tab_alignment" }, // TabContainer
+ { "table_hseparation", "table_h_separation" }, // Theme
+ { "table_vseparation", "table_v_separation" }, // Theme
+ { "translation", "position" }, // Node3D - broke GLTFNode
+ { "vseparation", "v_separation" }, // Theme
+
+ { nullptr, nullptr },
+};
+
+// Some needs to be disabled, because users can use this names as variables
+static const char *csharp_properties_renames[][2] = {
+ // // { "D", "Distance" }, //WorldMarginShape2D - TODO, looks that polish letters ą ę are treaten as space, not as letter, so `będą` are renamed to `będistanceą`
+ // // {"Alt","AltPressed"}, // This may broke a lot of comments and user variables
+ // // {"Command","CommandPressed"},// This may broke a lot of comments and user variables
+ // // {"Control","CtrlPressed"},// This may broke a lot of comments and user variables
+ // // {"Extends","Size"}, // BoxShape3D, LightmapGI broke ReflectionProbe
+ // // {"Meta","MetaPressed"},// This may broke a lot of comments and user variables
+ // // {"PauseMode","ProcessMode"}, // Node - Cyclic rename, look for others
+ // // {"Rotate","Rotates"}, // PathFollow2D - probably function exists with same name
+ // // {"Shift","ShiftPressed"},// This may broke a lot of comments and user variables
+ // { "Autowrap", "AutowrapMode" }, // Label
+ // { "CastTo", "TargetPosition" }, // RayCast2D, RayCast3D
+ // { "Doubleclick", "DoubleClick" }, // InputEventMouseButton
+ // { "Group", "ButtonGroup" }, // BaseButton
+ // { "ProcessMode", "ProcessCallback" }, // AnimationTree, Camera2D
+ // { "Scancode", "Keycode" }, // InputEventKey
+ // { "Toplevel", "TopLevel" }, // Node
+ // { "WindowTitle", "Title" }, // Window
+ // { "WrapEnabled", "WrapMode" }, // TextEdit
+ // { "Zfar", "Far" }, // Camera3D
+ // { "Znear", "Near" }, // Camera3D
+ { "AsNormalmap", "AsNormalMap" }, // NoiseTexture
+ { "BbcodeText", "Text" }, // RichTextLabel
+ { "CaretMovingByRightClick", "CaretMoveOnRightClick" }, // TextEdit
+ { "CaretPosition", "CaretColumn" }, // LineEdit
+ { "CheckVadjust", "CheckVAdjust" }, // Theme
+ { "CloseHOfs", "CloseHOffset" }, // Theme
+ { "CloseVOfs", "CloseVOffset" }, // Theme
+ { "Commentfocus", "CommentFocus" }, // Theme
+ { "DragMarginBottom", "DragBottomMargin" }, // Camera2D
+ { "DragMarginHEnabled", "DragHorizontalEnabled" }, // Camera2D
+ { "DragMarginLeft", "DragLeftMargin" }, // Camera2D
+ { "DragMarginRight", "DragRightMargin" }, // Camera2D
+ { "DragMarginTop", "DragTopMargin" }, // Camera2D
+ { "DragMarginVEnabled", "DragVerticalEnabled" }, // Camera2D
+ { "EnabledFocusMode", "FocusMode" }, // BaseButton - Removed
+ { "ExtraSpacingBottom", "SpacingBottom" }, // Font
+ { "ExtraSpacingTop", "SpacingTop" }, // Font
+ { "FocusNeighbourBottom", "FocusNeighborBottom" }, // Control
+ { "FocusNeighbourLeft", "FocusNeighborLeft" }, // Control
+ { "FocusNeighbourRight", "FocusNeighborRight" }, // Control
+ { "FocusNeighbourTop", "FocusNeighborTop" }, // Control
+ { "GlobalRateScale", "PlaybackSpeedScale" }, // AudioServer
+ { "GravityDistanceScale", "GravityPointDistanceScale" }, // Area2D
+ { "GravityVec", "GravityDirection" }, // Area2D
+ { "Hseparation", "HSeparation" }, // Theme
+ { "IterationsPerSecond", "PhysicsTicksPerSecond" }, // Engine
+ { "MarginBottom", "OffsetBottom" }, // Control broke NinePatchRect, StyleBox
+ { "MarginLeft", "OffsetLeft" }, // Control broke NinePatchRect, StyleBox
+ { "MarginRight", "OffsetRight" }, // Control broke NinePatchRect, StyleBox
+ { "MarginTop", "OffsetTop" }, // Control broke NinePatchRect, StyleBox
+ { "MidHeight", "Height" }, // CapsuleMesh
+ { "OffsetH", "DragHorizontalOffset" }, // Camera2D
+ { "OffsetV", "DragVerticalOffset" }, // Camera2D
+ { "Ofs", "Offset" }, // Theme
+ { "OutOfRangeMode", "MaxPolyphony" }, // AudioStreamPlayer3D
+ { "PauseMode", "ProcessMode" }, // Node
+ { "PhysicalScancode", "PhysicalKeycode" }, // InputEventKey
+ { "PopupExclusive", "Exclusive" }, // Window
+ { "RefuseNewNetworkConnections", "RefuseNewConnections" }, // MultiplayerAPI
+ { "RegionFilterClip", "RegionFilterClipEnabled" }, // Sprite2D
+ { "Selectedframe", "SelectedFrame" }, // Theme
+ { "SizeOverrideStretch", "Size2dOverrideStretch" }, // SubViewport
+ { "SlipsOnSlope", "SlideOnSlope" }, // SeparationRayShape2D
+ { "SsReflectionsDepthTolerance", "SsrDepthTolerance" }, // Environment
+ { "SsReflectionsEnabled", "SsrEnabled" }, // Environment
+ { "SsReflectionsFadeIn", "SsrFadeIn" }, // Environment
+ { "SsReflectionsFadeOut", "SsrFadeOut" }, // Environment
+ { "SsReflectionsMaxSteps", "SsrMaxSteps" }, // Environment
+ { "StateMachineSelectedframe", "StateMachineSelectedFrame" }, // Theme
+ { "SyntaxHighlighting", "SyntaxHighlighter" }, // TextEdit
+ { "TabAlign", "TabAlignment" }, // TabContainer
+ { "TableHseparation", "TableHSeparation" }, // Theme
+ { "TableVseparation", "TableVSeparation" }, // Theme
+ { "Translation", "Position" }, // Node3D - broke GLTFNode
+ { "Vseparation", "VSeparation" }, // Theme
+
+ { nullptr, nullptr },
+};
+
+static const char *gdscript_signals_renames[][2] = {
+ // {"instantiate","instance"}, // FileSystemDock
+ // { "hide", "hidden" }, // CanvasItem - function with same name exists
+ // { "tween_all_completed","loop_finished"}, // Tween - TODO, not sure
+ // {"changed","settings_changed"}, // EditorSettings
+ { "about_to_show", "about_to_popup" }, // Popup
+ { "button_release", "button_released" }, // XRController3D
+ { "network_peer_connected", "peer_connected" }, // MultiplayerAPI
+ { "network_peer_disconnected", "peer_disconnected" }, // MultiplayerAPI
+ { "network_peer_packet", "peer_packet" }, // MultiplayerAPI
+ { "node_unselected", "node_deselected" }, // GraphEdit
+ { "offset_changed", "position_offset_changed" }, // GraphNode
+ { "settings_changed", "changed" }, // TileMap broke EditorSettings
+ { "skeleton_updated", "pose_updated" }, //
+ { "tab_close", "tab_closed" }, // TextEdit
+ { "tab_hover", "tab_hovered" }, // TextEdit
+ { "text_entered", "text_submitted" }, // LineEdit
+ { "tween_completed", "finished" }, // Tween
+ { "tween_step", "step_finished" }, // Tween
+
+ { nullptr, nullptr },
+};
+
+static const char *csharp_signals_renames[][2] = {
+ // {"Instantiate","Instance"}, // FileSystemDock
+ // { "Hide", "Hidden" }, // CanvasItem - function with same name exists
+ // { "TweenAllCompleted","LoopFinished"}, // Tween - TODO, not sure
+ // {"Changed","SettingsChanged"}, // EditorSettings
+ { "AboutToShow", "AboutToPopup" }, // Popup
+ { "ButtonRelease", "ButtonReleased" }, // XRController3D
+ { "NetworkPeerConnected", "PeerConnected" }, // MultiplayerAPI
+ { "NetworkPeerDisconnected", "PeerDisconnected" }, // MultiplayerAPI
+ { "NetworkPeerPacket", "PeerPacket" }, // MultiplayerAPI
+ { "NodeUnselected", "NodeDeselected" }, // GraphEdit
+ { "OffsetChanged", "PositionOffsetChanged" }, // GraphNode
+ { "SettingsChanged", "Changed" }, // TileMap broke EditorSettings
+ { "SkeletonUpdated", "PoseUpdated" }, //
+ { "TabClose", "TabClosed" }, // TextEdit
+ { "TabHover", "TabHovered" }, // TextEdit
+ { "TextEntered", "TextSubmitted" }, // LineEdit
+ { "TweenCompleted", "Finished" }, // Tween
+ { "TweenStep", "StepFinished" }, // Tween
+
+ { nullptr, nullptr },
+
+};
+
+static const char *project_settings_renames[][2] = {
+ { "audio/channel_disable_threshold_db", "audio/buses/channel_disable_threshold_db" },
+ { "audio/channel_disable_time", "audio/buses/channel_disable_time" },
+ { "audio/default_bus_layout", "audio/buses/default_bus_layout" },
+ { "audio/driver", "audio/driver/driver" },
+ { "audio/enable_audio_input", "audio/driver/enable_input" },
+ { "audio/mix_rate", "audio/driver/mix_rate" },
+ { "audio/output_latency", "audio/driver/output_latency" },
+ { "audio/output_latency.web", "audio/driver/output_latency.web" },
+ { "audio/video_delay_compensation_ms", "audio/video/video_delay_compensation_ms" },
+ { "display/window/vsync/use_vsync", "display/window/vsync/vsync_mode" },
+ { "editor/main_run_args", "editor/run/main_run_args" },
+ { "gui/common/swap_ok_cancel", "gui/common/swap_cancel_ok" },
+ { "network/limits/debugger_stdout/max_chars_per_second", "network/limits/debugger/max_chars_per_second" },
+ { "network/limits/debugger_stdout/max_errors_per_second", "network/limits/debugger/max_errors_per_second" },
+ { "network/limits/debugger_stdout/max_messages_per_frame", "network/limits/debugger/max_queued_messages" },
+ { "network/limits/debugger_stdout/max_warnings_per_second", "network/limits/debugger/max_warnings_per_second" },
+ { "network/ssl/certificates", "network/ssl/certificate_bundle_override" },
+ { "physics/2d/thread_model", "physics/2d/run_on_thread" }, // TODO not sure
+ { "rendering/environment/default_clear_color", "rendering/environment/defaults/default_clear_color" },
+ { "rendering/environment/default_environment", "rendering/environment/defaults/default_environment" },
+ { "rendering/quality/depth_prepass/disable_for_vendors", "rendering/driver/depth_prepass/disable_for_vendors" },
+ { "rendering/quality/depth_prepass/enable", "rendering/driver/depth_prepass/enable" },
+ { "rendering/quality/shading/force_blinn_over_ggx", "rendering/shading/overrides/force_blinn_over_ggx" },
+ { "rendering/quality/shading/force_blinn_over_ggx.mobile", "rendering/shading/overrides/force_blinn_over_ggx.mobile" },
+ { "rendering/quality/shading/force_lambert_over_burley", "rendering/shading/overrides/force_lambert_over_burley" },
+ { "rendering/quality/shading/force_lambert_over_burley.mobile", "rendering/shading/overrides/force_lambert_over_burley.mobile" },
+ { "rendering/quality/shading/force_vertex_shading", "rendering/shading/overrides/force_vertex_shading" },
+ { "rendering/quality/shading/force_vertex_shading.mobile", "rendering/shading/overrides/force_vertex_shading.mobile" },
+ { "rendering/quality/shadow_atlas/quadrant_0_subdiv", "rendering/shadows/shadow_atlas/quadrant_0_subdiv" },
+ { "rendering/quality/shadow_atlas/quadrant_1_subdiv", "rendering/shadows/shadow_atlas/quadrant_1_subdiv" },
+ { "rendering/quality/shadow_atlas/quadrant_2_subdiv", "rendering/shadows/shadow_atlas/quadrant_2_subdiv" },
+ { "rendering/quality/shadow_atlas/quadrant_3_subdiv", "rendering/shadows/shadow_atlas/quadrant_3_subdiv" },
+ { "rendering/quality/shadow_atlas/size", "rendering/shadows/shadow_atlas/size" },
+ { "rendering/quality/shadow_atlas/size.mobile", "rendering/shadows/shadow_atlas/size.mobile" },
+ { "rendering/vram_compression/import_bptc", "rendering/textures/vram_compression/import_bptc" },
+ { "rendering/vram_compression/import_etc", "rendering/textures/vram_compression/import_etc" },
+ { "rendering/vram_compression/import_etc2", "rendering/textures/vram_compression/import_etc2" },
+ { "rendering/vram_compression/import_pvrtc", "rendering/textures/vram_compression/import_pvrtc" },
+ { "rendering/vram_compression/import_s3tc", "rendering/textures/vram_compression/import_s3tc" },
+
+ { nullptr, nullptr },
+};
+
+static const char *builtin_types_renames[][2] = {
+ { "PoolByteArray", "PackedByteArray" },
+ { "PoolColorArray", "PackedColorArray" },
+ { "PoolIntArray", "PackedInt32Array" },
+ { "PoolRealArray", "PackedFloat32Array" },
+ { "PoolStringArray", "PackedStringArray" },
+ { "PoolVector2Array", "PackedVector2Array" },
+ { "PoolVector3Array", "PackedVector3Array" },
+ { "Quat", "Quaternion" },
+ { "Transform", "Transform3D" },
+
+ { nullptr, nullptr },
+};
+
+static const char *shaders_renames[][2] = {
+ { "ALPHA_SCISSOR", "ALPHA_SCISSOR_THRESHOLD" },
+ { "NORMALMAP", "NORMAL_MAP" },
+ { "NORMALMAP_DEPTH", "NORMAL_MAP_DEPTH" },
+ { "TRANSMISSION", "SSS_TRANSMITTANCE_COLOR" },
+ { nullptr, nullptr },
+};
+
+static const char *class_renames[][2] = {
+ // { "BulletPhysicsDirectBodyState", "BulletPhysicsDirectBodyState3D" }, // Class is not visible in ClassDB
+ // { "BulletPhysicsServer", "BulletPhysicsServer3D" }, // Class is not visible in ClassDB
+ // { "GDScriptFunctionState", "Node3D" }, // TODO - not sure to which should be changed
+ // { "GDScriptNativeClass", "Node3D" }, // TODO - not sure to which should be changed
+ // { "InputDefault",""}, // TODO ?
+ // { "Physics2DDirectBodyStateSW", "GodotPhysicsDirectBodyState2D" }, // Class is not visible in ClassDB
+ // { "Physics2DShapeQueryResult", "PhysicsShapeQueryResult2D" }, // Class is not visible in ClassDB
+ // { "PhysicsShapeQueryResult", "PhysicsShapeQueryResult3D" }, // Class is not visible in ClassDB
+ // { "NativeScript","NativeExtension"}, ??
+ { "AStar", "AStar3D" },
+ { "ARVRAnchor", "XRAnchor3D" },
+ { "ARVRCamera", "XRCamera3D" },
+ { "ARVRController", "XRController3D" },
+ { "ARVRInterface", "XRInterface" },
+ { "ARVRInterfaceGDNative", "Node3D" },
+ { "ARVROrigin", "XROrigin3D" },
+ { "ARVRPositionalTracker", "XRPositionalTracker" },
+ { "ARVRServer", "XRServer" },
+ { "AnimatedSprite", "AnimatedSprite2D" },
+ { "AnimationTreePlayer", "AnimationTree" },
+ { "Area", "Area3D" }, // Be careful, this will be used everywhere
+ { "AudioStreamRandomPitch", "AudioStreamRandomizer" },
+ { "BakedLightmap", "LightmapGI" },
+ { "BakedLightmapData", "LightmapGIData" },
+ { "BitmapFont", "Font" },
+ { "BoneAttachment", "BoneAttachment3D" },
+ { "BoxShape", "BoxShape3D" },
+ { "CPUParticles", "CPUParticles3D" },
+ { "CSGBox", "CSGBox3D" },
+ { "CSGCombiner", "CSGCombiner3D" },
+ { "CSGCylinder", "CSGCylinder3D" },
+ { "CSGMesh", "CSGMesh3D" },
+ { "CSGPolygon", "CSGPolygon3D" },
+ { "CSGPrimitive", "CSGPrimitive3D" },
+ { "CSGShape", "CSGShape3D" },
+ { "CSGSphere", "CSGSphere3D" },
+ { "CSGTorus", "CSGTorus3D" },
+ { "Camera", "Camera3D" }, // Be careful, this will be used everywhere
+ { "CapsuleShape", "CapsuleShape3D" },
+ { "ClippedCamera", "Camera3D" },
+ { "CollisionObject", "CollisionObject3D" },
+ { "CollisionPolygon", "CollisionPolygon3D" },
+ { "CollisionShape", "CollisionShape3D" },
+ { "ConcavePolygonShape", "ConcavePolygonShape3D" },
+ { "ConeTwistJoint", "ConeTwistJoint3D" },
+ { "ConvexPolygonShape", "ConvexPolygonShape3D" },
+ { "CubeMap", "Cubemap" },
+ { "CubeMesh", "BoxMesh" },
+ { "CylinderShape", "CylinderShape3D" },
+ { "DirectionalLight", "DirectionalLight3D" },
+ { "DynamicFont", "Font" },
+ { "DynamicFontData", "FontData" },
+ { "EditorNavigationMeshGenerator", "NavigationMeshGenerator" },
+ { "EditorSceneImporter", "EditorSceneFormatImporter" },
+ { "EditorSceneImporterFBX", "EditorSceneFormatImporterFBX" },
+ { "EditorSceneImporterGLTF", "EditorSceneFormatImporterGLTF" },
+ { "EditorSpatialGizmo", "EditorNode3DGizmo" },
+ { "EditorSpatialGizmoPlugin", "EditorNode3DGizmoPlugin" },
+ { "ExternalTexture", "ImageTexture" },
+ { "FuncRef", "Callable" },
+ { "GIProbe", "VoxelGI" },
+ { "GIProbeData", "VoxelGIData" },
+ { "Generic6DOFJoint", "Generic6DOFJoint3D" },
+ { "Geometry", "Geometry2D" }, // Geometry class is split between Geometry2D and Geometry3D so we need to choose one
+ { "GeometryInstance", "GeometryInstance3D" },
+ { "GradientTexture", "GradientTexture2D" },
+ { "HeightMapShape", "HeightMapShape3D" },
+ { "HingeJoint", "HingeJoint3D" },
+ { "IP_Unix", "IPUnix" },
+ { "ImmediateGeometry", "ImmediateMesh" },
+ { "ImmediateGeometry3D", "ImmediateMesh" },
+ { "InterpolatedCamera", "Camera3D" },
+ { "InterpolatedCamera3D", "Camera3D" },
+ { "JSONParseResult", "JSON" },
+ { "Joint", "Joint3D" },
+ { "KinematicBody", "CharacterBody3D" },
+ { "KinematicBody2D", "CharacterBody2D" },
+ { "KinematicCollision", "KinematicCollision3D" },
+ { "LargeTexture", "ImageTexture" },
+ { "Light", "Light3D" },
+ { "Light2D", "PointLight2D" },
+ { "LineShape2D", "WorldBoundaryShape2D" },
+ { "Listener", "AudioListener3D" },
+ { "Listener2D", "AudioListener2D" },
+ { "MeshInstance", "MeshInstance3D" },
+ { "MultiMeshInstance", "MultiMeshInstance3D" },
+ { "MultiplayerPeerGDNative", "MultiplayerPeerExtension" },
+ { "Navigation", "Node3D" },
+ { "Navigation2D", "Node2D" },
+ { "Navigation2DServer", "NavigationServer2D" },
+ { "Navigation3D", "Node3D" },
+ { "NavigationAgent", "NavigationAgent3D" },
+ { "NavigationMeshInstance", "NavigationRegion3D" },
+ { "NavigationObstacle", "NavigationObstacle3D" },
+ { "NavigationPolygonInstance", "NavigationRegion2D" },
+ { "NavigationRegion", "NavigationRegion3D" },
+ { "NavigationServer", "NavigationServer3D" },
+ { "NetworkedMultiplayerENet", "ENetMultiplayerPeer" },
+ { "NetworkedMultiplayerPeer", "MultiplayerPeer" },
+ { "Occluder", "OccluderInstance3D" },
+ { "OmniLight", "OmniLight3D" },
+ { "PHashTranslation", "OptimizedTranslation" },
+ { "PacketPeerGDNative", "PacketPeerExtension" },
+ { "PanoramaSky", "Sky" },
+ { "Particles", "GPUParticles3D" }, // Be careful, this will be used everywhere
+ { "Particles2D", "GPUParticles2D" },
+ { "Path", "Path3D" }, // Be careful, this will be used everywhere
+ { "PathFollow", "PathFollow3D" },
+ { "PhysicalBone", "PhysicalBone3D" },
+ { "Physics2DDirectBodyState", "PhysicsDirectBodyState2D" },
+ { "Physics2DDirectSpaceState", "PhysicsDirectSpaceState2D" },
+ { "Physics2DServer", "PhysicsServer2D" },
+ { "Physics2DServerSW", "GodotPhysicsServer2D" },
+ { "Physics2DShapeQueryParameters", "PhysicsShapeQueryParameters2D" },
+ { "Physics2DTestMotionResult", "PhysicsTestMotionResult2D" },
+ { "PhysicsBody", "PhysicsBody3D" },
+ { "PhysicsDirectBodyState", "PhysicsDirectBodyState3D" },
+ { "PhysicsDirectSpaceState", "PhysicsDirectSpaceState3D" },
+ { "PhysicsServer", "PhysicsServer3D" },
+ { "PhysicsShapeQueryParameters", "PhysicsShapeQueryParameters3D" },
+ { "PhysicsTestMotionResult", "PhysicsTestMotionResult3D" },
+ { "PinJoint", "PinJoint3D" },
+ { "PlaneShape", "WorldBoundaryShape3D" },
+ { "PopupDialog", "Popup" },
+ { "ProceduralSky", "Sky" },
+ { "RayCast", "RayCast3D" },
+ { "RayShape", "SeparationRayShape3D" },
+ { "RayShape2D", "SeparationRayShape2D" },
+ { "Reference", "RefCounted" }, // Be careful, this will be used everywhere
+ { "RemoteTransform", "RemoteTransform3D" },
+ { "ResourceInteractiveLoader", "ResourceLoader" },
+ { "RigidBody", "RigidDynamicBody3D" },
+ { "RigidBody2D", "RigidDynamicBody2D" },
+ { "Shape", "Shape3D" }, // Be careful, this will be used everywhere
+ { "ShortCut", "Shortcut" },
+ { "Skeleton", "Skeleton3D" },
+ { "SkeletonIK", "SkeletonIK3D" },
+ { "SliderJoint", "SliderJoint3D" },
+ { "SoftBody", "SoftDynamicBody3D" },
+ { "Spatial", "Node3D" },
+ { "SpatialGizmo", "Node3DGizmo" },
+ { "SpatialMaterial", "StandardMaterial3D" },
+ { "SpatialVelocityTracker", "VelocityTracker3D" },
+ { "SphereShape", "SphereShape3D" },
+ { "SpotLight", "SpotLight3D" },
+ { "SpringArm", "SpringArm3D" },
+ { "Sprite", "Sprite2D" },
+ { "StaticBody", "StaticBody3D" },
+ { "StreamCubemap", "CompressedCubemap" },
+ { "StreamCubemapArray", "CompressedCubemapArray" },
+ { "StreamPeerGDNative", "StreamPeerExtension" },
+ { "StreamTexture", "CompressedTexture2D" },
+ { "StreamTexture2D", "CompressedTexture2D" },
+ { "StreamTexture2DArray", "CompressedTexture2DArray" },
+ { "StreamTextureLayered", "CompressedTextureLayered" },
+ { "TCP_Server", "TCPServer" },
+ { "Tabs", "TabBar" }, // Be careful, this will be used everywhere
+ { "TextFile", "Node3D" },
+ { "Texture", "Texture2D" }, // May broke TextureRect
+ { "TextureArray", "Texture2DArray" },
+ { "TextureProgress", "TextureProgressBar" },
+ { "ToolButton", "Button" },
+ { "VehicleBody", "VehicleBody3D" },
+ { "VehicleWheel", "VehicleWheel3D" },
+ { "VideoPlayer", "VideoStreamPlayer" },
+ { "Viewport", "SubViewport" },
+ { "ViewportContainer", "SubViewportContainer" },
+ { "VisibilityEnabler", "VisibleOnScreenEnabler3D" },
+ { "VisibilityEnabler2D", "VisibleOnScreenEnabler2D" },
+ { "VisibilityNotifier", "VisibleOnScreenNotifier3D" },
+ { "VisibilityNotifier2D", "VisibleOnScreenNotifier2D" },
+ { "VisibilityNotifier3D", "VisibleOnScreenNotifier3D" },
+ { "VisualInstance", "VisualInstance3D" },
+ { "VisualServer", "RenderingServer" },
+ { "VisualShaderNodeCubeMap", "VisualShaderNodeCubemap" },
+ { "VisualShaderNodeCubeMapUniform", "VisualShaderNodeCubemapUniform" },
+ { "VisualShaderNodeScalarClamp", "VisualShaderNodeClamp" },
+ { "VisualShaderNodeScalarConstant", "VisualShaderNodeFloatConstant" },
+ { "VisualShaderNodeScalarFunc", "VisualShaderNodeFloatFunc" },
+ { "VisualShaderNodeScalarInterp", "VisualShaderNodeMix" },
+ { "VisualShaderNodeScalarOp", "VisualShaderNodeFloatOp" },
+ { "VisualShaderNodeScalarSmoothStep", "VisualShaderNodeSmoothStep" },
+ { "VisualShaderNodeScalarSwitch", "VisualShaderNodeSwitch" },
+ { "VisualShaderNodeScalarTransformMult", "VisualShaderNodeTransformOp" },
+ { "VisualShaderNodeScalarUniform", "VisualShaderNodeFloatUniform" },
+ { "VisualShaderNodeTransformMult", "VisualShaderNode" },
+ { "VisualShaderNodeVectorClamp", "VisualShaderNodeClamp" },
+ { "VisualShaderNodeVectorInterp", "VisualShaderNodeMix" },
+ { "VisualShaderNodeVectorScalarMix", "VisualShaderNodeMix" },
+ { "VisualShaderNodeVectorScalarSmoothStep", "VisualShaderNodeSmoothStep" },
+ { "VisualShaderNodeVectorScalarStep", "VisualShaderNodeStep" },
+ { "VisualShaderNodeVectorSmoothStep", "VisualShaderNodeSmoothStep" },
+ { "WebRTCDataChannelGDNative", "WebRTCDataChannelExtension" },
+ { "WebRTCMultiplayer", "WebRTCMultiplayerPeer" },
+ { "WebRTCPeerConnectionGDNative", "WebRTCPeerConnectionExtension" },
+ { "WindowDialog", "Window" },
+ { "World", "World3D" }, // Be careful, this will be used everywhere
+ { "XRAnchor", "XRAnchor3D" },
+ { "XRController", "XRController3D" },
+ { "XROrigin", "XROrigin3D" },
+ { "YSort", "Node2D" },
+
+ { "CullInstance", "Node3D" }, // Probably this type needs to be added to Godot 4.0, since it is for now only available only in Godot 3.x
+ { "RoomGroup", "Node3D" }, // Probably this type needs to be added to Godot 4.0, since it is for now only available only in Godot 3.x
+ { "Room", "Node3D" }, // Probably this type needs to be added to Godot 4.0, since it is for now only available only in Godot 3.x
+ { "RoomManager", "Node3D" }, // Probably this type needs to be added to Godot 4.0, since it is for now only available only in Godot 3.x
+ { "Portal", "Node3D" }, // Probably this type needs to be added to Godot 4.0, since it is for now only available only in Godot 3.x
+
+ { nullptr, nullptr },
+};
+
+// TODO - this colors needs to be validated(not all are valid)
+static const char *colors_renames[][2] = {
+ { "aliceblue", "ALICE_BLUE" },
+ { "antiquewhite", "ANTIQUE_WHITE" },
+ { "aqua", "AQUA" },
+ { "aquamarine", "AQUAMARINE" },
+ { "azure", "AZURE" },
+ { "beige", "BEIGE" },
+ { "bisque", "BISQUE" },
+ { "black", "BLACK" },
+ { "blanchedalmond", "BLANCHED_ALMOND" },
+ { "blue", "BLUE" },
+ { "blueviolet", "BLUE_VIOLET" },
+ { "brown", "BROWN" },
+ { "burlywood", "BURLYWOOD" },
+ { "cadetblue", "CADET_BLUE" },
+ { "chartreuse", "CHARTREUSE" },
+ { "chocolate", "CHOCOLATE" },
+ { "coral", "CORAL" },
+ { "cornflowerblue", "CORNFLOWER_BLUE" },
+ { "cornsilk", "CORNSILK" },
+ { "crimson", "CRIMSON" },
+ { "cyan", "CYAN" },
+ { "darkblue", "DARK_BLUE" },
+ { "darkcyan", "DARK_CYAN" },
+ { "darkgoldenrod", "DARK_GOLDENROD" },
+ { "darkgray", "DARK_GRAY" },
+ { "darkgreen", "DARK_GREEN" },
+ { "darkkhaki", "DARK_KHAKI" },
+ { "darkmagenta", "DARK_MAGENTA" },
+ { "darkolivegreen", "DARK_OLIVE_GREEN" },
+ { "darkorange", "DARK_ORANGE" },
+ { "darkorchid", "DARK_ORCHID" },
+ { "darkred", "DARK_RED" },
+ { "darksalmon", "DARK_SALMON" },
+ { "darkseagreen", "DARK_SEA_GREEN" },
+ { "darkslateblue", "DARK_SLATE_BLUE" },
+ { "darkslategray", "DARK_SLATE_GRAY" },
+ { "darkturquoise", "DARK_TURQUOISE" },
+ { "darkviolet", "DARK_VIOLET" },
+ { "deeppink", "DEEP_PINK" },
+ { "deepskyblue", "DEEP_SKY_BLUE" },
+ { "dimgray", "DIM_GRAY" },
+ { "dodgerblue", "DODGER_BLUE" },
+ { "firebrick", "FIREBRICK" },
+ { "floralwhite", "FLORAL_WHITE" },
+ { "forestgreen", "FOREST_GREEN" },
+ { "fuchsia", "FUCHSIA" },
+ { "gainsboro", "GAINSBORO" },
+ { "ghostwhite", "GHOST_WHITE" },
+ { "gold", "GOLD" },
+ { "goldenrod", "GOLDENROD" },
+ { "gray", "GRAY" },
+ { "green", "GREEN" },
+ { "greenyellow", "GREEN_YELLOW" },
+ { "honeydew", "HONEYDEW" },
+ { "hotpink", "HOT_PINK" },
+ { "indianred", "INDIAN_RED" },
+ { "indigo", "INDIGO" },
+ { "ivory", "IVORY" },
+ { "khaki", "KHAKI" },
+ { "lavender", "LAVENDER" },
+ { "lavenderblush", "LAVENDER_BLUSH" },
+ { "lawngreen", "LAWN_GREEN" },
+ { "lemonchiffon", "LEMON_CHIFFON" },
+ { "lightblue", "LIGHT_BLUE" },
+ { "lightcoral", "LIGHT_CORAL" },
+ { "lightcyan", "LIGHT_CYAN" },
+ { "lightgoldenrod", "LIGHT_GOLDENROD" },
+ { "lightgray", "LIGHT_GRAY" },
+ { "lightgreen", "LIGHT_GREEN" },
+ { "lightpink", "LIGHT_PINK" },
+ { "lightsalmon", "LIGHT_SALMON" },
+ { "lightseagreen", "LIGHT_SEA_GREEN" },
+ { "lightskyblue", "LIGHT_SKY_BLUE" },
+ { "lightslategray", "LIGHT_SLATE_GRAY" },
+ { "lightsteelblue", "LIGHT_STEEL_BLUE" },
+ { "lightyellow", "LIGHT_YELLOW" },
+ { "lime", "LIME" },
+ { "limegreen", "LIME_GREEN" },
+ { "linen", "LINEN" },
+ { "magenta", "MAGENTA" },
+ { "maroon", "MAROON" },
+ { "mediumaquamarine", "MEDIUM_AQUAMARINE" },
+ { "mediumblue", "MEDIUM_BLUE" },
+ { "mediumorchid", "MEDIUM_ORCHID" },
+ { "mediumpurple", "MEDIUM_PURPLE" },
+ { "mediumseagreen", "MEDIUM_SEA_GREEN" },
+ { "mediumslateblue", "MEDIUM_SLATE_BLUE" },
+ { "mediumspringgreen", "MEDIUM_SPRING_GREEN" },
+ { "mediumturquoise", "MEDIUM_TURQUOISE" },
+ { "mediumvioletred", "MEDIUM_VIOLET_RED" },
+ { "midnightblue", "MIDNIGHT_BLUE" },
+ { "mintcream", "MINT_CREAM" },
+ { "mistyrose", "MISTY_ROSE" },
+ { "moccasin", "MOCCASIN" },
+ { "navajowhite", "NAVAJO_WHITE" },
+ { "navyblue", "NAVY_BLUE" },
+ { "oldlace", "OLD_LACE" },
+ { "olive", "OLIVE" },
+ { "olivedrab", "OLIVE_DRAB" },
+ { "orange", "ORANGE" },
+ { "orangered", "ORANGE_RED" },
+ { "orchid", "ORCHID" },
+ { "palegoldenrod", "PALE_GOLDENROD" },
+ { "palegreen", "PALE_GREEN" },
+ { "paleturquoise", "PALE_TURQUOISE" },
+ { "palevioletred", "PALE_VIOLET_RED" },
+ { "papayawhip", "PAPAYA_WHIP" },
+ { "peachpuff", "PEACH_PUFF" },
+ { "peru", "PERU" },
+ { "pink", "PINK" },
+ { "plum", "PLUM" },
+ { "powderblue", "POWDER_BLUE" },
+ { "purple", "PURPLE" },
+ { "rebeccapurple", "REBECCA_PURPLE" },
+ { "red", "RED" },
+ { "rosybrown", "ROSY_BROWN" },
+ { "royalblue", "ROYAL_BLUE" },
+ { "saddlebrown", "SADDLE_BROWN" },
+ { "salmon", "SALMON" },
+ { "sandybrown", "SANDY_BROWN" },
+ { "seagreen", "SEA_GREEN" },
+ { "seashell", "SEASHELL" },
+ { "sienna", "SIENNA" },
+ { "silver", "SILVER" },
+ { "skyblue", "SKY_BLUE" },
+ { "slateblue", "SLATE_BLUE" },
+ { "slategray", "SLATE_GRAY" },
+ { "snow", "SNOW" },
+ { "springgreen", "SPRING_GREEN" },
+ { "steelblue", "STEEL_BLUE" },
+ { "tan", "TAN" },
+ { "teal", "TEAL" },
+ { "thistle", "THISTLE" },
+ { "tomato", "TOMATO" },
+ { "transparent", "TRANSPARENT" },
+ { "turquoise", "TURQUOISE" },
+ { "violet", "VIOLET" },
+ { "webgray", "WEB_GRAY" },
+ { "webgreen", "WEB_GREEN" },
+ { "webmaroon", "WEB_MAROON" },
+ { "webpurple", "WEB_PURPLE" },
+ { "wheat", "WHEAT" },
+ { "white", "WHITE" },
+ { "whitesmoke", "WHITE_SMOKE" },
+ { "yellow", "YELLOW" },
+ { "yellowgreen", "YELLOW_GREEN" },
+
+ { nullptr, nullptr },
+};
+
+// Function responsible for converting project
+int ProjectConverter3To4::convert() {
+ print_line("Starting conversion.");
+
+ ERR_FAIL_COND_V_MSG(!test_array_names(), ERROR_CODE, "Cannot start converting due to problems with data in arrays.");
+ ERR_FAIL_COND_V_MSG(!test_conversion(), ERROR_CODE, "Cannot start converting due to problems with converting arrays.");
+
+ // Checking if folder contains valid Godot 3 project.
+ // Project cannot be converted 2 times
+ {
+ String conventer_text = "; Project was converted by built-in tool to Godot 4.0";
+
+ ERR_FAIL_COND_V_MSG(!FileAccess::exists("project.godot"), ERROR_CODE, "Current directory doesn't contains any Godot 3 project");
+
+ Error err = OK;
+ String project_godot_content = FileAccess::get_file_as_string("project.godot", &err);
+
+ ERR_FAIL_COND_V_MSG(err != OK, ERROR_CODE, "Failed to read content of \"project.godot\" file.");
+ ERR_FAIL_COND_V_MSG(project_godot_content.find(conventer_text) != -1, ERROR_CODE, "Project already was converted with this tool.");
+
+ Ref<FileAccess> file = FileAccess::open("project.godot", FileAccess::WRITE);
+ ERR_FAIL_COND_V_MSG(file.is_null(), ERROR_CODE, "Failed to open project.godot file.");
+
+ file->store_string(conventer_text + "\n" + project_godot_content);
+ }
+
+ Vector<String> collected_files = check_for_files();
+
+ uint32_t converted_files = 0;
+
+ // Check file by file
+ for (int i = 0; i < collected_files.size(); i++) {
+ String file_name = collected_files[i];
+ Error err = OK;
+ String file_content = FileAccess::get_file_as_string(file_name, &err);
+ ERR_CONTINUE_MSG(err != OK, "Failed to read content of \"" + file_name + "\".");
+ uint64_t hash_before = file_content.hash64();
+ uint64_t file_size = file_content.size();
+ print_line("Trying to convert\t" + itos(i + 1) + "/" + itos(collected_files.size()) + " file - \"" + file_name.trim_prefix("res://") + "\" with size - " + itos(file_size / 1024) + " KB");
+
+ Vector<String> reason;
+ bool is_ignored = false;
+ uint64_t start_time = Time::get_singleton()->get_ticks_msec();
+
+ if (file_name.ends_with(".shader")) {
+ DirAccess::remove_file_or_error(file_name);
+ file_name = file_name.replace(".shader", ".gdshader");
+ }
+
+ if (file_size < CONVERSION_MAX_FILE_SIZE) {
+ // TSCN must be the same work exactly same as .gd file because it may contains builtin script
+ if (file_name.ends_with(".gd")) {
+ rename_classes(file_content); // Using only specialized function
+
+ rename_common(enum_renames, file_content);
+ rename_enums(file_content); // Require to additional rename
+
+ rename_common(gdscript_function_renames, file_content);
+ rename_gdscript_functions(file_content); // Require to additional rename
+
+ rename_common(project_settings_renames, file_content);
+ rename_gdscript_keywords(file_content);
+ rename_common(gdscript_properties_renames, file_content);
+ rename_common(gdscript_signals_renames, file_content);
+ rename_common(shaders_renames, file_content);
+ rename_common(builtin_types_renames, file_content);
+
+ custom_rename(file_content, "\\.shader", ".gdshader");
+ custom_rename(file_content, "instance", "instantiate");
+ } else if (file_name.ends_with(".tscn")) {
+ rename_classes(file_content); // Using only specialized function
+
+ rename_common(enum_renames, file_content);
+ rename_enums(file_content); // Require to additional rename
+
+ rename_common(gdscript_function_renames, file_content);
+ rename_gdscript_functions(file_content); // Require to additional rename
+
+ rename_common(project_settings_renames, file_content);
+ rename_gdscript_keywords(file_content);
+ rename_common(gdscript_properties_renames, file_content);
+ rename_common(gdscript_signals_renames, file_content);
+ rename_common(shaders_renames, file_content);
+ rename_common(builtin_types_renames, file_content);
+
+ custom_rename(file_content, "\\.shader", ".gdshader");
+ } else if (file_name.ends_with(".cs")) { // TODO, C# should use different methods
+ rename_classes(file_content); // Using only specialized function
+ rename_common(csharp_function_renames, file_content);
+ rename_common(builtin_types_renames, file_content);
+ rename_common(csharp_properties_renames, file_content);
+ rename_common(csharp_signals_renames, file_content);
+ rename_csharp_functions(file_content);
+ custom_rename(file_content, "public class ", "public partial class ");
+ } else if (file_name.ends_with(".gdshader") || file_name.ends_with(".shader")) {
+ rename_common(shaders_renames, file_content);
+ } else if (file_name.ends_with("tres")) {
+ rename_classes(file_content); // Using only specialized function
+
+ rename_common(shaders_renames, file_content);
+ rename_common(builtin_types_renames, file_content);
+
+ custom_rename(file_content, "\\.shader", ".gdshader");
+ } else if (file_name.ends_with("project.godot")) {
+ rename_common(project_settings_renames, file_content);
+ rename_common(builtin_types_renames, file_content);
+ } else if (file_name.ends_with(".csproj")) {
+ // TODO
+ } else {
+ ERR_PRINT(file_name + " is not supported!");
+ continue;
+ }
+ } else {
+ reason.append(" ERROR: File has exceeded the maximum size allowed - 500 KB");
+ is_ignored = true;
+ }
+
+ uint64_t end_time = Time::get_singleton()->get_ticks_msec();
+
+ if (!is_ignored) {
+ uint64_t hash_after = file_content.hash64();
+ // Don't need to save file without any changes
+ // Save if this is a shader, because it was renamed
+ if (hash_before != hash_after || file_name.find(".gdshader") != -1) {
+ converted_files++;
+
+ Ref<FileAccess> file = FileAccess::open(file_name, FileAccess::WRITE);
+ ERR_CONTINUE_MSG(file.is_null(), "Failed to open \"" + file_name + "\" to save data to file.");
+ file->store_string(file_content);
+ reason.append(" File was changed, conversion took " + itos(end_time - start_time) + " ms.");
+ } else {
+ reason.append(" File was not changed, checking took " + itos(end_time - start_time) + " ms.");
+ }
+ }
+ for (int k = 0; k < reason.size(); k++) {
+ print_line(reason[k]);
+ }
+ }
+
+ print_line("Conversion ended - all files(" + itos(collected_files.size()) + "), converted files(" + itos(converted_files) + "), not converted files(" + itos(collected_files.size() - converted_files) + ").");
+ return 0;
+};
+
+// Function responsible for validating project conversion.
+int ProjectConverter3To4::validate_conversion() {
+ print_line("Starting checking if project conversion can be done.");
+
+ ERR_FAIL_COND_V_MSG(!test_array_names(), ERROR_CODE, "Cannot start converting due to problems with data in arrays.");
+ ERR_FAIL_COND_V_MSG(!test_conversion(), ERROR_CODE, "Cannot start converting due to problems with converting arrays.");
+
+ // Checking if folder contains valid Godot 3 project.
+ // Project cannot be converted 2 times
+ {
+ String conventer_text = "; Project was converted by built-in tool to Godot 4.0";
+
+ ERR_FAIL_COND_V_MSG(!FileAccess::exists("project.godot"), ERROR_CODE, "Current directory doesn't contains any Godot 3 project");
+
+ Error err = OK;
+ String project_godot_content = FileAccess::get_file_as_string("project.godot", &err);
+
+ ERR_FAIL_COND_V_MSG(err != OK, ERROR_CODE, "Failed to read content of \"project.godot\" file.");
+ ERR_FAIL_COND_V_MSG(project_godot_content.find(conventer_text) != -1, ERROR_CODE, "Project already was converted with this tool.");
+ }
+
+ Vector<String> collected_files = check_for_files();
+
+ uint32_t converted_files = 0;
+
+ // Check file by file
+ for (int i = 0; i < collected_files.size(); i++) {
+ String file_name = collected_files[i];
+ Vector<String> file_content;
+ uint64_t file_size = 0;
+ {
+ Ref<FileAccess> file = FileAccess::open(file_name, FileAccess::READ);
+ ERR_CONTINUE_MSG(file.is_null(), "Failed to read content of \"" + file_name + "\".");
+ while (!file->eof_reached()) {
+ String line = file->get_line();
+ file_size += line.size();
+ file_content.append(line);
+ }
+ }
+ print_line("Checking for conversion - " + itos(i + 1) + "/" + itos(collected_files.size()) + " file - \"" + file_name.trim_prefix("res://") + "\" with size - " + itos(file_size / 1024) + " KB");
+
+ Vector<String> changed_elements;
+ Vector<String> reason;
+ bool is_ignored = false;
+ uint64_t start_time = Time::get_singleton()->get_ticks_msec();
+
+ if (file_name.ends_with(".sader")) {
+ reason.append("\tFile extension will be renamed from `shader` to `gdshader`.");
+ }
+
+ if (file_size < CONVERSION_MAX_FILE_SIZE) {
+ if (file_name.ends_with(".gd")) {
+ changed_elements.append_array(check_for_rename_classes(file_content));
+
+ changed_elements.append_array(check_for_rename_common(enum_renames, file_content));
+ changed_elements.append_array(check_for_rename_enums(file_content));
+
+ changed_elements.append_array(check_for_rename_common(gdscript_function_renames, file_content));
+ changed_elements.append_array(check_for_rename_gdscript_functions(file_content));
+
+ changed_elements.append_array(check_for_rename_common(project_settings_renames, file_content));
+ changed_elements.append_array(check_for_rename_gdscript_keywords(file_content));
+ changed_elements.append_array(check_for_rename_common(gdscript_properties_renames, file_content));
+ changed_elements.append_array(check_for_rename_common(gdscript_signals_renames, file_content));
+ changed_elements.append_array(check_for_rename_common(shaders_renames, file_content));
+ changed_elements.append_array(check_for_rename_common(builtin_types_renames, file_content));
+
+ changed_elements.append_array(check_for_custom_rename(file_content, "instance", "instantiate"));
+ changed_elements.append_array(check_for_custom_rename(file_content, "\\.shader", ".gdshader"));
+ } else if (file_name.ends_with(".tscn")) {
+ changed_elements.append_array(check_for_rename_classes(file_content));
+
+ changed_elements.append_array(check_for_rename_common(enum_renames, file_content));
+ changed_elements.append_array(check_for_rename_enums(file_content));
+
+ changed_elements.append_array(check_for_rename_common(gdscript_function_renames, file_content));
+ changed_elements.append_array(check_for_rename_gdscript_functions(file_content));
+
+ changed_elements.append_array(check_for_rename_common(project_settings_renames, file_content));
+ changed_elements.append_array(check_for_rename_gdscript_keywords(file_content));
+ changed_elements.append_array(check_for_rename_common(gdscript_properties_renames, file_content));
+ changed_elements.append_array(check_for_rename_common(gdscript_signals_renames, file_content));
+ changed_elements.append_array(check_for_rename_common(shaders_renames, file_content));
+ changed_elements.append_array(check_for_rename_common(builtin_types_renames, file_content));
+
+ changed_elements.append_array(check_for_custom_rename(file_content, "\\.shader", ".gdshader"));
+ } else if (file_name.ends_with(".cs")) {
+ changed_elements.append_array(check_for_rename_common(class_renames, file_content));
+ changed_elements.append_array(check_for_rename_common(csharp_function_renames, file_content));
+ changed_elements.append_array(check_for_rename_common(builtin_types_renames, file_content));
+ changed_elements.append_array(check_for_rename_common(csharp_properties_renames, file_content));
+ changed_elements.append_array(check_for_rename_common(csharp_signals_renames, file_content));
+ changed_elements.append_array(check_for_rename_csharp_functions(file_content));
+ changed_elements.append_array(check_for_custom_rename(file_content, "public class ", "public partial class "));
+ } else if (file_name.ends_with(".gdshader") || file_name.ends_with(".shader")) {
+ changed_elements.append_array(check_for_rename_common(shaders_renames, file_content));
+ } else if (file_name.ends_with("tres")) {
+ changed_elements.append_array(check_for_rename_classes(file_content));
+
+ changed_elements.append_array(check_for_rename_common(shaders_renames, file_content));
+ changed_elements.append_array(check_for_rename_common(builtin_types_renames, file_content));
+
+ changed_elements.append_array(check_for_custom_rename(file_content, "\\.shader", ".gdshader"));
+ } else if (file_name.ends_with("project.godot")) {
+ changed_elements.append_array(check_for_rename_common(project_settings_renames, file_content));
+ changed_elements.append_array(check_for_rename_common(builtin_types_renames, file_content));
+ } else if (file_name.ends_with(".csproj")) {
+ // TODO
+ } else {
+ ERR_PRINT(file_name + " is not supported!");
+ continue;
+ }
+ } else {
+ reason.append("\tERROR: File has exceeded the maximum size allowed - 500 KB");
+ is_ignored = true;
+ }
+
+ uint64_t end_time = Time::get_singleton()->get_ticks_msec();
+ print_line(" Checking file took " + itos(end_time - start_time) + " ms.");
+
+ for (int k = 0; k < reason.size(); k++) {
+ print_line(reason[k]);
+ }
+
+ if (changed_elements.size() > 0 && !is_ignored) {
+ converted_files++;
+
+ for (int k = 0; k < changed_elements.size(); k++) {
+ print_line(String("\t\t") + changed_elements[k]);
+ }
+ }
+ }
+
+ print_line("Checking for valid conversion ended - all files(" + itos(collected_files.size()) + "), files which would be converted(" + itos(converted_files) + "), files which would not be converted(" + itos(collected_files.size() - converted_files) + ").");
+ return 0;
+}
+
+// Collect files which will be checked, it will not touch txt, mp4, wav etc. files
+Vector<String> ProjectConverter3To4::check_for_files() {
+ Vector<String> collected_files = Vector<String>();
+
+ Vector<String> directories_to_check = Vector<String>();
+ directories_to_check.push_back("res://");
+
+ core_bind::Directory dir = core_bind::Directory();
+ while (!directories_to_check.is_empty()) {
+ String path = directories_to_check.get(directories_to_check.size() - 1); // Is there any pop_back function?
+ directories_to_check.resize(directories_to_check.size() - 1); // Remove last element
+ if (dir.open(path) == OK) {
+ dir.set_include_hidden(true);
+ dir.list_dir_begin();
+ String current_dir = dir.get_current_dir();
+ String file_name = dir.get_next();
+
+ while (file_name != "") {
+ if (file_name == ".git" || file_name == ".import" || file_name == ".godot") {
+ file_name = dir.get_next();
+ continue;
+ }
+ if (dir.current_is_dir()) {
+ directories_to_check.append(current_dir + file_name + "/");
+ } else {
+ bool proper_extension = false;
+ if (file_name.ends_with(".gd") || file_name.ends_with(".shader") || file_name.ends_with(".tscn") || file_name.ends_with(".tres") || file_name.ends_with(".godot") || file_name.ends_with(".cs") || file_name.ends_with(".csproj"))
+ proper_extension = true;
+
+ if (proper_extension) {
+ collected_files.append(current_dir + file_name);
+ }
+ }
+ file_name = dir.get_next();
+ }
+ } else {
+ print_verbose("Failed to open " + path);
+ }
+ }
+ return collected_files;
+}
+
+bool ProjectConverter3To4::test_conversion_single_additional(String name, String expected, void (ProjectConverter3To4::*func)(String &), String what) {
+ String got = name;
+ (this->*func)(got);
+ if (expected != got) {
+ ERR_PRINT("Failed to convert " + what + " `" + name + "` to `" + expected + "`, got instead `" + got + "`");
+ return false;
+ }
+
+ return true;
+}
+
+bool ProjectConverter3To4::test_conversion_single_normal(String name, String expected, const char *array[][2], String what) {
+ String got = name;
+ rename_common(array, got);
+ if (expected != got) {
+ ERR_PRINT("Failed to convert " + what + " `" + name + "` to `" + expected + "`, got instead `" + got + "`");
+ return false;
+ }
+ return true;
+}
+
+// Validate if conversions are proper
+bool ProjectConverter3To4::test_conversion() {
+ bool valid = true;
+
+ valid = valid & test_conversion_single_normal("Spatial", "Node3D", class_renames, "class");
+
+ valid = valid & test_conversion_single_normal("TYPE_REAL", "TYPE_FLOAT", enum_renames, "enum");
+
+ valid = valid & test_conversion_single_normal("can_instance", "can_instantiate", gdscript_function_renames, "gdscript function");
+
+ valid = valid & test_conversion_single_normal("CanInstance", "CanInstantiate", csharp_function_renames, "csharp function");
+
+ valid = valid & test_conversion_single_normal("translation", "position", gdscript_properties_renames, "gdscript property");
+
+ valid = valid & test_conversion_single_normal("Translation", "Position", csharp_properties_renames, "csharp property");
+
+ valid = valid & test_conversion_single_normal("NORMALMAP", "NORMAL_MAP", shaders_renames, "shader");
+
+ valid = valid & test_conversion_single_normal("text_entered", "text_submitted", gdscript_signals_renames, "gdscript signal");
+
+ valid = valid & test_conversion_single_normal("TextEntered", "TextSubmitted", csharp_signals_renames, "csharp signal");
+
+ valid = valid & test_conversion_single_normal("audio/channel_disable_threshold_db", "audio/buses/channel_disable_threshold_db", project_settings_renames, "project setting");
+
+ valid = valid & test_conversion_single_normal("Transform", "Transform3D", builtin_types_renames, "builtin type");
+
+ // Custom Renames
+
+ valid = valid & test_conversion_single_additional("(Connect(A,B,C,D,E,F,G) != OK):", "(Connect(A,new Callable(B,C),D,E,F,G) != OK):", &ProjectConverter3To4::rename_csharp_functions, "custom rename csharp");
+ valid = valid & test_conversion_single_additional("(Disconnect(A,B,C) != OK):", "(Disconnect(A,new Callable(B,C)) != OK):", &ProjectConverter3To4::rename_csharp_functions, "custom rename csharp");
+ valid = valid & test_conversion_single_additional("(IsConnected(A,B,C) != OK):", "(IsConnected(A,new Callable(B,C)) != OK):", &ProjectConverter3To4::rename_csharp_functions, "custom rename");
+
+ valid = valid & test_conversion_single_additional("OS.window_fullscreen = Settings.fullscreen", "ProjectSettings.set(\"display/window/size/fullscreen\", Settings.fullscreen)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+
+ valid = valid & test_conversion_single_additional("\tvar aa = roman(r.move_and_slide( a, b, c, d, e, f )) # Roman", "\tr.set_motion_velocity(a)\n\tr.set_up_direction(b)\n\tr.set_floor_stop_on_slope_enabled(c)\n\tr.set_max_slides(d)\n\tr.set_floor_max_angle(e)\n\t# TODOConverter40 infinite_inertia were removed in Godot 4.0 - previous value `f`\n\tvar aa = roman(r.move_and_slide()) # Roman", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional("\tvar aa = roman(r.move_and_slide_with_snap( a, g, b, c, d, e, f )) # Roman", "\tr.set_motion_velocity(a)\n\t# TODOConverter40 looks that snap in Godot 4.0 is float, not vector like in Godot 3 - previous value `g`\n\tr.set_up_direction(b)\n\tr.set_floor_stop_on_slope_enabled(c)\n\tr.set_max_slides(d)\n\tr.set_floor_max_angle(e)\n\t# TODOConverter40 infinite_inertia were removed in Godot 4.0 - previous value `f`\n\tvar aa = roman(r.move_and_slide()) # Roman", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+
+ valid = valid & test_conversion_single_additional("list_dir_begin( a , b )", "list_dir_begin() # TODOGODOT4 fill missing arguments https://github.com/godotengine/godot/pull/40547", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional("list_dir_begin( a )", "list_dir_begin() # TODOGODOT4 fill missing arguments https://github.com/godotengine/godot/pull/40547", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional("list_dir_begin( )", "list_dir_begin() # TODOGODOT4 fill missing arguments https://github.com/godotengine/godot/pull/40547", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+
+ valid = valid & test_conversion_single_additional("sort_custom( a , b )", "sort_custom(Callable(a,b))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+
+ valid = valid & test_conversion_single_additional("func c(var a, var b)", "func c(a, b)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+
+ valid = valid & test_conversion_single_additional("draw_line(1, 2, 3, 4, 5)", "draw_line(1,2,3,4)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+
+ valid = valid & test_conversion_single_additional("\timage.lock()", "\tfalse # image.lock() # TODOConverter40, image no longer require locking, `false` helps to not broke one line if/else, so can be freely removed", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional("\timage.unlock()", "\tfalse # image.unlock() # TODOConverter40, image no longer require locking, `false` helps to not broke one line if/else, so can be freely removed", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional("\troman.image.unlock()", "\tfalse # roman.image.unlock() # TODOConverter40, image no longer require locking, `false` helps to not broke one line if/else, so can be freely removed", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional("\tmtx.lock()", "\tmtx.lock()", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional("\tmutex.unlock()", "\tmutex.unlock()", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+
+ valid = valid & test_conversion_single_additional("\nonready", "\n@onready", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword");
+ valid = valid & test_conversion_single_additional("onready", "@onready", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword");
+ valid = valid & test_conversion_single_additional(" onready", " onready", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword");
+ valid = valid & test_conversion_single_additional("\nexport", "\n@export", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword");
+ valid = valid & test_conversion_single_additional("\texport", "\t@export", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword");
+ valid = valid & test_conversion_single_additional("\texport_dialog", "\texport_dialog", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword");
+ valid = valid & test_conversion_single_additional("export", "@export", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword");
+ valid = valid & test_conversion_single_additional(" export", " export", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword");
+ valid = valid & test_conversion_single_additional("tool", "@tool", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword");
+ valid = valid & test_conversion_single_additional("\n tool", "\n tool", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword");
+ valid = valid & test_conversion_single_additional("\n\ntool", "\n\n@tool", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword");
+ valid = valid & test_conversion_single_additional("\n\nmaster func", "\n\n@rpc(any) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword");
+ valid = valid & test_conversion_single_additional("\n\npuppet func", "\n\n@rpc(auth) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword");
+ valid = valid & test_conversion_single_additional("\n\nremote func", "\n\n@rpc(any) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword");
+ valid = valid & test_conversion_single_additional("\n\nremotesync func", "\n\n@rpc(any,sync) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword");
+ valid = valid & test_conversion_single_additional("\n\nsync func", "\n\n@rpc(any,sync) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword");
+ valid = valid & test_conversion_single_additional("\n\npuppetsync func", "\n\n@rpc(auth,sync) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword");
+ valid = valid & test_conversion_single_additional("\n\nmastersync func", "\n\n@rpc(any,sync) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword");
+
+ valid = valid & test_conversion_single_additional("var size : Vector2 = Vector2() setget set_function , get_function", "var size : Vector2 = Vector2() :\n get:\n return size # TODOConverter40 Copy here content of get_function\n set(mod_value):\n mod_value # TODOConverter40 Copy here content of set_function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional("var size : Vector2 = Vector2() setget set_function , ", "var size : Vector2 = Vector2() :\n get:\n return size # TODOConverter40 Non existent get function \n set(mod_value):\n mod_value # TODOConverter40 Copy here content of set_function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional("var size : Vector2 = Vector2() setget set_function", "var size : Vector2 = Vector2() :\n get:\n return size # TODOConverter40 Non existent get function \n set(mod_value):\n mod_value # TODOConverter40 Copy here content of set_function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional("var size : Vector2 = Vector2() setget , get_function", "var size : Vector2 = Vector2() :\n get:\n return size # TODOConverter40 Copy here content of get_function \n set(mod_value):\n mod_value # TODOConverter40 Non existent set function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+
+ valid = valid & test_conversion_single_additional("get_node(@", "get_node(", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+
+ valid = valid & test_conversion_single_additional("yield(this, \"timeout\")", "await this.timeout", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+
+ valid = valid & test_conversion_single_additional(" Transform.xform(Vector3(a,b,c)) ", " Transform * Vector3(a,b,c) ", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional(" Transform.xform_inv(Vector3(a,b,c)) ", " Vector3(a,b,c) * Transform ", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+
+ valid = valid & test_conversion_single_additional("export(float) var lifetime = 3.0", "export var lifetime: float = 3.0", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional("export(String, 'AnonymousPro', 'CourierPrime') var _font_name = 'AnonymousPro'", "export var _font_name = 'AnonymousPro' # (String, 'AnonymousPro', 'CourierPrime')", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); // TODO, this is only a workaround
+ valid = valid & test_conversion_single_additional("export(PackedScene) var mob_scene", "export var mob_scene: PackedScene", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+
+ valid = valid & test_conversion_single_additional("var d = parse_json(roman(sfs))", "var test_json_conv = JSON.new()\ntest_json_conv.parse(roman(sfs))\nvar d = test_json_conv.get_data()", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+
+ valid = valid & test_conversion_single_additional("to_json( AA ) szon", "JSON.new().stringify( AA ) szon", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional("s to_json", "s JSON.new().stringify", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional("AF to_json2", "AF to_json2", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional("var rr = JSON.parse(a)", "var test_json_conv = JSON.new()\ntest_json_conv.parse(a)\nvar rr = test_json_conv.get_data()", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+
+ valid = valid & test_conversion_single_additional("empty()", "is_empty()", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional(".empty", ".empty", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+
+ valid = valid & test_conversion_single_additional(").roman(", ").roman(", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional("\t.roman(", "\tsuper.roman(", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional(" .roman(", " super.roman(", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional(".1", ".1", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional(" .1", " .1", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional("'.'", "'.'", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional("'.a'", "'.a'", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional("\t._input(_event)", "\tsuper._input(_event)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+
+ valid = valid & test_conversion_single_additional("(start(A,B,C,D,E,F,G) != OK):", "(start(A,Callable(B,C),D,E,F,G) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional("(connect(A,B,C,D,E,F,G) != OK):", "(connect(A,Callable(B,C),D,E,F,G) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional("(connect(A,B,C) != OK):", "(connect(A,Callable(B,C)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional("disconnect(A,B,C) != OK):", "disconnect(A,Callable(B,C)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional("is_connected(A,B,C) != OK):", "is_connected(A,Callable(B,C)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional("is_connected(A,B,C))", "is_connected(A,Callable(B,C)))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+
+ valid = valid & test_conversion_single_additional("func _init(p_x:int)->void:", "func _init(p_x:int):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional("q_PackedDataContainer._iter_init(variable1)", "q_PackedDataContainer._iter_init(variable1)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+
+ valid = valid & test_conversion_single_additional("assert(speed < 20, str(randi()%10))", "assert(speed < 20) #,str(randi()%10))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional("assert(speed < 2)", "assert(speed < 2)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional("assert(false, \"Missing type --\" + str(argument.type) + \"--, needs to be added to project\")", "assert(false) #,\"Missing type --\" + str(argument.type) + \"--, needs to be added to project\")", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+
+ valid = valid & test_conversion_single_additional("create_from_image(aa, bb)", "create_from_image(aa) #,bb", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional("q_ImageTexture.create_from_image(variable1, variable2)", "q_ImageTexture.create_from_image(variable1) #,variable2", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+
+ valid = valid & test_conversion_single_additional("set_cell_item(a, b, c, d ,e) # AA", "set_cell_item( Vector3(a,b,c) ,d,e) # AA", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional("set_cell_item(a, b)", "set_cell_item(a, b)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional("get_cell_item_orientation(a, b,c)", "get_cell_item_orientation(Vector3i(a,b,c))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional("get_cell_item(a, b,c)", "get_cell_item(Vector3i(a,b,c))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+
+ valid = valid & test_conversion_single_additional("PackedStringArray(req_godot).join('.')", "'.'.join(PackedStringArray(req_godot))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional("=PackedStringArray(req_godot).join('.')", "='.'.join(PackedStringArray(req_godot))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+
+ valid = valid & test_conversion_single_additional(" aa", " aa", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional("\taa", "\taa", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional("\t aa", "\taa", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional(" \taa", " \taa", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+
+ valid = valid & test_conversion_single_additional("AAA Color.white AF", "AAA Color.WHITE AF", &ProjectConverter3To4::rename_enums, "custom rename");
+
+ // Custom rule conversion
+ {
+ String from = "instance";
+ String to = "instantiate";
+ String name = "AA.instance()";
+ String got = "AA.instance()";
+ String expected = "AA.instantiate()";
+ custom_rename(got, from, to);
+ if (got != expected) {
+ ERR_PRINT("Failed to convert custom rename `" + name + "` to `" + expected + "`, got instead `" + got + "`");
+ }
+ valid = valid & (got == expected);
+ }
+
+ // get_object_of_execution
+ {
+ { String base = "var roman = kieliszek.";
+ String expected = "kieliszek.";
+ String got = get_object_of_execution(base);
+ if (got != expected) {
+ ERR_PRINT("Failed to get proper data from get_object_of_execution `" + base + "` should return `" + expected + "`(" + itos(expected.size()) + "), got instead `" + got + "`(" + itos(got.size()) + ")");
+ }
+ valid = valid & (got == expected);
+}
+{
+ String base = "r.";
+ String expected = "r.";
+ String got = get_object_of_execution(base);
+ if (got != expected) {
+ ERR_PRINT("Failed to get proper data from get_object_of_execution `" + base + "` should return `" + expected + "`(" + itos(expected.size()) + "), got instead `" + got + "`(" + itos(got.size()) + ")");
+ }
+ valid = valid & (got == expected);
+}
+{
+ String base = "mortadela(";
+ String expected = "";
+ String got = get_object_of_execution(base);
+ if (got != expected) {
+ ERR_PRINT("Failed to get proper data from get_object_of_execution `" + base + "` should return `" + expected + "`(" + itos(expected.size()) + "), got instead `" + got + "`(" + itos(got.size()) + ")");
+ }
+ valid = valid & (got == expected);
+}
+}
+// get_starting_space
+{
+ String base = "\t\t\t var roman = kieliszek.";
+ String expected = "\t\t\t";
+ String got = get_starting_space(base);
+ if (got != expected) {
+ ERR_PRINT("Failed to get proper data from get_starting_space `" + base + "` should return `" + expected + "`(" + itos(expected.size()) + "), got instead `" + got + "`(" + itos(got.size()) + ")");
+ }
+ valid = valid & (got == expected);
+}
+// Parse Arguments
+{
+ String line = "( )";
+ Vector<String> got_vector = parse_arguments(line);
+ String got = "";
+ String expected = "";
+ for (String &part : got_vector) {
+ got += part + "|||";
+ }
+ if (got != expected) {
+ ERR_PRINT("Failed to get proper data from parse_arguments `" + line + "` should return `" + expected + "`(" + itos(expected.size()) + "), got instead `" + got + "`(" + itos(got.size()) + ")");
+ }
+ valid = valid & (got == expected);
+}
+{
+ String line = "(a , b , c)";
+ Vector<String> got_vector = parse_arguments(line);
+ String got = "";
+ String expected = "a|||b|||c|||";
+ for (String &part : got_vector) {
+ got += part + "|||";
+ }
+ if (got != expected) {
+ ERR_PRINT("Failed to get proper data from parse_arguments `" + line + "` should return `" + expected + "`(" + itos(expected.size()) + "), got instead `" + got + "`(" + itos(got.size()) + ")");
+ }
+ valid = valid & (got == expected);
+}
+{
+ String line = "(a , \"b,\" , c)";
+ Vector<String> got_vector = parse_arguments(line);
+ String got = "";
+ String expected = "a|||\"b,\"|||c|||";
+ for (String &part : got_vector) {
+ got += part + "|||";
+ }
+ if (got != expected) {
+ ERR_PRINT("Failed to get proper data from parse_arguments `" + line + "` should return `" + expected + "`(" + itos(expected.size()) + "), got instead `" + got + "`(" + itos(got.size()) + ")");
+ }
+ valid = valid & (got == expected);
+}
+{
+ String line = "(a , \"(,),,,,\" , c)";
+ Vector<String> got_vector = parse_arguments(line);
+ String got = "";
+ String expected = "a|||\"(,),,,,\"|||c|||";
+ for (String &part : got_vector) {
+ got += part + "|||";
+ }
+ if (got != expected) {
+ ERR_PRINT("Failed to get proper data from parse_arguments `" + line + "` should return `" + expected + "`(" + itos(expected.size()) + "), got instead `" + got + "`(" + itos(got.size()) + ")");
+ }
+ valid = valid & (got == expected);
+}
+
+return valid;
+}
+
+// Validate in all arrays if names don't do cyclic renames `Node` -> `Node2D` | `Node2D` -> `2DNode`
+bool ProjectConverter3To4::test_array_names() {
+ bool valid = true;
+ Vector<String> names = Vector<String>();
+
+ // Validate if all classes are valid
+ {
+ int current_index = 0;
+ while (class_renames[current_index][0]) {
+ const String old_class = class_renames[current_index][0];
+ const String new_class = class_renames[current_index][1];
+
+ // Light2D, Texture, Viewport are special classes(probably virtual ones)
+ if (ClassDB::class_exists(StringName(old_class)) && old_class != "Light2D" && old_class != "Texture" && old_class != "Viewport") {
+ ERR_PRINT(String("Class `") + old_class + "` exists in Godot 4.0, so cannot be renamed to something else.");
+ valid = false; // This probably should be only a warning, but not 100% sure - this would need to be added to CI
+ }
+
+ // Callable is special class, to which normal classes may be renamed
+ if (!ClassDB::class_exists(StringName(new_class)) && new_class != "Callable") {
+ ERR_PRINT(String("Class `") + new_class + "` doesn't exists in Godot 4.0, so cannot be used in convertion.");
+ valid = false; // This probably should be only a warning, but not 100% sure - this would need to be added to CI
+ }
+ current_index++;
+ }
+ }
+
+ // // TODO To be able to fully work, it needs https://github.com/godotengine/godot/pull/49053
+ // // TODO this needs to be changed to hashset when available https://github.com/godotengine/godot-proposals/issues/867, to speedup searchng
+ // {
+ // OrderedHashMap<String, bool> all_functions;
+
+ // List<StringName> classes_list;
+ // ClassDB::get_class_list(&classes_list);
+ // for (StringName &name_of_class : classes_list) {
+ // List<MethodInfo> method_list;
+ // ClassDB::get_method_list(name_of_class, &method_list, true);
+ // for (MethodInfo &function_data : method_list) {
+ // if (!all_functions.has(function_data.name)) {
+ // all_functions.insert(function_data.name, false);
+ // }
+ // }
+ // }
+
+ // for (int type = Variant::Type::NIL + 1; type < Variant::Type::VARIANT_MAX; type++) {
+ // List<MethodInfo> method_list;
+ // Variant::get_method_list_by_type(&method_list, Variant::Type(type));
+ // for (MethodInfo &function_data : method_list) {
+ // if (!all_functions.has(function_data.name)) {
+ // all_functions.insert(function_data.name, false);
+ // }
+ // }
+ // }
+
+ // int current_element = 0;
+ // while (gdscript_function_renames[current_element][0] != nullptr) {
+ // if (!all_functions.has(gdscript_function_renames[current_element][1])) {
+ // ERR_PRINT(String("Missing gdscript function in pair (") + gdscript_function_renames[current_element][0] + " - ===> " + gdscript_function_renames[current_element][1] + " <===)");
+ // valid = false;
+ // }
+ // // // DEBUG, disable below after tests
+ // // if (all_functions.has(gdscript_function_renames[current_element][0])) {
+ // // String used_in_classes = "";
+ // //
+ // // for (StringName &name_of_class : classes_list) {
+ // // List<MethodInfo> method_list;
+ // // ClassDB::get_method_list(name_of_class, &method_list, true);
+ // // for (MethodInfo &function_data : method_list) {
+ // // if (function_data.name == gdscript_function_renames[current_element][0]) {
+ // // used_in_classes += String(name_of_class) + ", ";
+ // // }
+ // // }
+ // // }
+ // // for (int type = Variant::Type::NIL + 1; type < Variant::Type::VARIANT_MAX; type++) {
+ // // List<MethodInfo> method_list;
+ // // Variant::get_method_list_by_type(&method_list, Variant::Type(type));
+ // // for (MethodInfo &function_data : method_list) {
+ // // if (function_data.name == gdscript_function_renames[current_element][0]) {
+ // // used_in_classes += Variant::get_type_name(Variant::Type(type)) + ", ";
+ // // }
+ // // }
+ // // }
+ // // used_in_classes = used_in_classes.trim_suffix(", ");
+ // //
+ // // WARN_PRINT(String("Godot contains function which will be renamed in pair ( ===> ") + gdscript_function_renames[current_element][0] + " <=== - " + gdscript_function_renames[current_element][1] + ") in class " + used_in_classes + " - check for possible invalid rule.");
+ // // }
+ // current_element++;
+ // }
+ // }
+
+ valid = valid & test_single_array(enum_renames);
+ valid = valid & test_single_array(class_renames, true);
+ valid = valid & test_single_array(gdscript_function_renames, true);
+ valid = valid & test_single_array(csharp_function_renames, true);
+ valid = valid & test_single_array(gdscript_properties_renames);
+ valid = valid & test_single_array(csharp_properties_renames);
+ valid = valid & test_single_array(shaders_renames);
+ valid = valid & test_single_array(gdscript_signals_renames);
+ valid = valid & test_single_array(project_settings_renames);
+ valid = valid & test_single_array(builtin_types_renames);
+ valid = valid & test_single_array(colors_renames);
+
+ return valid;
+}
+
+// Validate in one array if names don't do cyclic renames `Node` -> `Node2D` | `Node2D` -> `2DNode`
+// Also checks if in name contains spaces at the end or beggining
+bool ProjectConverter3To4::test_single_array(const char *array[][2], bool ignore_second_check) {
+ bool valid = true;
+ int current_index = 0;
+ Vector<String> names = Vector<String>();
+
+ while (array[current_index][0]) {
+ if (String(array[current_index][0]).begins_with(" ") || String(array[current_index][0]).ends_with(" ")) {
+ {
+ ERR_PRINT(String("Entry \"") + array[current_index][0] + "\" ends or stars with space.");
+ valid = false;
+ }
+ }
+ if (names.has(array[current_index][0])) {
+ ERR_PRINT(String("Found duplicated things, pair ( -> ") + array[current_index][0] + " , " + array[current_index][1] + ")");
+ valid = false;
+ }
+ names.append(array[current_index][0]);
+
+ if (String(array[current_index][1]).begins_with(" ") || String(array[current_index][1]).ends_with(" ")) {
+ {
+ ERR_PRINT(String("Entry \"") + array[current_index][1] + "\" ends or stars with space.");
+ valid = false;
+ }
+ }
+ if (names.has(array[current_index][1])) {
+ ERR_PRINT(String("Found duplicated things, pair (") + array[current_index][0] + " , ->" + array[current_index][1] + ")");
+ valid = false;
+ }
+ if (!ignore_second_check) {
+ names.append(array[current_index][1]);
+ }
+ current_index++;
+ }
+ return valid;
+};
+
+// Returns arguments from given function execution, this cannot be really done as regex
+// `abc(d,e(f,g),h)` -> [d], [e(f,g)], [h]
+Vector<String> ProjectConverter3To4::parse_arguments(const String &line) {
+ Vector<String> parts;
+ int string_size = line.length();
+ int current_index = 0;
+ int start_part = 0; // Index of beginning of start par
+ int parts_counter = 0;
+ char32_t previous_character = '\0';
+ bool is_inside_string = false; // if true, it ignore this 3 characters ( , ) inside string
+
+ if (line.count("(") != line.count(")")) {
+ ERR_PRINT("Bug: substring should have equal number of open and close parenthess - `" + line + "`");
+ return parts;
+ }
+
+ while (current_index < string_size) {
+ char32_t character = line.get(current_index);
+ switch (character) {
+ case '(': {
+ parts_counter++;
+ if (parts_counter == 1 && !is_inside_string) {
+ start_part = current_index;
+ }
+ break;
+ };
+ case ')': {
+ parts_counter--;
+ if (parts_counter == 0 && !is_inside_string) {
+ parts.append(line.substr(start_part + 1, current_index - start_part - 1));
+ start_part = current_index;
+ }
+ break;
+ };
+ case ',': {
+ if (parts_counter == 1 && !is_inside_string) {
+ parts.append(line.substr(start_part + 1, current_index - start_part - 1));
+ start_part = current_index;
+ }
+ break;
+ };
+ case '"': {
+ if (previous_character != '\\')
+ is_inside_string = !is_inside_string;
+ }
+ }
+ current_index++;
+ previous_character = character;
+ }
+
+ Vector<String> clean_parts;
+ for (String &part : parts) {
+ part = part.strip_edges();
+ if (!part.is_empty()) {
+ clean_parts.append(part);
+ }
+ }
+
+ return clean_parts;
+}
+
+// Finds latest parenthess owned by function
+// `function(abc(a,b),DD)):` finds this parenthess `function(abc(a,b),DD => ) <= ):`
+int ProjectConverter3To4::get_end_parenthess(const String &line) const {
+ int current_index = 0;
+ int current_state = 0;
+ while (line.length() > current_index) {
+ char32_t character = line.get(current_index);
+ if (character == '(') {
+ current_state++;
+ }
+ if (character == ')') {
+ current_state--;
+ if (current_state == 0) {
+ return current_index;
+ }
+ }
+ current_index++;
+ }
+ return -1;
+}
+
+// Connects arguments from vector to one string
+// Needed when after processing e.g. 2 arguments, later arguments are not changed in any way
+String ProjectConverter3To4::connect_arguments(const Vector<String> &arguments, int from, int to) const {
+ if (to == -1) {
+ to = arguments.size();
+ }
+
+ String value;
+ if (arguments.size() > 0 && from != 0 && from < to) {
+ value = ",";
+ }
+
+ for (int i = from; i < to; i++) {
+ value += arguments[i];
+ if (i != to - 1) {
+ value += ',';
+ }
+ }
+ return value;
+}
+
+// Return spaces or tabs which starts line e.g. `\t\tmove_this` will return `\t\t`
+String ProjectConverter3To4::get_starting_space(const String &line) const {
+ String empty_space;
+ int current_character = 0;
+
+ if (line.is_empty()) {
+ return empty_space;
+ }
+
+ if (line[0] == ' ') {
+ while (current_character < line.size()) {
+ if (line[current_character] == ' ') {
+ empty_space += ' ';
+ current_character++;
+ } else {
+ break;
+ }
+ }
+ }
+ if (line[0] == '\t') {
+ while (current_character < line.size()) {
+ if (line[current_character] == '\t') {
+ empty_space += '\t';
+ current_character++;
+ } else {
+ break;
+ }
+ }
+ }
+ return empty_space;
+}
+
+// Return object which execute specific function
+// e.g. in `var roman = kieliszek.funkcja()` to this function is passed everything before function which we want to check
+// so it is `var roman = kieliszek.` and this function return `kieliszek.`
+String ProjectConverter3To4::get_object_of_execution(const String &line) const {
+ int end = line.size() - 1; // Last one is \0
+ int start = end - 1;
+
+ while (start >= 0) {
+ char32_t character = line[start];
+ if ((character >= 'A' && character <= 'Z') || (character >= 'a' && character <= 'z') || character == '.' || character == '_') {
+ if (start == 0) {
+ break;
+ }
+ start--;
+ continue;
+ } else {
+ start++; // Found invalid character, needs to be ignored
+ break;
+ }
+ }
+ return line.substr(start, (end - start));
+}
+
+void ProjectConverter3To4::rename_enums(String &file_content) {
+ int current_index = 0;
+
+ // Rename colors
+ if (file_content.find("Color.") != -1) {
+ while (colors_renames[current_index][0]) {
+ RegEx reg = RegEx(String("\\bColor.") + colors_renames[current_index][0] + "\\b");
+ CRASH_COND(!reg.is_valid());
+ file_content = reg.sub(file_content, String("Color.") + colors_renames[current_index][1], true);
+ current_index++;
+ }
+ }
+};
+
+Vector<String> ProjectConverter3To4::check_for_rename_enums(Vector<String> &file_content) {
+ int current_index = 0;
+
+ Vector<String> found_things;
+
+ // Rename colors
+ if (file_content.find("Color.") != -1) {
+ while (colors_renames[current_index][0]) {
+ RegEx reg = RegEx(String("\\bColor.") + colors_renames[current_index][0] + "\\b");
+ CRASH_COND(!reg.is_valid());
+
+ int current_line = 1;
+ for (String &line : file_content) {
+ Array reg_match = reg.search_all(line);
+ if (reg_match.size() > 0) {
+ found_things.append(line_formatter(current_line, colors_renames[current_index][0], colors_renames[current_index][1], line));
+ }
+ current_line++;
+ }
+ current_index++;
+ }
+ }
+
+ return found_things;
+}
+
+void ProjectConverter3To4::rename_classes(String &file_content) {
+ int current_index = 0;
+
+ // TODO Maybe it is better way to not rename gd, tscn and other files which are named are classes
+ while (class_renames[current_index][0]) {
+ // Begin renaming workaround `Resource.gd` -> `RefCounter.gd`
+ RegEx reg_before = RegEx(String("\\b") + class_renames[current_index][0] + ".tscn\\b");
+ CRASH_COND(!reg_before.is_valid());
+ file_content = reg_before.sub(file_content, "TEMP_RENAMED_CLASS.tscn", true);
+ RegEx reg_before2 = RegEx(String("\\b") + class_renames[current_index][0] + ".gd\\b");
+ CRASH_COND(!reg_before2.is_valid());
+ file_content = reg_before2.sub(file_content, "TEMP_RENAMED_CLASS.gd", true);
+ RegEx reg_before3 = RegEx(String("\\b") + class_renames[current_index][0] + ".shader\\b");
+ CRASH_COND(!reg_before3.is_valid());
+ file_content = reg_before3.sub(file_content, "TEMP_RENAMED_CLASS.gd", true);
+ // End
+
+ RegEx reg = RegEx(String("\\b") + class_renames[current_index][0] + "\\b");
+ CRASH_COND(!reg.is_valid());
+ file_content = reg.sub(file_content, class_renames[current_index][1], true);
+
+ // Begin renaming workaround `Resource.gd` -> `RefCounter.gd`
+ RegEx reg_after = RegEx("\\bTEMP_RENAMED_CLASS.tscn\\b");
+ CRASH_COND(!reg_after.is_valid());
+ file_content = reg_after.sub(file_content, String(class_renames[current_index][0]) + ".tscn", true);
+ RegEx reg_after2 = RegEx("\\bTEMP_RENAMED_CLASS.gd\\b");
+ CRASH_COND(!reg_after2.is_valid());
+ file_content = reg_after2.sub(file_content, String(class_renames[current_index][0]) + ".gd", true);
+ RegEx reg_after3 = RegEx("\\bTEMP_RENAMED_CLASS.gd\\b");
+ CRASH_COND(!reg_after3.is_valid());
+ file_content = reg_after3.sub(file_content, String(class_renames[current_index][0]) + ".shader", true);
+ // End
+
+ current_index++;
+ }
+
+ // OS.get_ticks_msec -> Time.get_ticks_msec
+ RegEx reg_time1 = RegEx("OS.get_ticks_msec");
+ CRASH_COND(!reg_time1.is_valid());
+ file_content = reg_time1.sub(file_content, "Time.get_ticks_msec", true);
+ RegEx reg_time2 = RegEx("OS.get_ticks_usec");
+ CRASH_COND(!reg_time2.is_valid());
+ file_content = reg_time2.sub(file_content, "Time.get_ticks_usec", true);
+};
+
+Vector<String> ProjectConverter3To4::check_for_rename_classes(Vector<String> &file_content) {
+ int current_index = 0;
+
+ Vector<String> found_things;
+
+ while (class_renames[current_index][0]) {
+ RegEx reg_before = RegEx(String("\\b") + class_renames[current_index][0] + ".tscn\\b");
+ CRASH_COND(!reg_before.is_valid());
+ RegEx reg_before2 = RegEx(String("\\b") + class_renames[current_index][0] + ".gd\\b");
+ CRASH_COND(!reg_before2.is_valid());
+
+ RegEx reg = RegEx(String("\\b") + class_renames[current_index][0] + "\\b");
+ CRASH_COND(!reg.is_valid());
+
+ int current_line = 1;
+ for (String &line : file_content) {
+ line = reg_before.sub(line, "TEMP_RENAMED_CLASS.tscn", true);
+ line = reg_before2.sub(line, "TEMP_RENAMED_CLASS.gd", true);
+
+ Array reg_match = reg.search_all(line);
+ if (reg_match.size() > 0) {
+ found_things.append(line_formatter(current_line, class_renames[current_index][0], class_renames[current_index][1], line));
+ }
+ current_line++;
+ }
+ current_index++;
+ }
+
+ // TODO OS -> TIME
+ int current_line = 1;
+ RegEx reg_time1 = RegEx("OS.get_ticks_msec");
+ CRASH_COND(!reg_time1.is_valid());
+ RegEx reg_time2 = RegEx("OS.get_ticks_usec");
+ CRASH_COND(!reg_time2.is_valid());
+ for (String &line : file_content) {
+ String old = line;
+
+ line = reg_time1.sub(line, "Time.get_ticks_msec", true);
+ line = reg_time2.sub(line, "Time.get_ticks_usec", true);
+
+ if (old != line) {
+ found_things.append(simple_line_formatter(current_line, old, line));
+ }
+ current_line++;
+ }
+ return found_things;
+}
+
+void ProjectConverter3To4::rename_gdscript_functions(String &file_content) {
+ // Custom renaming, each rule needs to be set manually
+ // Don't forget to put validate each rule in validate_conversion function
+ Vector<String> lines = file_content.split("\n");
+
+ RegEx reg_is_empty = RegEx("\\bempty\\(");
+ RegEx reg_super = RegEx("([\t ])\\.([a-zA-Z_])");
+ RegEx reg_json_to = RegEx("\\bto_json\\b");
+ RegEx reg_json_parse = RegEx("([\t]{0,})([^\n]+)parse_json\\(([^\n]+)");
+ RegEx reg_json_non_new = RegEx("([\t]{0,})([^\n]+)JSON\\.parse\\(([^\n]+)");
+ RegEx reg_export = RegEx("export\\(([a-zA-Z0-9_]+)\\)[ ]+var[ ]+([a-zA-Z0-9_]+)");
+ RegEx reg_export_advanced = RegEx("export\\(([^)^\n]+)\\)[ ]+var[ ]+([a-zA-Z0-9_]+)([^\n]+)");
+ RegEx reg_setget_setget = RegEx("var[ ]+([a-zA-Z0-9_]+)([^\n]+)setget[ \t]+([a-zA-Z0-9_]+)[ \t]*,[ \t]*([a-zA-Z0-9_]+)");
+ RegEx reg_setget_set = RegEx("var[ ]+([a-zA-Z0-9_]+)([^\n]+)setget[ \t]+([a-zA-Z0-9_]+)[ \t]*[,]*[^a-z^A-Z^0-9^_]*$");
+ RegEx reg_setget_get = RegEx("var[ ]+([a-zA-Z0-9_]+)([^\n]+)setget[ \t]+,[ \t]*([a-zA-Z0-9_]+)[ \t]*$");
+ RegEx reg_join = RegEx("([\\(\\)a-zA-Z0-9_]+)\\.join\\(([^\n^\\)]+)\\)");
+ RegEx reg_mixed_tab_space = RegEx("([\t]+)([ ]+)");
+ RegEx reg_image_lock = RegEx("([a-zA-Z0-9_\\.]+)\\.lock\\(\\)");
+ RegEx reg_image_unlock = RegEx("([a-zA-Z0-9_\\.]+)\\.unlock\\(\\)");
+ RegEx reg_os_fullscreen = RegEx("OS.window_fullscreen[= ]+([^#^\n]+)");
+
+ CRASH_COND(!reg_is_empty.is_valid());
+ CRASH_COND(!reg_super.is_valid());
+ CRASH_COND(!reg_json_to.is_valid());
+ CRASH_COND(!reg_json_parse.is_valid());
+ CRASH_COND(!reg_json_non_new.is_valid());
+ CRASH_COND(!reg_export.is_valid());
+ CRASH_COND(!reg_export_advanced.is_valid());
+ CRASH_COND(!reg_setget_setget.is_valid());
+ CRASH_COND(!reg_setget_set.is_valid());
+ CRASH_COND(!reg_setget_get.is_valid());
+ CRASH_COND(!reg_join.is_valid());
+ CRASH_COND(!reg_mixed_tab_space.is_valid());
+ CRASH_COND(!reg_image_lock.is_valid());
+ CRASH_COND(!reg_image_unlock.is_valid());
+ CRASH_COND(!reg_os_fullscreen.is_valid());
+
+ for (String &line : lines) {
+ if (line.find("mtx") == -1 && line.find("mutex") == -1 && line.find("Mutex") == -1) {
+ line = reg_image_lock.sub(line, "false # $1.lock() # TODOConverter40, image no longer require locking, `false` helps to not broke one line if/else, so can be freely removed", true);
+ line = reg_image_unlock.sub(line, "false # $1.unlock() # TODOConverter40, image no longer require locking, `false` helps to not broke one line if/else, so can be freely removed", true);
+ }
+
+ // Mixed use of spaces and tabs - tabs as first - TODO, this probably is problem problem, but not sure
+ line = reg_mixed_tab_space.sub(line, "$1", true);
+
+ // PackedStringArray(req_godot).join('.') -> '.'.join(PackedStringArray(req_godot)) PoolStringArray
+ line = reg_join.sub(line, "$2.join($1)", true);
+
+ // -- empty() -> is_empty() Pool*Array
+ line = reg_is_empty.sub(line, "is_empty(", true);
+
+ // -- \t.func() -> \tsuper.func() Object
+ line = reg_super.sub(line, "$1super.$2", true); // TODO, not sure if possible, but for now this brake String text e.g. "Choosen .gitignore" -> "Choosen super.gitignore"
+
+ // -- JSON.parse(a) -> JSON.new().parse(a) etc. JSON
+ line = reg_json_non_new.sub(line, "$1var test_json_conv = JSON.new()\n$1test_json_conv.parse($3\n$1$2test_json_conv.get_data()", true);
+
+ // -- to_json(a) -> JSON.new().stringify(a) Object
+ line = reg_json_to.sub(line, "JSON.new().stringify", true);
+
+ // -- parse_json(a) -> JSON.get_data() etc. Object
+ line = reg_json_parse.sub(line, "$1var test_json_conv = JSON.new()\n$1test_json_conv.parse($3\n$1$2test_json_conv.get_data()", true);
+
+ // -- get_node(@ -> get_node( Node
+ line = line.replace("get_node(@", "get_node(");
+
+ // export(float) var lifetime = 3.0 -> export var lifetime: float = 3.0 GDScript
+ line = reg_export.sub(line, "export var $2: $1");
+
+ // export(String, 'AnonymousPro', 'CourierPrime') var _font_name = 'AnonymousPro' -> export var _font_name = 'AnonymousPro' #(String, 'AnonymousPro', 'CourierPrime') GDScript
+ line = reg_export_advanced.sub(line, "export var $2$3 # ($1)");
+
+ // Setget Setget
+ line = reg_setget_setget.sub(line, "var $1$2:\n\tget:\n\t\treturn $1 # TODOConverter40 Copy here content of $4\n\tset(mod_value):\n\t\tmod_value # TODOConverter40 Copy here content of $3", true);
+
+ // Setget set
+ line = reg_setget_set.sub(line, "var $1$2:\n\tget:\n\t\treturn $1 # TODOConverter40 Non existent get function \n\tset(mod_value):\n\t\tmod_value # TODOConverter40 Copy here content of $3", true);
+
+ // Setget get
+ line = reg_setget_get.sub(line, "var $1$2:\n\tget:\n\t\treturn $1 # TODOConverter40 Copy here content of $3 \n\tset(mod_value):\n\t\tmod_value # TODOConverter40 Non existent set function", true);
+
+ // OS.window_fullscreen = true -> ProjectSettings.set("display/window/size/fullscreen",true)
+ line = reg_os_fullscreen.sub(line, "ProjectSettings.set(\"display/window/size/fullscreen\", $1)", true);
+
+ // -- r.move_and_slide( a, b, c, d, e ) -> r.set_motion_velocity(a) ... r.move_and_slide() KinematicBody
+ if (line.find("move_and_slide(") != -1) {
+ int start = line.find("move_and_slide(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ String base_obj = get_object_of_execution(line.substr(0, start));
+ String starting_space = get_starting_space(line);
+
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() >= 1) {
+ String line_new;
+
+ // motion_velocity
+ line_new += starting_space + base_obj + "set_motion_velocity(" + parts[0] + ")\n";
+
+ // up_direction
+ if (parts.size() >= 2) {
+ line_new += starting_space + base_obj + "set_up_direction(" + parts[1] + ")\n";
+ }
+
+ // stop_on_slope
+ if (parts.size() >= 3) {
+ line_new += starting_space + base_obj + "set_floor_stop_on_slope_enabled(" + parts[2] + ")\n";
+ }
+
+ // max_slides
+ if (parts.size() >= 4) {
+ line_new += starting_space + base_obj + "set_max_slides(" + parts[3] + ")\n";
+ }
+
+ // floor_max_angle
+ if (parts.size() >= 5) {
+ line_new += starting_space + base_obj + "set_floor_max_angle(" + parts[4] + ")\n";
+ }
+
+ // infiinite_interia
+ if (parts.size() >= 6) {
+ line_new += starting_space + "# TODOConverter40 infinite_inertia were removed in Godot 4.0 - previous value `" + parts[5] + "`\n";
+ }
+
+ line = line_new + line.substr(0, start) + "move_and_slide()" + line.substr(end + start);
+ }
+ }
+ }
+
+ // -- r.move_and_slide_with_snap( a, b, c, d, e ) -> r.set_motion_velocity(a) ... r.move_and_slide() KinematicBody
+ if (line.find("move_and_slide_with_snap(") != -1) {
+ int start = line.find("move_and_slide_with_snap(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ String base_obj = get_object_of_execution(line.substr(0, start));
+ String starting_space = get_starting_space(line);
+
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() >= 1) {
+ String line_new;
+
+ // motion_velocity
+ line_new += starting_space + base_obj + "set_motion_velocity(" + parts[0] + ")\n";
+
+ // snap
+ if (parts.size() >= 2) {
+ line_new += starting_space + "# TODOConverter40 looks that snap in Godot 4.0 is float, not vector like in Godot 3 - previous value `" + parts[1] + "`\n";
+ }
+
+ // up_direction
+ if (parts.size() >= 3) {
+ line_new += starting_space + base_obj + "set_up_direction(" + parts[2] + ")\n";
+ }
+
+ // stop_on_slope
+ if (parts.size() >= 4) {
+ line_new += starting_space + base_obj + "set_floor_stop_on_slope_enabled(" + parts[3] + ")\n";
+ }
+
+ // max_slides
+ if (parts.size() >= 5) {
+ line_new += starting_space + base_obj + "set_max_slides(" + parts[4] + ")\n";
+ }
+
+ // floor_max_angle
+ if (parts.size() >= 6) {
+ line_new += starting_space + base_obj + "set_floor_max_angle(" + parts[5] + ")\n";
+ }
+
+ // infiinite_interia
+ if (parts.size() >= 7) {
+ line_new += starting_space + "# TODOConverter40 infinite_inertia were removed in Godot 4.0 - previous value `" + parts[6] + "`\n";
+ }
+
+ line = line_new + line.substr(0, start) + "move_and_slide()" + line.substr(end + start);
+ }
+ }
+ }
+
+ // -- sort_custom( a , b ) -> sort_custom(Callable( a , b )) Object
+ if (line.find("sort_custom(") != -1) {
+ int start = line.find("sort_custom(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() == 2) {
+ line = line.substr(0, start) + "sort_custom(Callable(" + parts[0] + "," + parts[1] + "))" + line.substr(end + start);
+ }
+ }
+ }
+
+ // -- list_dir_begin( ) -> list_dir_begin() Object
+ if (line.find("list_dir_begin(") != -1) {
+ int start = line.find("list_dir_begin(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ line = line.substr(0, start) + "list_dir_begin() " + line.substr(end + start) + "# TODOGODOT4 fill missing arguments https://github.com/godotengine/godot/pull/40547";
+ }
+ }
+
+ // -- draw_line(1,2,3,4,5) -> draw_line(1,2,3,4) CanvasItem
+ if (line.find("draw_line(") != -1) {
+ int start = line.find("draw_line(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() == 5) {
+ line = line.substr(0, start) + "draw_line(" + parts[0] + "," + parts[1] + "," + parts[2] + "," + parts[3] + ")" + line.substr(end + start);
+ }
+ }
+ }
+
+ // -- func c(var a, var b) -> func c(a, b)
+ if (line.find("func ") != -1 && line.find("var ") != -1) {
+ int start = line.find("func ");
+ start = line.substr(start).find("(") + start;
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+
+ String start_string = line.substr(0, start) + "(";
+ for (int i = 0; i < parts.size(); i++) {
+ start_string += parts[i].strip_edges().trim_prefix("var ");
+ if (i != parts.size() - 1) {
+ start_string += ", ";
+ }
+ }
+ line = start_string + ")" + line.substr(end + start);
+ }
+ }
+
+ // -- yield(this, \"timeout\") -> await this.timeout GDScript
+ if (line.find("yield(") != -1) {
+ int start = line.find("yield(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() == 2) {
+ line = line.substr(0, start) + "await " + parts[0] + "." + parts[1].replace("\"", "").replace("\'", "").replace(" ", "") + line.substr(end + start);
+ }
+ }
+ }
+
+ // -- parse_json( AA ) -> TODO Object
+ if (line.find("parse_json(") != -1) {
+ int start = line.find("parse_json(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ line = line.substr(0, start) + "JSON.new().stringify(" + connect_arguments(parts, 0) + ")" + line.substr(end + start);
+ }
+ }
+
+ // -- .xform(Vector3(a,b,c)) -> * Vector3(a,b,c) Transform
+ if (line.find(".xform(") != -1) {
+ int start = line.find(".xform(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() == 1) {
+ line = line.substr(0, start) + " * " + parts[0] + line.substr(end + start);
+ }
+ }
+ }
+
+ // -- .xform_inv(Vector3(a,b,c)) -> * Vector3(a,b,c) Transform
+ if (line.find(".xform_inv(") != -1) {
+ int start = line.find(".xform_inv(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ String object_exec = get_object_of_execution(line.substr(0, start));
+ if (line.find(object_exec + ".xform") != -1) {
+ int start2 = line.find(object_exec + ".xform");
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() == 1) {
+ line = line.substr(0, start2) + parts[0] + " * " + object_exec + line.substr(end + start);
+ }
+ }
+ }
+ }
+
+ // -- connect(,,,things) -> connect(,Callable(,),things) Object
+ if (line.find("connect(") != -1) {
+ int start = line.find("connect(");
+ // Protection from disconnect
+ if (start == 0 || line.get(start - 1) != 's') {
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() >= 3) {
+ line = line.substr(0, start) + "connect(" + parts[0] + ",Callable(" + parts[1] + "," + parts[2] + ")" + connect_arguments(parts, 3) + ")" + line.substr(end + start);
+ }
+ }
+ }
+ }
+ // -- disconnect(a,b,c) -> disconnect(a,Callable(b,c)) Object
+ if (line.find("disconnect(") != -1) {
+ int start = line.find("disconnect(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() == 3) {
+ line = line.substr(0, start) + "disconnect(" + parts[0] + ",Callable(" + parts[1] + "," + parts[2] + "))" + line.substr(end + start);
+ }
+ }
+ }
+ // -- is_connected(a,b,c) -> is_connected(a,Callable(b,c)) Object
+ if (line.find("is_connected(") != -1) {
+ int start = line.find("is_connected(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() == 3) {
+ line = line.substr(0, start) + "is_connected(" + parts[0] + ",Callable(" + parts[1] + "," + parts[2] + "))" + line.substr(end + start);
+ }
+ }
+ }
+ // -- start(a,b,c) -> start(a,Callable(b,c)) Thread
+ if (line.find("start(") != -1) {
+ int start = line.find("start(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() >= 3) {
+ line = line.substr(0, start) + "start(" + parts[0] + ",Callable(" + parts[1] + "," + parts[2] + ")" + connect_arguments(parts, 3) + ")" + line.substr(end + start);
+ }
+ }
+ }
+ // -- func _init(p_x:int)->void: -> func _init(p_x:int): Object # https://github.com/godotengine/godot/issues/50589
+ if (line.find(" _init(") != -1) {
+ int start = line.find(" _init(");
+ int end = line.rfind(":") + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ line = line.substr(0, start) + " _init(" + connect_arguments(parts, 0) + "):" + line.substr(end + start);
+ }
+ }
+ // assert(speed < 20, str(randi()%10)) -> assert(speed < 20) #,str(randi()%10)) GDScript - GDScript bug constant message
+ if (line.find("assert(") != -1) {
+ int start = line.find("assert(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() == 2) {
+ line = line.substr(0, start) + "assert(" + parts[0] + ") " + line.substr(end + start) + "#," + parts[1] + ")";
+ }
+ }
+ }
+ // create_from_image(aa, bb) -> create_from_image(aa) #, bb ImageTexture
+ if (line.find("create_from_image(") != -1) {
+ int start = line.find("create_from_image(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() == 2) {
+ line = line.substr(0, start) + "create_from_image(" + parts[0] + ") " + "#," + parts[1] + line.substr(end + start);
+ }
+ }
+ }
+ // set_cell_item(a, b, c, d ,e) -> set_cell_item(Vector3(a, b, c), d ,e)
+ if (line.find("set_cell_item(") != -1) {
+ int start = line.find("set_cell_item(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() > 2) {
+ line = line.substr(0, start) + "set_cell_item( Vector3(" + parts[0] + "," + parts[1] + "," + parts[2] + ") " + connect_arguments(parts, 3) + ")" + line.substr(end + start);
+ }
+ }
+ }
+ // get_cell_item(a, b, c) -> get_cell_item(Vector3i(a, b, c))
+ if (line.find("get_cell_item(") != -1) {
+ int start = line.find("get_cell_item(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() == 3) {
+ line = line.substr(0, start) + "get_cell_item(Vector3i(" + parts[0] + "," + parts[1] + "," + parts[2] + "))" + line.substr(end + start);
+ }
+ }
+ }
+ // get_cell_item_orientation(a, b, c) -> get_cell_item_orientation(Vector3i(a, b, c))
+ if (line.find("get_cell_item_orientation(") != -1) {
+ int start = line.find("get_cell_item_orientation(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() == 3) {
+ line = line.substr(0, start) + "get_cell_item_orientation(Vector3i(" + parts[0] + "," + parts[1] + "," + parts[2] + "))" + line.substr(end + start);
+ }
+ }
+ }
+
+ // TODO - add_surface_from_arrays - additional 4 argument
+ // ENetMultiplayerPeer.create_client - additional argument
+ // ENetMultiplayerPeer.create_server - additional argument
+ // Translation.get_message (and similar)
+ // TreeItem.move_after() - new argument
+ // TreeItem.move_before() - new argument
+ // UndoRedo.commit_action() - additional argument
+ }
+
+ // Collect vector to string
+ file_content = "";
+ for (int i = 0; i < lines.size(); i++) {
+ file_content += lines[i];
+
+ if (i != lines.size() - 1) {
+ file_content += "\n";
+ }
+ }
+};
+
+// This is almost 1:1 copy of function which rename gdscript functions
+Vector<String> ProjectConverter3To4::check_for_rename_gdscript_functions(Vector<String> &file_content) {
+ int current_line = 1;
+
+ Vector<String> found_things;
+
+ RegEx reg_is_empty = RegEx("\\bempty\\(");
+ RegEx reg_super = RegEx("([\t ])\\.([a-zA-Z_])");
+ RegEx reg_json_to = RegEx("\\bto_json\\b");
+ RegEx reg_json_parse = RegEx("([\t]{0,})([^\n]+)parse_json\\(([^\n]+)");
+ RegEx reg_json_non_new = RegEx("([\t]{0,})([^\n]+)JSON\\.parse\\(([^\n]+)");
+ RegEx reg_export = RegEx("export\\(([a-zA-Z0-9_]+)\\)[ ]+var[ ]+([a-zA-Z0-9_]+)");
+ RegEx reg_export_advanced = RegEx("export\\(([^)^\n]+)\\)[ ]+var[ ]+([a-zA-Z0-9_]+)([^\n]+)");
+ RegEx reg_setget_setget = RegEx("var[ ]+([a-zA-Z0-9_]+)([^\n]+)setget[ \t]+([a-zA-Z0-9_]+)[ \t]*,[ \t]*([a-zA-Z0-9_]+)");
+ RegEx reg_setget_set = RegEx("var[ ]+([a-zA-Z0-9_]+)([^\n]+)setget[ \t]+([a-zA-Z0-9_]+)[ \t]*[,]*[^a-z^A-Z^0-9^_]*$");
+ RegEx reg_setget_get = RegEx("var[ ]+([a-zA-Z0-9_]+)([^\n]+)setget[ \t]+,[ \t]*([a-zA-Z0-9_]+)[ \t]*$");
+ RegEx reg_join = RegEx("([\\(\\)a-zA-Z0-9_]+)\\.join\\(([^\n^\\)]+)\\)");
+ RegEx reg_mixed_tab_space = RegEx("([\t]+)([ ]+)");
+ RegEx reg_image_lock = RegEx("([a-zA-Z0-9_\\.]+)\\.lock\\(\\)");
+ RegEx reg_image_unlock = RegEx("([a-zA-Z0-9_\\.]+)\\.unlock\\(\\)");
+ RegEx reg_os_fullscreen = RegEx("OS.window_fullscreen[= ]+([^#^\n]+)");
+
+ CRASH_COND(!reg_is_empty.is_valid());
+ CRASH_COND(!reg_super.is_valid());
+ CRASH_COND(!reg_json_to.is_valid());
+ CRASH_COND(!reg_json_parse.is_valid());
+ CRASH_COND(!reg_json_non_new.is_valid());
+ CRASH_COND(!reg_export.is_valid());
+ CRASH_COND(!reg_export_advanced.is_valid());
+ CRASH_COND(!reg_setget_setget.is_valid());
+ CRASH_COND(!reg_setget_set.is_valid());
+ CRASH_COND(!reg_setget_get.is_valid());
+ CRASH_COND(!reg_join.is_valid());
+ CRASH_COND(!reg_mixed_tab_space.is_valid());
+ CRASH_COND(!reg_image_lock.is_valid());
+ CRASH_COND(!reg_image_unlock.is_valid());
+ CRASH_COND(!reg_os_fullscreen.is_valid());
+
+ for (String &line : file_content) {
+ String old_line = line;
+
+ if (line.find("mtx") == -1 && line.find("mutex") == -1 && line.find("Mutex") == -1) {
+ line = reg_image_lock.sub(line, "false # $1.lock() # TODOConverter40, image no longer require locking, `false` helps to not broke one line if/else, so can be freely removed", true);
+ line = reg_image_unlock.sub(line, "false # $1.unlock() # TODOConverter40, image no longer require locking, `false` helps to not broke one line if/else, so can be freely removed", true);
+ }
+
+ // Mixed use of spaces and tabs - tabs as first - TODO, this probably is problem problem, but not sure
+ line = reg_mixed_tab_space.sub(line, "$1", true);
+
+ // PackedStringArray(req_godot).join('.') -> '.'.join(PackedStringArray(req_godot)) PoolStringArray
+ line = reg_join.sub(line, "$2.join($1)", true);
+
+ // -- empty() -> is_empty() Pool*Array
+ line = reg_is_empty.sub(line, "is_empty(", true);
+
+ // -- \t.func() -> \tsuper.func() Object
+ line = reg_super.sub(line, "$1super.$2", true); // TODO, not sure if possible, but for now this brake String text e.g. "Choosen .gitignore" -> "Choosen super.gitignore"
+
+ // -- JSON.parse(a) -> JSON.new().parse(a) etc. JSON
+ line = reg_json_non_new.sub(line, "$1var test_json_conv = JSON.new()\n$1test_json_conv.parse($3\n$1$2test_json_conv.get_data()", true);
+
+ // -- to_json(a) -> JSON.new().stringify(a) Object
+ line = reg_json_to.sub(line, "JSON.new().stringify", true);
+
+ // -- parse_json(a) -> JSON.get_data() etc. Object
+ line = reg_json_parse.sub(line, "$1var test_json_conv = JSON.new()\n$1test_json_conv.parse($3\n$1$2test_json_conv.get_data()", true);
+
+ // -- get_node(@ -> get_node( Node
+ line = line.replace("get_node(@", "get_node(");
+
+ // export(float) var lifetime = 3.0 -> export var lifetime: float = 3.0 GDScript
+ line = reg_export.sub(line, "export var $2: $1");
+
+ // export(String, 'AnonymousPro', 'CourierPrime') var _font_name = 'AnonymousPro' -> export var _font_name = 'AnonymousPro' #(String, 'AnonymousPro', 'CourierPrime') GDScript
+ line = reg_export_advanced.sub(line, "export var $2$3 # ($1)");
+
+ // Setget Setget
+ line = reg_setget_setget.sub(line, "var $1$2:\n\tget:\n\t\treturn $1 # TODOConverter40 Copy here content of $4\n\tset(mod_value):\n\t\tmod_value # TODOConverter40 Copy here content of $3", true);
+
+ // Setget set
+ line = reg_setget_set.sub(line, "var $1$2:\n\tget:\n\t\treturn $1 # TODOConverter40 Non existent get function \n\tset(mod_value):\n\t\tmod_value # TODOConverter40 Copy here content of $3", true);
+
+ // Setget get
+ line = reg_setget_get.sub(line, "var $1$2:\n\tget:\n\t\treturn $1 # TODOConverter40 Copy here content of $3 \n\tset(mod_value):\n\t\tmod_value # TODOConverter40 Non existent set function", true);
+
+ // OS.window_fullscreen = true -> ProjectSettings.set("display/window/size/fullscreen",true)
+ line = reg_os_fullscreen.sub(line, "ProjectSettings.set(\"display/window/size/fullscreen\", $1)", true);
+
+ // -- r.move_and_slide( a, b, c, d, e ) -> r.set_motion_velocity(a) ... r.move_and_slide() KinematicBody
+ if (line.find("move_and_slide(") != -1) {
+ int start = line.find("move_and_slide(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ String base_obj = get_object_of_execution(line.substr(0, start));
+ String starting_space = get_starting_space(line);
+
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() >= 1) {
+ String line_new;
+
+ // motion_velocity
+ line_new += starting_space + base_obj + "set_motion_velocity(" + parts[0] + ")\n";
+
+ // up_direction
+ if (parts.size() >= 2) {
+ line_new += starting_space + base_obj + "set_up_direction(" + parts[1] + ")\n";
+ }
+
+ // stop_on_slope
+ if (parts.size() >= 3) {
+ line_new += starting_space + base_obj + "set_floor_stop_on_slope_enabled(" + parts[2] + ")\n";
+ }
+
+ // max_slides
+ if (parts.size() >= 4) {
+ line_new += starting_space + base_obj + "set_max_slides(" + parts[3] + ")\n";
+ }
+
+ // floor_max_angle
+ if (parts.size() >= 5) {
+ line_new += starting_space + base_obj + "set_floor_max_angle(" + parts[4] + ")\n";
+ }
+
+ // infiinite_interia
+ if (parts.size() >= 6) {
+ line_new += starting_space + "# TODOConverter40 infinite_inertia were removed in Godot 4.0 - previous value `" + parts[5] + "`\n";
+ }
+
+ line = line_new + line.substr(0, start) + "move_and_slide()" + line.substr(end + start);
+ }
+ }
+ }
+
+ // -- r.move_and_slide_with_snap( a, b, c, d, e ) -> r.set_motion_velocity(a) ... r.move_and_slide() KinematicBody
+ if (line.find("move_and_slide_with_snap(") != -1) {
+ int start = line.find("move_and_slide_with_snap(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ String base_obj = get_object_of_execution(line.substr(0, start));
+ String starting_space = get_starting_space(line);
+
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() >= 1) {
+ String line_new;
+
+ // motion_velocity
+ line_new += starting_space + base_obj + "set_motion_velocity(" + parts[0] + ")\n";
+
+ // snap
+ if (parts.size() >= 2) {
+ line_new += starting_space + "# TODOConverter40 looks that snap in Godot 4.0 is float, not vector like in Godot 3 - previous value `" + parts[1] + "`\n";
+ }
+
+ // up_direction
+ if (parts.size() >= 3) {
+ line_new += starting_space + base_obj + "set_up_direction(" + parts[2] + ")\n";
+ }
+
+ // stop_on_slope
+ if (parts.size() >= 4) {
+ line_new += starting_space + base_obj + "set_floor_stop_on_slope_enabled(" + parts[3] + ")\n";
+ }
+
+ // max_slides
+ if (parts.size() >= 5) {
+ line_new += starting_space + base_obj + "set_max_slides(" + parts[4] + ")\n";
+ }
+
+ // floor_max_angle
+ if (parts.size() >= 6) {
+ line_new += starting_space + base_obj + "set_floor_max_angle(" + parts[5] + ")\n";
+ }
+
+ // infiinite_interia
+ if (parts.size() >= 7) {
+ line_new += starting_space + "# TODOConverter40 infinite_inertia were removed in Godot 4.0 - previous value `" + parts[6] + "`\n";
+ }
+
+ line = line_new + line.substr(0, start) + "move_and_slide()" + line.substr(end + start);
+ }
+ }
+ }
+
+ // -- sort_custom( a , b ) -> sort_custom(Callable( a , b )) Object
+ if (line.find("sort_custom(") != -1) {
+ int start = line.find("sort_custom(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() == 2) {
+ line = line.substr(0, start) + "sort_custom(Callable(" + parts[0] + "," + parts[1] + "))" + line.substr(end + start);
+ }
+ }
+ }
+
+ // -- draw_line(1,2,3,4,5) -> draw_line(1,2,3,4) CanvasItem
+ if (line.find("draw_line(") != -1) {
+ int start = line.find("draw_line(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() == 5) {
+ line = line.substr(0, start) + "draw_line(" + parts[0] + "," + parts[1] + "," + parts[2] + "," + parts[3] + ")" + line.substr(end + start);
+ }
+ }
+ }
+
+ // -- func c(var a, var b) -> func c(a, b)
+ if (line.find("func ") != -1 && line.find("var ") != -1) {
+ int start = line.find("func ");
+ start = line.substr(start).find("(") + start;
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+
+ String start_string = line.substr(0, start) + "(";
+ for (int i = 0; i < parts.size(); i++) {
+ start_string += parts[i].strip_edges().trim_prefix("var ");
+ if (i != parts.size() - 1) {
+ start_string += ", ";
+ }
+ }
+ line = start_string + ")" + line.substr(end + start);
+ }
+ }
+
+ // -- yield(this, \"timeout\") -> await this.timeout GDScript
+ if (line.find("yield(") != -1) {
+ int start = line.find("yield(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() == 2) {
+ line = line.substr(0, start) + "await " + parts[0] + "." + parts[1].replace("\"", "").replace("\'", "").replace(" ", "") + line.substr(end + start);
+ }
+ }
+ }
+
+ // -- parse_json( AA ) -> TODO Object
+ if (line.find("parse_json(") != -1) {
+ int start = line.find("parse_json(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ line = line.substr(0, start) + "JSON.new().stringify(" + connect_arguments(parts, 0) + ")" + line.substr(end + start);
+ }
+ }
+
+ // -- .xform(Vector3(a,b,c)) -> * Vector3(a,b,c) Transform
+ if (line.find(".xform(") != -1) {
+ int start = line.find(".xform(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() == 1) {
+ line = line.substr(0, start) + " * " + parts[0] + line.substr(end + start);
+ }
+ }
+ }
+
+ // -- .xform_inv(Vector3(a,b,c)) -> / Vector3(a,b,c) Transform
+ if (line.find(".xform_inv(") != -1) {
+ int start = line.find(".xform_inv(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() == 1) {
+ line = line.substr(0, start) + " / " + parts[0] + line.substr(end + start);
+ }
+ }
+ }
+
+ // -- connect(,,,things) -> connect(,Callable(,),things) Object
+ if (line.find("connect(") != -1) {
+ int start = line.find("connect(");
+ // Protection from disconnect
+ if (start == 0 || line.get(start - 1) != 's') {
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() >= 3) {
+ line = line.substr(0, start) + "connect(" + parts[0] + ",Callable(" + parts[1] + "," + parts[2] + ")" + connect_arguments(parts, 3) + ")" + line.substr(end + start);
+ }
+ }
+ }
+ }
+ // -- disconnect(a,b,c) -> disconnect(a,Callable(b,c)) Object
+ if (line.find("disconnect(") != -1) {
+ int start = line.find("disconnect(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() == 3) {
+ line = line.substr(0, start) + "disconnect(" + parts[0] + ",Callable(" + parts[1] + "," + parts[2] + "))" + line.substr(end + start);
+ }
+ }
+ }
+ // -- is_connected(a,b,c) -> is_connected(a,Callable(b,c)) Object
+ if (line.find("is_connected(") != -1) {
+ int start = line.find("is_connected(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() == 3) {
+ line = line.substr(0, start) + "is_connected(" + parts[0] + ",Callable(" + parts[1] + "," + parts[2] + "))" + line.substr(end + start);
+ }
+ }
+ }
+ // -- start(a,b,c) -> start(a,Callable(b,c)) Thread
+ if (line.find("start(") != -1) {
+ int start = line.find("start(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() >= 3) {
+ line = line.substr(0, start) + "start(" + parts[0] + ",Callable(" + parts[1] + "," + parts[2] + ")" + connect_arguments(parts, 3) + ")" + line.substr(end + start);
+ }
+ }
+ }
+ // -- func _init(p_x:int)->void: -> func _init(p_x:int): Object # https://github.com/godotengine/godot/issues/50589
+ if (line.find(" _init(") != -1) {
+ int start = line.find(" _init(");
+ int end = line.rfind(":") + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ line = line.substr(0, start) + " _init(" + connect_arguments(parts, 0) + "):" + line.substr(end + start);
+ }
+ }
+ // assert(speed < 20, str(randi()%10)) -> assert(speed < 20) #,str(randi()%10)) GDScript - GDScript bug constant message
+ if (line.find("assert(") != -1) {
+ int start = line.find("assert(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() == 2) {
+ line = line.substr(0, start) + "assert(" + parts[0] + ") " + line.substr(end + start) + "#," + parts[1] + ")";
+ }
+ }
+ }
+ // create_from_image(aa, bb) -> create_from_image(aa) #, bb ImageTexture
+ if (line.find("create_from_image(") != -1) {
+ int start = line.find("create_from_image(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() == 2) {
+ line = line.substr(0, start) + "create_from_image(" + parts[0] + ") " + "#," + parts[1] + line.substr(end + start);
+ }
+ }
+ }
+ // set_cell_item(a, b, c, d ,e) -> set_cell_item(Vector3(a, b, c), d ,e)
+ if (line.find("set_cell_item(") != -1) {
+ int start = line.find("set_cell_item(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() > 2) {
+ line = line.substr(0, start) + "set_cell_item( Vector3(" + parts[0] + "," + parts[1] + "," + parts[2] + ") " + connect_arguments(parts, 3) + ")" + line.substr(end + start);
+ }
+ }
+ }
+ // get_cell_item(a, b, c) -> get_cell_item(Vector3i(a, b, c))
+ if (line.find("get_cell_item(") != -1) {
+ int start = line.find("get_cell_item(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() == 3) {
+ line = line.substr(0, start) + "get_cell_item(Vector3i(" + parts[0] + "," + parts[1] + "," + parts[2] + "))" + line.substr(end + start);
+ }
+ }
+ }
+ // get_cell_item_orientation(a, b, c) -> get_cell_item_orientation(Vector3i(a, b, c))
+ if (line.find("get_cell_item_orientation(") != -1) {
+ int start = line.find("get_cell_item_orientation(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() == 3) {
+ line = line.substr(0, start) + "get_cell_item_orientation(Vector3i(" + parts[0] + "," + parts[1] + "," + parts[2] + "))" + line.substr(end + start);
+ }
+ }
+ }
+
+ // TODO - add_surface_from_arrays - additional 4 argument
+ // ENetMultiplayerPeer.create_client - additional argument
+ // ENetMultiplayerPeer.create_server - additional argument
+ // Translation.get_message (and similar)
+ // TreeItem.move_after() - new argument
+ // TreeItem.move_before() - new argument
+ // UndoRedo.commit_action() - additional argument
+
+ if (old_line != line) {
+ found_things.append(simple_line_formatter(current_line, old_line, line));
+ }
+ }
+
+ return found_things;
+}
+
+void ProjectConverter3To4::rename_csharp_functions(String &file_content) {
+ // Custom renaming, each rule needs to be set manually
+ // Don't forget to put validate each rule in validate_conversion function
+ Vector<String> lines = file_content.split("\n");
+
+ for (String &line : lines) {
+ // TODO maybe this can be changed to normal rule
+ line = line.replace("OS.GetWindowSafeArea()", "DisplayServer.ScreenGetUsableRect()");
+
+ // -- Connect(,,,things) -> Connect(,Callable(,),things) Object
+ if (line.find("Connect(") != -1) {
+ int start = line.find("Connect(");
+ // Protection from disconnect
+ if (start == 0 || line.get(start - 1) != 's') {
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() >= 3) {
+ line = line.substr(0, start) + "Connect(" + parts[0] + ",new Callable(" + parts[1] + "," + parts[2] + ")" + connect_arguments(parts, 3) + ")" + line.substr(end + start);
+ }
+ }
+ }
+ }
+ // -- Disconnect(a,b,c) -> Disconnect(a,Callable(b,c)) Object
+ if (line.find("Disconnect(") != -1) {
+ int start = line.find("Disconnect(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() == 3) {
+ line = line.substr(0, start) + "Disconnect(" + parts[0] + ",new Callable(" + parts[1] + "," + parts[2] + "))" + line.substr(end + start);
+ }
+ }
+ }
+ // -- IsConnected(a,b,c) -> IsConnected(a,Callable(b,c)) Object
+ if (line.find("IsConnected(") != -1) {
+ int start = line.find("IsConnected(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() == 3) {
+ line = line.substr(0, start) + "IsConnected(" + parts[0] + ",new Callable(" + parts[1] + "," + parts[2] + "))" + line.substr(end + start);
+ }
+ }
+ }
+ }
+
+ // Collect vector to string
+ file_content = "";
+ for (int i = 0; i < lines.size(); i++) {
+ file_content += lines[i];
+
+ if (i != lines.size() - 1) {
+ file_content += "\n";
+ }
+ }
+};
+
+// This is almost 1:1 copy of function which rename gdscript functions
+Vector<String> ProjectConverter3To4::check_for_rename_csharp_functions(Vector<String> &file_content) {
+ int current_line = 1;
+
+ Vector<String> found_things;
+
+ for (String &line : file_content) {
+ String old_line = line;
+
+ // TODO maybe this can be changed to normal rule
+ line = line.replace("OS.GetWindowSafeArea()", "DisplayServer.ScreenGetUsableRect()");
+
+ // -- Connect(,,,things) -> connect(,Callable(,),things) Object
+ if (line.find("Connect(") != -1) {
+ int start = line.find("Connect(");
+ // Protection from disconnect
+ if (start == 0 || line.get(start - 1) != 's') {
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() >= 3) {
+ line = line.substr(0, start) + "Connect(" + parts[0] + ",new Callable(" + parts[1] + "," + parts[2] + ")" + connect_arguments(parts, 3) + ")" + line.substr(end + start);
+ }
+ }
+ }
+ }
+ // -- Disconnect(a,b,c) -> Disconnect(a,Callable(b,c)) Object
+ if (line.find("Disconnect(") != -1) {
+ int start = line.find("Disconnect(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() == 3) {
+ line = line.substr(0, start) + "Disconnect(" + parts[0] + ",Callable(" + parts[1] + "," + parts[2] + "))" + line.substr(end + start);
+ }
+ }
+ }
+ // -- IsConnected(a,b,c) -> IsConnected(a,Callable(b,c)) Object
+ if (line.find("IsConnected(") != -1) {
+ int start = line.find("IsConnected(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() == 3) {
+ line = line.substr(0, start) + "IsConnected(" + parts[0] + ",Callable(" + parts[1] + "," + parts[2] + "))" + line.substr(end + start);
+ }
+ }
+ }
+
+ if (old_line != line) {
+ found_things.append(simple_line_formatter(current_line, old_line, line));
+ }
+ }
+
+ return found_things;
+}
+
+void ProjectConverter3To4::rename_gdscript_keywords(String &file_content){
+ { RegEx reg_tool = RegEx("([\n]+)tool");
+CRASH_COND(!reg_tool.is_valid());
+file_content = reg_tool.sub(file_content, "$1@tool", true);
+RegEx reg_tool2 = RegEx("^tool");
+CRASH_COND(!reg_tool2.is_valid());
+file_content = reg_tool2.sub(file_content, "@tool", true);
+}
+{
+ RegEx reg_export = RegEx("([\n\t]+)export\\b");
+ CRASH_COND(!reg_export.is_valid());
+ file_content = reg_export.sub(file_content, "$1@export", true);
+ RegEx reg_export2 = RegEx("^export");
+ CRASH_COND(!reg_export2.is_valid());
+ file_content = reg_export2.sub(file_content, "@export", true);
+}
+{
+ RegEx reg_onready = RegEx("([\n]+)onready");
+ CRASH_COND(!reg_onready.is_valid());
+ file_content = reg_onready.sub(file_content, "$1@onready", true);
+ RegEx reg_onready2 = RegEx("^onready");
+ CRASH_COND(!reg_onready2.is_valid());
+ file_content = reg_onready2.sub(file_content, "@onready", true);
+}
+{
+ RegEx reg_master = RegEx("([\n]+)master func");
+ CRASH_COND(!reg_master.is_valid());
+ file_content = reg_master.sub(file_content, "$1@rpc(any) func", true);
+ RegEx reg_master2 = RegEx("^master func");
+ CRASH_COND(!reg_master2.is_valid());
+ file_content = reg_master2.sub(file_content, "@rpc(any) func", true);
+}
+{
+ RegEx reg_puppet = RegEx("([\n]+)puppet func");
+ CRASH_COND(!reg_puppet.is_valid());
+ file_content = reg_puppet.sub(file_content, "$1@rpc(auth) func", true);
+ RegEx reg_puppet2 = RegEx("^puppet func");
+ CRASH_COND(!reg_puppet2.is_valid());
+ file_content = reg_puppet2.sub(file_content, "@rpc(auth) func", true);
+}
+{
+ RegEx reg_remote = RegEx("([\n]+)remote func");
+ CRASH_COND(!reg_remote.is_valid());
+ file_content = reg_remote.sub(file_content, "$1@rpc(any) func", true);
+ RegEx reg_remote2 = RegEx("^remote func");
+ CRASH_COND(!reg_remote2.is_valid());
+ file_content = reg_remote2.sub(file_content, "@rpc(any) func", true);
+}
+{
+ RegEx reg_remotesync = RegEx("([\n]+)remotesync func");
+ CRASH_COND(!reg_remotesync.is_valid());
+ file_content = reg_remotesync.sub(file_content, "$1@rpc(any,sync) func", true);
+ RegEx reg_remotesync2 = RegEx("^remotesync func");
+ CRASH_COND(!reg_remotesync2.is_valid());
+ file_content = reg_remotesync2.sub(file_content, "@rpc(any,sync) func", true);
+}
+{
+ RegEx reg_sync = RegEx("([\n]+)sync func");
+ CRASH_COND(!reg_sync.is_valid());
+ file_content = reg_sync.sub(file_content, "$1@rpc(any,sync) func", true);
+ RegEx reg_sync2 = RegEx("^sync func");
+ CRASH_COND(!reg_sync2.is_valid());
+ file_content = reg_sync2.sub(file_content, "@rpc(any,sync) func", true);
+}
+{
+ RegEx reg_puppetsync = RegEx("([\n]+)puppetsync func");
+ CRASH_COND(!reg_puppetsync.is_valid());
+ file_content = reg_puppetsync.sub(file_content, "$1@rpc(auth,sync) func", true);
+ RegEx reg_puppetsync2 = RegEx("^puppetsync func");
+ CRASH_COND(!reg_puppetsync2.is_valid());
+ file_content = reg_puppetsync2.sub(file_content, "@rpc(auth,sync) func", true);
+}
+{
+ RegEx reg_mastersync = RegEx("([\n]+)mastersync func");
+ CRASH_COND(!reg_mastersync.is_valid());
+ file_content = reg_mastersync.sub(file_content, "$1@rpc(any,sync) func", true);
+ RegEx reg_mastersync2 = RegEx("^mastersync func");
+ CRASH_COND(!reg_mastersync2.is_valid());
+ file_content = reg_mastersync2.sub(file_content, "@rpc(any,sync) func", true);
+}
+}
+;
+
+Vector<String> ProjectConverter3To4::check_for_rename_gdscript_keywords(Vector<String> &file_content) {
+ Vector<String> found_things;
+
+ int current_line = 1;
+
+ for (String &line : file_content) {
+ String old;
+ old = line;
+ {
+ RegEx reg_tool2 = RegEx("^tool");
+ CRASH_COND(!reg_tool2.is_valid());
+ line = reg_tool2.sub(line, "@tool", true);
+ }
+ if (old != line) {
+ found_things.append(line_formatter(current_line, "tool", "@tool", line));
+ }
+ old = line;
+ {
+ RegEx reg_export = RegEx("([\t]+)export\\b");
+ CRASH_COND(!reg_export.is_valid());
+ line = reg_export.sub(line, "$1@export", true);
+ RegEx reg_export2 = RegEx("^export");
+ CRASH_COND(!reg_export2.is_valid());
+ line = reg_export2.sub(line, "@export", true);
+ }
+ if (old != line) {
+ found_things.append(line_formatter(current_line, "export", "@export", line));
+ }
+ old = line;
+ {
+ RegEx reg_onready2 = RegEx("^onready");
+ CRASH_COND(!reg_onready2.is_valid());
+ line = reg_onready2.sub(line, "@onready", true);
+ }
+ if (old != line) {
+ found_things.append(line_formatter(current_line, "onready", "@onready", line));
+ }
+ old = line;
+ {
+ RegEx reg_master2 = RegEx("^master func");
+ CRASH_COND(!reg_master2.is_valid());
+ line = reg_master2.sub(line, "@rpc(any) func", true);
+ }
+ if (old != line) {
+ found_things.append(line_formatter(current_line, "master func", "@rpc(any) func", line));
+ }
+ old = line;
+ {
+ RegEx reg_puppet2 = RegEx("^puppet func");
+ CRASH_COND(!reg_puppet2.is_valid());
+ line = reg_puppet2.sub(line, "@rpc(auth) func", true);
+ }
+ if (old != line) {
+ found_things.append(line_formatter(current_line, "puppet func", "@rpc(auth) func", line));
+ }
+ old = line;
+ {
+ RegEx reg_remote2 = RegEx("^remote func");
+ CRASH_COND(!reg_remote2.is_valid());
+ line = reg_remote2.sub(line, "@rpc(any) func", true);
+ }
+ if (old != line) {
+ found_things.append(line_formatter(current_line, "remote func", "@rpc(any) func", line));
+ }
+ old = line;
+ {
+ RegEx reg_remotesync2 = RegEx("^remotesync func");
+ CRASH_COND(!reg_remotesync2.is_valid());
+ line = reg_remotesync2.sub(line, "@rpc(any,sync) func", true);
+ }
+ if (old != line) {
+ found_things.append(line_formatter(current_line, "remotesync func", "@rpc(any,sync) func", line));
+ }
+ old = line;
+ {
+ RegEx reg_sync2 = RegEx("^sync func");
+ CRASH_COND(!reg_sync2.is_valid());
+ line = reg_sync2.sub(line, "@rpc(any,sync) func", true);
+ }
+ if (old != line) {
+ found_things.append(line_formatter(current_line, "sync func", "@rpc(any,sync) func", line));
+ }
+ old = line;
+ {
+ RegEx reg_puppetsync2 = RegEx("^puppetsync func");
+ CRASH_COND(!reg_puppetsync2.is_valid());
+ line = reg_puppetsync2.sub(line, "@rpc(auth,sync) func", true);
+ }
+ if (old != line) {
+ found_things.append(line_formatter(current_line, "puppetsync func", "@rpc(any,sync) func", line));
+ }
+ old = line;
+ {
+ RegEx reg_mastersync2 = RegEx("^mastersync func");
+ CRASH_COND(!reg_mastersync2.is_valid());
+ line = reg_mastersync2.sub(line, "@rpc(any,sync) func", true);
+ }
+ if (old != line) {
+ found_things.append(line_formatter(current_line, "mastersync", "@rpc(any,sync) func", line));
+ }
+ old = line;
+
+ current_line++;
+ }
+
+ return found_things;
+}
+
+void ProjectConverter3To4::custom_rename(String &file_content, String from, String to) {
+ RegEx reg = RegEx(String("\\b") + from + "\\b");
+ CRASH_COND(!reg.is_valid());
+ file_content = reg.sub(file_content, to, true);
+};
+
+Vector<String> ProjectConverter3To4::check_for_custom_rename(Vector<String> &file_content, String from, String to) {
+ Vector<String> found_things;
+
+ RegEx reg = RegEx(String("\\b") + from + "\\b");
+ CRASH_COND(!reg.is_valid());
+
+ int current_line = 1;
+ for (String &line : file_content) {
+ Array reg_match = reg.search_all(line);
+ if (reg_match.size() > 0) {
+ found_things.append(line_formatter(current_line, from.replace("\\.", "."), to, line)); // Without replacing it will print "\.shader" instead ".shader"
+ }
+ current_line++;
+ }
+ return found_things;
+}
+
+void ProjectConverter3To4::rename_common(const char *array[][2], String &file_content) {
+ int current_index = 0;
+ while (array[current_index][0]) {
+ RegEx reg = RegEx(String("\\b") + array[current_index][0] + "\\b");
+ CRASH_COND(!reg.is_valid());
+ file_content = reg.sub(file_content, array[current_index][1], true);
+ current_index++;
+ }
+}
+
+// Common renaming,
+Vector<String> ProjectConverter3To4::check_for_rename_common(const char *array[][2], Vector<String> &file_content) {
+ int current_index = 0;
+
+ Vector<String> found_things;
+
+ while (array[current_index][0]) {
+ RegEx reg = RegEx(String("\\b") + array[current_index][0] + "\\b");
+ CRASH_COND(!reg.is_valid());
+
+ int current_line = 1;
+ for (String &line : file_content) {
+ Array reg_match = reg.search_all(line);
+ if (reg_match.size() > 0) {
+ found_things.append(line_formatter(current_line, array[current_index][0], array[current_index][1], line));
+ }
+ current_line++;
+ }
+ current_index++;
+ }
+ return found_things;
+}
+
+// Formats data to print them into user console when trying to convert data
+String ProjectConverter3To4::line_formatter(int current_line, String from, String to, String line) {
+ if (from.size() > 200) {
+ from = from.substr(0, 197) + "...";
+ }
+ if (to.size() > 200) {
+ to = to.substr(0, 197) + "...";
+ }
+ if (line.size() > 400) {
+ line = line.substr(0, 397) + "...";
+ }
+ return String("Line (") + itos(current_line) + ") " + from.replace("\r", "").replace("\n", "") + " -> " + to.replace("\r", "").replace("\n", "") + " - LINE \"\"\" " + line.replace("\r", "").replace("\n", "").strip_edges() + " \"\"\"";
+}
+
+String ProjectConverter3To4::simple_line_formatter(int current_line, String old_line, String line) {
+ if (old_line.size() > 1000) {
+ old_line = old_line.substr(0, 997) + "...";
+ }
+ if (line.size() > 1000) {
+ line = line.substr(0, 997) + "...";
+ }
+ return String("Line (") + itos(current_line) + ") - FULL LINES - \"\"\"" + old_line.replace("\r", "").replace("\n", "").strip_edges() + "\"\"\" =====> \"\"\" " + line.replace("\r", "").replace("\n", "").strip_edges() + " \"\"\"";
+}
+
+#else // No regex.
+
+int ProjectConverter3To4::convert() {
+ ERR_FAIL_V_MSG(ERROR_CODE, "Can't run converter for Godot 3.x projects as RegEx module is disabled.");
+}
+
+int ProjectConverter3To4::validate_conversion() {
+ ERR_FAIL_V_MSG(ERROR_CODE, "Can't validate conversion for Godot 3.x projects as RegEx module is disabled.");
+}
+
+#endif // MODULE_REGEX_ENABLED
diff --git a/editor/project_converter_3_to_4.h b/editor/project_converter_3_to_4.h
new file mode 100644
index 0000000000..95239666e0
--- /dev/null
+++ b/editor/project_converter_3_to_4.h
@@ -0,0 +1,83 @@
+/*************************************************************************/
+/* project_converter_3_to_4.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef PROJECT_CONVERTER_3_TO_4_H
+#define PROJECT_CONVERTER_3_TO_4_H
+
+#include "core/core_bind.h"
+#include "core/io/file_access.h"
+#include "core/object/ref_counted.h"
+#include "core/string/ustring.h"
+
+class ProjectConverter3To4 {
+ void rename_enums(String &file_content);
+ Vector<String> check_for_rename_enums(Vector<String> &file_content);
+
+ void rename_classes(String &file_content);
+ Vector<String> check_for_rename_classes(Vector<String> &file_content);
+
+ void rename_gdscript_functions(String &file_content);
+ Vector<String> check_for_rename_gdscript_functions(Vector<String> &file_content);
+
+ void rename_csharp_functions(String &file_content);
+ Vector<String> check_for_rename_csharp_functions(Vector<String> &file_content);
+
+ void rename_gdscript_keywords(String &file_content);
+ Vector<String> check_for_rename_gdscript_keywords(Vector<String> &file_content);
+
+ void custom_rename(String &file_content, String from, String to);
+ Vector<String> check_for_custom_rename(Vector<String> &file_content, String from, String to);
+
+ void rename_common(const char *array[][2], String &file_content);
+ Vector<String> check_for_rename_common(const char *array[][2], Vector<String> &file_content);
+
+ Vector<String> check_for_files();
+
+ Vector<String> parse_arguments(const String &line);
+ int get_end_parenthess(const String &line) const;
+ String connect_arguments(const Vector<String> &line, int from, int to = -1) const;
+ String get_starting_space(const String &line) const;
+ String get_object_of_execution(const String &line) const;
+
+ String line_formatter(int current_line, String from, String to, String line);
+ String simple_line_formatter(int current_line, String old_line, String line);
+
+ bool test_single_array(const char *array[][2], bool ignore_second_check = false);
+ bool test_conversion_single_additional(String name, String expected, void (ProjectConverter3To4::*func)(String &), String what);
+ bool test_conversion_single_normal(String name, String expected, const char *array[][2], String what);
+ bool test_array_names();
+ bool test_conversion();
+
+public:
+ int validate_conversion();
+ int convert();
+};
+
+#endif // PROJECT_CONVERTER_3_TO_4_H
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
index 9646462ead..08df4cdf3c 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -2655,7 +2655,7 @@ void SceneTreeDock::_add_children_to_popup(Object *p_obj, int p_depth) {
}
int index = menu_subresources->get_item_count();
menu_subresources->add_icon_item(icon, E.name.capitalize(), EDIT_SUBRESOURCE_BASE + subresources.size());
- menu_subresources->set_item_h_offset(index, p_depth * 10 * EDSCALE);
+ menu_subresources->set_item_horizontal_offset(index, p_depth * 10 * EDSCALE);
subresources.push_back(obj->get_instance_id());
_add_children_to_popup(obj, p_depth + 1);
diff --git a/main/main.cpp b/main/main.cpp
index 15166ce152..b2667d11e6 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -87,6 +87,7 @@
#include "editor/editor_settings.h"
#include "editor/editor_translation.h"
#include "editor/progress_dialog.h"
+#include "editor/project_converter_3_to_4.h"
#include "editor/project_manager.h"
#ifndef NO_EDITOR_SPLASH
#include "main/splash_editor.gen.h"
@@ -368,6 +369,8 @@ void Main::print_help(const char *p_binary) {
OS::get_singleton()->print(" <path> should be absolute or relative to the project directory, and include the filename for the binary (e.g. 'builds/game.exe'). The target directory should exist.\n");
OS::get_singleton()->print(" --export-debug <preset> <path> Same as --export, but using the debug template.\n");
OS::get_singleton()->print(" --export-pack <preset> <path> Same as --export, but only export the game pack for the given preset. The <path> extension determines whether it will be in PCK or ZIP format.\n");
+ OS::get_singleton()->print(" --convert-3to4 Converts project from Godot 3.x to Godot 4.x.\n");
+ OS::get_singleton()->print(" --validate-conversion-3to4 Shows what elements will be renamed when converting project from Godot 3.x to Godot 4.x.\n");
OS::get_singleton()->print(" --doctool [<path>] Dump the engine API reference to the given <path> (defaults to current dir) in XML format, merging if existing files are found.\n");
OS::get_singleton()->print(" --no-docbase Disallow dumping the base types (used with --doctool).\n");
OS::get_singleton()->print(" --build-solutions Build the scripting solutions (e.g. for C# projects). Implies --editor and requires a valid project to edit.\n");
@@ -996,6 +999,14 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
editor = true;
cmdline_tool = true;
main_args.push_back(I->get());
+ } else if (I->get() == "--convert-3to4") {
+ // Actually handling is done in start().
+ cmdline_tool = true;
+ main_args.push_back(I->get());
+ } else if (I->get() == "--validate-conversion-3to4") {
+ // Actually handling is done in start().
+ cmdline_tool = true;
+ main_args.push_back(I->get());
} else if (I->get() == "--doctool") {
// Actually handling is done in start().
cmdline_tool = true;
@@ -2035,6 +2046,8 @@ bool Main::start() {
String _export_preset;
bool export_debug = false;
bool export_pack_only = false;
+ bool converting_project = false;
+ bool validating_converting_project = false;
#endif
main_timer_sync.init(OS::get_singleton()->get_ticks_usec());
@@ -2050,6 +2063,10 @@ bool Main::start() {
#ifdef TOOLS_ENABLED
} else if (args[i] == "--no-docbase") {
doc_base = false;
+ } else if (args[i] == "--convert-3to4") {
+ converting_project = true;
+ } else if (args[i] == "--validate-conversion-3to4") {
+ validating_converting_project = true;
} else if (args[i] == "-e" || args[i] == "--editor") {
editor = true;
} else if (args[i] == "-p" || args[i] == "--project-manager") {
@@ -2203,6 +2220,18 @@ bool Main::start() {
NativeExtensionAPIDump::generate_extension_json_file("extension_api.json");
return false;
}
+
+ if (converting_project) {
+ int exit_code = ProjectConverter3To4().convert();
+ OS::get_singleton()->set_exit_code(exit_code);
+ return false;
+ }
+ if (validating_converting_project) {
+ int exit_code = ProjectConverter3To4().validate_conversion();
+ OS::get_singleton()->set_exit_code(exit_code);
+ return false;
+ }
+
#endif
if (script.is_empty() && game_path.is_empty() && String(GLOBAL_GET("application/run/main_scene")) != "") {
diff --git a/misc/dist/shell/_godot.zsh-completion b/misc/dist/shell/_godot.zsh-completion
index 6444ca337e..b17bb6e66b 100644
--- a/misc/dist/shell/_godot.zsh-completion
+++ b/misc/dist/shell/_godot.zsh-completion
@@ -78,6 +78,8 @@ _arguments \
'--export[export the project using the given preset and matching release template]:export preset name then path' \
'--export-debug[same as --export, but using the debug template]:export preset name then path' \
'--export-pack[same as --export, but only export the game pack for the given preset]:export preset name then path' \
+ '--convert-3to4[converts project from Godot 3.x to Godot 4.x]' \
+ '--validate-conversion-3to4[shows what elements will be renamed when converting project from Godot 3.x to Godot 4.x]' \
'--doctool[dump the engine API reference to the given path in XML format, merging if existing files are found]:path to base Godot build directory (optional):_dirs' \
'--no-docbase[disallow dumping the base types (used with --doctool)]' \
'--build-solutions[build the scripting solutions (e.g. for C# projects)]' \
diff --git a/misc/dist/shell/godot.bash-completion b/misc/dist/shell/godot.bash-completion
index 31e067e29a..1ab687e1fc 100644
--- a/misc/dist/shell/godot.bash-completion
+++ b/misc/dist/shell/godot.bash-completion
@@ -81,6 +81,8 @@ _complete_godot_options() {
--export
--export-debug
--export-pack
+--convert-3to4
+--validate-conversion-3to4
--doctool
--no-docbase
--build-solutions
diff --git a/misc/dist/shell/godot.fish b/misc/dist/shell/godot.fish
index da4ce1190c..d58066c135 100644
--- a/misc/dist/shell/godot.fish
+++ b/misc/dist/shell/godot.fish
@@ -93,6 +93,8 @@ complete -c godot -l check-only -d "Only parse for errors and quit (use with --s
complete -c godot -l export -d "Export the project using the given preset and matching release template" -x
complete -c godot -l export-debug -d "Same as --export, but using the debug template" -x
complete -c godot -l export-pack -d "Same as --export, but only export the game pack for the given preset" -x
+complete -c godot -l convert-3to4 -d "Converts project from Godot 3.x to Godot 4.x"
+complete -c godot -l validate-conversion-3to4 -d "Shows what elements will be renamed when converting project from Godot 3.x to Godot 4.x"
complete -c godot -l doctool -d "Dump the engine API reference to the given path in XML format, merging if existing files are found" -r
complete -c godot -l no-docbase -d "Disallow dumping the base types (used with --doctool)"
complete -c godot -l build-solutions -d "Build the scripting solutions (e.g. for C# projects)"
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index 910f94a936..b2cce9d8ee 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -1389,25 +1389,9 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_match_pattern(CodeGen &c
codegen.generator->pop_temporary();
codegen.generator->pop_temporary();
- // If this isn't the first, we need to OR with the previous pattern. If it's nested, we use AND instead.
- if (p_is_nested) {
- // Use the previous value as target, since we only need one temporary variable.
- codegen.generator->write_and_right_operand(result_addr);
- codegen.generator->write_end_and(p_previous_test);
- } else if (!p_is_first) {
- // Use the previous value as target, since we only need one temporary variable.
- codegen.generator->write_or_right_operand(result_addr);
- codegen.generator->write_end_or(p_previous_test);
- } else {
- // Just assign this value to the accumulator temporary.
- codegen.generator->write_assign(p_previous_test, result_addr);
- }
- codegen.generator->pop_temporary(); // Remove temp result addr.
-
// Create temporaries outside the loop so they can be reused.
GDScriptCodeGenerator::Address element_addr = codegen.add_temporary();
GDScriptCodeGenerator::Address element_type_addr = codegen.add_temporary();
- GDScriptCodeGenerator::Address test_addr = p_previous_test;
// Evaluate element by element.
for (int i = 0; i < p_pattern->array.size(); i++) {
@@ -1417,7 +1401,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_match_pattern(CodeGen &c
}
// Use AND here too, as we don't want to be checking elements if previous test failed (which means this might be an invalid get).
- codegen.generator->write_and_left_operand(test_addr);
+ codegen.generator->write_and_left_operand(result_addr);
// Add index to constant map.
GDScriptCodeGenerator::Address index_addr = codegen.add_constant(i);
@@ -1431,19 +1415,34 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_match_pattern(CodeGen &c
codegen.generator->write_call_utility(element_type_addr, "typeof", typeof_args);
// Try the pattern inside the element.
- test_addr = _parse_match_pattern(codegen, r_error, p_pattern->array[i], element_addr, element_type_addr, p_previous_test, false, true);
+ result_addr = _parse_match_pattern(codegen, r_error, p_pattern->array[i], element_addr, element_type_addr, result_addr, false, true);
if (r_error != OK) {
return GDScriptCodeGenerator::Address();
}
- codegen.generator->write_and_right_operand(test_addr);
- codegen.generator->write_end_and(test_addr);
+ codegen.generator->write_and_right_operand(result_addr);
+ codegen.generator->write_end_and(result_addr);
}
// Remove element temporaries.
codegen.generator->pop_temporary();
codegen.generator->pop_temporary();
- return test_addr;
+ // If this isn't the first, we need to OR with the previous pattern. If it's nested, we use AND instead.
+ if (p_is_nested) {
+ // Use the previous value as target, since we only need one temporary variable.
+ codegen.generator->write_and_right_operand(result_addr);
+ codegen.generator->write_end_and(p_previous_test);
+ } else if (!p_is_first) {
+ // Use the previous value as target, since we only need one temporary variable.
+ codegen.generator->write_or_right_operand(result_addr);
+ codegen.generator->write_end_or(p_previous_test);
+ } else {
+ // Just assign this value to the accumulator temporary.
+ codegen.generator->write_assign(p_previous_test, result_addr);
+ }
+ codegen.generator->pop_temporary(); // Remove temp result addr.
+
+ return p_previous_test;
} break;
case GDScriptParser::PatternNode::PT_DICTIONARY: {
if (p_is_nested) {
@@ -1488,27 +1487,9 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_match_pattern(CodeGen &c
codegen.generator->pop_temporary();
codegen.generator->pop_temporary();
- // If this isn't the first, we need to OR with the previous pattern. If it's nested, we use AND instead.
- if (p_is_nested) {
- // Use the previous value as target, since we only need one temporary variable.
- codegen.generator->write_and_right_operand(result_addr);
- codegen.generator->write_end_and(p_previous_test);
- } else if (!p_is_first) {
- // Use the previous value as target, since we only need one temporary variable.
- codegen.generator->write_or_right_operand(result_addr);
- codegen.generator->write_end_or(p_previous_test);
- } else {
- // Just assign this value to the accumulator temporary.
- codegen.generator->write_assign(p_previous_test, result_addr);
- }
- codegen.generator->pop_temporary(); // Remove temp result addr.
-
// Create temporaries outside the loop so they can be reused.
- temp_type.builtin_type = Variant::BOOL;
- GDScriptCodeGenerator::Address test_result = codegen.add_temporary(temp_type);
GDScriptCodeGenerator::Address element_addr = codegen.add_temporary();
GDScriptCodeGenerator::Address element_type_addr = codegen.add_temporary();
- GDScriptCodeGenerator::Address test_addr = p_previous_test;
// Evaluate element by element.
for (int i = 0; i < p_pattern->dictionary.size(); i++) {
@@ -1519,7 +1500,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_match_pattern(CodeGen &c
}
// Use AND here too, as we don't want to be checking elements if previous test failed (which means this might be an invalid get).
- codegen.generator->write_and_left_operand(test_addr);
+ codegen.generator->write_and_left_operand(result_addr);
// Get the pattern key.
GDScriptCodeGenerator::Address pattern_key_addr = _parse_expression(codegen, r_error, element.key);
@@ -1530,11 +1511,11 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_match_pattern(CodeGen &c
// Check if pattern key exists in user's dictionary. This will be AND-ed with next result.
func_args.clear();
func_args.push_back(pattern_key_addr);
- codegen.generator->write_call(test_result, p_value_addr, "has", func_args);
+ codegen.generator->write_call(result_addr, p_value_addr, "has", func_args);
if (element.value_pattern != nullptr) {
// Use AND here too, as we don't want to be checking elements if previous test failed (which means this might be an invalid get).
- codegen.generator->write_and_left_operand(test_result);
+ codegen.generator->write_and_left_operand(result_addr);
// Get actual value from user dictionary.
codegen.generator->write_get(element_addr, pattern_key_addr, p_value_addr);
@@ -1545,16 +1526,16 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_match_pattern(CodeGen &c
codegen.generator->write_call_utility(element_type_addr, "typeof", func_args);
// Try the pattern inside the value.
- test_addr = _parse_match_pattern(codegen, r_error, element.value_pattern, element_addr, element_type_addr, test_addr, false, true);
+ result_addr = _parse_match_pattern(codegen, r_error, element.value_pattern, element_addr, element_type_addr, result_addr, false, true);
if (r_error != OK) {
return GDScriptCodeGenerator::Address();
}
- codegen.generator->write_and_right_operand(test_addr);
- codegen.generator->write_end_and(test_addr);
+ codegen.generator->write_and_right_operand(result_addr);
+ codegen.generator->write_end_and(result_addr);
}
- codegen.generator->write_and_right_operand(test_addr);
- codegen.generator->write_end_and(test_addr);
+ codegen.generator->write_and_right_operand(result_addr);
+ codegen.generator->write_end_and(result_addr);
// Remove pattern key temporary.
if (pattern_key_addr.mode == GDScriptCodeGenerator::Address::TEMPORARY) {
@@ -1565,9 +1546,23 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_match_pattern(CodeGen &c
// Remove element temporaries.
codegen.generator->pop_temporary();
codegen.generator->pop_temporary();
- codegen.generator->pop_temporary();
- return test_addr;
+ // If this isn't the first, we need to OR with the previous pattern. If it's nested, we use AND instead.
+ if (p_is_nested) {
+ // Use the previous value as target, since we only need one temporary variable.
+ codegen.generator->write_and_right_operand(result_addr);
+ codegen.generator->write_end_and(p_previous_test);
+ } else if (!p_is_first) {
+ // Use the previous value as target, since we only need one temporary variable.
+ codegen.generator->write_or_right_operand(result_addr);
+ codegen.generator->write_end_or(p_previous_test);
+ } else {
+ // Just assign this value to the accumulator temporary.
+ codegen.generator->write_assign(p_previous_test, result_addr);
+ }
+ codegen.generator->pop_temporary(); // Remove temp result addr.
+
+ return p_previous_test;
} break;
case GDScriptParser::PatternNode::PT_REST:
// Do nothing.
diff --git a/modules/gdscript/tests/scripts/parser/features/match_dictionary.gd b/modules/gdscript/tests/scripts/parser/features/match_dictionary.gd
new file mode 100644
index 0000000000..377dd25e9e
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/features/match_dictionary.gd
@@ -0,0 +1,43 @@
+func foo(x):
+ match x:
+ {"key1": "value1", "key2": "value2"}:
+ print('{"key1": "value1", "key2": "value2"}')
+ {"key1": "value1", "key2"}:
+ print('{"key1": "value1", "key2"}')
+ {"key1", "key2": "value2"}:
+ print('{"key1", "key2": "value2"}')
+ {"key1", "key2"}:
+ print('{"key1", "key2"}')
+ {"key1": "value1"}:
+ print('{"key1": "value1"}')
+ {"key1"}:
+ print('{"key1"}')
+ _:
+ print("wildcard")
+
+func bar(x):
+ match x:
+ {0}:
+ print("0")
+ {1}:
+ print("1")
+ {2}:
+ print("2")
+ _:
+ print("wildcard")
+
+func test():
+ foo({"key1": "value1", "key2": "value2"})
+ foo({"key1": "value1", "key2": ""})
+ foo({"key1": "", "key2": "value2"})
+ foo({"key1": "", "key2": ""})
+ foo({"key1": "value1"})
+ foo({"key1": ""})
+ foo({"key1": "value1", "key2": "value2", "key3": "value3"})
+ foo({"key1": "value1", "key3": ""})
+ foo({"key2": "value2"})
+ foo({"key3": ""})
+ bar({0: "0"})
+ bar({1: "1"})
+ bar({2: "2"})
+ bar({3: "3"})
diff --git a/modules/gdscript/tests/scripts/parser/features/match_dictionary.out b/modules/gdscript/tests/scripts/parser/features/match_dictionary.out
new file mode 100644
index 0000000000..4dee886927
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/features/match_dictionary.out
@@ -0,0 +1,15 @@
+GDTEST_OK
+{"key1": "value1", "key2": "value2"}
+{"key1": "value1", "key2"}
+{"key1", "key2": "value2"}
+{"key1", "key2"}
+{"key1": "value1"}
+{"key1"}
+wildcard
+wildcard
+wildcard
+wildcard
+0
+1
+2
+wildcard
diff --git a/modules/gdscript/tests/scripts/parser/features/match_multiple_patterns_with_array.gd b/modules/gdscript/tests/scripts/parser/features/match_multiple_patterns_with_array.gd
new file mode 100644
index 0000000000..dbe223f5f5
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/features/match_multiple_patterns_with_array.gd
@@ -0,0 +1,26 @@
+func foo(x):
+ match x:
+ 1, [2]:
+ print('1, [2]')
+ _:
+ print('wildcard')
+
+func bar(x):
+ match x:
+ [1], [2], [3]:
+ print('[1], [2], [3]')
+ [4]:
+ print('[4]')
+ _:
+ print('wildcard')
+
+func test():
+ foo(1)
+ foo([2])
+ foo(2)
+ bar([1])
+ bar([2])
+ bar([3])
+ bar([4])
+ bar([5])
+
diff --git a/modules/gdscript/tests/scripts/parser/features/match_multiple_patterns_with_array.out b/modules/gdscript/tests/scripts/parser/features/match_multiple_patterns_with_array.out
new file mode 100644
index 0000000000..a12b934d67
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/features/match_multiple_patterns_with_array.out
@@ -0,0 +1,9 @@
+GDTEST_OK
+1, [2]
+1, [2]
+wildcard
+[1], [2], [3]
+[1], [2], [3]
+[1], [2], [3]
+[4]
+wildcard
diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp
index 6255e11405..0e34b5907e 100644
--- a/modules/gridmap/grid_map.cpp
+++ b/modules/gridmap/grid_map.cpp
@@ -226,8 +226,8 @@ bool GridMap::is_baking_navigation() {
return bake_navigation;
}
-void GridMap::set_navigation_layers(uint32_t p_layers) {
- navigation_layers = p_layers;
+void GridMap::set_navigation_layers(uint32_t p_navigation_layers) {
+ navigation_layers = p_navigation_layers;
_recreate_octant_data();
}
@@ -548,7 +548,7 @@ bool GridMap::_octant_update(const OctantKey &p_key) {
if (bake_navigation) {
RID region = NavigationServer3D::get_singleton()->region_create();
- NavigationServer3D::get_singleton()->region_set_layers(region, navigation_layers);
+ NavigationServer3D::get_singleton()->region_set_navigation_layers(region, navigation_layers);
NavigationServer3D::get_singleton()->region_set_navmesh(region, navmesh);
NavigationServer3D::get_singleton()->region_set_transform(region, get_global_transform() * nm.xform);
NavigationServer3D::get_singleton()->region_set_map(region, get_world_3d()->get_navigation_map());
@@ -659,7 +659,7 @@ void GridMap::_octant_enter_world(const OctantKey &p_key) {
Ref<NavigationMesh> nm = mesh_library->get_item_navmesh(cell_map[F.key].item);
if (nm.is_valid()) {
RID region = NavigationServer3D::get_singleton()->region_create();
- NavigationServer3D::get_singleton()->region_set_layers(region, navigation_layers);
+ NavigationServer3D::get_singleton()->region_set_navigation_layers(region, navigation_layers);
NavigationServer3D::get_singleton()->region_set_navmesh(region, nm);
NavigationServer3D::get_singleton()->region_set_transform(region, get_global_transform() * F.value.xform);
NavigationServer3D::get_singleton()->region_set_map(region, get_world_3d()->get_navigation_map());
diff --git a/modules/gridmap/grid_map.h b/modules/gridmap/grid_map.h
index c79557afea..08ed4d3d12 100644
--- a/modules/gridmap/grid_map.h
+++ b/modules/gridmap/grid_map.h
@@ -238,7 +238,7 @@ public:
void set_bake_navigation(bool p_bake_navigation);
bool is_baking_navigation();
- void set_navigation_layers(uint32_t p_layers);
+ void set_navigation_layers(uint32_t p_navigation_layers);
uint32_t get_navigation_layers();
void set_mesh_library(const Ref<MeshLibrary> &p_mesh_library);
diff --git a/modules/navigation/godot_navigation_server.cpp b/modules/navigation/godot_navigation_server.cpp
index f4e719b0c1..2f8cb6c230 100644
--- a/modules/navigation/godot_navigation_server.cpp
+++ b/modules/navigation/godot_navigation_server.cpp
@@ -198,11 +198,11 @@ real_t GodotNavigationServer::map_get_edge_connection_margin(RID p_map) const {
return map->get_edge_connection_margin();
}
-Vector<Vector3> GodotNavigationServer::map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_layers) const {
+Vector<Vector3> GodotNavigationServer::map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_navigation_layers) const {
const NavMap *map = map_owner.get_or_null(p_map);
ERR_FAIL_COND_V(map == nullptr, Vector<Vector3>());
- return map->get_path(p_origin, p_destination, p_optimize, p_layers);
+ return map->get_path(p_origin, p_destination, p_optimize, p_navigation_layers);
}
Vector3 GodotNavigationServer::map_get_closest_point_to_segment(RID p_map, const Vector3 &p_from, const Vector3 &p_to, const bool p_use_collision) const {
@@ -339,18 +339,18 @@ real_t GodotNavigationServer::region_get_travel_cost(RID p_region) const {
return region->get_travel_cost();
}
-COMMAND_2(region_set_layers, RID, p_region, uint32_t, p_layers) {
+COMMAND_2(region_set_navigation_layers, RID, p_region, uint32_t, p_navigation_layers) {
NavRegion *region = region_owner.get_or_null(p_region);
ERR_FAIL_COND(region == nullptr);
- region->set_layers(p_layers);
+ region->set_navigation_layers(p_navigation_layers);
}
-uint32_t GodotNavigationServer::region_get_layers(RID p_region) const {
+uint32_t GodotNavigationServer::region_get_navigation_layers(RID p_region) const {
NavRegion *region = region_owner.get_or_null(p_region);
ERR_FAIL_COND_V(region == nullptr, 0);
- return region->get_layers();
+ return region->get_navigation_layers();
}
COMMAND_2(region_set_navmesh, RID, p_region, Ref<NavigationMesh>, p_nav_mesh) {
diff --git a/modules/navigation/godot_navigation_server.h b/modules/navigation/godot_navigation_server.h
index 1a7fddb7e6..d931dbaee0 100644
--- a/modules/navigation/godot_navigation_server.h
+++ b/modules/navigation/godot_navigation_server.h
@@ -98,7 +98,7 @@ public:
COMMAND_2(map_set_edge_connection_margin, RID, p_map, real_t, p_connection_margin);
virtual real_t map_get_edge_connection_margin(RID p_map) const override;
- virtual Vector<Vector3> map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_layers = 1) const override;
+ virtual Vector<Vector3> map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_navigation_layers = 1) const override;
virtual Vector3 map_get_closest_point_to_segment(RID p_map, const Vector3 &p_from, const Vector3 &p_to, const bool p_use_collision = false) const override;
virtual Vector3 map_get_closest_point(RID p_map, const Vector3 &p_point) const override;
@@ -117,8 +117,8 @@ public:
COMMAND_2(region_set_map, RID, p_region, RID, p_map);
virtual RID region_get_map(RID p_region) const override;
- COMMAND_2(region_set_layers, RID, p_region, uint32_t, p_layers);
- virtual uint32_t region_get_layers(RID p_region) const override;
+ COMMAND_2(region_set_navigation_layers, RID, p_region, uint32_t, p_navigation_layers);
+ virtual uint32_t region_get_navigation_layers(RID p_region) const override;
COMMAND_2(region_set_transform, RID, p_region, Transform3D, p_transform);
COMMAND_2(region_set_navmesh, RID, p_region, Ref<NavigationMesh>, p_nav_mesh);
virtual void region_bake_navmesh(Ref<NavigationMesh> r_mesh, Node *p_node) const override;
diff --git a/modules/navigation/nav_map.cpp b/modules/navigation/nav_map.cpp
index 059dc989a8..49c12813b3 100644
--- a/modules/navigation/nav_map.cpp
+++ b/modules/navigation/nav_map.cpp
@@ -65,7 +65,7 @@ gd::PointKey NavMap::get_point_key(const Vector3 &p_pos) const {
return p;
}
-Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_layers) const {
+Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_navigation_layers) const {
// Find the start poly and the end poly on this map.
const gd::Polygon *begin_poly = nullptr;
const gd::Polygon *end_poly = nullptr;
@@ -78,7 +78,7 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
const gd::Polygon &p = polygons[i];
// Only consider the polygon if it in a region with compatible layers.
- if ((p_layers & p.owner->get_layers()) == 0) {
+ if ((p_navigation_layers & p.owner->get_navigation_layers()) == 0) {
continue;
}
@@ -154,7 +154,7 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
const gd::Edge::Connection &connection = edge.connections[connection_index];
// Only consider the connection to another polygon if this polygon is in a region with compatible layers.
- if ((p_layers & connection.polygon->owner->get_layers()) == 0) {
+ if ((p_navigation_layers & connection.polygon->owner->get_navigation_layers()) == 0) {
continue;
}
diff --git a/modules/navigation/nav_map.h b/modules/navigation/nav_map.h
index 20115dd1b4..2036dbecd7 100644
--- a/modules/navigation/nav_map.h
+++ b/modules/navigation/nav_map.h
@@ -105,7 +105,7 @@ public:
gd::PointKey get_point_key(const Vector3 &p_pos) const;
- Vector<Vector3> get_path(Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_layers = 1) const;
+ Vector<Vector3> get_path(Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_navigation_layers = 1) const;
Vector3 get_closest_point_to_segment(const Vector3 &p_from, const Vector3 &p_to, const bool p_use_collision) const;
Vector3 get_closest_point(const Vector3 &p_point) const;
Vector3 get_closest_point_normal(const Vector3 &p_point) const;
diff --git a/modules/navigation/nav_region.cpp b/modules/navigation/nav_region.cpp
index fea0ad519a..88740807eb 100644
--- a/modules/navigation/nav_region.cpp
+++ b/modules/navigation/nav_region.cpp
@@ -40,12 +40,12 @@ void NavRegion::set_map(NavMap *p_map) {
}
}
-void NavRegion::set_layers(uint32_t p_layers) {
- layers = p_layers;
+void NavRegion::set_navigation_layers(uint32_t p_navigation_layers) {
+ navigation_layers = p_navigation_layers;
}
-uint32_t NavRegion::get_layers() const {
- return layers;
+uint32_t NavRegion::get_navigation_layers() const {
+ return navigation_layers;
}
void NavRegion::set_transform(Transform3D p_transform) {
diff --git a/modules/navigation/nav_region.h b/modules/navigation/nav_region.h
index acde5de834..484856ae36 100644
--- a/modules/navigation/nav_region.h
+++ b/modules/navigation/nav_region.h
@@ -45,7 +45,7 @@ class NavRegion : public NavRid {
NavMap *map = nullptr;
Transform3D transform;
Ref<NavigationMesh> mesh;
- uint32_t layers = 1;
+ uint32_t navigation_layers = 1;
float enter_cost = 0.0;
float travel_cost = 1.0;
Vector<gd::Edge::Connection> connections;
@@ -73,8 +73,8 @@ public:
void set_travel_cost(float p_travel_cost) { travel_cost = MAX(p_travel_cost, 0.0); }
float get_travel_cost() const { return travel_cost; }
- void set_layers(uint32_t p_layers);
- uint32_t get_layers() const;
+ void set_navigation_layers(uint32_t p_navigation_layers);
+ uint32_t get_navigation_layers() const;
void set_transform(Transform3D transform);
const Transform3D &get_transform() const {
diff --git a/modules/openxr/openxr_api.cpp b/modules/openxr/openxr_api.cpp
index f42af0492f..d8d3bacb19 100644
--- a/modules/openxr/openxr_api.cpp
+++ b/modules/openxr/openxr_api.cpp
@@ -1102,7 +1102,7 @@ Size2 OpenXRAPI::get_recommended_target_size() {
return target_size;
}
-XRPose::TrackingConfidence OpenXRAPI::get_head_center(Transform3D &r_transform, Vector3 &r_linear_velocity, const Vector3 &r_angular_velocity) {
+XRPose::TrackingConfidence OpenXRAPI::get_head_center(Transform3D &r_transform, Vector3 &r_linear_velocity, Vector3 &r_angular_velocity) {
XrResult result;
ERR_FAIL_COND_V(!running, XRPose::XR_TRACKING_CONFIDENCE_NONE);
@@ -1730,7 +1730,7 @@ XRPose::TrackingConfidence OpenXRAPI::transform_from_location(const XrHandJointL
return _transform_from_location(p_location, r_transform);
}
-void OpenXRAPI::parse_velocities(const XrSpaceVelocity &p_velocity, Vector3 &r_linear_velocity, Vector3 r_angular_velocity) {
+void OpenXRAPI::parse_velocities(const XrSpaceVelocity &p_velocity, Vector3 &r_linear_velocity, Vector3 &r_angular_velocity) {
if (p_velocity.velocityFlags & XR_SPACE_VELOCITY_LINEAR_VALID_BIT) {
XrVector3f linear_velocity = p_velocity.linearVelocity;
r_linear_velocity = Vector3(linear_velocity.x, linear_velocity.y, linear_velocity.z);
@@ -2303,7 +2303,7 @@ Vector2 OpenXRAPI::get_action_vector2(RID p_action, RID p_tracker) {
return result_state.isActive ? Vector2(result_state.currentState.x, result_state.currentState.y) : Vector2();
}
-XRPose::TrackingConfidence OpenXRAPI::get_action_pose(RID p_action, RID p_tracker, Transform3D &r_transform, Vector3 &r_linear_velocity, const Vector3 &r_angular_velocity) {
+XRPose::TrackingConfidence OpenXRAPI::get_action_pose(RID p_action, RID p_tracker, Transform3D &r_transform, Vector3 &r_linear_velocity, Vector3 &r_angular_velocity) {
ERR_FAIL_COND_V(session == XR_NULL_HANDLE, XRPose::XR_TRACKING_CONFIDENCE_NONE);
Action *action = action_owner.get_or_null(p_action);
ERR_FAIL_NULL_V(action, XRPose::XR_TRACKING_CONFIDENCE_NONE);
diff --git a/modules/openxr/openxr_api.h b/modules/openxr/openxr_api.h
index bd71f0e1c2..fe9e2937b2 100644
--- a/modules/openxr/openxr_api.h
+++ b/modules/openxr/openxr_api.h
@@ -225,7 +225,7 @@ protected:
// helper method to get a valid Transform3D from an openxr space location
XRPose::TrackingConfidence transform_from_location(const XrSpaceLocation &p_location, Transform3D &r_transform);
XRPose::TrackingConfidence transform_from_location(const XrHandJointLocationEXT &p_location, Transform3D &r_transform);
- void parse_velocities(const XrSpaceVelocity &p_velocity, Vector3 &r_linear_velocity, Vector3 r_angular_velocity);
+ void parse_velocities(const XrSpaceVelocity &p_velocity, Vector3 &r_linear_velocity, Vector3 &r_angular_velocity);
public:
static bool openxr_is_enabled(bool p_check_run_in_editor = true);
@@ -247,7 +247,7 @@ public:
bool can_render() { return instance != XR_NULL_HANDLE && session != XR_NULL_HANDLE && running && view_pose_valid && frame_state.shouldRender; };
Size2 get_recommended_target_size();
- XRPose::TrackingConfidence get_head_center(Transform3D &r_transform, Vector3 &r_linear_velocity, const Vector3 &r_angular_velocity);
+ XRPose::TrackingConfidence get_head_center(Transform3D &r_transform, Vector3 &r_linear_velocity, Vector3 &r_angular_velocity);
bool get_view_transform(uint32_t p_view, Transform3D &r_transform);
bool get_view_projection(uint32_t p_view, double p_z_near, double p_z_far, CameraMatrix &p_camera_matrix);
bool process();
@@ -285,7 +285,7 @@ public:
bool get_action_bool(RID p_action, RID p_tracker);
float get_action_float(RID p_action, RID p_tracker);
Vector2 get_action_vector2(RID p_action, RID p_tracker);
- XRPose::TrackingConfidence get_action_pose(RID p_action, RID p_tracker, Transform3D &r_transform, Vector3 &r_linear_velocity, const Vector3 &r_angular_velocity);
+ XRPose::TrackingConfidence get_action_pose(RID p_action, RID p_tracker, Transform3D &r_transform, Vector3 &r_linear_velocity, Vector3 &r_angular_velocity);
bool trigger_haptic_pulse(RID p_action, RID p_tracker, float p_frequency, float p_amplitude, XrDuration p_duration_ns);
OpenXRAPI();
diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp
index f7d6ce87dc..86687357d6 100644
--- a/modules/text_server_adv/text_server_adv.cpp
+++ b/modules/text_server_adv/text_server_adv.cpp
@@ -2852,7 +2852,7 @@ Vector2 TextServerAdvanced::font_get_kerning(const RID &p_font_rid, int64_t p_si
ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Vector2());
- const HashMap<Vector2i, Vector2, VariantHasher, VariantComparator> &kern = fd->cache[size]->kerning_map;
+ const HashMap<Vector2i, Vector2> &kern = fd->cache[size]->kerning_map;
if (kern.has(p_glyph_pair)) {
if (fd->msdf) {
diff --git a/modules/text_server_adv/text_server_adv.h b/modules/text_server_adv/text_server_adv.h
index c72454d0bb..e7690cb70d 100644
--- a/modules/text_server_adv/text_server_adv.h
+++ b/modules/text_server_adv/text_server_adv.h
@@ -191,7 +191,7 @@ class TextServerAdvanced : public TextServerExtension {
Vector<FontTexture> textures;
HashMap<int32_t, FontGlyph> glyph_map;
- HashMap<Vector2i, Vector2, VariantHasher, VariantComparator> kerning_map;
+ HashMap<Vector2i, Vector2> kerning_map;
hb_font_t *hb_handle = nullptr;
#ifdef MODULE_FREETYPE_ENABLED
diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp
index 1863baf769..0bece4e7a7 100644
--- a/modules/text_server_fb/text_server_fb.cpp
+++ b/modules/text_server_fb/text_server_fb.cpp
@@ -2000,7 +2000,7 @@ Vector2 TextServerFallback::font_get_kerning(const RID &p_font_rid, int64_t p_si
ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Vector2());
- const HashMap<Vector2i, Vector2, VariantHasher, VariantComparator> &kern = fd->cache[size]->kerning_map;
+ const HashMap<Vector2i, Vector2> &kern = fd->cache[size]->kerning_map;
if (kern.has(p_glyph_pair)) {
if (fd->msdf) {
diff --git a/modules/text_server_fb/text_server_fb.h b/modules/text_server_fb/text_server_fb.h
index c085b58898..e4c81aed5b 100644
--- a/modules/text_server_fb/text_server_fb.h
+++ b/modules/text_server_fb/text_server_fb.h
@@ -159,7 +159,7 @@ class TextServerFallback : public TextServerExtension {
Vector<FontTexture> textures;
HashMap<int32_t, FontGlyph> glyph_map;
- HashMap<Vector2i, Vector2, VariantHasher, VariantComparator> kerning_map;
+ HashMap<Vector2i, Vector2> kerning_map;
#ifdef MODULE_FREETYPE_ENABLED
FT_Face face = nullptr;
diff --git a/scene/2d/navigation_agent_2d.cpp b/scene/2d/navigation_agent_2d.cpp
index 7186a63452..e2ab4f7538 100644
--- a/scene/2d/navigation_agent_2d.cpp
+++ b/scene/2d/navigation_agent_2d.cpp
@@ -61,8 +61,8 @@ void NavigationAgent2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_path_max_distance", "max_speed"), &NavigationAgent2D::set_path_max_distance);
ClassDB::bind_method(D_METHOD("get_path_max_distance"), &NavigationAgent2D::get_path_max_distance);
- ClassDB::bind_method(D_METHOD("set_navigable_layers", "navigable_layers"), &NavigationAgent2D::set_navigable_layers);
- ClassDB::bind_method(D_METHOD("get_navigable_layers"), &NavigationAgent2D::get_navigable_layers);
+ ClassDB::bind_method(D_METHOD("set_navigation_layers", "navigation_layers"), &NavigationAgent2D::set_navigation_layers);
+ ClassDB::bind_method(D_METHOD("get_navigation_layers"), &NavigationAgent2D::get_navigation_layers);
ClassDB::bind_method(D_METHOD("set_navigation_map", "navigation_map"), &NavigationAgent2D::set_navigation_map);
ClassDB::bind_method(D_METHOD("get_navigation_map"), &NavigationAgent2D::get_navigation_map);
@@ -89,7 +89,7 @@ void NavigationAgent2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_speed", PROPERTY_HINT_RANGE, "0.1,100000,0.01,suffix:px/s"), "set_max_speed", "get_max_speed");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_max_distance", PROPERTY_HINT_RANGE, "10,100,1,suffix:px"), "set_path_max_distance", "get_path_max_distance");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "avoidance_enabled"), "set_avoidance_enabled", "get_avoidance_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "navigable_layers", PROPERTY_HINT_LAYERS_2D_NAVIGATION), "set_navigable_layers", "get_navigable_layers");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_2D_NAVIGATION), "set_navigation_layers", "get_navigation_layers");
ADD_SIGNAL(MethodInfo("path_changed"));
ADD_SIGNAL(MethodInfo("target_reached"));
@@ -207,16 +207,16 @@ void NavigationAgent2D::set_agent_parent(Node *p_agent_parent) {
}
}
-void NavigationAgent2D::set_navigable_layers(uint32_t p_layers) {
- bool layers_changed = navigable_layers != p_layers;
- navigable_layers = p_layers;
- if (layers_changed) {
+void NavigationAgent2D::set_navigation_layers(uint32_t p_navigation_layers) {
+ bool navigation_layers_changed = navigation_layers != p_navigation_layers;
+ navigation_layers = p_navigation_layers;
+ if (navigation_layers_changed) {
_request_repath();
}
}
-uint32_t NavigationAgent2D::get_navigable_layers() const {
- return navigable_layers;
+uint32_t NavigationAgent2D::get_navigation_layers() const {
+ return navigation_layers;
}
void NavigationAgent2D::set_navigation_map(RID p_navigation_map) {
@@ -383,9 +383,9 @@ void NavigationAgent2D::update_navigation() {
if (reload_path) {
if (map_override.is_valid()) {
- navigation_path = NavigationServer2D::get_singleton()->map_get_path(map_override, o, target_location, true, navigable_layers);
+ navigation_path = NavigationServer2D::get_singleton()->map_get_path(map_override, o, target_location, true, navigation_layers);
} else {
- navigation_path = NavigationServer2D::get_singleton()->map_get_path(agent_parent->get_world_2d()->get_navigation_map(), o, target_location, true, navigable_layers);
+ navigation_path = NavigationServer2D::get_singleton()->map_get_path(agent_parent->get_world_2d()->get_navigation_map(), o, target_location, true, navigation_layers);
}
navigation_finished = false;
nav_path_index = 0;
diff --git a/scene/2d/navigation_agent_2d.h b/scene/2d/navigation_agent_2d.h
index 4c4880f77e..0e494a0512 100644
--- a/scene/2d/navigation_agent_2d.h
+++ b/scene/2d/navigation_agent_2d.h
@@ -45,7 +45,7 @@ class NavigationAgent2D : public Node {
RID map_override;
bool avoidance_enabled = false;
- uint32_t navigable_layers = 1;
+ uint32_t navigation_layers = 1;
real_t target_desired_distance = 1.0;
real_t radius = 0.0;
@@ -85,8 +85,8 @@ public:
void set_agent_parent(Node *p_agent_parent);
- void set_navigable_layers(uint32_t p_layers);
- uint32_t get_navigable_layers() const;
+ void set_navigation_layers(uint32_t p_navigation_layers);
+ uint32_t get_navigation_layers() const;
void set_navigation_map(RID p_navigation_map);
RID get_navigation_map() const;
diff --git a/scene/2d/navigation_region_2d.cpp b/scene/2d/navigation_region_2d.cpp
index 6f3222f27e..d611e524a6 100644
--- a/scene/2d/navigation_region_2d.cpp
+++ b/scene/2d/navigation_region_2d.cpp
@@ -380,12 +380,12 @@ bool NavigationRegion2D::is_enabled() const {
return enabled;
}
-void NavigationRegion2D::set_layers(uint32_t p_layers) {
- NavigationServer2D::get_singleton()->region_set_layers(region, p_layers);
+void NavigationRegion2D::set_navigation_layers(uint32_t p_navigation_layers) {
+ NavigationServer2D::get_singleton()->region_set_navigation_layers(region, p_navigation_layers);
}
-uint32_t NavigationRegion2D::get_layers() const {
- return NavigationServer2D::get_singleton()->region_get_layers(region);
+uint32_t NavigationRegion2D::get_navigation_layers() const {
+ return NavigationServer2D::get_singleton()->region_get_navigation_layers(region);
}
void NavigationRegion2D::set_enter_cost(real_t p_enter_cost) {
@@ -559,8 +559,8 @@ void NavigationRegion2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationRegion2D::set_enabled);
ClassDB::bind_method(D_METHOD("is_enabled"), &NavigationRegion2D::is_enabled);
- ClassDB::bind_method(D_METHOD("set_layers", "layers"), &NavigationRegion2D::set_layers);
- ClassDB::bind_method(D_METHOD("get_layers"), &NavigationRegion2D::get_layers);
+ ClassDB::bind_method(D_METHOD("set_navigation_layers", "navigation_layers"), &NavigationRegion2D::set_navigation_layers);
+ ClassDB::bind_method(D_METHOD("get_navigation_layers"), &NavigationRegion2D::get_navigation_layers);
ClassDB::bind_method(D_METHOD("get_region_rid"), &NavigationRegion2D::get_region_rid);
@@ -574,7 +574,7 @@ void NavigationRegion2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "navpoly", PROPERTY_HINT_RESOURCE_TYPE, "NavigationPolygon"), "set_navigation_polygon", "get_navigation_polygon");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "layers", PROPERTY_HINT_LAYERS_2D_NAVIGATION), "set_layers", "get_layers");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_2D_NAVIGATION), "set_navigation_layers", "get_navigation_layers");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "enter_cost"), "set_enter_cost", "get_enter_cost");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "travel_cost"), "set_travel_cost", "get_travel_cost");
}
diff --git a/scene/2d/navigation_region_2d.h b/scene/2d/navigation_region_2d.h
index 31574749f7..000cb32f95 100644
--- a/scene/2d/navigation_region_2d.h
+++ b/scene/2d/navigation_region_2d.h
@@ -117,8 +117,8 @@ public:
void set_enabled(bool p_enabled);
bool is_enabled() const;
- void set_layers(uint32_t p_layers);
- uint32_t get_layers() const;
+ void set_navigation_layers(uint32_t p_navigation_layers);
+ uint32_t get_navigation_layers() const;
RID get_region_rid() const;
diff --git a/scene/3d/navigation_agent_3d.cpp b/scene/3d/navigation_agent_3d.cpp
index 425c5df126..09d75dd284 100644
--- a/scene/3d/navigation_agent_3d.cpp
+++ b/scene/3d/navigation_agent_3d.cpp
@@ -65,8 +65,8 @@ void NavigationAgent3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_path_max_distance", "max_speed"), &NavigationAgent3D::set_path_max_distance);
ClassDB::bind_method(D_METHOD("get_path_max_distance"), &NavigationAgent3D::get_path_max_distance);
- ClassDB::bind_method(D_METHOD("set_navigable_layers", "navigable_layers"), &NavigationAgent3D::set_navigable_layers);
- ClassDB::bind_method(D_METHOD("get_navigable_layers"), &NavigationAgent3D::get_navigable_layers);
+ ClassDB::bind_method(D_METHOD("set_navigation_layers", "navigation_layers"), &NavigationAgent3D::set_navigation_layers);
+ ClassDB::bind_method(D_METHOD("get_navigation_layers"), &NavigationAgent3D::get_navigation_layers);
ClassDB::bind_method(D_METHOD("set_navigation_map", "navigation_map"), &NavigationAgent3D::set_navigation_map);
ClassDB::bind_method(D_METHOD("get_navigation_map"), &NavigationAgent3D::get_navigation_map);
@@ -95,7 +95,7 @@ void NavigationAgent3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_max_distance", PROPERTY_HINT_RANGE, "0.01,100,0.1,suffix:m"), "set_path_max_distance", "get_path_max_distance");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ignore_y"), "set_ignore_y", "get_ignore_y");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "avoidance_enabled"), "set_avoidance_enabled", "get_avoidance_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "navigable_layers", PROPERTY_HINT_LAYERS_3D_NAVIGATION), "set_navigable_layers", "get_navigable_layers");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_3D_NAVIGATION), "set_navigation_layers", "get_navigation_layers");
ADD_SIGNAL(MethodInfo("path_changed"));
ADD_SIGNAL(MethodInfo("target_reached"));
@@ -214,16 +214,16 @@ void NavigationAgent3D::set_agent_parent(Node *p_agent_parent) {
}
}
-void NavigationAgent3D::set_navigable_layers(uint32_t p_layers) {
- bool layers_changed = navigable_layers != p_layers;
- navigable_layers = p_layers;
- if (layers_changed) {
+void NavigationAgent3D::set_navigation_layers(uint32_t p_navigation_layers) {
+ bool navigation_layers_changed = navigation_layers != p_navigation_layers;
+ navigation_layers = p_navigation_layers;
+ if (navigation_layers_changed) {
_request_repath();
}
}
-uint32_t NavigationAgent3D::get_navigable_layers() const {
- return navigable_layers;
+uint32_t NavigationAgent3D::get_navigation_layers() const {
+ return navigation_layers;
}
void NavigationAgent3D::set_navigation_map(RID p_navigation_map) {
@@ -400,9 +400,9 @@ void NavigationAgent3D::update_navigation() {
if (reload_path) {
if (map_override.is_valid()) {
- navigation_path = NavigationServer3D::get_singleton()->map_get_path(map_override, o, target_location, true, navigable_layers);
+ navigation_path = NavigationServer3D::get_singleton()->map_get_path(map_override, o, target_location, true, navigation_layers);
} else {
- navigation_path = NavigationServer3D::get_singleton()->map_get_path(agent_parent->get_world_3d()->get_navigation_map(), o, target_location, true, navigable_layers);
+ navigation_path = NavigationServer3D::get_singleton()->map_get_path(agent_parent->get_world_3d()->get_navigation_map(), o, target_location, true, navigation_layers);
}
navigation_finished = false;
nav_path_index = 0;
diff --git a/scene/3d/navigation_agent_3d.h b/scene/3d/navigation_agent_3d.h
index 8e5cb83f6e..d0eaead3f1 100644
--- a/scene/3d/navigation_agent_3d.h
+++ b/scene/3d/navigation_agent_3d.h
@@ -45,7 +45,7 @@ class NavigationAgent3D : public Node {
RID map_override;
bool avoidance_enabled = false;
- uint32_t navigable_layers = 1;
+ uint32_t navigation_layers = 1;
real_t target_desired_distance = 1.0;
real_t radius = 0.0;
@@ -87,8 +87,8 @@ public:
void set_agent_parent(Node *p_agent_parent);
- void set_navigable_layers(uint32_t p_layers);
- uint32_t get_navigable_layers() const;
+ void set_navigation_layers(uint32_t p_navigation_layers);
+ uint32_t get_navigation_layers() const;
void set_navigation_map(RID p_navigation_map);
RID get_navigation_map() const;
diff --git a/scene/3d/navigation_region_3d.cpp b/scene/3d/navigation_region_3d.cpp
index dda1382814..7ef16fbc0a 100644
--- a/scene/3d/navigation_region_3d.cpp
+++ b/scene/3d/navigation_region_3d.cpp
@@ -65,12 +65,12 @@ bool NavigationRegion3D::is_enabled() const {
return enabled;
}
-void NavigationRegion3D::set_layers(uint32_t p_layers) {
- NavigationServer3D::get_singleton()->region_set_layers(region, p_layers);
+void NavigationRegion3D::set_navigation_layers(uint32_t p_navigation_layers) {
+ NavigationServer3D::get_singleton()->region_set_navigation_layers(region, p_navigation_layers);
}
-uint32_t NavigationRegion3D::get_layers() const {
- return NavigationServer3D::get_singleton()->region_get_layers(region);
+uint32_t NavigationRegion3D::get_navigation_layers() const {
+ return NavigationServer3D::get_singleton()->region_get_navigation_layers(region);
}
void NavigationRegion3D::set_enter_cost(real_t p_enter_cost) {
@@ -239,8 +239,8 @@ void NavigationRegion3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationRegion3D::set_enabled);
ClassDB::bind_method(D_METHOD("is_enabled"), &NavigationRegion3D::is_enabled);
- ClassDB::bind_method(D_METHOD("set_layers", "layers"), &NavigationRegion3D::set_layers);
- ClassDB::bind_method(D_METHOD("get_layers"), &NavigationRegion3D::get_layers);
+ ClassDB::bind_method(D_METHOD("set_navigation_layers", "navigation_layers"), &NavigationRegion3D::set_navigation_layers);
+ ClassDB::bind_method(D_METHOD("get_navigation_layers"), &NavigationRegion3D::get_navigation_layers);
ClassDB::bind_method(D_METHOD("get_region_rid"), &NavigationRegion3D::get_region_rid);
@@ -255,7 +255,7 @@ void NavigationRegion3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "navmesh", PROPERTY_HINT_RESOURCE_TYPE, "NavigationMesh"), "set_navigation_mesh", "get_navigation_mesh");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "layers", PROPERTY_HINT_LAYERS_3D_NAVIGATION), "set_layers", "get_layers");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_3D_NAVIGATION), "set_navigation_layers", "get_navigation_layers");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "enter_cost"), "set_enter_cost", "get_enter_cost");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "travel_cost"), "set_travel_cost", "get_travel_cost");
diff --git a/scene/3d/navigation_region_3d.h b/scene/3d/navigation_region_3d.h
index 042684c5b7..92474d1429 100644
--- a/scene/3d/navigation_region_3d.h
+++ b/scene/3d/navigation_region_3d.h
@@ -57,8 +57,8 @@ public:
void set_enabled(bool p_enabled);
bool is_enabled() const;
- void set_layers(uint32_t p_layers);
- uint32_t get_layers() const;
+ void set_navigation_layers(uint32_t p_navigation_layers);
+ uint32_t get_navigation_layers() const;
RID get_region_rid() const;
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index c9eecf54dd..5931c112eb 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -1274,6 +1274,11 @@ Ref<Shortcut> PopupMenu::get_item_shortcut(int p_idx) const {
return items[p_idx].shortcut;
}
+int PopupMenu::get_item_horizontal_offset(int p_idx) const {
+ ERR_FAIL_INDEX_V(p_idx, items.size(), 0);
+ return items[p_idx].h_ofs;
+}
+
int PopupMenu::get_item_state(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, items.size(), -1);
return items[p_idx].state;
@@ -1339,7 +1344,7 @@ void PopupMenu::set_item_shortcut(int p_idx, const Ref<Shortcut> &p_shortcut, bo
control->update();
}
-void PopupMenu::set_item_h_offset(int p_idx, int p_offset) {
+void PopupMenu::set_item_horizontal_offset(int p_idx, int p_offset) {
if (p_idx < 0) {
p_idx += get_item_count();
}
@@ -1862,6 +1867,7 @@ void PopupMenu::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_item_as_radio_checkable", "index", "enable"), &PopupMenu::set_item_as_radio_checkable);
ClassDB::bind_method(D_METHOD("set_item_tooltip", "index", "tooltip"), &PopupMenu::set_item_tooltip);
ClassDB::bind_method(D_METHOD("set_item_shortcut", "index", "shortcut", "global"), &PopupMenu::set_item_shortcut, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("set_item_horizontal_offset", "index", "offset"), &PopupMenu::set_item_horizontal_offset);
ClassDB::bind_method(D_METHOD("set_item_multistate", "index", "state"), &PopupMenu::set_item_multistate);
ClassDB::bind_method(D_METHOD("set_item_shortcut_disabled", "index", "disabled"), &PopupMenu::set_item_shortcut_disabled);
@@ -1887,6 +1893,7 @@ void PopupMenu::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_item_shortcut_disabled", "index"), &PopupMenu::is_item_shortcut_disabled);
ClassDB::bind_method(D_METHOD("get_item_tooltip", "index"), &PopupMenu::get_item_tooltip);
ClassDB::bind_method(D_METHOD("get_item_shortcut", "index"), &PopupMenu::get_item_shortcut);
+ ClassDB::bind_method(D_METHOD("get_item_horizontal_offset", "index"), &PopupMenu::get_item_horizontal_offset);
ClassDB::bind_method(D_METHOD("set_current_index", "index"), &PopupMenu::set_current_index);
ClassDB::bind_method(D_METHOD("get_current_index"), &PopupMenu::get_current_index);
diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h
index 53bc5a8c22..8218c6122e 100644
--- a/scene/gui/popup_menu.h
+++ b/scene/gui/popup_menu.h
@@ -186,7 +186,7 @@ public:
void set_item_as_radio_checkable(int p_idx, bool p_radio_checkable);
void set_item_tooltip(int p_idx, const String &p_tooltip);
void set_item_shortcut(int p_idx, const Ref<Shortcut> &p_shortcut, bool p_global = false);
- void set_item_h_offset(int p_idx, int p_offset);
+ void set_item_horizontal_offset(int p_idx, int p_offset);
void set_item_multistate(int p_idx, int p_state);
void toggle_item_multistate(int p_idx);
void set_item_shortcut_disabled(int p_idx, bool p_disabled);
@@ -212,6 +212,7 @@ public:
bool is_item_shortcut_disabled(int p_idx) const;
String get_item_tooltip(int p_idx) const;
Ref<Shortcut> get_item_shortcut(int p_idx) const;
+ int get_item_horizontal_offset(int p_idx) const;
int get_item_state(int p_idx) const;
void set_current_index(int p_idx);
diff --git a/servers/navigation_server_2d.cpp b/servers/navigation_server_2d.cpp
index ab323e76e8..0442089503 100644
--- a/servers/navigation_server_2d.cpp
+++ b/servers/navigation_server_2d.cpp
@@ -166,7 +166,7 @@ void NavigationServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("map_get_cell_size", "map"), &NavigationServer2D::map_get_cell_size);
ClassDB::bind_method(D_METHOD("map_set_edge_connection_margin", "map", "margin"), &NavigationServer2D::map_set_edge_connection_margin);
ClassDB::bind_method(D_METHOD("map_get_edge_connection_margin", "map"), &NavigationServer2D::map_get_edge_connection_margin);
- ClassDB::bind_method(D_METHOD("map_get_path", "map", "origin", "destination", "optimize", "layers"), &NavigationServer2D::map_get_path, DEFVAL(1));
+ ClassDB::bind_method(D_METHOD("map_get_path", "map", "origin", "destination", "optimize", "navigation_layers"), &NavigationServer2D::map_get_path, DEFVAL(1));
ClassDB::bind_method(D_METHOD("map_get_closest_point", "map", "to_point"), &NavigationServer2D::map_get_closest_point);
ClassDB::bind_method(D_METHOD("map_get_closest_point_owner", "map", "to_point"), &NavigationServer2D::map_get_closest_point_owner);
@@ -180,8 +180,8 @@ void NavigationServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("region_get_travel_cost", "region"), &NavigationServer2D::region_get_travel_cost);
ClassDB::bind_method(D_METHOD("region_set_map", "region", "map"), &NavigationServer2D::region_set_map);
ClassDB::bind_method(D_METHOD("region_get_map", "region"), &NavigationServer2D::region_get_map);
- ClassDB::bind_method(D_METHOD("region_set_layers", "region", "layers"), &NavigationServer2D::region_set_layers);
- ClassDB::bind_method(D_METHOD("region_get_layers", "region"), &NavigationServer2D::region_get_layers);
+ ClassDB::bind_method(D_METHOD("region_set_navigation_layers", "region", "navigation_layers"), &NavigationServer2D::region_set_navigation_layers);
+ ClassDB::bind_method(D_METHOD("region_get_navigation_layers", "region"), &NavigationServer2D::region_get_navigation_layers);
ClassDB::bind_method(D_METHOD("region_set_transform", "region", "transform"), &NavigationServer2D::region_set_transform);
ClassDB::bind_method(D_METHOD("region_set_navpoly", "region", "nav_poly"), &NavigationServer2D::region_set_navpoly);
ClassDB::bind_method(D_METHOD("region_get_connections_count", "region"), &NavigationServer2D::region_get_connections_count);
@@ -250,8 +250,8 @@ void FORWARD_2_C(region_set_travel_cost, RID, p_region, real_t, p_travel_cost, r
real_t FORWARD_1_C(region_get_travel_cost, RID, p_region, rid_to_rid);
void FORWARD_2_C(region_set_map, RID, p_region, RID, p_map, rid_to_rid, rid_to_rid);
-void FORWARD_2_C(region_set_layers, RID, p_region, uint32_t, p_layers, rid_to_rid, uint32_to_uint32);
-uint32_t FORWARD_1_C(region_get_layers, RID, p_region, rid_to_rid);
+void FORWARD_2_C(region_set_navigation_layers, RID, p_region, uint32_t, p_navigation_layers, rid_to_rid, uint32_to_uint32);
+uint32_t FORWARD_1_C(region_get_navigation_layers, RID, p_region, rid_to_rid);
void FORWARD_2_C(region_set_transform, RID, p_region, Transform2D, p_transform, rid_to_rid, trf2_to_trf3);
void NavigationServer2D::region_set_navpoly(RID p_region, Ref<NavigationPolygon> p_nav_mesh) const {
diff --git a/servers/navigation_server_2d.h b/servers/navigation_server_2d.h
index 8e285147b1..30f553d10b 100644
--- a/servers/navigation_server_2d.h
+++ b/servers/navigation_server_2d.h
@@ -75,7 +75,7 @@ public:
virtual real_t map_get_edge_connection_margin(RID p_map) const;
/// Returns the navigation path to reach the destination from the origin.
- virtual Vector<Vector2> map_get_path(RID p_map, Vector2 p_origin, Vector2 p_destination, bool p_optimize, uint32_t p_layers = 1) const;
+ virtual Vector<Vector2> map_get_path(RID p_map, Vector2 p_origin, Vector2 p_destination, bool p_optimize, uint32_t p_navigation_layers = 1) const;
virtual Vector2 map_get_closest_point(RID p_map, const Vector2 &p_point) const;
virtual RID map_get_closest_point_owner(RID p_map, const Vector2 &p_point) const;
@@ -99,8 +99,8 @@ public:
virtual RID region_get_map(RID p_region) const;
/// Set the region's layers
- virtual void region_set_layers(RID p_region, uint32_t p_layers) const;
- virtual uint32_t region_get_layers(RID p_region) const;
+ virtual void region_set_navigation_layers(RID p_region, uint32_t p_navigation_layers) const;
+ virtual uint32_t region_get_navigation_layers(RID p_region) const;
/// Set the global transformation of this region.
virtual void region_set_transform(RID p_region, Transform2D p_transform) const;
diff --git a/servers/navigation_server_3d.cpp b/servers/navigation_server_3d.cpp
index 6d99f6dfbb..60bbcec8d4 100644
--- a/servers/navigation_server_3d.cpp
+++ b/servers/navigation_server_3d.cpp
@@ -42,7 +42,7 @@ void NavigationServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("map_get_cell_size", "map"), &NavigationServer3D::map_get_cell_size);
ClassDB::bind_method(D_METHOD("map_set_edge_connection_margin", "map", "margin"), &NavigationServer3D::map_set_edge_connection_margin);
ClassDB::bind_method(D_METHOD("map_get_edge_connection_margin", "map"), &NavigationServer3D::map_get_edge_connection_margin);
- ClassDB::bind_method(D_METHOD("map_get_path", "map", "origin", "destination", "optimize", "layers"), &NavigationServer3D::map_get_path, DEFVAL(1));
+ ClassDB::bind_method(D_METHOD("map_get_path", "map", "origin", "destination", "optimize", "navigation_layers"), &NavigationServer3D::map_get_path, DEFVAL(1));
ClassDB::bind_method(D_METHOD("map_get_closest_point_to_segment", "map", "start", "end", "use_collision"), &NavigationServer3D::map_get_closest_point_to_segment, DEFVAL(false));
ClassDB::bind_method(D_METHOD("map_get_closest_point", "map", "to_point"), &NavigationServer3D::map_get_closest_point);
ClassDB::bind_method(D_METHOD("map_get_closest_point_normal", "map", "to_point"), &NavigationServer3D::map_get_closest_point_normal);
@@ -58,8 +58,8 @@ void NavigationServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("region_get_travel_cost", "region"), &NavigationServer3D::region_get_travel_cost);
ClassDB::bind_method(D_METHOD("region_set_map", "region", "map"), &NavigationServer3D::region_set_map);
ClassDB::bind_method(D_METHOD("region_get_map", "region"), &NavigationServer3D::region_get_map);
- ClassDB::bind_method(D_METHOD("region_set_layers", "region", "layers"), &NavigationServer3D::region_set_layers);
- ClassDB::bind_method(D_METHOD("region_get_layers", "region"), &NavigationServer3D::region_get_layers);
+ ClassDB::bind_method(D_METHOD("region_set_navigation_layers", "region", "navigation_layers"), &NavigationServer3D::region_set_navigation_layers);
+ ClassDB::bind_method(D_METHOD("region_get_navigation_layers", "region"), &NavigationServer3D::region_get_navigation_layers);
ClassDB::bind_method(D_METHOD("region_set_transform", "region", "transform"), &NavigationServer3D::region_set_transform);
ClassDB::bind_method(D_METHOD("region_set_navmesh", "region", "nav_mesh"), &NavigationServer3D::region_set_navmesh);
ClassDB::bind_method(D_METHOD("region_bake_navmesh", "mesh", "node"), &NavigationServer3D::region_bake_navmesh);
diff --git a/servers/navigation_server_3d.h b/servers/navigation_server_3d.h
index 9b7e48e8d1..9c04d68622 100644
--- a/servers/navigation_server_3d.h
+++ b/servers/navigation_server_3d.h
@@ -84,7 +84,7 @@ public:
virtual real_t map_get_edge_connection_margin(RID p_map) const = 0;
/// Returns the navigation path to reach the destination from the origin.
- virtual Vector<Vector3> map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_navigable_layers = 1) const = 0;
+ virtual Vector<Vector3> map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_navigation_layers = 1) const = 0;
virtual Vector3 map_get_closest_point_to_segment(RID p_map, const Vector3 &p_from, const Vector3 &p_to, const bool p_use_collision = false) const = 0;
virtual Vector3 map_get_closest_point(RID p_map, const Vector3 &p_point) const = 0;
@@ -110,8 +110,8 @@ public:
virtual RID region_get_map(RID p_region) const = 0;
/// Set the region's layers
- virtual void region_set_layers(RID p_region, uint32_t p_layers) const = 0;
- virtual uint32_t region_get_layers(RID p_region) const = 0;
+ virtual void region_set_navigation_layers(RID p_region, uint32_t p_navigation_layers) const = 0;
+ virtual uint32_t region_get_navigation_layers(RID p_region) const = 0;
/// Set the global transformation of this region.
virtual void region_set_transform(RID p_region, Transform3D p_transform) const = 0;