summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.git-blame-ignore-revs3
-rw-r--r--SConstruct20
-rw-r--r--core/extension/gdextension_interface.cpp2
-rw-r--r--core/extension/gdextension_interface.h4
-rw-r--r--core/io/dir_access.h4
-rw-r--r--core/io/file_access.h4
-rw-r--r--core/io/image.cpp10
-rw-r--r--core/math/bvh.h2
-rw-r--r--core/math/bvh_abb.h2
-rw-r--r--core/math/bvh_tree.h8
-rw-r--r--core/math/disjoint_set.h14
-rw-r--r--core/math/dynamic_bvh.h12
-rw-r--r--core/math/expression.h2
-rw-r--r--core/math/projection.h2
-rw-r--r--core/math/random_pcg.h2
-rw-r--r--core/object/callable_method_pointer.h20
-rw-r--r--core/object/class_db.h32
-rw-r--r--core/object/method_bind.h42
-rw-r--r--core/object/object.cpp4
-rw-r--r--core/object/object.h4
-rw-r--r--core/object/ref_counted.h20
-rw-r--r--core/object/script_language_extension.h9
-rw-r--r--core/object/worker_thread_pool.h8
-rw-r--r--core/os/condition_variable.h4
-rw-r--r--core/os/memory.h10
-rw-r--r--core/os/mutex.h8
-rw-r--r--core/string/ustring.cpp2
-rw-r--r--core/string/ustring.h6
-rw-r--r--core/templates/bin_sorted_array.h2
-rw-r--r--core/templates/command_queue_mt.h68
-rw-r--r--core/templates/cowdata.h28
-rw-r--r--core/templates/hash_map.h10
-rw-r--r--core/templates/hash_set.h6
-rw-r--r--core/templates/hashfuncs.h12
-rw-r--r--core/templates/list.h12
-rw-r--r--core/templates/local_vector.h6
-rw-r--r--core/templates/lru.h2
-rw-r--r--core/templates/oa_hash_map.h6
-rw-r--r--core/templates/paged_allocator.h6
-rw-r--r--core/templates/paged_array.h4
-rw-r--r--core/templates/pair.h18
-rw-r--r--core/templates/pooled_list.h4
-rw-r--r--core/templates/rb_map.h2
-rw-r--r--core/templates/rb_set.h2
-rw-r--r--core/templates/rid_owner.h6
-rw-r--r--core/templates/safe_list.h2
-rw-r--r--core/templates/safe_refcount.h2
-rw-r--r--core/templates/search_array.h2
-rw-r--r--core/templates/self_list.h4
-rw-r--r--core/templates/simple_type.h8
-rw-r--r--core/templates/sort_array.h4
-rw-r--r--core/templates/vector.h16
-rw-r--r--core/templates/vmap.h2
-rw-r--r--core/templates/vset.h2
-rw-r--r--core/typedefs.h6
-rw-r--r--core/variant/binder_common.h142
-rw-r--r--core/variant/method_ptrcall.h6
-rw-r--r--core/variant/native_ptr.h12
-rw-r--r--core/variant/type_info.h4
-rw-r--r--core/variant/typed_array.h14
-rw-r--r--core/variant/variant.cpp6
-rw-r--r--core/variant/variant.h2
-rw-r--r--core/variant/variant_call.cpp138
-rw-r--r--core/variant/variant_construct.cpp2
-rw-r--r--core/variant/variant_construct.h12
-rw-r--r--core/variant/variant_destruct.cpp2
-rw-r--r--core/variant/variant_destruct.h2
-rw-r--r--core/variant/variant_internal.h20
-rw-r--r--core/variant/variant_op.cpp2
-rw-r--r--core/variant/variant_op.h80
-rw-r--r--core/variant/variant_parser.cpp2
-rw-r--r--core/variant/variant_parser.h2
-rw-r--r--core/variant/variant_setget.cpp6
-rw-r--r--core/variant/variant_utility.cpp38
-rw-r--r--doc/classes/NativeMenu.xml142
-rw-r--r--doc/classes/PopupMenu.xml3
-rw-r--r--doc/classes/RayCast2D.xml5
-rw-r--r--doc/classes/RayCast3D.xml5
-rw-r--r--doc/classes/ScriptExtension.xml1
-rw-r--r--doc/classes/Time.xml4
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.h2
-rw-r--r--editor/debugger/debug_adapter/debug_adapter_parser.cpp4
-rw-r--r--editor/debugger/debug_adapter/debug_adapter_parser.h3
-rw-r--r--editor/debugger/debug_adapter/debug_adapter_protocol.cpp8
-rw-r--r--editor/debugger/debug_adapter/debug_adapter_protocol.h4
-rw-r--r--editor/debugger/script_editor_debugger.cpp4
-rw-r--r--editor/editor_data.h2
-rw-r--r--editor/editor_help_search.h2
-rw-r--r--editor/editor_node.cpp5
-rw-r--r--editor/editor_plugin.h4
-rw-r--r--editor/filesystem_dock.cpp56
-rw-r--r--editor/filesystem_dock.h5
-rw-r--r--editor/gui/editor_bottom_panel.cpp6
-rw-r--r--editor/import/3d/resource_importer_scene.h8
-rw-r--r--editor/themes/editor_theme_manager.cpp41
-rw-r--r--main/main.h2
-rw-r--r--modules/gdscript/doc_classes/@GDScript.xml6
-rw-r--r--modules/gdscript/gdscript_parser.cpp2
-rw-r--r--modules/gdscript/gdscript_parser.h8
-rw-r--r--modules/gltf/gltf_document.cpp444
-rw-r--r--modules/gltf/gltf_document.h26
-rw-r--r--modules/gltf/gltf_template_convert.h12
-rw-r--r--modules/gltf/structures/gltf_animation.h2
-rw-r--r--modules/multiplayer/scene_replication_interface.h2
-rw-r--r--modules/openxr/doc_classes/OpenXRExtensionWrapperExtension.xml19
-rw-r--r--modules/openxr/extensions/openxr_composition_layer_depth_extension.cpp11
-rw-r--r--modules/openxr/extensions/openxr_composition_layer_depth_extension.h4
-rw-r--r--modules/openxr/extensions/openxr_composition_layer_provider.h4
-rw-r--r--modules/openxr/extensions/openxr_extension_wrapper_extension.cpp20
-rw-r--r--modules/openxr/extensions/openxr_extension_wrapper_extension.h8
-rw-r--r--modules/openxr/openxr_api.cpp32
-rw-r--r--modules/openxr/openxr_api.h9
-rw-r--r--modules/websocket/packet_buffer.h2
-rw-r--r--platform/macos/native_menu_macos.h1
-rw-r--r--platform/macos/native_menu_macos.mm10
-rw-r--r--platform/windows/SCsub1
-rw-r--r--platform/windows/display_server_windows.cpp5
-rw-r--r--platform/windows/display_server_windows.h4
-rw-r--r--platform/windows/native_menu_windows.cpp1149
-rw-r--r--platform/windows/native_menu_windows.h151
-rw-r--r--platform/windows/os_windows.h2
-rw-r--r--scene/2d/physics/rigid_body_2d.cpp23
-rw-r--r--scene/3d/physics/rigid_body_3d.cpp21
-rw-r--r--scene/gui/code_edit.cpp9
-rw-r--r--scene/gui/dialogs.cpp8
-rw-r--r--scene/gui/menu_bar.cpp10
-rw-r--r--scene/gui/menu_bar.h2
-rw-r--r--scene/gui/popup_menu.cpp61
-rw-r--r--scene/gui/popup_menu.h5
-rw-r--r--scene/main/node.h2
-rw-r--r--scene/resources/animation.cpp10
-rw-r--r--scene/resources/animation.h12
-rw-r--r--scene/resources/audio_stream_wav.cpp2
-rw-r--r--scene/resources/audio_stream_wav.h2
-rw-r--r--scene/resources/material.cpp989
-rw-r--r--scu_builders.py2
-rw-r--r--servers/camera_server.h4
-rw-r--r--servers/native_menu.cpp8
-rw-r--r--servers/native_menu.h5
-rw-r--r--servers/physics_2d/godot_broad_phase_2d_bvh.h4
-rw-r--r--servers/physics_2d/godot_collision_solver_2d_sat.cpp2
-rw-r--r--servers/physics_3d/godot_broad_phase_3d_bvh.h4
-rw-r--r--servers/physics_3d/godot_collision_solver_3d_sat.cpp2
-rw-r--r--servers/rendering/renderer_canvas_cull.cpp2
-rw-r--r--servers/rendering/renderer_canvas_cull.h2
-rw-r--r--servers/rendering/renderer_canvas_render.h2
-rw-r--r--servers/rendering/renderer_rd/cluster_builder_rd.cpp6
-rw-r--r--servers/rendering/rendering_device.cpp2
-rw-r--r--servers/rendering/rendering_device.h2
-rw-r--r--servers/rendering/rendering_device_driver.h8
-rw-r--r--servers/rendering/shader_language.h2
-rw-r--r--servers/rendering/storage/variant_converters.h4
152 files changed, 3295 insertions, 1166 deletions
diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
index eed5b661b8..ebfd3b515a 100644
--- a/.git-blame-ignore-revs
+++ b/.git-blame-ignore-revs
@@ -51,3 +51,6 @@ bd282ff43f23fe845f29a3e25c8efc01bd65ffb0
# Add "Godot Engine contributors" copyright line
df61dc4b2bd54a5a40c515493c76f5a458e5b541
+
+# Enforce template syntax `typename` over `class`
+9903e6779b70fc03aae70a37b9cf053f4f355b91
diff --git a/SConstruct b/SConstruct
index c11fd50497..753cea40e3 100644
--- a/SConstruct
+++ b/SConstruct
@@ -956,25 +956,25 @@ if selected_platform in platform_list:
env.vs_incs = []
env.vs_srcs = []
- if env["compiledb"]:
- # Generating the compilation DB (`compile_commands.json`) requires SCons 4.0.0 or later.
- from SCons import __version__ as scons_raw_version
-
- scons_ver = env._get_major_minor_revision(scons_raw_version)
-
- if scons_ver < (4, 0, 0):
- print("The `compiledb=yes` option requires SCons 4.0 or later, but your version is %s." % scons_raw_version)
- Exit(255)
+ # CompileDB
+ from SCons import __version__ as scons_raw_version
+ scons_ver = env._get_major_minor_revision(scons_raw_version)
+ if env["compiledb"] and scons_ver < (4, 0, 0):
+ # Generating the compilation DB (`compile_commands.json`) requires SCons 4.0.0 or later.
+ print("The `compiledb=yes` option requires SCons 4.0 or later, but your version is %s." % scons_raw_version)
+ Exit(255)
+ if scons_ver >= (4, 0, 0):
env.Tool("compilation_db")
env.Alias("compiledb", env.CompilationDatabase())
+ # Threads
if env["threads"]:
env.Append(CPPDEFINES=["THREADS_ENABLED"])
+ # Build subdirs, the build order is dependent on link order.
Export("env")
- # Build subdirs, the build order is dependent on link order.
SConscript("core/SCsub")
SConscript("servers/SCsub")
SConscript("scene/SCsub")
diff --git a/core/extension/gdextension_interface.cpp b/core/extension/gdextension_interface.cpp
index ca58d589bd..9b4aa98357 100644
--- a/core/extension/gdextension_interface.cpp
+++ b/core/extension/gdextension_interface.cpp
@@ -1302,6 +1302,7 @@ static GDExtensionScriptInstancePtr gdextension_script_instance_create(const GDE
info_3->get_property_type_func = p_info->get_property_type_func;
info_3->validate_property_func = nullptr;
info_3->has_method_func = p_info->has_method_func;
+ info_3->get_method_argument_count_func = nullptr;
info_3->call_func = p_info->call_func;
info_3->notification_func = nullptr;
info_3->to_string_func = p_info->to_string_func;
@@ -1341,6 +1342,7 @@ static GDExtensionScriptInstancePtr gdextension_script_instance_create2(const GD
info_3->get_property_type_func = p_info->get_property_type_func;
info_3->validate_property_func = nullptr;
info_3->has_method_func = p_info->has_method_func;
+ info_3->get_method_argument_count_func = nullptr;
info_3->call_func = p_info->call_func;
info_3->notification_func = p_info->notification_func;
info_3->to_string_func = p_info->to_string_func;
diff --git a/core/extension/gdextension_interface.h b/core/extension/gdextension_interface.h
index c863507019..e9c570e994 100644
--- a/core/extension/gdextension_interface.h
+++ b/core/extension/gdextension_interface.h
@@ -535,6 +535,8 @@ typedef void (*GDExtensionScriptInstanceFreeMethodList2)(GDExtensionScriptInstan
typedef GDExtensionBool (*GDExtensionScriptInstanceHasMethod)(GDExtensionScriptInstanceDataPtr p_instance, GDExtensionConstStringNamePtr p_name);
+typedef GDExtensionInt (*GDExtensionScriptInstanceGetMethodArgumentCount)(GDExtensionScriptInstanceDataPtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionBool *r_is_valid);
+
typedef void (*GDExtensionScriptInstanceCall)(GDExtensionScriptInstanceDataPtr p_self, GDExtensionConstStringNamePtr p_method, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error);
typedef void (*GDExtensionScriptInstanceNotification)(GDExtensionScriptInstanceDataPtr p_instance, int32_t p_what); // Deprecated. Use GDExtensionScriptInstanceNotification2 instead.
typedef void (*GDExtensionScriptInstanceNotification2)(GDExtensionScriptInstanceDataPtr p_instance, int32_t p_what, GDExtensionBool p_reversed);
@@ -654,6 +656,8 @@ typedef struct {
GDExtensionScriptInstanceHasMethod has_method_func;
+ GDExtensionScriptInstanceGetMethodArgumentCount get_method_argument_count_func;
+
GDExtensionScriptInstanceCall call_func;
GDExtensionScriptInstanceNotification2 notification_func;
diff --git a/core/io/dir_access.h b/core/io/dir_access.h
index d175235b98..e9c864c56b 100644
--- a/core/io/dir_access.h
+++ b/core/io/dir_access.h
@@ -70,7 +70,7 @@ protected:
AccessType get_access_type() const;
virtual String fix_path(const String &p_path) const;
- template <class T>
+ template <typename T>
static Ref<DirAccess> _create_builtin() {
return memnew(T);
}
@@ -130,7 +130,7 @@ public:
static Ref<DirAccess> create(AccessType p_access);
static Error get_open_error();
- template <class T>
+ template <typename T>
static void make_default(AccessType p_access) {
create_func[p_access] = _create_builtin<T>;
}
diff --git a/core/io/file_access.h b/core/io/file_access.h
index 7d346ca2f4..122ae3b190 100644
--- a/core/io/file_access.h
+++ b/core/io/file_access.h
@@ -114,7 +114,7 @@ private:
AccessType _access_type = ACCESS_FILESYSTEM;
static CreateFunc create_func[ACCESS_MAX]; /** default file access creation function for a platform */
- template <class T>
+ template <typename T>
static Ref<FileAccess> _create_builtin() {
return memnew(T);
}
@@ -226,7 +226,7 @@ public:
static PackedByteArray _get_file_as_bytes(const String &p_path) { return get_file_as_bytes(p_path, &last_file_open_error); }
static String _get_file_as_string(const String &p_path) { return get_file_as_string(p_path, &last_file_open_error); }
- template <class T>
+ template <typename T>
static void make_default(AccessType p_access) {
create_func[p_access] = _create_builtin<T>;
}
diff --git a/core/io/image.cpp b/core/io/image.cpp
index b094290ac8..c454f06d67 100644
--- a/core/io/image.cpp
+++ b/core/io/image.cpp
@@ -679,7 +679,7 @@ static double _bicubic_interp_kernel(double x) {
return bc;
}
-template <int CC, class T>
+template <int CC, typename T>
static void _scale_cubic(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) {
// get source image size
int width = p_src_width;
@@ -766,7 +766,7 @@ static void _scale_cubic(const uint8_t *__restrict p_src, uint8_t *__restrict p_
}
}
-template <int CC, class T>
+template <int CC, typename T>
static void _scale_bilinear(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) {
enum {
FRAC_BITS = 8,
@@ -856,7 +856,7 @@ static void _scale_bilinear(const uint8_t *__restrict p_src, uint8_t *__restrict
}
}
-template <int CC, class T>
+template <int CC, typename T>
static void _scale_nearest(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) {
for (uint32_t i = 0; i < p_dst_height; i++) {
uint32_t src_yofs = i * p_src_height / p_dst_height;
@@ -883,7 +883,7 @@ static float _lanczos(float p_x) {
return Math::abs(p_x) >= LANCZOS_TYPE ? 0 : Math::sincn(p_x) * Math::sincn(p_x / LANCZOS_TYPE);
}
-template <int CC, class T>
+template <int CC, typename T>
static void _scale_lanczos(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) {
int32_t src_width = p_src_width;
int32_t src_height = p_src_height;
@@ -1665,7 +1665,7 @@ bool Image::_can_modify(Format p_format) const {
return p_format <= FORMAT_RGBE9995;
}
-template <class Component, int CC, bool renormalize,
+template <typename Component, int CC, bool renormalize,
void (*average_func)(Component &, const Component &, const Component &, const Component &, const Component &),
void (*renormalize_func)(Component *)>
static void _generate_po2_mipmap(const Component *p_src, Component *p_dst, uint32_t p_width, uint32_t p_height) {
diff --git a/core/math/bvh.h b/core/math/bvh.h
index 8fbbd8e7fd..4815466e89 100644
--- a/core/math/bvh.h
+++ b/core/math/bvh.h
@@ -57,7 +57,7 @@
#define BVHTREE_CLASS BVH_Tree<T, NUM_TREES, 2, MAX_ITEMS, USER_PAIR_TEST_FUNCTION, USER_CULL_TEST_FUNCTION, USE_PAIRS, BOUNDS, POINT>
#define BVH_LOCKED_FUNCTION BVHLockedFunction _lock_guard(&_mutex, BVH_THREAD_SAFE &&_thread_safe);
-template <class T, int NUM_TREES = 1, bool USE_PAIRS = false, int MAX_ITEMS = 32, class USER_PAIR_TEST_FUNCTION = BVH_DummyPairTestFunction<T>, class USER_CULL_TEST_FUNCTION = BVH_DummyCullTestFunction<T>, class BOUNDS = AABB, class POINT = Vector3, bool BVH_THREAD_SAFE = true>
+template <typename T, int NUM_TREES = 1, bool USE_PAIRS = false, int MAX_ITEMS = 32, typename USER_PAIR_TEST_FUNCTION = BVH_DummyPairTestFunction<T>, typename USER_CULL_TEST_FUNCTION = BVH_DummyCullTestFunction<T>, typename BOUNDS = AABB, typename POINT = Vector3, bool BVH_THREAD_SAFE = true>
class BVH_Manager {
public:
// note we are using uint32_t instead of BVHHandle, losing type safety, but this
diff --git a/core/math/bvh_abb.h b/core/math/bvh_abb.h
index fb0207e0bd..cec3dc90db 100644
--- a/core/math/bvh_abb.h
+++ b/core/math/bvh_abb.h
@@ -32,7 +32,7 @@
#define BVH_ABB_H
// special optimized version of axis aligned bounding box
-template <class BOUNDS = AABB, class POINT = Vector3>
+template <typename BOUNDS = AABB, typename POINT = Vector3>
struct BVH_ABB {
struct ConvexHull {
// convex hulls (optional)
diff --git a/core/math/bvh_tree.h b/core/math/bvh_tree.h
index ce296668db..0faa50555f 100644
--- a/core/math/bvh_tree.h
+++ b/core/math/bvh_tree.h
@@ -106,7 +106,7 @@ struct BVHHandle {
};
// helper class to make iterative versions of recursive functions
-template <class T>
+template <typename T>
class BVH_IterativeInfo {
public:
enum {
@@ -152,7 +152,7 @@ public:
}
};
-template <class T>
+template <typename T>
class BVH_DummyPairTestFunction {
public:
static bool user_collision_check(T *p_a, T *p_b) {
@@ -161,7 +161,7 @@ public:
}
};
-template <class T>
+template <typename T>
class BVH_DummyCullTestFunction {
public:
static bool user_cull_check(T *p_a, T *p_b) {
@@ -170,7 +170,7 @@ public:
}
};
-template <class T, int NUM_TREES, int MAX_CHILDREN, int MAX_ITEMS, class USER_PAIR_TEST_FUNCTION = BVH_DummyPairTestFunction<T>, class USER_CULL_TEST_FUNCTION = BVH_DummyCullTestFunction<T>, bool USE_PAIRS = false, class BOUNDS = AABB, class POINT = Vector3>
+template <typename T, int NUM_TREES, int MAX_CHILDREN, int MAX_ITEMS, typename USER_PAIR_TEST_FUNCTION = BVH_DummyPairTestFunction<T>, typename USER_CULL_TEST_FUNCTION = BVH_DummyCullTestFunction<T>, bool USE_PAIRS = false, typename BOUNDS = AABB, typename POINT = Vector3>
class BVH_Tree {
friend class BVH;
diff --git a/core/math/disjoint_set.h b/core/math/disjoint_set.h
index 2ece991fea..4348da992d 100644
--- a/core/math/disjoint_set.h
+++ b/core/math/disjoint_set.h
@@ -35,7 +35,7 @@
#include "core/templates/vector.h"
/* This DisjointSet class uses Find with path compression and Union by rank */
-template <typename T, class H = HashMapHasherDefault, class C = HashMapComparatorDefault<T>, class AL = DefaultAllocator>
+template <typename T, typename H = HashMapHasherDefault, typename C = HashMapComparatorDefault<T>, typename AL = DefaultAllocator>
class DisjointSet {
struct Element {
T object;
@@ -65,14 +65,14 @@ public:
/* FUNCTIONS */
-template <typename T, class H, class C, class AL>
+template <typename T, typename H, typename C, typename AL>
DisjointSet<T, H, C, AL>::~DisjointSet() {
for (KeyValue<T, Element *> &E : elements) {
memdelete_allocator<Element, AL>(E.value);
}
}
-template <typename T, class H, class C, class AL>
+template <typename T, typename H, typename C, typename AL>
typename DisjointSet<T, H, C, AL>::Element *DisjointSet<T, H, C, AL>::get_parent(Element *element) {
if (element->parent != element) {
element->parent = get_parent(element->parent);
@@ -81,7 +81,7 @@ typename DisjointSet<T, H, C, AL>::Element *DisjointSet<T, H, C, AL>::get_parent
return element->parent;
}
-template <typename T, class H, class C, class AL>
+template <typename T, typename H, typename C, typename AL>
typename DisjointSet<T, H, C, AL>::Element *DisjointSet<T, H, C, AL>::insert_or_get(T object) {
typename MapT::Iterator itr = elements.find(object);
if (itr != nullptr) {
@@ -96,7 +96,7 @@ typename DisjointSet<T, H, C, AL>::Element *DisjointSet<T, H, C, AL>::insert_or_
return new_element;
}
-template <typename T, class H, class C, class AL>
+template <typename T, typename H, typename C, typename AL>
void DisjointSet<T, H, C, AL>::create_union(T a, T b) {
Element *x = insert_or_get(a);
Element *y = insert_or_get(b);
@@ -121,7 +121,7 @@ void DisjointSet<T, H, C, AL>::create_union(T a, T b) {
}
}
-template <typename T, class H, class C, class AL>
+template <typename T, typename H, typename C, typename AL>
void DisjointSet<T, H, C, AL>::get_representatives(Vector<T> &out_representatives) {
for (KeyValue<T, Element *> &E : elements) {
Element *element = E.value;
@@ -131,7 +131,7 @@ void DisjointSet<T, H, C, AL>::get_representatives(Vector<T> &out_representative
}
}
-template <typename T, class H, class C, class AL>
+template <typename T, typename H, typename C, typename AL>
void DisjointSet<T, H, C, AL>::get_members(Vector<T> &out_members, T representative) {
typename MapT::Iterator rep_itr = elements.find(representative);
ERR_FAIL_NULL(rep_itr);
diff --git a/core/math/dynamic_bvh.h b/core/math/dynamic_bvh.h
index 9b49fcc3c8..f586b845c3 100644
--- a/core/math/dynamic_bvh.h
+++ b/core/math/dynamic_bvh.h
@@ -305,11 +305,11 @@ public:
virtual ~DefaultQueryResult() {}
};
- template <class QueryResult>
+ template <typename QueryResult>
_FORCE_INLINE_ void aabb_query(const AABB &p_aabb, QueryResult &r_result);
- template <class QueryResult>
+ template <typename QueryResult>
_FORCE_INLINE_ void convex_query(const Plane *p_planes, int p_plane_count, const Vector3 *p_points, int p_point_count, QueryResult &r_result);
- template <class QueryResult>
+ template <typename QueryResult>
_FORCE_INLINE_ void ray_query(const Vector3 &p_from, const Vector3 &p_to, QueryResult &r_result);
void set_index(uint32_t p_index);
@@ -318,7 +318,7 @@ public:
~DynamicBVH();
};
-template <class QueryResult>
+template <typename QueryResult>
void DynamicBVH::aabb_query(const AABB &p_box, QueryResult &r_result) {
if (!bvh_root) {
return;
@@ -363,7 +363,7 @@ void DynamicBVH::aabb_query(const AABB &p_box, QueryResult &r_result) {
} while (depth > 0);
}
-template <class QueryResult>
+template <typename QueryResult>
void DynamicBVH::convex_query(const Plane *p_planes, int p_plane_count, const Vector3 *p_points, int p_point_count, QueryResult &r_result) {
if (!bvh_root) {
return;
@@ -420,7 +420,7 @@ void DynamicBVH::convex_query(const Plane *p_planes, int p_plane_count, const Ve
}
} while (depth > 0);
}
-template <class QueryResult>
+template <typename QueryResult>
void DynamicBVH::ray_query(const Vector3 &p_from, const Vector3 &p_to, QueryResult &r_result) {
if (!bvh_root) {
return;
diff --git a/core/math/expression.h b/core/math/expression.h
index c6ad1bd634..46bc3618df 100644
--- a/core/math/expression.h
+++ b/core/math/expression.h
@@ -243,7 +243,7 @@ private:
}
};
- template <class T>
+ template <typename T>
T *alloc_node() {
T *node = memnew(T);
node->next = nodes;
diff --git a/core/math/projection.h b/core/math/projection.h
index a7adc9017e..b98f636344 100644
--- a/core/math/projection.h
+++ b/core/math/projection.h
@@ -34,7 +34,7 @@
#include "core/math/vector3.h"
#include "core/math/vector4.h"
-template <class T>
+template <typename T>
class Vector;
struct AABB;
diff --git a/core/math/random_pcg.h b/core/math/random_pcg.h
index fd0934b24a..6bad70059f 100644
--- a/core/math/random_pcg.h
+++ b/core/math/random_pcg.h
@@ -59,7 +59,7 @@ static int __bsr_clz32(uint32_t x) {
#define LDEXPF(s, e) ldexp(s, e)
#endif
-template <class T>
+template <typename T>
class Vector;
class RandomPCG {
diff --git a/core/object/callable_method_pointer.h b/core/object/callable_method_pointer.h
index 09fe9679f7..1b29e1778a 100644
--- a/core/object/callable_method_pointer.h
+++ b/core/object/callable_method_pointer.h
@@ -77,7 +77,7 @@ public:
virtual uint32_t hash() const;
};
-template <class T, class... P>
+template <typename T, typename... P>
class CallableCustomMethodPointer : public CallableCustomMethodPointerBase {
struct Data {
T *instance;
@@ -112,7 +112,7 @@ public:
}
};
-template <class T, class... P>
+template <typename T, typename... P>
Callable create_custom_callable_function_pointer(T *p_instance,
#ifdef DEBUG_METHODS_ENABLED
const char *p_func_text,
@@ -128,7 +128,7 @@ Callable create_custom_callable_function_pointer(T *p_instance,
// VERSION WITH RETURN
-template <class T, class R, class... P>
+template <typename T, typename R, typename... P>
class CallableCustomMethodPointerRet : public CallableCustomMethodPointerBase {
struct Data {
T *instance;
@@ -164,7 +164,7 @@ public:
}
};
-template <class T, class R, class... P>
+template <typename T, typename R, typename... P>
Callable create_custom_callable_function_pointer(T *p_instance,
#ifdef DEBUG_METHODS_ENABLED
const char *p_func_text,
@@ -180,7 +180,7 @@ Callable create_custom_callable_function_pointer(T *p_instance,
// CONST VERSION WITH RETURN
-template <class T, class R, class... P>
+template <typename T, typename R, typename... P>
class CallableCustomMethodPointerRetC : public CallableCustomMethodPointerBase {
struct Data {
T *instance;
@@ -216,7 +216,7 @@ public:
}
};
-template <class T, class R, class... P>
+template <typename T, typename R, typename... P>
Callable create_custom_callable_function_pointer(T *p_instance,
#ifdef DEBUG_METHODS_ENABLED
const char *p_func_text,
@@ -238,7 +238,7 @@ Callable create_custom_callable_function_pointer(T *p_instance,
// STATIC VERSIONS
-template <class... P>
+template <typename... P>
class CallableCustomStaticMethodPointer : public CallableCustomMethodPointerBase {
struct Data {
void (*method)(P...);
@@ -270,7 +270,7 @@ public:
}
};
-template <class T, class... P>
+template <typename T, typename... P>
Callable create_custom_callable_static_function_pointer(
#ifdef DEBUG_METHODS_ENABLED
const char *p_func_text,
@@ -284,7 +284,7 @@ Callable create_custom_callable_static_function_pointer(
return Callable(ccmp);
}
-template <class R, class... P>
+template <typename R, typename... P>
class CallableCustomStaticMethodPointerRet : public CallableCustomMethodPointerBase {
struct Data {
R(*method)
@@ -316,7 +316,7 @@ public:
}
};
-template <class R, class... P>
+template <typename R, typename... P>
Callable create_custom_callable_static_function_pointer(
#ifdef DEBUG_METHODS_ENABLED
const char *p_func_text,
diff --git a/core/object/class_db.h b/core/object/class_db.h
index 3b146dd06e..adb525cbe8 100644
--- a/core/object/class_db.h
+++ b/core/object/class_db.h
@@ -140,7 +140,7 @@ public:
~ClassInfo() {}
};
- template <class T>
+ template <typename T>
static Object *creator() {
return memnew(T);
}
@@ -187,12 +187,12 @@ private:
public:
// DO NOT USE THIS!!!!!! NEEDS TO BE PUBLIC BUT DO NOT USE NO MATTER WHAT!!!
- template <class T>
+ template <typename T>
static void _add_class() {
_add_class2(T::get_class_static(), T::get_parent_class_static());
}
- template <class T>
+ template <typename T>
static void register_class(bool p_virtual = false) {
GLOBAL_LOCK_FUNCTION;
static_assert(types_are_same_v<typename T::self_type, T>, "Class not declared properly, please use GDCLASS.");
@@ -207,7 +207,7 @@ public:
T::register_custom_data_to_otdb();
}
- template <class T>
+ template <typename T>
static void register_abstract_class() {
GLOBAL_LOCK_FUNCTION;
static_assert(types_are_same_v<typename T::self_type, T>, "Class not declared properly, please use GDCLASS.");
@@ -220,7 +220,7 @@ public:
//nothing
}
- template <class T>
+ template <typename T>
static void register_internal_class() {
GLOBAL_LOCK_FUNCTION;
static_assert(types_are_same_v<typename T::self_type, T>, "Class not declared properly, please use GDCLASS.");
@@ -235,7 +235,7 @@ public:
T::register_custom_data_to_otdb();
}
- template <class T>
+ template <typename T>
static void register_runtime_class() {
GLOBAL_LOCK_FUNCTION;
static_assert(types_are_same_v<typename T::self_type, T>, "Class not declared properly, please use GDCLASS.");
@@ -255,12 +255,12 @@ public:
static void register_extension_class(ObjectGDExtension *p_extension);
static void unregister_extension_class(const StringName &p_class, bool p_free_method_binds = true);
- template <class T>
+ template <typename T>
static Object *_create_ptr_func() {
return T::create();
}
- template <class T>
+ template <typename T>
static void register_custom_instance_class() {
GLOBAL_LOCK_FUNCTION;
static_assert(types_are_same_v<typename T::self_type, T>, "Class not declared properly, please use GDCLASS.");
@@ -314,7 +314,7 @@ public:
using return_type = R;
};
- template <class N, class M, typename... VarArgs>
+ template <typename N, typename M, typename... VarArgs>
static MethodBind *bind_method(N p_method_name, M p_method, VarArgs... p_args) {
Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
const Variant *argptrs[sizeof...(p_args) + 1];
@@ -328,7 +328,7 @@ public:
return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, false, p_method_name, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
}
- template <class N, class M, typename... VarArgs>
+ template <typename N, typename M, typename... VarArgs>
static MethodBind *bind_static_method(const StringName &p_class, N p_method_name, M p_method, VarArgs... p_args) {
Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
const Variant *argptrs[sizeof...(p_args) + 1];
@@ -343,7 +343,7 @@ public:
return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, false, p_method_name, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
}
- template <class N, class M, typename... VarArgs>
+ template <typename N, typename M, typename... VarArgs>
static MethodBind *bind_compatibility_method(N p_method_name, M p_method, VarArgs... p_args) {
Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
const Variant *argptrs[sizeof...(p_args) + 1];
@@ -357,7 +357,7 @@ public:
return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, true, p_method_name, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
}
- template <class N, class M, typename... VarArgs>
+ template <typename N, typename M, typename... VarArgs>
static MethodBind *bind_compatibility_static_method(const StringName &p_class, N p_method_name, M p_method, VarArgs... p_args) {
Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
const Variant *argptrs[sizeof...(p_args) + 1];
@@ -372,7 +372,7 @@ public:
return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, true, p_method_name, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
}
- template <class M>
+ template <typename M>
static MethodBind *bind_vararg_method(uint32_t p_flags, const StringName &p_name, M p_method, const MethodInfo &p_info = MethodInfo(), const Vector<Variant> &p_default_args = Vector<Variant>(), bool p_return_nil_is_variant = true) {
GLOBAL_LOCK_FUNCTION;
@@ -385,7 +385,7 @@ public:
return _bind_vararg_method(bind, p_name, p_default_args, false);
}
- template <class M>
+ template <typename M>
static MethodBind *bind_compatibility_vararg_method(uint32_t p_flags, const StringName &p_name, M p_method, const MethodInfo &p_info = MethodInfo(), const Vector<Variant> &p_default_args = Vector<Variant>(), bool p_return_nil_is_variant = true) {
GLOBAL_LOCK_FUNCTION;
@@ -498,13 +498,13 @@ _FORCE_INLINE_ void errarray_add_str(Vector<Error> &arr, const Error &p_err) {
arr.push_back(p_err);
}
-template <class... P>
+template <typename... P>
_FORCE_INLINE_ void errarray_add_str(Vector<Error> &arr, const Error &p_err, P... p_args) {
arr.push_back(p_err);
errarray_add_str(arr, p_args...);
}
-template <class... P>
+template <typename... P>
_FORCE_INLINE_ Vector<Error> errarray(P... p_args) {
Vector<Error> arr;
errarray_add_str(arr, p_args...);
diff --git a/core/object/method_bind.h b/core/object/method_bind.h
index 88b867a1ca..e97f4abc6a 100644
--- a/core/object/method_bind.h
+++ b/core/object/method_bind.h
@@ -140,7 +140,7 @@ public:
};
// MethodBindVarArg base CRTP
-template <class Derived, class T, class R, bool should_returns>
+template <typename Derived, typename T, typename R, bool should_returns>
class MethodBindVarArgBase : public MethodBind {
protected:
R(T::*method)
@@ -219,7 +219,7 @@ private:
};
// variadic, no return
-template <class T>
+template <typename T>
class MethodBindVarArgT : public MethodBindVarArgBase<MethodBindVarArgT<T>, T, void, false> {
friend class MethodBindVarArgBase<MethodBindVarArgT<T>, T, void, false>;
@@ -245,7 +245,7 @@ private:
}
};
-template <class T>
+template <typename T>
MethodBind *create_vararg_method_bind(void (T::*p_method)(const Variant **, int, Callable::CallError &), const MethodInfo &p_info, bool p_return_nil_is_variant) {
MethodBind *a = memnew((MethodBindVarArgT<T>)(p_method, p_info, p_return_nil_is_variant));
a->set_instance_class(T::get_class_static());
@@ -253,7 +253,7 @@ MethodBind *create_vararg_method_bind(void (T::*p_method)(const Variant **, int,
}
// variadic, return
-template <class T, class R>
+template <typename T, typename R>
class MethodBindVarArgTR : public MethodBindVarArgBase<MethodBindVarArgTR<T, R>, T, R, true> {
friend class MethodBindVarArgBase<MethodBindVarArgTR<T, R>, T, R, true>;
@@ -287,7 +287,7 @@ private:
}
};
-template <class T, class R>
+template <typename T, typename R>
MethodBind *create_vararg_method_bind(R (T::*p_method)(const Variant **, int, Callable::CallError &), const MethodInfo &p_info, bool p_return_nil_is_variant) {
MethodBind *a = memnew((MethodBindVarArgTR<T, R>)(p_method, p_info, p_return_nil_is_variant));
a->set_instance_class(T::get_class_static());
@@ -305,9 +305,9 @@ class __UnexistingClass;
// no return, not const
#ifdef TYPED_METHOD_BIND
-template <class T, class... P>
+template <typename T, typename... P>
#else
-template <class... P>
+template <typename... P>
#endif
class MethodBindT : public MethodBind {
void (MB_T::*method)(P...);
@@ -375,7 +375,7 @@ public:
}
};
-template <class T, class... P>
+template <typename T, typename... P>
MethodBind *create_method_bind(void (T::*p_method)(P...)) {
#ifdef TYPED_METHOD_BIND
MethodBind *a = memnew((MethodBindT<T, P...>)(p_method));
@@ -389,9 +389,9 @@ MethodBind *create_method_bind(void (T::*p_method)(P...)) {
// no return, const
#ifdef TYPED_METHOD_BIND
-template <class T, class... P>
+template <typename T, typename... P>
#else
-template <class... P>
+template <typename... P>
#endif
class MethodBindTC : public MethodBind {
void (MB_T::*method)(P...) const;
@@ -460,7 +460,7 @@ public:
}
};
-template <class T, class... P>
+template <typename T, typename... P>
MethodBind *create_method_bind(void (T::*p_method)(P...) const) {
#ifdef TYPED_METHOD_BIND
MethodBind *a = memnew((MethodBindTC<T, P...>)(p_method));
@@ -474,9 +474,9 @@ MethodBind *create_method_bind(void (T::*p_method)(P...) const) {
// return, not const
#ifdef TYPED_METHOD_BIND
-template <class T, class R, class... P>
+template <typename T, typename R, typename... P>
#else
-template <class R, class... P>
+template <typename R, typename... P>
#endif
class MethodBindTR : public MethodBind {
R(MB_T::*method)
@@ -555,7 +555,7 @@ public:
}
};
-template <class T, class R, class... P>
+template <typename T, typename R, typename... P>
MethodBind *create_method_bind(R (T::*p_method)(P...)) {
#ifdef TYPED_METHOD_BIND
MethodBind *a = memnew((MethodBindTR<T, R, P...>)(p_method));
@@ -570,9 +570,9 @@ MethodBind *create_method_bind(R (T::*p_method)(P...)) {
// return, const
#ifdef TYPED_METHOD_BIND
-template <class T, class R, class... P>
+template <typename T, typename R, typename... P>
#else
-template <class R, class... P>
+template <typename R, typename... P>
#endif
class MethodBindTRC : public MethodBind {
R(MB_T::*method)
@@ -652,7 +652,7 @@ public:
}
};
-template <class T, class R, class... P>
+template <typename T, typename R, typename... P>
MethodBind *create_method_bind(R (T::*p_method)(P...) const) {
#ifdef TYPED_METHOD_BIND
MethodBind *a = memnew((MethodBindTRC<T, R, P...>)(p_method));
@@ -667,7 +667,7 @@ MethodBind *create_method_bind(R (T::*p_method)(P...) const) {
// no return
-template <class... P>
+template <typename... P>
class MethodBindTS : public MethodBind {
void (*function)(P...);
@@ -717,7 +717,7 @@ public:
}
};
-template <class... P>
+template <typename... P>
MethodBind *create_static_method_bind(void (*p_method)(P...)) {
MethodBind *a = memnew((MethodBindTS<P...>)(p_method));
return a;
@@ -725,7 +725,7 @@ MethodBind *create_static_method_bind(void (*p_method)(P...)) {
// return
-template <class R, class... P>
+template <typename R, typename... P>
class MethodBindTRS : public MethodBind {
R(*function)
(P...);
@@ -784,7 +784,7 @@ public:
}
};
-template <class R, class... P>
+template <typename R, typename... P>
MethodBind *create_static_method_bind(R (*p_method)(P...)) {
MethodBind *a = memnew((MethodBindTRS<R, P...>)(p_method));
return a;
diff --git a/core/object/object.cpp b/core/object/object.cpp
index e5d771844b..8ec2b802bb 100644
--- a/core/object/object.cpp
+++ b/core/object/object.cpp
@@ -1537,7 +1537,7 @@ String Object::tr(const StringName &p_message, const StringName &p_context) cons
if (Engine::get_singleton()->is_editor_hint()) {
String tr_msg = TranslationServer::get_singleton()->extractable_translate(p_message, p_context);
- if (!tr_msg.is_empty()) {
+ if (!tr_msg.is_empty() && tr_msg != p_message) {
return tr_msg;
}
@@ -1558,7 +1558,7 @@ String Object::tr_n(const StringName &p_message, const StringName &p_message_plu
if (Engine::get_singleton()->is_editor_hint()) {
String tr_msg = TranslationServer::get_singleton()->extractable_translate_plural(p_message, p_message_plural, p_n, p_context);
- if (!tr_msg.is_empty()) {
+ if (!tr_msg.is_empty() && tr_msg != p_message && tr_msg != p_message_plural) {
return tr_msg;
}
diff --git a/core/object/object.h b/core/object/object.h
index 2efcf70670..d9551ecd01 100644
--- a/core/object/object.h
+++ b/core/object/object.h
@@ -797,12 +797,12 @@ public:
void detach_from_objectdb();
_FORCE_INLINE_ ObjectID get_instance_id() const { return _instance_id; }
- template <class T>
+ template <typename T>
static T *cast_to(Object *p_object) {
return p_object ? dynamic_cast<T *>(p_object) : nullptr;
}
- template <class T>
+ template <typename T>
static const T *cast_to(const Object *p_object) {
return p_object ? dynamic_cast<const T *>(p_object) : nullptr;
}
diff --git a/core/object/ref_counted.h b/core/object/ref_counted.h
index 10be27b879..5b358135c4 100644
--- a/core/object/ref_counted.h
+++ b/core/object/ref_counted.h
@@ -53,7 +53,7 @@ public:
~RefCounted() {}
};
-template <class T>
+template <typename T>
class Ref {
T *reference = nullptr;
@@ -117,7 +117,7 @@ public:
ref(p_from);
}
- template <class T_Other>
+ template <typename T_Other>
void operator=(const Ref<T_Other> &p_from) {
RefCounted *refb = const_cast<RefCounted *>(static_cast<const RefCounted *>(p_from.ptr()));
if (!refb) {
@@ -149,7 +149,7 @@ public:
}
}
- template <class T_Other>
+ template <typename T_Other>
void reference_ptr(T_Other *p_ptr) {
if (reference == p_ptr) {
return;
@@ -166,7 +166,7 @@ public:
ref(p_from);
}
- template <class T_Other>
+ template <typename T_Other>
Ref(const Ref<T_Other> &p_from) {
RefCounted *refb = const_cast<RefCounted *>(static_cast<const RefCounted *>(p_from.ptr()));
if (!refb) {
@@ -240,7 +240,7 @@ public:
WeakRef() {}
};
-template <class T>
+template <typename T>
struct PtrToArg<Ref<T>> {
_FORCE_INLINE_ static Ref<T> convert(const void *p_ptr) {
if (p_ptr == nullptr) {
@@ -258,7 +258,7 @@ struct PtrToArg<Ref<T>> {
}
};
-template <class T>
+template <typename T>
struct PtrToArg<const Ref<T> &> {
typedef Ref<T> EncodeT;
@@ -271,7 +271,7 @@ struct PtrToArg<const Ref<T> &> {
}
};
-template <class T>
+template <typename T>
struct GetTypeInfo<Ref<T>> {
static const Variant::Type VARIANT_TYPE = Variant::OBJECT;
static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
@@ -281,7 +281,7 @@ struct GetTypeInfo<Ref<T>> {
}
};
-template <class T>
+template <typename T>
struct GetTypeInfo<const Ref<T> &> {
static const Variant::Type VARIANT_TYPE = Variant::OBJECT;
static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
@@ -291,13 +291,13 @@ struct GetTypeInfo<const Ref<T> &> {
}
};
-template <class T>
+template <typename T>
struct VariantInternalAccessor<Ref<T>> {
static _FORCE_INLINE_ Ref<T> get(const Variant *v) { return Ref<T>(*VariantInternal::get_object(v)); }
static _FORCE_INLINE_ void set(Variant *v, const Ref<T> &p_ref) { VariantInternal::refcounted_object_assign(v, p_ref.ptr()); }
};
-template <class T>
+template <typename T>
struct VariantInternalAccessor<const Ref<T> &> {
static _FORCE_INLINE_ Ref<T> get(const Variant *v) { return Ref<T>(*VariantInternal::get_object(v)); }
static _FORCE_INLINE_ void set(Variant *v, const Ref<T> &p_ref) { VariantInternal::refcounted_object_assign(v, p_ref.ptr()); }
diff --git a/core/object/script_language_extension.h b/core/object/script_language_extension.h
index efb317b839..1db322526d 100644
--- a/core/object/script_language_extension.h
+++ b/core/object/script_language_extension.h
@@ -821,6 +821,14 @@ public:
}
virtual int get_method_argument_count(const StringName &p_method, bool *r_is_valid = nullptr) const override {
+ if (native_info->get_method_argument_count_func) {
+ GDExtensionBool is_valid = 0;
+ GDExtensionInt ret = native_info->get_method_argument_count_func(instance, (GDExtensionStringNamePtr)&p_method, &is_valid);
+ if (r_is_valid) {
+ *r_is_valid = is_valid != 0;
+ }
+ return ret;
+ }
// Fallback to default.
return ScriptInstance::get_method_argument_count(p_method, r_is_valid);
}
@@ -912,7 +920,6 @@ public:
return reinterpret_cast<ScriptLanguage *>(lang);
}
return nullptr;
- ;
}
virtual ~ScriptInstanceExtension() {
if (native_info->free_func) {
diff --git a/core/object/worker_thread_pool.h b/core/object/worker_thread_pool.h
index c9921c808d..fdddc9a647 100644
--- a/core/object/worker_thread_pool.h
+++ b/core/object/worker_thread_pool.h
@@ -157,7 +157,7 @@ private:
TaskID _add_task(const Callable &p_callable, void (*p_func)(void *), void *p_userdata, BaseTemplateUserdata *p_template_userdata, bool p_high_priority, const String &p_description);
GroupID _add_group_task(const Callable &p_callable, void (*p_func)(void *, uint32_t), void *p_userdata, BaseTemplateUserdata *p_template_userdata, int p_elements, int p_tasks, bool p_high_priority, const String &p_description);
- template <class C, class M, class U>
+ template <typename C, typename M, typename U>
struct TaskUserData : public BaseTemplateUserdata {
C *instance;
M method;
@@ -167,7 +167,7 @@ private:
}
};
- template <class C, class M, class U>
+ template <typename C, typename M, typename U>
struct GroupUserData : public BaseTemplateUserdata {
C *instance;
M method;
@@ -181,7 +181,7 @@ protected:
static void _bind_methods();
public:
- template <class C, class M, class U>
+ template <typename C, typename M, typename U>
TaskID add_template_task(C *p_instance, M p_method, U p_userdata, bool p_high_priority = false, const String &p_description = String()) {
typedef TaskUserData<C, M, U> TUD;
TUD *ud = memnew(TUD);
@@ -196,7 +196,7 @@ public:
bool is_task_completed(TaskID p_task_id) const;
Error wait_for_task_completion(TaskID p_task_id);
- template <class C, class M, class U>
+ template <typename C, typename M, typename U>
GroupID add_template_group_task(C *p_instance, M p_method, U p_userdata, int p_elements, int p_tasks = -1, bool p_high_priority = false, const String &p_description = String()) {
typedef GroupUserData<C, M, U> GroupUD;
GroupUD *ud = memnew(GroupUD);
diff --git a/core/os/condition_variable.h b/core/os/condition_variable.h
index 2b6b272e18..fa1355e98c 100644
--- a/core/os/condition_variable.h
+++ b/core/os/condition_variable.h
@@ -54,7 +54,7 @@ class ConditionVariable {
mutable THREADING_NAMESPACE::condition_variable condition;
public:
- template <class BinaryMutexT>
+ template <typename BinaryMutexT>
_ALWAYS_INLINE_ void wait(const MutexLock<BinaryMutexT> &p_lock) const {
condition.wait(const_cast<THREADING_NAMESPACE::unique_lock<THREADING_NAMESPACE::mutex> &>(p_lock.lock));
}
@@ -72,7 +72,7 @@ public:
class ConditionVariable {
public:
- template <class BinaryMutexT>
+ template <typename BinaryMutexT>
void wait(const MutexLock<BinaryMutexT> &p_lock) const {}
void notify_one() const {}
void notify_all() const {}
diff --git a/core/os/memory.h b/core/os/memory.h
index 6f3f6fed39..d03e08d785 100644
--- a/core/os/memory.h
+++ b/core/os/memory.h
@@ -92,7 +92,7 @@ void operator delete(void *p_mem, void *p_pointer, size_t check, const char *p_d
_ALWAYS_INLINE_ void postinitialize_handler(void *) {}
-template <class T>
+template <typename T>
_ALWAYS_INLINE_ T *_post_initialize(T *p_obj) {
postinitialize_handler(p_obj);
return p_obj;
@@ -107,7 +107,7 @@ _ALWAYS_INLINE_ bool predelete_handler(void *) {
return true;
}
-template <class T>
+template <typename T>
void memdelete(T *p_class) {
if (!predelete_handler(p_class)) {
return; // doesn't want to be deleted
@@ -119,7 +119,7 @@ void memdelete(T *p_class) {
Memory::free_static(p_class, false);
}
-template <class T, class A>
+template <typename T, typename A>
void memdelete_allocator(T *p_class) {
if (!predelete_handler(p_class)) {
return; // doesn't want to be deleted
@@ -213,10 +213,10 @@ struct _GlobalNilClass {
static _GlobalNil _nil;
};
-template <class T>
+template <typename T>
class DefaultTypedAllocator {
public:
- template <class... Args>
+ template <typename... Args>
_FORCE_INLINE_ T *new_allocation(const Args &&...p_args) { return memnew(T(p_args...)); }
_FORCE_INLINE_ void delete_allocation(T *p_allocation) { memdelete(p_allocation); }
};
diff --git a/core/os/mutex.h b/core/os/mutex.h
index a4eab0cd86..3e7aa81bc1 100644
--- a/core/os/mutex.h
+++ b/core/os/mutex.h
@@ -45,10 +45,10 @@
#ifdef THREADS_ENABLED
-template <class MutexT>
+template <typename MutexT>
class MutexLock;
-template <class StdMutexT>
+template <typename StdMutexT>
class MutexImpl {
friend class MutexLock<MutexImpl<StdMutexT>>;
@@ -70,7 +70,7 @@ public:
}
};
-template <class MutexT>
+template <typename MutexT>
class MutexLock {
friend class ConditionVariable;
@@ -100,7 +100,7 @@ public:
bool try_lock() const { return true; }
};
-template <class MutexT>
+template <typename MutexT>
class MutexLock {
public:
MutexLock(const MutexT &p_mutex) {}
diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp
index 1d27933016..a7e12138f2 100644
--- a/core/string/ustring.cpp
+++ b/core/string/ustring.cpp
@@ -2459,7 +2459,7 @@ bool String::is_numeric() const {
return true; // TODO: Use the parser below for this instead
}
-template <class C>
+template <typename C>
static double built_in_strtod(
/* A decimal ASCII floating-point number,
* optionally preceded by white space. Must
diff --git a/core/string/ustring.h b/core/string/ustring.h
index 468a015302..0fb72fccd2 100644
--- a/core/string/ustring.h
+++ b/core/string/ustring.h
@@ -43,7 +43,7 @@
/* CharProxy */
/*************************************************************************/
-template <class T>
+template <typename T>
class CharProxy {
friend class Char16String;
friend class CharString;
@@ -602,13 +602,13 @@ _FORCE_INLINE_ void sarray_add_str(Vector<String> &arr, const String &p_str) {
arr.push_back(p_str);
}
-template <class... P>
+template <typename... P>
_FORCE_INLINE_ void sarray_add_str(Vector<String> &arr, const String &p_str, P... p_args) {
arr.push_back(p_str);
sarray_add_str(arr, p_args...);
}
-template <class... P>
+template <typename... P>
_FORCE_INLINE_ Vector<String> sarray(P... p_args) {
Vector<String> arr;
sarray_add_str(arr, p_args...);
diff --git a/core/templates/bin_sorted_array.h b/core/templates/bin_sorted_array.h
index 500d1f1377..30c1fefbbd 100644
--- a/core/templates/bin_sorted_array.h
+++ b/core/templates/bin_sorted_array.h
@@ -34,7 +34,7 @@
#include "core/templates/local_vector.h"
#include "core/templates/paged_array.h"
-template <class T>
+template <typename T>
class BinSortedArray {
PagedArray<T> array;
LocalVector<uint64_t> bin_limits;
diff --git a/core/templates/command_queue_mt.h b/core/templates/command_queue_mt.h
index b1010f7f43..4056119851 100644
--- a/core/templates/command_queue_mt.h
+++ b/core/templates/command_queue_mt.h
@@ -207,41 +207,41 @@
#define ARG(N) p##N
#define PARAM(N) P##N p##N
-#define TYPE_PARAM(N) class P##N
+#define TYPE_PARAM(N) typename P##N
#define PARAM_DECL(N) typename GetSimpleTypeT<P##N>::type_t p##N
-#define DECL_CMD(N) \
- template <class T, class M COMMA(N) COMMA_SEP_LIST(TYPE_PARAM, N)> \
- struct Command##N : public CommandBase { \
- T *instance; \
- M method; \
- SEMIC_SEP_LIST(PARAM_DECL, N); \
- virtual void call() override { \
- (instance->*method)(COMMA_SEP_LIST(ARG, N)); \
- } \
+#define DECL_CMD(N) \
+ template <typename T, typename M COMMA(N) COMMA_SEP_LIST(TYPE_PARAM, N)> \
+ struct Command##N : public CommandBase { \
+ T *instance; \
+ M method; \
+ SEMIC_SEP_LIST(PARAM_DECL, N); \
+ virtual void call() override { \
+ (instance->*method)(COMMA_SEP_LIST(ARG, N)); \
+ } \
};
-#define DECL_CMD_RET(N) \
- template <class T, class M, COMMA_SEP_LIST(TYPE_PARAM, N) COMMA(N) class R> \
- struct CommandRet##N : public SyncCommand { \
- R *ret; \
- T *instance; \
- M method; \
- SEMIC_SEP_LIST(PARAM_DECL, N); \
- virtual void call() override { \
- *ret = (instance->*method)(COMMA_SEP_LIST(ARG, N)); \
- } \
+#define DECL_CMD_RET(N) \
+ template <typename T, typename M, COMMA_SEP_LIST(TYPE_PARAM, N) COMMA(N) typename R> \
+ struct CommandRet##N : public SyncCommand { \
+ R *ret; \
+ T *instance; \
+ M method; \
+ SEMIC_SEP_LIST(PARAM_DECL, N); \
+ virtual void call() override { \
+ *ret = (instance->*method)(COMMA_SEP_LIST(ARG, N)); \
+ } \
};
-#define DECL_CMD_SYNC(N) \
- template <class T, class M COMMA(N) COMMA_SEP_LIST(TYPE_PARAM, N)> \
- struct CommandSync##N : public SyncCommand { \
- T *instance; \
- M method; \
- SEMIC_SEP_LIST(PARAM_DECL, N); \
- virtual void call() override { \
- (instance->*method)(COMMA_SEP_LIST(ARG, N)); \
- } \
+#define DECL_CMD_SYNC(N) \
+ template <typename T, typename M COMMA(N) COMMA_SEP_LIST(TYPE_PARAM, N)> \
+ struct CommandSync##N : public SyncCommand { \
+ T *instance; \
+ M method; \
+ SEMIC_SEP_LIST(PARAM_DECL, N); \
+ virtual void call() override { \
+ (instance->*method)(COMMA_SEP_LIST(ARG, N)); \
+ } \
};
#define TYPE_ARG(N) P##N
@@ -249,7 +249,7 @@
#define CMD_ASSIGN_PARAM(N) cmd->p##N = p##N
#define DECL_PUSH(N) \
- template <class T, class M COMMA(N) COMMA_SEP_LIST(TYPE_PARAM, N)> \
+ template <typename T, typename M COMMA(N) COMMA_SEP_LIST(TYPE_PARAM, N)> \
void push(T *p_instance, M p_method COMMA(N) COMMA_SEP_LIST(PARAM, N)) { \
CMD_TYPE(N) *cmd = allocate_and_lock<CMD_TYPE(N)>(); \
cmd->instance = p_instance; \
@@ -263,7 +263,7 @@
#define CMD_RET_TYPE(N) CommandRet##N<T, M, COMMA_SEP_LIST(TYPE_ARG, N) COMMA(N) R>
#define DECL_PUSH_AND_RET(N) \
- template <class T, class M, COMMA_SEP_LIST(TYPE_PARAM, N) COMMA(N) class R> \
+ template <typename T, typename M, COMMA_SEP_LIST(TYPE_PARAM, N) COMMA(N) typename R> \
void push_and_ret(T *p_instance, M p_method, COMMA_SEP_LIST(PARAM, N) COMMA(N) R *r_ret) { \
SyncSemaphore *ss = _alloc_sync_sem(); \
CMD_RET_TYPE(N) *cmd = allocate_and_lock<CMD_RET_TYPE(N)>(); \
@@ -282,7 +282,7 @@
#define CMD_SYNC_TYPE(N) CommandSync##N<T, M COMMA(N) COMMA_SEP_LIST(TYPE_ARG, N)>
#define DECL_PUSH_AND_SYNC(N) \
- template <class T, class M COMMA(N) COMMA_SEP_LIST(TYPE_PARAM, N)> \
+ template <typename T, typename M COMMA(N) COMMA_SEP_LIST(TYPE_PARAM, N)> \
void push_and_sync(T *p_instance, M p_method COMMA(N) COMMA_SEP_LIST(PARAM, N)) { \
SyncSemaphore *ss = _alloc_sync_sem(); \
CMD_SYNC_TYPE(N) *cmd = allocate_and_lock<CMD_SYNC_TYPE(N)>(); \
@@ -343,7 +343,7 @@ class CommandQueueMT {
Semaphore *sync = nullptr;
uint64_t flush_read_ptr = 0;
- template <class T>
+ template <typename T>
T *allocate() {
// alloc size is size+T+safeguard
uint32_t alloc_size = ((sizeof(T) + 8 - 1) & ~(8 - 1));
@@ -354,7 +354,7 @@ class CommandQueueMT {
return cmd;
}
- template <class T>
+ template <typename T>
T *allocate_and_lock() {
lock();
T *ret = allocate<T>();
diff --git a/core/templates/cowdata.h b/core/templates/cowdata.h
index 466658951e..f22ae1f1d3 100644
--- a/core/templates/cowdata.h
+++ b/core/templates/cowdata.h
@@ -38,12 +38,12 @@
#include <string.h>
#include <type_traits>
-template <class T>
+template <typename T>
class Vector;
class String;
class Char16String;
class CharString;
-template <class T, class V>
+template <typename T, typename V>
class VMap;
static_assert(std::is_trivially_destructible_v<std::atomic<uint64_t>>);
@@ -54,14 +54,14 @@ static_assert(std::is_trivially_destructible_v<std::atomic<uint64_t>>);
#pragma GCC diagnostic ignored "-Wplacement-new"
#endif
-template <class T>
+template <typename T>
class CowData {
- template <class TV>
+ template <typename TV>
friend class Vector;
friend class String;
friend class Char16String;
friend class CharString;
- template <class TV, class VV>
+ template <typename TV, typename VV>
friend class VMap;
public:
@@ -241,7 +241,7 @@ public:
_FORCE_INLINE_ CowData(CowData<T> &p_from) { _ref(p_from); };
};
-template <class T>
+template <typename T>
void CowData<T>::_unref(void *p_data) {
if (!p_data) {
return;
@@ -268,7 +268,7 @@ void CowData<T>::_unref(void *p_data) {
Memory::free_static(((uint8_t *)p_data) - DATA_OFFSET, false);
}
-template <class T>
+template <typename T>
typename CowData<T>::USize CowData<T>::_copy_on_write() {
if (!_ptr) {
return 0;
@@ -308,7 +308,7 @@ typename CowData<T>::USize CowData<T>::_copy_on_write() {
return rc;
}
-template <class T>
+template <typename T>
template <bool p_ensure_zero>
Error CowData<T>::resize(Size p_size) {
ERR_FAIL_COND_V(p_size < 0, ERR_INVALID_PARAMETER);
@@ -401,7 +401,7 @@ Error CowData<T>::resize(Size p_size) {
return OK;
}
-template <class T>
+template <typename T>
typename CowData<T>::Size CowData<T>::find(const T &p_val, Size p_from) const {
Size ret = -1;
@@ -419,7 +419,7 @@ typename CowData<T>::Size CowData<T>::find(const T &p_val, Size p_from) const {
return ret;
}
-template <class T>
+template <typename T>
typename CowData<T>::Size CowData<T>::rfind(const T &p_val, Size p_from) const {
const Size s = size();
@@ -438,7 +438,7 @@ typename CowData<T>::Size CowData<T>::rfind(const T &p_val, Size p_from) const {
return -1;
}
-template <class T>
+template <typename T>
typename CowData<T>::Size CowData<T>::count(const T &p_val) const {
Size amount = 0;
for (Size i = 0; i < size(); i++) {
@@ -449,12 +449,12 @@ typename CowData<T>::Size CowData<T>::count(const T &p_val) const {
return amount;
}
-template <class T>
+template <typename T>
void CowData<T>::_ref(const CowData *p_from) {
_ref(*p_from);
}
-template <class T>
+template <typename T>
void CowData<T>::_ref(const CowData &p_from) {
if (_ptr == p_from._ptr) {
return; // self assign, do nothing.
@@ -472,7 +472,7 @@ void CowData<T>::_ref(const CowData &p_from) {
}
}
-template <class T>
+template <typename T>
CowData<T>::~CowData() {
_unref(_ptr);
}
diff --git a/core/templates/hash_map.h b/core/templates/hash_map.h
index e1745110d7..a3e8c2c788 100644
--- a/core/templates/hash_map.h
+++ b/core/templates/hash_map.h
@@ -51,7 +51,7 @@
* The assignment operator copy the pairs from one map to the other.
*/
-template <class TKey, class TValue>
+template <typename TKey, typename TValue>
struct HashMapElement {
HashMapElement *next = nullptr;
HashMapElement *prev = nullptr;
@@ -61,10 +61,10 @@ struct HashMapElement {
data(p_key, p_value) {}
};
-template <class TKey, class TValue,
- class Hasher = HashMapHasherDefault,
- class Comparator = HashMapComparatorDefault<TKey>,
- class Allocator = DefaultTypedAllocator<HashMapElement<TKey, TValue>>>
+template <typename TKey, typename TValue,
+ typename Hasher = HashMapHasherDefault,
+ typename Comparator = HashMapComparatorDefault<TKey>,
+ typename Allocator = DefaultTypedAllocator<HashMapElement<TKey, TValue>>>
class HashMap {
public:
static constexpr uint32_t MIN_CAPACITY_INDEX = 2; // Use a prime.
diff --git a/core/templates/hash_set.h b/core/templates/hash_set.h
index 00f4acbc9c..295b07e5e7 100644
--- a/core/templates/hash_set.h
+++ b/core/templates/hash_set.h
@@ -46,9 +46,9 @@
*
*/
-template <class TKey,
- class Hasher = HashMapHasherDefault,
- class Comparator = HashMapComparatorDefault<TKey>>
+template <typename TKey,
+ typename Hasher = HashMapHasherDefault,
+ typename Comparator = HashMapComparatorDefault<TKey>>
class HashSet {
public:
static constexpr uint32_t MIN_CAPACITY_INDEX = 2; // Use a prime.
diff --git a/core/templates/hashfuncs.h b/core/templates/hashfuncs.h
index a16f655524..fc7a78bcf5 100644
--- a/core/templates/hashfuncs.h
+++ b/core/templates/hashfuncs.h
@@ -248,7 +248,7 @@ static _FORCE_INLINE_ uint32_t hash_djb2_one_float(double p_in, uint32_t p_prev
return ((p_prev << 5) + p_prev) + hash_one_uint64(u.i);
}
-template <class T>
+template <typename T>
static _FORCE_INLINE_ uint32_t hash_make_uint32_t(T p_in) {
union {
T t;
@@ -281,7 +281,7 @@ static _FORCE_INLINE_ uint64_t hash_djb2_one_64(uint64_t p_in, uint64_t p_prev =
return ((p_prev << 5) + p_prev) ^ p_in;
}
-template <class T>
+template <typename T>
static _FORCE_INLINE_ uint64_t hash_make_uint64_t(T p_in) {
union {
T t;
@@ -293,15 +293,15 @@ static _FORCE_INLINE_ uint64_t hash_make_uint64_t(T p_in) {
return _u._u64;
}
-template <class T>
+template <typename T>
class Ref;
struct HashMapHasherDefault {
// Generic hash function for any type.
- template <class T>
+ template <typename T>
static _FORCE_INLINE_ uint32_t hash(const T *p_pointer) { return hash_one_uint64((uint64_t)p_pointer); }
- template <class T>
+ template <typename 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 String &p_string) { return p_string.hash(); }
@@ -387,7 +387,7 @@ struct HashMapHasherDefault {
};
// TODO: Fold this into HashMapHasherDefault once C++20 concepts are allowed
-template <class T>
+template <typename T>
struct HashableHasher {
static _FORCE_INLINE_ uint32_t hash(const T &hashable) { return hashable.hash(); }
};
diff --git a/core/templates/list.h b/core/templates/list.h
index 354e826a43..b4d4beb930 100644
--- a/core/templates/list.h
+++ b/core/templates/list.h
@@ -43,7 +43,7 @@
* from the iterator.
*/
-template <class T, class A = DefaultAllocator>
+template <typename T, typename A = DefaultAllocator>
class List {
struct _Data;
@@ -410,7 +410,7 @@ public:
/**
* find an element in the list,
*/
- template <class T_v>
+ template <typename T_v>
Element *find(const T_v &p_val) {
Element *it = front();
while (it) {
@@ -646,7 +646,7 @@ public:
sort_custom<Comparator<T>>();
}
- template <class C>
+ template <typename C>
void sort_custom_inplace() {
if (size() < 2) {
return;
@@ -693,7 +693,7 @@ public:
_data->last = to;
}
- template <class C>
+ template <typename C>
struct AuxiliaryComparator {
C compare;
_FORCE_INLINE_ bool operator()(const Element *a, const Element *b) const {
@@ -701,7 +701,7 @@ public:
}
};
- template <class C>
+ template <typename C>
void sort_custom() {
//this version uses auxiliary memory for speed.
//if you don't want to use auxiliary memory, use the in_place version
@@ -764,7 +764,7 @@ public:
}
};
-template <class T, class A>
+template <typename T, typename A>
void List<T, A>::Element::transfer_to_back(List<T, A> *p_dst_list) {
// Detach from current.
diff --git a/core/templates/local_vector.h b/core/templates/local_vector.h
index 17ddbf6161..6478297fd1 100644
--- a/core/templates/local_vector.h
+++ b/core/templates/local_vector.h
@@ -41,7 +41,7 @@
// If tight, it grows strictly as much as needed.
// Otherwise, it grows exponentially (the default and what you want in most cases).
-template <class T, class U = uint32_t, bool force_trivial = false, bool tight = false>
+template <typename T, typename U = uint32_t, bool force_trivial = false, bool tight = false>
class LocalVector {
private:
U count = 0;
@@ -248,7 +248,7 @@ public:
return -1;
}
- template <class C>
+ template <typename C>
void sort_custom() {
U len = count;
if (len == 0) {
@@ -322,7 +322,7 @@ public:
}
};
-template <class T, class U = uint32_t, bool force_trivial = false>
+template <typename T, typename U = uint32_t, bool force_trivial = false>
using TightLocalVector = LocalVector<T, U, force_trivial, true>;
#endif // LOCAL_VECTOR_H
diff --git a/core/templates/lru.h b/core/templates/lru.h
index aecb735c48..919c5605aa 100644
--- a/core/templates/lru.h
+++ b/core/templates/lru.h
@@ -35,7 +35,7 @@
#include "hash_map.h"
#include "list.h"
-template <class TKey, class TData, class Hasher = HashMapHasherDefault, class Comparator = HashMapComparatorDefault<TKey>>
+template <typename TKey, typename TData, typename Hasher = HashMapHasherDefault, typename Comparator = HashMapComparatorDefault<TKey>>
class LRUCache {
private:
struct Pair {
diff --git a/core/templates/oa_hash_map.h b/core/templates/oa_hash_map.h
index 752e264a49..7afb58b7c2 100644
--- a/core/templates/oa_hash_map.h
+++ b/core/templates/oa_hash_map.h
@@ -50,9 +50,9 @@
*
* The assignment operator copy the pairs from one map to the other.
*/
-template <class TKey, class TValue,
- class Hasher = HashMapHasherDefault,
- class Comparator = HashMapComparatorDefault<TKey>>
+template <typename TKey, typename TValue,
+ typename Hasher = HashMapHasherDefault,
+ typename Comparator = HashMapComparatorDefault<TKey>>
class OAHashMap {
private:
TValue *values = nullptr;
diff --git a/core/templates/paged_allocator.h b/core/templates/paged_allocator.h
index 48110d37e5..4854e1b866 100644
--- a/core/templates/paged_allocator.h
+++ b/core/templates/paged_allocator.h
@@ -40,7 +40,7 @@
#include <type_traits>
#include <typeinfo>
-template <class T, bool thread_safe = false, uint32_t DEFAULT_PAGE_SIZE = 4096>
+template <typename T, bool thread_safe = false, uint32_t DEFAULT_PAGE_SIZE = 4096>
class PagedAllocator {
T **page_pool = nullptr;
T ***available_pool = nullptr;
@@ -53,7 +53,7 @@ class PagedAllocator {
SpinLock spin_lock;
public:
- template <class... Args>
+ template <typename... Args>
T *alloc(Args &&...p_args) {
if (thread_safe) {
spin_lock.lock();
@@ -95,7 +95,7 @@ public:
}
}
- template <class... Args>
+ template <typename... Args>
T *new_allocation(Args &&...p_args) { return alloc(p_args...); }
void delete_allocation(T *p_mem) { free(p_mem); }
diff --git a/core/templates/paged_array.h b/core/templates/paged_array.h
index 21053dd033..1aa8fa2485 100644
--- a/core/templates/paged_array.h
+++ b/core/templates/paged_array.h
@@ -41,7 +41,7 @@
// PageArrayPool manages central page allocation in a thread safe matter
-template <class T>
+template <typename T>
class PagedArrayPool {
T **page_pool = nullptr;
uint32_t pages_allocated = 0;
@@ -134,7 +134,7 @@ public:
// It does so by allocating pages from a PagedArrayPool.
// It is safe to use multiple PagedArrays from different threads, sharing a single PagedArrayPool
-template <class T>
+template <typename T>
class PagedArray {
PagedArrayPool<T> *page_pool = nullptr;
diff --git a/core/templates/pair.h b/core/templates/pair.h
index ff093a58e6..fd774641c2 100644
--- a/core/templates/pair.h
+++ b/core/templates/pair.h
@@ -33,7 +33,7 @@
#include "core/templates/hashfuncs.h"
#include "core/typedefs.h"
-template <class F, class S>
+template <typename F, typename S>
struct Pair {
F first;
S second;
@@ -49,17 +49,17 @@ struct Pair {
}
};
-template <class F, class S>
+template <typename F, typename S>
bool operator==(const Pair<F, S> &pair, const Pair<F, S> &other) {
return (pair.first == other.first) && (pair.second == other.second);
}
-template <class F, class S>
+template <typename F, typename S>
bool operator!=(const Pair<F, S> &pair, const Pair<F, S> &other) {
return (pair.first != other.first) || (pair.second != other.second);
}
-template <class F, class S>
+template <typename F, typename S>
struct PairSort {
bool operator()(const Pair<F, S> &A, const Pair<F, S> &B) const {
if (A.first != B.first) {
@@ -69,7 +69,7 @@ struct PairSort {
}
};
-template <class F, class S>
+template <typename F, typename S>
struct PairHash {
static uint32_t hash(const Pair<F, S> &P) {
uint64_t h1 = HashMapHasherDefault::hash(P.first);
@@ -78,7 +78,7 @@ struct PairHash {
}
};
-template <class K, class V>
+template <typename K, typename V>
struct KeyValue {
const K key;
V value;
@@ -94,17 +94,17 @@ struct KeyValue {
}
};
-template <class K, class V>
+template <typename K, typename V>
bool operator==(const KeyValue<K, V> &pair, const KeyValue<K, V> &other) {
return (pair.key == other.key) && (pair.value == other.value);
}
-template <class K, class V>
+template <typename K, typename V>
bool operator!=(const KeyValue<K, V> &pair, const KeyValue<K, V> &other) {
return (pair.key != other.key) || (pair.value != other.value);
}
-template <class K, class V>
+template <typename K, typename V>
struct KeyValueSort {
bool operator()(const KeyValue<K, V> &A, const KeyValue<K, V> &B) const {
return A.key < B.key;
diff --git a/core/templates/pooled_list.h b/core/templates/pooled_list.h
index 0d96bbb239..0e7048732e 100644
--- a/core/templates/pooled_list.h
+++ b/core/templates/pooled_list.h
@@ -55,7 +55,7 @@
#include "core/templates/local_vector.h"
-template <class T, class U = uint32_t, bool force_trivial = false, bool zero_on_first_request = false>
+template <typename T, typename U = uint32_t, bool force_trivial = false, bool zero_on_first_request = false>
class PooledList {
LocalVector<T, U, force_trivial> list;
LocalVector<U, U, true> freelist;
@@ -128,7 +128,7 @@ public:
};
// a pooled list which automatically keeps a list of the active members
-template <class T, class U = uint32_t, bool force_trivial = false, bool zero_on_first_request = false>
+template <typename T, typename U = uint32_t, bool force_trivial = false, bool zero_on_first_request = false>
class TrackedPooledList {
public:
U pool_used_size() const { return _pool.used_size(); }
diff --git a/core/templates/rb_map.h b/core/templates/rb_map.h
index 152fddd011..ef555e4a16 100644
--- a/core/templates/rb_map.h
+++ b/core/templates/rb_map.h
@@ -38,7 +38,7 @@
// based on the very nice implementation of rb-trees by:
// https://web.archive.org/web/20120507164830/https://web.mit.edu/~emin/www/source_code/red_black_tree/index.html
-template <class K, class V, class C = Comparator<K>, class A = DefaultAllocator>
+template <typename K, typename V, typename C = Comparator<K>, typename A = DefaultAllocator>
class RBMap {
enum Color {
RED,
diff --git a/core/templates/rb_set.h b/core/templates/rb_set.h
index 0fc88709e4..ac7a8df36a 100644
--- a/core/templates/rb_set.h
+++ b/core/templates/rb_set.h
@@ -37,7 +37,7 @@
// based on the very nice implementation of rb-trees by:
// https://web.archive.org/web/20120507164830/https://web.mit.edu/~emin/www/source_code/red_black_tree/index.html
-template <class T, class C = Comparator<T>, class A = DefaultAllocator>
+template <typename T, typename C = Comparator<T>, typename A = DefaultAllocator>
class RBSet {
enum Color {
RED,
diff --git a/core/templates/rid_owner.h b/core/templates/rid_owner.h
index f92e0f4162..86304d3c73 100644
--- a/core/templates/rid_owner.h
+++ b/core/templates/rid_owner.h
@@ -67,7 +67,7 @@ public:
virtual ~RID_AllocBase() {}
};
-template <class T, bool THREAD_SAFE = false>
+template <typename T, bool THREAD_SAFE = false>
class RID_Alloc : public RID_AllocBase {
T **chunks = nullptr;
uint32_t **free_list_chunks = nullptr;
@@ -364,7 +364,7 @@ public:
}
};
-template <class T, bool THREAD_SAFE = false>
+template <typename T, bool THREAD_SAFE = false>
class RID_PtrOwner {
RID_Alloc<T *, THREAD_SAFE> alloc;
@@ -423,7 +423,7 @@ public:
alloc(p_target_chunk_byte_size) {}
};
-template <class T, bool THREAD_SAFE = false>
+template <typename T, bool THREAD_SAFE = false>
class RID_Owner {
RID_Alloc<T, THREAD_SAFE> alloc;
diff --git a/core/templates/safe_list.h b/core/templates/safe_list.h
index 79457db24c..60ccdd9423 100644
--- a/core/templates/safe_list.h
+++ b/core/templates/safe_list.h
@@ -48,7 +48,7 @@
// This is used in very specific areas of the engine where it's critical that these guarantees are held.
-template <class T, class A = DefaultAllocator>
+template <typename T, typename A = DefaultAllocator>
class SafeList {
struct SafeListNode {
std::atomic<SafeListNode *> next = nullptr;
diff --git a/core/templates/safe_refcount.h b/core/templates/safe_refcount.h
index 7bbceadc8d..637b068da9 100644
--- a/core/templates/safe_refcount.h
+++ b/core/templates/safe_refcount.h
@@ -59,7 +59,7 @@
static_assert(sizeof(SafeFlag) == sizeof(bool)); \
static_assert(alignof(SafeFlag) == alignof(bool));
-template <class T>
+template <typename T>
class SafeNumeric {
std::atomic<T> value;
diff --git a/core/templates/search_array.h b/core/templates/search_array.h
index 9c3f527323..835bcd63a6 100644
--- a/core/templates/search_array.h
+++ b/core/templates/search_array.h
@@ -33,7 +33,7 @@
#include <core/templates/sort_array.h>
-template <class T, class Comparator = _DefaultComparator<T>>
+template <typename T, typename Comparator = _DefaultComparator<T>>
class SearchArray {
public:
Comparator compare;
diff --git a/core/templates/self_list.h b/core/templates/self_list.h
index afa0501c75..a04972594e 100644
--- a/core/templates/self_list.h
+++ b/core/templates/self_list.h
@@ -34,7 +34,7 @@
#include "core/error/error_macros.h"
#include "core/typedefs.h"
-template <class T>
+template <typename T>
class SelfList {
public:
class List {
@@ -109,7 +109,7 @@ public:
sort_custom<Comparator<T>>();
}
- template <class C>
+ template <typename C>
void sort_custom() {
if (_first == _last) {
return;
diff --git a/core/templates/simple_type.h b/core/templates/simple_type.h
index 3950158c5a..b2ae0110e2 100644
--- a/core/templates/simple_type.h
+++ b/core/templates/simple_type.h
@@ -33,22 +33,22 @@
/* Batch of specializations to obtain the actual simple type */
-template <class T>
+template <typename T>
struct GetSimpleTypeT {
typedef T type_t;
};
-template <class T>
+template <typename T>
struct GetSimpleTypeT<T &> {
typedef T type_t;
};
-template <class T>
+template <typename T>
struct GetSimpleTypeT<T const> {
typedef T type_t;
};
-template <class T>
+template <typename T>
struct GetSimpleTypeT<T const &> {
typedef T type_t;
};
diff --git a/core/templates/sort_array.h b/core/templates/sort_array.h
index 45aeaf1579..e7eaf8ee81 100644
--- a/core/templates/sort_array.h
+++ b/core/templates/sort_array.h
@@ -40,7 +40,7 @@
break; \
}
-template <class T>
+template <typename T>
struct _DefaultComparator {
_FORCE_INLINE_ bool operator()(const T &a, const T &b) const { return (a < b); }
};
@@ -51,7 +51,7 @@ struct _DefaultComparator {
#define SORT_ARRAY_VALIDATE_ENABLED false
#endif
-template <class T, class Comparator = _DefaultComparator<T>, bool Validate = SORT_ARRAY_VALIDATE_ENABLED>
+template <typename T, typename Comparator = _DefaultComparator<T>, bool Validate = SORT_ARRAY_VALIDATE_ENABLED>
class SortArray {
enum {
INTROSORT_THRESHOLD = 16
diff --git a/core/templates/vector.h b/core/templates/vector.h
index 0de6a34ced..52c10eea68 100644
--- a/core/templates/vector.h
+++ b/core/templates/vector.h
@@ -45,7 +45,7 @@
#include <climits>
#include <initializer_list>
-template <class T>
+template <typename T>
class VectorWriteProxy {
public:
_FORCE_INLINE_ T &operator[](typename CowData<T>::Size p_index) {
@@ -55,7 +55,7 @@ public:
}
};
-template <class T>
+template <typename T>
class Vector {
friend class VectorWriteProxy<T>;
@@ -108,7 +108,7 @@ public:
sort_custom<_DefaultComparator<T>>();
}
- template <class Comparator, bool Validate = SORT_ARRAY_VALIDATE_ENABLED, class... Args>
+ template <typename Comparator, bool Validate = SORT_ARRAY_VALIDATE_ENABLED, typename... Args>
void sort_custom(Args &&...args) {
Size len = _cowdata.size();
if (len == 0) {
@@ -124,7 +124,7 @@ public:
return bsearch_custom<_DefaultComparator<T>>(p_value, p_before);
}
- template <class Comparator, class Value, class... Args>
+ template <typename Comparator, typename Value, typename... Args>
Size bsearch_custom(const Value &p_value, bool p_before, Args &&...args) {
SearchArray<T, Comparator> search{ args... };
return search.bisect(ptrw(), size(), p_value, p_before);
@@ -291,7 +291,7 @@ public:
_FORCE_INLINE_ ~Vector() {}
};
-template <class T>
+template <typename T>
void Vector<T>::reverse() {
for (Size i = 0; i < size() / 2; i++) {
T *p = ptrw();
@@ -299,7 +299,7 @@ void Vector<T>::reverse() {
}
}
-template <class T>
+template <typename T>
void Vector<T>::append_array(const Vector<T> &p_other) {
const Size ds = p_other.size();
if (ds == 0) {
@@ -312,7 +312,7 @@ void Vector<T>::append_array(const Vector<T> &p_other) {
}
}
-template <class T>
+template <typename T>
bool Vector<T>::push_back(T p_elem) {
Error err = resize(size() + 1);
ERR_FAIL_COND_V(err, true);
@@ -321,7 +321,7 @@ bool Vector<T>::push_back(T p_elem) {
return false;
}
-template <class T>
+template <typename T>
void Vector<T>::fill(T p_elem) {
T *p = ptrw();
for (Size i = 0; i < size(); i++) {
diff --git a/core/templates/vmap.h b/core/templates/vmap.h
index 5620bd3772..2ad074942b 100644
--- a/core/templates/vmap.h
+++ b/core/templates/vmap.h
@@ -34,7 +34,7 @@
#include "core/templates/cowdata.h"
#include "core/typedefs.h"
-template <class T, class V>
+template <typename T, typename V>
class VMap {
public:
struct Pair {
diff --git a/core/templates/vset.h b/core/templates/vset.h
index a4886ca965..614d0e1e5f 100644
--- a/core/templates/vset.h
+++ b/core/templates/vset.h
@@ -34,7 +34,7 @@
#include "core/templates/vector.h"
#include "core/typedefs.h"
-template <class T>
+template <typename T>
class VSet {
Vector<T> _data;
diff --git a/core/typedefs.h b/core/typedefs.h
index 8807ee3c99..2b90a911cd 100644
--- a/core/typedefs.h
+++ b/core/typedefs.h
@@ -132,7 +132,7 @@ constexpr auto CLAMP(const T m_a, const T2 m_min, const T3 m_max) {
// Generic swap template.
#ifndef SWAP
#define SWAP(m_x, m_y) __swap_tmpl((m_x), (m_y))
-template <class T>
+template <typename T>
inline void __swap_tmpl(T &x, T &y) {
T aux = x;
x = y;
@@ -186,7 +186,7 @@ static inline int get_shift_from_power_of_2(unsigned int p_bits) {
return -1;
}
-template <class T>
+template <typename T>
static _FORCE_INLINE_ T nearest_power_of_2_templated(T x) {
--x;
@@ -256,7 +256,7 @@ static inline uint64_t BSWAP64(uint64_t x) {
#endif
// Generic comparator used in Map, List, etc.
-template <class T>
+template <typename T>
struct Comparator {
_ALWAYS_INLINE_ bool operator()(const T &p_a, const T &p_b) const { return (p_a < p_b); }
};
diff --git a/core/variant/binder_common.h b/core/variant/binder_common.h
index a44b938395..0fe4518b0f 100644
--- a/core/variant/binder_common.h
+++ b/core/variant/binder_common.h
@@ -47,7 +47,7 @@
// Variant cannot define an implicit cast operator for every Object subclass, so the
// casting is done here, to allow binding methods with parameters more specific than Object *
-template <class T>
+template <typename T>
struct VariantCaster {
static _FORCE_INLINE_ T cast(const Variant &p_variant) {
using TStripped = std::remove_pointer_t<T>;
@@ -59,7 +59,7 @@ struct VariantCaster {
}
};
-template <class T>
+template <typename T>
struct VariantCaster<T &> {
static _FORCE_INLINE_ T cast(const Variant &p_variant) {
using TStripped = std::remove_pointer_t<T>;
@@ -71,7 +71,7 @@ struct VariantCaster<T &> {
}
};
-template <class T>
+template <typename T>
struct VariantCaster<const T &> {
static _FORCE_INLINE_ T cast(const Variant &p_variant) {
using TStripped = std::remove_pointer_t<T>;
@@ -249,7 +249,7 @@ struct VariantObjectClassChecker<const Ref<T> &> {
#ifdef DEBUG_METHODS_ENABLED
-template <class T>
+template <typename T>
struct VariantCasterAndValidate {
static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, Callable::CallError &r_error) {
Variant::Type argtype = GetTypeInfo<T>::VARIANT_TYPE;
@@ -264,7 +264,7 @@ struct VariantCasterAndValidate {
}
};
-template <class T>
+template <typename T>
struct VariantCasterAndValidate<T &> {
static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, Callable::CallError &r_error) {
Variant::Type argtype = GetTypeInfo<T>::VARIANT_TYPE;
@@ -279,7 +279,7 @@ struct VariantCasterAndValidate<T &> {
}
};
-template <class T>
+template <typename T>
struct VariantCasterAndValidate<const T &> {
static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, Callable::CallError &r_error) {
Variant::Type argtype = GetTypeInfo<T>::VARIANT_TYPE;
@@ -296,7 +296,7 @@ struct VariantCasterAndValidate<const T &> {
#endif // DEBUG_METHODS_ENABLED
-template <class T, class... P, size_t... Is>
+template <typename T, typename... P, size_t... Is>
void call_with_variant_args_helper(T *p_instance, void (T::*p_method)(P...), const Variant **p_args, Callable::CallError &r_error, IndexSequence<Is...>) {
r_error.error = Callable::CallError::CALL_OK;
@@ -308,7 +308,7 @@ void call_with_variant_args_helper(T *p_instance, void (T::*p_method)(P...), con
(void)(p_args); //avoid warning
}
-template <class T, class... P, size_t... Is>
+template <typename T, typename... P, size_t... Is>
void call_with_variant_argsc_helper(T *p_instance, void (T::*p_method)(P...) const, const Variant **p_args, Callable::CallError &r_error, IndexSequence<Is...>) {
r_error.error = Callable::CallError::CALL_OK;
@@ -320,87 +320,87 @@ void call_with_variant_argsc_helper(T *p_instance, void (T::*p_method)(P...) con
(void)(p_args); //avoid warning
}
-template <class T, class... P, size_t... Is>
+template <typename T, typename... P, size_t... Is>
void call_with_ptr_args_helper(T *p_instance, void (T::*p_method)(P...), const void **p_args, IndexSequence<Is...>) {
(p_instance->*p_method)(PtrToArg<P>::convert(p_args[Is])...);
}
-template <class T, class... P, size_t... Is>
+template <typename T, typename... P, size_t... Is>
void call_with_ptr_argsc_helper(T *p_instance, void (T::*p_method)(P...) const, const void **p_args, IndexSequence<Is...>) {
(p_instance->*p_method)(PtrToArg<P>::convert(p_args[Is])...);
}
-template <class T, class R, class... P, size_t... Is>
+template <typename T, typename R, typename... P, size_t... Is>
void call_with_ptr_args_ret_helper(T *p_instance, R (T::*p_method)(P...), const void **p_args, void *r_ret, IndexSequence<Is...>) {
PtrToArg<R>::encode((p_instance->*p_method)(PtrToArg<P>::convert(p_args[Is])...), r_ret);
}
-template <class T, class R, class... P, size_t... Is>
+template <typename T, typename R, typename... P, size_t... Is>
void call_with_ptr_args_retc_helper(T *p_instance, R (T::*p_method)(P...) const, const void **p_args, void *r_ret, IndexSequence<Is...>) {
PtrToArg<R>::encode((p_instance->*p_method)(PtrToArg<P>::convert(p_args[Is])...), r_ret);
}
-template <class T, class... P, size_t... Is>
+template <typename T, typename... P, size_t... Is>
void call_with_ptr_args_static_helper(T *p_instance, void (*p_method)(T *, P...), const void **p_args, IndexSequence<Is...>) {
p_method(p_instance, PtrToArg<P>::convert(p_args[Is])...);
}
-template <class T, class R, class... P, size_t... Is>
+template <typename T, typename R, typename... P, size_t... Is>
void call_with_ptr_args_static_retc_helper(T *p_instance, R (*p_method)(T *, P...), const void **p_args, void *r_ret, IndexSequence<Is...>) {
PtrToArg<R>::encode(p_method(p_instance, PtrToArg<P>::convert(p_args[Is])...), r_ret);
}
-template <class R, class... P, size_t... Is>
+template <typename R, typename... P, size_t... Is>
void call_with_ptr_args_static_method_ret_helper(R (*p_method)(P...), const void **p_args, void *r_ret, IndexSequence<Is...>) {
PtrToArg<R>::encode(p_method(PtrToArg<P>::convert(p_args[Is])...), r_ret);
}
-template <class... P, size_t... Is>
+template <typename... P, size_t... Is>
void call_with_ptr_args_static_method_helper(void (*p_method)(P...), const void **p_args, IndexSequence<Is...>) {
p_method(PtrToArg<P>::convert(p_args[Is])...);
}
-template <class T, class... P, size_t... Is>
+template <typename T, typename... P, size_t... Is>
void call_with_validated_variant_args_helper(T *p_instance, void (T::*p_method)(P...), const Variant **p_args, IndexSequence<Is...>) {
(p_instance->*p_method)((VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...);
}
-template <class T, class... P, size_t... Is>
+template <typename T, typename... P, size_t... Is>
void call_with_validated_variant_argsc_helper(T *p_instance, void (T::*p_method)(P...) const, const Variant **p_args, IndexSequence<Is...>) {
(p_instance->*p_method)((VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...);
}
-template <class T, class R, class... P, size_t... Is>
+template <typename T, typename R, typename... P, size_t... Is>
void call_with_validated_variant_args_ret_helper(T *p_instance, R (T::*p_method)(P...), const Variant **p_args, Variant *r_ret, IndexSequence<Is...>) {
VariantInternalAccessor<typename GetSimpleTypeT<R>::type_t>::set(r_ret, (p_instance->*p_method)((VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...));
}
-template <class T, class R, class... P, size_t... Is>
+template <typename T, typename R, typename... P, size_t... Is>
void call_with_validated_variant_args_retc_helper(T *p_instance, R (T::*p_method)(P...) const, const Variant **p_args, Variant *r_ret, IndexSequence<Is...>) {
VariantInternalAccessor<typename GetSimpleTypeT<R>::type_t>::set(r_ret, (p_instance->*p_method)((VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...));
}
-template <class T, class R, class... P, size_t... Is>
+template <typename T, typename R, typename... P, size_t... Is>
void call_with_validated_variant_args_static_retc_helper(T *p_instance, R (*p_method)(T *, P...), const Variant **p_args, Variant *r_ret, IndexSequence<Is...>) {
VariantInternalAccessor<typename GetSimpleTypeT<R>::type_t>::set(r_ret, p_method(p_instance, (VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...));
}
-template <class T, class... P, size_t... Is>
+template <typename T, typename... P, size_t... Is>
void call_with_validated_variant_args_static_helper(T *p_instance, void (*p_method)(T *, P...), const Variant **p_args, IndexSequence<Is...>) {
p_method(p_instance, (VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...);
}
-template <class R, class... P, size_t... Is>
+template <typename R, typename... P, size_t... Is>
void call_with_validated_variant_args_static_method_ret_helper(R (*p_method)(P...), const Variant **p_args, Variant *r_ret, IndexSequence<Is...>) {
VariantInternalAccessor<typename GetSimpleTypeT<R>::type_t>::set(r_ret, p_method((VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...));
}
-template <class... P, size_t... Is>
+template <typename... P, size_t... Is>
void call_with_validated_variant_args_static_method_helper(void (*p_method)(P...), const Variant **p_args, IndexSequence<Is...>) {
p_method((VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...);
}
-template <class T, class... P>
+template <typename T, typename... P>
void call_with_variant_args(T *p_instance, void (T::*p_method)(P...), const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
#ifdef DEBUG_METHODS_ENABLED
if ((size_t)p_argcount > sizeof...(P)) {
@@ -418,7 +418,7 @@ void call_with_variant_args(T *p_instance, void (T::*p_method)(P...), const Vari
call_with_variant_args_helper<T, P...>(p_instance, p_method, p_args, r_error, BuildIndexSequence<sizeof...(P)>{});
}
-template <class T, class... P>
+template <typename T, typename... P>
void call_with_variant_args_dv(T *p_instance, void (T::*p_method)(P...), const Variant **p_args, int p_argcount, Callable::CallError &r_error, const Vector<Variant> &default_values) {
#ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) {
@@ -451,7 +451,7 @@ void call_with_variant_args_dv(T *p_instance, void (T::*p_method)(P...), const V
call_with_variant_args_helper(p_instance, p_method, args, r_error, BuildIndexSequence<sizeof...(P)>{});
}
-template <class T, class... P>
+template <typename T, typename... P>
void call_with_variant_argsc(T *p_instance, void (T::*p_method)(P...) const, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
#ifdef DEBUG_METHODS_ENABLED
if ((size_t)p_argcount > sizeof...(P)) {
@@ -469,7 +469,7 @@ void call_with_variant_argsc(T *p_instance, void (T::*p_method)(P...) const, con
call_with_variant_args_helper<T, P...>(p_instance, p_method, p_args, r_error, BuildIndexSequence<sizeof...(P)>{});
}
-template <class T, class... P>
+template <typename T, typename... P>
void call_with_variant_argsc_dv(T *p_instance, void (T::*p_method)(P...) const, const Variant **p_args, int p_argcount, Callable::CallError &r_error, const Vector<Variant> &default_values) {
#ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) {
@@ -502,7 +502,7 @@ void call_with_variant_argsc_dv(T *p_instance, void (T::*p_method)(P...) const,
call_with_variant_argsc_helper(p_instance, p_method, args, r_error, BuildIndexSequence<sizeof...(P)>{});
}
-template <class T, class R, class... P>
+template <typename T, typename R, typename... P>
void call_with_variant_args_ret_dv(T *p_instance, R (T::*p_method)(P...), const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error, const Vector<Variant> &default_values) {
#ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) {
@@ -535,7 +535,7 @@ void call_with_variant_args_ret_dv(T *p_instance, R (T::*p_method)(P...), const
call_with_variant_args_ret_helper(p_instance, p_method, args, r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
}
-template <class T, class R, class... P>
+template <typename T, typename R, typename... P>
void call_with_variant_args_retc_dv(T *p_instance, R (T::*p_method)(P...) const, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error, const Vector<Variant> &default_values) {
#ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) {
@@ -568,111 +568,111 @@ void call_with_variant_args_retc_dv(T *p_instance, R (T::*p_method)(P...) const,
call_with_variant_args_retc_helper(p_instance, p_method, args, r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
}
-template <class T, class... P>
+template <typename T, typename... P>
void call_with_ptr_args(T *p_instance, void (T::*p_method)(P...), const void **p_args) {
call_with_ptr_args_helper<T, P...>(p_instance, p_method, p_args, BuildIndexSequence<sizeof...(P)>{});
}
-template <class T, class... P>
+template <typename T, typename... P>
void call_with_ptr_argsc(T *p_instance, void (T::*p_method)(P...) const, const void **p_args) {
call_with_ptr_argsc_helper<T, P...>(p_instance, p_method, p_args, BuildIndexSequence<sizeof...(P)>{});
}
-template <class T, class R, class... P>
+template <typename T, typename R, typename... P>
void call_with_ptr_args_ret(T *p_instance, R (T::*p_method)(P...), const void **p_args, void *r_ret) {
call_with_ptr_args_ret_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
}
-template <class T, class R, class... P>
+template <typename T, typename R, typename... P>
void call_with_ptr_args_retc(T *p_instance, R (T::*p_method)(P...) const, const void **p_args, void *r_ret) {
call_with_ptr_args_retc_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
}
-template <class T, class... P>
+template <typename T, typename... P>
void call_with_ptr_args_static(T *p_instance, void (*p_method)(T *, P...), const void **p_args) {
call_with_ptr_args_static_helper<T, P...>(p_instance, p_method, p_args, BuildIndexSequence<sizeof...(P)>{});
}
-template <class T, class R, class... P>
+template <typename T, typename R, typename... P>
void call_with_ptr_args_static_retc(T *p_instance, R (*p_method)(T *, P...), const void **p_args, void *r_ret) {
call_with_ptr_args_static_retc_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
}
-template <class R, class... P>
+template <typename R, typename... P>
void call_with_ptr_args_static_method_ret(R (*p_method)(P...), const void **p_args, void *r_ret) {
call_with_ptr_args_static_method_ret_helper<R, P...>(p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
}
-template <class... P>
+template <typename... P>
void call_with_ptr_args_static_method(void (*p_method)(P...), const void **p_args) {
call_with_ptr_args_static_method_helper<P...>(p_method, p_args, BuildIndexSequence<sizeof...(P)>{});
}
// Validated
-template <class T, class... P>
+template <typename T, typename... P>
void call_with_validated_variant_args(Variant *base, void (T::*p_method)(P...), const Variant **p_args) {
call_with_validated_variant_args_helper<T, P...>(VariantGetInternalPtr<T>::get_ptr(base), p_method, p_args, BuildIndexSequence<sizeof...(P)>{});
}
-template <class T, class R, class... P>
+template <typename T, typename R, typename... P>
void call_with_validated_variant_args_ret(Variant *base, R (T::*p_method)(P...), const Variant **p_args, Variant *r_ret) {
call_with_validated_variant_args_ret_helper<T, R, P...>(VariantGetInternalPtr<T>::get_ptr(base), p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
}
-template <class T, class R, class... P>
+template <typename T, typename R, typename... P>
void call_with_validated_variant_args_retc(Variant *base, R (T::*p_method)(P...) const, const Variant **p_args, Variant *r_ret) {
call_with_validated_variant_args_retc_helper<T, R, P...>(VariantGetInternalPtr<T>::get_ptr(base), p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
}
-template <class T, class... P>
+template <typename T, typename... P>
void call_with_validated_variant_args_static(Variant *base, void (*p_method)(T *, P...), const Variant **p_args) {
call_with_validated_variant_args_static_helper<T, P...>(VariantGetInternalPtr<T>::get_ptr(base), p_method, p_args, BuildIndexSequence<sizeof...(P)>{});
}
-template <class T, class R, class... P>
+template <typename T, typename R, typename... P>
void call_with_validated_variant_args_static_retc(Variant *base, R (*p_method)(T *, P...), const Variant **p_args, Variant *r_ret) {
call_with_validated_variant_args_static_retc_helper<T, R, P...>(VariantGetInternalPtr<T>::get_ptr(base), p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
}
-template <class... P>
+template <typename... P>
void call_with_validated_variant_args_static_method(void (*p_method)(P...), const Variant **p_args) {
call_with_validated_variant_args_static_method_helper<P...>(p_method, p_args, BuildIndexSequence<sizeof...(P)>{});
}
-template <class R, class... P>
+template <typename R, typename... P>
void call_with_validated_variant_args_static_method_ret(R (*p_method)(P...), const Variant **p_args, Variant *r_ret) {
call_with_validated_variant_args_static_method_ret_helper<R, P...>(p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
}
// Validated Object
-template <class T, class... P>
+template <typename T, typename... P>
void call_with_validated_object_instance_args(T *base, void (T::*p_method)(P...), const Variant **p_args) {
call_with_validated_variant_args_helper<T, P...>(base, p_method, p_args, BuildIndexSequence<sizeof...(P)>{});
}
-template <class T, class... P>
+template <typename T, typename... P>
void call_with_validated_object_instance_argsc(T *base, void (T::*p_method)(P...) const, const Variant **p_args) {
call_with_validated_variant_argsc_helper<T, P...>(base, p_method, p_args, BuildIndexSequence<sizeof...(P)>{});
}
-template <class T, class R, class... P>
+template <typename T, typename R, typename... P>
void call_with_validated_object_instance_args_ret(T *base, R (T::*p_method)(P...), const Variant **p_args, Variant *r_ret) {
call_with_validated_variant_args_ret_helper<T, R, P...>(base, p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
}
-template <class T, class R, class... P>
+template <typename T, typename R, typename... P>
void call_with_validated_object_instance_args_retc(T *base, R (T::*p_method)(P...) const, const Variant **p_args, Variant *r_ret) {
call_with_validated_variant_args_retc_helper<T, R, P...>(base, p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
}
-template <class T, class... P>
+template <typename T, typename... P>
void call_with_validated_object_instance_args_static(T *base, void (*p_method)(T *, P...), const Variant **p_args) {
call_with_validated_variant_args_static_helper<T, P...>(base, p_method, p_args, BuildIndexSequence<sizeof...(P)>{});
}
-template <class T, class R, class... P>
+template <typename T, typename R, typename... P>
void call_with_validated_object_instance_args_static_retc(T *base, R (*p_method)(T *, P...), const Variant **p_args, Variant *r_ret) {
call_with_validated_variant_args_static_retc_helper<T, R, P...>(base, p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
}
@@ -684,7 +684,7 @@ void call_with_validated_object_instance_args_static_retc(T *base, R (*p_method)
#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
#endif
-template <class Q>
+template <typename Q>
void call_get_argument_type_helper(int p_arg, int &index, Variant::Type &type) {
if (p_arg == index) {
type = GetTypeInfo<Q>::VARIANT_TYPE;
@@ -692,7 +692,7 @@ void call_get_argument_type_helper(int p_arg, int &index, Variant::Type &type) {
index++;
}
-template <class... P>
+template <typename... P>
Variant::Type call_get_argument_type(int p_arg) {
Variant::Type type = Variant::NIL;
int index = 0;
@@ -704,7 +704,7 @@ Variant::Type call_get_argument_type(int p_arg) {
return type;
}
-template <class Q>
+template <typename Q>
void call_get_argument_type_info_helper(int p_arg, int &index, PropertyInfo &info) {
if (p_arg == index) {
info = GetTypeInfo<Q>::get_class_info();
@@ -712,7 +712,7 @@ void call_get_argument_type_info_helper(int p_arg, int &index, PropertyInfo &inf
index++;
}
-template <class... P>
+template <typename... P>
void call_get_argument_type_info(int p_arg, PropertyInfo &info) {
int index = 0;
// I think rocket science is simpler than modern C++.
@@ -723,7 +723,7 @@ void call_get_argument_type_info(int p_arg, PropertyInfo &info) {
}
#ifdef DEBUG_METHODS_ENABLED
-template <class Q>
+template <typename Q>
void call_get_argument_metadata_helper(int p_arg, int &index, GodotTypeInfo::Metadata &md) {
if (p_arg == index) {
md = GetTypeInfo<Q>::METADATA;
@@ -731,7 +731,7 @@ void call_get_argument_metadata_helper(int p_arg, int &index, GodotTypeInfo::Met
index++;
}
-template <class... P>
+template <typename... P>
GodotTypeInfo::Metadata call_get_argument_metadata(int p_arg) {
GodotTypeInfo::Metadata md = GodotTypeInfo::METADATA_NONE;
@@ -748,7 +748,7 @@ GodotTypeInfo::Metadata call_get_argument_metadata(int p_arg) {
//////////////////////
-template <class T, class R, class... P, size_t... Is>
+template <typename T, typename R, typename... P, size_t... Is>
void call_with_variant_args_ret_helper(T *p_instance, R (T::*p_method)(P...), const Variant **p_args, Variant &r_ret, Callable::CallError &r_error, IndexSequence<Is...>) {
r_error.error = Callable::CallError::CALL_OK;
@@ -759,7 +759,7 @@ void call_with_variant_args_ret_helper(T *p_instance, R (T::*p_method)(P...), co
#endif
}
-template <class R, class... P, size_t... Is>
+template <typename R, typename... P, size_t... Is>
void call_with_variant_args_static_ret(R (*p_method)(P...), const Variant **p_args, Variant &r_ret, Callable::CallError &r_error, IndexSequence<Is...>) {
r_error.error = Callable::CallError::CALL_OK;
@@ -770,7 +770,7 @@ void call_with_variant_args_static_ret(R (*p_method)(P...), const Variant **p_ar
#endif
}
-template <class... P, size_t... Is>
+template <typename... P, size_t... Is>
void call_with_variant_args_static(void (*p_method)(P...), const Variant **p_args, Callable::CallError &r_error, IndexSequence<Is...>) {
r_error.error = Callable::CallError::CALL_OK;
@@ -781,7 +781,7 @@ void call_with_variant_args_static(void (*p_method)(P...), const Variant **p_arg
#endif
}
-template <class T, class R, class... P>
+template <typename T, typename R, typename... P>
void call_with_variant_args_ret(T *p_instance, R (T::*p_method)(P...), const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) {
#ifdef DEBUG_METHODS_ENABLED
if ((size_t)p_argcount > sizeof...(P)) {
@@ -799,7 +799,7 @@ void call_with_variant_args_ret(T *p_instance, R (T::*p_method)(P...), const Var
call_with_variant_args_ret_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
}
-template <class T, class R, class... P, size_t... Is>
+template <typename T, typename R, typename... P, size_t... Is>
void call_with_variant_args_retc_helper(T *p_instance, R (T::*p_method)(P...) const, const Variant **p_args, Variant &r_ret, Callable::CallError &r_error, IndexSequence<Is...>) {
r_error.error = Callable::CallError::CALL_OK;
@@ -811,7 +811,7 @@ void call_with_variant_args_retc_helper(T *p_instance, R (T::*p_method)(P...) co
(void)p_args;
}
-template <class R, class... P>
+template <typename R, typename... P>
void call_with_variant_args_static_ret(R (*p_method)(P...), const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) {
#ifdef DEBUG_METHODS_ENABLED
if ((size_t)p_argcount > sizeof...(P)) {
@@ -829,7 +829,7 @@ void call_with_variant_args_static_ret(R (*p_method)(P...), const Variant **p_ar
call_with_variant_args_static_ret<R, P...>(p_method, p_args, r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
}
-template <class... P>
+template <typename... P>
void call_with_variant_args_static_ret(void (*p_method)(P...), const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) {
#ifdef DEBUG_METHODS_ENABLED
if ((size_t)p_argcount > sizeof...(P)) {
@@ -847,7 +847,7 @@ void call_with_variant_args_static_ret(void (*p_method)(P...), const Variant **p
call_with_variant_args_static<P...>(p_method, p_args, r_error, BuildIndexSequence<sizeof...(P)>{});
}
-template <class T, class R, class... P>
+template <typename T, typename R, typename... P>
void call_with_variant_args_retc(T *p_instance, R (T::*p_method)(P...) const, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) {
#ifdef DEBUG_METHODS_ENABLED
if ((size_t)p_argcount > sizeof...(P)) {
@@ -865,7 +865,7 @@ void call_with_variant_args_retc(T *p_instance, R (T::*p_method)(P...) const, co
call_with_variant_args_retc_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
}
-template <class T, class R, class... P, size_t... Is>
+template <typename T, typename R, typename... P, size_t... Is>
void call_with_variant_args_retc_static_helper(T *p_instance, R (*p_method)(T *, P...), const Variant **p_args, Variant &r_ret, Callable::CallError &r_error, IndexSequence<Is...>) {
r_error.error = Callable::CallError::CALL_OK;
@@ -878,7 +878,7 @@ void call_with_variant_args_retc_static_helper(T *p_instance, R (*p_method)(T *,
(void)p_args;
}
-template <class T, class R, class... P>
+template <typename T, typename R, typename... P>
void call_with_variant_args_retc_static_helper_dv(T *p_instance, R (*p_method)(T *, P...), const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &default_values, Callable::CallError &r_error) {
#ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) {
@@ -911,7 +911,7 @@ void call_with_variant_args_retc_static_helper_dv(T *p_instance, R (*p_method)(T
call_with_variant_args_retc_static_helper(p_instance, p_method, args, r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
}
-template <class T, class... P, size_t... Is>
+template <typename T, typename... P, size_t... Is>
void call_with_variant_args_static_helper(T *p_instance, void (*p_method)(T *, P...), const Variant **p_args, Callable::CallError &r_error, IndexSequence<Is...>) {
r_error.error = Callable::CallError::CALL_OK;
@@ -924,7 +924,7 @@ void call_with_variant_args_static_helper(T *p_instance, void (*p_method)(T *, P
(void)p_args;
}
-template <class T, class... P>
+template <typename T, typename... P>
void call_with_variant_args_static_helper_dv(T *p_instance, void (*p_method)(T *, P...), const Variant **p_args, int p_argcount, const Vector<Variant> &default_values, Callable::CallError &r_error) {
#ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) {
@@ -957,7 +957,7 @@ void call_with_variant_args_static_helper_dv(T *p_instance, void (*p_method)(T *
call_with_variant_args_static_helper(p_instance, p_method, args, r_error, BuildIndexSequence<sizeof...(P)>{});
}
-template <class R, class... P>
+template <typename R, typename... P>
void call_with_variant_args_static_ret_dv(R (*p_method)(P...), const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error, const Vector<Variant> &default_values) {
#ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) {
@@ -990,7 +990,7 @@ void call_with_variant_args_static_ret_dv(R (*p_method)(P...), const Variant **p
call_with_variant_args_static_ret(p_method, args, r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
}
-template <class... P>
+template <typename... P>
void call_with_variant_args_static_dv(void (*p_method)(P...), const Variant **p_args, int p_argcount, Callable::CallError &r_error, const Vector<Variant> &default_values) {
#ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) {
diff --git a/core/variant/method_ptrcall.h b/core/variant/method_ptrcall.h
index 1be54ba3fd..123f2067e2 100644
--- a/core/variant/method_ptrcall.h
+++ b/core/variant/method_ptrcall.h
@@ -35,7 +35,7 @@
#include "core/typedefs.h"
#include "core/variant/variant.h"
-template <class T>
+template <typename T>
struct PtrToArg {};
#define MAKE_PTRARG(m_type) \
@@ -156,7 +156,7 @@ MAKE_PTRARG_BY_REFERENCE(Variant);
// This is for Object.
-template <class T>
+template <typename T>
struct PtrToArg<T *> {
_FORCE_INLINE_ static T *convert(const void *p_ptr) {
if (p_ptr == nullptr) {
@@ -170,7 +170,7 @@ struct PtrToArg<T *> {
}
};
-template <class T>
+template <typename T>
struct PtrToArg<const T *> {
_FORCE_INLINE_ static const T *convert(const void *p_ptr) {
if (p_ptr == nullptr) {
diff --git a/core/variant/native_ptr.h b/core/variant/native_ptr.h
index 9199b12845..33ba038132 100644
--- a/core/variant/native_ptr.h
+++ b/core/variant/native_ptr.h
@@ -35,7 +35,7 @@
#include "core/variant/method_ptrcall.h"
#include "core/variant/type_info.h"
-template <class T>
+template <typename T>
struct GDExtensionConstPtr {
const T *data = nullptr;
GDExtensionConstPtr(const T *p_assign) { data = p_assign; }
@@ -44,7 +44,7 @@ struct GDExtensionConstPtr {
operator Variant() const { return uint64_t(data); }
};
-template <class T>
+template <typename T>
struct GDExtensionPtr {
T *data = nullptr;
GDExtensionPtr(T *p_assign) { data = p_assign; }
@@ -95,7 +95,7 @@ struct GDExtensionPtr {
static _FORCE_INLINE_ void set(Variant *v, const GDExtensionPtr<m_type> &p_value) { *VariantInternal::get_int(v) = uint64_t(p_value.data); } \
};
-template <class T>
+template <typename T>
struct GetTypeInfo<GDExtensionConstPtr<T>> {
static const Variant::Type VARIANT_TYPE = Variant::NIL;
static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
@@ -104,7 +104,7 @@ struct GetTypeInfo<GDExtensionConstPtr<T>> {
}
};
-template <class T>
+template <typename T>
struct GetTypeInfo<GDExtensionPtr<T>> {
static const Variant::Type VARIANT_TYPE = Variant::NIL;
static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
@@ -113,7 +113,7 @@ struct GetTypeInfo<GDExtensionPtr<T>> {
}
};
-template <class T>
+template <typename T>
struct PtrToArg<GDExtensionConstPtr<T>> {
_FORCE_INLINE_ static GDExtensionConstPtr<T> convert(const void *p_ptr) {
return GDExtensionConstPtr<T>(reinterpret_cast<const T *>(p_ptr));
@@ -123,7 +123,7 @@ struct PtrToArg<GDExtensionConstPtr<T>> {
*((const T **)p_ptr) = p_val.data;
}
};
-template <class T>
+template <typename T>
struct PtrToArg<GDExtensionPtr<T>> {
_FORCE_INLINE_ static GDExtensionPtr<T> convert(const void *p_ptr) {
return GDExtensionPtr<T>(reinterpret_cast<const T *>(p_ptr));
diff --git a/core/variant/type_info.h b/core/variant/type_info.h
index 49c4db8229..32c410463b 100644
--- a/core/variant/type_info.h
+++ b/core/variant/type_info.h
@@ -80,7 +80,7 @@ enum Metadata {
// If 'T' is a class that inherits 'Object', make sure it can see the actual class declaration
// instead of a forward declaration. You can always forward declare 'T' in a header file, and then
// include the actual declaration of 'T' in the source file where 'GetTypeInfo<T>' is instantiated.
-template <class T, typename = void>
+template <typename T, typename = void>
struct GetTypeInfo;
#define MAKE_TYPE_INFO(m_type, m_var_type) \
@@ -278,7 +278,7 @@ inline StringName __constant_get_enum_name(T param, const String &p_constant) {
return GetTypeInfo<T>::get_class_info().class_name;
}
-template <class T>
+template <typename T>
class BitField {
int64_t value = 0;
diff --git a/core/variant/typed_array.h b/core/variant/typed_array.h
index ed973b9daa..0befd19864 100644
--- a/core/variant/typed_array.h
+++ b/core/variant/typed_array.h
@@ -38,7 +38,7 @@
#include "core/variant/type_info.h"
#include "core/variant/variant.h"
-template <class T>
+template <typename T>
class TypedArray : public Array {
public:
_FORCE_INLINE_ void operator=(const Array &p_array) {
@@ -56,12 +56,12 @@ public:
}
};
-template <class T>
+template <typename T>
struct VariantInternalAccessor<TypedArray<T>> {
static _FORCE_INLINE_ TypedArray<T> get(const Variant *v) { return *VariantInternal::get_array(v); }
static _FORCE_INLINE_ void set(Variant *v, const TypedArray<T> &p_array) { *VariantInternal::get_array(v) = p_array; }
};
-template <class T>
+template <typename T>
struct VariantInternalAccessor<const TypedArray<T> &> {
static _FORCE_INLINE_ TypedArray<T> get(const Variant *v) { return *VariantInternal::get_array(v); }
static _FORCE_INLINE_ void set(Variant *v, const TypedArray<T> &p_array) { *VariantInternal::get_array(v) = p_array; }
@@ -136,7 +136,7 @@ MAKE_TYPED_ARRAY(PackedVector3Array, Variant::PACKED_VECTOR3_ARRAY)
MAKE_TYPED_ARRAY(PackedColorArray, Variant::PACKED_COLOR_ARRAY)
MAKE_TYPED_ARRAY(IPAddress, Variant::STRING)
-template <class T>
+template <typename T>
struct PtrToArg<TypedArray<T>> {
_FORCE_INLINE_ static TypedArray<T> convert(const void *p_ptr) {
return TypedArray<T>(*reinterpret_cast<const Array *>(p_ptr));
@@ -147,7 +147,7 @@ struct PtrToArg<TypedArray<T>> {
}
};
-template <class T>
+template <typename T>
struct PtrToArg<const TypedArray<T> &> {
typedef Array EncodeT;
_FORCE_INLINE_ static TypedArray<T> convert(const void *p_ptr) {
@@ -155,7 +155,7 @@ struct PtrToArg<const TypedArray<T> &> {
}
};
-template <class T>
+template <typename T>
struct GetTypeInfo<TypedArray<T>> {
static const Variant::Type VARIANT_TYPE = Variant::ARRAY;
static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
@@ -164,7 +164,7 @@ struct GetTypeInfo<TypedArray<T>> {
}
};
-template <class T>
+template <typename T>
struct GetTypeInfo<const TypedArray<T> &> {
static const Variant::Type VARIANT_TYPE = Variant::ARRAY;
static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp
index ce5423fafc..89c22c05dd 100644
--- a/core/variant/variant.cpp
+++ b/core/variant/variant.cpp
@@ -1697,7 +1697,7 @@ String stringify_variant_clean(const Variant &p_variant, int recursion_count) {
return s;
}
-template <class T>
+template <typename T>
String stringify_vector(const T &vec, int recursion_count) {
String str("[");
for (int i = 0; i < vec.size(); i++) {
@@ -2188,7 +2188,7 @@ Variant::operator Signal() const {
}
}
-template <class DA, class SA>
+template <typename DA, typename SA>
inline DA _convert_array(const SA &p_array) {
DA da;
da.resize(p_array.size());
@@ -2200,7 +2200,7 @@ inline DA _convert_array(const SA &p_array) {
return da;
}
-template <class DA>
+template <typename DA>
inline DA _convert_array_from_variant(const Variant &p_variant) {
switch (p_variant.get_type()) {
case Variant::ARRAY: {
diff --git a/core/variant/variant.h b/core/variant/variant.h
index c358559c9b..e8eec8171b 100644
--- a/core/variant/variant.h
+++ b/core/variant/variant.h
@@ -204,7 +204,7 @@ private:
_FORCE_INLINE_ virtual ~PackedArrayRefBase() {} //needs virtual destructor, but make inline
};
- template <class T>
+ template <typename T>
struct PackedArrayRef : public PackedArrayRefBase {
Vector<T> array;
static _FORCE_INLINE_ PackedArrayRef<T> *create() {
diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp
index 40c9a588d8..5f04c42536 100644
--- a/core/variant/variant_call.cpp
+++ b/core/variant/variant_call.cpp
@@ -43,329 +43,329 @@
typedef void (*VariantFunc)(Variant &r_ret, Variant &p_self, const Variant **p_args);
typedef void (*VariantConstructFunc)(Variant &r_ret, const Variant **p_args);
-template <class R, class... P>
+template <typename R, typename... P>
static _FORCE_INLINE_ void vc_static_method_call(R (*method)(P...), const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) {
call_with_variant_args_static_ret_dv(method, p_args, p_argcount, r_ret, r_error, p_defvals);
}
-template <class... P>
+template <typename... P>
static _FORCE_INLINE_ void vc_static_method_call(void (*method)(P...), const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) {
call_with_variant_args_static_dv(method, p_args, p_argcount, r_error, p_defvals);
}
-template <class R, class T, class... P>
+template <typename R, typename T, typename... P>
static _FORCE_INLINE_ void vc_method_call(R (T::*method)(P...), Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) {
call_with_variant_args_ret_dv(VariantGetInternalPtr<T>::get_ptr(base), method, p_args, p_argcount, r_ret, r_error, p_defvals);
}
-template <class R, class T, class... P>
+template <typename R, typename T, typename... P>
static _FORCE_INLINE_ void vc_method_call(R (T::*method)(P...) const, Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) {
call_with_variant_args_retc_dv(VariantGetInternalPtr<T>::get_ptr(base), method, p_args, p_argcount, r_ret, r_error, p_defvals);
}
-template <class T, class... P>
+template <typename T, typename... P>
static _FORCE_INLINE_ void vc_method_call(void (T::*method)(P...), Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) {
VariantInternal::clear(&r_ret);
call_with_variant_args_dv(VariantGetInternalPtr<T>::get_ptr(base), method, p_args, p_argcount, r_error, p_defvals);
}
-template <class T, class... P>
+template <typename T, typename... P>
static _FORCE_INLINE_ void vc_method_call(void (T::*method)(P...) const, Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) {
VariantInternal::clear(&r_ret);
call_with_variant_argsc_dv(VariantGetInternalPtr<T>::get_ptr(base), method, p_args, p_argcount, r_error, p_defvals);
}
-template <class From, class R, class T, class... P>
+template <typename From, typename R, typename T, typename... P>
static _FORCE_INLINE_ void vc_convert_method_call(R (T::*method)(P...), Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) {
T converted(static_cast<T>(*VariantGetInternalPtr<From>::get_ptr(base)));
call_with_variant_args_ret_dv(&converted, method, p_args, p_argcount, r_ret, r_error, p_defvals);
}
-template <class From, class R, class T, class... P>
+template <typename From, typename R, typename T, typename... P>
static _FORCE_INLINE_ void vc_convert_method_call(R (T::*method)(P...) const, Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) {
T converted(static_cast<T>(*VariantGetInternalPtr<From>::get_ptr(base)));
call_with_variant_args_retc_dv(&converted, method, p_args, p_argcount, r_ret, r_error, p_defvals);
}
-template <class From, class T, class... P>
+template <typename From, typename T, typename... P>
static _FORCE_INLINE_ void vc_convert_method_call(void (T::*method)(P...), Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) {
T converted(static_cast<T>(*VariantGetInternalPtr<From>::get_ptr(base)));
call_with_variant_args_dv(&converted, method, p_args, p_argcount, r_error, p_defvals);
}
-template <class From, class T, class... P>
+template <typename From, typename T, typename... P>
static _FORCE_INLINE_ void vc_convert_method_call(void (T::*method)(P...) const, Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) {
T converted(static_cast<T>(*VariantGetInternalPtr<From>::get_ptr(base)));
call_with_variant_argsc_dv(&converted, method, p_args, p_argcount, r_error, p_defvals);
}
-template <class R, class T, class... P>
+template <typename R, typename T, typename... P>
static _FORCE_INLINE_ void vc_method_call_static(R (*method)(T *, P...), Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) {
call_with_variant_args_retc_static_helper_dv(VariantGetInternalPtr<T>::get_ptr(base), method, p_args, p_argcount, r_ret, p_defvals, r_error);
}
-template <class T, class... P>
+template <typename T, typename... P>
static _FORCE_INLINE_ void vc_method_call_static(void (*method)(T *, P...), Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) {
call_with_variant_args_static_helper_dv(VariantGetInternalPtr<T>::get_ptr(base), method, p_args, p_argcount, p_defvals, r_error);
}
-template <class R, class T, class... P>
+template <typename R, typename T, typename... P>
static _FORCE_INLINE_ void vc_validated_call(R (T::*method)(P...), Variant *base, const Variant **p_args, Variant *r_ret) {
call_with_validated_variant_args_ret(base, method, p_args, r_ret);
}
-template <class R, class T, class... P>
+template <typename R, typename T, typename... P>
static _FORCE_INLINE_ void vc_validated_call(R (T::*method)(P...) const, Variant *base, const Variant **p_args, Variant *r_ret) {
call_with_validated_variant_args_retc(base, method, p_args, r_ret);
}
-template <class T, class... P>
+template <typename T, typename... P>
static _FORCE_INLINE_ void vc_validated_call(void (T::*method)(P...), Variant *base, const Variant **p_args, Variant *r_ret) {
call_with_validated_variant_args(base, method, p_args);
}
-template <class T, class... P>
+template <typename T, typename... P>
static _FORCE_INLINE_ void vc_validated_call(void (T::*method)(P...) const, Variant *base, const Variant **p_args, Variant *r_ret) {
call_with_validated_variant_argsc(base, method, p_args);
}
-template <class From, class R, class T, class... P>
+template <typename From, typename R, typename T, typename... P>
static _FORCE_INLINE_ void vc_convert_validated_call(R (T::*method)(P...), Variant *base, const Variant **p_args, Variant *r_ret) {
T converted(static_cast<T>(*VariantGetInternalPtr<From>::get_ptr(base)));
call_with_validated_variant_args_ret_helper<T, R, P...>(&converted, method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
}
-template <class From, class R, class T, class... P>
+template <typename From, typename R, typename T, typename... P>
static _FORCE_INLINE_ void vc_convert_validated_call(R (T::*method)(P...) const, Variant *base, const Variant **p_args, Variant *r_ret) {
T converted(static_cast<T>(*VariantGetInternalPtr<From>::get_ptr(base)));
call_with_validated_variant_args_retc_helper<T, R, P...>(&converted, method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
}
-template <class From, class T, class... P>
+template <typename From, typename T, typename... P>
static _FORCE_INLINE_ void vc_convert_validated_call(void (T::*method)(P...), Variant *base, const Variant **p_args, Variant *r_ret) {
T converted(static_cast<T>(*VariantGetInternalPtr<From>::get_ptr(base)));
call_with_validated_variant_args_helper<T, P...>(&converted, method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
}
-template <class From, class T, class... P>
+template <typename From, typename T, typename... P>
static _FORCE_INLINE_ void vc_convert_validated_call(void (T::*method)(P...) const, Variant *base, const Variant **p_args, Variant *r_ret) {
T converted(static_cast<T>(*VariantGetInternalPtr<From>::get_ptr(base)));
call_with_validated_variant_argsc_helper<T, P...>(&converted, method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
}
-template <class R, class T, class... P>
+template <typename R, typename T, typename... P>
static _FORCE_INLINE_ void vc_validated_call_static(R (*method)(T *, P...), Variant *base, const Variant **p_args, Variant *r_ret) {
call_with_validated_variant_args_static_retc(base, method, p_args, r_ret);
}
-template <class T, class... P>
+template <typename T, typename... P>
static _FORCE_INLINE_ void vc_validated_call_static(void (*method)(T *, P...), Variant *base, const Variant **p_args, Variant *r_ret) {
call_with_validated_variant_args_static(base, method, p_args);
}
-template <class R, class... P>
+template <typename R, typename... P>
static _FORCE_INLINE_ void vc_validated_static_call(R (*method)(P...), const Variant **p_args, Variant *r_ret) {
call_with_validated_variant_args_static_method_ret(method, p_args, r_ret);
}
-template <class... P>
+template <typename... P>
static _FORCE_INLINE_ void vc_validated_static_call(void (*method)(P...), const Variant **p_args, Variant *r_ret) {
call_with_validated_variant_args_static_method(method, p_args);
}
-template <class R, class T, class... P>
+template <typename R, typename T, typename... P>
static _FORCE_INLINE_ void vc_ptrcall(R (T::*method)(P...), void *p_base, const void **p_args, void *r_ret) {
call_with_ptr_args_ret(reinterpret_cast<T *>(p_base), method, p_args, r_ret);
}
-template <class R, class T, class... P>
+template <typename R, typename T, typename... P>
static _FORCE_INLINE_ void vc_ptrcall(R (T::*method)(P...) const, void *p_base, const void **p_args, void *r_ret) {
call_with_ptr_args_retc(reinterpret_cast<T *>(p_base), method, p_args, r_ret);
}
-template <class T, class... P>
+template <typename T, typename... P>
static _FORCE_INLINE_ void vc_ptrcall(void (T::*method)(P...), void *p_base, const void **p_args, void *r_ret) {
call_with_ptr_args(reinterpret_cast<T *>(p_base), method, p_args);
}
-template <class T, class... P>
+template <typename T, typename... P>
static _FORCE_INLINE_ void vc_ptrcall(void (T::*method)(P...) const, void *p_base, const void **p_args, void *r_ret) {
call_with_ptr_argsc(reinterpret_cast<T *>(p_base), method, p_args);
}
-template <class From, class R, class T, class... P>
+template <typename From, typename R, typename T, typename... P>
static _FORCE_INLINE_ void vc_convert_ptrcall(R (T::*method)(P...), void *p_base, const void **p_args, void *r_ret) {
T converted(*reinterpret_cast<From *>(p_base));
call_with_ptr_args_ret(&converted, method, p_args, r_ret);
}
-template <class From, class R, class T, class... P>
+template <typename From, typename R, typename T, typename... P>
static _FORCE_INLINE_ void vc_convert_ptrcall(R (T::*method)(P...) const, void *p_base, const void **p_args, void *r_ret) {
T converted(*reinterpret_cast<From *>(p_base));
call_with_ptr_args_retc(&converted, method, p_args, r_ret);
}
-template <class From, class T, class... P>
+template <typename From, typename T, typename... P>
static _FORCE_INLINE_ void vc_convert_ptrcall(void (T::*method)(P...), void *p_base, const void **p_args, void *r_ret) {
T converted(*reinterpret_cast<From *>(p_base));
call_with_ptr_args(&converted, method, p_args);
}
-template <class From, class T, class... P>
+template <typename From, typename T, typename... P>
static _FORCE_INLINE_ void vc_convert_ptrcall(void (T::*method)(P...) const, void *p_base, const void **p_args, void *r_ret) {
T converted(*reinterpret_cast<From *>(p_base));
call_with_ptr_argsc(&converted, method, p_args);
}
-template <class R, class T, class... P>
+template <typename R, typename T, typename... P>
static _FORCE_INLINE_ int vc_get_argument_count(R (T::*method)(P...)) {
return sizeof...(P);
}
-template <class R, class T, class... P>
+template <typename R, typename T, typename... P>
static _FORCE_INLINE_ int vc_get_argument_count(R (T::*method)(P...) const) {
return sizeof...(P);
}
-template <class T, class... P>
+template <typename T, typename... P>
static _FORCE_INLINE_ int vc_get_argument_count(void (T::*method)(P...)) {
return sizeof...(P);
}
-template <class T, class... P>
+template <typename T, typename... P>
static _FORCE_INLINE_ int vc_get_argument_count(void (T::*method)(P...) const) {
return sizeof...(P);
}
-template <class R, class T, class... P>
+template <typename R, typename T, typename... P>
static _FORCE_INLINE_ int vc_get_argument_count(R (*method)(T *, P...)) {
return sizeof...(P);
}
-template <class R, class... P>
+template <typename R, typename... P>
static _FORCE_INLINE_ int vc_get_argument_count_static(R (*method)(P...)) {
return sizeof...(P);
}
-template <class R, class T, class... P>
+template <typename R, typename T, typename... P>
static _FORCE_INLINE_ Variant::Type vc_get_argument_type(R (T::*method)(P...), int p_arg) {
return call_get_argument_type<P...>(p_arg);
}
-template <class R, class T, class... P>
+template <typename R, typename T, typename... P>
static _FORCE_INLINE_ Variant::Type vc_get_argument_type(R (T::*method)(P...) const, int p_arg) {
return call_get_argument_type<P...>(p_arg);
}
-template <class T, class... P>
+template <typename T, typename... P>
static _FORCE_INLINE_ Variant::Type vc_get_argument_type(void (T::*method)(P...), int p_arg) {
return call_get_argument_type<P...>(p_arg);
}
-template <class T, class... P>
+template <typename T, typename... P>
static _FORCE_INLINE_ Variant::Type vc_get_argument_type(void (T::*method)(P...) const, int p_arg) {
return call_get_argument_type<P...>(p_arg);
}
-template <class R, class T, class... P>
+template <typename R, typename T, typename... P>
static _FORCE_INLINE_ Variant::Type vc_get_argument_type(R (*method)(T *, P...), int p_arg) {
return call_get_argument_type<P...>(p_arg);
}
-template <class R, class... P>
+template <typename R, typename... P>
static _FORCE_INLINE_ Variant::Type vc_get_argument_type_static(R (*method)(P...), int p_arg) {
return call_get_argument_type<P...>(p_arg);
}
-template <class R, class T, class... P>
+template <typename R, typename T, typename... P>
static _FORCE_INLINE_ Variant::Type vc_get_return_type(R (T::*method)(P...)) {
return GetTypeInfo<R>::VARIANT_TYPE;
}
-template <class R, class T, class... P>
+template <typename R, typename T, typename... P>
static _FORCE_INLINE_ Variant::Type vc_get_return_type(R (T::*method)(P...) const) {
return GetTypeInfo<R>::VARIANT_TYPE;
}
-template <class T, class... P>
+template <typename T, typename... P>
static _FORCE_INLINE_ Variant::Type vc_get_return_type(void (T::*method)(P...)) {
return Variant::NIL;
}
-template <class T, class... P>
+template <typename T, typename... P>
static _FORCE_INLINE_ Variant::Type vc_get_return_type(void (T::*method)(P...) const) {
return Variant::NIL;
}
-template <class R, class... P>
+template <typename R, typename... P>
static _FORCE_INLINE_ Variant::Type vc_get_return_type(R (*method)(P...)) {
return GetTypeInfo<R>::VARIANT_TYPE;
}
-template <class... P>
+template <typename... P>
static _FORCE_INLINE_ Variant::Type vc_get_return_type(void (*method)(P...)) {
return Variant::NIL;
}
-template <class R, class T, class... P>
+template <typename R, typename T, typename... P>
static _FORCE_INLINE_ bool vc_has_return_type(R (T::*method)(P...)) {
return true;
}
-template <class R, class T, class... P>
+template <typename R, typename T, typename... P>
static _FORCE_INLINE_ bool vc_has_return_type(R (T::*method)(P...) const) {
return true;
}
-template <class T, class... P>
+template <typename T, typename... P>
static _FORCE_INLINE_ bool vc_has_return_type(void (T::*method)(P...)) {
return false;
}
-template <class T, class... P>
+template <typename T, typename... P>
static _FORCE_INLINE_ bool vc_has_return_type(void (T::*method)(P...) const) {
return false;
}
-template <class... P>
+template <typename... P>
static _FORCE_INLINE_ bool vc_has_return_type_static(void (*method)(P...)) {
return false;
}
-template <class R, class... P>
+template <typename R, typename... P>
static _FORCE_INLINE_ bool vc_has_return_type_static(R (*method)(P...)) {
return true;
}
-template <class R, class T, class... P>
+template <typename R, typename T, typename... P>
static _FORCE_INLINE_ bool vc_is_const(R (T::*method)(P...)) {
return false;
}
-template <class R, class T, class... P>
+template <typename R, typename T, typename... P>
static _FORCE_INLINE_ bool vc_is_const(R (T::*method)(P...) const) {
return true;
}
-template <class T, class... P>
+template <typename T, typename... P>
static _FORCE_INLINE_ bool vc_is_const(void (T::*method)(P...)) {
return false;
}
-template <class T, class... P>
+template <typename T, typename... P>
static _FORCE_INLINE_ bool vc_is_const(void (T::*method)(P...) const) {
return true;
}
-template <class R, class T, class... P>
+template <typename R, typename T, typename... P>
static _FORCE_INLINE_ Variant::Type vc_get_base_type(R (T::*method)(P...)) {
return GetTypeInfo<T>::VARIANT_TYPE;
}
-template <class R, class T, class... P>
+template <typename R, typename T, typename... P>
static _FORCE_INLINE_ Variant::Type vc_get_base_type(R (T::*method)(P...) const) {
return GetTypeInfo<T>::VARIANT_TYPE;
}
-template <class T, class... P>
+template <typename T, typename... P>
static _FORCE_INLINE_ Variant::Type vc_get_base_type(void (T::*method)(P...)) {
return GetTypeInfo<T>::VARIANT_TYPE;
}
-template <class T, class... P>
+template <typename T, typename... P>
static _FORCE_INLINE_ Variant::Type vc_get_base_type(void (T::*method)(P...) const) {
return GetTypeInfo<T>::VARIANT_TYPE;
}
@@ -450,12 +450,12 @@ static _FORCE_INLINE_ Variant::Type vc_get_base_type(void (T::*method)(P...) con
} \
};
-template <class R, class... P>
+template <typename R, typename... P>
static _FORCE_INLINE_ void vc_static_ptrcall(R (*method)(P...), const void **p_args, void *r_ret) {
call_with_ptr_args_static_method_ret<R, P...>(method, p_args, r_ret);
}
-template <class... P>
+template <typename... P>
static _FORCE_INLINE_ void vc_static_ptrcall(void (*method)(P...), const void **p_args, void *r_ret) {
call_with_ptr_args_static_method<P...>(method, p_args);
}
@@ -500,12 +500,12 @@ static _FORCE_INLINE_ void vc_static_ptrcall(void (*method)(P...), const void **
} \
};
-template <class R, class T, class... P>
+template <typename R, typename T, typename... P>
static _FORCE_INLINE_ void vc_ptrcall(R (*method)(T *, P...), void *p_base, const void **p_args, void *r_ret) {
call_with_ptr_args_static_retc<T, R, P...>(reinterpret_cast<T *>(p_base), method, p_args, r_ret);
}
-template <class T, class... P>
+template <typename T, typename... P>
static _FORCE_INLINE_ void vc_ptrcall(void (*method)(T *, P...), void *p_base, const void **p_args, void *r_ret) {
call_with_ptr_args_static<T, P...>(reinterpret_cast<T *>(p_base), method, p_args);
}
@@ -1164,7 +1164,7 @@ typedef OAHashMap<StringName, VariantBuiltInMethodInfo> BuiltinMethodMap;
static BuiltinMethodMap *builtin_method_info;
static List<StringName> *builtin_method_names;
-template <class T>
+template <typename T>
static void register_builtin_method(const Vector<String> &p_argnames, const Vector<Variant> &p_def_args) {
StringName name = T::get_name();
diff --git a/core/variant/variant_construct.cpp b/core/variant/variant_construct.cpp
index 3427950224..b0ed49be5d 100644
--- a/core/variant/variant_construct.cpp
+++ b/core/variant/variant_construct.cpp
@@ -41,7 +41,7 @@ struct VariantConstructData {
static LocalVector<VariantConstructData> construct_data[Variant::VARIANT_MAX];
-template <class T>
+template <typename T>
static void add_constructor(const Vector<String> &arg_names) {
ERR_FAIL_COND_MSG(arg_names.size() != T::get_argument_count(), "Argument names size mismatch for " + Variant::get_type_name(T::get_base_type()) + ".");
diff --git a/core/variant/variant_construct.h b/core/variant/variant_construct.h
index 36935907ae..a93723a910 100644
--- a/core/variant/variant_construct.h
+++ b/core/variant/variant_construct.h
@@ -42,7 +42,7 @@
#include "core/templates/local_vector.h"
#include "core/templates/oa_hash_map.h"
-template <class T>
+template <typename T>
struct PtrConstruct {};
#define MAKE_PTRCONSTRUCT(m_type) \
@@ -99,7 +99,7 @@ MAKE_PTRCONSTRUCT(PackedVector3Array);
MAKE_PTRCONSTRUCT(PackedColorArray);
MAKE_PTRCONSTRUCT(Variant);
-template <class T, class... P>
+template <typename T, typename... P>
class VariantConstructor {
template <size_t... Is>
static _FORCE_INLINE_ void construct_helper(T &base, const Variant **p_args, Callable::CallError &r_error, IndexSequence<Is...>) {
@@ -222,7 +222,7 @@ public:
}
};
-template <class T>
+template <typename T>
class VariantConstructorFromString {
public:
static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
@@ -470,7 +470,7 @@ public:
}
};
-template <class T>
+template <typename T>
class VariantConstructorToArray {
public:
static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
@@ -529,7 +529,7 @@ public:
}
};
-template <class T>
+template <typename T>
class VariantConstructorFromArray {
public:
static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
@@ -622,7 +622,7 @@ public:
}
};
-template <class T>
+template <typename T>
class VariantConstructNoArgs {
public:
static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
diff --git a/core/variant/variant_destruct.cpp b/core/variant/variant_destruct.cpp
index 5308eba97d..c7455d5117 100644
--- a/core/variant/variant_destruct.cpp
+++ b/core/variant/variant_destruct.cpp
@@ -34,7 +34,7 @@
static Variant::PTRDestructor destruct_pointers[Variant::VARIANT_MAX] = { nullptr };
-template <class T>
+template <typename T>
static void add_destructor() {
destruct_pointers[T::get_base_type()] = T::ptr_destruct;
}
diff --git a/core/variant/variant_destruct.h b/core/variant/variant_destruct.h
index c5f9c260c0..c496189c6d 100644
--- a/core/variant/variant_destruct.h
+++ b/core/variant/variant_destruct.h
@@ -35,7 +35,7 @@
#include "core/object/class_db.h"
-template <class T>
+template <typename T>
struct VariantDestruct {};
#define MAKE_PTRDESTRUCT(m_type) \
diff --git a/core/variant/variant_internal.h b/core/variant/variant_internal.h
index 79bed9be33..dbd4a6a7ad 100644
--- a/core/variant/variant_internal.h
+++ b/core/variant/variant_internal.h
@@ -211,7 +211,7 @@ public:
_FORCE_INLINE_ static const ObjectID get_object_id(const Variant *v) { return v->_get_obj().id; }
- template <class T>
+ template <typename T>
_FORCE_INLINE_ static void init_generic(Variant *v) {
v->type = GetTypeInfo<T>::VARIANT_TYPE;
}
@@ -510,7 +510,7 @@ public:
}
};
-template <class T>
+template <typename T>
struct VariantGetInternalPtr {
};
@@ -797,7 +797,7 @@ struct VariantGetInternalPtr<PackedColorArray> {
static const PackedColorArray *get_ptr(const Variant *v) { return VariantInternal::get_color_array(v); }
};
-template <class T>
+template <typename T>
struct VariantInternalAccessor {
};
@@ -830,13 +830,13 @@ struct VariantInternalAccessor<ObjectID> {
static _FORCE_INLINE_ void set(Variant *v, ObjectID p_value) { *VariantInternal::get_int(v) = p_value; }
};
-template <class T>
+template <typename T>
struct VariantInternalAccessor<T *> {
static _FORCE_INLINE_ T *get(const Variant *v) { return const_cast<T *>(static_cast<const T *>(*VariantInternal::get_object(v))); }
static _FORCE_INLINE_ void set(Variant *v, const T *p_value) { VariantInternal::object_assign(v, p_value); }
};
-template <class T>
+template <typename T>
struct VariantInternalAccessor<const T *> {
static _FORCE_INLINE_ const T *get(const Variant *v) { return static_cast<const T *>(*VariantInternal::get_object(v)); }
static _FORCE_INLINE_ void set(Variant *v, const T *p_value) { VariantInternal::object_assign(v, p_value); }
@@ -1091,7 +1091,7 @@ struct VariantInternalAccessor<Vector<Variant>> {
}
};
-template <class T>
+template <typename T>
struct VariantInitializer {
};
@@ -1301,7 +1301,7 @@ struct VariantInitializer<Object *> {
static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_object(v); }
};
-template <class T>
+template <typename T>
struct VariantDefaultInitializer {
};
@@ -1490,7 +1490,7 @@ struct VariantDefaultInitializer<PackedColorArray> {
static _FORCE_INLINE_ void init(Variant *v) { *VariantInternal::get_color_array(v) = PackedColorArray(); }
};
-template <class T>
+template <typename T>
struct VariantTypeChanger {
static _FORCE_INLINE_ void change(Variant *v) {
if (v->get_type() != GetTypeInfo<T>::VARIANT_TYPE || GetTypeInfo<T>::VARIANT_TYPE >= Variant::PACKED_BYTE_ARRAY) { //second condition removed by optimizer
@@ -1508,7 +1508,7 @@ struct VariantTypeChanger {
}
};
-template <class T>
+template <typename T>
struct VariantTypeAdjust {
_FORCE_INLINE_ static void adjust(Variant *r_ret) {
VariantTypeChanger<typename GetSimpleTypeT<T>::type_t>::change(r_ret);
@@ -1532,7 +1532,7 @@ struct VariantTypeAdjust<Object *> {
// GDExtension helpers.
-template <class T>
+template <typename T>
struct VariantTypeConstructor {
_FORCE_INLINE_ static void variant_from_type(void *r_variant, void *p_value) {
// r_variant is provided by caller as uninitialized memory
diff --git a/core/variant/variant_op.cpp b/core/variant/variant_op.cpp
index 4f9c38dc4c..60ae09c6f1 100644
--- a/core/variant/variant_op.cpp
+++ b/core/variant/variant_op.cpp
@@ -37,7 +37,7 @@ static VariantEvaluatorFunction operator_evaluator_table[Variant::OP_MAX][Varian
static Variant::ValidatedOperatorEvaluator validated_operator_evaluator_table[Variant::OP_MAX][Variant::VARIANT_MAX][Variant::VARIANT_MAX];
static Variant::PTROperatorEvaluator ptr_operator_evaluator_table[Variant::OP_MAX][Variant::VARIANT_MAX][Variant::VARIANT_MAX];
-template <class T>
+template <typename T>
void register_op(Variant::Operator p_op, Variant::Type p_type_a, Variant::Type p_type_b) {
operator_return_type_table[p_op][p_type_a][p_type_b] = T::get_return_type();
operator_evaluator_table[p_op][p_type_a][p_type_b] = T::evaluate;
diff --git a/core/variant/variant_op.h b/core/variant/variant_op.h
index 17ad126891..3142f49fc6 100644
--- a/core/variant/variant_op.h
+++ b/core/variant/variant_op.h
@@ -37,7 +37,7 @@
#include "core/debugger/engine_debugger.h"
#include "core/object/class_db.h"
-template <class R, class A, class B>
+template <typename R, typename A, typename B>
class OperatorEvaluatorAdd {
public:
static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
@@ -55,7 +55,7 @@ public:
static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
};
-template <class R, class A, class B>
+template <typename R, typename A, typename B>
class OperatorEvaluatorSub {
public:
static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
@@ -73,7 +73,7 @@ public:
static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
};
-template <class R, class A, class B>
+template <typename R, typename A, typename B>
class OperatorEvaluatorMul {
public:
static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
@@ -91,7 +91,7 @@ public:
static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
};
-template <class R, class A, class B>
+template <typename R, typename A, typename B>
class OperatorEvaluatorPow {
public:
static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
@@ -109,7 +109,7 @@ public:
static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
};
-template <class R, class A, class B>
+template <typename R, typename A, typename B>
class OperatorEvaluatorXForm {
public:
static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
@@ -127,7 +127,7 @@ public:
static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
};
-template <class R, class A, class B>
+template <typename R, typename A, typename B>
class OperatorEvaluatorXFormInv {
public:
static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
@@ -145,7 +145,7 @@ public:
static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
};
-template <class R, class A, class B>
+template <typename R, typename A, typename B>
class OperatorEvaluatorDiv {
public:
static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
@@ -163,7 +163,7 @@ public:
static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
};
-template <class R, class A, class B>
+template <typename R, typename A, typename B>
class OperatorEvaluatorDivNZ {
public:
static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
@@ -258,7 +258,7 @@ public:
static Variant::Type get_return_type() { return GetTypeInfo<Vector4i>::VARIANT_TYPE; }
};
-template <class R, class A, class B>
+template <typename R, typename A, typename B>
class OperatorEvaluatorMod {
public:
static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
@@ -276,7 +276,7 @@ public:
static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
};
-template <class R, class A, class B>
+template <typename R, typename A, typename B>
class OperatorEvaluatorModNZ {
public:
static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
@@ -371,7 +371,7 @@ public:
static Variant::Type get_return_type() { return GetTypeInfo<Vector4i>::VARIANT_TYPE; }
};
-template <class R, class A>
+template <typename R, typename A>
class OperatorEvaluatorNeg {
public:
static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
@@ -388,7 +388,7 @@ public:
static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
};
-template <class R, class A>
+template <typename R, typename A>
class OperatorEvaluatorPos {
public:
static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
@@ -405,7 +405,7 @@ public:
static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
};
-template <class R, class A, class B>
+template <typename R, typename A, typename B>
class OperatorEvaluatorShiftLeft {
public:
static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
@@ -431,7 +431,7 @@ public:
static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
};
-template <class R, class A, class B>
+template <typename R, typename A, typename B>
class OperatorEvaluatorShiftRight {
public:
static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
@@ -457,7 +457,7 @@ public:
static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
};
-template <class R, class A, class B>
+template <typename R, typename A, typename B>
class OperatorEvaluatorBitOr {
public:
static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
@@ -475,7 +475,7 @@ public:
static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
};
-template <class R, class A, class B>
+template <typename R, typename A, typename B>
class OperatorEvaluatorBitAnd {
public:
static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
@@ -493,7 +493,7 @@ public:
static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
};
-template <class R, class A, class B>
+template <typename R, typename A, typename B>
class OperatorEvaluatorBitXor {
public:
static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
@@ -511,7 +511,7 @@ public:
static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
};
-template <class R, class A>
+template <typename R, typename A>
class OperatorEvaluatorBitNeg {
public:
static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
@@ -528,7 +528,7 @@ public:
static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
};
-template <class A, class B>
+template <typename A, typename B>
class OperatorEvaluatorEqual {
public:
static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
@@ -599,7 +599,7 @@ public:
static Variant::Type get_return_type() { return Variant::BOOL; }
};
-template <class A, class B>
+template <typename A, typename B>
class OperatorEvaluatorNotEqual {
public:
static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
@@ -670,7 +670,7 @@ public:
static Variant::Type get_return_type() { return Variant::BOOL; }
};
-template <class A, class B>
+template <typename A, typename B>
class OperatorEvaluatorLess {
public:
static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
@@ -688,7 +688,7 @@ public:
static Variant::Type get_return_type() { return Variant::BOOL; }
};
-template <class A, class B>
+template <typename A, typename B>
class OperatorEvaluatorLessEqual {
public:
static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
@@ -706,7 +706,7 @@ public:
static Variant::Type get_return_type() { return Variant::BOOL; }
};
-template <class A, class B>
+template <typename A, typename B>
class OperatorEvaluatorGreater {
public:
static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
@@ -724,7 +724,7 @@ public:
static Variant::Type get_return_type() { return Variant::BOOL; }
};
-template <class A, class B>
+template <typename A, typename B>
class OperatorEvaluatorGreaterEqual {
public:
static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
@@ -742,7 +742,7 @@ public:
static Variant::Type get_return_type() { return Variant::BOOL; }
};
-template <class A, class B>
+template <typename A, typename B>
class OperatorEvaluatorAnd {
public:
static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
@@ -760,7 +760,7 @@ public:
static Variant::Type get_return_type() { return Variant::BOOL; }
};
-template <class A, class B>
+template <typename A, typename B>
class OperatorEvaluatorOr {
public:
static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
@@ -779,7 +779,7 @@ public:
};
#define XOR_OP(m_a, m_b) (((m_a) || (m_b)) && !((m_a) && (m_b)))
-template <class A, class B>
+template <typename A, typename B>
class OperatorEvaluatorXor {
public:
_FORCE_INLINE_ static bool xor_op(const A &a, const B &b) {
@@ -800,7 +800,7 @@ public:
static Variant::Type get_return_type() { return Variant::BOOL; }
};
-template <class A>
+template <typename A>
class OperatorEvaluatorNot {
public:
static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
@@ -857,7 +857,7 @@ public:
static Variant::Type get_return_type() { return Variant::ARRAY; }
};
-template <class T>
+template <typename T>
class OperatorEvaluatorAppendArray {
public:
static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
@@ -880,7 +880,7 @@ public:
static Variant::Type get_return_type() { return GetTypeInfo<Vector<T>>::VARIANT_TYPE; }
};
-template <class Left, class Right>
+template <typename Left, typename Right>
class OperatorEvaluatorStringConcat {
public:
static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
@@ -902,10 +902,10 @@ public:
static Variant::Type get_return_type() { return Variant::STRING; }
};
-template <class S, class T>
+template <typename S, typename T>
class OperatorEvaluatorStringFormat;
-template <class S>
+template <typename S>
class OperatorEvaluatorStringFormat<S, void> {
public:
_FORCE_INLINE_ static String do_mod(const String &s, bool *r_valid) {
@@ -933,7 +933,7 @@ public:
static Variant::Type get_return_type() { return Variant::STRING; }
};
-template <class S>
+template <typename S>
class OperatorEvaluatorStringFormat<S, Array> {
public:
_FORCE_INLINE_ static String do_mod(const String &s, const Array &p_values, bool *r_valid) {
@@ -958,7 +958,7 @@ public:
static Variant::Type get_return_type() { return Variant::STRING; }
};
-template <class S>
+template <typename S>
class OperatorEvaluatorStringFormat<S, Object> {
public:
_FORCE_INLINE_ static String do_mod(const String &s, const Object *p_object, bool *r_valid) {
@@ -986,7 +986,7 @@ public:
static Variant::Type get_return_type() { return Variant::STRING; }
};
-template <class S, class T>
+template <typename S, typename T>
class OperatorEvaluatorStringFormat {
public:
_FORCE_INLINE_ static String do_mod(const String &s, const T &p_value, bool *r_valid) {
@@ -1317,10 +1317,10 @@ public:
////
-template <class Left, class Right>
+template <typename Left, typename Right>
class OperatorEvaluatorInStringFind;
-template <class Left>
+template <typename Left>
class OperatorEvaluatorInStringFind<Left, String> {
public:
static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
@@ -1341,7 +1341,7 @@ public:
static Variant::Type get_return_type() { return Variant::BOOL; }
};
-template <class Left>
+template <typename Left>
class OperatorEvaluatorInStringFind<Left, StringName> {
public:
static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
@@ -1362,7 +1362,7 @@ public:
static Variant::Type get_return_type() { return Variant::BOOL; }
};
-template <class A, class B>
+template <typename A, typename B>
class OperatorEvaluatorInArrayFind {
public:
static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
@@ -1417,7 +1417,7 @@ public:
static Variant::Type get_return_type() { return Variant::BOOL; }
};
-template <class A>
+template <typename A>
class OperatorEvaluatorInDictionaryHas {
public:
static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
diff --git a/core/variant/variant_parser.cpp b/core/variant/variant_parser.cpp
index e35751fd61..46c450d9f8 100644
--- a/core/variant/variant_parser.cpp
+++ b/core/variant/variant_parser.cpp
@@ -546,7 +546,7 @@ Error VariantParser::_parse_enginecfg(Stream *p_stream, Vector<String> &strings,
}
}
-template <class T>
+template <typename T>
Error VariantParser::_parse_construct(Stream *p_stream, Vector<T> &r_construct, int &line, String &r_err_str) {
Token token;
get_token(p_stream, token, line, r_err_str);
diff --git a/core/variant/variant_parser.h b/core/variant/variant_parser.h
index 8505fff739..18448100e0 100644
--- a/core/variant/variant_parser.h
+++ b/core/variant/variant_parser.h
@@ -139,7 +139,7 @@ public:
private:
static const char *tk_name[TK_MAX];
- template <class T>
+ template <typename T>
static Error _parse_construct(Stream *p_stream, Vector<T> &r_construct, int &line, String &r_err_str);
static Error _parse_enginecfg(Stream *p_stream, Vector<String> &strings, int &line, String &r_err_str);
static Error _parse_dictionary(Dictionary &object, Stream *p_stream, int &line, String &r_err_str, ResourceParser *p_res_parser = nullptr);
diff --git a/core/variant/variant_setget.cpp b/core/variant/variant_setget.cpp
index 20941b944f..9d5ed22b1a 100644
--- a/core/variant/variant_setget.cpp
+++ b/core/variant/variant_setget.cpp
@@ -45,7 +45,7 @@ struct VariantSetterGetterInfo {
static LocalVector<VariantSetterGetterInfo> variant_setters_getters[Variant::VARIANT_MAX];
static LocalVector<StringName> variant_setters_getters_names[Variant::VARIANT_MAX]; //one next to another to make it cache friendly
-template <class T>
+template <typename T>
static void register_member(Variant::Type p_type, const StringName &p_member) {
VariantSetterGetterInfo sgi;
sgi.setter = T::set;
@@ -873,7 +873,7 @@ struct VariantIndexedSetterGetterInfo {
static VariantIndexedSetterGetterInfo variant_indexed_setters_getters[Variant::VARIANT_MAX];
-template <class T>
+template <typename T>
static void register_indexed_member(Variant::Type p_type) {
VariantIndexedSetterGetterInfo &sgi = variant_indexed_setters_getters[p_type];
@@ -1094,7 +1094,7 @@ struct VariantKeyedSetterGetterInfo {
static VariantKeyedSetterGetterInfo variant_keyed_setters_getters[Variant::VARIANT_MAX];
-template <class T>
+template <typename T>
static void register_keyed_member(Variant::Type p_type) {
VariantKeyedSetterGetterInfo &sgi = variant_keyed_setters_getters[p_type];
diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp
index 7136fa00c4..916ba7aa2f 100644
--- a/core/variant/variant_utility.cpp
+++ b/core/variant/variant_utility.cpp
@@ -1235,7 +1235,7 @@ bool VariantUtilityFunctions::is_same(const Variant &p_a, const Variant &p_b) {
#define VCALL p_func(VariantCaster<P>::cast(*p_args[Is])...)
#endif
-template <class R, class... P, size_t... Is>
+template <typename R, typename... P, size_t... Is>
static _FORCE_INLINE_ void call_helperpr(R (*p_func)(P...), Variant *ret, const Variant **p_args, Callable::CallError &r_error, IndexSequence<Is...>) {
r_error.error = Callable::CallError::CALL_OK;
VCALLR;
@@ -1243,51 +1243,51 @@ static _FORCE_INLINE_ void call_helperpr(R (*p_func)(P...), Variant *ret, const
(void)r_error;
}
-template <class R, class... P, size_t... Is>
+template <typename R, typename... P, size_t... Is>
static _FORCE_INLINE_ void validated_call_helperpr(R (*p_func)(P...), Variant *ret, const Variant **p_args, IndexSequence<Is...>) {
*ret = p_func(VariantCaster<P>::cast(*p_args[Is])...);
(void)p_args;
}
-template <class R, class... P, size_t... Is>
+template <typename R, typename... P, size_t... Is>
static _FORCE_INLINE_ void ptr_call_helperpr(R (*p_func)(P...), void *ret, const void **p_args, IndexSequence<Is...>) {
PtrToArg<R>::encode(p_func(PtrToArg<P>::convert(p_args[Is])...), ret);
(void)p_args;
}
-template <class R, class... P>
+template <typename R, typename... P>
static _FORCE_INLINE_ void call_helperr(R (*p_func)(P...), Variant *ret, const Variant **p_args, Callable::CallError &r_error) {
call_helperpr(p_func, ret, p_args, r_error, BuildIndexSequence<sizeof...(P)>{});
}
-template <class R, class... P>
+template <typename R, typename... P>
static _FORCE_INLINE_ void validated_call_helperr(R (*p_func)(P...), Variant *ret, const Variant **p_args) {
validated_call_helperpr(p_func, ret, p_args, BuildIndexSequence<sizeof...(P)>{});
}
-template <class R, class... P>
+template <typename R, typename... P>
static _FORCE_INLINE_ void ptr_call_helperr(R (*p_func)(P...), void *ret, const void **p_args) {
ptr_call_helperpr(p_func, ret, p_args, BuildIndexSequence<sizeof...(P)>{});
}
-template <class R, class... P>
+template <typename R, typename... P>
static _FORCE_INLINE_ int get_arg_count_helperr(R (*p_func)(P...)) {
return sizeof...(P);
}
-template <class R, class... P>
+template <typename R, typename... P>
static _FORCE_INLINE_ Variant::Type get_arg_type_helperr(R (*p_func)(P...), int p_arg) {
return call_get_argument_type<P...>(p_arg);
}
-template <class R, class... P>
+template <typename R, typename... P>
static _FORCE_INLINE_ Variant::Type get_ret_type_helperr(R (*p_func)(P...)) {
return GetTypeInfo<R>::VARIANT_TYPE;
}
// WITHOUT RET
-template <class... P, size_t... Is>
+template <typename... P, size_t... Is>
static _FORCE_INLINE_ void call_helperp(void (*p_func)(P...), const Variant **p_args, Callable::CallError &r_error, IndexSequence<Is...>) {
r_error.error = Callable::CallError::CALL_OK;
VCALL;
@@ -1295,44 +1295,44 @@ static _FORCE_INLINE_ void call_helperp(void (*p_func)(P...), const Variant **p_
(void)r_error;
}
-template <class... P, size_t... Is>
+template <typename... P, size_t... Is>
static _FORCE_INLINE_ void validated_call_helperp(void (*p_func)(P...), const Variant **p_args, IndexSequence<Is...>) {
p_func(VariantCaster<P>::cast(*p_args[Is])...);
(void)p_args;
}
-template <class... P, size_t... Is>
+template <typename... P, size_t... Is>
static _FORCE_INLINE_ void ptr_call_helperp(void (*p_func)(P...), const void **p_args, IndexSequence<Is...>) {
p_func(PtrToArg<P>::convert(p_args[Is])...);
(void)p_args;
}
-template <class... P>
+template <typename... P>
static _FORCE_INLINE_ void call_helper(void (*p_func)(P...), const Variant **p_args, Callable::CallError &r_error) {
call_helperp(p_func, p_args, r_error, BuildIndexSequence<sizeof...(P)>{});
}
-template <class... P>
+template <typename... P>
static _FORCE_INLINE_ void validated_call_helper(void (*p_func)(P...), const Variant **p_args) {
validated_call_helperp(p_func, p_args, BuildIndexSequence<sizeof...(P)>{});
}
-template <class... P>
+template <typename... P>
static _FORCE_INLINE_ void ptr_call_helper(void (*p_func)(P...), const void **p_args) {
ptr_call_helperp(p_func, p_args, BuildIndexSequence<sizeof...(P)>{});
}
-template <class... P>
+template <typename... P>
static _FORCE_INLINE_ int get_arg_count_helper(void (*p_func)(P...)) {
return sizeof...(P);
}
-template <class... P>
+template <typename... P>
static _FORCE_INLINE_ Variant::Type get_arg_type_helper(void (*p_func)(P...), int p_arg) {
return call_get_argument_type<P...>(p_arg);
}
-template <class... P>
+template <typename... P>
static _FORCE_INLINE_ Variant::Type get_ret_type_helper(void (*p_func)(P...)) {
return Variant::NIL;
}
@@ -1645,7 +1645,7 @@ struct VariantUtilityFunctionInfo {
static OAHashMap<StringName, VariantUtilityFunctionInfo> utility_function_table;
static List<StringName> utility_function_name_table;
-template <class T>
+template <typename T>
static void register_utility_function(const String &p_name, const Vector<String> &argnames) {
String name = p_name;
if (name.begins_with("_")) {
diff --git a/doc/classes/NativeMenu.xml b/doc/classes/NativeMenu.xml
index 159666ded8..cc81c81a24 100644
--- a/doc/classes/NativeMenu.xml
+++ b/doc/classes/NativeMenu.xml
@@ -5,6 +5,35 @@
</brief_description>
<description>
[NativeMenu] handles low-level access to the OS native global menu bar and popup menus.
+ [b]Note:[/b] This is low-level API, consider using [MenuBar] with [member MenuBar.prefer_global_menu] set to [code]true[/code], and [PopupMenu] with [member PopupMenu.prefer_native_menu] set to [code]true[/code].
+ To create a menu, use [method create_menu], add menu items using [code]add_*_item[/code] methods. To remove a menu, use [method free_menu].
+ [codeblock]
+ var menu
+
+ func _menu_callback(item_id):
+ if item_id == "ITEM_CUT":
+ cut()
+ elif item_id == "ITEM_COPY":
+ copy()
+ elif item_id == "ITEM_PASTE":
+ paste()
+
+ func _enter_tree():
+ # Create new menu and add items:
+ menu = NativeMenu.create_menu()
+ NativeMenu.add_item(menu, "Cut", _menu_callback, Callable(), "ITEM_CUT")
+ NativeMenu.add_item(menu, "Copy", _menu_callback, Callable(), "ITEM_COPY")
+ NativeMenu.add_separator(menu)
+ NativeMenu.add_item(menu, "Paste", _menu_callback, Callable(), "ITEM_PASTE")
+
+ func _on_button_pressed():
+ # Show popup menu at mouse position:
+ NativeMenu.popup(menu, DisplayServer.mouse_get_position())
+
+ func _exit_tree():
+ # Remove menu when it's no longer needed:
+ NativeMenu.free_menu(menu)
+ [/codeblock]
</description>
<tutorials>
</tutorials>
@@ -23,7 +52,8 @@
Returns index of the inserted item, it's not guaranteed to be the same as [param index] value.
An [param accelerator] can optionally be defined, which is a keyboard shortcut that can be pressed to trigger the menu button even if it's not currently open. The [param accelerator] is generally a combination of [enum KeyModifierMask]s and [enum Key]s using bitwise OR such as [code]KEY_MASK_CTRL | KEY_A[/code] ([kbd]Ctrl + A[/kbd]).
[b]Note:[/b] The [param callback] and [param key_callback] Callables need to accept exactly one Variant parameter, the parameter passed to the Callables will be the value passed to [param tag].
- [b]Note:[/b] This method is implemented only on macOS.
+ [b]Note:[/b] This method is implemented on macOS and Windows.
+ [b]Note:[/b] [param accelerator] and [param key_callback] are ignored on Windows.
</description>
</method>
<method name="add_icon_check_item">
@@ -41,7 +71,8 @@
Returns index of the inserted item, it's not guaranteed to be the same as [param index] value.
An [param accelerator] can optionally be defined, which is a keyboard shortcut that can be pressed to trigger the menu button even if it's not currently open. The [param accelerator] is generally a combination of [enum KeyModifierMask]s and [enum Key]s using bitwise OR such as [code]KEY_MASK_CTRL | KEY_A[/code] ([kbd]Ctrl + A[/kbd]).
[b]Note:[/b] The [param callback] and [param key_callback] Callables need to accept exactly one Variant parameter, the parameter passed to the Callables will be the value passed to [param tag].
- [b]Note:[/b] This method is implemented only on macOS.
+ [b]Note:[/b] This method is implemented on macOS and Windows.
+ [b]Note:[/b] [param accelerator] and [param key_callback] are ignored on Windows.
</description>
</method>
<method name="add_icon_item">
@@ -59,7 +90,8 @@
Returns index of the inserted item, it's not guaranteed to be the same as [param index] value.
An [param accelerator] can optionally be defined, which is a keyboard shortcut that can be pressed to trigger the menu button even if it's not currently open. The [param accelerator] is generally a combination of [enum KeyModifierMask]s and [enum Key]s using bitwise OR such as [code]KEY_MASK_CTRL | KEY_A[/code] ([kbd]Ctrl + A[/kbd]).
[b]Note:[/b] The [param callback] and [param key_callback] Callables need to accept exactly one Variant parameter, the parameter passed to the Callables will be the value passed to [param tag].
- [b]Note:[/b] This method is implemented only on macOS.
+ [b]Note:[/b] This method is implemented on macOS and Windows.
+ [b]Note:[/b] [param accelerator] and [param key_callback] are ignored on Windows.
</description>
</method>
<method name="add_icon_radio_check_item">
@@ -78,7 +110,8 @@
An [param accelerator] can optionally be defined, which is a keyboard shortcut that can be pressed to trigger the menu button even if it's not currently open. The [param accelerator] is generally a combination of [enum KeyModifierMask]s and [enum Key]s using bitwise OR such as [code]KEY_MASK_CTRL | KEY_A[/code] ([kbd]Ctrl + A[/kbd]).
[b]Note:[/b] Radio-checkable items just display a checkmark, but don't have any built-in checking behavior and must be checked/unchecked manually. See [method set_item_checked] for more info on how to control it.
[b]Note:[/b] The [param callback] and [param key_callback] Callables need to accept exactly one Variant parameter, the parameter passed to the Callables will be the value passed to [param tag].
- [b]Note:[/b] This method is implemented only on macOS.
+ [b]Note:[/b] This method is implemented on macOS and Windows.
+ [b]Note:[/b] [param accelerator] and [param key_callback] are ignored on Windows.
</description>
</method>
<method name="add_item">
@@ -95,7 +128,8 @@
Returns index of the inserted item, it's not guaranteed to be the same as [param index] value.
An [param accelerator] can optionally be defined, which is a keyboard shortcut that can be pressed to trigger the menu button even if it's not currently open. The [param accelerator] is generally a combination of [enum KeyModifierMask]s and [enum Key]s using bitwise OR such as [code]KEY_MASK_CTRL | KEY_A[/code] ([kbd]Ctrl + A[/kbd]).
[b]Note:[/b] The [param callback] and [param key_callback] Callables need to accept exactly one Variant parameter, the parameter passed to the Callables will be the value passed to [param tag].
- [b]Note:[/b] This method is implemented only on macOS.
+ [b]Note:[/b] This method is implemented on macOS and Windows.
+ [b]Note:[/b] [param accelerator] and [param key_callback] are ignored on Windows.
</description>
</method>
<method name="add_multistate_item">
@@ -116,7 +150,8 @@
An [param accelerator] can optionally be defined, which is a keyboard shortcut that can be pressed to trigger the menu button even if it's not currently open. The [param accelerator] is generally a combination of [enum KeyModifierMask]s and [enum Key]s using bitwise OR such as [code]KEY_MASK_CTRL | KEY_A[/code] ([kbd]Ctrl + A[/kbd]).
[b]Note:[/b] By default, there's no indication of the current item state, it should be changed manually.
[b]Note:[/b] The [param callback] and [param key_callback] Callables need to accept exactly one Variant parameter, the parameter passed to the Callables will be the value passed to [param tag].
- [b]Note:[/b] This method is implemented only on macOS.
+ [b]Note:[/b] This method is implemented on macOS and Windows.
+ [b]Note:[/b] [param accelerator] and [param key_callback] are ignored on Windows.
</description>
</method>
<method name="add_radio_check_item">
@@ -134,7 +169,8 @@
An [param accelerator] can optionally be defined, which is a keyboard shortcut that can be pressed to trigger the menu button even if it's not currently open. The [param accelerator] is generally a combination of [enum KeyModifierMask]s and [enum Key]s using bitwise OR such as [code]KEY_MASK_CTRL | KEY_A[/code] ([kbd]Ctrl + A[/kbd]).
[b]Note:[/b] Radio-checkable items just display a checkmark, but don't have any built-in checking behavior and must be checked/unchecked manually. See [method set_item_checked] for more info on how to control it.
[b]Note:[/b] The [param callback] and [param key_callback] Callables need to accept exactly one Variant parameter, the parameter passed to the Callables will be the value passed to [param tag].
- [b]Note:[/b] This method is implemented only on macOS.
+ [b]Note:[/b] This method is implemented on macOS and Windows.
+ [b]Note:[/b] [param accelerator] and [param key_callback] are ignored on Windows.
</description>
</method>
<method name="add_separator">
@@ -144,7 +180,7 @@
<description>
Adds a separator between items to the global menu [param rid]. Separators also occupy an index.
Returns index of the inserted item, it's not guaranteed to be the same as [param index] value.
- [b]Note:[/b] This method is implemented only on macOS.
+ [b]Note:[/b] This method is implemented on macOS and Windows.
</description>
</method>
<method name="add_submenu_item">
@@ -157,7 +193,7 @@
<description>
Adds an item that will act as a submenu of the global menu [param rid]. The [param submenu_rid] argument is the RID of the global menu that will be shown when the item is clicked.
Returns index of the inserted item, it's not guaranteed to be the same as [param index] value.
- [b]Note:[/b] This method is implemented only on macOS.
+ [b]Note:[/b] This method is implemented on macOS and Windows.
</description>
</method>
<method name="clear">
@@ -165,14 +201,14 @@
<param index="0" name="rid" type="RID" />
<description>
Removes all items from the global menu [param rid].
- [b]Note:[/b] This method is implemented only on macOS.
+ [b]Note:[/b] This method is implemented on macOS and Windows.
</description>
</method>
<method name="create_menu">
<return type="RID" />
<description>
Creates a new global menu object.
- [b]Note:[/b] This method is implemented only on macOS.
+ [b]Note:[/b] This method is implemented on macOS and Windows.
</description>
</method>
<method name="find_item_index_with_tag" qualifiers="const">
@@ -181,7 +217,7 @@
<param index="1" name="tag" type="Variant" />
<description>
Returns the index of the item with the specified [param tag]. Index is automatically assigned to each item by the engine. Index can not be set manually.
- [b]Note:[/b] This method is implemented only on macOS.
+ [b]Note:[/b] This method is implemented on macOS and Windows.
</description>
</method>
<method name="find_item_index_with_text" qualifiers="const">
@@ -190,7 +226,7 @@
<param index="1" name="text" type="String" />
<description>
Returns the index of the item with the specified [param text]. Index is automatically assigned to each item by the engine. Index can not be set manually.
- [b]Note:[/b] This method is implemented only on macOS.
+ [b]Note:[/b] This method is implemented on macOS and Windows.
</description>
</method>
<method name="free_menu">
@@ -198,7 +234,7 @@
<param index="0" name="rid" type="RID" />
<description>
Frees a global menu object created by this [NativeMenu].
- [b]Note:[/b] This method is implemented only on macOS.
+ [b]Note:[/b] This method is implemented on macOS and Windows.
</description>
</method>
<method name="get_item_accelerator" qualifiers="const">
@@ -216,7 +252,7 @@
<param index="1" name="idx" type="int" />
<description>
Returns the callback of the item at index [param idx].
- [b]Note:[/b] This method is implemented only on macOS.
+ [b]Note:[/b] This method is implemented on macOS and Windows.
</description>
</method>
<method name="get_item_count" qualifiers="const">
@@ -224,7 +260,7 @@
<param index="0" name="rid" type="RID" />
<description>
Returns number of items in the global menu [param rid].
- [b]Note:[/b] This method is implemented only on macOS.
+ [b]Note:[/b] This method is implemented on macOS and Windows.
</description>
</method>
<method name="get_item_icon" qualifiers="const">
@@ -233,7 +269,7 @@
<param index="1" name="idx" type="int" />
<description>
Returns the icon of the item at index [param idx].
- [b]Note:[/b] This method is implemented only on macOS.
+ [b]Note:[/b] This method is implemented on macOS and Windows.
</description>
</method>
<method name="get_item_indentation_level" qualifiers="const">
@@ -260,7 +296,7 @@
<param index="1" name="idx" type="int" />
<description>
Returns number of states of a multistate item. See [method add_multistate_item] for details.
- [b]Note:[/b] This method is implemented only on macOS.
+ [b]Note:[/b] This method is implemented on macOS and Windows.
</description>
</method>
<method name="get_item_state" qualifiers="const">
@@ -269,7 +305,7 @@
<param index="1" name="idx" type="int" />
<description>
Returns the state of a multistate item. See [method add_multistate_item] for details.
- [b]Note:[/b] This method is implemented only on macOS.
+ [b]Note:[/b] This method is implemented on macOS and Windows.
</description>
</method>
<method name="get_item_submenu" qualifiers="const">
@@ -278,7 +314,7 @@
<param index="1" name="idx" type="int" />
<description>
Returns the submenu ID of the item at index [param idx]. See [method add_submenu_item] for more info on how to add a submenu.
- [b]Note:[/b] This method is implemented only on macOS.
+ [b]Note:[/b] This method is implemented on macOS and Windows.
</description>
</method>
<method name="get_item_tag" qualifiers="const">
@@ -287,7 +323,7 @@
<param index="1" name="idx" type="int" />
<description>
Returns the metadata of the specified item, which might be of any type. You can set it with [method set_item_tag], which provides a simple way of assigning context data to items.
- [b]Note:[/b] This method is implemented only on macOS.
+ [b]Note:[/b] This method is implemented on macOS and Windows.
</description>
</method>
<method name="get_item_text" qualifiers="const">
@@ -296,7 +332,7 @@
<param index="1" name="idx" type="int" />
<description>
Returns the text of the item at index [param idx].
- [b]Note:[/b] This method is implemented only on macOS.
+ [b]Note:[/b] This method is implemented on macOS and Windows.
</description>
</method>
<method name="get_item_tooltip" qualifiers="const">
@@ -337,7 +373,7 @@
<param index="0" name="rid" type="RID" />
<description>
Returns global menu size.
- [b]Note:[/b] This method is implemented only on macOS.
+ [b]Note:[/b] This method is implemented on macOS and Windows.
</description>
</method>
<method name="get_system_menu" qualifiers="const">
@@ -361,7 +397,7 @@
<param index="0" name="feature" type="int" enum="NativeMenu.Feature" />
<description>
Returns [code]true[/code] if the specified [param feature] is supported by the current [NativeMenu], [code]false[/code] otherwise.
- [b]Note:[/b] This method is implemented only on macOS.
+ [b]Note:[/b] This method is implemented on macOS and Windows.
</description>
</method>
<method name="has_menu" qualifiers="const">
@@ -369,7 +405,7 @@
<param index="0" name="rid" type="RID" />
<description>
Returns [code]true[/code] if [param rid] is valid global menu.
- [b]Note:[/b] This method is implemented only on macOS.
+ [b]Note:[/b] This method is implemented on macOS and Windows.
</description>
</method>
<method name="has_system_menu" qualifiers="const">
@@ -386,7 +422,7 @@
<param index="1" name="idx" type="int" />
<description>
Returns [code]true[/code] if the item at index [param idx] is checkable in some way, i.e. if it has a checkbox or radio button.
- [b]Note:[/b] This method is implemented only on macOS.
+ [b]Note:[/b] This method is implemented on macOS and Windows.
</description>
</method>
<method name="is_item_checked" qualifiers="const">
@@ -395,7 +431,7 @@
<param index="1" name="idx" type="int" />
<description>
Returns [code]true[/code] if the item at index [param idx] is checked.
- [b]Note:[/b] This method is implemented only on macOS.
+ [b]Note:[/b] This method is implemented on macOS and Windows.
</description>
</method>
<method name="is_item_disabled" qualifiers="const">
@@ -405,7 +441,7 @@
<description>
Returns [code]true[/code] if the item at index [param idx] is disabled. When it is disabled it can't be selected, or its action invoked.
See [method set_item_disabled] for more info on how to disable an item.
- [b]Note:[/b] This method is implemented only on macOS.
+ [b]Note:[/b] This method is implemented on macOS and Windows.
</description>
</method>
<method name="is_item_hidden" qualifiers="const">
@@ -425,7 +461,7 @@
<description>
Returns [code]true[/code] if the item at index [param idx] has radio button-style checkability.
[b]Note:[/b] This is purely cosmetic; you must add the logic for checking/unchecking items in radio groups.
- [b]Note:[/b] This method is implemented only on macOS.
+ [b]Note:[/b] This method is implemented on macOS and Windows.
</description>
</method>
<method name="is_system_menu" qualifiers="const">
@@ -442,7 +478,7 @@
<param index="1" name="position" type="Vector2i" />
<description>
Shows the global menu at [param position] in the screen coordinates.
- [b]Note:[/b] This method is implemented only on macOS.
+ [b]Note:[/b] This method is implemented on macOS and Windows.
</description>
</method>
<method name="remove_item">
@@ -452,7 +488,16 @@
<description>
Removes the item at index [param idx] from the global menu [param rid].
[b]Note:[/b] The indices of items after the removed item will be shifted by one.
- [b]Note:[/b] This method is implemented only on macOS.
+ [b]Note:[/b] This method is implemented on macOS and Windows.
+ </description>
+ </method>
+ <method name="set_interface_direction">
+ <return type="void" />
+ <param index="0" name="rid" type="RID" />
+ <param index="1" name="is_rtl" type="bool" />
+ <description>
+ Sets the menu text layout directtion.
+ [b]Note:[/b] This method is implemented on macOS and Windows.
</description>
</method>
<method name="set_item_accelerator">
@@ -473,7 +518,7 @@
<description>
Sets the callback of the item at index [param idx]. Callback is emitted when an item is pressed.
[b]Note:[/b] The [param callback] Callable needs to accept exactly one Variant parameter, the parameter passed to the Callable will be the value passed to the [code]tag[/code] parameter when the menu item was created.
- [b]Note:[/b] This method is implemented only on macOS.
+ [b]Note:[/b] This method is implemented on macOS and Windows.
</description>
</method>
<method name="set_item_checkable">
@@ -483,7 +528,7 @@
<param index="2" name="checkable" type="bool" />
<description>
Sets whether the item at index [param idx] has a checkbox. If [code]false[/code], sets the type of the item to plain text.
- [b]Note:[/b] This method is implemented only on macOS.
+ [b]Note:[/b] This method is implemented on macOS and Windows.
</description>
</method>
<method name="set_item_checked">
@@ -493,7 +538,7 @@
<param index="2" name="checked" type="bool" />
<description>
Sets the checkstate status of the item at index [param idx].
- [b]Note:[/b] This method is implemented only on macOS.
+ [b]Note:[/b] This method is implemented on macOS and Windows.
</description>
</method>
<method name="set_item_disabled">
@@ -503,7 +548,7 @@
<param index="2" name="disabled" type="bool" />
<description>
Enables/disables the item at index [param idx]. When it is disabled, it can't be selected and its action can't be invoked.
- [b]Note:[/b] This method is implemented only on macOS.
+ [b]Note:[/b] This method is implemented on macOS and Windows.
</description>
</method>
<method name="set_item_hidden">
@@ -534,8 +579,8 @@
<param index="2" name="icon" type="Texture2D" />
<description>
Replaces the [Texture2D] icon of the specified [param idx].
- [b]Note:[/b] This method is implemented only on macOS.
- [b]Note:[/b] This method is not supported by macOS "_dock" menu items.
+ [b]Note:[/b] This method is implemented on macOS and Windows.
+ [b]Note:[/b] This method is not supported by macOS Dock menu items.
</description>
</method>
<method name="set_item_indentation_level">
@@ -566,7 +611,7 @@
<param index="2" name="max_states" type="int" />
<description>
Sets number of state of a multistate item. See [method add_multistate_item] for details.
- [b]Note:[/b] This method is implemented only on macOS.
+ [b]Note:[/b] This method is implemented on macOS and Windows.
</description>
</method>
<method name="set_item_radio_checkable">
@@ -577,7 +622,7 @@
<description>
Sets the type of the item at the specified index [param idx] to radio button. If [code]false[/code], sets the type of the item to plain text.
[b]Note:[/b] This is purely cosmetic; you must add the logic for checking/unchecking items in radio groups.
- [b]Note:[/b] This method is implemented only on macOS.
+ [b]Note:[/b] This method is implemented on macOS and Windows.
</description>
</method>
<method name="set_item_state">
@@ -587,7 +632,7 @@
<param index="2" name="state" type="int" />
<description>
Sets the state of a multistate item. See [method add_multistate_item] for details.
- [b]Note:[/b] This method is implemented only on macOS.
+ [b]Note:[/b] This method is implemented on macOS and Windows.
</description>
</method>
<method name="set_item_submenu">
@@ -597,7 +642,7 @@
<param index="2" name="submenu_rid" type="RID" />
<description>
Sets the submenu RID of the item at index [param idx]. The submenu is a global menu that would be shown when the item is clicked.
- [b]Note:[/b] This method is implemented only on macOS.
+ [b]Note:[/b] This method is implemented on macOS and Windows.
</description>
</method>
<method name="set_item_tag">
@@ -607,7 +652,7 @@
<param index="2" name="tag" type="Variant" />
<description>
Sets the metadata of an item, which may be of any type. You can later get it with [method get_item_tag], which provides a simple way of assigning context data to items.
- [b]Note:[/b] This method is implemented only on macOS.
+ [b]Note:[/b] This method is implemented on macOS and Windows.
</description>
</method>
<method name="set_item_text">
@@ -617,7 +662,7 @@
<param index="2" name="text" type="String" />
<description>
Sets the text of the item at index [param idx].
- [b]Note:[/b] This method is implemented only on macOS.
+ [b]Note:[/b] This method is implemented on macOS and Windows.
</description>
</method>
<method name="set_item_tooltip">
@@ -645,6 +690,7 @@
<param index="1" name="callback" type="Callable" />
<description>
Registers callable to emit when the menu is about to show.
+ [b]Note:[/b] This method is implemented only on macOS.
</description>
</method>
<method name="set_popup_open_callback">
@@ -653,6 +699,7 @@
<param index="1" name="callback" type="Callable" />
<description>
Registers callable to emit when the menu is about to closed.
+ [b]Note:[/b] This method is implemented only on macOS.
</description>
</method>
</methods>
@@ -663,6 +710,15 @@
<constant name="FEATURE_POPUP_MENU" value="1" enum="Feature">
[NativeMenu] supports native popup menus.
</constant>
+ <constant name="FEATURE_OPEN_CLOSE_CALLBACK" value="2" enum="Feature">
+ [NativeMenu] supports menu open and close callbacks.
+ </constant>
+ <constant name="FEATURE_HOVER_CALLBACK" value="3" enum="Feature">
+ [NativeMenu] supports menu item hover callback.
+ </constant>
+ <constant name="FEATURE_KEY_CALLBACK" value="4" enum="Feature">
+ [NativeMenu] supports menu item accelerator/key callback.
+ </constant>
<constant name="INVALID_MENU_ID" value="0" enum="SystemMenus">
Invalid special system menu ID.
</constant>
diff --git a/doc/classes/PopupMenu.xml b/doc/classes/PopupMenu.xml
index 1e0b4d12e0..7831ebd1b9 100644
--- a/doc/classes/PopupMenu.xml
+++ b/doc/classes/PopupMenu.xml
@@ -634,6 +634,9 @@
<member name="item_count" type="int" setter="set_item_count" getter="get_item_count" default="0">
The number of items currently in the list.
</member>
+ <member name="prefer_native_menu" type="bool" setter="set_prefer_native_menu" getter="is_prefer_native_menu" default="false">
+ If [code]true[/code], [MenuBar] will use native menu when supported.
+ </member>
<member name="submenu_popup_delay" type="float" setter="set_submenu_popup_delay" getter="get_submenu_popup_delay" default="0.3">
Sets the delay time in seconds for the submenu item to popup on mouse hovering. If the popup menu is added as a child of another (acting as a submenu), it will inherit the delay time of the parent menu item.
</member>
diff --git a/doc/classes/RayCast2D.xml b/doc/classes/RayCast2D.xml
index a101fd24de..31daaab417 100644
--- a/doc/classes/RayCast2D.xml
+++ b/doc/classes/RayCast2D.xml
@@ -69,13 +69,14 @@
<return type="Vector2" />
<description>
Returns the normal of the intersecting object's shape at the collision point, or [code]Vector2(0, 0)[/code] if the ray starts inside the shape and [member hit_from_inside] is [code]true[/code].
+ [b]Note:[/b] Check that [method is_colliding] returns [code]true[/code] before calling this method to ensure the returned normal is valid and up-to-date.
</description>
</method>
<method name="get_collision_point" qualifiers="const">
<return type="Vector2" />
<description>
- Returns the collision point at which the ray intersects the closest object. If [member hit_from_inside] is [code]true[/code] and the ray starts inside of a collision shape, this function will return the origin point of the ray.
- [b]Note:[/b] This point is in the [b]global[/b] coordinate system.
+ Returns the collision point at which the ray intersects the closest object, in the global coordinate system. If [member hit_from_inside] is [code]true[/code] and the ray starts inside of a collision shape, this function will return the origin point of the ray.
+ [b]Note:[/b] Check that [method is_colliding] returns [code]true[/code] before calling this method to ensure the returned point is valid and up-to-date.
</description>
</method>
<method name="is_colliding" qualifiers="const">
diff --git a/doc/classes/RayCast3D.xml b/doc/classes/RayCast3D.xml
index 641c5ec653..f9f94e5cfc 100644
--- a/doc/classes/RayCast3D.xml
+++ b/doc/classes/RayCast3D.xml
@@ -76,13 +76,14 @@
<return type="Vector3" />
<description>
Returns the normal of the intersecting object's shape at the collision point, or [code]Vector3(0, 0, 0)[/code] if the ray starts inside the shape and [member hit_from_inside] is [code]true[/code].
+ [b]Note:[/b] Check that [method is_colliding] returns [code]true[/code] before calling this method to ensure the returned normal is valid and up-to-date.
</description>
</method>
<method name="get_collision_point" qualifiers="const">
<return type="Vector3" />
<description>
- Returns the collision point at which the ray intersects the closest object. If [member hit_from_inside] is [code]true[/code] and the ray starts inside of a collision shape, this function will return the origin point of the ray.
- [b]Note:[/b] This point is in the [b]global[/b] coordinate system.
+ Returns the collision point at which the ray intersects the closest object, in the global coordinate system. If [member hit_from_inside] is [code]true[/code] and the ray starts inside of a collision shape, this function will return the origin point of the ray.
+ [b]Note:[/b] Check that [method is_colliding] returns [code]true[/code] before calling this method to ensure the returned point is valid and up-to-date.
</description>
</method>
<method name="is_colliding" qualifiers="const">
diff --git a/doc/classes/ScriptExtension.xml b/doc/classes/ScriptExtension.xml
index 6c7888510e..d102676035 100644
--- a/doc/classes/ScriptExtension.xml
+++ b/doc/classes/ScriptExtension.xml
@@ -84,6 +84,7 @@
<return type="Variant" />
<param index="0" name="method" type="StringName" />
<description>
+ Return the expected argument count for the given [param method], or [code]null[/code] if it can't be determined (which will then fall back to the default behavior).
</description>
</method>
<method name="_get_script_method_list" qualifiers="virtual const">
diff --git a/doc/classes/Time.xml b/doc/classes/Time.xml
index 79c332327f..2948d20fbb 100644
--- a/doc/classes/Time.xml
+++ b/doc/classes/Time.xml
@@ -7,7 +7,7 @@
The Time singleton allows converting time between various formats and also getting time information from the system.
This class conforms with as many of the ISO 8601 standards as possible. All dates follow the Proleptic Gregorian calendar. As such, the day before [code]1582-10-15[/code] is [code]1582-10-14[/code], not [code]1582-10-04[/code]. The year before 1 AD (aka 1 BC) is number [code]0[/code], with the year before that (2 BC) being [code]-1[/code], etc.
Conversion methods assume "the same timezone", and do not handle timezone conversions or DST automatically. Leap seconds are also not handled, they must be done manually if desired. Suffixes such as "Z" are not handled, you need to strip them away manually.
- When getting time information from the system, the time can either be in the local timezone or UTC depending on the [code]utc[/code] parameter. However, the [method get_unix_time_from_system] method always returns the time in UTC.
+ When getting time information from the system, the time can either be in the local timezone or UTC depending on the [code]utc[/code] parameter. However, the [method get_unix_time_from_system] method always uses UTC as it returns the seconds passed since the [url=https://en.wikipedia.org/wiki/Unix_time]Unix epoch[/url].
[b]Important:[/b] The [code]_from_system[/code] methods use the system clock that the user can manually set. [b]Never use[/b] this method for precise time calculation since its results are subject to automatic adjustments by the user or the operating system. [b]Always use[/b] [method get_ticks_usec] or [method get_ticks_msec] for precise time calculation instead, since they are guaranteed to be monotonic (i.e. never decrease).
</description>
<tutorials>
@@ -180,7 +180,7 @@
<method name="get_unix_time_from_system" qualifiers="const">
<return type="float" />
<description>
- Returns the current Unix timestamp in seconds based on the system time in UTC. This method is implemented by the operating system and always returns the time in UTC.
+ Returns the current Unix timestamp in seconds based on the system time in UTC. This method is implemented by the operating system and always returns the time in UTC. The Unix timestamp is the number of seconds passed since 1970-01-01 at 00:00:00, the [url=https://en.wikipedia.org/wiki/Unix_time]Unix epoch[/url].
[b]Note:[/b] Unlike other methods that use integer timestamps, this method returns the timestamp as a [float] for sub-second precision.
</description>
</method>
diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h
index ce0876972a..71cd152520 100644
--- a/drivers/gles3/rasterizer_scene_gles3.h
+++ b/drivers/gles3/rasterizer_scene_gles3.h
@@ -144,7 +144,7 @@ private:
RS::ViewportDebugDraw debug_draw = RS::VIEWPORT_DEBUG_DRAW_DISABLED;
uint64_t scene_pass = 0;
- template <class T>
+ template <typename T>
struct InstanceSort {
float depth;
T *instance = nullptr;
diff --git a/editor/debugger/debug_adapter/debug_adapter_parser.cpp b/editor/debugger/debug_adapter/debug_adapter_parser.cpp
index 5009de4ac4..b75e5c1c0d 100644
--- a/editor/debugger/debug_adapter/debug_adapter_parser.cpp
+++ b/editor/debugger/debug_adapter/debug_adapter_parser.cpp
@@ -601,12 +601,12 @@ Dictionary DebugAdapterParser::ev_continued() const {
return event;
}
-Dictionary DebugAdapterParser::ev_output(const String &p_message) const {
+Dictionary DebugAdapterParser::ev_output(const String &p_message, RemoteDebugger::MessageType p_type) const {
Dictionary event = prepare_base_event(), body;
event["event"] = "output";
event["body"] = body;
- body["category"] = "stdout";
+ body["category"] = (p_type == RemoteDebugger::MessageType::MESSAGE_TYPE_ERROR) ? "stderr" : "stdout";
body["output"] = p_message + "\r\n";
return event;
diff --git a/editor/debugger/debug_adapter/debug_adapter_parser.h b/editor/debugger/debug_adapter/debug_adapter_parser.h
index e5493a4b9f..9860e96498 100644
--- a/editor/debugger/debug_adapter/debug_adapter_parser.h
+++ b/editor/debugger/debug_adapter/debug_adapter_parser.h
@@ -32,6 +32,7 @@
#define DEBUG_ADAPTER_PARSER_H
#include "core/config/project_settings.h"
+#include "core/debugger/remote_debugger.h"
#include "debug_adapter_protocol.h"
#include "debug_adapter_types.h"
@@ -98,7 +99,7 @@ public:
Dictionary ev_stopped_breakpoint(const int &p_id) const;
Dictionary ev_stopped_step() const;
Dictionary ev_continued() const;
- Dictionary ev_output(const String &p_message) const;
+ Dictionary ev_output(const String &p_message, RemoteDebugger::MessageType p_type) const;
Dictionary ev_custom_data(const String &p_msg, const Array &p_data) const;
Dictionary ev_breakpoint(const DAP::Breakpoint &p_breakpoint, const bool &p_enabled) const;
};
diff --git a/editor/debugger/debug_adapter/debug_adapter_protocol.cpp b/editor/debugger/debug_adapter/debug_adapter_protocol.cpp
index 7417a3d8f7..d03df88b75 100644
--- a/editor/debugger/debug_adapter/debug_adapter_protocol.cpp
+++ b/editor/debugger/debug_adapter/debug_adapter_protocol.cpp
@@ -763,8 +763,8 @@ void DebugAdapterProtocol::notify_continued() {
reset_stack_info();
}
-void DebugAdapterProtocol::notify_output(const String &p_message) {
- Dictionary event = parser->ev_output(p_message);
+void DebugAdapterProtocol::notify_output(const String &p_message, RemoteDebugger::MessageType p_type) {
+ Dictionary event = parser->ev_output(p_message, p_type);
for (List<Ref<DAPeer>>::Element *E = clients.front(); E; E = E->next()) {
E->get()->res_queue.push_back(event);
}
@@ -828,8 +828,8 @@ void DebugAdapterProtocol::on_debug_stopped() {
notify_terminated();
}
-void DebugAdapterProtocol::on_debug_output(const String &p_message) {
- notify_output(p_message);
+void DebugAdapterProtocol::on_debug_output(const String &p_message, int p_type) {
+ notify_output(p_message, RemoteDebugger::MessageType(p_type));
}
void DebugAdapterProtocol::on_debug_breaked(const bool &p_reallydid, const bool &p_can_debug, const String &p_reason, const bool &p_has_stackdump) {
diff --git a/editor/debugger/debug_adapter/debug_adapter_protocol.h b/editor/debugger/debug_adapter/debug_adapter_protocol.h
index fb1c533bbb..caff0f9c7f 100644
--- a/editor/debugger/debug_adapter/debug_adapter_protocol.h
+++ b/editor/debugger/debug_adapter/debug_adapter_protocol.h
@@ -86,7 +86,7 @@ private:
void on_client_disconnected(const Ref<DAPeer> &p_peer);
void on_debug_paused();
void on_debug_stopped();
- void on_debug_output(const String &p_message);
+ void on_debug_output(const String &p_message, int p_type);
void on_debug_breaked(const bool &p_reallydid, const bool &p_can_debug, const String &p_reason, const bool &p_has_stackdump);
void on_debug_breakpoint_toggled(const String &p_path, const int &p_line, const bool &p_enabled);
void on_debug_stack_dump(const Array &p_stack_dump);
@@ -139,7 +139,7 @@ public:
void notify_stopped_breakpoint(const int &p_id);
void notify_stopped_step();
void notify_continued();
- void notify_output(const String &p_message);
+ void notify_output(const String &p_message, RemoteDebugger::MessageType p_type);
void notify_custom_data(const String &p_msg, const Array &p_data);
void notify_breakpoint(const DAP::Breakpoint &p_breakpoint, const bool &p_enabled);
diff --git a/editor/debugger/script_editor_debugger.cpp b/editor/debugger/script_editor_debugger.cpp
index 979834ebab..2b880274f8 100644
--- a/editor/debugger/script_editor_debugger.cpp
+++ b/editor/debugger/script_editor_debugger.cpp
@@ -495,7 +495,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, uint64_t p_thread
} break;
}
EditorNode::get_log()->add_message(output_strings[i], msg_type);
- emit_signal(SNAME("output"), output_strings[i]);
+ emit_signal(SNAME("output"), output_strings[i], msg_type);
}
} else if (p_msg == "performance:profile_frame") {
Vector<float> frame_data;
@@ -1757,7 +1757,7 @@ void ScriptEditorDebugger::_bind_methods() {
ADD_SIGNAL(MethodInfo("remote_object_updated", PropertyInfo(Variant::INT, "id")));
ADD_SIGNAL(MethodInfo("remote_object_property_updated", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::STRING, "property")));
ADD_SIGNAL(MethodInfo("remote_tree_updated"));
- ADD_SIGNAL(MethodInfo("output"));
+ ADD_SIGNAL(MethodInfo("output", PropertyInfo(Variant::STRING, "msg"), PropertyInfo(Variant::INT, "level")));
ADD_SIGNAL(MethodInfo("stack_dump", PropertyInfo(Variant::ARRAY, "stack_dump")));
ADD_SIGNAL(MethodInfo("stack_frame_vars", PropertyInfo(Variant::INT, "num_vars")));
ADD_SIGNAL(MethodInfo("stack_frame_var", PropertyInfo(Variant::ARRAY, "data")));
diff --git a/editor/editor_data.h b/editor/editor_data.h
index d71a2b3ed3..42b2d2ed0c 100644
--- a/editor/editor_data.h
+++ b/editor/editor_data.h
@@ -300,7 +300,7 @@ public:
void remove_node(Node *p_node);
bool is_selected(Node *p_node) const;
- template <class T>
+ template <typename T>
T *get_node_editor_data(Node *p_node) {
if (!selection.has(p_node)) {
return nullptr;
diff --git a/editor/editor_help_search.h b/editor/editor_help_search.h
index 003b98adf0..39ffc2f71b 100644
--- a/editor/editor_help_search.h
+++ b/editor/editor_help_search.h
@@ -117,7 +117,7 @@ class EditorHelpSearch::Runner : public RefCounted {
};
int phase = 0;
- template <class T>
+ template <typename T>
struct MemberMatch {
T *doc = nullptr;
bool name = false;
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 89e5e3f3b0..3abf0582bc 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -517,9 +517,8 @@ void EditorNode::_update_theme(bool p_skip_creation) {
scene_root_parent->add_theme_style_override("panel", theme->get_stylebox(SNAME("Content"), EditorStringName(EditorStyles)));
bottom_panel->add_theme_style_override("panel", theme->get_stylebox(SNAME("BottomPanel"), EditorStringName(EditorStyles)));
- main_menu->add_theme_style_override("pressed", theme->get_stylebox(SNAME("MenuTransparent"), EditorStringName(EditorStyles)));
distraction_free->set_icon(theme->get_icon(SNAME("DistractionFree"), EditorStringName(EditorIcons)));
- distraction_free->add_theme_style_override("pressed", theme->get_stylebox(SNAME("MenuTransparent"), EditorStringName(EditorStyles)));
+ distraction_free->add_theme_style_override("pressed", theme->get_stylebox("normal", "FlatMenuButton"));
help_menu->set_item_icon(help_menu->get_item_index(HELP_SEARCH), theme->get_icon(SNAME("HelpSearch"), EditorStringName(EditorIcons)));
help_menu->set_item_icon(help_menu->get_item_index(HELP_COPY_SYSTEM_INFO), theme->get_icon(SNAME("ActionCopy"), EditorStringName(EditorIcons)));
@@ -6638,7 +6637,7 @@ EditorNode::EditorNode() {
main_menu = memnew(MenuBar);
title_bar->add_child(main_menu);
- main_menu->set_theme_type_variation("FlatMenuButton");
+ main_menu->set_theme_type_variation("MainMenuBar");
main_menu->set_start_index(0); // Main menu, add to the start of global menu.
main_menu->set_prefer_global_menu(global_menu);
main_menu->set_switch_on_hover(true);
diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h
index 7c28818b2f..f45a512b89 100644
--- a/editor/editor_plugin.h
+++ b/editor/editor_plugin.h
@@ -264,7 +264,7 @@ class EditorPlugins {
static EditorPluginCreateFunc creation_funcs[MAX_CREATE_FUNCS];
static int creation_func_count;
- template <class T>
+ template <typename T>
static EditorPlugin *creator() {
return memnew(T);
}
@@ -276,7 +276,7 @@ public:
return creation_funcs[p_idx]();
}
- template <class T>
+ template <typename T>
static void add_by_type() {
add_create_func(creator<T>);
}
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp
index fc170d606a..0f83e109fa 100644
--- a/editor/filesystem_dock.cpp
+++ b/editor/filesystem_dock.cpp
@@ -173,14 +173,48 @@ FileSystemList::FileSystemList() {
FileSystemDock *FileSystemDock::singleton = nullptr;
-Ref<Texture2D> FileSystemDock::_get_tree_item_icon(bool p_is_valid, const String &p_file_type) {
- Ref<Texture2D> file_icon;
+Ref<Texture2D> FileSystemDock::_get_tree_item_icon(bool p_is_valid, const String &p_file_type, const String &p_icon_path) {
+ if (!p_icon_path.is_empty()) {
+ Ref<Texture2D> icon = ResourceLoader::load(p_icon_path);
+ if (icon.is_valid()) {
+ return icon;
+ }
+ }
+
if (!p_is_valid) {
- file_icon = get_editor_theme_icon(SNAME("ImportFail"));
+ return get_editor_theme_icon(SNAME("ImportFail"));
+ } else if (has_theme_icon(p_file_type, EditorStringName(EditorIcons))) {
+ return get_editor_theme_icon(p_file_type);
} else {
- file_icon = (has_theme_icon(p_file_type, EditorStringName(EditorIcons))) ? get_editor_theme_icon(p_file_type) : get_editor_theme_icon(SNAME("File"));
+ return get_editor_theme_icon(SNAME("File"));
}
- return file_icon;
+}
+
+String FileSystemDock::_get_entry_script_icon(const EditorFileSystemDirectory *p_dir, int p_file) {
+ const PackedStringArray &deps = p_dir->get_file_deps(p_file);
+ if (deps.is_empty()) {
+ return String();
+ }
+
+ const String &script_path = deps[0]; // Assuming the first dependency is a script.
+ if (script_path.is_empty() || !ClassDB::is_parent_class(ResourceLoader::get_resource_type(script_path), SNAME("Script"))) {
+ return String();
+ }
+
+ String *cached = icon_cache.getptr(script_path);
+ if (cached) {
+ return *cached;
+ }
+
+ HashMap<String, String>::Iterator I;
+ int script_file;
+ EditorFileSystemDirectory *efsd = EditorFileSystem::get_singleton()->find_file(script_path, &script_file);
+ if (efsd) {
+ I = icon_cache.insert(script_path, efsd->get_file_script_class_icon_path(script_file));
+ } else {
+ I = icon_cache.insert(script_path, String());
+ }
+ return I->value;
}
bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory *p_dir, Vector<String> &uncollapsed_paths, bool p_select_in_favorites, bool p_unfold_path) {
@@ -272,6 +306,7 @@ bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory
FileInfo fi;
fi.name = p_dir->get_file(i);
fi.type = p_dir->get_file_type(i);
+ fi.icon_path = _get_entry_script_icon(p_dir, i);
fi.import_broken = !p_dir->get_file_import_is_valid(i);
fi.modified_time = p_dir->get_file_modified_time(i);
@@ -282,18 +317,21 @@ bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory
_sort_file_info_list(file_list);
// Build the tree.
+ const int icon_size = get_theme_constant(SNAME("class_icon_size"), SNAME("Editor"));
+
for (const FileInfo &fi : file_list) {
TreeItem *file_item = tree->create_item(subdirectory_item);
+ const String file_metadata = lpath.path_join(fi.name);
file_item->set_text(0, fi.name);
file_item->set_structured_text_bidi_override(0, TextServer::STRUCTURED_TEXT_FILE);
- file_item->set_icon(0, _get_tree_item_icon(!fi.import_broken, fi.type));
+ file_item->set_icon(0, _get_tree_item_icon(!fi.import_broken, fi.type, fi.icon_path));
+ file_item->set_icon_max_width(0, icon_size);
Color parent_bg_color = subdirectory_item->get_custom_bg_color(0);
if (has_custom_color) {
file_item->set_custom_bg_color(0, parent_bg_color.darkened(0.3));
} else if (parent_bg_color != Color()) {
file_item->set_custom_bg_color(0, parent_bg_color);
}
- String file_metadata = lpath.path_join(fi.name);
file_item->set_metadata(0, file_metadata);
if (!p_select_in_favorites && current_path == file_metadata) {
file_item->select(0);
@@ -366,6 +404,8 @@ void FileSystemDock::_update_tree(const Vector<String> &p_uncollapsed_paths, boo
updating_tree = true;
TreeItem *root = tree->create_item();
+ icon_cache.clear();
+
// Handles the favorites.
TreeItem *favorites_item = tree->create_item(root);
favorites_item->set_icon(0, get_editor_theme_icon(SNAME("Favorites")));
@@ -413,7 +453,7 @@ void FileSystemDock::_update_tree(const Vector<String> &p_uncollapsed_paths, boo
int index;
EditorFileSystemDirectory *dir = EditorFileSystem::get_singleton()->find_file(favorite, &index);
if (dir) {
- icon = _get_tree_item_icon(dir->get_file_import_is_valid(index), dir->get_file_type(index));
+ icon = _get_tree_item_icon(dir->get_file_import_is_valid(index), dir->get_file_path(index), dir->get_file_type(index));
} else {
icon = get_editor_theme_icon(SNAME("File"));
}
diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h
index acb7ca017b..15a43dc6f2 100644
--- a/editor/filesystem_dock.h
+++ b/editor/filesystem_dock.h
@@ -139,6 +139,7 @@ private:
FILE_NEW_SCENE,
};
+ HashMap<String, String> icon_cache;
HashMap<String, Color> folder_colors;
Dictionary assigned_folder_colors;
@@ -245,7 +246,8 @@ private:
void _tree_mouse_exited();
void _reselect_items_selected_on_drag_begin(bool reset = false);
- Ref<Texture2D> _get_tree_item_icon(bool p_is_valid, const String &p_file_type);
+ Ref<Texture2D> _get_tree_item_icon(bool p_is_valid, const String &p_file_type, const String &p_icon_path);
+ String _get_entry_script_icon(const EditorFileSystemDirectory *p_dir, int p_file);
bool _create_tree(TreeItem *p_parent, EditorFileSystemDirectory *p_dir, Vector<String> &uncollapsed_paths, bool p_select_in_favorites, bool p_unfold_path = false);
void _update_tree(const Vector<String> &p_uncollapsed_paths = Vector<String>(), bool p_uncollapse_root = false, bool p_select_in_favorites = false, bool p_unfold_path = false);
void _navigate_to_path(const String &p_path, bool p_select_in_favorites = false);
@@ -323,6 +325,7 @@ private:
struct FileInfo {
String name;
String path;
+ String icon_path;
StringName type;
Vector<String> sources;
bool import_broken = false;
diff --git a/editor/gui/editor_bottom_panel.cpp b/editor/gui/editor_bottom_panel.cpp
index e567e42bdb..1c95b546f4 100644
--- a/editor/gui/editor_bottom_panel.cpp
+++ b/editor/gui/editor_bottom_panel.cpp
@@ -50,10 +50,6 @@ void EditorBottomPanel::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_THEME_CHANGED: {
expand_button->set_icon(get_editor_theme_icon(SNAME("ExpandBottomDock")));
- for (int i = 0; i < items.size(); i++) {
- items.write[i].button->add_theme_style_override("pressed", get_theme_stylebox(SNAME("MenuTransparent"), EditorStringName(EditorStyles)));
- items.write[i].button->add_theme_style_override("hover_pressed", get_theme_stylebox(SNAME("MenuHover"), EditorStringName(EditorStyles)));
- }
} break;
}
}
@@ -160,7 +156,7 @@ void EditorBottomPanel::load_layout_from_config(Ref<ConfigFile> p_config_file, c
Button *EditorBottomPanel::add_item(String p_text, Control *p_item, const Ref<Shortcut> &p_shortcut, bool p_at_front) {
Button *tb = memnew(Button);
- tb->set_theme_type_variation("FlatMenuButton");
+ tb->set_theme_type_variation("BottomPanelButton");
tb->connect("toggled", callable_mp(this, &EditorBottomPanel::_switch_by_control).bind(p_item));
tb->set_drag_forwarding(Callable(), callable_mp(this, &EditorBottomPanel::_button_drag_hover).bind(tb, p_item), Callable());
tb->set_text(p_text);
diff --git a/editor/import/3d/resource_importer_scene.h b/editor/import/3d/resource_importer_scene.h
index 2e682350bc..17fa9ef0e2 100644
--- a/editor/import/3d/resource_importer_scene.h
+++ b/editor/import/3d/resource_importer_scene.h
@@ -303,10 +303,10 @@ public:
ResourceImporterScene(bool p_animation_import = false, bool p_singleton = false);
~ResourceImporterScene();
- template <class M>
+ template <typename M>
static Vector<Ref<Shape3D>> get_collision_shapes(const Ref<ImporterMesh> &p_mesh, const M &p_options, float p_applied_root_scale);
- template <class M>
+ template <typename M>
static Transform3D get_collision_shapes_transform(const M &p_options);
};
@@ -319,7 +319,7 @@ public:
virtual Node *import_scene(const String &p_path, uint32_t p_flags, const HashMap<StringName, Variant> &p_options, List<String> *r_missing_deps, Error *r_err = nullptr) override;
};
-template <class M>
+template <typename M>
Vector<Ref<Shape3D>> ResourceImporterScene::get_collision_shapes(const Ref<ImporterMesh> &p_mesh, const M &p_options, float p_applied_root_scale) {
ERR_FAIL_COND_V(p_mesh.is_null(), Vector<Ref<Shape3D>>());
ShapeType generate_shape_type = SHAPE_TYPE_DECOMPOSE_CONVEX;
@@ -476,7 +476,7 @@ Vector<Ref<Shape3D>> ResourceImporterScene::get_collision_shapes(const Ref<Impor
return Vector<Ref<Shape3D>>();
}
-template <class M>
+template <typename M>
Transform3D ResourceImporterScene::get_collision_shapes_transform(const M &p_options) {
Transform3D transform;
diff --git a/editor/themes/editor_theme_manager.cpp b/editor/themes/editor_theme_manager.cpp
index 1f451487cb..bb4dce808c 100644
--- a/editor/themes/editor_theme_manager.cpp
+++ b/editor/themes/editor_theme_manager.cpp
@@ -1742,29 +1742,40 @@ void EditorThemeManager::_populate_editor_styles(const Ref<EditorTheme> &p_theme
p_theme->set_stylebox("ScriptEditorPanelFloating", EditorStringName(EditorStyles), make_empty_stylebox(0, 0, 0, 0));
p_theme->set_stylebox("ScriptEditor", EditorStringName(EditorStyles), make_empty_stylebox(0, 0, 0, 0));
- // Bottom panel.
- Ref<StyleBoxFlat> style_bottom_panel = p_config.content_panel_style->duplicate();
- style_bottom_panel->set_corner_radius_all(p_config.corner_radius * EDSCALE);
- p_theme->set_stylebox("BottomPanel", EditorStringName(EditorStyles), style_bottom_panel);
-
// Main menu.
Ref<StyleBoxFlat> menu_transparent_style = p_config.button_style->duplicate();
menu_transparent_style->set_bg_color(Color(1, 1, 1, 0));
menu_transparent_style->set_border_width_all(0);
- Ref<StyleBoxFlat> main_screen_button_transparent = menu_transparent_style->duplicate();
+ Ref<StyleBoxFlat> main_screen_button_hover = p_config.button_style_hover->duplicate();
for (int i = 0; i < 4; i++) {
- menu_transparent_style->set_content_margin((Side)i, p_config.button_style->get_margin((Side)i) + p_config.button_style->get_border_width((Side)i));
+ menu_transparent_style->set_content_margin((Side)i, p_config.button_style->get_content_margin((Side)i));
+ main_screen_button_hover->set_content_margin((Side)i, p_config.button_style_hover->get_content_margin((Side)i));
}
- p_theme->set_stylebox("MenuTransparent", EditorStringName(EditorStyles), menu_transparent_style);
- p_theme->set_stylebox("MenuHover", EditorStringName(EditorStyles), p_config.button_style_hover);
- p_theme->set_stylebox("normal", "MainScreenButton", main_screen_button_transparent);
- p_theme->set_stylebox("pressed", "MainScreenButton", main_screen_button_transparent);
- p_theme->set_stylebox("hover_pressed", "MainScreenButton", p_config.button_style_hover);
+ p_theme->set_stylebox("normal", "MainScreenButton", menu_transparent_style);
+ p_theme->set_stylebox("pressed", "MainScreenButton", menu_transparent_style);
+ p_theme->set_stylebox("hover", "MainScreenButton", main_screen_button_hover);
+ p_theme->set_stylebox("hover_pressed", "MainScreenButton", main_screen_button_hover);
+
+ p_theme->set_type_variation("MainMenuBar", "FlatMenuButton");
+ p_theme->set_stylebox("normal", "MainMenuBar", menu_transparent_style);
+ p_theme->set_stylebox("pressed", "MainMenuBar", main_screen_button_hover);
+ p_theme->set_stylebox("hover", "MainMenuBar", main_screen_button_hover);
+ p_theme->set_stylebox("hover_pressed", "MainMenuBar", main_screen_button_hover);
// Run bar.
p_theme->set_type_variation("RunBarButton", "FlatMenuButton");
p_theme->set_stylebox("disabled", "RunBarButton", menu_transparent_style);
p_theme->set_stylebox("pressed", "RunBarButton", menu_transparent_style);
+
+ // Bottom panel.
+ Ref<StyleBoxFlat> style_bottom_panel = p_config.content_panel_style->duplicate();
+ style_bottom_panel->set_corner_radius_all(p_config.corner_radius * EDSCALE);
+ p_theme->set_stylebox("BottomPanel", EditorStringName(EditorStyles), style_bottom_panel);
+ p_theme->set_type_variation("BottomPanelButton", "FlatMenuButton");
+ p_theme->set_stylebox("normal", "BottomPanelButton", menu_transparent_style);
+ p_theme->set_stylebox("pressed", "BottomPanelButton", menu_transparent_style);
+ p_theme->set_stylebox("hover_pressed", "BottomPanelButton", main_screen_button_hover);
+ p_theme->set_stylebox("hover", "BottomPanelButton", main_screen_button_hover);
}
// Editor GUI widgets.
@@ -1821,9 +1832,9 @@ void EditorThemeManager::_populate_editor_styles(const Ref<EditorTheme> &p_theme
Ref<StyleBoxFlat> style_flat_button_pressed = p_config.button_style_pressed->duplicate();
for (int i = 0; i < 4; i++) {
- style_flat_button->set_content_margin((Side)i, p_config.button_style->get_margin((Side)i) + p_config.button_style->get_border_width((Side)i));
- style_flat_button_hover->set_content_margin((Side)i, p_config.button_style->get_margin((Side)i) + p_config.button_style->get_border_width((Side)i));
- style_flat_button_pressed->set_content_margin((Side)i, p_config.button_style->get_margin((Side)i) + p_config.button_style->get_border_width((Side)i));
+ style_flat_button->set_content_margin((Side)i, p_config.button_style->get_content_margin((Side)i));
+ style_flat_button_hover->set_content_margin((Side)i, p_config.button_style->get_content_margin((Side)i));
+ style_flat_button_pressed->set_content_margin((Side)i, p_config.button_style->get_content_margin((Side)i));
}
Color flat_pressed_color = p_config.dark_color_1.lightened(0.24).lerp(p_config.accent_color, 0.2) * Color(0.8, 0.8, 0.8, 0.85);
if (p_config.dark_theme) {
diff --git a/main/main.h b/main/main.h
index 062af73d57..755c7d841a 100644
--- a/main/main.h
+++ b/main/main.h
@@ -35,7 +35,7 @@
#include "core/os/thread.h"
#include "core/typedefs.h"
-template <class T>
+template <typename T>
class Vector;
class Main {
diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml
index d98580b771..4869573972 100644
--- a/modules/gdscript/doc_classes/@GDScript.xml
+++ b/modules/gdscript/doc_classes/@GDScript.xml
@@ -43,6 +43,7 @@
assert(speed &gt;= 0 and speed &lt; 20) # You can also combine the two conditional statements in one check.
assert(speed &lt; 20, "the speed limit is 20") # Show a message.
[/codeblock]
+ [b]Note:[/b] [method assert] is a keyword, not a function. So you cannot access it as a [Callable] or use it inside expressions.
</description>
</method>
<method name="char">
@@ -131,7 +132,7 @@
- A constant from the [enum Variant.Type] enumeration, for example [constant TYPE_INT].
- An [Object]-derived class which exists in [ClassDB], for example [Node].
- A [Script] (you can use any class, including inner one).
- Unlike the right operand of the [code]is[/code] operator, [param type] can be a non-constant value. The [code]is[/code] operator supports more features (such as typed arrays) and is more performant. Use the operator instead of this method if you do not need dynamic type checking.
+ Unlike the right operand of the [code]is[/code] operator, [param type] can be a non-constant value. The [code]is[/code] operator supports more features (such as typed arrays). Use the operator instead of this method if you do not need dynamic type checking.
Examples:
[codeblock]
print(is_instance_of(a, TYPE_INT))
@@ -183,6 +184,7 @@
# Create instance of a scene.
var diamond = preload("res://diamond.tscn").instantiate()
[/codeblock]
+ [b]Note:[/b] [method preload] is a keyword, not a function. So you cannot access it as a [Callable].
</description>
</method>
<method name="print_debug" qualifiers="vararg">
@@ -717,6 +719,8 @@
<return type="void" />
<description>
Make a script with static variables to not persist after all references are lost. If the script is loaded again the static variables will revert to their default values.
+ [b]Note:[/b] As annotations describe their subject, the [annotation @static_unload] annotation must be placed before the class definition and inheritance.
+ [b]Warning:[/b] Currently, due to a bug, scripts are never freed, even if [annotation @static_unload] annotation is used.
</description>
</annotation>
<annotation name="@tool">
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index 8d98c0b11c..d706f4e9a3 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -856,7 +856,7 @@ void GDScriptParser::parse_extends() {
}
}
-template <class T>
+template <typename T>
void GDScriptParser::parse_class_member(T *(GDScriptParser::*p_parse_function)(bool), AnnotationInfo::TargetKind p_target, const String &p_member_kind, bool p_is_static) {
advance();
diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h
index 583b60bf16..ea67f1eaff 100644
--- a/modules/gdscript/gdscript_parser.h
+++ b/modules/gdscript/gdscript_parser.h
@@ -774,7 +774,7 @@ public:
bool has_function(const StringName &p_name) const {
return has_member(p_name) && members[members_indices[p_name]].type == Member::FUNCTION;
}
- template <class T>
+ template <typename T>
void add_member(T *p_member_node) {
members_indices[p_member_node->identifier->name] = members.size();
members.push_back(Member(p_member_node));
@@ -1167,7 +1167,7 @@ public:
bool has_local(const StringName &p_name) const;
const Local &get_local(const StringName &p_name) const;
- template <class T>
+ template <typename T>
void add_local(T *p_local, FunctionNode *p_source_function) {
locals_indices[p_local->identifier->name] = locals.size();
locals.push_back(Local(p_local, p_source_function));
@@ -1426,7 +1426,7 @@ private:
void reset_extents(Node *p_node, GDScriptTokenizer::Token p_token);
void reset_extents(Node *p_node, Node *p_from);
- template <class T>
+ template <typename T>
T *alloc_node() {
T *node = memnew(T);
@@ -1473,7 +1473,7 @@ private:
void parse_class_name();
void parse_extends();
void parse_class_body(bool p_is_multiline);
- template <class T>
+ template <typename T>
void parse_class_member(T *(GDScriptParser::*p_parse_function)(bool), AnnotationInfo::TargetKind p_target, const String &p_member_kind, bool p_is_static = false);
SignalNode *parse_signal(bool p_is_static);
EnumNode *parse_enum(bool p_is_static);
diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp
index b53be7f855..6e7ca370dd 100644
--- a/modules/gltf/gltf_document.cpp
+++ b/modules/gltf/gltf_document.cpp
@@ -884,42 +884,40 @@ Error GLTFDocument::_encode_accessors(Ref<GLTFState> p_state) {
d["componentType"] = accessor->component_type;
d["count"] = accessor->count;
d["type"] = _get_accessor_type_name(accessor->type);
- d["byteOffset"] = accessor->byte_offset;
d["normalized"] = accessor->normalized;
d["max"] = accessor->max;
d["min"] = accessor->min;
- d["bufferView"] = accessor->buffer_view; //optional because it may be sparse...
-
- // Dictionary s;
- // s["count"] = accessor->sparse_count;
- // ERR_FAIL_COND_V(!s.has("count"), ERR_PARSE_ERROR);
-
- // s["indices"] = accessor->sparse_accessors;
- // ERR_FAIL_COND_V(!s.has("indices"), ERR_PARSE_ERROR);
-
- // Dictionary si;
+ if (accessor->buffer_view != -1) {
+ // bufferView may be omitted to zero-initialize the buffer. When this happens, byteOffset MUST also be omitted.
+ d["byteOffset"] = accessor->byte_offset;
+ d["bufferView"] = accessor->buffer_view;
+ }
- // si["bufferView"] = accessor->sparse_indices_buffer_view;
+ if (accessor->sparse_count > 0) {
+ Dictionary s;
+ s["count"] = accessor->sparse_count;
- // ERR_FAIL_COND_V(!si.has("bufferView"), ERR_PARSE_ERROR);
- // si["componentType"] = accessor->sparse_indices_component_type;
+ Dictionary si;
+ si["bufferView"] = accessor->sparse_indices_buffer_view;
+ si["componentType"] = accessor->sparse_indices_component_type;
+ if (accessor->sparse_indices_byte_offset != -1) {
+ si["byteOffset"] = accessor->sparse_indices_byte_offset;
+ }
+ ERR_FAIL_COND_V(!si.has("bufferView") || !si.has("componentType"), ERR_PARSE_ERROR);
+ s["indices"] = si;
- // if (si.has("byteOffset")) {
- // si["byteOffset"] = accessor->sparse_indices_byte_offset;
- // }
+ Dictionary sv;
+ sv["bufferView"] = accessor->sparse_values_buffer_view;
+ if (accessor->sparse_values_byte_offset != -1) {
+ sv["byteOffset"] = accessor->sparse_values_byte_offset;
+ }
+ ERR_FAIL_COND_V(!sv.has("bufferView"), ERR_PARSE_ERROR);
+ s["values"] = sv;
- // ERR_FAIL_COND_V(!si.has("componentType"), ERR_PARSE_ERROR);
- // s["indices"] = si;
- // Dictionary sv;
+ ERR_FAIL_COND_V(!s.has("count") || !s.has("indices") || !s.has("values"), ERR_PARSE_ERROR);
+ d["sparse"] = s;
+ }
- // sv["bufferView"] = accessor->sparse_values_buffer_view;
- // if (sv.has("byteOffset")) {
- // sv["byteOffset"] = accessor->sparse_values_byte_offset;
- // }
- // ERR_FAIL_COND_V(!sv.has("bufferView"), ERR_PARSE_ERROR);
- // s["values"] = sv;
- // ERR_FAIL_COND_V(!s.has("values"), ERR_PARSE_ERROR);
- // d["sparse"] = s;
accessors.push_back(d);
}
@@ -1026,8 +1024,6 @@ Error GLTFDocument::_parse_accessors(Ref<GLTFState> p_state) {
}
if (d.has("sparse")) {
- //eeh..
-
const Dictionary &s = d["sparse"];
ERR_FAIL_COND_V(!s.has("count"), ERR_PARSE_ERROR);
@@ -1143,7 +1139,7 @@ Error GLTFDocument::_encode_buffer_view(Ref<GLTFState> p_state, const double *p_
const uint32_t offset = bv->byte_offset = p_byte_offset;
Vector<uint8_t> &gltf_buffer = p_state->buffers.write[0];
- int stride = _get_component_type_size(p_component_type);
+ int stride = component_count * component_size;
if (p_for_vertex && stride % 4) {
stride += 4 - (stride % 4); //according to spec must be multiple of 4
}
@@ -1152,13 +1148,14 @@ Error GLTFDocument::_encode_buffer_view(Ref<GLTFState> p_state, const double *p_
print_verbose("glTF: encoding accessor offset " + itos(p_byte_offset) + " view offset: " + itos(bv->byte_offset) + " total buffer len: " + itos(gltf_buffer.size()) + " view len " + itos(bv->byte_length));
- const int buffer_end = (stride * (p_count - 1)) + _get_component_type_size(p_component_type);
+ const int buffer_end = (stride * (p_count - 1)) + component_size;
// TODO define bv->byte_stride
bv->byte_offset = gltf_buffer.size();
if (p_for_vertex_indices) {
bv->indices = true;
} else if (p_for_vertex) {
bv->vertex_attributes = true;
+ bv->byte_stride = stride;
}
switch (p_component_type) {
@@ -1300,6 +1297,11 @@ Error GLTFDocument::_encode_buffer_view(Ref<GLTFState> p_state, const double *p_
ERR_FAIL_COND_V(buffer_end > bv->byte_length, ERR_INVALID_DATA);
ERR_FAIL_COND_V((int)(offset + buffer_end) > gltf_buffer.size(), ERR_INVALID_DATA);
+ int pad_bytes = (4 - gltf_buffer.size()) & 3;
+ for (int i = 0; i < pad_bytes; i++) {
+ gltf_buffer.push_back(0);
+ }
+
r_accessor = bv->buffer = p_state->buffer_views.size();
p_state->buffer_views.push_back(bv);
return OK;
@@ -1519,8 +1521,12 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_ints(Ref<GLTFState> p_state,
type_max.resize(element_count);
Vector<double> type_min;
type_min.resize(element_count);
+ int max_index = 0;
for (int i = 0; i < p_attribs.size(); i++) {
attribs.write[i] = p_attribs[i];
+ if (p_attribs[i] > max_index) {
+ max_index = p_attribs[i];
+ }
if (i == 0) {
for (int32_t type_i = 0; type_i < element_count; type_i++) {
type_max.write[type_i] = attribs[(i * element_count) + type_i];
@@ -1539,7 +1545,12 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_ints(Ref<GLTFState> p_state,
GLTFBufferIndex buffer_view_i;
int64_t size = p_state->buffers[0].size();
const GLTFType type = GLTFType::TYPE_SCALAR;
- const int component_type = GLTFDocument::COMPONENT_TYPE_INT;
+ int component_type;
+ if (max_index > 65535 || p_for_vertex) {
+ component_type = GLTFDocument::COMPONENT_TYPE_INT;
+ } else {
+ component_type = GLTFDocument::COMPONENT_TYPE_UNSIGNED_SHORT;
+ }
accessor->max = type_max;
accessor->min = type_min;
@@ -1557,7 +1568,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_ints(Ref<GLTFState> p_state,
return p_state->accessors.size() - 1;
}
-Vector<int> GLTFDocument::_decode_accessor_as_ints(Ref<GLTFState> p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
+Vector<int> GLTFDocument::_decode_accessor_as_ints(Ref<GLTFState> p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex, const Vector<int> &p_packed_vertex_ids) {
const Vector<double> attribs = _decode_accessor(p_state, p_accessor, p_for_vertex);
Vector<int> ret;
@@ -1566,17 +1577,23 @@ Vector<int> GLTFDocument::_decode_accessor_as_ints(Ref<GLTFState> p_state, const
}
const double *attribs_ptr = attribs.ptr();
- const int ret_size = attribs.size();
+ int ret_size = attribs.size();
+ if (!p_packed_vertex_ids.is_empty()) {
+ ERR_FAIL_COND_V(p_packed_vertex_ids[p_packed_vertex_ids.size() - 1] >= ret_size, ret);
+ ret_size = p_packed_vertex_ids.size();
+ }
ret.resize(ret_size);
- {
- for (int i = 0; i < ret_size; i++) {
- ret.write[i] = int(attribs_ptr[i]);
+ for (int i = 0; i < ret_size; i++) {
+ int src_i = i;
+ if (!p_packed_vertex_ids.is_empty()) {
+ src_i = p_packed_vertex_ids[i];
}
+ ret.write[i] = int(attribs_ptr[src_i]);
}
return ret;
}
-Vector<float> GLTFDocument::_decode_accessor_as_floats(Ref<GLTFState> p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
+Vector<float> GLTFDocument::_decode_accessor_as_floats(Ref<GLTFState> p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex, const Vector<int> &p_packed_vertex_ids) {
const Vector<double> attribs = _decode_accessor(p_state, p_accessor, p_for_vertex);
Vector<float> ret;
@@ -1585,12 +1602,18 @@ Vector<float> GLTFDocument::_decode_accessor_as_floats(Ref<GLTFState> p_state, c
}
const double *attribs_ptr = attribs.ptr();
- const int ret_size = attribs.size();
+ int ret_size = attribs.size();
+ if (!p_packed_vertex_ids.is_empty()) {
+ ERR_FAIL_COND_V(p_packed_vertex_ids[p_packed_vertex_ids.size() - 1] >= ret_size, ret);
+ ret_size = p_packed_vertex_ids.size();
+ }
ret.resize(ret_size);
- {
- for (int i = 0; i < ret_size; i++) {
- ret.write[i] = float(attribs_ptr[i]);
+ for (int i = 0; i < ret_size; i++) {
+ int src_i = i;
+ if (!p_packed_vertex_ids.is_empty()) {
+ src_i = p_packed_vertex_ids[i];
}
+ ret.write[i] = float(attribs_ptr[src_i]);
}
return ret;
}
@@ -1863,7 +1886,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_quaternions(Ref<GLTFState> p
return p_state->accessors.size() - 1;
}
-Vector<Vector2> GLTFDocument::_decode_accessor_as_vec2(Ref<GLTFState> p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
+Vector<Vector2> GLTFDocument::_decode_accessor_as_vec2(Ref<GLTFState> p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex, const Vector<int> &p_packed_vertex_ids) {
const Vector<double> attribs = _decode_accessor(p_state, p_accessor, p_for_vertex);
Vector<Vector2> ret;
@@ -1873,12 +1896,18 @@ Vector<Vector2> GLTFDocument::_decode_accessor_as_vec2(Ref<GLTFState> p_state, c
ERR_FAIL_COND_V(attribs.size() % 2 != 0, ret);
const double *attribs_ptr = attribs.ptr();
- const int ret_size = attribs.size() / 2;
+ int ret_size = attribs.size() / 2;
+ if (!p_packed_vertex_ids.is_empty()) {
+ ERR_FAIL_COND_V(p_packed_vertex_ids[p_packed_vertex_ids.size() - 1] >= ret_size, ret);
+ ret_size = p_packed_vertex_ids.size();
+ }
ret.resize(ret_size);
- {
- for (int i = 0; i < ret_size; i++) {
- ret.write[i] = Vector2(attribs_ptr[i * 2 + 0], attribs_ptr[i * 2 + 1]);
+ for (int i = 0; i < ret_size; i++) {
+ int src_i = i;
+ if (!p_packed_vertex_ids.is_empty()) {
+ src_i = p_packed_vertex_ids[i];
}
+ ret.write[i] = Vector2(attribs_ptr[src_i * 2 + 0], attribs_ptr[src_i * 2 + 1]);
}
return ret;
}
@@ -1976,6 +2005,112 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_vec3(Ref<GLTFState> p_state,
return p_state->accessors.size() - 1;
}
+GLTFAccessorIndex GLTFDocument::_encode_sparse_accessor_as_vec3(Ref<GLTFState> p_state, const Vector<Vector3> p_attribs, const Vector<Vector3> p_reference_attribs, const float p_reference_multiplier, const bool p_for_vertex, const GLTFAccessorIndex p_reference_accessor) {
+ if (p_attribs.size() == 0) {
+ return -1;
+ }
+
+ const int element_count = 3;
+ Vector<double> attribs;
+ Vector<double> type_max;
+ Vector<double> type_min;
+ attribs.resize(p_attribs.size() * element_count);
+ type_max.resize(element_count);
+ type_min.resize(element_count);
+
+ Vector<double> changed_indices;
+ Vector<double> changed_values;
+ int max_changed_index = 0;
+
+ for (int i = 0; i < p_attribs.size(); i++) {
+ Vector3 attrib = p_attribs[i];
+ bool is_different = false;
+ if (i < p_reference_attribs.size()) {
+ is_different = !(attrib * p_reference_multiplier).is_equal_approx(p_reference_attribs[i]);
+ if (!is_different) {
+ attrib = p_reference_attribs[i];
+ }
+ } else {
+ is_different = !(attrib * p_reference_multiplier).is_zero_approx();
+ if (!is_different) {
+ attrib = Vector3();
+ }
+ }
+ attribs.write[(i * element_count) + 0] = _filter_number(attrib.x);
+ attribs.write[(i * element_count) + 1] = _filter_number(attrib.y);
+ attribs.write[(i * element_count) + 2] = _filter_number(attrib.z);
+ if (is_different) {
+ changed_indices.push_back(i);
+ if (i > max_changed_index) {
+ max_changed_index = i;
+ }
+ changed_values.push_back(_filter_number(attrib.x));
+ changed_values.push_back(_filter_number(attrib.y));
+ changed_values.push_back(_filter_number(attrib.z));
+ }
+ _calc_accessor_min_max(i, element_count, type_max, attribs, type_min);
+ }
+ _round_min_max_components(type_min, type_max);
+
+ if (attribs.size() % element_count != 0) {
+ return -1;
+ }
+
+ Ref<GLTFAccessor> sparse_accessor;
+ sparse_accessor.instantiate();
+ int64_t size = p_state->buffers[0].size();
+ const GLTFType type = GLTFType::TYPE_VEC3;
+ const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT;
+
+ sparse_accessor->normalized = false;
+ sparse_accessor->count = p_attribs.size();
+ sparse_accessor->type = type;
+ sparse_accessor->component_type = component_type;
+ if (p_reference_accessor < p_state->accessors.size() && p_reference_accessor >= 0 && p_state->accessors[p_reference_accessor].is_valid()) {
+ sparse_accessor->byte_offset = p_state->accessors[p_reference_accessor]->byte_offset;
+ sparse_accessor->buffer_view = p_state->accessors[p_reference_accessor]->buffer_view;
+ }
+ sparse_accessor->max = type_max;
+ sparse_accessor->min = type_min;
+ int sparse_accessor_index_stride = max_changed_index > 65535 ? 4 : 2;
+
+ int sparse_accessor_storage_size = changed_indices.size() * (sparse_accessor_index_stride + element_count * sizeof(float));
+ int conventional_storage_size = p_attribs.size() * element_count * sizeof(float);
+
+ if (changed_indices.size() > 0 && sparse_accessor_storage_size < conventional_storage_size) {
+ // It must be worthwhile to use a sparse accessor.
+
+ GLTFBufferIndex buffer_view_i_indices = -1;
+ GLTFBufferIndex buffer_view_i_values = -1;
+ if (sparse_accessor_index_stride == 4) {
+ sparse_accessor->sparse_indices_component_type = GLTFDocument::COMPONENT_TYPE_INT;
+ } else {
+ sparse_accessor->sparse_indices_component_type = GLTFDocument::COMPONENT_TYPE_UNSIGNED_SHORT;
+ }
+ if (_encode_buffer_view(p_state, changed_indices.ptr(), changed_indices.size(), GLTFType::TYPE_SCALAR, sparse_accessor->sparse_indices_component_type, sparse_accessor->normalized, sparse_accessor->sparse_indices_byte_offset, false, buffer_view_i_indices) != OK) {
+ return -1;
+ }
+ // We use changed_indices.size() here, because we must pass the number of vec3 values rather than the number of components.
+ if (_encode_buffer_view(p_state, changed_values.ptr(), changed_indices.size(), sparse_accessor->type, sparse_accessor->component_type, sparse_accessor->normalized, sparse_accessor->sparse_values_byte_offset, false, buffer_view_i_values) != OK) {
+ return -1;
+ }
+ sparse_accessor->sparse_indices_buffer_view = buffer_view_i_indices;
+ sparse_accessor->sparse_values_buffer_view = buffer_view_i_values;
+ sparse_accessor->sparse_count = changed_indices.size();
+ } else if (changed_indices.size() > 0) {
+ GLTFBufferIndex buffer_view_i;
+ sparse_accessor->byte_offset = 0;
+ Error err = _encode_buffer_view(p_state, attribs.ptr(), p_attribs.size(), type, component_type, sparse_accessor->normalized, size, p_for_vertex, buffer_view_i);
+ if (err != OK) {
+ return -1;
+ }
+ sparse_accessor->buffer_view = buffer_view_i;
+ }
+ p_state->accessors.push_back(sparse_accessor);
+
+ return p_state->accessors.size() - 1;
+}
+
GLTFAccessorIndex GLTFDocument::_encode_accessor_as_xform(Ref<GLTFState> p_state, const Vector<Transform3D> p_attribs, const bool p_for_vertex) {
if (p_attribs.size() == 0) {
return -1;
@@ -2045,7 +2180,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_xform(Ref<GLTFState> p_state
return p_state->accessors.size() - 1;
}
-Vector<Vector3> GLTFDocument::_decode_accessor_as_vec3(Ref<GLTFState> p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
+Vector<Vector3> GLTFDocument::_decode_accessor_as_vec3(Ref<GLTFState> p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex, const Vector<int> &p_packed_vertex_ids) {
const Vector<double> attribs = _decode_accessor(p_state, p_accessor, p_for_vertex);
Vector<Vector3> ret;
@@ -2055,17 +2190,23 @@ Vector<Vector3> GLTFDocument::_decode_accessor_as_vec3(Ref<GLTFState> p_state, c
ERR_FAIL_COND_V(attribs.size() % 3 != 0, ret);
const double *attribs_ptr = attribs.ptr();
- const int ret_size = attribs.size() / 3;
+ int ret_size = attribs.size() / 3;
+ if (!p_packed_vertex_ids.is_empty()) {
+ ERR_FAIL_COND_V(p_packed_vertex_ids[p_packed_vertex_ids.size() - 1] >= ret_size, ret);
+ ret_size = p_packed_vertex_ids.size();
+ }
ret.resize(ret_size);
- {
- for (int i = 0; i < ret_size; i++) {
- ret.write[i] = Vector3(attribs_ptr[i * 3 + 0], attribs_ptr[i * 3 + 1], attribs_ptr[i * 3 + 2]);
+ for (int i = 0; i < ret_size; i++) {
+ int src_i = i;
+ if (!p_packed_vertex_ids.is_empty()) {
+ src_i = p_packed_vertex_ids[i];
}
+ ret.write[i] = Vector3(attribs_ptr[src_i * 3 + 0], attribs_ptr[src_i * 3 + 1], attribs_ptr[src_i * 3 + 2]);
}
return ret;
}
-Vector<Color> GLTFDocument::_decode_accessor_as_color(Ref<GLTFState> p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
+Vector<Color> GLTFDocument::_decode_accessor_as_color(Ref<GLTFState> p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex, const Vector<int> &p_packed_vertex_ids) {
const Vector<double> attribs = _decode_accessor(p_state, p_accessor, p_for_vertex);
Vector<Color> ret;
@@ -2082,12 +2223,18 @@ Vector<Color> GLTFDocument::_decode_accessor_as_color(Ref<GLTFState> p_state, co
ERR_FAIL_COND_V(attribs.size() % vec_len != 0, ret);
const double *attribs_ptr = attribs.ptr();
- const int ret_size = attribs.size() / vec_len;
+ int ret_size = attribs.size() / vec_len;
+ if (!p_packed_vertex_ids.is_empty()) {
+ ERR_FAIL_COND_V(p_packed_vertex_ids[p_packed_vertex_ids.size() - 1] >= ret_size, ret);
+ ret_size = p_packed_vertex_ids.size();
+ }
ret.resize(ret_size);
- {
- for (int i = 0; i < ret_size; i++) {
- ret.write[i] = Color(attribs_ptr[i * vec_len + 0], attribs_ptr[i * vec_len + 1], attribs_ptr[i * vec_len + 2], vec_len == 4 ? attribs_ptr[i * 4 + 3] : 1.0);
+ for (int i = 0; i < ret_size; i++) {
+ int src_i = i;
+ if (!p_packed_vertex_ids.is_empty()) {
+ src_i = p_packed_vertex_ids[i];
}
+ ret.write[i] = Color(attribs_ptr[src_i * vec_len + 0], attribs_ptr[src_i * vec_len + 1], attribs_ptr[src_i * vec_len + 2], vec_len == 4 ? attribs_ptr[src_i * 4 + 3] : 1.0);
}
return ret;
}
@@ -2430,16 +2577,16 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> p_state) {
Vector<int32_t> mesh_indices = array[Mesh::ARRAY_INDEX];
if (mesh_indices.size()) {
if (primitive_type == Mesh::PRIMITIVE_TRIANGLES) {
- //swap around indices, convert ccw to cw for front face
+ // Swap around indices, convert ccw to cw for front face.
const int is = mesh_indices.size();
for (int k = 0; k < is; k += 3) {
SWAP(mesh_indices.write[k + 0], mesh_indices.write[k + 2]);
}
}
- primitive["indices"] = _encode_accessor_as_ints(p_state, mesh_indices, true, true);
+ primitive["indices"] = _encode_accessor_as_ints(p_state, mesh_indices, false, true);
} else {
if (primitive_type == Mesh::PRIMITIVE_TRIANGLES) {
- //generate indices because they need to be swapped for CW/CCW
+ // Generate indices because they need to be swapped for CW/CCW.
const Vector<Vector3> &vertices = array[Mesh::ARRAY_VERTEX];
Ref<SurfaceTool> st;
st.instantiate();
@@ -2455,50 +2602,77 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> p_state) {
generated_indices.write[k + 2] = k + 1;
}
}
- primitive["indices"] = _encode_accessor_as_ints(p_state, generated_indices, true, true);
+ primitive["indices"] = _encode_accessor_as_ints(p_state, generated_indices, false, true);
}
}
}
primitive["attributes"] = attributes;
- //blend shapes
+ // Blend shapes
print_verbose("glTF: Mesh has targets");
if (import_mesh->get_blend_shape_count()) {
ArrayMesh::BlendShapeMode shape_mode = import_mesh->get_blend_shape_mode();
+ const float normal_tangent_sparse_rounding = 0.001;
for (int morph_i = 0; morph_i < import_mesh->get_blend_shape_count(); morph_i++) {
Array array_morph = import_mesh->get_surface_blend_shape_arrays(surface_i, morph_i);
Dictionary t;
Vector<Vector3> varr = array_morph[Mesh::ARRAY_VERTEX];
+ Vector<Vector3> src_varr = array[Mesh::ARRAY_VERTEX];
Array mesh_arrays = import_mesh->get_surface_arrays(surface_i);
- if (varr.size()) {
- Vector<Vector3> src_varr = array[Mesh::ARRAY_VERTEX];
+ if (varr.size() && varr.size() == src_varr.size()) {
if (shape_mode == ArrayMesh::BlendShapeMode::BLEND_SHAPE_MODE_NORMALIZED) {
const int max_idx = src_varr.size();
for (int blend_i = 0; blend_i < max_idx; blend_i++) {
- varr.write[blend_i] = Vector3(varr[blend_i]) - src_varr[blend_i];
+ varr.write[blend_i] = varr[blend_i] - src_varr[blend_i];
+ }
+ }
+ GLTFAccessorIndex position_accessor = attributes["POSITION"];
+ if (position_accessor != -1) {
+ int new_accessor = _encode_sparse_accessor_as_vec3(p_state, varr, Vector<Vector3>(), 1.0, true, -1);
+ if (new_accessor != -1) {
+ t["POSITION"] = new_accessor;
}
}
-
- t["POSITION"] = _encode_accessor_as_vec3(p_state, varr, true);
}
Vector<Vector3> narr = array_morph[Mesh::ARRAY_NORMAL];
- if (narr.size()) {
- t["NORMAL"] = _encode_accessor_as_vec3(p_state, narr, true);
+ Vector<Vector3> src_narr = array[Mesh::ARRAY_NORMAL];
+ if (narr.size() && narr.size() == src_narr.size()) {
+ if (shape_mode == ArrayMesh::BlendShapeMode::BLEND_SHAPE_MODE_NORMALIZED) {
+ const int max_idx = src_narr.size();
+ for (int blend_i = 0; blend_i < max_idx; blend_i++) {
+ narr.write[blend_i] = narr[blend_i] - src_narr[blend_i];
+ }
+ }
+ GLTFAccessorIndex normal_accessor = attributes["NORMAL"];
+ if (normal_accessor != -1) {
+ int new_accessor = _encode_sparse_accessor_as_vec3(p_state, narr, Vector<Vector3>(), normal_tangent_sparse_rounding, true, -1);
+ if (new_accessor != -1) {
+ t["NORMAL"] = new_accessor;
+ }
+ }
}
Vector<real_t> tarr = array_morph[Mesh::ARRAY_TANGENT];
- if (tarr.size()) {
+ Vector<real_t> src_tarr = array[Mesh::ARRAY_TANGENT];
+ if (tarr.size() && tarr.size() == src_tarr.size()) {
const int ret_size = tarr.size() / 4;
Vector<Vector3> attribs;
attribs.resize(ret_size);
for (int i = 0; i < ret_size; i++) {
Vector3 vec3;
- vec3.x = tarr[(i * 4) + 0];
- vec3.y = tarr[(i * 4) + 1];
- vec3.z = tarr[(i * 4) + 2];
+ vec3.x = tarr[(i * 4) + 0] - src_tarr[(i * 4) + 0];
+ vec3.y = tarr[(i * 4) + 1] - src_tarr[(i * 4) + 1];
+ vec3.z = tarr[(i * 4) + 2] - src_tarr[(i * 4) + 2];
+ attribs.write[i] = vec3;
+ }
+ GLTFAccessorIndex tangent_accessor = attributes["TANGENT"];
+ if (tangent_accessor != -1) {
+ int new_accessor = _encode_sparse_accessor_as_vec3(p_state, attribs, Vector<Vector3>(), normal_tangent_sparse_rounding, true, -1);
+ if (new_accessor != -1) {
+ t["TANGENT"] = new_accessor;
+ }
}
- t["TANGENT"] = _encode_accessor_as_vec3(p_state, attribs, true);
}
targets.push_back(t);
}
@@ -2623,24 +2797,72 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> p_state) {
primitive = primitives2[mode];
}
+ int32_t orig_vertex_num = 0;
ERR_FAIL_COND_V(!a.has("POSITION"), ERR_PARSE_ERROR);
- int32_t vertex_num = 0;
if (a.has("POSITION")) {
PackedVector3Array vertices = _decode_accessor_as_vec3(p_state, a["POSITION"], true);
array[Mesh::ARRAY_VERTEX] = vertices;
- vertex_num = vertices.size();
+ orig_vertex_num = vertices.size();
+ }
+ int32_t vertex_num = orig_vertex_num;
+
+ Vector<int> indices;
+ Vector<int> indices_mapping;
+ Vector<int> indices_rev_mapping;
+ Vector<int> indices_vec4_mapping;
+ if (p.has("indices")) {
+ indices = _decode_accessor_as_ints(p_state, p["indices"], false);
+ const int is = indices.size();
+
+ if (primitive == Mesh::PRIMITIVE_TRIANGLES) {
+ // Swap around indices, convert ccw to cw for front face.
+
+ int *w = indices.ptrw();
+ for (int k = 0; k < is; k += 3) {
+ SWAP(w[k + 1], w[k + 2]);
+ }
+ }
+
+ const int *indices_w = indices.ptrw();
+ Vector<bool> used_indices;
+ used_indices.resize_zeroed(orig_vertex_num);
+ bool *used_w = used_indices.ptrw();
+ for (int idx_i = 0; idx_i < is; idx_i++) {
+ ERR_FAIL_INDEX_V(indices_w[idx_i], orig_vertex_num, ERR_INVALID_DATA);
+ used_w[indices_w[idx_i]] = true;
+ }
+ indices_rev_mapping.resize_zeroed(orig_vertex_num);
+ int *rev_w = indices_rev_mapping.ptrw();
+ vertex_num = 0;
+ for (int vert_i = 0; vert_i < orig_vertex_num; vert_i++) {
+ if (used_w[vert_i]) {
+ rev_w[vert_i] = indices_mapping.size();
+ indices_mapping.push_back(vert_i);
+ indices_vec4_mapping.push_back(vert_i * 4 + 0);
+ indices_vec4_mapping.push_back(vert_i * 4 + 1);
+ indices_vec4_mapping.push_back(vert_i * 4 + 2);
+ indices_vec4_mapping.push_back(vert_i * 4 + 3);
+ vertex_num++;
+ }
+ }
+ }
+ ERR_FAIL_COND_V(vertex_num <= 0, ERR_INVALID_DECLARATION);
+
+ if (a.has("POSITION")) {
+ PackedVector3Array vertices = _decode_accessor_as_vec3(p_state, a["POSITION"], true, indices_mapping);
+ array[Mesh::ARRAY_VERTEX] = vertices;
}
if (a.has("NORMAL")) {
- array[Mesh::ARRAY_NORMAL] = _decode_accessor_as_vec3(p_state, a["NORMAL"], true);
+ array[Mesh::ARRAY_NORMAL] = _decode_accessor_as_vec3(p_state, a["NORMAL"], true, indices_mapping);
}
if (a.has("TANGENT")) {
- array[Mesh::ARRAY_TANGENT] = _decode_accessor_as_floats(p_state, a["TANGENT"], true);
+ array[Mesh::ARRAY_TANGENT] = _decode_accessor_as_floats(p_state, a["TANGENT"], true, indices_vec4_mapping);
}
if (a.has("TEXCOORD_0")) {
- array[Mesh::ARRAY_TEX_UV] = _decode_accessor_as_vec2(p_state, a["TEXCOORD_0"], true);
+ array[Mesh::ARRAY_TEX_UV] = _decode_accessor_as_vec2(p_state, a["TEXCOORD_0"], true, indices_mapping);
}
if (a.has("TEXCOORD_1")) {
- array[Mesh::ARRAY_TEX_UV2] = _decode_accessor_as_vec2(p_state, a["TEXCOORD_1"], true);
+ array[Mesh::ARRAY_TEX_UV2] = _decode_accessor_as_vec2(p_state, a["TEXCOORD_1"], true, indices_mapping);
}
for (int custom_i = 0; custom_i < 3; custom_i++) {
Vector<float> cur_custom;
@@ -2651,12 +2873,12 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> p_state) {
String gltf_texcoord_key = vformat("TEXCOORD_%d", texcoord_i);
int num_channels = 0;
if (a.has(gltf_texcoord_key)) {
- texcoord_first = _decode_accessor_as_vec2(p_state, a[gltf_texcoord_key], true);
+ texcoord_first = _decode_accessor_as_vec2(p_state, a[gltf_texcoord_key], true, indices_mapping);
num_channels = 2;
}
gltf_texcoord_key = vformat("TEXCOORD_%d", texcoord_i + 1);
if (a.has(gltf_texcoord_key)) {
- texcoord_second = _decode_accessor_as_vec2(p_state, a[gltf_texcoord_key], true);
+ texcoord_second = _decode_accessor_as_vec2(p_state, a[gltf_texcoord_key], true, indices_mapping);
num_channels = 4;
}
if (!num_channels) {
@@ -2697,15 +2919,18 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> p_state) {
}
}
if (a.has("COLOR_0")) {
- array[Mesh::ARRAY_COLOR] = _decode_accessor_as_color(p_state, a["COLOR_0"], true);
+ array[Mesh::ARRAY_COLOR] = _decode_accessor_as_color(p_state, a["COLOR_0"], true, indices_mapping);
has_vertex_color = true;
}
if (a.has("JOINTS_0") && !a.has("JOINTS_1")) {
- array[Mesh::ARRAY_BONES] = _decode_accessor_as_ints(p_state, a["JOINTS_0"], true);
+ PackedInt32Array joints_0 = _decode_accessor_as_ints(p_state, a["JOINTS_0"], true, indices_vec4_mapping);
+ ERR_FAIL_COND_V(joints_0.size() != 4 * vertex_num, ERR_INVALID_DATA);
+ array[Mesh::ARRAY_BONES] = joints_0;
} else if (a.has("JOINTS_0") && a.has("JOINTS_1")) {
- PackedInt32Array joints_0 = _decode_accessor_as_ints(p_state, a["JOINTS_0"], true);
- PackedInt32Array joints_1 = _decode_accessor_as_ints(p_state, a["JOINTS_1"], true);
+ PackedInt32Array joints_0 = _decode_accessor_as_ints(p_state, a["JOINTS_0"], true, indices_vec4_mapping);
+ PackedInt32Array joints_1 = _decode_accessor_as_ints(p_state, a["JOINTS_1"], true, indices_vec4_mapping);
ERR_FAIL_COND_V(joints_0.size() != joints_1.size(), ERR_INVALID_DATA);
+ ERR_FAIL_COND_V(joints_0.size() != 4 * vertex_num, ERR_INVALID_DATA);
int32_t weight_8_count = JOINT_GROUP_SIZE * 2;
Vector<int> joints;
joints.resize(vertex_num * weight_8_count);
@@ -2722,8 +2947,9 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> p_state) {
array[Mesh::ARRAY_BONES] = joints;
}
if (a.has("WEIGHTS_0") && !a.has("WEIGHTS_1")) {
- Vector<float> weights = _decode_accessor_as_floats(p_state, a["WEIGHTS_0"], true);
- { //gltf does not seem to normalize the weights for some reason..
+ Vector<float> weights = _decode_accessor_as_floats(p_state, a["WEIGHTS_0"], true, indices_vec4_mapping);
+ ERR_FAIL_COND_V(weights.size() != 4 * vertex_num, ERR_INVALID_DATA);
+ { // glTF does not seem to normalize the weights for some reason.
int wc = weights.size();
float *w = weights.ptrw();
@@ -2743,10 +2969,11 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> p_state) {
}
array[Mesh::ARRAY_WEIGHTS] = weights;
} else if (a.has("WEIGHTS_0") && a.has("WEIGHTS_1")) {
- Vector<float> weights_0 = _decode_accessor_as_floats(p_state, a["WEIGHTS_0"], true);
- Vector<float> weights_1 = _decode_accessor_as_floats(p_state, a["WEIGHTS_1"], true);
+ Vector<float> weights_0 = _decode_accessor_as_floats(p_state, a["WEIGHTS_0"], true, indices_vec4_mapping);
+ Vector<float> weights_1 = _decode_accessor_as_floats(p_state, a["WEIGHTS_1"], true, indices_vec4_mapping);
Vector<float> weights;
ERR_FAIL_COND_V(weights_0.size() != weights_1.size(), ERR_INVALID_DATA);
+ ERR_FAIL_COND_V(weights_0.size() != 4 * vertex_num, ERR_INVALID_DATA);
int32_t weight_8_count = JOINT_GROUP_SIZE * 2;
weights.resize(vertex_num * weight_8_count);
for (int32_t vertex_i = 0; vertex_i < vertex_num; vertex_i++) {
@@ -2759,7 +2986,7 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> p_state) {
weights.write[vertex_i * weight_8_count + 6] = weights_1[vertex_i * JOINT_GROUP_SIZE + 2];
weights.write[vertex_i * weight_8_count + 7] = weights_1[vertex_i * JOINT_GROUP_SIZE + 3];
}
- { //gltf does not seem to normalize the weights for some reason..
+ { // glTF does not seem to normalize the weights for some reason.
int wc = weights.size();
float *w = weights.ptrw();
@@ -2788,25 +3015,18 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> p_state) {
array[Mesh::ARRAY_WEIGHTS] = weights;
}
- if (p.has("indices")) {
- Vector<int> indices = _decode_accessor_as_ints(p_state, p["indices"], false);
-
- if (primitive == Mesh::PRIMITIVE_TRIANGLES) {
- //swap around indices, convert ccw to cw for front face
-
- const int is = indices.size();
- int *w = indices.ptrw();
- for (int k = 0; k < is; k += 3) {
- SWAP(w[k + 1], w[k + 2]);
- }
+ if (!indices.is_empty()) {
+ int *w = indices.ptrw();
+ const int is = indices.size();
+ for (int ind_i = 0; ind_i < is; ind_i++) {
+ w[ind_i] = indices_rev_mapping[indices[ind_i]];
}
array[Mesh::ARRAY_INDEX] = indices;
} else if (primitive == Mesh::PRIMITIVE_TRIANGLES) {
- //generate indices because they need to be swapped for CW/CCW
+ // Generate indices because they need to be swapped for CW/CCW.
const Vector<Vector3> &vertices = array[Mesh::ARRAY_VERTEX];
ERR_FAIL_COND_V(vertices.is_empty(), ERR_PARSE_ERROR);
- Vector<int> indices;
const int vs = vertices.size();
indices.resize(vs);
{
@@ -2870,13 +3090,11 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> p_state) {
}
Array morphs;
- //blend shapes
+ // Blend shapes
if (p.has("targets")) {
print_verbose("glTF: Mesh has targets");
const Array &targets = p["targets"];
- //ideally BLEND_SHAPE_MODE_RELATIVE since gltf2 stores in displacement
- //but it could require a larger refactor?
import_mesh->set_blend_shape_mode(Mesh::BLEND_SHAPE_MODE_NORMALIZED);
if (j == 0) {
@@ -2903,7 +3121,7 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> p_state) {
}
if (t.has("POSITION")) {
- Vector<Vector3> varr = _decode_accessor_as_vec3(p_state, t["POSITION"], true);
+ Vector<Vector3> varr = _decode_accessor_as_vec3(p_state, t["POSITION"], true, indices_mapping);
const Vector<Vector3> src_varr = array[Mesh::ARRAY_VERTEX];
const int size = src_varr.size();
ERR_FAIL_COND_V(size == 0, ERR_PARSE_ERROR);
@@ -2925,7 +3143,7 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> p_state) {
array_copy[Mesh::ARRAY_VERTEX] = varr;
}
if (t.has("NORMAL")) {
- Vector<Vector3> narr = _decode_accessor_as_vec3(p_state, t["NORMAL"], true);
+ Vector<Vector3> narr = _decode_accessor_as_vec3(p_state, t["NORMAL"], true, indices_mapping);
const Vector<Vector3> src_narr = array[Mesh::ARRAY_NORMAL];
int size = src_narr.size();
ERR_FAIL_COND_V(size == 0, ERR_PARSE_ERROR);
@@ -2947,7 +3165,7 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> p_state) {
array_copy[Mesh::ARRAY_NORMAL] = narr;
}
if (t.has("TANGENT")) {
- const Vector<Vector3> tangents_v3 = _decode_accessor_as_vec3(p_state, t["TANGENT"], true);
+ const Vector<Vector3> tangents_v3 = _decode_accessor_as_vec3(p_state, t["TANGENT"], true, indices_mapping);
const Vector<float> src_tangents = array[Mesh::ARRAY_TANGENT];
ERR_FAIL_COND_V(src_tangents.is_empty(), ERR_PARSE_ERROR);
@@ -5517,7 +5735,7 @@ void GLTFDocument::_generate_skeleton_bone_node(Ref<GLTFState> p_state, const GL
}
}
-template <class T>
+template <typename T>
struct SceneFormatImporterGLTFInterpolate {
T lerp(const T &a, const T &b, float c) const {
return a + (b - a) * c;
@@ -5567,7 +5785,7 @@ struct SceneFormatImporterGLTFInterpolate<Quaternion> {
}
};
-template <class T>
+template <typename T>
T GLTFDocument::_interpolate_track(const Vector<real_t> &p_times, const Vector<T> &p_values, const float p_time, const GLTFAnimation::Interpolation p_interp) {
ERR_FAIL_COND_V(p_values.is_empty(), T());
if (p_times.size() != (p_values.size() / (p_interp == GLTFAnimation::INTERP_CUBIC_SPLINE ? 3 : 1))) {
diff --git a/modules/gltf/gltf_document.h b/modules/gltf/gltf_document.h
index 1682e9eeb7..1001b482cd 100644
--- a/modules/gltf/gltf_document.h
+++ b/modules/gltf/gltf_document.h
@@ -57,13 +57,6 @@ public:
ARRAY_BUFFER = 34962,
ELEMENT_ARRAY_BUFFER = 34963,
- TYPE_BYTE = 5120,
- TYPE_UNSIGNED_BYTE = 5121,
- TYPE_SHORT = 5122,
- TYPE_UNSIGNED_SHORT = 5123,
- TYPE_UNSIGNED_INT = 5125,
- TYPE_FLOAT = 5126,
-
COMPONENT_TYPE_BYTE = 5120,
COMPONENT_TYPE_UNSIGNED_BYTE = 5121,
COMPONENT_TYPE_SHORT = 5122,
@@ -155,19 +148,24 @@ private:
const bool p_for_vertex);
Vector<float> _decode_accessor_as_floats(Ref<GLTFState> p_state,
const GLTFAccessorIndex p_accessor,
- const bool p_for_vertex);
+ const bool p_for_vertex,
+ const Vector<int> &p_packed_vertex_ids = Vector<int>());
Vector<int> _decode_accessor_as_ints(Ref<GLTFState> p_state,
const GLTFAccessorIndex p_accessor,
- const bool p_for_vertex);
+ const bool p_for_vertex,
+ const Vector<int> &p_packed_vertex_ids = Vector<int>());
Vector<Vector2> _decode_accessor_as_vec2(Ref<GLTFState> p_state,
const GLTFAccessorIndex p_accessor,
- const bool p_for_vertex);
+ const bool p_for_vertex,
+ const Vector<int> &p_packed_vertex_ids = Vector<int>());
Vector<Vector3> _decode_accessor_as_vec3(Ref<GLTFState> p_state,
const GLTFAccessorIndex p_accessor,
- const bool p_for_vertex);
+ const bool p_for_vertex,
+ const Vector<int> &p_packed_vertex_ids = Vector<int>());
Vector<Color> _decode_accessor_as_color(Ref<GLTFState> p_state,
const GLTFAccessorIndex p_accessor,
- const bool p_for_vertex);
+ const bool p_for_vertex,
+ const Vector<int> &p_packed_vertex_ids = Vector<int>());
Vector<Quaternion> _decode_accessor_as_quaternion(Ref<GLTFState> p_state,
const GLTFAccessorIndex p_accessor,
const bool p_for_vertex);
@@ -217,7 +215,7 @@ private:
Light3D *_generate_light(Ref<GLTFState> p_state, const GLTFNodeIndex p_node_index);
Node3D *_generate_spatial(Ref<GLTFState> p_state, const GLTFNodeIndex p_node_index);
void _assign_node_names(Ref<GLTFState> p_state);
- template <class T>
+ template <typename T>
T _interpolate_track(const Vector<real_t> &p_times, const Vector<T> &p_values,
const float p_time,
const GLTFAnimation::Interpolation p_interp);
@@ -255,6 +253,7 @@ private:
GLTFAccessorIndex _encode_accessor_as_vec3(Ref<GLTFState> p_state,
const Vector<Vector3> p_attribs,
const bool p_for_vertex);
+ GLTFAccessorIndex _encode_sparse_accessor_as_vec3(Ref<GLTFState> p_state, const Vector<Vector3> p_attribs, const Vector<Vector3> p_reference_attribs, const float p_reference_multiplier, const bool p_for_vertex, const GLTFAccessorIndex p_reference_accessor);
GLTFAccessorIndex _encode_accessor_as_color(Ref<GLTFState> p_state,
const Vector<Color> p_attribs,
const bool p_for_vertex);
@@ -273,6 +272,7 @@ private:
const int p_component_type, const bool p_normalized,
const int p_byte_offset, const bool p_for_vertex,
GLTFBufferViewIndex &r_accessor, const bool p_for_indices = false);
+
Error _encode_accessors(Ref<GLTFState> p_state);
Error _encode_buffer_views(Ref<GLTFState> p_state);
Error _serialize_materials(Ref<GLTFState> p_state);
diff --git a/modules/gltf/gltf_template_convert.h b/modules/gltf/gltf_template_convert.h
index 2743cd8a9b..46f185867a 100644
--- a/modules/gltf/gltf_template_convert.h
+++ b/modules/gltf/gltf_template_convert.h
@@ -37,7 +37,7 @@
#include "core/variant/typed_array.h"
namespace GLTFTemplateConvert {
-template <class T>
+template <typename T>
static Array to_array(const Vector<T> &p_inp) {
Array ret;
for (int i = 0; i < p_inp.size(); i++) {
@@ -46,7 +46,7 @@ static Array to_array(const Vector<T> &p_inp) {
return ret;
}
-template <class T>
+template <typename T>
static TypedArray<T> to_array(const HashSet<T> &p_inp) {
TypedArray<T> ret;
typename HashSet<T>::Iterator elem = p_inp.begin();
@@ -57,7 +57,7 @@ static TypedArray<T> to_array(const HashSet<T> &p_inp) {
return ret;
}
-template <class T>
+template <typename T>
static void set_from_array(Vector<T> &r_out, const Array &p_inp) {
r_out.clear();
for (int i = 0; i < p_inp.size(); i++) {
@@ -65,7 +65,7 @@ static void set_from_array(Vector<T> &r_out, const Array &p_inp) {
}
}
-template <class T>
+template <typename T>
static void set_from_array(HashSet<T> &r_out, const TypedArray<T> &p_inp) {
r_out.clear();
for (int i = 0; i < p_inp.size(); i++) {
@@ -73,7 +73,7 @@ static void set_from_array(HashSet<T> &r_out, const TypedArray<T> &p_inp) {
}
}
-template <class K, class V>
+template <typename K, typename V>
static Dictionary to_dictionary(const HashMap<K, V> &p_inp) {
Dictionary ret;
for (const KeyValue<K, V> &E : p_inp) {
@@ -82,7 +82,7 @@ static Dictionary to_dictionary(const HashMap<K, V> &p_inp) {
return ret;
}
-template <class K, class V>
+template <typename K, typename V>
static void set_from_dictionary(HashMap<K, V> &r_out, const Dictionary &p_inp) {
r_out.clear();
Array keys = p_inp.keys();
diff --git a/modules/gltf/structures/gltf_animation.h b/modules/gltf/structures/gltf_animation.h
index 7f769752c2..afc9784895 100644
--- a/modules/gltf/structures/gltf_animation.h
+++ b/modules/gltf/structures/gltf_animation.h
@@ -47,7 +47,7 @@ public:
INTERP_CUBIC_SPLINE,
};
- template <class T>
+ template <typename T>
struct Channel {
Interpolation interpolation = INTERP_LINEAR;
Vector<real_t> times;
diff --git a/modules/multiplayer/scene_replication_interface.h b/modules/multiplayer/scene_replication_interface.h
index 31211bb108..cb582a2caf 100644
--- a/modules/multiplayer/scene_replication_interface.h
+++ b/modules/multiplayer/scene_replication_interface.h
@@ -112,7 +112,7 @@ private:
Error _update_spawn_visibility(int p_peer, const ObjectID &p_oid);
void _free_remotes(const PeerInfo &p_info);
- template <class T>
+ template <typename T>
static T *get_id_as(const ObjectID &p_id) {
return p_id.is_valid() ? Object::cast_to<T>(ObjectDB::get_instance(p_id)) : nullptr;
}
diff --git a/modules/openxr/doc_classes/OpenXRExtensionWrapperExtension.xml b/modules/openxr/doc_classes/OpenXRExtensionWrapperExtension.xml
index 20ce1c42bf..9d6b197ee1 100644
--- a/modules/openxr/doc_classes/OpenXRExtensionWrapperExtension.xml
+++ b/modules/openxr/doc_classes/OpenXRExtensionWrapperExtension.xml
@@ -11,8 +11,25 @@
<methods>
<method name="_get_composition_layer" qualifiers="virtual">
<return type="int" />
+ <param index="0" name="index" type="int" />
<description>
- Returns a pointer to an [code]XrCompositionLayerBaseHeader[/code] struct to provide a composition layer. This will only be called if the extension previously registered itself with [method OpenXRAPIExtension.register_composition_layer_provider].
+ Returns a pointer to an [code]XrCompositionLayerBaseHeader[/code] struct to provide the given composition layer.
+ This will only be called if the extension previously registered itself with [method OpenXRAPIExtension.register_composition_layer_provider].
+ </description>
+ </method>
+ <method name="_get_composition_layer_count" qualifiers="virtual">
+ <return type="int" />
+ <description>
+ Returns the number of composition layers this extension wrapper provides via [method _get_composition_layer].
+ This will only be called if the extension previously registered itself with [method OpenXRAPIExtension.register_composition_layer_provider].
+ </description>
+ </method>
+ <method name="_get_composition_layer_order" qualifiers="virtual">
+ <return type="int" />
+ <param index="0" name="index" type="int" />
+ <description>
+ Returns an integer that will be used to sort the given composition layer provided via [method _get_composition_layer]. Lower numbers will move the layer to the front of the list, and higher numbers to the end. The default projection layer has an order of [code]0[/code], so layers provided by this method should probably be above or below (but not exactly) [code]0[/code].
+ This will only be called if the extension previously registered itself with [method OpenXRAPIExtension.register_composition_layer_provider].
</description>
</method>
<method name="_get_requested_extensions" qualifiers="virtual">
diff --git a/modules/openxr/extensions/openxr_composition_layer_depth_extension.cpp b/modules/openxr/extensions/openxr_composition_layer_depth_extension.cpp
index 7a16da144e..b3c94d44f0 100644
--- a/modules/openxr/extensions/openxr_composition_layer_depth_extension.cpp
+++ b/modules/openxr/extensions/openxr_composition_layer_depth_extension.cpp
@@ -56,8 +56,15 @@ bool OpenXRCompositionLayerDepthExtension::is_available() {
return available;
}
-XrCompositionLayerBaseHeader *OpenXRCompositionLayerDepthExtension::get_composition_layer() {
- // Seems this is all done in our base layer... Just in case this changes...
+int OpenXRCompositionLayerDepthExtension::get_composition_layer_count() {
+ return 0;
+}
+XrCompositionLayerBaseHeader *OpenXRCompositionLayerDepthExtension::get_composition_layer(int p_index) {
+ // Seems this is all done in our base layer... Just in case this changes...
return nullptr;
}
+
+int OpenXRCompositionLayerDepthExtension::get_composition_layer_order(int p_index) {
+ return 0;
+}
diff --git a/modules/openxr/extensions/openxr_composition_layer_depth_extension.h b/modules/openxr/extensions/openxr_composition_layer_depth_extension.h
index 50bbef4db4..1fda8844af 100644
--- a/modules/openxr/extensions/openxr_composition_layer_depth_extension.h
+++ b/modules/openxr/extensions/openxr_composition_layer_depth_extension.h
@@ -43,7 +43,9 @@ public:
virtual HashMap<String, bool *> get_requested_extensions() override;
bool is_available();
- virtual XrCompositionLayerBaseHeader *get_composition_layer() override;
+ virtual int get_composition_layer_count() override;
+ virtual XrCompositionLayerBaseHeader *get_composition_layer(int p_index) override;
+ virtual int get_composition_layer_order(int p_index) override;
private:
static OpenXRCompositionLayerDepthExtension *singleton;
diff --git a/modules/openxr/extensions/openxr_composition_layer_provider.h b/modules/openxr/extensions/openxr_composition_layer_provider.h
index d77ae06174..44f90a0e0e 100644
--- a/modules/openxr/extensions/openxr_composition_layer_provider.h
+++ b/modules/openxr/extensions/openxr_composition_layer_provider.h
@@ -38,7 +38,9 @@
// Interface for OpenXR extensions that provide a composition layer.
class OpenXRCompositionLayerProvider {
public:
- virtual XrCompositionLayerBaseHeader *get_composition_layer() = 0;
+ virtual int get_composition_layer_count() = 0;
+ virtual XrCompositionLayerBaseHeader *get_composition_layer(int p_index) = 0;
+ virtual int get_composition_layer_order(int p_index) = 0;
virtual ~OpenXRCompositionLayerProvider() {}
};
diff --git a/modules/openxr/extensions/openxr_extension_wrapper_extension.cpp b/modules/openxr/extensions/openxr_extension_wrapper_extension.cpp
index a9b62819b7..60a934e3a8 100644
--- a/modules/openxr/extensions/openxr_extension_wrapper_extension.cpp
+++ b/modules/openxr/extensions/openxr_extension_wrapper_extension.cpp
@@ -39,7 +39,9 @@ void OpenXRExtensionWrapperExtension::_bind_methods() {
GDVIRTUAL_BIND(_set_session_create_and_get_next_pointer, "next_pointer");
GDVIRTUAL_BIND(_set_swapchain_create_info_and_get_next_pointer, "next_pointer");
GDVIRTUAL_BIND(_set_hand_joint_locations_and_get_next_pointer, "hand_index", "next_pointer");
- GDVIRTUAL_BIND(_get_composition_layer);
+ GDVIRTUAL_BIND(_get_composition_layer_count);
+ GDVIRTUAL_BIND(_get_composition_layer, "index");
+ GDVIRTUAL_BIND(_get_composition_layer_order, "index");
GDVIRTUAL_BIND(_get_suggested_tracker_names);
GDVIRTUAL_BIND(_on_register_metadata);
GDVIRTUAL_BIND(_on_before_instance_created);
@@ -140,16 +142,28 @@ PackedStringArray OpenXRExtensionWrapperExtension::get_suggested_tracker_names()
return PackedStringArray();
}
-XrCompositionLayerBaseHeader *OpenXRExtensionWrapperExtension::get_composition_layer() {
+int OpenXRExtensionWrapperExtension::get_composition_layer_count() {
+ int count = 0;
+ GDVIRTUAL_CALL(_get_composition_layer_count, count);
+ return count;
+}
+
+XrCompositionLayerBaseHeader *OpenXRExtensionWrapperExtension::get_composition_layer(int p_index) {
uint64_t pointer;
- if (GDVIRTUAL_CALL(_get_composition_layer, pointer)) {
+ if (GDVIRTUAL_CALL(_get_composition_layer, p_index, pointer)) {
return reinterpret_cast<XrCompositionLayerBaseHeader *>(pointer);
}
return nullptr;
}
+int OpenXRExtensionWrapperExtension::get_composition_layer_order(int p_index) {
+ int order = 0;
+ GDVIRTUAL_CALL(_get_composition_layer_order, p_index, order);
+ return order;
+}
+
void OpenXRExtensionWrapperExtension::on_register_metadata() {
GDVIRTUAL_CALL(_on_register_metadata);
}
diff --git a/modules/openxr/extensions/openxr_extension_wrapper_extension.h b/modules/openxr/extensions/openxr_extension_wrapper_extension.h
index edcbc0139b..d3b78bf617 100644
--- a/modules/openxr/extensions/openxr_extension_wrapper_extension.h
+++ b/modules/openxr/extensions/openxr_extension_wrapper_extension.h
@@ -59,7 +59,9 @@ public:
virtual void *set_session_create_and_get_next_pointer(void *p_next_pointer) override;
virtual void *set_swapchain_create_info_and_get_next_pointer(void *p_next_pointer) override;
virtual void *set_hand_joint_locations_and_get_next_pointer(int p_hand_index, void *p_next_pointer) override;
- virtual XrCompositionLayerBaseHeader *get_composition_layer() override;
+ virtual int get_composition_layer_count() override;
+ virtual XrCompositionLayerBaseHeader *get_composition_layer(int p_index) override;
+ virtual int get_composition_layer_order(int p_index) override;
//TODO workaround as GDExtensionPtr<void> return type results in build error in godot-cpp
GDVIRTUAL1R(uint64_t, _set_system_properties_and_get_next_pointer, GDExtensionPtr<void>);
@@ -67,7 +69,9 @@ public:
GDVIRTUAL1R(uint64_t, _set_session_create_and_get_next_pointer, GDExtensionPtr<void>);
GDVIRTUAL1R(uint64_t, _set_swapchain_create_info_and_get_next_pointer, GDExtensionPtr<void>);
GDVIRTUAL2R(uint64_t, _set_hand_joint_locations_and_get_next_pointer, int, GDExtensionPtr<void>);
- GDVIRTUAL0R(uint64_t, _get_composition_layer);
+ GDVIRTUAL0R(int, _get_composition_layer_count);
+ GDVIRTUAL1R(uint64_t, _get_composition_layer, int);
+ GDVIRTUAL1R(int, _get_composition_layer_order, int);
virtual PackedStringArray get_suggested_tracker_names() override;
diff --git a/modules/openxr/openxr_api.cpp b/modules/openxr/openxr_api.cpp
index e978c012b5..8dd017c213 100644
--- a/modules/openxr/openxr_api.cpp
+++ b/modules/openxr/openxr_api.cpp
@@ -2080,18 +2080,29 @@ void OpenXRAPI::end_frame() {
projection_views[eye].pose = views[eye].pose;
}
- Vector<const XrCompositionLayerBaseHeader *> layers_list;
+ Vector<OrderedCompositionLayer> ordered_layers_list;
+ bool projection_layer_is_first = true;
// Add composition layers from providers
for (OpenXRCompositionLayerProvider *provider : composition_layer_providers) {
- XrCompositionLayerBaseHeader *layer = provider->get_composition_layer();
- if (layer) {
- layers_list.push_back(layer);
+ for (int i = 0; i < provider->get_composition_layer_count(); i++) {
+ OrderedCompositionLayer layer = {
+ provider->get_composition_layer(i),
+ provider->get_composition_layer_order(i),
+ };
+ if (layer.composition_layer) {
+ ordered_layers_list.push_back(layer);
+ if (layer.sort_order == 0) {
+ WARN_PRINT_ONCE_ED("Composition layer returned sort order 0, it may be overwritten by projection layer.");
+ } else if (layer.sort_order < 0) {
+ projection_layer_is_first = false;
+ }
+ }
}
}
XrCompositionLayerFlags layer_flags = XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT;
- if (layers_list.size() > 0 || environment_blend_mode != XR_ENVIRONMENT_BLEND_MODE_OPAQUE) {
+ if (!projection_layer_is_first || environment_blend_mode != XR_ENVIRONMENT_BLEND_MODE_OPAQUE) {
layer_flags |= XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT;
}
@@ -2103,7 +2114,16 @@ void OpenXRAPI::end_frame() {
view_count, // viewCount
projection_views, // views
};
- layers_list.push_back((const XrCompositionLayerBaseHeader *)&projection_layer);
+ ordered_layers_list.push_back({ (const XrCompositionLayerBaseHeader *)&projection_layer, 0 });
+
+ // Sort our layers.
+ ordered_layers_list.sort_custom<OrderedCompositionLayer>();
+
+ // Now make a list we can pass on to OpenXR.
+ Vector<const XrCompositionLayerBaseHeader *> layers_list;
+ for (OrderedCompositionLayer &ordered_layer : ordered_layers_list) {
+ layers_list.push_back(ordered_layer.composition_layer);
+ }
XrFrameEndInfo frame_end_info = {
XR_TYPE_FRAME_END_INFO, // type
diff --git a/modules/openxr/openxr_api.h b/modules/openxr/openxr_api.h
index e1a04a0796..7ec622364b 100644
--- a/modules/openxr/openxr_api.h
+++ b/modules/openxr/openxr_api.h
@@ -287,6 +287,15 @@ private:
RID get_interaction_profile_rid(XrPath p_path);
XrPath get_interaction_profile_path(RID p_interaction_profile);
+ struct OrderedCompositionLayer {
+ const XrCompositionLayerBaseHeader *composition_layer;
+ int sort_order;
+
+ _FORCE_INLINE_ bool operator()(const OrderedCompositionLayer &a, const OrderedCompositionLayer &b) const {
+ return a.sort_order < b.sort_order || (a.sort_order == b.sort_order && uint64_t(a.composition_layer) < uint64_t(b.composition_layer));
+ }
+ };
+
// state changes
bool poll_events();
bool on_state_idle();
diff --git a/modules/websocket/packet_buffer.h b/modules/websocket/packet_buffer.h
index 25e1b1f15a..f98ee12ef9 100644
--- a/modules/websocket/packet_buffer.h
+++ b/modules/websocket/packet_buffer.h
@@ -33,7 +33,7 @@
#include "core/templates/ring_buffer.h"
-template <class T>
+template <typename T>
class PacketBuffer {
private:
typedef struct {
diff --git a/platform/macos/native_menu_macos.h b/platform/macos/native_menu_macos.h
index e0e15df832..c00a510fd5 100644
--- a/platform/macos/native_menu_macos.h
+++ b/platform/macos/native_menu_macos.h
@@ -88,6 +88,7 @@ public:
virtual Size2 get_size(const RID &p_rid) const override;
virtual void popup(const RID &p_rid, const Vector2i &p_position) override;
+ virtual void set_interface_direction(const RID &p_rid, bool p_is_rtl) override;
virtual void set_popup_open_callback(const RID &p_rid, const Callable &p_callback) override;
virtual Callable get_popup_open_callback(const RID &p_rid) const override;
virtual void set_popup_close_callback(const RID &p_rid, const Callable &p_callback) override;
diff --git a/platform/macos/native_menu_macos.mm b/platform/macos/native_menu_macos.mm
index cb88f94a28..f00527767c 100644
--- a/platform/macos/native_menu_macos.mm
+++ b/platform/macos/native_menu_macos.mm
@@ -181,6 +181,9 @@ bool NativeMenuMacOS::has_feature(Feature p_feature) const {
switch (p_feature) {
case FEATURE_GLOBAL_MENU:
case FEATURE_POPUP_MENU:
+ case FEATURE_OPEN_CLOSE_CALLBACK:
+ case FEATURE_HOVER_CALLBACK:
+ case FEATURE_KEY_CALLBACK:
return true;
default:
return false;
@@ -264,6 +267,13 @@ void NativeMenuMacOS::popup(const RID &p_rid, const Vector2i &p_position) {
}
}
+void NativeMenuMacOS::set_interface_direction(const RID &p_rid, bool p_is_rtl) {
+ MenuData *md = menus.get_or_null(p_rid);
+ ERR_FAIL_NULL(md);
+
+ md->menu.userInterfaceLayoutDirection = p_is_rtl ? NSUserInterfaceLayoutDirectionLeftToRight : NSUserInterfaceLayoutDirectionRightToLeft;
+}
+
void NativeMenuMacOS::set_popup_open_callback(const RID &p_rid, const Callable &p_callback) {
MenuData *md = menus.get_or_null(p_rid);
ERR_FAIL_NULL(md);
diff --git a/platform/windows/SCsub b/platform/windows/SCsub
index 18c5878a1a..cf6416b8da 100644
--- a/platform/windows/SCsub
+++ b/platform/windows/SCsub
@@ -17,6 +17,7 @@ common_win = [
"joypad_windows.cpp",
"tts_windows.cpp",
"windows_terminal_logger.cpp",
+ "native_menu_windows.cpp",
"gl_manager_windows_native.cpp",
"gl_manager_windows_angle.cpp",
"wgl_detect_version.cpp",
diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp
index 14718d8838..2093f552ce 100644
--- a/platform/windows/display_server_windows.cpp
+++ b/platform/windows/display_server_windows.cpp
@@ -3664,6 +3664,9 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
// Process window messages.
switch (uMsg) {
+ case WM_MENUCOMMAND: {
+ native_menu->_menu_activate(HMENU(lParam), (int)wParam);
+ } break;
case WM_CREATE: {
if (is_dark_mode_supported() && dark_title_available) {
BOOL value = is_dark_mode();
@@ -5468,7 +5471,7 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
if (tts_enabled) {
tts = memnew(TTS_Windows);
}
- native_menu = memnew(NativeMenu);
+ native_menu = memnew(NativeMenuWindows);
// Enforce default keep screen on value.
screen_set_keep_on(GLOBAL_GET("display/window/energy_saving/keep_screen_on"));
diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h
index cc5099cbb4..910b9baa45 100644
--- a/platform/windows/display_server_windows.h
+++ b/platform/windows/display_server_windows.h
@@ -61,6 +61,8 @@
#include "gl_manager_windows_native.h"
#endif // GLES3_ENABLED
+#include "native_menu_windows.h"
+
#include <io.h>
#include <stdio.h>
@@ -358,7 +360,7 @@ class DisplayServerWindows : public DisplayServer {
HANDLE power_request;
TTS_Windows *tts = nullptr;
- NativeMenu *native_menu = nullptr;
+ NativeMenuWindows *native_menu = nullptr;
struct WindowData {
HWND hWnd;
diff --git a/platform/windows/native_menu_windows.cpp b/platform/windows/native_menu_windows.cpp
new file mode 100644
index 0000000000..eea30cab9a
--- /dev/null
+++ b/platform/windows/native_menu_windows.cpp
@@ -0,0 +1,1149 @@
+/**************************************************************************/
+/* native_menu_windows.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* 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 "native_menu_windows.h"
+
+#include "display_server_windows.h"
+
+#include "scene/resources/image_texture.h"
+
+HBITMAP NativeMenuWindows::_make_bitmap(const Ref<Image> &p_img) const {
+ Vector2i texture_size = p_img->get_size();
+ UINT image_size = texture_size.width * texture_size.height;
+
+ COLORREF *buffer = nullptr;
+
+ BITMAPV5HEADER bi;
+ ZeroMemory(&bi, sizeof(bi));
+ bi.bV5Size = sizeof(bi);
+ bi.bV5Width = texture_size.width;
+ bi.bV5Height = -texture_size.height;
+ bi.bV5Planes = 1;
+ bi.bV5BitCount = 32;
+ bi.bV5Compression = BI_BITFIELDS;
+ bi.bV5RedMask = 0x00ff0000;
+ bi.bV5GreenMask = 0x0000ff00;
+ bi.bV5BlueMask = 0x000000ff;
+ bi.bV5AlphaMask = 0xff000000;
+
+ HDC dc = GetDC(nullptr);
+ HBITMAP bitmap = CreateDIBSection(dc, reinterpret_cast<BITMAPINFO *>(&bi), DIB_RGB_COLORS, reinterpret_cast<void **>(&buffer), nullptr, 0);
+ for (UINT index = 0; index < image_size; index++) {
+ int row_index = floor(index / texture_size.width);
+ int column_index = (index % int(texture_size.width));
+ const Color &c = p_img->get_pixel(column_index, row_index);
+ *(buffer + index) = c.to_argb32();
+ }
+ ReleaseDC(nullptr, dc);
+
+ return bitmap;
+}
+
+void NativeMenuWindows::_menu_activate(HMENU p_menu, int p_index) const {
+ if (menu_lookup.has(p_menu)) {
+ MenuData *md = menus.get_or_null(menu_lookup[p_menu]);
+ if (md) {
+ int count = GetMenuItemCount(md->menu);
+ if (p_index >= 0 && p_index < count) {
+ MENUITEMINFOW item;
+ ZeroMemory(&item, sizeof(item));
+ item.cbSize = sizeof(item);
+ item.fMask = MIIM_STATE | MIIM_DATA;
+ if (GetMenuItemInfoW(md->menu, p_index, true, &item)) {
+ MenuItemData *item_data = (MenuItemData *)item.dwItemData;
+ if (item_data) {
+ if (item_data->max_states > 0) {
+ item_data->state++;
+ if (item_data->state >= item_data->max_states) {
+ item_data->state = 0;
+ }
+ }
+
+ if (item_data->checkable_type == CHECKABLE_TYPE_CHECK_BOX) {
+ if ((item.fState & MFS_CHECKED) == MFS_CHECKED) {
+ item.fState &= ~MFS_CHECKED;
+ } else {
+ item.fState |= MFS_CHECKED;
+ }
+ SetMenuItemInfoW(md->menu, p_index, true, &item);
+ }
+
+ if (item_data->callback.is_valid()) {
+ Variant ret;
+ Callable::CallError ce;
+ const Variant *args[1] = { &item_data->meta };
+
+ item_data->callback.callp(args, 1, ret, ce);
+ if (ce.error != Callable::CallError::CALL_OK) {
+ ERR_PRINT(vformat("Failed to execute menu callback: %s.", Variant::get_callable_error_text(item_data->callback, args, 1, ce)));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+bool NativeMenuWindows::has_feature(Feature p_feature) const {
+ switch (p_feature) {
+ // case FEATURE_GLOBAL_MENU:
+ // case FEATURE_OPEN_CLOSE_CALLBACK:
+ // case FEATURE_HOVER_CALLBACK:
+ // case FEATURE_KEY_CALLBACK:
+ case FEATURE_POPUP_MENU:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool NativeMenuWindows::has_system_menu(SystemMenus p_menu_id) const {
+ return false;
+}
+
+RID NativeMenuWindows::get_system_menu(SystemMenus p_menu_id) const {
+ return RID();
+}
+
+RID NativeMenuWindows::create_menu() {
+ MenuData *md = memnew(MenuData);
+ md->menu = CreatePopupMenu();
+
+ MENUINFO menu_info;
+ ZeroMemory(&menu_info, sizeof(menu_info));
+ menu_info.cbSize = sizeof(menu_info);
+ menu_info.fMask = MIM_STYLE;
+ menu_info.dwStyle = MNS_NOTIFYBYPOS | MNS_MODELESS;
+ SetMenuInfo(md->menu, &menu_info);
+
+ RID rid = menus.make_rid(md);
+ menu_lookup[md->menu] = rid;
+ return rid;
+}
+
+bool NativeMenuWindows::has_menu(const RID &p_rid) const {
+ return menus.owns(p_rid);
+}
+
+void NativeMenuWindows::free_menu(const RID &p_rid) {
+ MenuData *md = menus.get_or_null(p_rid);
+ if (md) {
+ clear(p_rid);
+ DestroyMenu(md->menu);
+ menus.free(p_rid);
+ menu_lookup.erase(md->menu);
+ memdelete(md);
+ }
+}
+
+Size2 NativeMenuWindows::get_size(const RID &p_rid) const {
+ const MenuData *md = menus.get_or_null(p_rid);
+ ERR_FAIL_NULL_V(md, Size2());
+
+ Size2 size;
+ int count = GetMenuItemCount(md->menu);
+ for (int i = 0; i < count; i++) {
+ RECT rect;
+ if (GetMenuItemRect(NULL, md->menu, i, &rect)) {
+ size.x = MAX(size.x, rect.right - rect.left);
+ size.y += rect.bottom - rect.top;
+ }
+ }
+ return size;
+}
+
+void NativeMenuWindows::popup(const RID &p_rid, const Vector2i &p_position) {
+ const MenuData *md = menus.get_or_null(p_rid);
+ ERR_FAIL_NULL(md);
+
+ HWND hwnd = (HWND)DisplayServer::get_singleton()->window_get_native_handle(DisplayServer::WINDOW_HANDLE, DisplayServer::MAIN_WINDOW_ID);
+ UINT flags = TPM_HORIZONTAL | TPM_LEFTALIGN | TPM_TOPALIGN | TPM_LEFTBUTTON | TPM_VERPOSANIMATION;
+ if (md->is_rtl) {
+ flags |= TPM_LAYOUTRTL;
+ }
+ TrackPopupMenuEx(md->menu, flags, p_position.x, p_position.y, hwnd, nullptr);
+}
+
+void NativeMenuWindows::set_interface_direction(const RID &p_rid, bool p_is_rtl) {
+ MenuData *md = menus.get_or_null(p_rid);
+ ERR_FAIL_NULL(md);
+
+ if (md->is_rtl == p_is_rtl) {
+ return;
+ }
+ md->is_rtl = p_is_rtl;
+}
+
+void NativeMenuWindows::set_popup_open_callback(const RID &p_rid, const Callable &p_callback) {
+ // Not supported.
+}
+
+Callable NativeMenuWindows::get_popup_open_callback(const RID &p_rid) const {
+ // Not supported.
+ return Callable();
+}
+
+void NativeMenuWindows::set_popup_close_callback(const RID &p_rid, const Callable &p_callback) {
+ // Not supported.
+}
+
+Callable NativeMenuWindows::get_popup_close_callback(const RID &p_rid) const {
+ // Not supported.
+ return Callable();
+}
+
+void NativeMenuWindows::set_minimum_width(const RID &p_rid, float p_width) {
+ // Not supported.
+}
+
+float NativeMenuWindows::get_minimum_width(const RID &p_rid) const {
+ // Not supported.
+ return 0.f;
+}
+
+int NativeMenuWindows::add_submenu_item(const RID &p_rid, const String &p_label, const RID &p_submenu_rid, const Variant &p_tag, int p_index) {
+ MenuData *md = menus.get_or_null(p_rid);
+ MenuData *md_sub = menus.get_or_null(p_submenu_rid);
+ ERR_FAIL_NULL_V(md, -1);
+ ERR_FAIL_NULL_V(md_sub, -1);
+ ERR_FAIL_COND_V_MSG(md->menu == md_sub->menu, -1, "Can't set submenu to self!");
+
+ if (p_index == -1) {
+ p_index = GetMenuItemCount(md->menu);
+ } else {
+ p_index = CLAMP(p_index, 0, GetMenuItemCount(md->menu));
+ }
+
+ MenuItemData *item_data = memnew(MenuItemData);
+ item_data->meta = p_tag;
+ item_data->checkable_type = CHECKABLE_TYPE_NONE;
+ item_data->max_states = 0;
+ item_data->state = 0;
+
+ Char16String label = p_label.utf16();
+ MENUITEMINFOW item;
+ ZeroMemory(&item, sizeof(item));
+ item.cbSize = sizeof(item);
+ item.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_DATA | MIIM_SUBMENU;
+ item.fType = MFT_STRING;
+ item.hSubMenu = md_sub->menu;
+ item.dwItemData = (ULONG_PTR)item_data;
+ item.dwTypeData = (LPWSTR)label.ptrw();
+
+ if (!InsertMenuItemW(md->menu, p_index, true, &item)) {
+ memdelete(item_data);
+ return -1;
+ }
+ return p_index;
+}
+
+int NativeMenuWindows::add_item(const RID &p_rid, const String &p_label, const Callable &p_callback, const Callable &p_key_callback, const Variant &p_tag, Key p_accel, int p_index) {
+ const MenuData *md = menus.get_or_null(p_rid);
+ ERR_FAIL_NULL_V(md, -1);
+
+ if (p_index == -1) {
+ p_index = GetMenuItemCount(md->menu);
+ } else {
+ p_index = CLAMP(p_index, 0, GetMenuItemCount(md->menu));
+ }
+
+ MenuItemData *item_data = memnew(MenuItemData);
+ item_data->callback = p_callback;
+ item_data->meta = p_tag;
+ item_data->checkable_type = CHECKABLE_TYPE_NONE;
+ item_data->max_states = 0;
+ item_data->state = 0;
+
+ Char16String label = p_label.utf16();
+ MENUITEMINFOW item;
+ ZeroMemory(&item, sizeof(item));
+ item.cbSize = sizeof(item);
+ item.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_DATA;
+ item.fType = MFT_STRING;
+ item.dwItemData = (ULONG_PTR)item_data;
+ item.dwTypeData = (LPWSTR)label.ptrw();
+
+ if (!InsertMenuItemW(md->menu, p_index, true, &item)) {
+ memdelete(item_data);
+ return -1;
+ }
+ return p_index;
+}
+
+int NativeMenuWindows::add_check_item(const RID &p_rid, const String &p_label, const Callable &p_callback, const Callable &p_key_callback, const Variant &p_tag, Key p_accel, int p_index) {
+ const MenuData *md = menus.get_or_null(p_rid);
+ ERR_FAIL_NULL_V(md, -1);
+
+ if (p_index == -1) {
+ p_index = GetMenuItemCount(md->menu);
+ } else {
+ p_index = CLAMP(p_index, 0, GetMenuItemCount(md->menu));
+ }
+
+ MenuItemData *item_data = memnew(MenuItemData);
+ item_data->callback = p_callback;
+ item_data->meta = p_tag;
+ item_data->checkable_type = CHECKABLE_TYPE_CHECK_BOX;
+ item_data->max_states = 0;
+ item_data->state = 0;
+
+ Char16String label = p_label.utf16();
+ MENUITEMINFOW item;
+ ZeroMemory(&item, sizeof(item));
+ item.cbSize = sizeof(item);
+ item.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_DATA;
+ item.fType = MFT_STRING;
+ item.dwItemData = (ULONG_PTR)item_data;
+ item.dwTypeData = (LPWSTR)label.ptrw();
+
+ if (!InsertMenuItemW(md->menu, p_index, true, &item)) {
+ memdelete(item_data);
+ return -1;
+ }
+ return p_index;
+}
+
+int NativeMenuWindows::add_icon_item(const RID &p_rid, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Callable &p_key_callback, const Variant &p_tag, Key p_accel, int p_index) {
+ const MenuData *md = menus.get_or_null(p_rid);
+ ERR_FAIL_NULL_V(md, -1);
+
+ if (p_index == -1) {
+ p_index = GetMenuItemCount(md->menu);
+ } else {
+ p_index = CLAMP(p_index, 0, GetMenuItemCount(md->menu));
+ }
+
+ MenuItemData *item_data = memnew(MenuItemData);
+ item_data->callback = p_callback;
+ item_data->meta = p_tag;
+ item_data->checkable_type = CHECKABLE_TYPE_NONE;
+ item_data->max_states = 0;
+ item_data->state = 0;
+ item_data->img = p_icon->get_image();
+ item_data->img = item_data->img->duplicate();
+ if (item_data->img->is_compressed()) {
+ item_data->img->decompress();
+ }
+ item_data->bmp = _make_bitmap(item_data->img);
+
+ Char16String label = p_label.utf16();
+ MENUITEMINFOW item;
+ ZeroMemory(&item, sizeof(item));
+ item.cbSize = sizeof(item);
+ item.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_DATA | MIIM_BITMAP;
+ item.fType = MFT_STRING;
+ item.dwItemData = (ULONG_PTR)item_data;
+ item.dwTypeData = (LPWSTR)label.ptrw();
+ item.hbmpItem = item_data->bmp;
+
+ if (!InsertMenuItemW(md->menu, p_index, true, &item)) {
+ memdelete(item_data);
+ return -1;
+ }
+ return p_index;
+}
+
+int NativeMenuWindows::add_icon_check_item(const RID &p_rid, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Callable &p_key_callback, const Variant &p_tag, Key p_accel, int p_index) {
+ const MenuData *md = menus.get_or_null(p_rid);
+ ERR_FAIL_NULL_V(md, -1);
+
+ if (p_index == -1) {
+ p_index = GetMenuItemCount(md->menu);
+ } else {
+ p_index = CLAMP(p_index, 0, GetMenuItemCount(md->menu));
+ }
+
+ MenuItemData *item_data = memnew(MenuItemData);
+ item_data->callback = p_callback;
+ item_data->meta = p_tag;
+ item_data->checkable_type = CHECKABLE_TYPE_CHECK_BOX;
+ item_data->max_states = 0;
+ item_data->state = 0;
+ item_data->img = p_icon->get_image();
+ item_data->img = item_data->img->duplicate();
+ if (item_data->img->is_compressed()) {
+ item_data->img->decompress();
+ }
+ item_data->bmp = _make_bitmap(item_data->img);
+
+ Char16String label = p_label.utf16();
+ MENUITEMINFOW item;
+ ZeroMemory(&item, sizeof(item));
+ item.cbSize = sizeof(item);
+ item.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_DATA | MIIM_BITMAP;
+ item.fType = MFT_STRING;
+ item.dwItemData = (ULONG_PTR)item_data;
+ item.dwTypeData = (LPWSTR)label.ptrw();
+ item.hbmpItem = item_data->bmp;
+
+ if (!InsertMenuItemW(md->menu, p_index, true, &item)) {
+ memdelete(item_data);
+ return -1;
+ }
+ return p_index;
+}
+
+int NativeMenuWindows::add_radio_check_item(const RID &p_rid, const String &p_label, const Callable &p_callback, const Callable &p_key_callback, const Variant &p_tag, Key p_accel, int p_index) {
+ const MenuData *md = menus.get_or_null(p_rid);
+ ERR_FAIL_NULL_V(md, -1);
+
+ if (p_index == -1) {
+ p_index = GetMenuItemCount(md->menu);
+ } else {
+ p_index = CLAMP(p_index, 0, GetMenuItemCount(md->menu));
+ }
+
+ MenuItemData *item_data = memnew(MenuItemData);
+ item_data->callback = p_callback;
+ item_data->meta = p_tag;
+ item_data->checkable_type = CHECKABLE_TYPE_RADIO_BUTTON;
+ item_data->max_states = 0;
+ item_data->state = 0;
+
+ Char16String label = p_label.utf16();
+ MENUITEMINFOW item;
+ ZeroMemory(&item, sizeof(item));
+ item.cbSize = sizeof(item);
+ item.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_DATA;
+ item.fType = MFT_STRING | MFT_RADIOCHECK;
+ item.dwItemData = (ULONG_PTR)item_data;
+ item.dwTypeData = (LPWSTR)label.ptrw();
+
+ if (!InsertMenuItemW(md->menu, p_index, true, &item)) {
+ memdelete(item_data);
+ return -1;
+ }
+ return p_index;
+}
+
+int NativeMenuWindows::add_icon_radio_check_item(const RID &p_rid, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Callable &p_key_callback, const Variant &p_tag, Key p_accel, int p_index) {
+ const MenuData *md = menus.get_or_null(p_rid);
+ ERR_FAIL_NULL_V(md, -1);
+
+ if (p_index == -1) {
+ p_index = GetMenuItemCount(md->menu);
+ } else {
+ p_index = CLAMP(p_index, 0, GetMenuItemCount(md->menu));
+ }
+
+ MenuItemData *item_data = memnew(MenuItemData);
+ item_data->callback = p_callback;
+ item_data->meta = p_tag;
+ item_data->checkable_type = CHECKABLE_TYPE_RADIO_BUTTON;
+ item_data->max_states = 0;
+ item_data->state = 0;
+ item_data->img = p_icon->get_image();
+ item_data->img = item_data->img->duplicate();
+ if (item_data->img->is_compressed()) {
+ item_data->img->decompress();
+ }
+ item_data->bmp = _make_bitmap(item_data->img);
+
+ Char16String label = p_label.utf16();
+ MENUITEMINFOW item;
+ ZeroMemory(&item, sizeof(item));
+ item.cbSize = sizeof(item);
+ item.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_DATA | MIIM_BITMAP;
+ item.fType = MFT_STRING | MFT_RADIOCHECK;
+ item.dwItemData = (ULONG_PTR)item_data;
+ item.dwTypeData = (LPWSTR)label.ptrw();
+ item.hbmpItem = item_data->bmp;
+
+ if (!InsertMenuItemW(md->menu, p_index, true, &item)) {
+ memdelete(item_data);
+ return -1;
+ }
+ return p_index;
+}
+
+int NativeMenuWindows::add_multistate_item(const RID &p_rid, const String &p_label, int p_max_states, int p_default_state, const Callable &p_callback, const Callable &p_key_callback, const Variant &p_tag, Key p_accel, int p_index) {
+ const MenuData *md = menus.get_or_null(p_rid);
+ ERR_FAIL_NULL_V(md, -1);
+
+ if (p_index == -1) {
+ p_index = GetMenuItemCount(md->menu);
+ } else {
+ p_index = CLAMP(p_index, 0, GetMenuItemCount(md->menu));
+ }
+
+ MenuItemData *item_data = memnew(MenuItemData);
+ item_data->callback = p_callback;
+ item_data->meta = p_tag;
+ item_data->checkable_type = CHECKABLE_TYPE_NONE;
+ item_data->max_states = p_max_states;
+ item_data->state = p_default_state;
+
+ Char16String label = p_label.utf16();
+ MENUITEMINFOW item;
+ ZeroMemory(&item, sizeof(item));
+ item.cbSize = sizeof(item);
+ item.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_DATA;
+ item.fType = MFT_STRING;
+ item.dwItemData = (ULONG_PTR)item_data;
+ item.dwTypeData = (LPWSTR)label.ptrw();
+
+ if (!InsertMenuItemW(md->menu, p_index, true, &item)) {
+ memdelete(item_data);
+ return -1;
+ }
+ return p_index;
+}
+
+int NativeMenuWindows::add_separator(const RID &p_rid, int p_index) {
+ const MenuData *md = menus.get_or_null(p_rid);
+ ERR_FAIL_NULL_V(md, -1);
+
+ if (p_index == -1) {
+ p_index = GetMenuItemCount(md->menu);
+ } else {
+ p_index = CLAMP(p_index, 0, GetMenuItemCount(md->menu));
+ }
+
+ MenuItemData *item_data = memnew(MenuItemData);
+ item_data->checkable_type = CHECKABLE_TYPE_NONE;
+ item_data->max_states = 0;
+ item_data->state = 0;
+
+ MENUITEMINFOW item;
+ ZeroMemory(&item, sizeof(item));
+ item.cbSize = sizeof(item);
+ item.fMask = MIIM_FTYPE | MIIM_DATA;
+ item.fType = MFT_SEPARATOR;
+ item.dwItemData = (ULONG_PTR)item_data;
+
+ if (!InsertMenuItemW(md->menu, p_index, true, &item)) {
+ memdelete(item_data);
+ return -1;
+ }
+ return p_index;
+}
+
+int NativeMenuWindows::find_item_index_with_text(const RID &p_rid, const String &p_text) const {
+ const MenuData *md = menus.get_or_null(p_rid);
+ ERR_FAIL_NULL_V(md, -1);
+
+ MENUITEMINFOW item;
+ int count = GetMenuItemCount(md->menu);
+ for (int i = 0; i < count; i++) {
+ ZeroMemory(&item, sizeof(item));
+ item.cbSize = sizeof(item);
+ item.fMask = MIIM_STRING;
+ if (GetMenuItemInfoW(md->menu, i, true, &item)) {
+ if (String::utf16((const char16_t *)item.dwTypeData) == p_text) {
+ return i;
+ }
+ }
+ }
+ return -1;
+}
+
+int NativeMenuWindows::find_item_index_with_tag(const RID &p_rid, const Variant &p_tag) const {
+ const MenuData *md = menus.get_or_null(p_rid);
+ ERR_FAIL_NULL_V(md, -1);
+
+ MENUITEMINFOW item;
+ int count = GetMenuItemCount(md->menu);
+ for (int i = 0; i < count; i++) {
+ ZeroMemory(&item, sizeof(item));
+ item.cbSize = sizeof(item);
+ item.fMask = MIIM_DATA;
+ if (GetMenuItemInfoW(md->menu, i, true, &item)) {
+ MenuItemData *item_data = (MenuItemData *)item.dwItemData;
+ if (item_data) {
+ if (item_data->meta == p_tag) {
+ return i;
+ }
+ }
+ }
+ }
+ return -1;
+}
+
+bool NativeMenuWindows::is_item_checked(const RID &p_rid, int p_idx) const {
+ ERR_FAIL_COND_V(p_idx < 0, false);
+ const MenuData *md = menus.get_or_null(p_rid);
+ ERR_FAIL_NULL_V(md, false);
+ int count = GetMenuItemCount(md->menu);
+ ERR_FAIL_COND_V(p_idx >= count, false);
+
+ MENUITEMINFOW item;
+ ZeroMemory(&item, sizeof(item));
+ item.cbSize = sizeof(item);
+ item.fMask = MIIM_STATE;
+ if (GetMenuItemInfoW(md->menu, p_idx, true, &item)) {
+ return (item.fState & MFS_CHECKED) == MFS_CHECKED;
+ }
+ return false;
+}
+
+bool NativeMenuWindows::is_item_checkable(const RID &p_rid, int p_idx) const {
+ ERR_FAIL_COND_V(p_idx < 0, false);
+ const MenuData *md = menus.get_or_null(p_rid);
+ ERR_FAIL_NULL_V(md, false);
+ int count = GetMenuItemCount(md->menu);
+ ERR_FAIL_COND_V(p_idx >= count, false);
+
+ MENUITEMINFOW item;
+ ZeroMemory(&item, sizeof(item));
+ item.cbSize = sizeof(item);
+ item.fMask = MIIM_DATA;
+ if (GetMenuItemInfoW(md->menu, p_idx, true, &item)) {
+ MenuItemData *item_data = (MenuItemData *)item.dwItemData;
+ if (item_data) {
+ return item_data->checkable_type == CHECKABLE_TYPE_CHECK_BOX;
+ }
+ }
+ return false;
+}
+
+bool NativeMenuWindows::is_item_radio_checkable(const RID &p_rid, int p_idx) const {
+ ERR_FAIL_COND_V(p_idx < 0, false);
+ const MenuData *md = menus.get_or_null(p_rid);
+ ERR_FAIL_NULL_V(md, false);
+ int count = GetMenuItemCount(md->menu);
+ ERR_FAIL_COND_V(p_idx >= count, false);
+
+ MENUITEMINFOW item;
+ ZeroMemory(&item, sizeof(item));
+ item.cbSize = sizeof(item);
+ item.fMask = MIIM_DATA;
+ if (GetMenuItemInfoW(md->menu, p_idx, true, &item)) {
+ MenuItemData *item_data = (MenuItemData *)item.dwItemData;
+ if (item_data) {
+ return item_data->checkable_type == CHECKABLE_TYPE_RADIO_BUTTON;
+ }
+ }
+ return false;
+}
+
+Callable NativeMenuWindows::get_item_callback(const RID &p_rid, int p_idx) const {
+ ERR_FAIL_COND_V(p_idx < 0, Callable());
+ const MenuData *md = menus.get_or_null(p_rid);
+ ERR_FAIL_NULL_V(md, Callable());
+ int count = GetMenuItemCount(md->menu);
+ ERR_FAIL_COND_V(p_idx >= count, Callable());
+
+ MENUITEMINFOW item;
+ ZeroMemory(&item, sizeof(item));
+ item.cbSize = sizeof(item);
+ item.fMask = MIIM_DATA;
+ if (GetMenuItemInfoW(md->menu, p_idx, true, &item)) {
+ MenuItemData *item_data = (MenuItemData *)item.dwItemData;
+ if (item_data) {
+ return item_data->callback;
+ }
+ }
+ return Callable();
+}
+
+Callable NativeMenuWindows::get_item_key_callback(const RID &p_rid, int p_idx) const {
+ // Not supported.
+ return Callable();
+}
+
+Variant NativeMenuWindows::get_item_tag(const RID &p_rid, int p_idx) const {
+ ERR_FAIL_COND_V(p_idx < 0, Variant());
+ const MenuData *md = menus.get_or_null(p_rid);
+ ERR_FAIL_NULL_V(md, Variant());
+ int count = GetMenuItemCount(md->menu);
+ ERR_FAIL_COND_V(p_idx >= count, Variant());
+
+ MENUITEMINFOW item;
+ ZeroMemory(&item, sizeof(item));
+ item.cbSize = sizeof(item);
+ item.fMask = MIIM_DATA;
+ if (GetMenuItemInfoW(md->menu, p_idx, true, &item)) {
+ MenuItemData *item_data = (MenuItemData *)item.dwItemData;
+ if (item_data) {
+ return item_data->meta;
+ }
+ }
+ return Variant();
+}
+
+String NativeMenuWindows::get_item_text(const RID &p_rid, int p_idx) const {
+ ERR_FAIL_COND_V(p_idx < 0, String());
+ const MenuData *md = menus.get_or_null(p_rid);
+ ERR_FAIL_NULL_V(md, String());
+ int count = GetMenuItemCount(md->menu);
+ ERR_FAIL_COND_V(p_idx >= count, String());
+
+ MENUITEMINFOW item;
+ ZeroMemory(&item, sizeof(item));
+ item.cbSize = sizeof(item);
+ item.fMask = MIIM_STRING;
+ if (GetMenuItemInfoW(md->menu, p_idx, true, &item)) {
+ return String::utf16((const char16_t *)item.dwTypeData);
+ }
+ return String();
+}
+
+RID NativeMenuWindows::get_item_submenu(const RID &p_rid, int p_idx) const {
+ ERR_FAIL_COND_V(p_idx < 0, RID());
+ const MenuData *md = menus.get_or_null(p_rid);
+ ERR_FAIL_NULL_V(md, RID());
+ int count = GetMenuItemCount(md->menu);
+ ERR_FAIL_COND_V(p_idx >= count, RID());
+
+ MENUITEMINFOW item;
+ ZeroMemory(&item, sizeof(item));
+ item.cbSize = sizeof(item);
+ item.fMask = MIIM_SUBMENU;
+ if (GetMenuItemInfoW(md->menu, p_idx, true, &item)) {
+ if (menu_lookup.has(item.hSubMenu)) {
+ return menu_lookup[item.hSubMenu];
+ }
+ }
+ return RID();
+}
+
+Key NativeMenuWindows::get_item_accelerator(const RID &p_rid, int p_idx) const {
+ // Not supported.
+ return Key::NONE;
+}
+
+bool NativeMenuWindows::is_item_disabled(const RID &p_rid, int p_idx) const {
+ ERR_FAIL_COND_V(p_idx < 0, false);
+ const MenuData *md = menus.get_or_null(p_rid);
+ ERR_FAIL_NULL_V(md, false);
+ int count = GetMenuItemCount(md->menu);
+ ERR_FAIL_COND_V(p_idx >= count, false);
+
+ MENUITEMINFOW item;
+ ZeroMemory(&item, sizeof(item));
+ item.cbSize = sizeof(item);
+ item.fMask = MIIM_STATE;
+ if (GetMenuItemInfoW(md->menu, p_idx, true, &item)) {
+ return (item.fState & MFS_DISABLED) == MFS_DISABLED;
+ }
+ return false;
+}
+
+bool NativeMenuWindows::is_item_hidden(const RID &p_rid, int p_idx) const {
+ // Not supported.
+ return false;
+}
+
+String NativeMenuWindows::get_item_tooltip(const RID &p_rid, int p_idx) const {
+ // Not supported.
+ return String();
+}
+
+int NativeMenuWindows::get_item_state(const RID &p_rid, int p_idx) const {
+ ERR_FAIL_COND_V(p_idx < 0, -1);
+ const MenuData *md = menus.get_or_null(p_rid);
+ ERR_FAIL_NULL_V(md, -1);
+ int count = GetMenuItemCount(md->menu);
+ ERR_FAIL_COND_V(p_idx >= count, -1);
+
+ MENUITEMINFOW item;
+ ZeroMemory(&item, sizeof(item));
+ item.cbSize = sizeof(item);
+ item.fMask = MIIM_DATA;
+ if (GetMenuItemInfoW(md->menu, p_idx, true, &item)) {
+ MenuItemData *item_data = (MenuItemData *)item.dwItemData;
+ if (item_data) {
+ return item_data->state;
+ }
+ }
+ return -1;
+}
+
+int NativeMenuWindows::get_item_max_states(const RID &p_rid, int p_idx) const {
+ ERR_FAIL_COND_V(p_idx < 0, -1);
+ const MenuData *md = menus.get_or_null(p_rid);
+ ERR_FAIL_NULL_V(md, -1);
+ int count = GetMenuItemCount(md->menu);
+ ERR_FAIL_COND_V(p_idx >= count, -1);
+
+ MENUITEMINFOW item;
+ ZeroMemory(&item, sizeof(item));
+ item.cbSize = sizeof(item);
+ item.fMask = MIIM_DATA;
+ if (GetMenuItemInfoW(md->menu, p_idx, true, &item)) {
+ MenuItemData *item_data = (MenuItemData *)item.dwItemData;
+ if (item_data) {
+ return item_data->max_states;
+ }
+ }
+ return -1;
+}
+
+Ref<Texture2D> NativeMenuWindows::get_item_icon(const RID &p_rid, int p_idx) const {
+ ERR_FAIL_COND_V(p_idx < 0, Ref<Texture2D>());
+ const MenuData *md = menus.get_or_null(p_rid);
+ ERR_FAIL_NULL_V(md, Ref<Texture2D>());
+ int count = GetMenuItemCount(md->menu);
+ ERR_FAIL_COND_V(p_idx >= count, Ref<Texture2D>());
+
+ MENUITEMINFOW item;
+ ZeroMemory(&item, sizeof(item));
+ item.cbSize = sizeof(item);
+ item.fMask = MIIM_DATA;
+ if (GetMenuItemInfoW(md->menu, p_idx, true, &item)) {
+ MenuItemData *item_data = (MenuItemData *)item.dwItemData;
+ if (item_data) {
+ return ImageTexture::create_from_image(item_data->img);
+ }
+ }
+ return Ref<Texture2D>();
+}
+
+int NativeMenuWindows::get_item_indentation_level(const RID &p_rid, int p_idx) const {
+ // Not supported.
+ return 0;
+}
+
+void NativeMenuWindows::set_item_checked(const RID &p_rid, int p_idx, bool p_checked) {
+ ERR_FAIL_COND(p_idx < 0);
+ const MenuData *md = menus.get_or_null(p_rid);
+ ERR_FAIL_NULL(md);
+ int count = GetMenuItemCount(md->menu);
+ ERR_FAIL_COND(p_idx >= count);
+
+ MENUITEMINFOW item;
+ ZeroMemory(&item, sizeof(item));
+ item.cbSize = sizeof(item);
+ item.fMask = MIIM_STATE;
+ if (GetMenuItemInfoW(md->menu, p_idx, true, &item)) {
+ if (p_checked) {
+ item.fState |= MFS_CHECKED;
+ } else {
+ item.fState &= ~MFS_CHECKED;
+ }
+ SetMenuItemInfoW(md->menu, p_idx, true, &item);
+ }
+}
+
+void NativeMenuWindows::set_item_checkable(const RID &p_rid, int p_idx, bool p_checkable) {
+ ERR_FAIL_COND(p_idx < 0);
+ const MenuData *md = menus.get_or_null(p_rid);
+ ERR_FAIL_NULL(md);
+ int count = GetMenuItemCount(md->menu);
+ ERR_FAIL_COND(p_idx >= count);
+
+ MENUITEMINFOW item;
+ ZeroMemory(&item, sizeof(item));
+ item.cbSize = sizeof(item);
+ item.fMask = MIIM_FTYPE | MIIM_DATA;
+ if (GetMenuItemInfoW(md->menu, p_idx, true, &item)) {
+ MenuItemData *item_data = (MenuItemData *)item.dwItemData;
+ if (item_data) {
+ item.fType &= ~MFT_RADIOCHECK;
+ item_data->checkable_type = (p_checkable) ? CHECKABLE_TYPE_CHECK_BOX : CHECKABLE_TYPE_NONE;
+ SetMenuItemInfoW(md->menu, p_idx, true, &item);
+ }
+ }
+}
+
+void NativeMenuWindows::set_item_radio_checkable(const RID &p_rid, int p_idx, bool p_checkable) {
+ ERR_FAIL_COND(p_idx < 0);
+ const MenuData *md = menus.get_or_null(p_rid);
+ ERR_FAIL_NULL(md);
+ int count = GetMenuItemCount(md->menu);
+ ERR_FAIL_COND(p_idx >= count);
+
+ MENUITEMINFOW item;
+ ZeroMemory(&item, sizeof(item));
+ item.cbSize = sizeof(item);
+ item.fMask = MIIM_FTYPE | MIIM_DATA;
+ if (GetMenuItemInfoW(md->menu, p_idx, true, &item)) {
+ MenuItemData *item_data = (MenuItemData *)item.dwItemData;
+ if (item_data) {
+ if (p_checkable) {
+ item.fType |= MFT_RADIOCHECK;
+ item_data->checkable_type = CHECKABLE_TYPE_CHECK_BOX;
+ } else {
+ item.fType &= ~MFT_RADIOCHECK;
+ item_data->checkable_type = CHECKABLE_TYPE_NONE;
+ }
+ SetMenuItemInfoW(md->menu, p_idx, true, &item);
+ }
+ }
+}
+
+void NativeMenuWindows::set_item_callback(const RID &p_rid, int p_idx, const Callable &p_callback) {
+ ERR_FAIL_COND(p_idx < 0);
+ const MenuData *md = menus.get_or_null(p_rid);
+ ERR_FAIL_NULL(md);
+ int count = GetMenuItemCount(md->menu);
+ ERR_FAIL_COND(p_idx >= count);
+
+ MENUITEMINFOW item;
+ ZeroMemory(&item, sizeof(item));
+ item.cbSize = sizeof(item);
+ item.fMask = MIIM_DATA;
+ if (GetMenuItemInfoW(md->menu, p_idx, true, &item)) {
+ MenuItemData *item_data = (MenuItemData *)item.dwItemData;
+ if (item_data) {
+ item_data->callback = p_callback;
+ }
+ }
+}
+
+void NativeMenuWindows::set_item_key_callback(const RID &p_rid, int p_idx, const Callable &p_key_callback) {
+ // Not supported.
+}
+
+void NativeMenuWindows::set_item_hover_callbacks(const RID &p_rid, int p_idx, const Callable &p_callback) {
+ // Not supported.
+}
+
+void NativeMenuWindows::set_item_tag(const RID &p_rid, int p_idx, const Variant &p_tag) {
+ ERR_FAIL_COND(p_idx < 0);
+ const MenuData *md = menus.get_or_null(p_rid);
+ ERR_FAIL_NULL(md);
+ int count = GetMenuItemCount(md->menu);
+ ERR_FAIL_COND(p_idx >= count);
+
+ MENUITEMINFOW item;
+ ZeroMemory(&item, sizeof(item));
+ item.cbSize = sizeof(item);
+ item.fMask = MIIM_DATA;
+ if (GetMenuItemInfoW(md->menu, p_idx, true, &item)) {
+ MenuItemData *item_data = (MenuItemData *)item.dwItemData;
+ if (item_data) {
+ item_data->meta = p_tag;
+ }
+ }
+}
+
+void NativeMenuWindows::set_item_text(const RID &p_rid, int p_idx, const String &p_text) {
+ ERR_FAIL_COND(p_idx < 0);
+ const MenuData *md = menus.get_or_null(p_rid);
+ ERR_FAIL_NULL(md);
+ int count = GetMenuItemCount(md->menu);
+ ERR_FAIL_COND(p_idx >= count);
+
+ Char16String label = p_text.utf16();
+ MENUITEMINFOW item;
+ ZeroMemory(&item, sizeof(item));
+ item.cbSize = sizeof(item);
+ item.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_DATA;
+ if (GetMenuItemInfoW(md->menu, p_idx, true, &item)) {
+ item.dwTypeData = (LPWSTR)label.ptrw();
+ SetMenuItemInfoW(md->menu, p_idx, true, &item);
+ }
+}
+
+void NativeMenuWindows::set_item_submenu(const RID &p_rid, int p_idx, const RID &p_submenu_rid) {
+ ERR_FAIL_COND(p_idx < 0);
+ const MenuData *md = menus.get_or_null(p_rid);
+ ERR_FAIL_NULL(md);
+ int count = GetMenuItemCount(md->menu);
+ ERR_FAIL_COND(p_idx >= count);
+
+ MenuData *md_sub = menus.get_or_null(p_submenu_rid);
+ ERR_FAIL_COND_MSG(md->menu == md_sub->menu, "Can't set submenu to self!");
+
+ MENUITEMINFOW item;
+ ZeroMemory(&item, sizeof(item));
+ item.cbSize = sizeof(item);
+ item.fMask = MIIM_SUBMENU;
+ if (GetMenuItemInfoW(md->menu, p_idx, true, &item)) {
+ if (p_submenu_rid.is_valid()) {
+ item.hSubMenu = md_sub->menu;
+ } else {
+ item.hSubMenu = 0;
+ }
+ SetMenuItemInfoW(md->menu, p_idx, true, &item);
+ }
+}
+
+void NativeMenuWindows::set_item_accelerator(const RID &p_rid, int p_idx, Key p_keycode) {
+ // Not supported.
+}
+
+void NativeMenuWindows::set_item_disabled(const RID &p_rid, int p_idx, bool p_disabled) {
+ ERR_FAIL_COND(p_idx < 0);
+ const MenuData *md = menus.get_or_null(p_rid);
+ ERR_FAIL_NULL(md);
+ int count = GetMenuItemCount(md->menu);
+ ERR_FAIL_COND(p_idx >= count);
+
+ MENUITEMINFOW item;
+ ZeroMemory(&item, sizeof(item));
+ item.cbSize = sizeof(item);
+ item.fMask = MIIM_STATE;
+ if (GetMenuItemInfoW(md->menu, p_idx, true, &item)) {
+ if (p_disabled) {
+ item.fState |= MFS_DISABLED;
+ } else {
+ item.fState &= ~MFS_DISABLED;
+ }
+ SetMenuItemInfoW(md->menu, p_idx, true, &item);
+ }
+}
+
+void NativeMenuWindows::set_item_hidden(const RID &p_rid, int p_idx, bool p_hidden) {
+ // Not supported.
+}
+
+void NativeMenuWindows::set_item_tooltip(const RID &p_rid, int p_idx, const String &p_tooltip) {
+ // Not supported.
+}
+
+void NativeMenuWindows::set_item_state(const RID &p_rid, int p_idx, int p_state) {
+ ERR_FAIL_COND(p_idx < 0);
+ const MenuData *md = menus.get_or_null(p_rid);
+ ERR_FAIL_NULL(md);
+ int count = GetMenuItemCount(md->menu);
+ ERR_FAIL_COND(p_idx >= count);
+
+ MENUITEMINFOW item;
+ ZeroMemory(&item, sizeof(item));
+ item.cbSize = sizeof(item);
+ item.fMask = MIIM_DATA;
+ if (GetMenuItemInfoW(md->menu, p_idx, true, &item)) {
+ MenuItemData *item_data = (MenuItemData *)item.dwItemData;
+ if (item_data) {
+ item_data->state = p_state;
+ }
+ }
+}
+
+void NativeMenuWindows::set_item_max_states(const RID &p_rid, int p_idx, int p_max_states) {
+ ERR_FAIL_COND(p_idx < 0);
+ const MenuData *md = menus.get_or_null(p_rid);
+ ERR_FAIL_NULL(md);
+ int count = GetMenuItemCount(md->menu);
+ ERR_FAIL_COND(p_idx >= count);
+
+ MENUITEMINFOW item;
+ ZeroMemory(&item, sizeof(item));
+ item.cbSize = sizeof(item);
+ item.fMask = MIIM_DATA;
+ if (GetMenuItemInfoW(md->menu, p_idx, true, &item)) {
+ MenuItemData *item_data = (MenuItemData *)item.dwItemData;
+ if (item_data) {
+ item_data->max_states = p_max_states;
+ }
+ }
+}
+
+void NativeMenuWindows::set_item_icon(const RID &p_rid, int p_idx, const Ref<Texture2D> &p_icon) {
+ ERR_FAIL_COND(p_idx < 0);
+ const MenuData *md = menus.get_or_null(p_rid);
+ ERR_FAIL_NULL(md);
+ int count = GetMenuItemCount(md->menu);
+ ERR_FAIL_COND(p_idx >= count);
+
+ MENUITEMINFOW item;
+ ZeroMemory(&item, sizeof(item));
+ item.cbSize = sizeof(item);
+ item.fMask = MIIM_DATA | MIIM_BITMAP;
+ if (GetMenuItemInfoW(md->menu, p_idx, true, &item)) {
+ MenuItemData *item_data = (MenuItemData *)item.dwItemData;
+ if (item_data) {
+ if (item_data->bmp) {
+ DeleteObject(item_data->bmp);
+ }
+ if (p_icon.is_valid()) {
+ item_data->img = p_icon->get_image();
+ item_data->img = item_data->img->duplicate();
+ if (item_data->img->is_compressed()) {
+ item_data->img->decompress();
+ }
+ item_data->bmp = _make_bitmap(item_data->img);
+ } else {
+ item_data->img = Ref<Image>();
+ item_data->bmp = 0;
+ }
+ item.hbmpItem = item_data->bmp;
+ SetMenuItemInfoW(md->menu, p_idx, true, &item);
+ }
+ }
+}
+
+void NativeMenuWindows::set_item_indentation_level(const RID &p_rid, int p_idx, int p_level) {
+ // Not supported.
+}
+
+int NativeMenuWindows::get_item_count(const RID &p_rid) const {
+ const MenuData *md = menus.get_or_null(p_rid);
+ ERR_FAIL_NULL_V(md, 0);
+
+ return GetMenuItemCount(md->menu);
+}
+
+bool NativeMenuWindows::is_system_menu(const RID &p_rid) const {
+ return false;
+}
+
+void NativeMenuWindows::remove_item(const RID &p_rid, int p_idx) {
+ ERR_FAIL_COND(p_idx < 0);
+ const MenuData *md = menus.get_or_null(p_rid);
+ ERR_FAIL_NULL(md);
+ int count = GetMenuItemCount(md->menu);
+ ERR_FAIL_COND(p_idx >= count);
+
+ MENUITEMINFOW item;
+ ZeroMemory(&item, sizeof(item));
+ item.cbSize = sizeof(item);
+ item.fMask = MIIM_DATA;
+ if (GetMenuItemInfoW(md->menu, p_idx, true, &item)) {
+ MenuItemData *item_data = (MenuItemData *)item.dwItemData;
+ if (item_data) {
+ if (item_data->bmp) {
+ DeleteObject(item_data->bmp);
+ }
+ memdelete(item_data);
+ }
+ }
+ RemoveMenu(md->menu, p_idx, MF_BYPOSITION);
+}
+
+void NativeMenuWindows::clear(const RID &p_rid) {
+ const MenuData *md = menus.get_or_null(p_rid);
+ ERR_FAIL_NULL(md);
+
+ MENUITEMINFOW item;
+ int count = GetMenuItemCount(md->menu);
+ for (int i = 0; i < count; i++) {
+ ZeroMemory(&item, sizeof(item));
+ item.cbSize = sizeof(item);
+ item.fMask = MIIM_DATA;
+ if (GetMenuItemInfoW(md->menu, 0, true, &item)) {
+ MenuItemData *item_data = (MenuItemData *)item.dwItemData;
+ if (item_data) {
+ if (item_data->bmp) {
+ DeleteObject(item_data->bmp);
+ }
+ memdelete(item_data);
+ }
+ }
+ RemoveMenu(md->menu, 0, MF_BYPOSITION);
+ }
+}
+
+NativeMenuWindows::NativeMenuWindows() {}
+
+NativeMenuWindows::~NativeMenuWindows() {}
diff --git a/platform/windows/native_menu_windows.h b/platform/windows/native_menu_windows.h
new file mode 100644
index 0000000000..6eab56d8b6
--- /dev/null
+++ b/platform/windows/native_menu_windows.h
@@ -0,0 +1,151 @@
+/**************************************************************************/
+/* native_menu_windows.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* 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 NATIVE_MENU_WINDOWS_H
+#define NATIVE_MENU_WINDOWS_H
+
+#include "core/templates/hash_map.h"
+#include "core/templates/rid_owner.h"
+#include "servers/native_menu.h"
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+class NativeMenuWindows : public NativeMenu {
+ GDCLASS(NativeMenuWindows, NativeMenu)
+
+ enum GlobalMenuCheckType {
+ CHECKABLE_TYPE_NONE,
+ CHECKABLE_TYPE_CHECK_BOX,
+ CHECKABLE_TYPE_RADIO_BUTTON,
+ };
+
+ struct MenuItemData {
+ Callable callback;
+ Variant meta;
+ GlobalMenuCheckType checkable_type;
+ int max_states = 0;
+ int state = 0;
+ Ref<Image> img;
+ HBITMAP bmp = 0;
+ };
+
+ struct MenuData {
+ HMENU menu = 0;
+ bool is_rtl = false;
+ };
+
+ mutable RID_PtrOwner<MenuData> menus;
+ HashMap<HMENU, RID> menu_lookup;
+
+ HBITMAP _make_bitmap(const Ref<Image> &p_img) const;
+
+public:
+ void _menu_activate(HMENU p_menu, int p_index) const;
+
+ virtual bool has_feature(Feature p_feature) const override;
+
+ virtual bool has_system_menu(SystemMenus p_menu_id) const override;
+ virtual RID get_system_menu(SystemMenus p_menu_id) const override;
+
+ virtual RID create_menu() override;
+ virtual bool has_menu(const RID &p_rid) const override;
+ virtual void free_menu(const RID &p_rid) override;
+
+ virtual Size2 get_size(const RID &p_rid) const override;
+ virtual void popup(const RID &p_rid, const Vector2i &p_position) override;
+
+ virtual void set_interface_direction(const RID &p_rid, bool p_is_rtl) override;
+ virtual void set_popup_open_callback(const RID &p_rid, const Callable &p_callback) override;
+ virtual Callable get_popup_open_callback(const RID &p_rid) const override;
+ virtual void set_popup_close_callback(const RID &p_rid, const Callable &p_callback) override;
+ virtual Callable get_popup_close_callback(const RID &p_rid) const override;
+ virtual void set_minimum_width(const RID &p_rid, float p_width) override;
+ virtual float get_minimum_width(const RID &p_rid) const override;
+
+ virtual int add_submenu_item(const RID &p_rid, const String &p_label, const RID &p_submenu_rid, const Variant &p_tag = Variant(), int p_index = -1) override;
+ virtual int add_item(const RID &p_rid, const String &p_label, const Callable &p_callback = Callable(), const Callable &p_key_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1) override;
+ virtual int add_check_item(const RID &p_rid, const String &p_label, const Callable &p_callback = Callable(), const Callable &p_key_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1) override;
+ virtual int add_icon_item(const RID &p_rid, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback = Callable(), const Callable &p_key_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1) override;
+ virtual int add_icon_check_item(const RID &p_rid, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback = Callable(), const Callable &p_key_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1) override;
+ virtual int add_radio_check_item(const RID &p_rid, const String &p_label, const Callable &p_callback = Callable(), const Callable &p_key_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1) override;
+ virtual int add_icon_radio_check_item(const RID &p_rid, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback = Callable(), const Callable &p_key_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1) override;
+ virtual int add_multistate_item(const RID &p_rid, const String &p_label, int p_max_states, int p_default_state, const Callable &p_callback = Callable(), const Callable &p_key_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1) override;
+ virtual int add_separator(const RID &p_rid, int p_index = -1) override;
+
+ virtual int find_item_index_with_text(const RID &p_rid, const String &p_text) const override;
+ virtual int find_item_index_with_tag(const RID &p_rid, const Variant &p_tag) const override;
+
+ virtual bool is_item_checked(const RID &p_rid, int p_idx) const override;
+ virtual bool is_item_checkable(const RID &p_rid, int p_idx) const override;
+ virtual bool is_item_radio_checkable(const RID &p_rid, int p_idx) const override;
+ virtual Callable get_item_callback(const RID &p_rid, int p_idx) const override;
+ virtual Callable get_item_key_callback(const RID &p_rid, int p_idx) const override;
+ virtual Variant get_item_tag(const RID &p_rid, int p_idx) const override;
+ virtual String get_item_text(const RID &p_rid, int p_idx) const override;
+ virtual RID get_item_submenu(const RID &p_rid, int p_idx) const override;
+ virtual Key get_item_accelerator(const RID &p_rid, int p_idx) const override;
+ virtual bool is_item_disabled(const RID &p_rid, int p_idx) const override;
+ virtual bool is_item_hidden(const RID &p_rid, int p_idx) const override;
+ virtual String get_item_tooltip(const RID &p_rid, int p_idx) const override;
+ virtual int get_item_state(const RID &p_rid, int p_idx) const override;
+ virtual int get_item_max_states(const RID &p_rid, int p_idx) const override;
+ virtual Ref<Texture2D> get_item_icon(const RID &p_rid, int p_idx) const override;
+ virtual int get_item_indentation_level(const RID &p_rid, int p_idx) const override;
+
+ virtual void set_item_checked(const RID &p_rid, int p_idx, bool p_checked) override;
+ virtual void set_item_checkable(const RID &p_rid, int p_idx, bool p_checkable) override;
+ virtual void set_item_radio_checkable(const RID &p_rid, int p_idx, bool p_checkable) override;
+ virtual void set_item_callback(const RID &p_rid, int p_idx, const Callable &p_callback) override;
+ virtual void set_item_key_callback(const RID &p_rid, int p_idx, const Callable &p_key_callback) override;
+ virtual void set_item_hover_callbacks(const RID &p_rid, int p_idx, const Callable &p_callback) override;
+ virtual void set_item_tag(const RID &p_rid, int p_idx, const Variant &p_tag) override;
+ virtual void set_item_text(const RID &p_rid, int p_idx, const String &p_text) override;
+ virtual void set_item_submenu(const RID &p_rid, int p_idx, const RID &p_submenu_rid) override;
+ virtual void set_item_accelerator(const RID &p_rid, int p_idx, Key p_keycode) override;
+ virtual void set_item_disabled(const RID &p_rid, int p_idx, bool p_disabled) override;
+ virtual void set_item_hidden(const RID &p_rid, int p_idx, bool p_hidden) override;
+ virtual void set_item_tooltip(const RID &p_rid, int p_idx, const String &p_tooltip) override;
+ virtual void set_item_state(const RID &p_rid, int p_idx, int p_state) override;
+ virtual void set_item_max_states(const RID &p_rid, int p_idx, int p_max_states) override;
+ virtual void set_item_icon(const RID &p_rid, int p_idx, const Ref<Texture2D> &p_icon) override;
+ virtual void set_item_indentation_level(const RID &p_rid, int p_idx, int p_level) override;
+
+ virtual int get_item_count(const RID &p_rid) const override;
+ virtual bool is_system_menu(const RID &p_rid) const override;
+
+ virtual void remove_item(const RID &p_rid, int p_idx) override;
+ virtual void clear(const RID &p_rid) override;
+
+ NativeMenuWindows();
+ ~NativeMenuWindows();
+};
+
+#endif // NATIVE_MENU_WINDOWS_H
diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h
index 7e7d23a2a8..351cb32c9b 100644
--- a/platform/windows/os_windows.h
+++ b/platform/windows/os_windows.h
@@ -69,7 +69,7 @@
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x4
#endif
-template <class T>
+template <typename T>
class ComAutoreleaseRef {
public:
T *reference = nullptr;
diff --git a/scene/2d/physics/rigid_body_2d.cpp b/scene/2d/physics/rigid_body_2d.cpp
index 12112510a8..5e05c563a4 100644
--- a/scene/2d/physics/rigid_body_2d.cpp
+++ b/scene/2d/physics/rigid_body_2d.cpp
@@ -356,6 +356,8 @@ void RigidBody2D::set_center_of_mass_mode(CenterOfMassMode p_mode) {
PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_CENTER_OF_MASS, center_of_mass);
} break;
}
+
+ notify_property_list_changed();
}
RigidBody2D::CenterOfMassMode RigidBody2D::get_center_of_mass_mode() const {
@@ -614,6 +616,8 @@ void RigidBody2D::set_contact_monitor(bool p_enabled) {
contact_monitor = memnew(ContactMonitor);
contact_monitor->locked = false;
}
+
+ notify_property_list_changed();
}
bool RigidBody2D::is_contact_monitor_enabled() const {
@@ -736,13 +740,12 @@ void RigidBody2D::_bind_methods() {
GDVIRTUAL_BIND(_integrate_forces, "state");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mass", PROPERTY_HINT_RANGE, "0.01,1000,0.01,or_greater,exp,suffix:kg"), "set_mass", "get_mass");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mass", PROPERTY_HINT_RANGE, "0.001,1000,0.001,or_greater,exp,suffix:kg"), "set_mass", "get_mass");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_scale", PROPERTY_HINT_RANGE, "-8,8,0.001,or_less,or_greater"), "set_gravity_scale", "get_gravity_scale");
ADD_GROUP("Mass Distribution", "");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "center_of_mass_mode", PROPERTY_HINT_ENUM, "Auto,Custom", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_center_of_mass_mode", "get_center_of_mass_mode");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "center_of_mass", PROPERTY_HINT_RANGE, "-10,10,0.01,or_less,or_greater,suffix:px"), "set_center_of_mass", "get_center_of_mass");
- ADD_LINKED_PROPERTY("center_of_mass_mode", "center_of_mass");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "center_of_mass_mode", PROPERTY_HINT_ENUM, "Auto,Custom"), "set_center_of_mass_mode", "get_center_of_mass_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "center_of_mass", PROPERTY_HINT_RANGE, "-1000,1000,0.01,or_less,or_greater,suffix:px"), "set_center_of_mass", "get_center_of_mass");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "inertia", PROPERTY_HINT_RANGE, U"0,1000,0.01,or_greater,exp,suffix:kg\u22C5px\u00B2"), "set_inertia", "get_inertia");
ADD_GROUP("Deactivation", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sleeping"), "set_sleeping", "is_sleeping");
@@ -753,8 +756,8 @@ void RigidBody2D::_bind_methods() {
ADD_GROUP("Solver", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "custom_integrator"), "set_use_custom_integrator", "is_using_custom_integrator");
ADD_PROPERTY(PropertyInfo(Variant::INT, "continuous_cd", PROPERTY_HINT_ENUM, "Disabled,Cast Ray,Cast Shape"), "set_continuous_collision_detection_mode", "get_continuous_collision_detection_mode");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "max_contacts_reported", PROPERTY_HINT_RANGE, "0,64,1,or_greater"), "set_max_contacts_reported", "get_max_contacts_reported");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "contact_monitor"), "set_contact_monitor", "is_contact_monitor_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "max_contacts_reported", PROPERTY_HINT_RANGE, "0,64,1,or_greater"), "set_max_contacts_reported", "get_max_contacts_reported");
ADD_GROUP("Linear", "linear_");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "linear_velocity", PROPERTY_HINT_NONE, "suffix:px/s"), "set_linear_velocity", "get_linear_velocity");
ADD_PROPERTY(PropertyInfo(Variant::INT, "linear_damp_mode", PROPERTY_HINT_ENUM, "Combine,Replace"), "set_linear_damp_mode", "get_linear_damp_mode");
@@ -788,10 +791,12 @@ void RigidBody2D::_bind_methods() {
}
void RigidBody2D::_validate_property(PropertyInfo &p_property) const {
- if (center_of_mass_mode != CENTER_OF_MASS_MODE_CUSTOM) {
- if (p_property.name == "center_of_mass") {
- p_property.usage = PROPERTY_USAGE_NO_EDITOR;
- }
+ if (center_of_mass_mode != CENTER_OF_MASS_MODE_CUSTOM && p_property.name == "center_of_mass") {
+ p_property.usage = PROPERTY_USAGE_NO_EDITOR;
+ }
+
+ if (!contact_monitor && p_property.name == "max_contacts_reported") {
+ p_property.usage = PROPERTY_USAGE_NO_EDITOR;
}
}
diff --git a/scene/3d/physics/rigid_body_3d.cpp b/scene/3d/physics/rigid_body_3d.cpp
index 54bd1c0d25..6cd621c1c7 100644
--- a/scene/3d/physics/rigid_body_3d.cpp
+++ b/scene/3d/physics/rigid_body_3d.cpp
@@ -375,6 +375,8 @@ void RigidBody3D::set_center_of_mass_mode(CenterOfMassMode p_mode) {
PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_CENTER_OF_MASS, center_of_mass);
} break;
}
+
+ notify_property_list_changed();
}
RigidBody3D::CenterOfMassMode RigidBody3D::get_center_of_mass_mode() const {
@@ -622,6 +624,8 @@ void RigidBody3D::set_contact_monitor(bool p_enabled) {
contact_monitor = memnew(ContactMonitor);
contact_monitor->locked = false;
}
+
+ notify_property_list_changed();
}
bool RigidBody3D::is_contact_monitor_enabled() const {
@@ -758,13 +762,12 @@ void RigidBody3D::_bind_methods() {
GDVIRTUAL_BIND(_integrate_forces, "state");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mass", PROPERTY_HINT_RANGE, "0.01,1000,0.01,or_greater,exp,suffix:kg"), "set_mass", "get_mass");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mass", PROPERTY_HINT_RANGE, "0.001,1000,0.001,or_greater,exp,suffix:kg"), "set_mass", "get_mass");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_scale", PROPERTY_HINT_RANGE, "-8,8,0.001,or_less,or_greater"), "set_gravity_scale", "get_gravity_scale");
ADD_GROUP("Mass Distribution", "");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "center_of_mass_mode", PROPERTY_HINT_ENUM, "Auto,Custom", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_center_of_mass_mode", "get_center_of_mass_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "center_of_mass_mode", PROPERTY_HINT_ENUM, "Auto,Custom"), "set_center_of_mass_mode", "get_center_of_mass_mode");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "center_of_mass", PROPERTY_HINT_RANGE, "-10,10,0.01,or_less,or_greater,suffix:m"), "set_center_of_mass", "get_center_of_mass");
- ADD_LINKED_PROPERTY("center_of_mass_mode", "center_of_mass");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "inertia", PROPERTY_HINT_RANGE, U"0,1000,0.01,or_greater,exp,suffix:kg\u22C5m\u00B2"), "set_inertia", "get_inertia");
ADD_GROUP("Deactivation", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sleeping"), "set_sleeping", "is_sleeping");
@@ -775,8 +778,8 @@ void RigidBody3D::_bind_methods() {
ADD_GROUP("Solver", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "custom_integrator"), "set_use_custom_integrator", "is_using_custom_integrator");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "continuous_cd"), "set_use_continuous_collision_detection", "is_using_continuous_collision_detection");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "max_contacts_reported", PROPERTY_HINT_RANGE, "0,64,1,or_greater"), "set_max_contacts_reported", "get_max_contacts_reported");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "contact_monitor"), "set_contact_monitor", "is_contact_monitor_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "max_contacts_reported", PROPERTY_HINT_RANGE, "0,64,1,or_greater"), "set_max_contacts_reported", "get_max_contacts_reported");
ADD_GROUP("Linear", "linear_");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "linear_velocity", PROPERTY_HINT_NONE, "suffix:m/s"), "set_linear_velocity", "get_linear_velocity");
ADD_PROPERTY(PropertyInfo(Variant::INT, "linear_damp_mode", PROPERTY_HINT_ENUM, "Combine,Replace"), "set_linear_damp_mode", "get_linear_damp_mode");
@@ -806,10 +809,12 @@ void RigidBody3D::_bind_methods() {
}
void RigidBody3D::_validate_property(PropertyInfo &p_property) const {
- if (center_of_mass_mode != CENTER_OF_MASS_MODE_CUSTOM) {
- if (p_property.name == "center_of_mass") {
- p_property.usage = PROPERTY_USAGE_NO_EDITOR;
- }
+ if (center_of_mass_mode != CENTER_OF_MASS_MODE_CUSTOM && p_property.name == "center_of_mass") {
+ p_property.usage = PROPERTY_USAGE_NO_EDITOR;
+ }
+
+ if (!contact_monitor && p_property.name == "max_contacts_reported") {
+ p_property.usage = PROPERTY_USAGE_NO_EDITOR;
}
}
diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp
index f7eae2b772..632e6af2ce 100644
--- a/scene/gui/code_edit.cpp
+++ b/scene/gui/code_edit.cpp
@@ -733,14 +733,15 @@ void CodeEdit::_backspace_internal(int p_caret) {
prev_column = cc - auto_brace_completion_pairs[idx].open_key.length();
if (_get_auto_brace_pair_close_at_pos(cl, cc) == idx) {
- remove_text(prev_line, prev_column, cl, cc + auto_brace_completion_pairs[idx].close_key.length());
- } else {
- remove_text(prev_line, prev_column, cl, cc);
+ cc += auto_brace_completion_pairs[idx].close_key.length();
}
+
+ remove_text(prev_line, prev_column, cl, cc);
+
set_caret_line(prev_line, false, true, 0, i);
set_caret_column(prev_column, i == 0, i);
- adjust_carets_after_edit(i, prev_line, prev_column, cl, cc + auto_brace_completion_pairs[idx].close_key.length());
+ adjust_carets_after_edit(i, prev_line, prev_column, cl, cc);
continue;
}
}
diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp
index aa67f0d200..3746b667f6 100644
--- a/scene/gui/dialogs.cpp
+++ b/scene/gui/dialogs.cpp
@@ -317,7 +317,7 @@ Button *AcceptDialog::add_button(const String &p_text, bool p_right, const Strin
Button *AcceptDialog::add_cancel_button(const String &p_cancel) {
String c = p_cancel;
if (p_cancel.is_empty()) {
- c = "Cancel";
+ c = ETR("Cancel");
}
Button *b = swap_cancel_ok ? add_button(c, true) : add_button(c);
@@ -419,13 +419,13 @@ AcceptDialog::AcceptDialog() {
buttons_hbox->add_spacer();
ok_button = memnew(Button);
- ok_button->set_text("OK");
+ ok_button->set_text(ETR("OK"));
buttons_hbox->add_child(ok_button);
buttons_hbox->add_spacer();
ok_button->connect("pressed", callable_mp(this, &AcceptDialog::_ok_pressed));
- set_title(TTRC("Alert!"));
+ set_title(ETR("Alert!"));
}
AcceptDialog::~AcceptDialog() {
@@ -454,7 +454,7 @@ Button *ConfirmationDialog::get_cancel_button() {
}
ConfirmationDialog::ConfirmationDialog() {
- set_title(TTRC("Please Confirm..."));
+ set_title(ETR("Please Confirm..."));
set_min_size(Size2(200, 70));
cancel = add_cancel_button();
diff --git a/scene/gui/menu_bar.cpp b/scene/gui/menu_bar.cpp
index a808a3b1b5..8eb455d0ac 100644
--- a/scene/gui/menu_bar.cpp
+++ b/scene/gui/menu_bar.cpp
@@ -192,7 +192,7 @@ bool MenuBar::is_native_menu() const {
}
#endif
- return (NativeMenu::get_singleton()->has_feature(NativeMenu::FEATURE_GLOBAL_MENU) && is_native);
+ return (NativeMenu::get_singleton()->has_feature(NativeMenu::FEATURE_GLOBAL_MENU) && prefer_native);
}
void MenuBar::bind_global_menu() {
@@ -767,9 +767,9 @@ int MenuBar::get_start_index() const {
}
void MenuBar::set_prefer_global_menu(bool p_enabled) {
- if (is_native != p_enabled) {
- is_native = p_enabled;
- if (is_native) {
+ if (prefer_native != p_enabled) {
+ prefer_native = p_enabled;
+ if (prefer_native) {
bind_global_menu();
} else {
unbind_global_menu();
@@ -778,7 +778,7 @@ void MenuBar::set_prefer_global_menu(bool p_enabled) {
}
bool MenuBar::is_prefer_global_menu() const {
- return is_native;
+ return prefer_native;
}
Size2 MenuBar::get_minimum_size() const {
diff --git a/scene/gui/menu_bar.h b/scene/gui/menu_bar.h
index 962eea593f..631b791e1b 100644
--- a/scene/gui/menu_bar.h
+++ b/scene/gui/menu_bar.h
@@ -41,7 +41,7 @@ class MenuBar : public Control {
bool switch_on_hover = true;
bool disable_shortcuts = false;
- bool is_native = true;
+ bool prefer_native = true;
bool flat = false;
int start_index = -1;
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index dfe0649d0f..25d999851b 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -82,7 +82,7 @@ RID PopupMenu::bind_global_menu() {
return RID();
}
#endif
- if (!NativeMenu::get_singleton()->has_feature(NativeMenu::FEATURE_GLOBAL_MENU)) {
+ if (!NativeMenu::get_singleton()->has_feature(NativeMenu::FEATURE_POPUP_MENU)) {
return RID();
}
@@ -105,6 +105,7 @@ RID PopupMenu::bind_global_menu() {
global_menu = nmenu->create_menu();
}
+ nmenu->set_interface_direction(global_menu, control->is_layout_rtl());
nmenu->set_popup_open_callback(global_menu, callable_mp(this, &PopupMenu::_about_to_popup));
nmenu->set_popup_close_callback(global_menu, callable_mp(this, &PopupMenu::_about_to_close));
for (int i = 0; i < items.size(); i++) {
@@ -1027,6 +1028,9 @@ void PopupMenu::_notification(int p_what) {
case NOTIFICATION_TRANSLATION_CHANGED: {
NativeMenu *nmenu = NativeMenu::get_singleton();
bool is_global = global_menu.is_valid();
+ if (is_global) {
+ nmenu->set_interface_direction(global_menu, control->is_layout_rtl());
+ }
for (int i = 0; i < items.size(); i++) {
Item &item = items.write[i];
item.xl_text = atr(item.text);
@@ -2289,6 +2293,21 @@ void PopupMenu::scroll_to_item(int p_idx) {
}
}
+void PopupMenu::set_prefer_native_menu(bool p_enabled) {
+ if (prefer_native != p_enabled) {
+ prefer_native = p_enabled;
+ if (prefer_native) {
+ bind_global_menu();
+ } else {
+ unbind_global_menu();
+ }
+ }
+}
+
+bool PopupMenu::is_prefer_native_menu() const {
+ return prefer_native;
+}
+
bool PopupMenu::activate_item_by_event(const Ref<InputEvent> &p_event, bool p_for_global_only) {
ERR_FAIL_COND_V(p_event.is_null(), false);
Key code = Key::NONE;
@@ -2616,6 +2635,9 @@ bool PopupMenu::_set(const StringName &p_name, const Variant &p_value) {
void PopupMenu::_bind_methods() {
ClassDB::bind_method(D_METHOD("activate_item_by_event", "event", "for_global_only"), &PopupMenu::activate_item_by_event, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("set_prefer_native_menu", "enabled"), &PopupMenu::set_prefer_native_menu);
+ ClassDB::bind_method(D_METHOD("is_prefer_native_menu"), &PopupMenu::is_prefer_native_menu);
+
ClassDB::bind_method(D_METHOD("add_item", "label", "id", "accel"), &PopupMenu::add_item, DEFVAL(-1), DEFVAL(0));
ClassDB::bind_method(D_METHOD("add_icon_item", "texture", "label", "id", "accel"), &PopupMenu::add_icon_item, DEFVAL(-1), DEFVAL(0));
ClassDB::bind_method(D_METHOD("add_check_item", "label", "id", "accel"), &PopupMenu::add_check_item, DEFVAL(-1), DEFVAL(0));
@@ -2722,7 +2744,8 @@ void PopupMenu::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hide_on_state_item_selection"), "set_hide_on_state_item_selection", "is_hide_on_state_item_selection");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "submenu_popup_delay", PROPERTY_HINT_NONE, "suffix:s"), "set_submenu_popup_delay", "get_submenu_popup_delay");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_search"), "set_allow_search", "get_allow_search");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "system_menu_id", PROPERTY_HINT_ENUM, "Application Menu:2,Window Menu:3,Help Menu:4,Dock:5"), "set_system_menu", "get_system_menu");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "system_menu_id", PROPERTY_HINT_ENUM, "None:0,Application Menu:2,Window Menu:3,Help Menu:4,Dock:5"), "set_system_menu", "get_system_menu");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "prefer_native_menu"), "set_prefer_native_menu", "is_prefer_native_menu");
ADD_ARRAY_COUNT("Items", "item_count", "set_item_count", "get_item_count", "item_");
@@ -2786,9 +2809,37 @@ void PopupMenu::_bind_methods() {
}
void PopupMenu::popup(const Rect2i &p_bounds) {
- moved = Vector2();
- popup_time_msec = OS::get_singleton()->get_ticks_msec();
- Popup::popup(p_bounds);
+ bool native = global_menu.is_valid();
+#ifdef TOOLS_ENABLED
+ if (is_part_of_edited_scene()) {
+ native = false;
+ }
+#endif
+
+ if (native) {
+ NativeMenu::get_singleton()->popup(global_menu, (p_bounds != Rect2i()) ? p_bounds.position : get_position());
+ } else {
+ moved = Vector2();
+ popup_time_msec = OS::get_singleton()->get_ticks_msec();
+ Popup::popup(p_bounds);
+ }
+}
+
+void PopupMenu::set_visible(bool p_visible) {
+ bool native = global_menu.is_valid();
+#ifdef TOOLS_ENABLED
+ if (is_part_of_edited_scene()) {
+ native = false;
+ }
+#endif
+
+ if (native) {
+ if (p_visible) {
+ NativeMenu::get_singleton()->popup(global_menu, get_position());
+ }
+ } else {
+ Popup::set_visible(p_visible);
+ }
}
PopupMenu::PopupMenu() {
diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h
index 602d5466a9..f7097fffaf 100644
--- a/scene/gui/popup_menu.h
+++ b/scene/gui/popup_menu.h
@@ -100,6 +100,7 @@ class PopupMenu : public Popup {
RID global_menu;
RID system_menu;
NativeMenu::SystemMenus system_menu_id = NativeMenu::INVALID_MENU_ID;
+ bool prefer_native = false;
bool close_allowed = false;
bool activated_by_keyboard = false;
@@ -322,6 +323,9 @@ public:
void set_item_count(int p_count);
int get_item_count() const;
+ void set_prefer_native_menu(bool p_enabled);
+ bool is_prefer_native_menu() const;
+
void scroll_to_item(int p_idx);
bool activate_item_by_event(const Ref<InputEvent> &p_event, bool p_for_global_only = false);
@@ -357,6 +361,7 @@ public:
bool get_allow_search() const;
virtual void popup(const Rect2i &p_bounds = Rect2i()) override;
+ virtual void set_visible(bool p_visible) override;
void take_mouse_focus();
diff --git a/scene/main/node.h b/scene/main/node.h
index 7cc0f7b370..57a7278e73 100644
--- a/scene/main/node.h
+++ b/scene/main/node.h
@@ -57,7 +57,7 @@ protected:
MTFlag() :
mt{} {}
};
- template <class T>
+ template <typename T>
union MTNumeric {
SafeNumeric<T> mt;
T st;
diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp
index 079101f679..cd530f100e 100644
--- a/scene/resources/animation.cpp
+++ b/scene/resources/animation.cpp
@@ -1041,7 +1041,7 @@ bool Animation::track_get_interpolation_loop_wrap(int p_track) const {
return tracks[p_track]->loop_wrap;
}
-template <class T, class V>
+template <typename T, typename V>
int Animation::_insert(double p_time, T &p_keys, const V &p_value) {
int idx = p_keys.size();
@@ -1065,7 +1065,7 @@ int Animation::_insert(double p_time, T &p_keys, const V &p_value) {
return -1;
}
-template <class T>
+template <typename T>
void Animation::_clear(T &p_keys) {
p_keys.clear();
}
@@ -2331,7 +2331,7 @@ void Animation::track_set_key_transition(int p_track, int p_key_idx, real_t p_tr
emit_changed();
}
-template <class K>
+template <typename K>
int Animation::_find(const Vector<K> &p_keys, double p_time, bool p_backward, bool p_limit) const {
int len = p_keys.size();
if (len == 0) {
@@ -2451,7 +2451,7 @@ Variant Animation::_cubic_interpolate_angle_in_time(const Variant &p_pre_a, cons
return _cubic_interpolate_in_time(p_pre_a, p_a, p_b, p_post_b, p_c, p_pre_a_t, p_b_t, p_post_b_t);
}
-template <class T>
+template <typename T>
T Animation::_interpolate(const Vector<TKey<T>> &p_keys, double p_time, InterpolationType p_interp, bool p_loop_wrap, bool *p_ok, bool p_backward) const {
int len = _find(p_keys, length) + 1; // try to find last key (there may be more past the end)
@@ -2693,7 +2693,7 @@ Animation::UpdateMode Animation::value_track_get_update_mode(int p_track) const
return vt->update_mode;
}
-template <class T>
+template <typename T>
void Animation::_track_get_key_indices_in_range(const Vector<T> &p_array, double from_time, double to_time, List<int> *p_indices, bool p_is_backward) const {
int len = p_array.size();
if (len == 0) {
diff --git a/scene/resources/animation.h b/scene/resources/animation.h
index 5b27958005..d3df8d03e5 100644
--- a/scene/resources/animation.h
+++ b/scene/resources/animation.h
@@ -120,7 +120,7 @@ private:
};
// Transform key holds either Vector3 or Quaternion.
- template <class T>
+ template <typename T>
struct TKey : public Key {
T value;
};
@@ -235,13 +235,13 @@ private:
Vector<Track *> tracks;
- template <class T>
+ template <typename T>
void _clear(T &p_keys);
- template <class T, class V>
+ template <typename T, typename V>
int _insert(double p_time, T &p_keys, const V &p_value);
- template <class K>
+ template <typename K>
inline int _find(const Vector<K> &p_keys, double p_time, bool p_backward = false, bool p_limit = false) const;
@@ -257,10 +257,10 @@ private:
_FORCE_INLINE_ real_t _cubic_interpolate_in_time(const real_t &p_pre_a, const real_t &p_a, const real_t &p_b, const real_t &p_post_b, real_t p_c, real_t p_pre_a_t, real_t p_b_t, real_t p_post_b_t) const;
_FORCE_INLINE_ Variant _cubic_interpolate_angle_in_time(const Variant &p_pre_a, const Variant &p_a, const Variant &p_b, const Variant &p_post_b, real_t p_c, real_t p_pre_a_t, real_t p_b_t, real_t p_post_b_t) const;
- template <class T>
+ template <typename T>
_FORCE_INLINE_ T _interpolate(const Vector<TKey<T>> &p_keys, double p_time, InterpolationType p_interp, bool p_loop_wrap, bool *p_ok, bool p_backward = false) const;
- template <class T>
+ template <typename T>
_FORCE_INLINE_ void _track_get_key_indices_in_range(const Vector<T> &p_array, double from_time, double to_time, List<int> *p_indices, bool p_is_backward) const;
double length = 1.0;
diff --git a/scene/resources/audio_stream_wav.cpp b/scene/resources/audio_stream_wav.cpp
index b6e6493b68..0185c6ef85 100644
--- a/scene/resources/audio_stream_wav.cpp
+++ b/scene/resources/audio_stream_wav.cpp
@@ -86,7 +86,7 @@ void AudioStreamPlaybackWAV::seek(double p_time) {
offset = uint64_t(p_time * base->mix_rate) << MIX_FRAC_BITS;
}
-template <class Depth, bool is_stereo, bool is_ima_adpcm>
+template <typename Depth, bool is_stereo, bool is_ima_adpcm>
void AudioStreamPlaybackWAV::do_resample(const Depth *p_src, AudioFrame *p_dst, int64_t &p_offset, int32_t &p_increment, uint32_t p_amount, IMA_ADPCM_State *p_ima_adpcm) {
// this function will be compiled branchless by any decent compiler
diff --git a/scene/resources/audio_stream_wav.h b/scene/resources/audio_stream_wav.h
index f150a17d21..959d1ceca0 100644
--- a/scene/resources/audio_stream_wav.h
+++ b/scene/resources/audio_stream_wav.h
@@ -60,7 +60,7 @@ class AudioStreamPlaybackWAV : public AudioStreamPlayback {
friend class AudioStreamWAV;
Ref<AudioStreamWAV> base;
- template <class Depth, bool is_stereo, bool is_ima_adpcm>
+ template <typename Depth, bool is_stereo, bool is_ima_adpcm>
void do_resample(const Depth *p_src, AudioFrame *p_dst, int64_t &p_offset, int32_t &p_increment, uint32_t p_amount, IMA_ADPCM_State *p_ima_adpcm);
public:
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index 322a8a853e..b381096df8 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -661,20 +661,19 @@ void BaseMaterial3D::_update_shader() {
}
if (flags[FLAG_USE_TEXTURE_REPEAT]) {
- texfilter_str += ",repeat_enable";
- texfilter_height_str += ",repeat_enable";
+ texfilter_str += ", repeat_enable";
+ texfilter_height_str += ", repeat_enable";
} else {
- texfilter_str += ",repeat_disable";
- texfilter_height_str += ",repeat_disable";
+ texfilter_str += ", repeat_disable";
+ texfilter_height_str += ", repeat_disable";
}
- //must create a shader!
-
// Add a comment to describe the shader origin (useful when converting to ShaderMaterial).
String code = vformat(
"// NOTE: Shader automatically converted from " VERSION_NAME " " VERSION_FULL_CONFIG "'s %s.\n\n",
orm ? "ORMMaterial3D" : "StandardMaterial3D");
+ // Define shader type and render mode based on property values.
code += "shader_type spatial;\nrender_mode ";
switch (blend_mode) {
case BLEND_MODE_MIX:
@@ -700,13 +699,13 @@ void BaseMaterial3D::_update_shader() {
switch (ddm) {
case DEPTH_DRAW_OPAQUE_ONLY:
- code += ",depth_draw_opaque";
+ code += ", depth_draw_opaque";
break;
case DEPTH_DRAW_ALWAYS:
- code += ",depth_draw_always";
+ code += ", depth_draw_always";
break;
case DEPTH_DRAW_DISABLED:
- code += ",depth_draw_never";
+ code += ", depth_draw_never";
break;
case DEPTH_DRAW_MAX:
break; // Internal value, skip.
@@ -714,238 +713,291 @@ void BaseMaterial3D::_update_shader() {
switch (cull_mode) {
case CULL_BACK:
- code += ",cull_back";
+ code += ", cull_back";
break;
case CULL_FRONT:
- code += ",cull_front";
+ code += ", cull_front";
break;
case CULL_DISABLED:
- code += ",cull_disabled";
+ code += ", cull_disabled";
break;
case CULL_MAX:
break; // Internal value, skip.
}
switch (diffuse_mode) {
case DIFFUSE_BURLEY:
- code += ",diffuse_burley";
+ code += ", diffuse_burley";
break;
case DIFFUSE_LAMBERT:
- code += ",diffuse_lambert";
+ code += ", diffuse_lambert";
break;
case DIFFUSE_LAMBERT_WRAP:
- code += ",diffuse_lambert_wrap";
+ code += ", diffuse_lambert_wrap";
break;
case DIFFUSE_TOON:
- code += ",diffuse_toon";
+ code += ", diffuse_toon";
break;
case DIFFUSE_MAX:
break; // Internal value, skip.
}
switch (specular_mode) {
case SPECULAR_SCHLICK_GGX:
- code += ",specular_schlick_ggx";
+ code += ", specular_schlick_ggx";
break;
case SPECULAR_TOON:
- code += ",specular_toon";
+ code += ", specular_toon";
break;
case SPECULAR_DISABLED:
- code += ",specular_disabled";
+ code += ", specular_disabled";
break;
case SPECULAR_MAX:
break; // Internal value, skip.
}
if (features[FEATURE_SUBSURFACE_SCATTERING] && flags[FLAG_SUBSURFACE_MODE_SKIN]) {
- code += ",sss_mode_skin";
+ code += ", sss_mode_skin";
}
if (shading_mode == SHADING_MODE_UNSHADED) {
- code += ",unshaded";
+ code += ", unshaded";
}
if (flags[FLAG_DISABLE_DEPTH_TEST]) {
- code += ",depth_test_disabled";
+ code += ", depth_test_disabled";
}
if (flags[FLAG_PARTICLE_TRAILS_MODE]) {
- code += ",particle_trails";
+ code += ", particle_trails";
}
if (shading_mode == SHADING_MODE_PER_VERTEX) {
- code += ",vertex_lighting";
+ code += ", vertex_lighting";
}
if (flags[FLAG_DONT_RECEIVE_SHADOWS]) {
- code += ",shadows_disabled";
+ code += ", shadows_disabled";
}
if (flags[FLAG_DISABLE_AMBIENT_LIGHT]) {
- code += ",ambient_light_disabled";
+ code += ", ambient_light_disabled";
}
if (flags[FLAG_USE_SHADOW_TO_OPACITY]) {
- code += ",shadow_to_opacity";
+ code += ", shadow_to_opacity";
}
if (flags[FLAG_DISABLE_FOG]) {
- code += ",fog_disabled";
+ code += ", fog_disabled";
}
if (transparency == TRANSPARENCY_ALPHA_DEPTH_PRE_PASS) {
- code += ",depth_prepass_alpha";
+ code += ", depth_prepass_alpha";
}
- // Although its technically possible to do alpha antialiasing without using alpha hash or alpha scissor,
+ // Although it's technically possible to do alpha antialiasing without using alpha hash or alpha scissor,
// it is restricted in the base material because it has no use, and abusing it with regular Alpha blending can
- // saturate the MSAA mask
+ // saturate the MSAA mask.
if (transparency == TRANSPARENCY_ALPHA_HASH || transparency == TRANSPARENCY_ALPHA_SCISSOR) {
- // alpha antialiasing is only useful in ALPHA_HASH or ALPHA_SCISSOR
+ // Alpha antialiasing is only useful with ALPHA_HASH or ALPHA_SCISSOR.
if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE) {
- code += ",alpha_to_coverage";
+ code += ", alpha_to_coverage";
} else if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE) {
- code += ",alpha_to_coverage_and_one";
+ code += ", alpha_to_coverage_and_one";
}
}
code += ";\n";
- code += "uniform vec4 albedo : source_color;\n";
- code += "uniform sampler2D texture_albedo : source_color," + texfilter_str + ";\n";
+ // Generate list of uniforms.
+ code += vformat(R"(
+uniform vec4 albedo : source_color;
+uniform sampler2D texture_albedo : source_color, %s;
+)",
+ texfilter_str);
+
if (grow_enabled) {
- code += "uniform float grow;\n";
+ code += "uniform float grow : hint_range(-16.0, 16.0, 0.001);\n";
}
if (proximity_fade_enabled) {
- code += "uniform float proximity_fade_distance;\n";
+ code += "uniform float proximity_fade_distance : hint_range(0.0, 4096.0, 0.01);\n";
}
if (distance_fade != DISTANCE_FADE_DISABLED) {
- code += "uniform float distance_fade_min;\n";
- code += "uniform float distance_fade_max;\n";
+ code += R"(
+uniform float distance_fade_min : hint_range(0.0, 4096.0, 0.01);
+uniform float distance_fade_max : hint_range(0.0, 4096.0, 0.01);
+)";
}
if (flags[FLAG_ALBEDO_TEXTURE_MSDF]) {
- code += "uniform float msdf_pixel_range;\n";
- code += "uniform float msdf_outline_size;\n";
+ code += R"(
+uniform float msdf_pixel_range : hint_range(1.0, 100.0, 1.0);
+uniform float msdf_outline_size : hint_range(0.0, 250.0, 1.0);
+)";
}
- // alpha scissor is only valid if there is not antialiasing edge
- // alpha hash is valid whenever, but not with alpha scissor
+ // Alpha scissor is only valid if there is no antialiasing edge.
+ // Alpha hash is valid whenever, but not with alpha scissor.
if (transparency == TRANSPARENCY_ALPHA_SCISSOR) {
- code += "uniform float alpha_scissor_threshold;\n";
+ code += "uniform float alpha_scissor_threshold : hint_range(0.0, 1.0, 0.001);\n";
} else if (transparency == TRANSPARENCY_ALPHA_HASH) {
- code += "uniform float alpha_hash_scale;\n";
+ code += "uniform float alpha_hash_scale : hint_range(0.0, 2.0, 0.01);\n";
}
- // if alpha antialiasing isn't off, add in the edge variable
+ // If alpha antialiasing isn't off, add in the edge variable.
if (alpha_antialiasing_mode != ALPHA_ANTIALIASING_OFF &&
(transparency == TRANSPARENCY_ALPHA_SCISSOR || transparency == TRANSPARENCY_ALPHA_HASH)) {
- code += "uniform float alpha_antialiasing_edge;\n";
- code += "uniform ivec2 albedo_texture_size;\n";
+ code += R"(
+uniform float alpha_antialiasing_edge : hint_range(0.0, 1.0, 0.01);
+uniform ivec2 albedo_texture_size;
+)";
}
- code += "uniform float point_size : hint_range(0,128);\n";
+ code += "uniform float point_size : hint_range(0.1, 128.0, 0.1);\n";
- //TODO ALL HINTS
if (!orm) {
- code += "uniform float roughness : hint_range(0,1);\n";
- code += "uniform sampler2D texture_metallic : hint_default_white," + texfilter_str + ";\n";
- code += "uniform vec4 metallic_texture_channel;\n";
+ code += vformat(R"(
+uniform float roughness : hint_range(0.0, 1.0);
+uniform sampler2D texture_metallic : hint_default_white, %s;
+uniform vec4 metallic_texture_channel;
+)",
+ texfilter_str);
switch (roughness_texture_channel) {
case TEXTURE_CHANNEL_RED: {
- code += "uniform sampler2D texture_roughness : hint_roughness_r," + texfilter_str + ";\n";
+ code += vformat("uniform sampler2D texture_roughness : hint_roughness_r, %s;\n", texfilter_str);
} break;
case TEXTURE_CHANNEL_GREEN: {
- code += "uniform sampler2D texture_roughness : hint_roughness_g," + texfilter_str + ";\n";
+ code += vformat("uniform sampler2D texture_roughness : hint_roughness_g, %s;\n", texfilter_str);
} break;
case TEXTURE_CHANNEL_BLUE: {
- code += "uniform sampler2D texture_roughness : hint_roughness_b," + texfilter_str + ";\n";
+ code += vformat("uniform sampler2D texture_roughness : hint_roughness_b, %s;\n", texfilter_str);
} break;
case TEXTURE_CHANNEL_ALPHA: {
- code += "uniform sampler2D texture_roughness : hint_roughness_a," + texfilter_str + ";\n";
+ code += vformat("uniform sampler2D texture_roughness : hint_roughness_a, %s;\n", texfilter_str);
} break;
case TEXTURE_CHANNEL_GRAYSCALE: {
- code += "uniform sampler2D texture_roughness : hint_roughness_gray," + texfilter_str + ";\n";
+ code += vformat("uniform sampler2D texture_roughness : hint_roughness_gray, %s;\n", texfilter_str);
} break;
case TEXTURE_CHANNEL_MAX:
break; // Internal value, skip.
}
- code += "uniform float specular;\n";
- code += "uniform float metallic;\n";
+ code += R"(
+uniform float specular : hint_range(0.0, 1.0, 0.01);
+uniform float metallic : hint_range(0.0, 1.0, 0.01);
+)";
} else {
- code += "uniform sampler2D texture_orm : hint_roughness_g," + texfilter_str + ";\n";
+ code += "uniform sampler2D texture_orm : hint_roughness_g, " + texfilter_str + ";\n";
}
if (billboard_mode == BILLBOARD_PARTICLES) {
- code += "uniform int particles_anim_h_frames;\n";
- code += "uniform int particles_anim_v_frames;\n";
- code += "uniform bool particles_anim_loop;\n";
+ code += R"(
+uniform int particles_anim_h_frames : hint_range(1, 128);
+uniform int particles_anim_v_frames : hint_range(1, 128);
+uniform bool particles_anim_loop;
+)";
}
if (features[FEATURE_EMISSION]) {
- code += "uniform sampler2D texture_emission : source_color, hint_default_black," + texfilter_str + ";\n";
- code += "uniform vec4 emission : source_color;\n";
- code += "uniform float emission_energy;\n";
+ code += vformat(R"(
+uniform sampler2D texture_emission : source_color, hint_default_black, %s;
+uniform vec4 emission : source_color;
+uniform float emission_energy : hint_range(0.0, 100.0, 0.01);
+)",
+ texfilter_str);
}
if (features[FEATURE_REFRACTION]) {
- code += "uniform sampler2D texture_refraction : " + texfilter_str + ";\n";
- code += "uniform float refraction : hint_range(-16,16);\n";
- code += "uniform vec4 refraction_texture_channel;\n";
+ code += vformat(R"(
+uniform sampler2D texture_refraction : %s;
+uniform float refraction : hint_range(-1.0, 1.0, 0.001);
+uniform vec4 refraction_texture_channel;
+)",
+ texfilter_str);
}
if (features[FEATURE_REFRACTION]) {
- code += "uniform sampler2D screen_texture : hint_screen_texture, repeat_disable, filter_linear_mipmap;";
+ code += "uniform sampler2D screen_texture : hint_screen_texture, repeat_disable, filter_linear_mipmap;\n";
}
if (proximity_fade_enabled) {
- code += "uniform sampler2D depth_texture : hint_depth_texture, repeat_disable, filter_nearest;";
+ code += "uniform sampler2D depth_texture : hint_depth_texture, repeat_disable, filter_nearest;\n";
}
if (features[FEATURE_NORMAL_MAPPING]) {
- code += "uniform sampler2D texture_normal : hint_roughness_normal," + texfilter_str + ";\n";
- code += "uniform float normal_scale : hint_range(-16,16);\n";
+ code += vformat(R"(
+uniform sampler2D texture_normal : hint_roughness_normal, %s;
+uniform float normal_scale : hint_range(-16.0, 16.0);
+)",
+ texfilter_str);
}
if (features[FEATURE_RIM]) {
- code += "uniform float rim : hint_range(0,1);\n";
- code += "uniform float rim_tint : hint_range(0,1);\n";
- code += "uniform sampler2D texture_rim : hint_default_white," + texfilter_str + ";\n";
+ code += vformat(R"(
+uniform float rim : hint_range(0.0, 1.0, 0.01);
+uniform float rim_tint : hint_range(0.0, 1.0, 0.01);
+uniform sampler2D texture_rim : hint_default_white, %s;
+)",
+ texfilter_str);
}
if (features[FEATURE_CLEARCOAT]) {
- code += "uniform float clearcoat : hint_range(0,1);\n";
- code += "uniform float clearcoat_roughness : hint_range(0,1);\n";
- code += "uniform sampler2D texture_clearcoat : hint_default_white," + texfilter_str + ";\n";
+ code += vformat(R"(
+uniform float clearcoat : hint_range(0.0, 1.0, 0.01);
+uniform float clearcoat_roughness : hint_range(0.0, 1.0, 0.01);
+uniform sampler2D texture_clearcoat : hint_default_white, %s;
+)",
+ texfilter_str);
}
if (features[FEATURE_ANISOTROPY]) {
- code += "uniform float anisotropy_ratio : hint_range(0,256);\n";
- code += "uniform sampler2D texture_flowmap : hint_anisotropy," + texfilter_str + ";\n";
+ code += vformat(R"(
+uniform float anisotropy_ratio : hint_range(0.0, 1.0, 0.01);
+uniform sampler2D texture_flowmap : hint_anisotropy, %s;
+)",
+ texfilter_str);
}
if (features[FEATURE_AMBIENT_OCCLUSION]) {
- code += "uniform sampler2D texture_ambient_occlusion : hint_default_white, " + texfilter_str + ";\n";
- code += "uniform vec4 ao_texture_channel;\n";
- code += "uniform float ao_light_affect;\n";
+ code += vformat(R"(
+uniform sampler2D texture_ambient_occlusion : hint_default_white, %s;
+uniform vec4 ao_texture_channel;
+uniform float ao_light_affect : hint_range(0.0, 1.0, 0.01);
+)",
+ texfilter_str);
}
if (features[FEATURE_DETAIL]) {
- code += "uniform sampler2D texture_detail_albedo : source_color," + texfilter_str + ";\n";
- code += "uniform sampler2D texture_detail_normal : hint_normal," + texfilter_str + ";\n";
- code += "uniform sampler2D texture_detail_mask : hint_default_white," + texfilter_str + ";\n";
+ code += vformat(R"(
+uniform sampler2D texture_detail_albedo : source_color, %s;
+uniform sampler2D texture_detail_normal : hint_normal, %s;
+uniform sampler2D texture_detail_mask : hint_default_white, %s;
+)",
+ texfilter_str, texfilter_str, texfilter_str);
}
if (features[FEATURE_SUBSURFACE_SCATTERING]) {
- code += "uniform float subsurface_scattering_strength : hint_range(0,1);\n";
- code += "uniform sampler2D texture_subsurface_scattering : hint_default_white," + texfilter_str + ";\n";
+ code += vformat(R"(
+uniform float subsurface_scattering_strength : hint_range(0.0, 1.0, 0.01);
+uniform sampler2D texture_subsurface_scattering : hint_default_white, %s;
+)",
+ texfilter_str);
}
if (features[FEATURE_SUBSURFACE_TRANSMITTANCE]) {
- code += "uniform vec4 transmittance_color : source_color;\n";
- code += "uniform float transmittance_depth;\n";
- code += "uniform sampler2D texture_subsurface_transmittance : hint_default_white," + texfilter_str + ";\n";
- code += "uniform float transmittance_boost;\n";
+ code += vformat(R"(
+uniform vec4 transmittance_color : source_color;
+uniform float transmittance_depth : hint_range(0.001, 8.0, 0.001);
+uniform sampler2D texture_subsurface_transmittance : hint_default_white, %s;
+uniform float transmittance_boost : hint_range(0.0, 1.0, 0.01);
+)",
+ texfilter_str);
}
if (features[FEATURE_BACKLIGHT]) {
- code += "uniform vec4 backlight : source_color;\n";
- code += "uniform sampler2D texture_backlight : hint_default_black," + texfilter_str + ";\n";
+ code += vformat(R"(
+uniform vec4 backlight : source_color;
+uniform sampler2D texture_backlight : hint_default_black, %s;
+)",
+ texfilter_str);
}
if (features[FEATURE_HEIGHT_MAPPING]) {
- code += "uniform sampler2D texture_heightmap : hint_default_black," + texfilter_height_str + ";\n";
- code += "uniform float heightmap_scale;\n";
- code += "uniform int heightmap_min_layers;\n";
- code += "uniform int heightmap_max_layers;\n";
- code += "uniform vec2 heightmap_flip;\n";
+ code += vformat(R"(
+uniform sampler2D texture_heightmap : hint_default_black, %s;
+uniform float heightmap_scale : hint_range(-16.0, 16.0, 0.001);
+uniform int heightmap_min_layers : hint_range(1, 64);
+uniform int heightmap_max_layers : hint_range(1, 64);
+uniform vec2 heightmap_flip;
+)",
+ texfilter_height_str);
}
if (flags[FLAG_UV1_USE_TRIPLANAR]) {
code += "varying vec3 uv1_triplanar_pos;\n";
@@ -954,132 +1006,216 @@ void BaseMaterial3D::_update_shader() {
code += "varying vec3 uv2_triplanar_pos;\n";
}
if (flags[FLAG_UV1_USE_TRIPLANAR]) {
- code += "uniform float uv1_blend_sharpness;\n";
- code += "varying vec3 uv1_power_normal;\n";
+ code += R"(
+uniform float uv1_blend_sharpness : hint_range(0.0, 150.0, 0.001);
+varying vec3 uv1_power_normal;
+)";
}
if (flags[FLAG_UV2_USE_TRIPLANAR]) {
- code += "uniform float uv2_blend_sharpness;\n";
- code += "varying vec3 uv2_power_normal;\n";
+ code += R"(uniform float uv2_blend_sharpness : hint_range(0.0, 150.0, 0.001);
+varying vec3 uv2_power_normal;
+)";
}
- code += "uniform vec3 uv1_scale;\n";
- code += "uniform vec3 uv1_offset;\n";
- code += "uniform vec3 uv2_scale;\n";
- code += "uniform vec3 uv2_offset;\n";
-
- code += "\n\n";
+ code += R"(
+uniform vec3 uv1_scale;
+uniform vec3 uv1_offset;
+uniform vec3 uv2_scale;
+uniform vec3 uv2_offset;
+)";
- code += "void vertex() {\n";
+ // Generate vertex shader.
+ code += R"(
+void vertex() {)";
if (flags[FLAG_SRGB_VERTEX_COLOR]) {
- code += " if (!OUTPUT_IS_SRGB) {\n";
- code += " COLOR.rgb = mix(pow((COLOR.rgb + vec3(0.055)) * (1.0 / (1.0 + 0.055)), vec3(2.4)), COLOR.rgb * (1.0 / 12.92), lessThan(COLOR.rgb, vec3(0.04045)));\n";
- code += " }\n";
+ code += R"(
+ // Vertex Color is sRGB: Enabled
+ if (!OUTPUT_IS_SRGB) {
+ COLOR.rgb = mix(
+ pow((COLOR.rgb + vec3(0.055)) * (1.0 / (1.0 + 0.055)), vec3(2.4)),
+ COLOR.rgb * (1.0 / 12.92),
+ lessThan(COLOR.rgb, vec3(0.04045)));
+ }
+)";
}
if (flags[FLAG_USE_POINT_SIZE]) {
- code += " POINT_SIZE=point_size;\n";
+ code += R"(
+ // Use Point Size: Enabled
+ POINT_SIZE = point_size;
+)";
}
if (shading_mode == SHADING_MODE_PER_VERTEX) {
- code += " ROUGHNESS=roughness;\n";
+ code += R"(
+ // Shading Mode: Per Vertex
+ ROUGHNESS = roughness;
+)";
}
if (!flags[FLAG_UV1_USE_TRIPLANAR]) {
- code += " UV=UV*uv1_scale.xy+uv1_offset.xy;\n";
+ code += R"(
+ UV = UV * uv1_scale.xy + uv1_offset.xy;
+)";
+ }
+
+ if (detail_uv == DETAIL_UV_2 && !flags[FLAG_UV2_USE_TRIPLANAR]) {
+ // Don't add a newline if the UV assignment above is already performed,
+ // so that UV1 and UV2 are closer to each other.
+ if (flags[FLAG_UV1_USE_TRIPLANAR]) {
+ code += "\n";
+ }
+ code += R"( // Detail UV Layer: UV2
+ UV2 = UV2 * uv2_scale.xy + uv2_offset.xy;
+)";
}
switch (billboard_mode) {
case BILLBOARD_DISABLED: {
} break;
case BILLBOARD_ENABLED: {
- // MAIN_CAM_INV_VIEW_MATRIX is inverse of the camera, even on shadow passes: this ensures the billboard faces the camera when casting shadows.
- code += " MODELVIEW_MATRIX = VIEW_MATRIX * mat4(MAIN_CAM_INV_VIEW_MATRIX[0], MAIN_CAM_INV_VIEW_MATRIX[1], MAIN_CAM_INV_VIEW_MATRIX[2], MODEL_MATRIX[3]);\n";
-
+ // `MAIN_CAM_INV_VIEW_MATRIX` is inverse of the camera, even on shadow passes.
+ // This ensures the billboard faces the camera when casting shadows.
+ code += R"(
+ // Billboard Mode: Enabled
+ MODELVIEW_MATRIX = VIEW_MATRIX * mat4(
+ MAIN_CAM_INV_VIEW_MATRIX[0],
+ MAIN_CAM_INV_VIEW_MATRIX[1],
+ MAIN_CAM_INV_VIEW_MATRIX[2],
+ MODEL_MATRIX[3]);
+)";
if (flags[FLAG_BILLBOARD_KEEP_SCALE]) {
- code += " MODELVIEW_MATRIX = MODELVIEW_MATRIX * mat4(vec4(length(MODEL_MATRIX[0].xyz), 0.0, 0.0, 0.0), vec4(0.0, length(MODEL_MATRIX[1].xyz), 0.0, 0.0), vec4(0.0, 0.0, length(MODEL_MATRIX[2].xyz), 0.0), vec4(0.0, 0.0, 0.0, 1.0));\n";
+ code += R"(
+ // Billboard Keep Scale: Enabled
+ MODELVIEW_MATRIX = MODELVIEW_MATRIX * mat4(
+ vec4(length(MODEL_MATRIX[0].xyz), 0.0, 0.0, 0.0),
+ vec4(0.0, length(MODEL_MATRIX[1].xyz), 0.0, 0.0),
+ vec4(0.0, 0.0, length(MODEL_MATRIX[2].xyz), 0.0),
+ vec4(0.0, 0.0, 0.0, 1.0));
+)";
}
code += " MODELVIEW_NORMAL_MATRIX = mat3(MODELVIEW_MATRIX);\n";
} break;
case BILLBOARD_FIXED_Y: {
- // MAIN_CAM_INV_VIEW_MATRIX is inverse of the camera, even on shadow passes: this ensures the billboard faces the camera when casting shadows.
- code += " MODELVIEW_MATRIX = VIEW_MATRIX * mat4(vec4(normalize(cross(vec3(0.0, 1.0, 0.0), MAIN_CAM_INV_VIEW_MATRIX[2].xyz)), 0.0), vec4(0.0, 1.0, 0.0, 0.0), vec4(normalize(cross(MAIN_CAM_INV_VIEW_MATRIX[0].xyz, vec3(0.0, 1.0, 0.0))), 0.0), MODEL_MATRIX[3]);\n";
-
+ // `MAIN_CAM_INV_VIEW_MATRIX` is inverse of the camera, even on shadow passes.
+ // This ensures the billboard faces the camera when casting shadows.
+ code += R"(
+ // Billboard Mode: Y-Billboard
+ MODELVIEW_MATRIX = VIEW_MATRIX * mat4(
+ vec4(normalize(cross(vec3(0.0, 1.0, 0.0), MAIN_CAM_INV_VIEW_MATRIX[2].xyz)), 0.0),
+ vec4(0.0, 1.0, 0.0, 0.0),
+ vec4(normalize(cross(MAIN_CAM_INV_VIEW_MATRIX[0].xyz, vec3(0.0, 1.0, 0.0))), 0.0),
+ MODEL_MATRIX[3]);
+)";
if (flags[FLAG_BILLBOARD_KEEP_SCALE]) {
- code += " MODELVIEW_MATRIX = MODELVIEW_MATRIX * mat4(vec4(length(MODEL_MATRIX[0].xyz), 0.0, 0.0, 0.0), vec4(0.0, length(MODEL_MATRIX[1].xyz), 0.0, 0.0), vec4(0.0, 0.0, length(MODEL_MATRIX[2].xyz), 0.0), vec4(0.0, 0.0, 0.0, 1.0));\n";
+ code += R"(
+ // Billboard Keep Scale: Enabled
+ MODELVIEW_MATRIX = MODELVIEW_MATRIX * mat4(
+ vec4(length(MODEL_MATRIX[0].xyz), 0.0, 0.0, 0.0),
+ vec4(0.0, length(MODEL_MATRIX[1].xyz), 0.0, 0.0),
+ vec4(0.0, 0.0, length(MODEL_MATRIX[2].xyz), 0.0),
+ vec4(0.0, 0.0, 0.0, 1.0));
+)";
}
code += " MODELVIEW_NORMAL_MATRIX = mat3(MODELVIEW_MATRIX);\n";
} break;
case BILLBOARD_PARTICLES: {
- //make billboard
- code += " mat4 mat_world = mat4(normalize(INV_VIEW_MATRIX[0]), normalize(INV_VIEW_MATRIX[1]) ,normalize(INV_VIEW_MATRIX[2]), MODEL_MATRIX[3]);\n";
- //rotate by rotation
- code += " mat_world = mat_world * mat4(vec4(cos(INSTANCE_CUSTOM.x), -sin(INSTANCE_CUSTOM.x), 0.0, 0.0), vec4(sin(INSTANCE_CUSTOM.x), cos(INSTANCE_CUSTOM.x), 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));\n";
- //set modelview
+ // Make billboard and rotated by rotation.
+ code += R"(
+ // Billboard Mode: Particles
+ mat4 mat_world = mat4(
+ normalize(INV_VIEW_MATRIX[0]),
+ normalize(INV_VIEW_MATRIX[1]),
+ normalize(INV_VIEW_MATRIX[2]),
+ MODEL_MATRIX[3]);
+ mat_world = mat_world * mat4(
+ vec4(cos(INSTANCE_CUSTOM.x), -sin(INSTANCE_CUSTOM.x), 0.0, 0.0),
+ vec4(sin(INSTANCE_CUSTOM.x), cos(INSTANCE_CUSTOM.x), 0.0, 0.0),
+ vec4(0.0, 0.0, 1.0, 0.0),
+ vec4(0.0, 0.0, 0.0, 1.0));
+)";
+ // Set modelview.
code += " MODELVIEW_MATRIX = VIEW_MATRIX * mat_world;\n";
if (flags[FLAG_BILLBOARD_KEEP_SCALE]) {
- code += " MODELVIEW_MATRIX = MODELVIEW_MATRIX * mat4(vec4(length(MODEL_MATRIX[0].xyz), 0.0, 0.0, 0.0),vec4(0.0, length(MODEL_MATRIX[1].xyz), 0.0, 0.0), vec4(0.0, 0.0, length(MODEL_MATRIX[2].xyz), 0.0), vec4(0.0, 0.0, 0.0, 1.0));\n";
+ code += R"(
+ // Billboard Keep Scale: Enabled
+ MODELVIEW_MATRIX = MODELVIEW_MATRIX * mat4(
+ vec4(length(MODEL_MATRIX[0].xyz), 0.0, 0.0, 0.0),
+ vec4(0.0, length(MODEL_MATRIX[1].xyz), 0.0, 0.0),
+ vec4(0.0, 0.0, length(MODEL_MATRIX[2].xyz), 0.0),
+ vec4(0.0, 0.0, 0.0, 1.0));
+)";
}
- //set modelview normal
- code += " MODELVIEW_NORMAL_MATRIX = mat3(MODELVIEW_MATRIX);\n";
-
- //handle animation
- code += " float h_frames = float(particles_anim_h_frames);\n";
- code += " float v_frames = float(particles_anim_v_frames);\n";
- code += " float particle_total_frames = float(particles_anim_h_frames * particles_anim_v_frames);\n";
- code += " float particle_frame = floor(INSTANCE_CUSTOM.z * float(particle_total_frames));\n";
- code += " if (!particles_anim_loop) {\n";
- code += " particle_frame = clamp(particle_frame, 0.0, particle_total_frames - 1.0);\n";
- code += " } else {\n";
- code += " particle_frame = mod(particle_frame, particle_total_frames);\n";
- code += " }\n";
- code += " UV /= vec2(h_frames, v_frames);\n";
- code += " UV += vec2(mod(particle_frame, h_frames) / h_frames, floor((particle_frame + 0.5) / h_frames) / v_frames);\n";
+ // Set modelview normal and handle animation.
+ code += R"(
+ MODELVIEW_NORMAL_MATRIX = mat3(MODELVIEW_MATRIX);
+
+ float h_frames = float(particles_anim_h_frames);
+ float v_frames = float(particles_anim_v_frames);
+ float particle_total_frames = float(particles_anim_h_frames * particles_anim_v_frames);
+ float particle_frame = floor(INSTANCE_CUSTOM.z * float(particle_total_frames));
+ if (!particles_anim_loop) {
+ particle_frame = clamp(particle_frame, 0.0, particle_total_frames - 1.0);
+ } else {
+ particle_frame = mod(particle_frame, particle_total_frames);
+ }
+ UV /= vec2(h_frames, v_frames);
+ UV += vec2(mod(particle_frame, h_frames) / h_frames, floor((particle_frame + 0.5) / h_frames) / v_frames);
+)";
} break;
case BILLBOARD_MAX:
break; // Internal value, skip.
}
if (flags[FLAG_FIXED_SIZE]) {
- code += " if (PROJECTION_MATRIX[3][3] != 0.0) {\n";
- //orthogonal matrix, try to do about the same
- //with viewport size
- code += " float h = abs(1.0 / (2.0 * PROJECTION_MATRIX[1][1]));\n";
- code += " float sc = (h * 2.0); //consistent with Y-fov\n";
- code += " MODELVIEW_MATRIX[0]*=sc;\n";
- code += " MODELVIEW_MATRIX[1]*=sc;\n";
- code += " MODELVIEW_MATRIX[2]*=sc;\n";
- code += " } else {\n";
- //just scale by depth
- code += " float sc = -(MODELVIEW_MATRIX)[3].z;\n";
- code += " MODELVIEW_MATRIX[0]*=sc;\n";
- code += " MODELVIEW_MATRIX[1]*=sc;\n";
- code += " MODELVIEW_MATRIX[2]*=sc;\n";
- code += " }\n";
+ code += R"(
+ // Fixed Size: Enabled
+ if (PROJECTION_MATRIX[3][3] != 0.0) {
+ // Orthogonal matrix; try to do about the same with viewport size.
+ float h = abs(1.0 / (2.0 * PROJECTION_MATRIX[1][1]));
+ // Consistent with vertical FOV (Keep Height).
+ float sc = (h * 2.0);
+ MODELVIEW_MATRIX[0] *= sc;
+ MODELVIEW_MATRIX[1] *= sc;
+ MODELVIEW_MATRIX[2] *= sc;
+ } else {
+ // Scale by depth.
+ float sc = -(MODELVIEW_MATRIX)[3].z;
+ MODELVIEW_MATRIX[0] *= sc;
+ MODELVIEW_MATRIX[1] *= sc;
+ MODELVIEW_MATRIX[2] *= sc;
}
-
- if (detail_uv == DETAIL_UV_2 && !flags[FLAG_UV2_USE_TRIPLANAR]) {
- code += " UV2=UV2*uv2_scale.xy+uv2_offset.xy;\n";
+)";
}
+
if (flags[FLAG_UV1_USE_TRIPLANAR] || flags[FLAG_UV2_USE_TRIPLANAR]) {
- //generate tangent and binormal in world space
+ // Generate tangent and binormal in world space.
if (flags[FLAG_UV1_USE_WORLD_TRIPLANAR]) {
- code += " vec3 normal = MODEL_NORMAL_MATRIX * NORMAL;\n";
+ code += R"(
+ vec3 normal = MODEL_NORMAL_MATRIX * NORMAL;
+)";
} else {
- code += " vec3 normal = NORMAL;\n";
- }
- code += " TANGENT = vec3(0.0,0.0,-1.0) * abs(normal.x);\n";
- code += " TANGENT+= vec3(1.0,0.0,0.0) * abs(normal.y);\n";
- code += " TANGENT+= vec3(1.0,0.0,0.0) * abs(normal.z);\n";
+ code += R"(
+ vec3 normal = NORMAL;
+)";
+ }
+ code += R"(
+ TANGENT = vec3(0.0, 0.0, -1.0) * abs(normal.x);
+ TANGENT += vec3(1.0, 0.0, 0.0) * abs(normal.y);
+ TANGENT += vec3(1.0, 0.0, 0.0) * abs(normal.z);
+)";
if (flags[FLAG_UV1_USE_WORLD_TRIPLANAR]) {
code += " TANGENT = inverse(MODEL_NORMAL_MATRIX) * normalize(TANGENT);\n";
} else {
code += " TANGENT = normalize(TANGENT);\n";
}
- code += " BINORMAL = vec3(0.0,1.0,0.0) * abs(normal.x);\n";
- code += " BINORMAL+= vec3(0.0,0.0,-1.0) * abs(normal.y);\n";
- code += " BINORMAL+= vec3(0.0,1.0,0.0) * abs(normal.z);\n";
+ code += R"(
+ BINORMAL = vec3(0.0, 1.0, 0.0) * abs(normal.x);
+ BINORMAL += vec3(0.0, 0.0, -1.0) * abs(normal.y);
+ BINORMAL += vec3(0.0, 1.0, 0.0) * abs(normal.z);
+)";
if (flags[FLAG_UV1_USE_WORLD_TRIPLANAR]) {
code += " BINORMAL = inverse(MODEL_NORMAL_MATRIX) * normalize(BINORMAL);\n";
} else {
@@ -1089,58 +1225,89 @@ void BaseMaterial3D::_update_shader() {
if (flags[FLAG_UV1_USE_TRIPLANAR]) {
if (flags[FLAG_UV1_USE_WORLD_TRIPLANAR]) {
- code += " uv1_power_normal=pow(abs(normal),vec3(uv1_blend_sharpness));\n";
- code += " uv1_triplanar_pos = (MODEL_MATRIX * vec4(VERTEX, 1.0f)).xyz * uv1_scale + uv1_offset;\n";
+ code += R"(
+ // UV1 Triplanar: Enabled (with World Triplanar)
+ uv1_power_normal = pow(abs(normal), vec3(uv1_blend_sharpness));
+ uv1_triplanar_pos = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz * uv1_scale + uv1_offset;
+)";
} else {
- code += " uv1_power_normal=pow(abs(NORMAL),vec3(uv1_blend_sharpness));\n";
- code += " uv1_triplanar_pos = VERTEX * uv1_scale + uv1_offset;\n";
+ code += R"(
+ // UV1 Triplanar: Enabled
+ uv1_power_normal = pow(abs(NORMAL), vec3(uv1_blend_sharpness));
+ uv1_triplanar_pos = VERTEX * uv1_scale + uv1_offset;
+)";
}
- code += " uv1_power_normal/=dot(uv1_power_normal,vec3(1.0));\n";
- code += " uv1_triplanar_pos *= vec3(1.0,-1.0, 1.0);\n";
+ code += R"( uv1_power_normal /= dot(uv1_power_normal, vec3(1.0));
+ uv1_triplanar_pos *= vec3(1.0, -1.0, 1.0);
+)";
}
if (flags[FLAG_UV2_USE_TRIPLANAR]) {
if (flags[FLAG_UV2_USE_WORLD_TRIPLANAR]) {
- code += " uv2_power_normal=pow(abs(mat3(MODEL_MATRIX) * NORMAL), vec3(uv2_blend_sharpness));\n";
- code += " uv2_triplanar_pos = (MODEL_MATRIX * vec4(VERTEX, 1.0f)).xyz * uv2_scale + uv2_offset;\n";
+ code += R"(
+ // UV2 Triplanar: Enabled (with World Triplanar)
+ uv2_power_normal = pow(abs(mat3(MODEL_MATRIX) * NORMAL), vec3(uv2_blend_sharpness));
+ uv2_triplanar_pos = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz * uv2_scale + uv2_offset;
+)";
} else {
- code += " uv2_power_normal=pow(abs(NORMAL), vec3(uv2_blend_sharpness));\n";
- code += " uv2_triplanar_pos = VERTEX * uv2_scale + uv2_offset;\n";
+ code += R"(
+ // UV2 Triplanar: Enabled
+ uv2_power_normal = pow(abs(NORMAL), vec3(uv2_blend_sharpness));
+ uv2_triplanar_pos = VERTEX * uv2_scale + uv2_offset;
+)";
}
- code += " uv2_power_normal/=dot(uv2_power_normal,vec3(1.0));\n";
- code += " uv2_triplanar_pos *= vec3(1.0,-1.0, 1.0);\n";
+ code += R"( uv2_power_normal /= dot(uv2_power_normal, vec3(1.0));
+ uv2_triplanar_pos *= vec3(1.0, -1.0, 1.0);
+)";
}
if (grow_enabled) {
- code += " VERTEX+=NORMAL*grow;\n";
+ code += R"(
+ // Grow: Enabled
+ VERTEX += NORMAL * grow;
+)";
}
code += "}\n";
- code += "\n\n";
+
if (flags[FLAG_ALBEDO_TEXTURE_MSDF]) {
- code += "float msdf_median(float r, float g, float b, float a) {\n";
- code += " return min(max(min(r, g), min(max(r, g), b)), a);\n";
- code += "}\n";
+ code += R"(
+float msdf_median(float r, float g, float b, float a) {
+ return min(max(min(r, g), min(max(r, g), b)), a);
+}
+)";
}
- code += "\n\n";
+
if (flags[FLAG_UV1_USE_TRIPLANAR] || flags[FLAG_UV2_USE_TRIPLANAR]) {
- code += "vec4 triplanar_texture(sampler2D p_sampler,vec3 p_weights,vec3 p_triplanar_pos) {\n";
- code += " vec4 samp=vec4(0.0);\n";
- code += " samp+= texture(p_sampler,p_triplanar_pos.xy) * p_weights.z;\n";
- code += " samp+= texture(p_sampler,p_triplanar_pos.xz) * p_weights.y;\n";
- code += " samp+= texture(p_sampler,p_triplanar_pos.zy * vec2(-1.0,1.0)) * p_weights.x;\n";
- code += " return samp;\n";
- code += "}\n";
+ code += R"(
+vec4 triplanar_texture(sampler2D p_sampler, vec3 p_weights, vec3 p_triplanar_pos) {
+ vec4 samp = vec4(0.0);
+ samp += texture(p_sampler, p_triplanar_pos.xy) * p_weights.z;
+ samp += texture(p_sampler, p_triplanar_pos.xz) * p_weights.y;
+ samp += texture(p_sampler, p_triplanar_pos.zy * vec2(-1.0, 1.0)) * p_weights.x;
+ return samp;
+}
+)";
}
- code += "\n\n";
- code += "void fragment() {\n";
+
+ // Generate fragment shader.
+ code += R"(
+void fragment() {)";
if (!flags[FLAG_UV1_USE_TRIPLANAR]) {
- code += " vec2 base_uv = UV;\n";
+ code += R"(
+ vec2 base_uv = UV;
+)";
}
if ((features[FEATURE_DETAIL] && detail_uv == DETAIL_UV_2) || (features[FEATURE_AMBIENT_OCCLUSION] && flags[FLAG_AO_ON_UV2]) || (features[FEATURE_EMISSION] && flags[FLAG_EMISSION_ON_UV2])) {
- code += " vec2 base_uv2 = UV2;\n";
+ // Don't add a newline if the UV assignment above is already performed,
+ // so that UV1 and UV2 are closer to each other.
+ if (flags[FLAG_UV1_USE_TRIPLANAR]) {
+ code += "\n";
+ }
+ code += R"( vec2 base_uv2 = UV2;
+)";
}
if (features[FEATURE_HEIGHT_MAPPING] && flags[FLAG_UV1_USE_TRIPLANAR]) {
@@ -1157,42 +1324,57 @@ void BaseMaterial3D::_update_shader() {
}
}
- if (!RenderingServer::get_singleton()->is_low_end() && features[FEATURE_HEIGHT_MAPPING] && !flags[FLAG_UV1_USE_TRIPLANAR]) { //heightmap not supported with triplanar
- code += " {\n";
- code += " vec3 view_dir = normalize(normalize(-VERTEX + EYE_OFFSET) * mat3(TANGENT * heightmap_flip.x, -BINORMAL * heightmap_flip.y, NORMAL));\n"; // binormal is negative due to mikktspace, flip 'unflips' it ;-)
+ // Heightmapping isn't supported at the same time as triplanar mapping.
+ if (!RenderingServer::get_singleton()->is_low_end() && features[FEATURE_HEIGHT_MAPPING] && !flags[FLAG_UV1_USE_TRIPLANAR]) {
+ // Binormal is negative due to mikktspace. Flipping it "unflips" it.
+ code += R"(
+ {
+ // Height: Enabled
+ vec3 view_dir = normalize(normalize(-VERTEX + EYE_OFFSET) * mat3(TANGENT * heightmap_flip.x, -BINORMAL * heightmap_flip.y, NORMAL));
+)";
if (deep_parallax) {
- code += " float num_layers = mix(float(heightmap_max_layers),float(heightmap_min_layers), abs(dot(vec3(0.0, 0.0, 1.0), view_dir)));\n";
- code += " float layer_depth = 1.0 / num_layers;\n";
- code += " float current_layer_depth = 0.0;\n";
// Multiply the heightmap scale by 0.01 to improve heightmap scale usability.
- code += " vec2 P = view_dir.xy * heightmap_scale * 0.01;\n";
- code += " vec2 delta = P / num_layers;\n";
- code += " vec2 ofs = base_uv;\n";
+ code += R"(
+ // Height Deep Parallax: Enabled
+ float num_layers = mix(float(heightmap_max_layers), float(heightmap_min_layers), abs(dot(vec3(0.0, 0.0, 1.0), view_dir)));
+ float layer_depth = 1.0 / num_layers;
+ float current_layer_depth = 0.0;
+ vec2 p = view_dir.xy * heightmap_scale * 0.01;
+ vec2 delta = p / num_layers;
+ vec2 ofs = base_uv;
+)";
if (flags[FLAG_INVERT_HEIGHTMAP]) {
code += " float depth = texture(texture_heightmap, ofs).r;\n";
} else {
code += " float depth = 1.0 - texture(texture_heightmap, ofs).r;\n";
}
- code += " float current_depth = 0.0;\n";
- code += " while(current_depth < depth) {\n";
- code += " ofs -= delta;\n";
+ code += R"(
+ float current_depth = 0.0;
+ while (current_depth < depth) {
+ ofs -= delta;
+)";
if (flags[FLAG_INVERT_HEIGHTMAP]) {
code += " depth = texture(texture_heightmap, ofs).r;\n";
} else {
code += " depth = 1.0 - texture(texture_heightmap, ofs).r;\n";
}
- code += " current_depth += layer_depth;\n";
- code += " }\n";
- code += " vec2 prev_ofs = ofs + delta;\n";
- code += " float after_depth = depth - current_depth;\n";
+ code += R"(
+ current_depth += layer_depth;
+ }
+
+ vec2 prev_ofs = ofs + delta;
+ float after_depth = depth - current_depth;
+)";
if (flags[FLAG_INVERT_HEIGHTMAP]) {
code += " float before_depth = texture(texture_heightmap, prev_ofs).r - current_depth + layer_depth;\n";
} else {
- code += " float before_depth = ( 1.0 - texture(texture_heightmap, prev_ofs).r ) - current_depth + layer_depth;\n";
+ code += " float before_depth = (1.0 - texture(texture_heightmap, prev_ofs).r) - current_depth + layer_depth;\n";
}
- code += " float weight = after_depth / (after_depth - before_depth);\n";
- code += " ofs = mix(ofs,prev_ofs,weight);\n";
+ code += R"(
+ float weight = after_depth / (after_depth - before_depth);
+ ofs = mix(ofs, prev_ofs, weight);
+)";
} else {
if (flags[FLAG_INVERT_HEIGHTMAP]) {
@@ -1206,28 +1388,41 @@ void BaseMaterial3D::_update_shader() {
code += " vec2 ofs = base_uv - view_dir.xy * depth * heightmap_scale * 0.01;\n";
}
- code += " base_uv=ofs;\n";
+ code += " base_uv = ofs;\n";
if (features[FEATURE_DETAIL] && detail_uv == DETAIL_UV_2) {
- code += " base_uv2-=ofs;\n";
+ code += " base_uv2 -= ofs;\n";
}
code += " }\n";
}
if (flags[FLAG_USE_POINT_SIZE]) {
- code += " vec4 albedo_tex = texture(texture_albedo,POINT_COORD);\n";
+ code += R"(
+ // Use Point Size: Enabled
+ vec4 albedo_tex = texture(texture_albedo, POINT_COORD);
+)";
} else {
if (flags[FLAG_UV1_USE_TRIPLANAR]) {
- code += " vec4 albedo_tex = triplanar_texture(texture_albedo,uv1_power_normal,uv1_triplanar_pos);\n";
+ code += R"(
+ vec4 albedo_tex = triplanar_texture(texture_albedo, uv1_power_normal, uv1_triplanar_pos);
+)";
} else {
- code += " vec4 albedo_tex = texture(texture_albedo,base_uv);\n";
+ code += R"(
+ vec4 albedo_tex = texture(texture_albedo, base_uv);
+)";
}
}
if (flags[FLAG_ALBEDO_TEXTURE_MSDF]) {
- code += " {\n";
- code += " albedo_tex.rgb = mix(vec3(1.0 + 0.055) * pow(albedo_tex.rgb, vec3(1.0 / 2.4)) - vec3(0.055), vec3(12.92) * albedo_tex.rgb.rgb, lessThan(albedo_tex.rgb, vec3(0.0031308)));\n";
- code += " vec2 msdf_size = vec2(msdf_pixel_range) / vec2(textureSize(texture_albedo, 0));\n";
+ code += R"(
+ {
+ // Albedo Texture MSDF: Enabled
+ albedo_tex.rgb = mix(
+ vec3(1.0 + 0.055) * pow(albedo_tex.rgb, vec3(1.0 / 2.4)) - vec3(0.055),
+ vec3(12.92) * albedo_tex.rgb,
+ lessThan(albedo_tex.rgb, vec3(0.0031308)));
+ vec2 msdf_size = vec2(msdf_pixel_range) / vec2(textureSize(texture_albedo, 0));
+)";
if (flags[FLAG_USE_POINT_SIZE]) {
code += " vec2 dest_size = vec2(1.0) / fwidth(POINT_COORD);\n";
} else {
@@ -1237,120 +1432,175 @@ void BaseMaterial3D::_update_shader() {
code += " vec2 dest_size = vec2(1.0) / fwidth(base_uv);\n";
}
}
- code += " float px_size = max(0.5 * dot(msdf_size, dest_size), 1.0);\n";
- code += " float d = msdf_median(albedo_tex.r, albedo_tex.g, albedo_tex.b, albedo_tex.a) - 0.5;\n";
- code += " if (msdf_outline_size > 0.0) {\n";
- code += " float cr = clamp(msdf_outline_size, 0.0, msdf_pixel_range / 2.0) / msdf_pixel_range;\n";
- code += " albedo_tex.a = clamp((d + cr) * px_size, 0.0, 1.0);\n";
- code += " } else {\n";
- code += " albedo_tex.a = clamp(d * px_size + 0.5, 0.0, 1.0);\n";
- code += " }\n";
- code += " albedo_tex.rgb = vec3(1.0);\n";
- code += " }\n";
+ code += R"(
+ float px_size = max(0.5 * dot(msdf_size, dest_size), 1.0);
+ float d = msdf_median(albedo_tex.r, albedo_tex.g, albedo_tex.b, albedo_tex.a) - 0.5;
+ if (msdf_outline_size > 0.0) {
+ float cr = clamp(msdf_outline_size, 0.0, msdf_pixel_range / 2.0) / msdf_pixel_range;
+ albedo_tex.a = clamp((d + cr) * px_size, 0.0, 1.0);
+ } else {
+ albedo_tex.a = clamp(d * px_size + 0.5, 0.0, 1.0);
+ }
+ albedo_tex.rgb = vec3(1.0);
+ }
+)";
} else if (flags[FLAG_ALBEDO_TEXTURE_FORCE_SRGB]) {
- code += " albedo_tex.rgb = mix(pow((albedo_tex.rgb + vec3(0.055)) * (1.0 / (1.0 + 0.055)),vec3(2.4)),albedo_tex.rgb.rgb * (1.0 / 12.92),lessThan(albedo_tex.rgb,vec3(0.04045)));\n";
+ code += R"(
+ // Albedo Texture Force sRGB: Enabled
+ albedo_tex.rgb = mix(
+ pow((albedo_tex.rgb + vec3(0.055)) * (1.0 / (1.0 + 0.055)), vec3(2.4)),
+ albedo_tex.rgb.rgb * (1.0 / 12.92),
+ lessThan(albedo_tex.rgb, vec3(0.04045)));
+)";
}
if (flags[FLAG_ALBEDO_FROM_VERTEX_COLOR]) {
- code += " albedo_tex *= COLOR;\n";
+ code += R"(
+ // Vertex Color Use as Albedo: Enabled
+ albedo_tex *= COLOR;
+
+)";
}
code += " ALBEDO = albedo.rgb * albedo_tex.rgb;\n";
if (!orm) {
if (flags[FLAG_UV1_USE_TRIPLANAR]) {
- code += " float metallic_tex = dot(triplanar_texture(texture_metallic,uv1_power_normal,uv1_triplanar_pos),metallic_texture_channel);\n";
+ code += R"(
+ float metallic_tex = dot(triplanar_texture(texture_metallic, uv1_power_normal, uv1_triplanar_pos), metallic_texture_channel);
+)";
} else {
- code += " float metallic_tex = dot(texture(texture_metallic,base_uv),metallic_texture_channel);\n";
+ code += R"(
+ float metallic_tex = dot(texture(texture_metallic, base_uv), metallic_texture_channel);
+)";
}
- code += " METALLIC = metallic_tex * metallic;\n";
+ code += R"( METALLIC = metallic_tex * metallic;
+ SPECULAR = specular;
+)";
switch (roughness_texture_channel) {
case TEXTURE_CHANNEL_RED: {
- code += " vec4 roughness_texture_channel = vec4(1.0,0.0,0.0,0.0);\n";
+ code += R"(
+ vec4 roughness_texture_channel = vec4(1.0, 0.0, 0.0, 0.0);
+)";
} break;
case TEXTURE_CHANNEL_GREEN: {
- code += " vec4 roughness_texture_channel = vec4(0.0,1.0,0.0,0.0);\n";
+ code += R"(
+ vec4 roughness_texture_channel = vec4(0.0, 1.0, 0.0, 0.0);
+)";
} break;
case TEXTURE_CHANNEL_BLUE: {
- code += " vec4 roughness_texture_channel = vec4(0.0,0.0,1.0,0.0);\n";
+ code += R"(
+ vec4 roughness_texture_channel = vec4(0.0, 0.0, 1.0, 0.0);
+)";
} break;
case TEXTURE_CHANNEL_ALPHA: {
- code += " vec4 roughness_texture_channel = vec4(0.0,0.0,0.0,1.0);\n";
+ code += R"(
+ vec4 roughness_texture_channel = vec4(0.0, 0.0, 0.0, 1.0);
+)";
} break;
case TEXTURE_CHANNEL_GRAYSCALE: {
- code += " vec4 roughness_texture_channel = vec4(0.333333,0.333333,0.333333,0.0);\n";
+ code += R"(
+ vec4 roughness_texture_channel = vec4(0.333333, 0.333333, 0.333333, 0.0);
+)";
} break;
case TEXTURE_CHANNEL_MAX:
break; // Internal value, skip.
}
if (flags[FLAG_UV1_USE_TRIPLANAR]) {
- code += " float roughness_tex = dot(triplanar_texture(texture_roughness,uv1_power_normal,uv1_triplanar_pos),roughness_texture_channel);\n";
+ code += " float roughness_tex = dot(triplanar_texture(texture_roughness, uv1_power_normal, uv1_triplanar_pos), roughness_texture_channel);\n";
} else {
- code += " float roughness_tex = dot(texture(texture_roughness,base_uv),roughness_texture_channel);\n";
+ code += " float roughness_tex = dot(texture(texture_roughness, base_uv), roughness_texture_channel);\n";
}
- code += " ROUGHNESS = roughness_tex * roughness;\n";
- code += " SPECULAR = specular;\n";
+ code += R"( ROUGHNESS = roughness_tex * roughness;
+)";
} else {
if (flags[FLAG_UV1_USE_TRIPLANAR]) {
- code += " vec4 orm_tex = triplanar_texture(texture_orm,uv1_power_normal,uv1_triplanar_pos);\n";
+ code += R"(
+ vec4 orm_tex = triplanar_texture(texture_orm, uv1_power_normal, uv1_triplanar_pos);
+)";
} else {
- code += " vec4 orm_tex = texture(texture_orm,base_uv);\n";
+ code += R"(
+ vec4 orm_tex = texture(texture_orm, base_uv);
+)";
}
- code += " ROUGHNESS = orm_tex.g;\n";
- code += " METALLIC = orm_tex.b;\n";
+ code += R"( ROUGHNESS = orm_tex.g;
+ METALLIC = orm_tex.b;
+)";
}
if (features[FEATURE_NORMAL_MAPPING]) {
+ code += R"(
+ // Normal Map: Enabled
+)";
if (flags[FLAG_UV1_USE_TRIPLANAR]) {
- code += " NORMAL_MAP = triplanar_texture(texture_normal,uv1_power_normal,uv1_triplanar_pos).rgb;\n";
+ code += " NORMAL_MAP = triplanar_texture(texture_normal, uv1_power_normal, uv1_triplanar_pos).rgb;\n";
} else {
- code += " NORMAL_MAP = texture(texture_normal,base_uv).rgb;\n";
+ code += " NORMAL_MAP = texture(texture_normal, base_uv).rgb;\n";
}
code += " NORMAL_MAP_DEPTH = normal_scale;\n";
}
if (features[FEATURE_EMISSION]) {
+ code += R"(
+ // Emission: Enabled
+)";
if (flags[FLAG_EMISSION_ON_UV2]) {
if (flags[FLAG_UV2_USE_TRIPLANAR]) {
- code += " vec3 emission_tex = triplanar_texture(texture_emission,uv2_power_normal,uv2_triplanar_pos).rgb;\n";
+ code += " vec3 emission_tex = triplanar_texture(texture_emission, uv2_power_normal, uv2_triplanar_pos).rgb;\n";
} else {
- code += " vec3 emission_tex = texture(texture_emission,base_uv2).rgb;\n";
+ code += " vec3 emission_tex = texture(texture_emission, base_uv2).rgb;\n";
}
} else {
if (flags[FLAG_UV1_USE_TRIPLANAR]) {
- code += " vec3 emission_tex = triplanar_texture(texture_emission,uv1_power_normal,uv1_triplanar_pos).rgb;\n";
+ code += " vec3 emission_tex = triplanar_texture(texture_emission, uv1_power_normal, uv1_triplanar_pos).rgb;\n";
} else {
- code += " vec3 emission_tex = texture(texture_emission,base_uv).rgb;\n";
+ code += " vec3 emission_tex = texture(texture_emission, base_uv).rgb;\n";
}
}
if (emission_op == EMISSION_OP_ADD) {
- code += " EMISSION = (emission.rgb+emission_tex)*emission_energy;\n";
+ code += R"( // Emission Operator: Add
+ EMISSION = (emission.rgb + emission_tex) * emission_energy;
+)";
} else {
- code += " EMISSION = (emission.rgb*emission_tex)*emission_energy;\n";
+ code += R"( // Emission Operator: Multiply
+ EMISSION = (emission.rgb * emission_tex) * emission_energy;
+)";
}
}
if (features[FEATURE_REFRACTION]) {
if (features[FEATURE_NORMAL_MAPPING]) {
- code += " vec3 unpacked_normal = NORMAL_MAP;\n";
- code += " unpacked_normal.xy = unpacked_normal.xy * 2.0 - 1.0;\n";
- code += " unpacked_normal.z = sqrt(max(0.0, 1.0 - dot(unpacked_normal.xy, unpacked_normal.xy)));\n";
- code += " vec3 ref_normal = normalize( mix(NORMAL,TANGENT * unpacked_normal.x + BINORMAL * unpacked_normal.y + NORMAL * unpacked_normal.z,NORMAL_MAP_DEPTH) );\n";
+ code += R"(
+ // Refraction: Enabled (with normal map texture)
+ vec3 unpacked_normal = NORMAL_MAP;
+ unpacked_normal.xy = unpacked_normal.xy * 2.0 - 1.0;
+ unpacked_normal.z = sqrt(max(0.0, 1.0 - dot(unpacked_normal.xy, unpacked_normal.xy)));
+ vec3 ref_normal = normalize(mix(
+ NORMAL,
+ TANGENT * unpacked_normal.x + BINORMAL * unpacked_normal.y + NORMAL * unpacked_normal.z,
+ NORMAL_MAP_DEPTH));
+)";
} else {
- code += " vec3 ref_normal = NORMAL;\n";
+ code += R"(
+ // Refraction: Enabled
+ vec3 ref_normal = NORMAL;
+)";
}
if (flags[FLAG_UV1_USE_TRIPLANAR]) {
- code += " vec2 ref_ofs = SCREEN_UV - ref_normal.xy * dot(triplanar_texture(texture_refraction,uv1_power_normal,uv1_triplanar_pos),refraction_texture_channel) * refraction;\n";
+ code += " vec2 ref_ofs = SCREEN_UV - ref_normal.xy * dot(triplanar_texture(texture_refraction, uv1_power_normal, uv1_triplanar_pos), refraction_texture_channel) * refraction;\n";
} else {
- code += " vec2 ref_ofs = SCREEN_UV - ref_normal.xy * dot(texture(texture_refraction,base_uv),refraction_texture_channel) * refraction;\n";
+ code += " vec2 ref_ofs = SCREEN_UV - ref_normal.xy * dot(texture(texture_refraction, base_uv), refraction_texture_channel) * refraction;\n";
}
- code += " float ref_amount = 1.0 - albedo.a * albedo_tex.a;\n";
- code += " EMISSION += textureLod(screen_texture,ref_ofs,ROUGHNESS * 8.0).rgb * ref_amount * EXPOSURE;\n";
- code += " ALBEDO *= 1.0 - ref_amount;\n";
- code += " ALPHA = 1.0;\n";
+ code += R"(
+ float ref_amount = 1.0 - albedo.a * albedo_tex.a;
+ EMISSION += textureLod(screen_texture, ref_ofs, ROUGHNESS * 8.0).rgb * ref_amount * EXPOSURE;
+ ALBEDO *= 1.0 - ref_amount;
+ // Force transparency on the material (required for refraction).
+ ALPHA = 1.0;
+)";
} else if (transparency != TRANSPARENCY_DISABLED || flags[FLAG_USE_SHADOW_TO_OPACITY] || (distance_fade == DISTANCE_FADE_PIXEL_ALPHA) || proximity_fade_enabled) {
code += " ALPHA *= albedo.a * albedo_tex.a;\n";
@@ -1366,10 +1616,13 @@ void BaseMaterial3D::_update_shader() {
}
if (proximity_fade_enabled) {
- code += " float depth_tex = textureLod(depth_texture,SCREEN_UV,0.0).r;\n";
- code += " vec4 world_pos = INV_PROJECTION_MATRIX * vec4(SCREEN_UV*2.0-1.0,depth_tex,1.0);\n";
- code += " world_pos.xyz/=world_pos.w;\n";
- code += " ALPHA*=clamp(1.0-smoothstep(world_pos.z+proximity_fade_distance,world_pos.z,VERTEX.z),0.0,1.0);\n";
+ code += R"(
+ // Proximity Fade: Enabled
+ float depth_tex = textureLod(depth_texture, SCREEN_UV, 0.0).r;
+ vec4 world_pos = INV_PROJECTION_MATRIX * vec4(SCREEN_UV * 2.0 - 1.0, depth_tex, 1.0);
+ world_pos.xyz /= world_pos.w;
+ ALPHA *= clamp(1.0 - smoothstep(world_pos.z + proximity_fade_distance, world_pos.z, VERTEX.z), 0.0, 1.0);
+)";
}
if (distance_fade != DISTANCE_FADE_DISABLED) {
@@ -1377,72 +1630,96 @@ void BaseMaterial3D::_update_shader() {
// (Z distance), so that the fade is always the same regardless of the camera angle.
if ((distance_fade == DISTANCE_FADE_OBJECT_DITHER || distance_fade == DISTANCE_FADE_PIXEL_DITHER)) {
if (!RenderingServer::get_singleton()->is_low_end()) {
- code += " {\n";
+ code += "\n {";
if (distance_fade == DISTANCE_FADE_OBJECT_DITHER) {
- code += " float fade_distance = length((VIEW_MATRIX * MODEL_MATRIX[3]));\n";
+ code += R"(
+ // Distance Fade: Object Dither
+ float fade_distance = length((VIEW_MATRIX * MODEL_MATRIX[3]));
+)";
} else {
- code += " float fade_distance = length(VERTEX);\n";
+ code += R"(
+ // Distance Fade: Pixel Dither
+ float fade_distance = length(VERTEX);
+)";
}
- // Use interleaved gradient noise, which is fast but still looks good.
- code += " const vec3 magic = vec3(0.06711056f, 0.00583715f, 52.9829189f);";
- code += " float fade = clamp(smoothstep(distance_fade_min, distance_fade_max, fade_distance), 0.0, 1.0);\n";
- // Use a hard cap to prevent a few stray pixels from remaining when past the fade-out distance.
- code += " if (fade < 0.001 || fade < fract(magic.z * fract(dot(FRAGCOORD.xy, magic.xy)))) {\n";
- code += " discard;\n";
- code += " }\n";
-
- code += " }\n\n";
+ code += R"(
+ // Use interleaved gradient noise, which is fast but still looks good.
+ const vec3 magic = vec3(0.06711056, 0.00583715, 52.9829189);
+ float fade = clamp(smoothstep(distance_fade_min, distance_fade_max, fade_distance), 0.0, 1.0);
+ // Use a hard cap to prevent a few stray pixels from remaining when past the fade-out distance.
+ if (fade < 0.001 || fade < fract(magic.z * fract(dot(FRAGCOORD.xy, magic.xy)))) {
+ discard;
+ }
+ }
+)";
}
-
} else {
- code += " ALPHA *= clamp(smoothstep(distance_fade_min, distance_fade_max, length(VERTEX)), 0.0, 1.0);\n";
+ code += R"(
+ // Distance Fade: Pixel Alpha
+ ALPHA *= clamp(smoothstep(distance_fade_min, distance_fade_max, length(VERTEX)), 0.0, 1.0);
+)";
}
}
if (features[FEATURE_RIM]) {
+ code += R"(
+ // Rim: Enabled
+)";
if (flags[FLAG_UV1_USE_TRIPLANAR]) {
- code += " vec2 rim_tex = triplanar_texture(texture_rim,uv1_power_normal,uv1_triplanar_pos).xy;\n";
+ code += " vec2 rim_tex = triplanar_texture(texture_rim, uv1_power_normal, uv1_triplanar_pos).xy;\n";
} else {
- code += " vec2 rim_tex = texture(texture_rim,base_uv).xy;\n";
+ code += " vec2 rim_tex = texture(texture_rim, base_uv).xy;\n";
}
- code += " RIM = rim*rim_tex.x;";
- code += " RIM_TINT = rim_tint*rim_tex.y;\n";
+ code += R"( RIM = rim * rim_tex.x;
+ RIM_TINT = rim_tint * rim_tex.y;
+)";
}
if (features[FEATURE_CLEARCOAT]) {
+ code += R"(
+ // Clearcoat: Enabled
+)";
if (flags[FLAG_UV1_USE_TRIPLANAR]) {
- code += " vec2 clearcoat_tex = triplanar_texture(texture_clearcoat,uv1_power_normal,uv1_triplanar_pos).xy;\n";
+ code += " vec2 clearcoat_tex = triplanar_texture(texture_clearcoat, uv1_power_normal, uv1_triplanar_pos).xy;\n";
} else {
- code += " vec2 clearcoat_tex = texture(texture_clearcoat,base_uv).xy;\n";
+ code += " vec2 clearcoat_tex = texture(texture_clearcoat, base_uv).xy;\n";
}
- code += " CLEARCOAT = clearcoat*clearcoat_tex.x;";
- code += " CLEARCOAT_ROUGHNESS = clearcoat_roughness*clearcoat_tex.y;\n";
+ code += R"( CLEARCOAT = clearcoat * clearcoat_tex.x;
+ CLEARCOAT_ROUGHNESS = clearcoat_roughness * clearcoat_tex.y;
+)";
}
if (features[FEATURE_ANISOTROPY]) {
+ code += R"(
+ // Anisotropy: Enabled
+)";
if (flags[FLAG_UV1_USE_TRIPLANAR]) {
- code += " vec3 anisotropy_tex = triplanar_texture(texture_flowmap,uv1_power_normal,uv1_triplanar_pos).rga;\n";
+ code += " vec3 anisotropy_tex = triplanar_texture(texture_flowmap, uv1_power_normal, uv1_triplanar_pos).rga;\n";
} else {
- code += " vec3 anisotropy_tex = texture(texture_flowmap,base_uv).rga;\n";
+ code += " vec3 anisotropy_tex = texture(texture_flowmap, base_uv).rga;\n";
}
- code += " ANISOTROPY = anisotropy_ratio*anisotropy_tex.b;\n";
- code += " ANISOTROPY_FLOW = anisotropy_tex.rg*2.0-1.0;\n";
+ code += R"( ANISOTROPY = anisotropy_ratio * anisotropy_tex.b;
+ ANISOTROPY_FLOW = anisotropy_tex.rg * 2.0 - 1.0;
+)";
}
if (features[FEATURE_AMBIENT_OCCLUSION]) {
+ code += R"(
+ // Ambient Occlusion: Enabled
+)";
if (!orm) {
if (flags[FLAG_AO_ON_UV2]) {
if (flags[FLAG_UV2_USE_TRIPLANAR]) {
- code += " AO = dot(triplanar_texture(texture_ambient_occlusion,uv2_power_normal,uv2_triplanar_pos),ao_texture_channel);\n";
+ code += " AO = dot(triplanar_texture(texture_ambient_occlusion, uv2_power_normal, uv2_triplanar_pos), ao_texture_channel);\n";
} else {
- code += " AO = dot(texture(texture_ambient_occlusion,base_uv2),ao_texture_channel);\n";
+ code += " AO = dot(texture(texture_ambient_occlusion, base_uv2), ao_texture_channel);\n";
}
} else {
if (flags[FLAG_UV1_USE_TRIPLANAR]) {
- code += " AO = dot(triplanar_texture(texture_ambient_occlusion,uv1_power_normal,uv1_triplanar_pos),ao_texture_channel);\n";
+ code += " AO = dot(triplanar_texture(texture_ambient_occlusion, uv1_power_normal, uv1_triplanar_pos), ao_texture_channel);\n";
} else {
- code += " AO = dot(texture(texture_ambient_occlusion,base_uv),ao_texture_channel);\n";
+ code += " AO = dot(texture(texture_ambient_occlusion, base_uv), ao_texture_channel);\n";
}
}
} else {
@@ -1453,75 +1730,103 @@ void BaseMaterial3D::_update_shader() {
}
if (features[FEATURE_SUBSURFACE_SCATTERING]) {
+ code += R"(
+ // Subsurface Scattering: Enabled
+)";
if (flags[FLAG_UV1_USE_TRIPLANAR]) {
- code += " float sss_tex = triplanar_texture(texture_subsurface_scattering,uv1_power_normal,uv1_triplanar_pos).r;\n";
+ code += " float sss_tex = triplanar_texture(texture_subsurface_scattering, uv1_power_normal, uv1_triplanar_pos).r;\n";
} else {
- code += " float sss_tex = texture(texture_subsurface_scattering,base_uv).r;\n";
+ code += " float sss_tex = texture(texture_subsurface_scattering, base_uv).r;\n";
}
- code += " SSS_STRENGTH=subsurface_scattering_strength*sss_tex;\n";
+ code += " SSS_STRENGTH = subsurface_scattering_strength * sss_tex;\n";
}
if (features[FEATURE_SUBSURFACE_TRANSMITTANCE]) {
+ code += R"(
+ // Subsurface Scattering Transmittance: Enabled
+)";
if (flags[FLAG_UV1_USE_TRIPLANAR]) {
- code += " vec4 trans_color_tex = triplanar_texture(texture_subsurface_transmittance,uv1_power_normal,uv1_triplanar_pos);\n";
+ code += " vec4 trans_color_tex = triplanar_texture(texture_subsurface_transmittance, uv1_power_normal, uv1_triplanar_pos);\n";
} else {
- code += " vec4 trans_color_tex = texture(texture_subsurface_transmittance,base_uv);\n";
+ code += " vec4 trans_color_tex = texture(texture_subsurface_transmittance, base_uv);\n";
}
- code += " SSS_TRANSMITTANCE_COLOR=transmittance_color*trans_color_tex;\n";
+ code += " SSS_TRANSMITTANCE_COLOR = transmittance_color * trans_color_tex;\n";
- code += " SSS_TRANSMITTANCE_DEPTH=transmittance_depth;\n";
- code += " SSS_TRANSMITTANCE_BOOST=transmittance_boost;\n";
+ code += R"( SSS_TRANSMITTANCE_DEPTH = transmittance_depth;
+ SSS_TRANSMITTANCE_BOOST = transmittance_boost;
+)";
}
if (features[FEATURE_BACKLIGHT]) {
+ code += R"(
+ // Backlight: Enabled
+)";
if (flags[FLAG_UV1_USE_TRIPLANAR]) {
- code += " vec3 backlight_tex = triplanar_texture(texture_backlight,uv1_power_normal,uv1_triplanar_pos).rgb;\n";
+ code += " vec3 backlight_tex = triplanar_texture(texture_backlight, uv1_power_normal, uv1_triplanar_pos).rgb;\n";
} else {
- code += " vec3 backlight_tex = texture(texture_backlight,base_uv).rgb;\n";
+ code += " vec3 backlight_tex = texture(texture_backlight, base_uv).rgb;\n";
}
- code += " BACKLIGHT = (backlight.rgb+backlight_tex);\n";
+ code += " BACKLIGHT = (backlight.rgb + backlight_tex);\n";
}
if (features[FEATURE_DETAIL]) {
- bool triplanar = (flags[FLAG_UV1_USE_TRIPLANAR] && detail_uv == DETAIL_UV_1) || (flags[FLAG_UV2_USE_TRIPLANAR] && detail_uv == DETAIL_UV_2);
-
+ code += R"(
+ // Detail: Enabled
+)";
+ const bool triplanar = (flags[FLAG_UV1_USE_TRIPLANAR] && detail_uv == DETAIL_UV_1) || (flags[FLAG_UV2_USE_TRIPLANAR] && detail_uv == DETAIL_UV_2);
if (triplanar) {
- String tp_uv = detail_uv == DETAIL_UV_1 ? "uv1" : "uv2";
- code += " vec4 detail_tex = triplanar_texture(texture_detail_albedo," + tp_uv + "_power_normal," + tp_uv + "_triplanar_pos);\n";
- code += " vec4 detail_norm_tex = triplanar_texture(texture_detail_normal," + tp_uv + "_power_normal," + tp_uv + "_triplanar_pos);\n";
-
+ const String tp_uv = detail_uv == DETAIL_UV_1 ? "uv1" : "uv2";
+ code += vformat(R"( vec4 detail_tex = triplanar_texture(texture_detail_albedo, %s_power_normal, %s_triplanar_pos);
+ vec4 detail_norm_tex = triplanar_texture(texture_detail_normal, %s_power_normal, %s_triplanar_pos);
+)",
+ tp_uv, tp_uv, tp_uv, tp_uv);
} else {
- String det_uv = detail_uv == DETAIL_UV_1 ? "base_uv" : "base_uv2";
- code += " vec4 detail_tex = texture(texture_detail_albedo," + det_uv + ");\n";
- code += " vec4 detail_norm_tex = texture(texture_detail_normal," + det_uv + ");\n";
+ const String det_uv = detail_uv == DETAIL_UV_1 ? "base_uv" : "base_uv2";
+ code += vformat(R"( vec4 detail_tex = texture(texture_detail_albedo, %s);
+ vec4 detail_norm_tex = texture(texture_detail_normal, %s);
+)",
+ det_uv, det_uv);
}
if (flags[FLAG_UV1_USE_TRIPLANAR]) {
- code += " vec4 detail_mask_tex = triplanar_texture(texture_detail_mask,uv1_power_normal,uv1_triplanar_pos);\n";
+ code += " vec4 detail_mask_tex = triplanar_texture(texture_detail_mask, uv1_power_normal, uv1_triplanar_pos);\n";
} else {
- code += " vec4 detail_mask_tex = texture(texture_detail_mask,base_uv);\n";
+ code += " vec4 detail_mask_tex = texture(texture_detail_mask, base_uv);\n";
}
switch (detail_blend_mode) {
case BLEND_MODE_MIX: {
- code += " vec3 detail = mix(ALBEDO.rgb,detail_tex.rgb,detail_tex.a);\n";
+ code += R"(
+ // Detail Blend Mode: Mix
+ vec3 detail = mix(ALBEDO.rgb, detail_tex.rgb, detail_tex.a);
+)";
} break;
case BLEND_MODE_ADD: {
- code += " vec3 detail = mix(ALBEDO.rgb,ALBEDO.rgb+detail_tex.rgb,detail_tex.a);\n";
+ code += R"(
+ // Detail Blend Mode: Add
+ vec3 detail = mix(ALBEDO.rgb, ALBEDO.rgb + detail_tex.rgb, detail_tex.a);
+)";
} break;
case BLEND_MODE_SUB: {
- code += " vec3 detail = mix(ALBEDO.rgb,ALBEDO.rgb-detail_tex.rgb,detail_tex.a);\n";
+ code += R"(
+ // Detail Blend Mode: Subtract
+ vec3 detail = mix(ALBEDO.rgb, ALBEDO.rgb - detail_tex.rgb, detail_tex.a);
+)";
} break;
case BLEND_MODE_MUL: {
- code += " vec3 detail = mix(ALBEDO.rgb,ALBEDO.rgb*detail_tex.rgb,detail_tex.a);\n";
+ code += R"(
+ // Detail Blend Mode: Multiply
+ vec3 detail = mix(ALBEDO.rgb, ALBEDO.rgb * detail_tex.rgb, detail_tex.a);
+)";
} break;
case BLEND_MODE_MAX:
break; // Internal value, skip.
}
- code += " vec3 detail_norm = mix(NORMAL_MAP,detail_norm_tex.rgb,detail_tex.a);\n";
- code += " NORMAL_MAP = mix(NORMAL_MAP,detail_norm,detail_mask_tex.r);\n";
- code += " ALBEDO.rgb = mix(ALBEDO.rgb,detail,detail_mask_tex.r);\n";
+ code += R"( vec3 detail_norm = mix(NORMAL_MAP, detail_norm_tex.rgb, detail_tex.a);
+ NORMAL_MAP = mix(NORMAL_MAP, detail_norm, detail_mask_tex.r);
+ ALBEDO.rgb = mix(ALBEDO.rgb, detail, detail_mask_tex.r);
+)";
}
code += "}\n";
diff --git a/scu_builders.py b/scu_builders.py
index 8cd87a13d5..0435c0a4f5 100644
--- a/scu_builders.py
+++ b/scu_builders.py
@@ -8,7 +8,7 @@ from os.path import normpath, basename
base_folder_path = str(Path(__file__).parent) + "/"
base_folder_only = os.path.basename(os.path.normpath(base_folder_path))
-_verbose = True # Set manually for debug prints
+_verbose = False # Set manually for debug prints
_scu_folders = set()
_max_includes_per_scu = 1024
diff --git a/servers/camera_server.h b/servers/camera_server.h
index 4e0b75fbf6..e9bcd771d2 100644
--- a/servers/camera_server.h
+++ b/servers/camera_server.h
@@ -71,7 +71,7 @@ protected:
static void _bind_methods();
- template <class T>
+ template <typename T>
static CameraServer *_create_builtin() {
return memnew(T);
}
@@ -79,7 +79,7 @@ protected:
public:
static CameraServer *get_singleton();
- template <class T>
+ template <typename T>
static void make_default() {
create_func = _create_builtin<T>;
}
diff --git a/servers/native_menu.cpp b/servers/native_menu.cpp
index 4372c10707..d1894ba6c3 100644
--- a/servers/native_menu.cpp
+++ b/servers/native_menu.cpp
@@ -48,6 +48,7 @@ void NativeMenu::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_size", "rid"), &NativeMenu::get_size);
ClassDB::bind_method(D_METHOD("popup", "rid", "position"), &NativeMenu::popup);
+ ClassDB::bind_method(D_METHOD("set_interface_direction", "rid", "is_rtl"), &NativeMenu::set_interface_direction);
ClassDB::bind_method(D_METHOD("set_popup_open_callback", "rid", "callback"), &NativeMenu::set_popup_open_callback);
ClassDB::bind_method(D_METHOD("get_popup_open_callback", "rid"), &NativeMenu::get_popup_open_callback);
ClassDB::bind_method(D_METHOD("set_popup_close_callback", "rid", "callback"), &NativeMenu::set_popup_close_callback);
@@ -111,6 +112,9 @@ void NativeMenu::_bind_methods() {
BIND_ENUM_CONSTANT(FEATURE_GLOBAL_MENU);
BIND_ENUM_CONSTANT(FEATURE_POPUP_MENU);
+ BIND_ENUM_CONSTANT(FEATURE_OPEN_CLOSE_CALLBACK);
+ BIND_ENUM_CONSTANT(FEATURE_HOVER_CALLBACK);
+ BIND_ENUM_CONSTANT(FEATURE_KEY_CALLBACK);
BIND_ENUM_CONSTANT(INVALID_MENU_ID);
BIND_ENUM_CONSTANT(MAIN_MENU_ID);
@@ -173,6 +177,10 @@ void NativeMenu::popup(const RID &p_rid, const Vector2i &p_position) {
WARN_PRINT("Global menus are not supported on this platform.");
}
+void NativeMenu::set_interface_direction(const RID &p_rid, bool p_is_rtl) {
+ WARN_PRINT("Global menus are not supported on this platform.");
+}
+
void NativeMenu::set_popup_open_callback(const RID &p_rid, const Callable &p_callback) {
WARN_PRINT("Global menus are not supported on this platform.");
}
diff --git a/servers/native_menu.h b/servers/native_menu.h
index bb61caa633..f65e193972 100644
--- a/servers/native_menu.h
+++ b/servers/native_menu.h
@@ -54,6 +54,9 @@ public:
enum Feature {
FEATURE_GLOBAL_MENU,
FEATURE_POPUP_MENU,
+ FEATURE_OPEN_CLOSE_CALLBACK,
+ FEATURE_HOVER_CALLBACK,
+ FEATURE_KEY_CALLBACK,
};
enum SystemMenus {
@@ -78,6 +81,8 @@ public:
virtual Size2 get_size(const RID &p_rid) const;
virtual void popup(const RID &p_rid, const Vector2i &p_position);
+ virtual void set_interface_direction(const RID &p_rid, bool p_is_rtl);
+
virtual void set_popup_open_callback(const RID &p_rid, const Callable &p_callback);
virtual Callable get_popup_open_callback(const RID &p_rid) const;
virtual void set_popup_close_callback(const RID &p_rid, const Callable &p_callback);
diff --git a/servers/physics_2d/godot_broad_phase_2d_bvh.h b/servers/physics_2d/godot_broad_phase_2d_bvh.h
index 36fd1223b0..6c1fae5cb2 100644
--- a/servers/physics_2d/godot_broad_phase_2d_bvh.h
+++ b/servers/physics_2d/godot_broad_phase_2d_bvh.h
@@ -38,7 +38,7 @@
#include "core/math/vector2.h"
class GodotBroadPhase2DBVH : public GodotBroadPhase2D {
- template <class T>
+ template <typename T>
class UserPairTestFunction {
public:
static bool user_pair_check(const T *p_a, const T *p_b) {
@@ -47,7 +47,7 @@ class GodotBroadPhase2DBVH : public GodotBroadPhase2D {
}
};
- template <class T>
+ template <typename T>
class UserCullTestFunction {
public:
static bool user_cull_check(const T *p_a, const T *p_b) {
diff --git a/servers/physics_2d/godot_collision_solver_2d_sat.cpp b/servers/physics_2d/godot_collision_solver_2d_sat.cpp
index c85fdc592a..daa9982b2e 100644
--- a/servers/physics_2d/godot_collision_solver_2d_sat.cpp
+++ b/servers/physics_2d/godot_collision_solver_2d_sat.cpp
@@ -171,7 +171,7 @@ static void _generate_contacts_from_supports(const Vector2 *p_points_A, int p_po
contacts_func(points_A, pointcount_A, points_B, pointcount_B, p_collector);
}
-template <class ShapeA, class ShapeB, bool castA = false, bool castB = false, bool withMargin = false>
+template <typename ShapeA, typename ShapeB, bool castA = false, bool castB = false, bool withMargin = false>
class SeparatorAxisTest2D {
const ShapeA *shape_A = nullptr;
const ShapeB *shape_B = nullptr;
diff --git a/servers/physics_3d/godot_broad_phase_3d_bvh.h b/servers/physics_3d/godot_broad_phase_3d_bvh.h
index 6279658ec4..63968dea64 100644
--- a/servers/physics_3d/godot_broad_phase_3d_bvh.h
+++ b/servers/physics_3d/godot_broad_phase_3d_bvh.h
@@ -36,7 +36,7 @@
#include "core/math/bvh.h"
class GodotBroadPhase3DBVH : public GodotBroadPhase3D {
- template <class T>
+ template <typename T>
class UserPairTestFunction {
public:
static bool user_pair_check(const T *p_a, const T *p_b) {
@@ -45,7 +45,7 @@ class GodotBroadPhase3DBVH : public GodotBroadPhase3D {
}
};
- template <class T>
+ template <typename T>
class UserCullTestFunction {
public:
static bool user_cull_check(const T *p_a, const T *p_b) {
diff --git a/servers/physics_3d/godot_collision_solver_3d_sat.cpp b/servers/physics_3d/godot_collision_solver_3d_sat.cpp
index 3aa2f256c1..beaa30eb84 100644
--- a/servers/physics_3d/godot_collision_solver_3d_sat.cpp
+++ b/servers/physics_3d/godot_collision_solver_3d_sat.cpp
@@ -612,7 +612,7 @@ static void _generate_contacts_from_supports(const Vector3 *p_points_A, int p_po
contacts_func(points_A, pointcount_A, points_B, pointcount_B, p_callback);
}
-template <class ShapeA, class ShapeB, bool withMargin = false>
+template <typename ShapeA, typename ShapeB, bool withMargin = false>
class SeparatorAxisTest {
const ShapeA *shape_A = nullptr;
const ShapeB *shape_B = nullptr;
diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp
index cd38aa05f3..8e342375f8 100644
--- a/servers/rendering/renderer_canvas_cull.cpp
+++ b/servers/rendering/renderer_canvas_cull.cpp
@@ -2162,7 +2162,7 @@ bool RendererCanvasCull::free(RID p_rid) {
return true;
}
-template <class T>
+template <typename T>
void RendererCanvasCull::_free_rids(T &p_owner, const char *p_type) {
List<RID> owned;
p_owner.get_owned_list(&owned);
diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h
index 8d40c2fbaa..d733a7bed2 100644
--- a/servers/rendering/renderer_canvas_cull.h
+++ b/servers/rendering/renderer_canvas_cull.h
@@ -170,7 +170,7 @@ public:
RID_Owner<Item, true> canvas_item_owner;
RID_Owner<RendererCanvasRender::Light, true> canvas_light_owner;
- template <class T>
+ template <typename T>
void _free_rids(T &p_owner, const char *p_type);
bool disable_scale;
diff --git a/servers/rendering/renderer_canvas_render.h b/servers/rendering/renderer_canvas_render.h
index fd31a40a3e..cf8f6dcb2e 100644
--- a/servers/rendering/renderer_canvas_render.h
+++ b/servers/rendering/renderer_canvas_render.h
@@ -366,7 +366,7 @@ public:
mutable double debug_redraw_time = 0;
#endif
- template <class T>
+ template <typename T>
T *alloc_command() {
T *command = nullptr;
if (commands == nullptr) {
diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.cpp b/servers/rendering/renderer_rd/cluster_builder_rd.cpp
index e661fd9217..41df6107a8 100644
--- a/servers/rendering/renderer_rd/cluster_builder_rd.cpp
+++ b/servers/rendering/renderer_rd/cluster_builder_rd.cpp
@@ -62,15 +62,17 @@ ClusterBuilderSharedDataRD::ClusterBuilderSharedDataRD() {
defines = "\n#define USE_ATTACHMENT\n";
}
+ RD::PipelineRasterizationState rasterization_state;
+ rasterization_state.enable_depth_clamp = true;
Vector<String> versions;
versions.push_back("");
cluster_render.cluster_render_shader.initialize(versions, defines);
cluster_render.shader_version = cluster_render.cluster_render_shader.version_create();
cluster_render.shader = cluster_render.cluster_render_shader.version_get_shader(cluster_render.shader_version, 0);
- cluster_render.shader_pipelines[ClusterRender::PIPELINE_NORMAL] = RD::get_singleton()->render_pipeline_create(cluster_render.shader, fb_format, vertex_format, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0);
+ cluster_render.shader_pipelines[ClusterRender::PIPELINE_NORMAL] = RD::get_singleton()->render_pipeline_create(cluster_render.shader, fb_format, vertex_format, RD::RENDER_PRIMITIVE_TRIANGLES, rasterization_state, RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0);
RD::PipelineMultisampleState ms;
ms.sample_count = RD::TEXTURE_SAMPLES_4;
- cluster_render.shader_pipelines[ClusterRender::PIPELINE_MSAA] = RD::get_singleton()->render_pipeline_create(cluster_render.shader, fb_format, vertex_format, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), ms, RD::PipelineDepthStencilState(), blend_state, 0);
+ cluster_render.shader_pipelines[ClusterRender::PIPELINE_MSAA] = RD::get_singleton()->render_pipeline_create(cluster_render.shader, fb_format, vertex_format, RD::RENDER_PRIMITIVE_TRIANGLES, rasterization_state, ms, RD::PipelineDepthStencilState(), blend_state, 0);
}
{
Vector<String> versions;
diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp
index dc48ddbd56..7dfff0b76f 100644
--- a/servers/rendering/rendering_device.cpp
+++ b/servers/rendering/rendering_device.cpp
@@ -5182,7 +5182,7 @@ void RenderingDevice::_save_pipeline_cache(void *p_data) {
}
}
-template <class T>
+template <typename T>
void RenderingDevice::_free_rids(T &p_owner, const char *p_type) {
List<RID> owned;
p_owner.get_owned_list(&owned);
diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h
index 8c88c08950..9a898a2fca 100644
--- a/servers/rendering/rendering_device.h
+++ b/servers/rendering/rendering_device.h
@@ -1294,7 +1294,7 @@ private:
void _stall_for_previous_frames();
void _flush_and_stall_for_all_frames();
- template <class T>
+ template <typename T>
void _free_rids(T &p_owner, const char *p_type);
#ifdef DEV_ENABLED
diff --git a/servers/rendering/rendering_device_driver.h b/servers/rendering/rendering_device_driver.h
index ee33dc103c..09a0412941 100644
--- a/servers/rendering/rendering_device_driver.h
+++ b/servers/rendering/rendering_device_driver.h
@@ -56,7 +56,7 @@
// This may one day be used in Godot for interoperability between C arrays, Vector and LocalVector.
// (See https://github.com/godotengine/godot-proposals/issues/5144.)
-template <class T>
+template <typename T>
class VectorView {
const T *_ptr = nullptr;
const uint32_t _size = 0;
@@ -97,20 +97,20 @@ public:
#define ENUM_MEMBERS_EQUAL(m_a, m_b) ((int64_t)m_a == (int64_t)m_b)
// This helps using a single paged allocator for many resource types.
-template <class... RESOURCE_TYPES>
+template <typename... RESOURCE_TYPES>
struct VersatileResourceTemplate {
static constexpr size_t RESOURCE_SIZES[] = { sizeof(RESOURCE_TYPES)... };
static constexpr size_t MAX_RESOURCE_SIZE = std::max_element(RESOURCE_SIZES, RESOURCE_SIZES + sizeof...(RESOURCE_TYPES))[0];
uint8_t data[MAX_RESOURCE_SIZE];
- template <class T>
+ template <typename T>
static T *allocate(PagedAllocator<VersatileResourceTemplate> &p_allocator) {
T *obj = (T *)p_allocator.alloc();
memnew_placement(obj, T);
return obj;
}
- template <class T>
+ template <typename T>
static void free(PagedAllocator<VersatileResourceTemplate> &p_allocator, T *p_object) {
p_object->~T();
p_allocator.free((VersatileResourceTemplate *)p_object);
diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h
index 737545b8ca..816a202b50 100644
--- a/servers/rendering/shader_language.h
+++ b/servers/rendering/shader_language.h
@@ -383,7 +383,7 @@ public:
virtual ~Node() {}
};
- template <class T>
+ template <typename T>
T *alloc_node() {
T *node = memnew(T);
node->next = nodes;
diff --git a/servers/rendering/storage/variant_converters.h b/servers/rendering/storage/variant_converters.h
index 6e3c07237e..7dbdb0f517 100644
--- a/servers/rendering/storage/variant_converters.h
+++ b/servers/rendering/storage/variant_converters.h
@@ -242,10 +242,10 @@ inline bool is_convertible_array(Variant::Type type) {
type == Variant::PACKED_COLOR_ARRAY;
}
-template <class, class = void>
+template <typename, typename = void>
inline constexpr bool is_vector_type_v = false;
-template <class T>
+template <typename T>
inline constexpr bool is_vector_type_v<T, std::void_t<decltype(T::AXIS_COUNT)>> = true;
template <typename T, typename P>