summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/SCsub1
-rw-r--r--core/core_constants.cpp10
-rw-r--r--core/math/quaternion.cpp2
-rw-r--r--core/math/quaternion.h2
-rw-r--r--core/math/transform_2d.cpp10
-rw-r--r--core/math/transform_2d.h6
-rw-r--r--core/math/transform_3d.cpp18
-rw-r--r--core/math/transform_3d.h8
-rw-r--r--core/multiplayer/SCsub5
-rw-r--r--core/multiplayer/multiplayer_api.cpp593
-rw-r--r--core/multiplayer/multiplayer_api.h196
-rw-r--r--core/object/script_language.h7
-rw-r--r--core/object/script_language_extension.cpp2
-rw-r--r--core/object/script_language_extension.h26
-rw-r--r--core/register_core_types.cpp5
-rw-r--r--core/variant/callable.cpp9
-rw-r--r--core/variant/callable.h4
-rw-r--r--core/variant/variant_call.cpp8
-rw-r--r--doc/classes/@GlobalScope.xml18
-rw-r--r--doc/classes/AudioEffectRecord.xml6
-rw-r--r--doc/classes/AudioStream.xml2
-rw-r--r--doc/classes/AudioStreamPlayback.xml2
-rw-r--r--doc/classes/AudioStreamWAV.xml (renamed from doc/classes/AudioStreamSample.xml)10
-rw-r--r--doc/classes/MultiplayerAPI.xml100
-rw-r--r--doc/classes/MultiplayerAPIExtension.xml141
-rw-r--r--doc/classes/MultiplayerPeer.xml11
-rw-r--r--doc/classes/Node.xml22
-rw-r--r--doc/classes/ProjectSettings.xml12
-rw-r--r--doc/classes/Quaternion.xml20
-rw-r--r--doc/classes/RenderingServer.xml93
-rw-r--r--doc/classes/ScriptExtension.xml4
-rw-r--r--doc/classes/Transform2D.xml2
-rw-r--r--doc/classes/Transform3D.xml4
-rw-r--r--doc/classes/Viewport.xml9
-rwxr-xr-xdoc/tools/make_rst.py2
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp6
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp8
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.h2
-rw-r--r--drivers/gles3/shaders/canvas_uniforms_inc.glsl4
-rw-r--r--drivers/gles3/shaders/scene.glsl8
-rw-r--r--drivers/gles3/shaders/sky.glsl4
-rw-r--r--drivers/gles3/storage/material_storage.cpp294
-rw-r--r--drivers/gles3/storage/material_storage.h48
-rw-r--r--drivers/gles3/storage/utilities.cpp2
-rw-r--r--drivers/vulkan/rendering_device_vulkan.cpp6
-rw-r--r--editor/animation_track_editor.cpp29
-rw-r--r--editor/animation_track_editor.h3
-rw-r--r--editor/editor_asset_installer.cpp4
-rw-r--r--editor/editor_node.cpp4
-rw-r--r--editor/editor_paths.cpp4
-rw-r--r--editor/icons/AudioStreamOggVorbis.svg (renamed from editor/icons/AudioStreamOGGVorbis.svg)0
-rw-r--r--editor/icons/AudioStreamWAV.svg (renamed from editor/icons/AudioStreamSample.svg)0
-rw-r--r--editor/import/resource_importer_wav.cpp26
-rw-r--r--editor/import/scene_import_settings.cpp2
-rw-r--r--editor/plugins/animation_state_machine_editor.cpp2
-rw-r--r--editor/plugins/bone_map_editor_plugin.cpp46
-rw-r--r--editor/plugins/bone_map_editor_plugin.h1
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp4
-rw-r--r--editor/plugins/curve_editor_plugin.cpp4
-rw-r--r--editor/plugins/node_3d_editor_gizmos.cpp114
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp228
-rw-r--r--editor/plugins/node_3d_editor_plugin.h27
-rw-r--r--editor/plugins/shader_editor_plugin.cpp10
-rw-r--r--editor/plugins/tiles/tile_set_atlas_source_editor.cpp8
-rw-r--r--editor/plugins/tiles/tiles_editor_plugin.cpp12
-rw-r--r--editor/plugins/tiles/tiles_editor_plugin.h3
-rw-r--r--editor/plugins/visual_shader_editor_plugin.cpp8
-rw-r--r--editor/project_converter_3_to_4.cpp4
-rw-r--r--editor/project_settings_editor.cpp8
-rw-r--r--editor/project_settings_editor.h2
-rw-r--r--editor/shader_globals_editor.cpp36
-rw-r--r--main/main.cpp24
-rw-r--r--modules/csg/csg_shape.cpp6
-rw-r--r--modules/enet/enet_multiplayer_peer.cpp6
-rw-r--r--modules/enet/enet_multiplayer_peer.h2
-rw-r--r--modules/gdscript/gdscript.cpp32
-rw-r--r--modules/gdscript/gdscript.h6
-rw-r--r--modules/gdscript/gdscript_byte_codegen.cpp2
-rw-r--r--modules/gdscript/gdscript_byte_codegen.h2
-rw-r--r--modules/gdscript/gdscript_codegen.h3
-rw-r--r--modules/gdscript/gdscript_compiler.cpp2
-rw-r--r--modules/gdscript/gdscript_function.h4
-rw-r--r--modules/gdscript/gdscript_parser.cpp48
-rw-r--r--modules/gdscript/gdscript_parser.h6
-rw-r--r--modules/gdscript/gdscript_rpc_callable.cpp6
-rw-r--r--modules/gdscript/gdscript_rpc_callable.h2
-rw-r--r--modules/gdscript/gdscript_vm.cpp1
-rw-r--r--modules/gdscript/language_server/gdscript_extend_parser.cpp4
-rw-r--r--modules/gridmap/editor/grid_map_editor_plugin.cpp4
-rw-r--r--modules/mono/csharp_script.cpp39
-rw-r--r--modules/mono/csharp_script.h8
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttribute.cs10
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs2
-rw-r--r--modules/multiplayer/SCsub14
-rw-r--r--modules/multiplayer/config.py19
-rw-r--r--modules/multiplayer/doc_classes/MultiplayerSpawner.xml (renamed from doc/classes/MultiplayerSpawner.xml)3
-rw-r--r--modules/multiplayer/doc_classes/MultiplayerSynchronizer.xml (renamed from doc/classes/MultiplayerSynchronizer.xml)3
-rw-r--r--modules/multiplayer/doc_classes/SceneMultiplayer.xml55
-rw-r--r--modules/multiplayer/doc_classes/SceneReplicationConfig.xml (renamed from doc/classes/SceneReplicationConfig.xml)2
-rw-r--r--modules/multiplayer/editor/replication_editor_plugin.cpp (renamed from editor/plugins/replication_editor_plugin.cpp)2
-rw-r--r--modules/multiplayer/editor/replication_editor_plugin.h (renamed from editor/plugins/replication_editor_plugin.h)15
-rw-r--r--modules/multiplayer/multiplayer_spawner.cpp (renamed from scene/multiplayer/multiplayer_spawner.cpp)8
-rw-r--r--modules/multiplayer/multiplayer_spawner.h (renamed from scene/multiplayer/multiplayer_spawner.h)3
-rw-r--r--modules/multiplayer/multiplayer_synchronizer.cpp (renamed from scene/multiplayer/multiplayer_synchronizer.cpp)10
-rw-r--r--modules/multiplayer/multiplayer_synchronizer.h (renamed from scene/multiplayer/multiplayer_synchronizer.h)2
-rw-r--r--modules/multiplayer/register_types.cpp (renamed from core/multiplayer/multiplayer.h)76
-rw-r--r--modules/multiplayer/register_types.h39
-rw-r--r--modules/multiplayer/scene_cache_interface.cpp (renamed from scene/multiplayer/scene_cache_interface.cpp)16
-rw-r--r--modules/multiplayer/scene_cache_interface.h (renamed from scene/multiplayer/scene_cache_interface.h)31
-rw-r--r--modules/multiplayer/scene_multiplayer.cpp332
-rw-r--r--modules/multiplayer/scene_multiplayer.h136
-rw-r--r--modules/multiplayer/scene_replication_config.cpp (renamed from scene/resources/scene_replication_config.cpp)2
-rw-r--r--modules/multiplayer/scene_replication_config.h (renamed from scene/resources/scene_replication_config.h)0
-rw-r--r--modules/multiplayer/scene_replication_interface.cpp (renamed from scene/multiplayer/scene_replication_interface.cpp)32
-rw-r--r--modules/multiplayer/scene_replication_interface.h (renamed from scene/multiplayer/scene_replication_interface.h)37
-rw-r--r--modules/multiplayer/scene_replication_state.cpp (renamed from scene/multiplayer/scene_replication_state.cpp)8
-rw-r--r--modules/multiplayer/scene_replication_state.h (renamed from scene/multiplayer/scene_replication_state.h)3
-rw-r--r--modules/multiplayer/scene_rpc_interface.cpp (renamed from scene/multiplayer/scene_rpc_interface.cpp)158
-rw-r--r--modules/multiplayer/scene_rpc_interface.h (renamed from scene/multiplayer/scene_rpc_interface.h)73
-rw-r--r--modules/ogg/config.py4
-rw-r--r--modules/ogg/doc_classes/OggPacketSequence.xml (renamed from modules/ogg/doc_classes/OGGPacketSequence.xml)8
-rw-r--r--modules/ogg/doc_classes/OggPacketSequencePlayback.xml (renamed from modules/ogg/doc_classes/OGGPacketSequencePlayback.xml)2
-rw-r--r--modules/ogg/ogg_packet_sequence.cpp50
-rw-r--r--modules/ogg/ogg_packet_sequence.h28
-rw-r--r--modules/ogg/register_types.cpp4
-rw-r--r--modules/openxr/openxr_api.cpp15
-rw-r--r--modules/visual_script/visual_script.cpp26
-rw-r--r--modules/visual_script/visual_script.h6
-rw-r--r--modules/visual_script/visual_script_nodes.cpp10
-rw-r--r--modules/visual_script/visual_script_nodes.h7
-rw-r--r--modules/vorbis/audio_stream_ogg_vorbis.cpp94
-rw-r--r--modules/vorbis/audio_stream_ogg_vorbis.h34
-rw-r--r--modules/vorbis/config.py4
-rw-r--r--modules/vorbis/doc_classes/AudioStreamOggVorbis.xml (renamed from modules/vorbis/doc_classes/AudioStreamOGGVorbis.xml)6
-rw-r--r--modules/vorbis/doc_classes/AudioStreamPlaybackOggVorbis.xml (renamed from modules/vorbis/doc_classes/AudioStreamPlaybackOGGVorbis.xml)2
-rw-r--r--modules/vorbis/register_types.cpp6
-rw-r--r--modules/vorbis/resource_importer_ogg_vorbis.cpp60
-rw-r--r--modules/vorbis/resource_importer_ogg_vorbis.h8
-rw-r--r--modules/webrtc/doc_classes/WebRTCMultiplayerPeer.xml2
-rw-r--r--modules/webrtc/webrtc_multiplayer_peer.cpp12
-rw-r--r--modules/webrtc/webrtc_multiplayer_peer.h2
-rw-r--r--modules/websocket/websocket_multiplayer_peer.h2
-rw-r--r--scene/2d/camera_2d.cpp4
-rw-r--r--scene/2d/ray_cast_2d.cpp2
-rw-r--r--scene/2d/shape_cast_2d.cpp2
-rw-r--r--scene/2d/touch_screen_button.cpp4
-rw-r--r--scene/3d/node_3d.cpp4
-rw-r--r--scene/3d/path_3d.cpp2
-rw-r--r--scene/SCsub1
-rw-r--r--scene/gui/color_picker.cpp6
-rw-r--r--scene/main/canvas_item.cpp12
-rw-r--r--scene/main/canvas_item.h1
-rw-r--r--scene/main/multiplayer_api.cpp416
-rw-r--r--scene/main/multiplayer_api.h115
-rw-r--r--scene/main/multiplayer_peer.cpp (renamed from core/multiplayer/multiplayer_peer.cpp)14
-rw-r--r--scene/main/multiplayer_peer.h (renamed from core/multiplayer/multiplayer_peer.h)19
-rw-r--r--scene/main/node.cpp84
-rw-r--r--scene/main/node.h30
-rw-r--r--scene/main/scene_tree.cpp18
-rw-r--r--scene/main/shader_globals_override.cpp14
-rw-r--r--scene/main/viewport.cpp22
-rw-r--r--scene/main/viewport.h6
-rw-r--r--scene/main/window.cpp2
-rw-r--r--scene/multiplayer/SCsub5
-rw-r--r--scene/register_scene_types.cpp26
-rw-r--r--scene/resources/animation.cpp4
-rw-r--r--scene/resources/audio_stream_wav.cpp (renamed from scene/resources/audio_stream_sample.cpp)168
-rw-r--r--scene/resources/audio_stream_wav.h (renamed from scene/resources/audio_stream_sample.h)34
-rw-r--r--scene/resources/mesh.cpp66
-rw-r--r--scene/resources/mesh.h3
-rw-r--r--scene/resources/separation_ray_shape_2d.cpp2
-rw-r--r--scene/resources/visual_shader.cpp2
-rw-r--r--servers/audio/effects/audio_effect_record.cpp20
-rw-r--r--servers/audio/effects/audio_effect_record.h10
-rw-r--r--servers/audio_server.cpp2
-rw-r--r--servers/audio_server.h2
-rw-r--r--servers/rendering/dummy/rasterizer_scene_dummy.h2
-rw-r--r--servers/rendering/dummy/storage/material_storage.h26
-rw-r--r--servers/rendering/renderer_compositor.cpp7
-rw-r--r--servers/rendering/renderer_rd/environment/fog.cpp2
-rw-r--r--servers/rendering/renderer_rd/environment/sky.cpp4
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp2
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp2
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp2
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp2
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp6
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp10
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.h2
-rw-r--r--servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl4
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/sky.glsl4
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl4
-rw-r--r--servers/rendering/renderer_rd/shaders/particles.glsl4
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl4
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl4
-rw-r--r--servers/rendering/renderer_rd/storage_rd/material_storage.cpp280
-rw-r--r--servers/rendering/renderer_rd/storage_rd/material_storage.h48
-rw-r--r--servers/rendering/renderer_rd/storage_rd/particles_storage.cpp4
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.cpp3
-rw-r--r--servers/rendering/renderer_rd/storage_rd/utilities.cpp2
-rw-r--r--servers/rendering/renderer_scene.h2
-rw-r--r--servers/rendering/renderer_scene_cull.cpp10
-rw-r--r--servers/rendering/renderer_scene_render.h2
-rw-r--r--servers/rendering/renderer_viewport.cpp6
-rw-r--r--servers/rendering/renderer_viewport.h4
-rw-r--r--servers/rendering/rendering_server_default.h22
-rw-r--r--servers/rendering/shader_compiler.cpp16
-rw-r--r--servers/rendering/shader_language.cpp6
-rw-r--r--servers/rendering/shader_language.h6
-rw-r--r--servers/rendering/storage/material_storage.h32
-rw-r--r--servers/rendering_server.cpp28
-rw-r--r--servers/rendering_server.h28
-rw-r--r--servers/xr_server.cpp10
-rw-r--r--servers/xr_server.h11
-rw-r--r--tests/core/object/test_object.h4
-rw-r--r--tests/test_main.cpp2
216 files changed, 3287 insertions, 2485 deletions
diff --git a/core/SCsub b/core/SCsub
index 97080b8710..d4462fa546 100644
--- a/core/SCsub
+++ b/core/SCsub
@@ -188,7 +188,6 @@ SConscript("os/SCsub")
SConscript("math/SCsub")
SConscript("crypto/SCsub")
SConscript("io/SCsub")
-SConscript("multiplayer/SCsub")
SConscript("debugger/SCsub")
SConscript("input/SCsub")
SConscript("variant/SCsub")
diff --git a/core/core_constants.cpp b/core/core_constants.cpp
index 4a2d09d2a0..dc0ab72a86 100644
--- a/core/core_constants.cpp
+++ b/core/core_constants.cpp
@@ -31,7 +31,6 @@
#include "core_constants.h"
#include "core/input/input_event.h"
-#include "core/multiplayer/multiplayer.h"
#include "core/object/class_db.h"
#include "core/os/keyboard.h"
#include "core/variant/variant.h"
@@ -660,15 +659,6 @@ void register_global_constants() {
BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_OBJECT_CORE);
BIND_CORE_ENUM_CONSTANT(METHOD_FLAGS_DEFAULT);
- // rpc
- BIND_CORE_ENUM_CONSTANT_CUSTOM("RPC_MODE_DISABLED", Multiplayer::RPC_MODE_DISABLED);
- BIND_CORE_ENUM_CONSTANT_CUSTOM("RPC_MODE_ANY_PEER", Multiplayer::RPC_MODE_ANY_PEER);
- BIND_CORE_ENUM_CONSTANT_CUSTOM("RPC_MODE_AUTHORITY", Multiplayer::RPC_MODE_AUTHORITY);
-
- BIND_CORE_ENUM_CONSTANT_CUSTOM("TRANSFER_MODE_UNRELIABLE", Multiplayer::TRANSFER_MODE_UNRELIABLE);
- BIND_CORE_ENUM_CONSTANT_CUSTOM("TRANSFER_MODE_UNRELIABLE_ORDERED", Multiplayer::TRANSFER_MODE_UNRELIABLE_ORDERED);
- BIND_CORE_ENUM_CONSTANT_CUSTOM("TRANSFER_MODE_RELIABLE", Multiplayer::TRANSFER_MODE_RELIABLE);
-
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_NIL", Variant::NIL);
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_BOOL", Variant::BOOL);
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_INT", Variant::INT);
diff --git a/core/math/quaternion.cpp b/core/math/quaternion.cpp
index bb3b1ca63c..252c108166 100644
--- a/core/math/quaternion.cpp
+++ b/core/math/quaternion.cpp
@@ -183,7 +183,7 @@ Quaternion Quaternion::slerpni(const Quaternion &p_to, const real_t &p_weight) c
invFactor * from.w + newFactor * p_to.w);
}
-Quaternion Quaternion::cubic_slerp(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, const real_t &p_weight) const {
+Quaternion Quaternion::spherical_cubic_interpolate(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, const real_t &p_weight) const {
#ifdef MATH_CHECKS
ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion must be normalized.");
ERR_FAIL_COND_V_MSG(!p_b.is_normalized(), Quaternion(), "The end quaternion must be normalized.");
diff --git a/core/math/quaternion.h b/core/math/quaternion.h
index 684e7cb091..cb54a6f540 100644
--- a/core/math/quaternion.h
+++ b/core/math/quaternion.h
@@ -71,7 +71,7 @@ struct _NO_DISCARD_ Quaternion {
Quaternion slerp(const Quaternion &p_to, const real_t &p_weight) const;
Quaternion slerpni(const Quaternion &p_to, const real_t &p_weight) const;
- Quaternion cubic_slerp(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, const real_t &p_weight) const;
+ Quaternion spherical_cubic_interpolate(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, const real_t &p_weight) const;
Vector3 get_axis() const;
real_t get_angle() const;
diff --git a/core/math/transform_2d.cpp b/core/math/transform_2d.cpp
index cbd2fd3fa1..bb8bf9f569 100644
--- a/core/math/transform_2d.cpp
+++ b/core/math/transform_2d.cpp
@@ -136,11 +136,11 @@ void Transform2D::scale_basis(const Size2 &p_scale) {
columns[1][1] *= p_scale.y;
}
-void Transform2D::translate(const real_t p_tx, const real_t p_ty) {
- translate(Vector2(p_tx, p_ty));
+void Transform2D::translate_local(const real_t p_tx, const real_t p_ty) {
+ translate_local(Vector2(p_tx, p_ty));
}
-void Transform2D::translate(const Vector2 &p_translation) {
+void Transform2D::translate_local(const Vector2 &p_translation) {
columns[2] += basis_xform(p_translation);
}
@@ -235,9 +235,9 @@ Transform2D Transform2D::untranslated() const {
return copy;
}
-Transform2D Transform2D::translated(const Vector2 &p_offset) const {
+Transform2D Transform2D::translated_local(const Vector2 &p_offset) const {
Transform2D copy = *this;
- copy.translate(p_offset);
+ copy.translate_local(p_offset);
return copy;
}
diff --git a/core/math/transform_2d.h b/core/math/transform_2d.h
index 72d34a5d4c..e64d050f0c 100644
--- a/core/math/transform_2d.h
+++ b/core/math/transform_2d.h
@@ -74,8 +74,8 @@ struct _NO_DISCARD_ Transform2D {
void scale(const Size2 &p_scale);
void scale_basis(const Size2 &p_scale);
- void translate(const real_t p_tx, const real_t p_ty);
- void translate(const Vector2 &p_translation);
+ void translate_local(const real_t p_tx, const real_t p_ty);
+ void translate_local(const Vector2 &p_translation);
real_t basis_determinant() const;
@@ -87,7 +87,7 @@ struct _NO_DISCARD_ Transform2D {
Transform2D scaled(const Size2 &p_scale) const;
Transform2D basis_scaled(const Size2 &p_scale) const;
- Transform2D translated(const Vector2 &p_offset) const;
+ Transform2D translated_local(const Vector2 &p_offset) const;
Transform2D rotated(const real_t p_angle) const;
Transform2D untranslated() const;
diff --git a/core/math/transform_3d.cpp b/core/math/transform_3d.cpp
index 76b31daa76..c497a276f3 100644
--- a/core/math/transform_3d.cpp
+++ b/core/math/transform_3d.cpp
@@ -70,17 +70,23 @@ void Transform3D::rotate_basis(const Vector3 &p_axis, real_t p_angle) {
}
Transform3D Transform3D::looking_at(const Vector3 &p_target, const Vector3 &p_up) const {
+#ifdef MATH_CHECKS
+ ERR_FAIL_COND_V_MSG(origin.is_equal_approx(p_target), Transform3D(), "The transform's origin and target can't be equal.");
+#endif
Transform3D t = *this;
t.basis = Basis::looking_at(p_target - origin, p_up);
return t;
}
void Transform3D::set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up) {
+#ifdef MATH_CHECKS
+ ERR_FAIL_COND_MSG(p_eye.is_equal_approx(p_target), "The eye and target vectors can't be equal.");
+#endif
basis = Basis::looking_at(p_target - p_eye, p_up);
origin = p_eye;
}
-Transform3D Transform3D::sphere_interpolate_with(const Transform3D &p_transform, real_t p_c) const {
+Transform3D Transform3D::spherical_interpolate_with(const Transform3D &p_transform, real_t p_c) const {
/* not sure if very "efficient" but good enough? */
Transform3D interp;
@@ -123,19 +129,19 @@ void Transform3D::scale_basis(const Vector3 &p_scale) {
basis.scale(p_scale);
}
-void Transform3D::translate(real_t p_tx, real_t p_ty, real_t p_tz) {
- translate(Vector3(p_tx, p_ty, p_tz));
+void Transform3D::translate_local(real_t p_tx, real_t p_ty, real_t p_tz) {
+ translate_local(Vector3(p_tx, p_ty, p_tz));
}
-void Transform3D::translate(const Vector3 &p_translation) {
+void Transform3D::translate_local(const Vector3 &p_translation) {
for (int i = 0; i < 3; i++) {
origin[i] += basis[i].dot(p_translation);
}
}
-Transform3D Transform3D::translated(const Vector3 &p_translation) const {
+Transform3D Transform3D::translated_local(const Vector3 &p_translation) const {
Transform3D t = *this;
- t.translate(p_translation);
+ t.translate_local(p_translation);
return t;
}
diff --git a/core/math/transform_3d.h b/core/math/transform_3d.h
index 25832434cd..1f8026043f 100644
--- a/core/math/transform_3d.h
+++ b/core/math/transform_3d.h
@@ -56,9 +56,9 @@ struct _NO_DISCARD_ Transform3D {
void scale(const Vector3 &p_scale);
Transform3D scaled(const Vector3 &p_scale) const;
void scale_basis(const Vector3 &p_scale);
- void translate(real_t p_tx, real_t p_ty, real_t p_tz);
- void translate(const Vector3 &p_translation);
- Transform3D translated(const Vector3 &p_translation) const;
+ void translate_local(real_t p_tx, real_t p_ty, real_t p_tz);
+ void translate_local(const Vector3 &p_translation);
+ Transform3D translated_local(const Vector3 &p_translation) const;
const Basis &get_basis() const { return basis; }
void set_basis(const Basis &p_basis) { basis = p_basis; }
@@ -100,7 +100,7 @@ struct _NO_DISCARD_ Transform3D {
void operator*=(const real_t p_val);
Transform3D operator*(const real_t p_val) const;
- Transform3D sphere_interpolate_with(const Transform3D &p_transform, real_t p_c) const;
+ Transform3D spherical_interpolate_with(const Transform3D &p_transform, real_t p_c) const;
Transform3D interpolate_with(const Transform3D &p_transform, real_t p_c) const;
_FORCE_INLINE_ Transform3D inverse_xform(const Transform3D &t) const {
diff --git a/core/multiplayer/SCsub b/core/multiplayer/SCsub
deleted file mode 100644
index 19a6549225..0000000000
--- a/core/multiplayer/SCsub
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/usr/bin/env python
-
-Import("env")
-
-env.add_source_files(env.core_sources, "*.cpp")
diff --git a/core/multiplayer/multiplayer_api.cpp b/core/multiplayer/multiplayer_api.cpp
deleted file mode 100644
index 6cce31e0d1..0000000000
--- a/core/multiplayer/multiplayer_api.cpp
+++ /dev/null
@@ -1,593 +0,0 @@
-/*************************************************************************/
-/* multiplayer_api.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#include "multiplayer_api.h"
-
-#include "core/debugger/engine_debugger.h"
-#include "core/io/marshalls.h"
-
-#include <stdint.h>
-
-#ifdef DEBUG_ENABLED
-#include "core/os/os.h"
-#endif
-
-MultiplayerReplicationInterface *(*MultiplayerAPI::create_default_replication_interface)(MultiplayerAPI *p_multiplayer) = nullptr;
-MultiplayerRPCInterface *(*MultiplayerAPI::create_default_rpc_interface)(MultiplayerAPI *p_multiplayer) = nullptr;
-MultiplayerCacheInterface *(*MultiplayerAPI::create_default_cache_interface)(MultiplayerAPI *p_multiplayer) = nullptr;
-
-#ifdef DEBUG_ENABLED
-void MultiplayerAPI::profile_bandwidth(const String &p_inout, int p_size) {
- if (EngineDebugger::is_profiling("multiplayer")) {
- Array values;
- values.push_back(p_inout);
- values.push_back(OS::get_singleton()->get_ticks_msec());
- values.push_back(p_size);
- EngineDebugger::profiler_add_frame_data("multiplayer", values);
- }
-}
-#endif
-
-void MultiplayerAPI::poll() {
- if (!multiplayer_peer.is_valid() || multiplayer_peer->get_connection_status() == MultiplayerPeer::CONNECTION_DISCONNECTED) {
- return;
- }
-
- multiplayer_peer->poll();
-
- if (!multiplayer_peer.is_valid()) { // It's possible that polling might have resulted in a disconnection, so check here.
- return;
- }
-
- while (multiplayer_peer->get_available_packet_count()) {
- int sender = multiplayer_peer->get_packet_peer();
- const uint8_t *packet;
- int len;
-
- Error err = multiplayer_peer->get_packet(&packet, len);
- if (err != OK) {
- ERR_PRINT("Error getting packet!");
- return; // Something is wrong!
- }
-
- remote_sender_id = sender;
- _process_packet(sender, packet, len);
- remote_sender_id = 0;
-
- if (!multiplayer_peer.is_valid()) {
- return; // It's also possible that a packet or RPC caused a disconnection, so also check here.
- }
- }
- replicator->on_network_process();
-}
-
-void MultiplayerAPI::clear() {
- connected_peers.clear();
- packet_cache.clear();
- cache->clear();
-}
-
-void MultiplayerAPI::set_root_path(const NodePath &p_path) {
- ERR_FAIL_COND_MSG(!p_path.is_absolute() && !p_path.is_empty(), "MultiplayerAPI root path must be absolute.");
- root_path = p_path;
-}
-
-NodePath MultiplayerAPI::get_root_path() const {
- return root_path;
-}
-
-void MultiplayerAPI::set_multiplayer_peer(const Ref<MultiplayerPeer> &p_peer) {
- if (p_peer == multiplayer_peer) {
- return; // Nothing to do
- }
-
- ERR_FAIL_COND_MSG(p_peer.is_valid() && p_peer->get_connection_status() == MultiplayerPeer::CONNECTION_DISCONNECTED,
- "Supplied MultiplayerPeer must be connecting or connected.");
-
- if (multiplayer_peer.is_valid()) {
- multiplayer_peer->disconnect("peer_connected", callable_mp(this, &MultiplayerAPI::_add_peer));
- multiplayer_peer->disconnect("peer_disconnected", callable_mp(this, &MultiplayerAPI::_del_peer));
- multiplayer_peer->disconnect("connection_succeeded", callable_mp(this, &MultiplayerAPI::_connected_to_server));
- multiplayer_peer->disconnect("connection_failed", callable_mp(this, &MultiplayerAPI::_connection_failed));
- multiplayer_peer->disconnect("server_disconnected", callable_mp(this, &MultiplayerAPI::_server_disconnected));
- clear();
- }
-
- multiplayer_peer = p_peer;
-
- if (multiplayer_peer.is_valid()) {
- multiplayer_peer->connect("peer_connected", callable_mp(this, &MultiplayerAPI::_add_peer));
- multiplayer_peer->connect("peer_disconnected", callable_mp(this, &MultiplayerAPI::_del_peer));
- multiplayer_peer->connect("connection_succeeded", callable_mp(this, &MultiplayerAPI::_connected_to_server));
- multiplayer_peer->connect("connection_failed", callable_mp(this, &MultiplayerAPI::_connection_failed));
- multiplayer_peer->connect("server_disconnected", callable_mp(this, &MultiplayerAPI::_server_disconnected));
- }
- replicator->on_reset();
-}
-
-Ref<MultiplayerPeer> MultiplayerAPI::get_multiplayer_peer() const {
- return multiplayer_peer;
-}
-
-void MultiplayerAPI::_process_packet(int p_from, const uint8_t *p_packet, int p_packet_len) {
- ERR_FAIL_COND_MSG(root_path.is_empty(), "Multiplayer root was not initialized. If you are using custom multiplayer, remember to set the root path via MultiplayerAPI.set_root_path before using it.");
- ERR_FAIL_COND_MSG(p_packet_len < 1, "Invalid packet received. Size too small.");
-
-#ifdef DEBUG_ENABLED
- profile_bandwidth("in", p_packet_len);
-#endif
-
- // Extract the `packet_type` from the LSB three bits:
- uint8_t packet_type = p_packet[0] & CMD_MASK;
-
- switch (packet_type) {
- case NETWORK_COMMAND_SIMPLIFY_PATH: {
- cache->process_simplify_path(p_from, p_packet, p_packet_len);
- } break;
-
- case NETWORK_COMMAND_CONFIRM_PATH: {
- cache->process_confirm_path(p_from, p_packet, p_packet_len);
- } break;
-
- case NETWORK_COMMAND_REMOTE_CALL: {
- rpc->process_rpc(p_from, p_packet, p_packet_len);
- } break;
-
- case NETWORK_COMMAND_RAW: {
- _process_raw(p_from, p_packet, p_packet_len);
- } break;
- case NETWORK_COMMAND_SPAWN: {
- replicator->on_spawn_receive(p_from, p_packet, p_packet_len);
- } break;
- case NETWORK_COMMAND_DESPAWN: {
- replicator->on_despawn_receive(p_from, p_packet, p_packet_len);
- } break;
- case NETWORK_COMMAND_SYNC: {
- replicator->on_sync_receive(p_from, p_packet, p_packet_len);
- } break;
- }
-}
-
-// The variant is compressed and encoded; The first byte contains all the meta
-// information and the format is:
-// - The first LSB 5 bits are used for the variant type.
-// - The next two bits are used to store the encoding mode.
-// - The most significant is used to store the boolean value.
-#define VARIANT_META_TYPE_MASK 0x1F
-#define VARIANT_META_EMODE_MASK 0x60
-#define VARIANT_META_BOOL_MASK 0x80
-#define ENCODE_8 0 << 5
-#define ENCODE_16 1 << 5
-#define ENCODE_32 2 << 5
-#define ENCODE_64 3 << 5
-Error MultiplayerAPI::encode_and_compress_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bool p_allow_object_decoding) {
- // Unreachable because `VARIANT_MAX` == 27 and `ENCODE_VARIANT_MASK` == 31
- CRASH_COND(p_variant.get_type() > VARIANT_META_TYPE_MASK);
-
- uint8_t *buf = r_buffer;
- r_len = 0;
- uint8_t encode_mode = 0;
-
- switch (p_variant.get_type()) {
- case Variant::BOOL: {
- if (buf) {
- // We still have 1 free bit in the meta, so let's use it.
- buf[0] = (p_variant.operator bool()) ? (1 << 7) : 0;
- buf[0] |= encode_mode | p_variant.get_type();
- }
- r_len += 1;
- } break;
- case Variant::INT: {
- if (buf) {
- // Reserve the first byte for the meta.
- buf += 1;
- }
- r_len += 1;
- int64_t val = p_variant;
- if (val <= (int64_t)INT8_MAX && val >= (int64_t)INT8_MIN) {
- // Use 8 bit
- encode_mode = ENCODE_8;
- if (buf) {
- buf[0] = val;
- }
- r_len += 1;
- } else if (val <= (int64_t)INT16_MAX && val >= (int64_t)INT16_MIN) {
- // Use 16 bit
- encode_mode = ENCODE_16;
- if (buf) {
- encode_uint16(val, buf);
- }
- r_len += 2;
- } else if (val <= (int64_t)INT32_MAX && val >= (int64_t)INT32_MIN) {
- // Use 32 bit
- encode_mode = ENCODE_32;
- if (buf) {
- encode_uint32(val, buf);
- }
- r_len += 4;
- } else {
- // Use 64 bit
- encode_mode = ENCODE_64;
- if (buf) {
- encode_uint64(val, buf);
- }
- r_len += 8;
- }
- // Store the meta
- if (buf) {
- buf -= 1;
- buf[0] = encode_mode | p_variant.get_type();
- }
- } break;
- default:
- // Any other case is not yet compressed.
- Error err = encode_variant(p_variant, r_buffer, r_len, p_allow_object_decoding);
- if (err != OK) {
- return err;
- }
- if (r_buffer) {
- // The first byte is not used by the marshalling, so store the type
- // so we know how to decompress and decode this variant.
- r_buffer[0] = p_variant.get_type();
- }
- }
-
- return OK;
-}
-
-Error MultiplayerAPI::decode_and_decompress_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int *r_len, bool p_allow_object_decoding) {
- const uint8_t *buf = p_buffer;
- int len = p_len;
-
- ERR_FAIL_COND_V(len < 1, ERR_INVALID_DATA);
- uint8_t type = buf[0] & VARIANT_META_TYPE_MASK;
- uint8_t encode_mode = buf[0] & VARIANT_META_EMODE_MASK;
-
- ERR_FAIL_COND_V(type >= Variant::VARIANT_MAX, ERR_INVALID_DATA);
-
- switch (type) {
- case Variant::BOOL: {
- bool val = (buf[0] & VARIANT_META_BOOL_MASK) > 0;
- r_variant = val;
- if (r_len) {
- *r_len = 1;
- }
- } break;
- case Variant::INT: {
- buf += 1;
- len -= 1;
- if (r_len) {
- *r_len = 1;
- }
- if (encode_mode == ENCODE_8) {
- // 8 bits.
- ERR_FAIL_COND_V(len < 1, ERR_INVALID_DATA);
- int8_t val = buf[0];
- r_variant = val;
- if (r_len) {
- (*r_len) += 1;
- }
- } else if (encode_mode == ENCODE_16) {
- // 16 bits.
- ERR_FAIL_COND_V(len < 2, ERR_INVALID_DATA);
- int16_t val = decode_uint16(buf);
- r_variant = val;
- if (r_len) {
- (*r_len) += 2;
- }
- } else if (encode_mode == ENCODE_32) {
- // 32 bits.
- ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
- int32_t val = decode_uint32(buf);
- r_variant = val;
- if (r_len) {
- (*r_len) += 4;
- }
- } else {
- // 64 bits.
- ERR_FAIL_COND_V(len < 8, ERR_INVALID_DATA);
- int64_t val = decode_uint64(buf);
- r_variant = val;
- if (r_len) {
- (*r_len) += 8;
- }
- }
- } break;
- default:
- Error err = decode_variant(r_variant, p_buffer, p_len, r_len, p_allow_object_decoding);
- if (err != OK) {
- return err;
- }
- }
-
- return OK;
-}
-
-Error MultiplayerAPI::encode_and_compress_variants(const Variant **p_variants, int p_count, uint8_t *p_buffer, int &r_len, bool *r_raw, bool p_allow_object_decoding) {
- r_len = 0;
- int size = 0;
-
- if (p_count == 0) {
- if (r_raw) {
- *r_raw = true;
- }
- return OK;
- }
-
- // Try raw encoding optimization.
- if (r_raw && p_count == 1) {
- *r_raw = false;
- const Variant &v = *(p_variants[0]);
- if (v.get_type() == Variant::PACKED_BYTE_ARRAY) {
- *r_raw = true;
- const PackedByteArray pba = v;
- if (p_buffer) {
- memcpy(p_buffer, pba.ptr(), pba.size());
- }
- r_len += pba.size();
- } else {
- encode_and_compress_variant(v, p_buffer, size, p_allow_object_decoding);
- r_len += size;
- }
- return OK;
- }
-
- // Regular encoding.
- for (int i = 0; i < p_count; i++) {
- const Variant &v = *(p_variants[i]);
- encode_and_compress_variant(v, p_buffer ? p_buffer + r_len : nullptr, size, p_allow_object_decoding);
- r_len += size;
- }
- return OK;
-}
-
-Error MultiplayerAPI::decode_and_decompress_variants(Vector<Variant> &r_variants, const uint8_t *p_buffer, int p_len, int &r_len, bool p_raw, bool p_allow_object_decoding) {
- r_len = 0;
- int argc = r_variants.size();
- if (argc == 0 && p_raw) {
- return OK;
- }
- ERR_FAIL_COND_V(p_raw && argc != 1, ERR_INVALID_DATA);
- if (p_raw) {
- r_len = p_len;
- PackedByteArray pba;
- pba.resize(p_len);
- memcpy(pba.ptrw(), p_buffer, p_len);
- r_variants.write[0] = pba;
- return OK;
- }
-
- Vector<Variant> args;
- Vector<const Variant *> argp;
- args.resize(argc);
-
- for (int i = 0; i < argc; i++) {
- ERR_FAIL_COND_V_MSG(r_len >= p_len, ERR_INVALID_DATA, "Invalid packet received. Size too small.");
-
- int vlen;
- Error err = MultiplayerAPI::decode_and_decompress_variant(r_variants.write[i], &p_buffer[r_len], p_len - r_len, &vlen, p_allow_object_decoding);
- ERR_FAIL_COND_V_MSG(err != OK, err, "Invalid packet received. Unable to decode state variable.");
- r_len += vlen;
- }
- return OK;
-}
-
-void MultiplayerAPI::_add_peer(int p_id) {
- connected_peers.insert(p_id);
- cache->on_peer_change(p_id, true);
- replicator->on_peer_change(p_id, true);
- emit_signal(SNAME("peer_connected"), p_id);
-}
-
-void MultiplayerAPI::_del_peer(int p_id) {
- replicator->on_peer_change(p_id, false);
- cache->on_peer_change(p_id, false);
- connected_peers.erase(p_id);
- emit_signal(SNAME("peer_disconnected"), p_id);
-}
-
-void MultiplayerAPI::_connected_to_server() {
- emit_signal(SNAME("connected_to_server"));
-}
-
-void MultiplayerAPI::_connection_failed() {
- emit_signal(SNAME("connection_failed"));
-}
-
-void MultiplayerAPI::_server_disconnected() {
- replicator->on_reset();
- emit_signal(SNAME("server_disconnected"));
-}
-
-Error MultiplayerAPI::send_bytes(Vector<uint8_t> p_data, int p_to, Multiplayer::TransferMode p_mode, int p_channel) {
- ERR_FAIL_COND_V_MSG(p_data.size() < 1, ERR_INVALID_DATA, "Trying to send an empty raw packet.");
- ERR_FAIL_COND_V_MSG(!multiplayer_peer.is_valid(), ERR_UNCONFIGURED, "Trying to send a raw packet while no multiplayer peer is active.");
- ERR_FAIL_COND_V_MSG(multiplayer_peer->get_connection_status() != MultiplayerPeer::CONNECTION_CONNECTED, ERR_UNCONFIGURED, "Trying to send a raw packet via a multiplayer peer which is not connected.");
-
- if (packet_cache.size() < p_data.size() + 1) {
- packet_cache.resize(p_data.size() + 1);
- }
-
- const uint8_t *r = p_data.ptr();
- packet_cache.write[0] = NETWORK_COMMAND_RAW;
- memcpy(&packet_cache.write[1], &r[0], p_data.size());
-
- multiplayer_peer->set_target_peer(p_to);
- multiplayer_peer->set_transfer_channel(p_channel);
- multiplayer_peer->set_transfer_mode(p_mode);
-
- return multiplayer_peer->put_packet(packet_cache.ptr(), p_data.size() + 1);
-}
-
-void MultiplayerAPI::_process_raw(int p_from, const uint8_t *p_packet, int p_packet_len) {
- ERR_FAIL_COND_MSG(p_packet_len < 2, "Invalid packet received. Size too small.");
-
- Vector<uint8_t> out;
- int len = p_packet_len - 1;
- out.resize(len);
- {
- uint8_t *w = out.ptrw();
- memcpy(&w[0], &p_packet[1], len);
- }
- emit_signal(SNAME("peer_packet"), p_from, out);
-}
-
-bool MultiplayerAPI::is_cache_confirmed(NodePath p_path, int p_peer) {
- return cache->is_cache_confirmed(p_path, p_peer);
-}
-
-bool MultiplayerAPI::send_object_cache(Object *p_obj, int p_peer_id, int &r_id) {
- return cache->send_object_cache(p_obj, p_peer_id, r_id);
-}
-
-int MultiplayerAPI::make_object_cache(Object *p_obj) {
- return cache->make_object_cache(p_obj);
-}
-
-Object *MultiplayerAPI::get_cached_object(int p_from, uint32_t p_cache_id) {
- return cache->get_cached_object(p_from, p_cache_id);
-}
-
-int MultiplayerAPI::get_unique_id() const {
- ERR_FAIL_COND_V_MSG(!multiplayer_peer.is_valid(), 0, "No multiplayer peer is assigned. Unable to get unique ID.");
- return multiplayer_peer->get_unique_id();
-}
-
-bool MultiplayerAPI::is_server() const {
- return multiplayer_peer.is_valid() && multiplayer_peer->is_server();
-}
-
-void MultiplayerAPI::set_refuse_new_connections(bool p_refuse) {
- ERR_FAIL_COND_MSG(!multiplayer_peer.is_valid(), "No multiplayer peer is assigned. Unable to set 'refuse_new_connections'.");
- multiplayer_peer->set_refuse_new_connections(p_refuse);
-}
-
-bool MultiplayerAPI::is_refusing_new_connections() const {
- ERR_FAIL_COND_V_MSG(!multiplayer_peer.is_valid(), false, "No multiplayer peer is assigned. Unable to get 'refuse_new_connections'.");
- return multiplayer_peer->is_refusing_new_connections();
-}
-
-Vector<int> MultiplayerAPI::get_peer_ids() const {
- ERR_FAIL_COND_V_MSG(!multiplayer_peer.is_valid(), Vector<int>(), "No multiplayer peer is assigned. Assume no peers are connected.");
-
- Vector<int> ret;
- for (const int &E : connected_peers) {
- ret.push_back(E);
- }
-
- return ret;
-}
-
-void MultiplayerAPI::set_allow_object_decoding(bool p_enable) {
- allow_object_decoding = p_enable;
-}
-
-bool MultiplayerAPI::is_object_decoding_allowed() const {
- return allow_object_decoding;
-}
-
-String MultiplayerAPI::get_rpc_md5(const Object *p_obj) const {
- return rpc->get_rpc_md5(p_obj);
-}
-
-void MultiplayerAPI::rpcp(Object *p_obj, int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount) {
- rpc->rpcp(p_obj, p_peer_id, p_method, p_arg, p_argcount);
-}
-
-Error MultiplayerAPI::spawn(Object *p_object, Variant p_config) {
- return replicator->on_spawn(p_object, p_config);
-}
-
-Error MultiplayerAPI::despawn(Object *p_object, Variant p_config) {
- return replicator->on_despawn(p_object, p_config);
-}
-
-Error MultiplayerAPI::replication_start(Object *p_object, Variant p_config) {
- return replicator->on_replication_start(p_object, p_config);
-}
-
-Error MultiplayerAPI::replication_stop(Object *p_object, Variant p_config) {
- return replicator->on_replication_stop(p_object, p_config);
-}
-
-void MultiplayerAPI::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_root_path", "path"), &MultiplayerAPI::set_root_path);
- ClassDB::bind_method(D_METHOD("get_root_path"), &MultiplayerAPI::get_root_path);
- ClassDB::bind_method(D_METHOD("send_bytes", "bytes", "id", "mode", "channel"), &MultiplayerAPI::send_bytes, DEFVAL(MultiplayerPeer::TARGET_PEER_BROADCAST), DEFVAL(Multiplayer::TRANSFER_MODE_RELIABLE), DEFVAL(0));
- ClassDB::bind_method(D_METHOD("has_multiplayer_peer"), &MultiplayerAPI::has_multiplayer_peer);
- ClassDB::bind_method(D_METHOD("get_multiplayer_peer"), &MultiplayerAPI::get_multiplayer_peer);
- ClassDB::bind_method(D_METHOD("set_multiplayer_peer", "peer"), &MultiplayerAPI::set_multiplayer_peer);
- ClassDB::bind_method(D_METHOD("get_unique_id"), &MultiplayerAPI::get_unique_id);
- ClassDB::bind_method(D_METHOD("is_server"), &MultiplayerAPI::is_server);
- ClassDB::bind_method(D_METHOD("get_remote_sender_id"), &MultiplayerAPI::get_remote_sender_id);
- ClassDB::bind_method(D_METHOD("poll"), &MultiplayerAPI::poll);
- ClassDB::bind_method(D_METHOD("clear"), &MultiplayerAPI::clear);
-
- ClassDB::bind_method(D_METHOD("get_peers"), &MultiplayerAPI::get_peer_ids);
- ClassDB::bind_method(D_METHOD("set_refuse_new_connections", "refuse"), &MultiplayerAPI::set_refuse_new_connections);
- ClassDB::bind_method(D_METHOD("is_refusing_new_connections"), &MultiplayerAPI::is_refusing_new_connections);
- ClassDB::bind_method(D_METHOD("set_allow_object_decoding", "enable"), &MultiplayerAPI::set_allow_object_decoding);
- ClassDB::bind_method(D_METHOD("is_object_decoding_allowed"), &MultiplayerAPI::is_object_decoding_allowed);
-
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_object_decoding"), "set_allow_object_decoding", "is_object_decoding_allowed");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "refuse_new_connections"), "set_refuse_new_connections", "is_refusing_new_connections");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "multiplayer_peer", PROPERTY_HINT_RESOURCE_TYPE, "MultiplayerPeer", PROPERTY_USAGE_NONE), "set_multiplayer_peer", "get_multiplayer_peer");
- ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "root_path"), "set_root_path", "get_root_path");
- ADD_PROPERTY_DEFAULT("refuse_new_connections", false);
-
- ADD_SIGNAL(MethodInfo("peer_connected", PropertyInfo(Variant::INT, "id")));
- ADD_SIGNAL(MethodInfo("peer_disconnected", PropertyInfo(Variant::INT, "id")));
- ADD_SIGNAL(MethodInfo("peer_packet", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::PACKED_BYTE_ARRAY, "packet")));
- ADD_SIGNAL(MethodInfo("connected_to_server"));
- ADD_SIGNAL(MethodInfo("connection_failed"));
- ADD_SIGNAL(MethodInfo("server_disconnected"));
-}
-
-MultiplayerAPI::MultiplayerAPI() {
- if (create_default_replication_interface) {
- replicator = Ref<MultiplayerReplicationInterface>(create_default_replication_interface(this));
- } else {
- replicator.instantiate();
- }
- if (create_default_rpc_interface) {
- rpc = Ref<MultiplayerRPCInterface>(create_default_rpc_interface(this));
- } else {
- rpc.instantiate();
- }
- if (create_default_cache_interface) {
- cache = Ref<MultiplayerCacheInterface>(create_default_cache_interface(this));
- } else {
- cache.instantiate();
- }
-}
-
-MultiplayerAPI::~MultiplayerAPI() {
- clear();
-}
diff --git a/core/multiplayer/multiplayer_api.h b/core/multiplayer/multiplayer_api.h
deleted file mode 100644
index 35452acb1f..0000000000
--- a/core/multiplayer/multiplayer_api.h
+++ /dev/null
@@ -1,196 +0,0 @@
-/*************************************************************************/
-/* multiplayer_api.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifndef MULTIPLAYER_API_H
-#define MULTIPLAYER_API_H
-
-#include "core/multiplayer/multiplayer.h"
-#include "core/multiplayer/multiplayer_peer.h"
-#include "core/object/ref_counted.h"
-
-class MultiplayerAPI;
-
-class MultiplayerReplicationInterface : public RefCounted {
- GDCLASS(MultiplayerReplicationInterface, RefCounted);
-
-public:
- virtual void on_peer_change(int p_id, bool p_connected) {}
- virtual void on_reset() {}
- virtual Error on_spawn_receive(int p_from, const uint8_t *p_buffer, int p_buffer_len) { return ERR_UNAVAILABLE; }
- virtual Error on_despawn_receive(int p_from, const uint8_t *p_buffer, int p_buffer_len) { return ERR_UNAVAILABLE; }
- virtual Error on_sync_receive(int p_from, const uint8_t *p_buffer, int p_buffer_len) { return ERR_UNAVAILABLE; }
- virtual Error on_spawn(Object *p_obj, Variant p_config) { return ERR_UNAVAILABLE; }
- virtual Error on_despawn(Object *p_obj, Variant p_config) { return ERR_UNAVAILABLE; }
- virtual Error on_replication_start(Object *p_obj, Variant p_config) { return ERR_UNAVAILABLE; }
- virtual Error on_replication_stop(Object *p_obj, Variant p_config) { return ERR_UNAVAILABLE; }
- virtual void on_network_process() {}
-
- MultiplayerReplicationInterface() {}
-};
-
-class MultiplayerRPCInterface : public RefCounted {
- GDCLASS(MultiplayerRPCInterface, RefCounted);
-
-public:
- // Called by Node.rpc
- virtual void rpcp(Object *p_obj, int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount) {}
- virtual void process_rpc(int p_from, const uint8_t *p_packet, int p_packet_len) {}
- virtual String get_rpc_md5(const Object *p_obj) const { return String(); }
-
- MultiplayerRPCInterface() {}
-};
-
-class MultiplayerCacheInterface : public RefCounted {
- GDCLASS(MultiplayerCacheInterface, RefCounted);
-
-public:
- virtual void clear() {}
- virtual void on_peer_change(int p_id, bool p_connected) {}
- virtual void process_simplify_path(int p_from, const uint8_t *p_packet, int p_packet_len) {}
- virtual void process_confirm_path(int p_from, const uint8_t *p_packet, int p_packet_len) {}
-
- // Returns true if all peers have cached path.
- virtual bool send_object_cache(Object *p_obj, int p_target, int &r_id) { return false; }
- virtual int make_object_cache(Object *p_obj) { return false; }
- virtual Object *get_cached_object(int p_from, uint32_t p_cache_id) { return nullptr; }
- virtual bool is_cache_confirmed(NodePath p_path, int p_peer) { return false; }
-
- MultiplayerCacheInterface() {}
-};
-
-class MultiplayerAPI : public RefCounted {
- GDCLASS(MultiplayerAPI, RefCounted);
-
-public:
- enum NetworkCommands {
- NETWORK_COMMAND_REMOTE_CALL = 0,
- NETWORK_COMMAND_SIMPLIFY_PATH,
- NETWORK_COMMAND_CONFIRM_PATH,
- NETWORK_COMMAND_RAW,
- NETWORK_COMMAND_SPAWN,
- NETWORK_COMMAND_DESPAWN,
- NETWORK_COMMAND_SYNC,
- };
-
- // For each command, the 4 MSB can contain custom flags, as defined by subsystems.
- enum {
- CMD_FLAG_0_SHIFT = 4,
- CMD_FLAG_1_SHIFT = 5,
- CMD_FLAG_2_SHIFT = 6,
- CMD_FLAG_3_SHIFT = 7,
- };
-
- // This is the mask that will be used to extract the command.
- enum {
- CMD_MASK = 7, // 0x7 -> 0b00001111
- };
-
-private:
- Ref<MultiplayerPeer> multiplayer_peer;
- HashSet<int> connected_peers;
- int remote_sender_id = 0;
- int remote_sender_override = 0;
-
- Vector<uint8_t> packet_cache;
-
- NodePath root_path;
- bool allow_object_decoding = false;
-
- Ref<MultiplayerCacheInterface> cache;
- Ref<MultiplayerReplicationInterface> replicator;
- Ref<MultiplayerRPCInterface> rpc;
-
-protected:
- static void _bind_methods();
-
- void _process_packet(int p_from, const uint8_t *p_packet, int p_packet_len);
- void _process_raw(int p_from, const uint8_t *p_packet, int p_packet_len);
-
-public:
- static MultiplayerReplicationInterface *(*create_default_replication_interface)(MultiplayerAPI *p_multiplayer);
- static MultiplayerRPCInterface *(*create_default_rpc_interface)(MultiplayerAPI *p_multiplayer);
- static MultiplayerCacheInterface *(*create_default_cache_interface)(MultiplayerAPI *p_multiplayer);
-
- static Error encode_and_compress_variant(const Variant &p_variant, uint8_t *p_buffer, int &r_len, bool p_allow_object_decoding);
- static Error decode_and_decompress_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int *r_len, bool p_allow_object_decoding);
- static Error encode_and_compress_variants(const Variant **p_variants, int p_count, uint8_t *p_buffer, int &r_len, bool *r_raw = nullptr, bool p_allow_object_decoding = false);
- static Error decode_and_decompress_variants(Vector<Variant> &r_variants, const uint8_t *p_buffer, int p_len, int &r_len, bool p_raw = false, bool p_allow_object_decoding = false);
-
- void poll();
- void clear();
- void set_root_path(const NodePath &p_path);
- NodePath get_root_path() const;
- void set_multiplayer_peer(const Ref<MultiplayerPeer> &p_peer);
- Ref<MultiplayerPeer> get_multiplayer_peer() const;
-
- Error send_bytes(Vector<uint8_t> p_data, int p_to = MultiplayerPeer::TARGET_PEER_BROADCAST, Multiplayer::TransferMode p_mode = Multiplayer::TRANSFER_MODE_RELIABLE, int p_channel = 0);
-
- // RPC API
- void rpcp(Object *p_obj, int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount);
- String get_rpc_md5(const Object *p_obj) const;
- // Replication API
- Error spawn(Object *p_object, Variant p_config);
- Error despawn(Object *p_object, Variant p_config);
- Error replication_start(Object *p_object, Variant p_config);
- Error replication_stop(Object *p_object, Variant p_config);
- // Cache API
- bool send_object_cache(Object *p_obj, int p_target, int &r_id);
- int make_object_cache(Object *p_obj);
- Object *get_cached_object(int p_from, uint32_t p_cache_id);
- bool is_cache_confirmed(NodePath p_path, int p_peer);
-
- void _add_peer(int p_id);
- void _del_peer(int p_id);
- void _connected_to_server();
- void _connection_failed();
- void _server_disconnected();
-
- bool has_multiplayer_peer() const { return multiplayer_peer.is_valid(); }
- Vector<int> get_peer_ids() const;
- const HashSet<int> get_connected_peers() const { return connected_peers; }
- int get_remote_sender_id() const { return remote_sender_override ? remote_sender_override : remote_sender_id; }
- void set_remote_sender_override(int p_id) { remote_sender_override = p_id; }
- int get_unique_id() const;
- bool is_server() const;
- void set_refuse_new_connections(bool p_refuse);
- bool is_refusing_new_connections() const;
-
- void set_allow_object_decoding(bool p_enable);
- bool is_object_decoding_allowed() const;
-
-#ifdef DEBUG_ENABLED
- void profile_bandwidth(const String &p_inout, int p_size);
-#endif
-
- MultiplayerAPI();
- ~MultiplayerAPI();
-};
-
-#endif // MULTIPLAYER_API_H
diff --git a/core/object/script_language.h b/core/object/script_language.h
index 686ab5b8d3..c9f8a4f828 100644
--- a/core/object/script_language.h
+++ b/core/object/script_language.h
@@ -33,7 +33,6 @@
#include "core/doc_data.h"
#include "core/io/resource.h"
-#include "core/multiplayer/multiplayer.h"
#include "core/templates/pair.h"
#include "core/templates/rb_map.h"
@@ -159,7 +158,7 @@ public:
virtual bool is_placeholder_fallback_enabled() const { return false; }
- virtual const Vector<Multiplayer::RPCConfig> get_rpc_methods() const = 0;
+ virtual const Variant get_rpc_config() const = 0;
Script() {}
};
@@ -213,7 +212,7 @@ public:
virtual void property_set_fallback(const StringName &p_name, const Variant &p_value, bool *r_valid);
virtual Variant property_get_fallback(const StringName &p_name, bool *r_valid);
- virtual const Vector<Multiplayer::RPCConfig> get_rpc_methods() const { return get_script()->get_rpc_methods(); }
+ virtual const Variant get_rpc_config() const { return get_script()->get_rpc_config(); }
virtual ScriptLanguage *get_language() = 0;
virtual ~ScriptInstance();
@@ -469,7 +468,7 @@ public:
virtual void property_set_fallback(const StringName &p_name, const Variant &p_value, bool *r_valid = nullptr) override;
virtual Variant property_get_fallback(const StringName &p_name, bool *r_valid = nullptr) override;
- virtual const Vector<Multiplayer::RPCConfig> get_rpc_methods() const override { return Vector<Multiplayer::RPCConfig>(); }
+ virtual const Variant get_rpc_config() const override { return Variant(); }
PlaceHolderScriptInstance(ScriptLanguage *p_language, Ref<Script> p_script, Object *p_owner);
~PlaceHolderScriptInstance();
diff --git a/core/object/script_language_extension.cpp b/core/object/script_language_extension.cpp
index ab8dd6d1ee..9de784ea7f 100644
--- a/core/object/script_language_extension.cpp
+++ b/core/object/script_language_extension.cpp
@@ -74,7 +74,7 @@ void ScriptExtension::_bind_methods() {
GDVIRTUAL_BIND(_get_members);
GDVIRTUAL_BIND(_is_placeholder_fallback_enabled);
- GDVIRTUAL_BIND(_get_rpc_methods);
+ GDVIRTUAL_BIND(_get_rpc_config);
}
void ScriptLanguageExtension::_bind_methods() {
diff --git a/core/object/script_language_extension.h b/core/object/script_language_extension.h
index 2c53139ec2..10eacfd9f7 100644
--- a/core/object/script_language_extension.h
+++ b/core/object/script_language_extension.h
@@ -173,28 +173,12 @@ public:
EXBIND0RC(bool, is_placeholder_fallback_enabled)
- GDVIRTUAL0RC(TypedArray<Dictionary>, _get_rpc_methods)
+ GDVIRTUAL0RC(Variant, _get_rpc_config)
- virtual const Vector<Multiplayer::RPCConfig> get_rpc_methods() const override {
- TypedArray<Dictionary> ret;
- GDVIRTUAL_REQUIRED_CALL(_get_rpc_methods, ret);
- Vector<Multiplayer::RPCConfig> rpcret;
- for (int i = 0; i < ret.size(); i++) {
- Dictionary d = ret[i];
- Multiplayer::RPCConfig rpc;
- ERR_CONTINUE(!d.has("name"));
- rpc.name = d["name"];
- ERR_CONTINUE(!d.has("rpc_mode"));
- rpc.rpc_mode = Multiplayer::RPCMode(int(d["rpc_mode"]));
- ERR_CONTINUE(!d.has("call_local"));
- rpc.call_local = d["call_local"];
- ERR_CONTINUE(!d.has("transfer_mode"));
- rpc.transfer_mode = Multiplayer::TransferMode(int(d["transfer_mode"]));
- ERR_CONTINUE(!d.has("channel"));
- rpc.channel = d["channel"];
- rpcret.push_back(rpc);
- }
- return rpcret;
+ virtual const Variant get_rpc_config() const override {
+ Variant ret;
+ GDVIRTUAL_REQUIRED_CALL(_get_rpc_config, ret);
+ return ret;
}
ScriptExtension() {}
diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp
index aab4b9a580..1ae5d1c83f 100644
--- a/core/register_core_types.cpp
+++ b/core/register_core_types.cpp
@@ -69,8 +69,6 @@
#include "core/math/geometry_3d.h"
#include "core/math/random_number_generator.h"
#include "core/math/triangle_mesh.h"
-#include "core/multiplayer/multiplayer_api.h"
-#include "core/multiplayer/multiplayer_peer.h"
#include "core/object/class_db.h"
#include "core/object/script_language_extension.h"
#include "core/object/undo_redo.h"
@@ -212,9 +210,6 @@ void register_core_types() {
resource_format_loader_crypto.instantiate();
ResourceLoader::add_resource_format_loader(resource_format_loader_crypto);
- GDREGISTER_ABSTRACT_CLASS(MultiplayerPeer);
- GDREGISTER_CLASS(MultiplayerPeerExtension);
- GDREGISTER_CLASS(MultiplayerAPI);
GDREGISTER_CLASS(MainLoop);
GDREGISTER_CLASS(Translation);
GDREGISTER_CLASS(OptimizedTranslation);
diff --git a/core/variant/callable.cpp b/core/variant/callable.cpp
index f20ec4037a..8b9b5f41de 100644
--- a/core/variant/callable.cpp
+++ b/core/variant/callable.cpp
@@ -63,17 +63,19 @@ void Callable::call(const Variant **p_arguments, int p_argcount, Variant &r_retu
}
}
-void Callable::rpc(int p_id, const Variant **p_arguments, int p_argcount, CallError &r_call_error) const {
+Error Callable::rpc(int p_id, const Variant **p_arguments, int p_argcount, CallError &r_call_error) const {
if (is_null()) {
r_call_error.error = CallError::CALL_ERROR_INSTANCE_IS_NULL;
r_call_error.argument = 0;
r_call_error.expected = 0;
+ return ERR_UNCONFIGURED;
} else if (!is_custom()) {
r_call_error.error = CallError::CALL_ERROR_INVALID_METHOD;
r_call_error.argument = 0;
r_call_error.expected = 0;
+ return ERR_UNCONFIGURED;
} else {
- custom->rpc(p_id, p_arguments, p_argcount, r_call_error);
+ return custom->rpc(p_id, p_arguments, p_argcount, r_call_error);
}
}
@@ -316,10 +318,11 @@ StringName CallableCustom::get_method() const {
ERR_FAIL_V_MSG(StringName(), vformat("Can't get method on CallableCustom \"%s\".", get_as_text()));
}
-void CallableCustom::rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const {
+Error CallableCustom::rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const {
r_call_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
r_call_error.argument = 0;
r_call_error.expected = 0;
+ return ERR_UNCONFIGURED;
}
const Callable *CallableCustom::get_base_comparator() const {
diff --git a/core/variant/callable.h b/core/variant/callable.h
index bbcf5427ba..954365d010 100644
--- a/core/variant/callable.h
+++ b/core/variant/callable.h
@@ -71,7 +71,7 @@ public:
void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, CallError &r_call_error) const;
void call_deferred(const Variant **p_arguments, int p_argcount) const;
- void rpc(int p_id, const Variant **p_arguments, int p_argcount, CallError &r_call_error) const;
+ Error rpc(int p_id, const Variant **p_arguments, int p_argcount, CallError &r_call_error) const;
_FORCE_INLINE_ bool is_null() const {
return method == StringName() && object == 0;
@@ -129,7 +129,7 @@ public:
virtual StringName get_method() const;
virtual ObjectID get_object() const = 0; //must always be able to provide an object
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const = 0;
- virtual void rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const;
+ virtual Error rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const;
virtual const Callable *get_base_comparator() const;
CallableCustom();
diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp
index 6b04c6e4e8..56fc16c5a3 100644
--- a/core/variant/variant_call.cpp
+++ b/core/variant/variant_call.cpp
@@ -1781,7 +1781,7 @@ static void _register_variant_builtin_methods() {
bind_method(Quaternion, dot, sarray("with"), varray());
bind_method(Quaternion, slerp, sarray("to", "weight"), varray());
bind_method(Quaternion, slerpni, sarray("to", "weight"), varray());
- bind_method(Quaternion, cubic_slerp, sarray("b", "pre_a", "post_b", "weight"), varray());
+ bind_method(Quaternion, spherical_cubic_interpolate, sarray("b", "pre_a", "post_b", "weight"), varray());
bind_method(Quaternion, get_euler, sarray(), varray());
bind_method(Quaternion, get_axis, sarray(), varray());
bind_method(Quaternion, get_angle, sarray(), varray());
@@ -1883,7 +1883,7 @@ static void _register_variant_builtin_methods() {
bind_method(Transform2D, orthonormalized, sarray(), varray());
bind_method(Transform2D, rotated, sarray("angle"), varray());
bind_method(Transform2D, scaled, sarray("scale"), varray());
- bind_method(Transform2D, translated, sarray("offset"), varray());
+ bind_method(Transform2D, translated_local, sarray("offset"), varray());
bind_method(Transform2D, basis_xform, sarray("v"), varray());
bind_method(Transform2D, basis_xform_inv, sarray("v"), varray());
bind_method(Transform2D, interpolate_with, sarray("xform", "weight"), varray());
@@ -1948,9 +1948,9 @@ static void _register_variant_builtin_methods() {
bind_method(Transform3D, orthonormalized, sarray(), varray());
bind_method(Transform3D, rotated, sarray("axis", "angle"), varray());
bind_method(Transform3D, scaled, sarray("scale"), varray());
- bind_method(Transform3D, translated, sarray("offset"), varray());
+ bind_method(Transform3D, translated_local, sarray("offset"), varray());
bind_method(Transform3D, looking_at, sarray("target", "up"), varray(Vector3(0, 1, 0)));
- bind_method(Transform3D, sphere_interpolate_with, sarray("xform", "weight"), varray());
+ bind_method(Transform3D, spherical_interpolate_with, sarray("xform", "weight"), varray());
bind_method(Transform3D, interpolate_with, sarray("xform", "weight"), varray());
bind_method(Transform3D, is_equal_approx, sarray("xform"), varray());
diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml
index 30a2228294..709863b70f 100644
--- a/doc/classes/@GlobalScope.xml
+++ b/doc/classes/@GlobalScope.xml
@@ -2728,24 +2728,6 @@
<constant name="METHOD_FLAGS_DEFAULT" value="1" enum="MethodFlags">
Default method flags.
</constant>
- <constant name="RPC_MODE_DISABLED" value="0" enum="RPCMode">
- Used with [method Node.rpc_config] to disable a method or property for all RPC calls, making it unavailable. Default for all methods.
- </constant>
- <constant name="RPC_MODE_ANY_PEER" value="1" enum="RPCMode">
- Used with [method Node.rpc_config] to set a method to be callable remotely by any peer. Analogous to the [code]@rpc(any)[/code] annotation. Calls are accepted from all remote peers, no matter if they are node's authority or not.
- </constant>
- <constant name="RPC_MODE_AUTHORITY" value="2" enum="RPCMode">
- Used with [method Node.rpc_config] to set a method to be callable remotely only by the current multiplayer authority (which is the server by default). Analogous to the [code]@rpc(authority)[/code] annotation. See [method Node.set_multiplayer_authority].
- </constant>
- <constant name="TRANSFER_MODE_UNRELIABLE" value="0" enum="TransferMode">
- Packets are not acknowledged, no resend attempts are made for lost packets. Packets may arrive in any order. Potentially faster than [constant TRANSFER_MODE_UNRELIABLE_ORDERED]. Use for non-critical data, and always consider whether the order matters.
- </constant>
- <constant name="TRANSFER_MODE_UNRELIABLE_ORDERED" value="1" enum="TransferMode">
- Packets are not acknowledged, no resend attempts are made for lost packets. Packets are received in the order they were sent in. Potentially faster than [constant TRANSFER_MODE_RELIABLE]. Use for non-critical data or data that would be outdated if received late due to resend attempt(s) anyway, for example movement and positional data.
- </constant>
- <constant name="TRANSFER_MODE_RELIABLE" value="2" enum="TransferMode">
- Packets must be received and resend attempts should be made until the packets are acknowledged. Packets must be received in the order they were sent in. Most reliable transfer mode, but potentially the slowest due to the overhead. Use for critical data that must be transmitted and arrive in order, for example an ability being triggered or a chat message. Consider carefully if the information really is critical, and use sparingly.
- </constant>
<constant name="TYPE_NIL" value="0" enum="Variant.Type">
Variable is [code]null[/code].
</constant>
diff --git a/doc/classes/AudioEffectRecord.xml b/doc/classes/AudioEffectRecord.xml
index 9728011bb2..32a6aea340 100644
--- a/doc/classes/AudioEffectRecord.xml
+++ b/doc/classes/AudioEffectRecord.xml
@@ -14,7 +14,7 @@
</tutorials>
<methods>
<method name="get_recording" qualifiers="const">
- <return type="AudioStreamSample" />
+ <return type="AudioStreamWAV" />
<description>
Returns the recorded sample.
</description>
@@ -34,8 +34,8 @@
</method>
</methods>
<members>
- <member name="format" type="int" setter="set_format" getter="get_format" enum="AudioStreamSample.Format" default="1">
- Specifies the format in which the sample will be recorded. See [enum AudioStreamSample.Format] for available formats.
+ <member name="format" type="int" setter="set_format" getter="get_format" enum="AudioStreamWAV.Format" default="1">
+ Specifies the format in which the sample will be recorded. See [enum AudioStreamWAV.Format] for available formats.
</member>
</members>
</class>
diff --git a/doc/classes/AudioStream.xml b/doc/classes/AudioStream.xml
index 68f64505d0..7645cafe86 100644
--- a/doc/classes/AudioStream.xml
+++ b/doc/classes/AudioStream.xml
@@ -4,7 +4,7 @@
Base class for audio streams.
</brief_description>
<description>
- Base class for audio streams. Audio streams are used for sound effects and music playback, and support WAV (via [AudioStreamSample]) and OGG (via [AudioStreamOGGVorbis]) file formats.
+ Base class for audio streams. Audio streams are used for sound effects and music playback, and support WAV (via [AudioStreamWAV]) and Ogg (via [AudioStreamOggVorbis]) file formats.
</description>
<tutorials>
<link title="Audio streams">$DOCS_URL/tutorials/audio/audio_streams.html</link>
diff --git a/doc/classes/AudioStreamPlayback.xml b/doc/classes/AudioStreamPlayback.xml
index d3d97e0c8a..f1a1c18c1c 100644
--- a/doc/classes/AudioStreamPlayback.xml
+++ b/doc/classes/AudioStreamPlayback.xml
@@ -4,7 +4,7 @@
Meta class for playing back audio.
</brief_description>
<description>
- Can play, loop, pause a scroll through audio. See [AudioStream] and [AudioStreamOGGVorbis] for usage.
+ Can play, loop, pause a scroll through audio. See [AudioStream] and [AudioStreamOggVorbis] for usage.
</description>
<tutorials>
<link title="Audio Generator Demo">https://godotengine.org/asset-library/asset/526</link>
diff --git a/doc/classes/AudioStreamSample.xml b/doc/classes/AudioStreamWAV.xml
index 62f27ce876..17595aec2f 100644
--- a/doc/classes/AudioStreamSample.xml
+++ b/doc/classes/AudioStreamWAV.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AudioStreamSample" inherits="AudioStream" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="AudioStreamWAV" inherits="AudioStream" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Stores audio data loaded from WAV files.
</brief_description>
<description>
- AudioStreamSample stores sound samples loaded from WAV files. To play the stored sound, use an [AudioStreamPlayer] (for non-positional audio) or [AudioStreamPlayer2D]/[AudioStreamPlayer3D] (for positional audio). The sound can be looped.
+ AudioStreamWAV stores sound samples loaded from WAV files. To play the stored sound, use an [AudioStreamPlayer] (for non-positional audio) or [AudioStreamPlayer2D]/[AudioStreamPlayer3D] (for positional audio). The sound can be looped.
This class can also be used to store dynamically-generated PCM audio data. See also [AudioStreamGenerator] for procedural audio generation.
</description>
<tutorials>
@@ -14,7 +14,7 @@
<return type="int" enum="Error" />
<argument index="0" name="path" type="String" />
<description>
- Saves the AudioStreamSample as a WAV file to [code]path[/code]. Samples with IMA ADPCM format can't be saved.
+ Saves the AudioStreamWAV as a WAV file to [code]path[/code]. Samples with IMA ADPCM format can't be saved.
[b]Note:[/b] A [code].wav[/code] extension is automatically appended to [code]path[/code] if it is missing.
</description>
</method>
@@ -24,7 +24,7 @@
Contains the audio data in bytes.
[b]Note:[/b] This property expects signed PCM8 data. To convert unsigned PCM8 to signed PCM8, subtract 128 from each byte.
</member>
- <member name="format" type="int" setter="set_format" getter="get_format" enum="AudioStreamSample.Format" default="0">
+ <member name="format" type="int" setter="set_format" getter="get_format" enum="AudioStreamWAV.Format" default="0">
Audio format. See [enum Format] constants for values.
</member>
<member name="loop_begin" type="int" setter="set_loop_begin" getter="get_loop_begin" default="0">
@@ -33,7 +33,7 @@
<member name="loop_end" type="int" setter="set_loop_end" getter="get_loop_end" default="0">
The loop end point (in number of samples, relative to the beginning of the sample). This information will be imported automatically from the WAV file if present.
</member>
- <member name="loop_mode" type="int" setter="set_loop_mode" getter="get_loop_mode" enum="AudioStreamSample.LoopMode" default="0">
+ <member name="loop_mode" type="int" setter="set_loop_mode" getter="get_loop_mode" enum="AudioStreamWAV.LoopMode" default="0">
The loop mode. This information will be imported automatically from the WAV file if present. See [enum LoopMode] constants for values.
</member>
<member name="mix_rate" type="int" setter="set_mix_rate" getter="get_mix_rate" default="44100">
diff --git a/doc/classes/MultiplayerAPI.xml b/doc/classes/MultiplayerAPI.xml
index 059d147979..06658bf004 100644
--- a/doc/classes/MultiplayerAPI.xml
+++ b/doc/classes/MultiplayerAPI.xml
@@ -1,88 +1,108 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="MultiplayerAPI" inherits="RefCounted" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
- High-level multiplayer API.
+ High-level multiplayer API interface.
</brief_description>
<description>
- This class implements the high-level multiplayer API. See also [MultiplayerPeer].
- By default, [SceneTree] has a reference to this class that is used to provide multiplayer capabilities (i.e. RPCs) across the whole scene.
+ Base class for high-level multiplayer API implementations. See also [MultiplayerPeer].
+ By default, [SceneTree] has a reference to an implementation of this class and uses it to provide multiplayer capabilities (i.e. RPCs) across the whole scene.
It is possible to override the MultiplayerAPI instance used by specific tree branches by calling the [method SceneTree.set_multiplayer] method, effectively allowing to run both client and server in the same scene.
- [b]Note:[/b] The high-level multiplayer API protocol is an implementation detail and isn't meant to be used by non-Godot servers. It may change without notice.
- [b]Note:[/b] When exporting to Android, make sure to enable the [code]INTERNET[/code] permission in the Android export preset before exporting the project or using one-click deploy. Otherwise, network communication of any kind will be blocked by Android.
+ It is also possible to extend or replace the default implementation via scripting or native extensions. See [MultiplayerAPIExtension] for details about extensions, [SceneMultiplayer] for the details about the default implementation.
</description>
<tutorials>
</tutorials>
<methods>
- <method name="clear">
- <return type="void" />
+ <method name="create_default_interface" qualifiers="static">
+ <return type="MultiplayerAPI" />
+ <description>
+ Returns a new instance of the default MultiplayerAPI.
+ </description>
+ </method>
+ <method name="get_default_interface" qualifiers="static">
+ <return type="StringName" />
<description>
- Clears the current MultiplayerAPI network state (you shouldn't call this unless you know what you are doing).
+ Returns the default MultiplayerAPI implementation class name. This is usually [code]"SceneMultiplayer"[/code] when [SceneMultiplayer] is available. See [method set_default_interface].
</description>
</method>
- <method name="get_peers" qualifiers="const">
+ <method name="get_peers">
<return type="PackedInt32Array" />
<description>
Returns the peer IDs of all connected peers of this MultiplayerAPI's [member multiplayer_peer].
</description>
</method>
- <method name="get_remote_sender_id" qualifiers="const">
+ <method name="get_remote_sender_id">
<return type="int" />
<description>
Returns the sender's peer ID for the RPC currently being executed.
[b]Note:[/b] If not inside an RPC this method will return 0.
</description>
</method>
- <method name="get_unique_id" qualifiers="const">
+ <method name="get_unique_id">
<return type="int" />
<description>
Returns the unique peer ID of this MultiplayerAPI's [member multiplayer_peer].
</description>
</method>
- <method name="has_multiplayer_peer" qualifiers="const">
+ <method name="has_multiplayer_peer">
<return type="bool" />
<description>
Returns [code]true[/code] if there is a [member multiplayer_peer] set.
</description>
</method>
- <method name="is_server" qualifiers="const">
+ <method name="is_server">
<return type="bool" />
<description>
Returns [code]true[/code] if this MultiplayerAPI's [member multiplayer_peer] is valid and in server mode (listening for connections).
</description>
</method>
+ <method name="object_configuration_add">
+ <return type="int" enum="Error" />
+ <argument index="0" name="object" type="Object" />
+ <argument index="1" name="configuration" type="Variant" />
+ <description>
+ Notifies the MultiplayerAPI of a new [code]configuration[/code] for the given [code]object[/code]. This method is used internally by [SceneTree] to configure the root path for this MultiplayerAPI (passing [code]null[/code] and a valid [NodePath] as [code]configuration[/code]). This method can be further used by MultiplayerAPI implementations to provide additional features, refer to specific implementation (e.g. [SceneMultiplayer]) for details on how they use it.
+ [b]Note:[/b] This method is mostly relevant when extending or overriding the MultiplayerAPI behavior via [MultiplayerAPIExtension].
+ </description>
+ </method>
+ <method name="object_configuration_remove">
+ <return type="int" enum="Error" />
+ <argument index="0" name="object" type="Object" />
+ <argument index="1" name="configuration" type="Variant" />
+ <description>
+ Notifies the MultiplayerAPI to remove a [code]configuration[/code] for the given [code]object[/code]. This method is used internally by [SceneTree] to configure the root path for this MultiplayerAPI (passing [code]null[/code] and an empty [NodePath] as [code]configuration[/code]). This method can be further used by MultiplayerAPI implementations to provide additional features, refer to specific implementation (e.g. [SceneMultiplayer]) for details on how they use it.
+ [b]Note:[/b] This method is mostly relevant when extending or overriding the MultiplayerAPI behavior via [MultiplayerAPIExtension].
+ </description>
+ </method>
<method name="poll">
- <return type="void" />
+ <return type="int" enum="Error" />
<description>
Method used for polling the MultiplayerAPI. You only need to worry about this if you set [member SceneTree.multiplayer_poll] to [code]false[/code]. By default, [SceneTree] will poll its MultiplayerAPI(s) for you.
[b]Note:[/b] This method results in RPCs being called, so they will be executed in the same context of this function (e.g. [code]_process[/code], [code]physics[/code], [Thread]).
</description>
</method>
- <method name="send_bytes">
+ <method name="rpc">
<return type="int" enum="Error" />
- <argument index="0" name="bytes" type="PackedByteArray" />
- <argument index="1" name="id" type="int" default="0" />
- <argument index="2" name="mode" type="int" enum="TransferMode" default="2" />
- <argument index="3" name="channel" type="int" default="0" />
+ <argument index="0" name="peer" type="int" />
+ <argument index="1" name="object" type="Object" />
+ <argument index="2" name="method" type="StringName" />
+ <argument index="3" name="arguments" type="Array" default="[]" />
+ <description>
+ Sends an RPC to the target [code]peer[/code]. The given [code]method[/code] will be called on the remote [code]object[/code] with the provided [code]arguments[/code]. The RPC may also be called locally depending on the implementation and RPC configuration. See [method Node.rpc] and [method Node.rpc_config].
+ [b]Note:[/b] Prefer using [method Node.rpc], [method Node.rpc_id], or [code]my_method.rpc(peer, arg1, arg2, ...)[/code] (in GDScript), since they are faster. This method is mostly useful in conjunction with [MultiplayerAPIExtension] when augmenting or replacing the multiplayer capabilities.
+ </description>
+ </method>
+ <method name="set_default_interface" qualifiers="static">
+ <return type="void" />
+ <argument index="0" name="interface_name" type="StringName" />
<description>
- Sends the given raw [code]bytes[/code] to a specific peer identified by [code]id[/code] (see [method MultiplayerPeer.set_target_peer]). Default ID is [code]0[/code], i.e. broadcast to all peers.
+ Sets the default MultiplayerAPI implementation class. This method can be used by modules and extensions to configure which implementation will be used by [SceneTree] when the engine starts.
</description>
</method>
</methods>
<members>
- <member name="allow_object_decoding" type="bool" setter="set_allow_object_decoding" getter="is_object_decoding_allowed" default="false">
- If [code]true[/code], the MultiplayerAPI will allow encoding and decoding of object during RPCs.
- [b]Warning:[/b] Deserialized objects can contain code which gets executed. Do not use this option if the serialized object comes from untrusted sources to avoid potential security threats such as remote code execution.
- </member>
<member name="multiplayer_peer" type="MultiplayerPeer" setter="set_multiplayer_peer" getter="get_multiplayer_peer">
The peer object to handle the RPC system (effectively enabling networking when set). Depending on the peer itself, the MultiplayerAPI will become a network server (check with [method is_server]) and will set root node's network mode to authority, or it will become a regular client peer. All child nodes are set to inherit the network mode by default. Handling of networking-related events (connection, disconnection, new clients) is done by connecting to MultiplayerAPI's signals.
</member>
- <member name="refuse_new_connections" type="bool" setter="set_refuse_new_connections" getter="is_refusing_new_connections" default="false">
- If [code]true[/code], the MultiplayerAPI's [member multiplayer_peer] refuses new incoming connections.
- </member>
- <member name="root_path" type="NodePath" setter="set_root_path" getter="get_root_path" default="NodePath(&quot;&quot;)">
- The root path to use for RPCs and replication. Instead of an absolute path, a relative path will be used to find the node upon which the RPC should be executed.
- This effectively allows to have different branches of the scene tree to be managed by different MultiplayerAPI, allowing for example to run both client and server in the same scene.
- </member>
</members>
<signals>
<signal name="connected_to_server">
@@ -107,17 +127,21 @@
Emitted when this MultiplayerAPI's [member multiplayer_peer] disconnects from a peer. Clients get notified when other clients disconnect from the same server.
</description>
</signal>
- <signal name="peer_packet">
- <argument index="0" name="id" type="int" />
- <argument index="1" name="packet" type="PackedByteArray" />
- <description>
- Emitted when this MultiplayerAPI's [member multiplayer_peer] receives a [code]packet[/code] with custom data (see [method send_bytes]). ID is the peer ID of the peer that sent the packet.
- </description>
- </signal>
<signal name="server_disconnected">
<description>
Emitted when this MultiplayerAPI's [member multiplayer_peer] disconnects from server. Only emitted on clients.
</description>
</signal>
</signals>
+ <constants>
+ <constant name="RPC_MODE_DISABLED" value="0" enum="RPCMode">
+ Used with [method Node.rpc_config] to disable a method or property for all RPC calls, making it unavailable. Default for all methods.
+ </constant>
+ <constant name="RPC_MODE_ANY_PEER" value="1" enum="RPCMode">
+ Used with [method Node.rpc_config] to set a method to be callable remotely by any peer. Analogous to the [code]@rpc(any)[/code] annotation. Calls are accepted from all remote peers, no matter if they are node's authority or not.
+ </constant>
+ <constant name="RPC_MODE_AUTHORITY" value="2" enum="RPCMode">
+ Used with [method Node.rpc_config] to set a method to be callable remotely only by the current multiplayer authority (which is the server by default). Analogous to the [code]@rpc(authority)[/code] annotation. See [method Node.set_multiplayer_authority].
+ </constant>
+ </constants>
</class>
diff --git a/doc/classes/MultiplayerAPIExtension.xml b/doc/classes/MultiplayerAPIExtension.xml
new file mode 100644
index 0000000000..c369977d57
--- /dev/null
+++ b/doc/classes/MultiplayerAPIExtension.xml
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="MultiplayerAPIExtension" inherits="MultiplayerAPI" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+ <brief_description>
+ Base class used for extending the [MultiplayerAPI].
+ </brief_description>
+ <description>
+ This class can be used to augment or replace the default [MultiplayerAPI] implementation via script or extensions.
+ The following example augment the default implemenation ([SceneMultiplayer]) by logging every RPC being made, and every object being configured for replication.
+ [codeblocks]
+ [gdscript]
+ extends MultiplayerAPIExtension
+ class_name LogMultiplayer
+
+ # We want to augment the default SceneMultiplayer.
+ var base_multiplayer = SceneMultiplayer.new()
+
+ func _init():
+ # Just passthourgh base signals (copied to var to avoid cyclic reference)
+ var cts = connected_to_server
+ var cf = connection_failed
+ var pc = peer_connected
+ var pd = peer_disconnected
+ base_multiplayer.connected_to_server.connect(func(): cts.emit())
+ base_multiplayer.connection_failed.connect(func(): cf.emit())
+ base_multiplayer.peer_connected.connect(func(id): pc.emit(id))
+ base_multiplayer.peer_disconnected.connect(func(id): pd.emit(id))
+
+ # Log RPC being made and forward it to the default multiplayer.
+ func _rpc(peer: int, object: Object, method: StringName, args: Array) -&gt; int: # Error
+ print("Got RPC for %d: %s::%s(%s)" % [peer, object, method, args])
+ return base_multiplayer.rpc(peer, object, method, args)
+
+ # Log configuration add. E.g. root path (nullptr, NodePath), replication (Node, Spawner|Synchronizer), custom.
+ func _object_configuration_add(object, config: Variant) -&gt; int: # Error
+ if config is MultiplayerSynchronizer:
+ print("Adding synchronization configuration for %s. Synchronizer: %s" % [object, config])
+ elif config is MultiplayerSpawner:
+ print("Adding node %s to the spawn list. Spawner: %s" % [object, config])
+ return base_multiplayer.object_configuration_add(object, config)
+
+ # Log configuration remove. E.g. root path (nullptr, NodePath), replication (Node, Spawner|Synchronizer), custom.
+ func _object_configuration_remove(object, config: Variant) -&gt; int: # Error
+ if config is MultiplayerSynchronizer:
+ print("Removing synchronization configuration for %s. Synchronizer: %s" % [object, config])
+ elif config is MultiplayerSpawner:
+ print("Removing node %s from the spawn list. Spawner: %s" % [object, config])
+ return base_multiplayer.object_configuration_remove(object, config)
+
+ # These can be optional, but in our case we want to augment SceneMultiplayer, so forward everything.
+ func _set_multiplayer_peer(p_peer: MultiplayerPeer):
+ base_multiplayer.multiplayer_peer = p_peer
+
+ func _get_multiplayer_peer() -&gt; MultiplayerPeer:
+ return base_multiplayer.multiplayer_peer
+
+ func _get_unique_id() -&gt; int:
+ return base_multiplayer.get_unique_id()
+
+ func _get_peer_ids() -&gt; PackedInt32Array:
+ return base_multiplayer.get_peers()
+ [/gdscript]
+ [/codeblocks]
+ Then in your main scene or in an autoload call [method SceneTree.set_multiplayer] to start using your custom [MultiplayerAPI]:
+ [codeblocks]
+ [gdscript]
+ # autoload.gd
+ func _enter_tree():
+ # Sets our custom multiplayer as the main one in SceneTree.
+ get_tree().set_multiplayer(LogMultiplayer.new())
+ [/gdscript]
+ [/codeblocks]
+ Native extensions can alternatively use the [method MultiplayerAPI.set_default_interface] method during initialization to configure themselves as the default implementation.
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ <method name="_get_multiplayer_peer" qualifiers="virtual">
+ <return type="MultiplayerPeer" />
+ <description>
+ Called when the [member MultiplayerAPI.multiplayer_peer] is retrieved.
+ </description>
+ </method>
+ <method name="_get_peer_ids" qualifiers="virtual const">
+ <return type="PackedInt32Array" />
+ <description>
+ Callback for [method MultiplayerAPI.get_peers].
+ </description>
+ </method>
+ <method name="_get_remote_sender_id" qualifiers="virtual const">
+ <return type="int" />
+ <description>
+ Callback for [method MultiplayerAPI.get_remote_sender_id].
+ </description>
+ </method>
+ <method name="_get_unique_id" qualifiers="virtual const">
+ <return type="int" />
+ <description>
+ Callback for [method MultiplayerAPI.get_unique_id].
+ </description>
+ </method>
+ <method name="_object_configuration_add" qualifiers="virtual">
+ <return type="int" />
+ <argument index="0" name="object" type="Object" />
+ <argument index="1" name="configuration" type="Variant" />
+ <description>
+ Callback for [method MultiplayerAPI.object_configuration_add].
+ </description>
+ </method>
+ <method name="_object_configuration_remove" qualifiers="virtual">
+ <return type="int" />
+ <argument index="0" name="object" type="Object" />
+ <argument index="1" name="configuration" type="Variant" />
+ <description>
+ Callback for [method MultiplayerAPI.object_configuration_remove].
+ </description>
+ </method>
+ <method name="_poll" qualifiers="virtual">
+ <return type="int" />
+ <description>
+ Callback for [method MultiplayerAPI.poll].
+ </description>
+ </method>
+ <method name="_rpc" qualifiers="virtual">
+ <return type="int" />
+ <argument index="0" name="peer" type="int" />
+ <argument index="1" name="object" type="Object" />
+ <argument index="2" name="method" type="StringName" />
+ <argument index="3" name="args" type="Array" />
+ <description>
+ Callback for [method MultiplayerAPI.rpc].
+ </description>
+ </method>
+ <method name="_set_multiplayer_peer" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="multiplayer_peer" type="MultiplayerPeer" />
+ <description>
+ Called when the [member MultiplayerAPI.multiplayer_peer] is set.
+ </description>
+ </method>
+ </methods>
+</class>
diff --git a/doc/classes/MultiplayerPeer.xml b/doc/classes/MultiplayerPeer.xml
index 4a3559b0f7..6dde40f018 100644
--- a/doc/classes/MultiplayerPeer.xml
+++ b/doc/classes/MultiplayerPeer.xml
@@ -60,7 +60,7 @@
The channel to use to send packets. Many network APIs such as ENet and WebRTC allow the creation of multiple independent channels which behaves, in a way, like separate connections. This means that reliable data will only block delivery of other packets on that channel, and ordering will only be in respect to the channel the packet is being sent on. Using different channels to send [b]different and independent[/b] state updates is a common way to optimize network usage and decrease latency in fast-paced games.
[b]Note:[/b] The default channel ([code]0[/code]) actually works as 3 separate channels (one for each [enum TransferMode]) so that [constant TRANSFER_MODE_RELIABLE] and [constant TRANSFER_MODE_UNRELIABLE_ORDERED] does not interact with each other by default. Refer to the specific network API documentation (e.g. ENet or WebRTC) to learn how to set up channels correctly.
</member>
- <member name="transfer_mode" type="int" setter="set_transfer_mode" getter="get_transfer_mode" enum="TransferMode" default="2">
+ <member name="transfer_mode" type="int" setter="set_transfer_mode" getter="get_transfer_mode" enum="MultiplayerPeer.TransferMode" default="2">
The manner in which to send packets to the [code]target_peer[/code]. See [enum TransferMode].
</member>
</members>
@@ -109,5 +109,14 @@
<constant name="TARGET_PEER_SERVER" value="1">
Packets are sent to the server alone.
</constant>
+ <constant name="TRANSFER_MODE_UNRELIABLE" value="0" enum="TransferMode">
+ Packets are not acknowledged, no resend attempts are made for lost packets. Packets may arrive in any order. Potentially faster than [constant TRANSFER_MODE_UNRELIABLE_ORDERED]. Use for non-critical data, and always consider whether the order matters.
+ </constant>
+ <constant name="TRANSFER_MODE_UNRELIABLE_ORDERED" value="1" enum="TransferMode">
+ Packets are not acknowledged, no resend attempts are made for lost packets. Packets are received in the order they were sent in. Potentially faster than [constant TRANSFER_MODE_RELIABLE]. Use for non-critical data or data that would be outdated if received late due to resend attempt(s) anyway, for example movement and positional data.
+ </constant>
+ <constant name="TRANSFER_MODE_RELIABLE" value="2" enum="TransferMode">
+ Packets must be received and resend attempts should be made until the packets are acknowledged. Packets must be received in the order they were sent in. Most reliable transfer mode, but potentially the slowest due to the overhead. Use for critical data that must be transmitted and arrive in order, for example an ability being triggered or a chat message. Consider carefully if the information really is critical, and use sparingly.
+ </constant>
</constants>
</class>
diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml
index b7591ed4f4..8cc8498609 100644
--- a/doc/classes/Node.xml
+++ b/doc/classes/Node.xml
@@ -622,7 +622,7 @@
</description>
</method>
<method name="rpc" qualifiers="vararg">
- <return type="void" />
+ <return type="int" enum="Error" />
<argument index="0" name="method" type="StringName" />
<description>
Sends a remote procedure call request for the given [code]method[/code] to peers on the network (and locally), optionally sending all additional arguments as arguments to the method called by the RPC. The call request will only be received by nodes with the same [NodePath], including the exact same node name. Behaviour depends on the RPC configuration for the given method, see [method rpc_config]. Methods are not exposed to RPCs by default. Returns [code]null[/code].
@@ -630,18 +630,24 @@
</description>
</method>
<method name="rpc_config">
- <return type="int" />
+ <return type="void" />
<argument index="0" name="method" type="StringName" />
- <argument index="1" name="rpc_mode" type="int" enum="RPCMode" />
- <argument index="2" name="call_local" type="bool" default="false" />
- <argument index="3" name="transfer_mode" type="int" enum="TransferMode" default="2" />
- <argument index="4" name="channel" type="int" default="0" />
+ <argument index="1" name="config" type="Variant" />
<description>
- Changes the RPC mode for the given [code]method[/code] to the given [code]rpc_mode[/code], optionally specifying the [code]transfer_mode[/code] and [code]channel[/code] (on supported peers). See [enum RPCMode] and [enum TransferMode]. An alternative is annotating methods and properties with the corresponding annotation ([code]@rpc(any)[/code], [code]@rpc(authority)[/code]). By default, methods are not exposed to networking (and RPCs).
+ Changes the RPC mode for the given [code]method[/code] with the given [code]config[/code] which should be [code]null[/code] (to disable) or a [Dictionary] in the form:
+ [codeblock]
+ {
+ rpc_mode = MultiplayerAPI.RPCMode,
+ transfer_mode = MultiplayerPeer.TranferMode,
+ call_local = false,
+ channel = 0,
+ }
+ [/codeblock]
+ See [enum MultiplayerAPI.RPCMode] and [enum MultiplayerPeer.TransferMode]. An alternative is annotating methods and properties with the corresponding annotation ([code]@rpc(any)[/code], [code]@rpc(authority)[/code]). By default, methods are not exposed to networking (and RPCs).
</description>
</method>
<method name="rpc_id" qualifiers="vararg">
- <return type="void" />
+ <return type="int" enum="Error" />
<argument index="0" name="peer_id" type="int" />
<argument index="1" name="method" type="StringName" />
<description>
diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index f7567133cd..a2e92fb61b 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -1632,13 +1632,13 @@
Sets the number of MSAA samples to use (as a power of two). MSAA is used to reduce aliasing around the edges of polygons. A higher MSAA value results in smoother edges but can be significantly slower on some hardware. See also bilinear scaling 3d [member rendering/scaling_3d/mode] for supersampling, which provides higher quality but is much more expensive.
</member>
<member name="rendering/anti_aliasing/quality/screen_space_aa" type="int" setter="" getter="" default="0">
- Sets the screen-space antialiasing mode for the default screen [Viewport]. Screen-space antialiasing works by selectively blurring edges in a post-process shader. It differs from MSAA which takes multiple coverage samples while rendering objects. Screen-space AA methods are typically faster than MSAA and will smooth out specular aliasing, but tend to make scenes appear blurry.
+ Sets the screen-space antialiasing mode for the default screen [Viewport]. Screen-space antialiasing works by selectively blurring edges in a post-process shader. It differs from MSAA which takes multiple coverage samples while rendering objects. Screen-space AA methods are typically faster than MSAA and will smooth out specular aliasing, but tend to make scenes appear blurry. The blurriness can be counteracted to an extent by using a negative mipmap LOD bias ([member rendering/textures/default_filters/texture_mipmap_bias]).
Another way to combat specular aliasing is to enable [member rendering/anti_aliasing/screen_space_roughness_limiter/enabled].
</member>
<member name="rendering/anti_aliasing/quality/use_debanding" type="bool" setter="" getter="" default="false">
</member>
<member name="rendering/anti_aliasing/quality/use_taa" type="bool" setter="" getter="" default="false">
- Enables Temporal Anti-Aliasing for the default screen [Viewport]. TAA works by jittering the camera and accumulating the images of the last rendered frames, motion vector rendering is used to account for camera and object motion.
+ Enables Temporal Anti-Aliasing for the default screen [Viewport]. TAA works by jittering the camera and accumulating the images of the last rendered frames, motion vector rendering is used to account for camera and object motion. Enabling TAA can make the image blurrier, which can be counteracted to an extent by using a negative mipmap LOD bias ([member rendering/textures/default_filters/texture_mipmap_bias]).
[b]Note:[/b] The implementation is not complete yet, some visual instances such as particles and skinned meshes may show artifacts.
</member>
<member name="rendering/anti_aliasing/screen_space_roughness_limiter/amount" type="float" setter="" getter="" default="0.25">
@@ -1856,9 +1856,6 @@
<member name="rendering/reflections/sky_reflections/texture_array_reflections.mobile" type="bool" setter="" getter="" default="false">
Lower-end override for [member rendering/reflections/sky_reflections/texture_array_reflections] on mobile devices, due to performance concerns or driver support.
</member>
- <member name="rendering/scaling_3d/fsr_mipmap_bias" type="float" setter="" getter="" default="0.0">
- Affects the final texture sharpness by reading from a lower or higher mipmap. Negative values make textures sharper, while positive values make textures blurrier. When using FSR, this value is used to adjust the mipmap bias calculated internally which is based on the selected quality. The formula for this is [code]-log2(1.0 / scale) + mipmap_bias[/code]
- </member>
<member name="rendering/scaling_3d/fsr_sharpness" type="float" setter="" getter="" default="0.2">
Determines how sharp the upscaled image will be when using the FSR upscaling mode. Sharpness halves with every whole number. Values go from 0.0 (sharpest) to 2.0. Values above 2.0 won't make a visible difference.
</member>
@@ -1940,6 +1937,11 @@
Sets the maximum number of samples to take when using anisotropic filtering on textures (as a power of two). A higher sample count will result in sharper textures at oblique angles, but is more expensive to compute. A value of [code]0[/code] forcibly disables anisotropic filtering, even on materials where it is enabled.
[b]Note:[/b] This property is only read when the project starts. There is currently no way to change this setting at run-time.
</member>
+ <member name="rendering/textures/default_filters/texture_mipmap_bias" type="float" setter="" getter="" default="0.0">
+ Affects the final texture sharpness by reading from a lower or higher mipmap (also called "texture LOD bias"). Negative values make mipmapped textures sharper but grainier when viewed at a distance, while positive values make mipmapped textures blurrier (even when up close). To get sharper textures at a distance without introducing too much graininess, set this between [code]-0.75[/code] and [code]0.0[/code]. Enabling temporal antialiasing ([member rendering/anti_aliasing/quality/use_taa]) can help reduce the graininess visible when using negative mipmap bias.
+ [b]Note:[/b] When the 3D scaling mode is set to FSR 1.0, this value is used to adjust the automatic mipmap bias which is calculated internally based on the scale factor. The formula for this is [code]-log2(1.0 / scale) + mipmap_bias[/code].
+ [b]Note:[/b] This property is only read when the project starts. To change the mipmap LOD bias at run-time, set [member Viewport.texture_mipmap_bias] instead.
+ </member>
<member name="rendering/textures/default_filters/use_nearest_mipmap_filter" type="bool" setter="" getter="" default="false">
If [code]true[/code], uses nearest-neighbor mipmap filtering when using mipmaps (also called "bilinear filtering"), which will result in visible seams appearing between mipmap stages. This may increase performance in mobile as less memory bandwidth is used. If [code]false[/code], linear mipmap filtering (also called "trilinear filtering") is used.
[b]Note:[/b] This property is only read when the project starts. There is currently no way to change this setting at run-time.
diff --git a/doc/classes/Quaternion.xml b/doc/classes/Quaternion.xml
index 48e6317b11..30e96607da 100644
--- a/doc/classes/Quaternion.xml
+++ b/doc/classes/Quaternion.xml
@@ -74,16 +74,6 @@
[b]Note:[/b] This method has an abnormally high amount of floating-point error, so methods such as [code]is_zero_approx[/code] will not work reliably.
</description>
</method>
- <method name="cubic_slerp" qualifiers="const">
- <return type="Quaternion" />
- <argument index="0" name="b" type="Quaternion" />
- <argument index="1" name="pre_a" type="Quaternion" />
- <argument index="2" name="post_b" type="Quaternion" />
- <argument index="3" name="weight" type="float" />
- <description>
- Performs a cubic spherical interpolation between quaternions [code]pre_a[/code], this vector, [code]b[/code], and [code]post_b[/code], by the given amount [code]weight[/code].
- </description>
- </method>
<method name="dot" qualifiers="const">
<return type="float" />
<argument index="0" name="with" type="Quaternion" />
@@ -171,6 +161,16 @@
Returns the result of the spherical linear interpolation between this quaternion and [code]to[/code] by amount [code]weight[/code], but without checking if the rotation path is not bigger than 90 degrees.
</description>
</method>
+ <method name="spherical_cubic_interpolate" qualifiers="const">
+ <return type="Quaternion" />
+ <argument index="0" name="b" type="Quaternion" />
+ <argument index="1" name="pre_a" type="Quaternion" />
+ <argument index="2" name="post_b" type="Quaternion" />
+ <argument index="3" name="weight" type="float" />
+ <description>
+ Performs a spherical cubic interpolation between quaternions [code]pre_a[/code], this vector, [code]b[/code], and [code]post_b[/code], by the given amount [code]weight[/code].
+ </description>
+ </method>
</methods>
<members>
<member name="w" type="float" setter="" getter="" default="1.0">
diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml
index c2752d9f7b..9616ab3515 100644
--- a/doc/classes/RenderingServer.xml
+++ b/doc/classes/RenderingServer.xml
@@ -1293,45 +1293,45 @@
If [code]half_resolution[/code] is [code]true[/code], renders [VoxelGI] and SDFGI ([member Environment.sdfgi_enabled]) buffers at halved resolution (e.g. 960×540 when the viewport size is 1920×1080). This improves performance significantly when VoxelGI or SDFGI is enabled, at the cost of artifacts that may be visible on polygon edges. The loss in quality becomes less noticeable as the viewport resolution increases. [LightmapGI] rendering is not affected by this setting. See also [member ProjectSettings.rendering/global_illumination/gi/use_half_resolution].
</description>
</method>
- <method name="global_variable_add">
+ <method name="global_shader_uniform_add">
<return type="void" />
<argument index="0" name="name" type="StringName" />
- <argument index="1" name="type" type="int" enum="RenderingServer.GlobalVariableType" />
+ <argument index="1" name="type" type="int" enum="RenderingServer.GlobalShaderUniformType" />
<argument index="2" name="default_value" type="Variant" />
<description>
</description>
</method>
- <method name="global_variable_get" qualifiers="const">
+ <method name="global_shader_uniform_get" qualifiers="const">
<return type="Variant" />
<argument index="0" name="name" type="StringName" />
<description>
</description>
</method>
- <method name="global_variable_get_list" qualifiers="const">
+ <method name="global_shader_uniform_get_list" qualifiers="const">
<return type="PackedStringArray" />
<description>
</description>
</method>
- <method name="global_variable_get_type" qualifiers="const">
- <return type="int" enum="RenderingServer.GlobalVariableType" />
+ <method name="global_shader_uniform_get_type" qualifiers="const">
+ <return type="int" enum="RenderingServer.GlobalShaderUniformType" />
<argument index="0" name="name" type="StringName" />
<description>
</description>
</method>
- <method name="global_variable_remove">
+ <method name="global_shader_uniform_remove">
<return type="void" />
<argument index="0" name="name" type="StringName" />
<description>
</description>
</method>
- <method name="global_variable_set">
+ <method name="global_shader_uniform_set">
<return type="void" />
<argument index="0" name="name" type="StringName" />
<argument index="1" name="value" type="Variant" />
<description>
</description>
</method>
- <method name="global_variable_set_override">
+ <method name="global_shader_uniform_set_override">
<return type="void" />
<argument index="0" name="name" type="StringName" />
<argument index="1" name="value" type="Variant" />
@@ -3175,14 +3175,6 @@
If [code]true[/code], rendering of a viewport's environment is disabled.
</description>
</method>
- <method name="viewport_set_fsr_mipmap_bias">
- <return type="void" />
- <argument index="0" name="viewport" type="RID" />
- <argument index="1" name="mipmap_bias" type="float" />
- <description>
- Affects the final texture sharpness by reading from a lower or higher mipmap. Negative values make textures sharper, while positive values make textures blurrier. When using FSR, this value is used to adjust the mipmap bias calculated internally which is based on the selected quality. The formula for this is [code]-log2(1.0 / scale) + mipmap_bias[/code]
- </description>
- </method>
<method name="viewport_set_fsr_sharpness">
<return type="void" />
<argument index="0" name="viewport" type="RID" />
@@ -3325,6 +3317,15 @@
<description>
</description>
</method>
+ <method name="viewport_set_texture_mipmap_bias">
+ <return type="void" />
+ <argument index="0" name="viewport" type="RID" />
+ <argument index="1" name="mipmap_bias" type="float" />
+ <description>
+ Affects the final texture sharpness by reading from a lower or higher mipmap (also called "texture LOD bias"). Negative values make mipmapped textures sharper but grainier when viewed at a distance, while positive values make mipmapped textures blurrier (even when up close). To get sharper textures at a distance without introducing too much graininess, set this between [code]-0.75[/code] and [code]0.0[/code]. Enabling temporal antialiasing ([member ProjectSettings.rendering/anti_aliasing/quality/use_taa]) can help reduce the graininess visible when using negative mipmap bias.
+ [b]Note:[/b] When the 3D scaling mode is set to FSR 1.0, this value is used to adjust the automatic mipmap bias which is calculated internally based on the scale factor. The formula for this is [code]-log2(1.0 / scale) + mipmap_bias[/code].
+ </description>
+ </method>
<method name="viewport_set_transparent_background">
<return type="void" />
<argument index="0" name="viewport" type="RID" />
@@ -4536,63 +4537,63 @@
<constant name="CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE" value="2" enum="CanvasOccluderPolygonCullMode">
Culling of the canvas occluder is counterclockwise.
</constant>
- <constant name="GLOBAL_VAR_TYPE_BOOL" value="0" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_BOOL" value="0" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_BVEC2" value="1" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_BVEC2" value="1" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_BVEC3" value="2" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_BVEC3" value="2" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_BVEC4" value="3" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_BVEC4" value="3" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_INT" value="4" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_INT" value="4" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_IVEC2" value="5" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_IVEC2" value="5" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_IVEC3" value="6" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_IVEC3" value="6" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_IVEC4" value="7" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_IVEC4" value="7" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_RECT2I" value="8" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_RECT2I" value="8" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_UINT" value="9" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_UINT" value="9" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_UVEC2" value="10" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_UVEC2" value="10" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_UVEC3" value="11" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_UVEC3" value="11" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_UVEC4" value="12" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_UVEC4" value="12" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_FLOAT" value="13" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_FLOAT" value="13" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_VEC2" value="14" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_VEC2" value="14" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_VEC3" value="15" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_VEC3" value="15" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_VEC4" value="16" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_VEC4" value="16" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_COLOR" value="17" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_COLOR" value="17" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_RECT2" value="18" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_RECT2" value="18" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_MAT2" value="19" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_MAT2" value="19" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_MAT3" value="20" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_MAT3" value="20" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_MAT4" value="21" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_MAT4" value="21" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_TRANSFORM_2D" value="22" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_TRANSFORM_2D" value="22" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_TRANSFORM" value="23" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_TRANSFORM" value="23" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_SAMPLER2D" value="24" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_SAMPLER2D" value="24" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_SAMPLER2DARRAY" value="25" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_SAMPLER2DARRAY" value="25" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_SAMPLER3D" value="26" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_SAMPLER3D" value="26" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_SAMPLERCUBE" value="27" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_SAMPLERCUBE" value="27" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_MAX" value="28" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_MAX" value="28" enum="GlobalShaderUniformType">
</constant>
<constant name="RENDERING_INFO_TOTAL_OBJECTS_IN_FRAME" value="0" enum="RenderingInfo">
</constant>
diff --git a/doc/classes/ScriptExtension.xml b/doc/classes/ScriptExtension.xml
index 91fa6206d7..4e432ca9a8 100644
--- a/doc/classes/ScriptExtension.xml
+++ b/doc/classes/ScriptExtension.xml
@@ -65,8 +65,8 @@
<description>
</description>
</method>
- <method name="_get_rpc_methods" qualifiers="virtual const">
- <return type="Dictionary[]" />
+ <method name="_get_rpc_config" qualifiers="virtual const">
+ <return type="Variant" />
<description>
</description>
</method>
diff --git a/doc/classes/Transform2D.xml b/doc/classes/Transform2D.xml
index e1f7ff21d0..924b4cd8e4 100644
--- a/doc/classes/Transform2D.xml
+++ b/doc/classes/Transform2D.xml
@@ -173,7 +173,7 @@
Sets the transform's skew (in radians).
</description>
</method>
- <method name="translated" qualifiers="const">
+ <method name="translated_local" qualifiers="const">
<return type="Transform2D" />
<argument index="0" name="offset" type="Vector2" />
<description>
diff --git a/doc/classes/Transform3D.xml b/doc/classes/Transform3D.xml
index 147eba9f25..de1db718c2 100644
--- a/doc/classes/Transform3D.xml
+++ b/doc/classes/Transform3D.xml
@@ -112,7 +112,7 @@
Returns a copy of the transform with its basis and origin scaled by the given [code]scale[/code] factor, using matrix multiplication.
</description>
</method>
- <method name="sphere_interpolate_with" qualifiers="const">
+ <method name="spherical_interpolate_with" qualifiers="const">
<return type="Transform3D" />
<argument index="0" name="xform" type="Transform3D" />
<argument index="1" name="weight" type="float" />
@@ -120,7 +120,7 @@
Returns a transform spherically interpolated between this transform and another by a given [code]weight[/code] (on the range of 0.0 to 1.0).
</description>
</method>
- <method name="translated" qualifiers="const">
+ <method name="translated_local" qualifiers="const">
<return type="Transform3D" />
<argument index="0" name="offset" type="Vector3" />
<description>
diff --git a/doc/classes/Viewport.xml b/doc/classes/Viewport.xml
index 53603b5356..0808a8f1cf 100644
--- a/doc/classes/Viewport.xml
+++ b/doc/classes/Viewport.xml
@@ -196,10 +196,6 @@
<member name="disable_3d" type="bool" setter="set_disable_3d" getter="is_3d_disabled" default="false">
Disable 3D rendering (but keep 2D rendering).
</member>
- <member name="fsr_mipmap_bias" type="float" setter="set_fsr_mipmap_bias" getter="get_fsr_mipmap_bias" default="0.0">
- Affects the final texture sharpness by reading from a lower or higher mipmap when using FSR. Mipmap bias does nothing when FSR is not being used. Negative values make textures sharper, while positive values make textures blurrier. This value is used to adjust the mipmap bias calculated internally which is based on the selected quality. The formula for this is [code]-log2(1.0 / scale) + mipmap_bias[/code]. This updates the rendering server's mipmap bias when called
- To control this property on the root viewport, set the [member ProjectSettings.rendering/scaling_3d/fsr_mipmap_bias] project setting.
- </member>
<member name="fsr_sharpness" type="float" setter="set_fsr_sharpness" getter="get_fsr_sharpness" default="0.2">
Determines how sharp the upscaled image will be when using the FSR upscaling mode. Sharpness halves with every whole number. Values go from 0.0 (sharpest) to 2.0. Values above 2.0 won't make a visible difference.
To control this property on the root viewport, set the [member ProjectSettings.rendering/scaling_3d/fsr_sharpness] project setting.
@@ -270,6 +266,11 @@
</member>
<member name="snap_2d_vertices_to_pixel" type="bool" setter="set_snap_2d_vertices_to_pixel" getter="is_snap_2d_vertices_to_pixel_enabled" default="false">
</member>
+ <member name="texture_mipmap_bias" type="float" setter="set_texture_mipmap_bias" getter="get_texture_mipmap_bias" default="0.0">
+ Affects the final texture sharpness by reading from a lower or higher mipmap (also called "texture LOD bias"). Negative values make mipmapped textures sharper but grainier when viewed at a distance, while positive values make mipmapped textures blurrier (even when up close). To get sharper textures at a distance without introducing too much graininess, set this between [code]-0.75[/code] and [code]0.0[/code]. Enabling temporal antialiasing ([member ProjectSettings.rendering/anti_aliasing/quality/use_taa]) can help reduce the graininess visible when using negative mipmap bias.
+ [b]Note:[/b] When the 3D scaling mode is set to FSR 1.0, this value is used to adjust the automatic mipmap bias which is calculated internally based on the scale factor. The formula for this is [code]-log2(1.0 / scale) + mipmap_bias[/code].
+ To control this property on the root viewport, set the [member ProjectSettings.rendering/textures/default_filters/texture_mipmap_bias] project setting.
+ </member>
<member name="transparent_bg" type="bool" setter="set_transparent_background" getter="has_transparent_background" default="false">
If [code]true[/code], the viewport should render its background as transparent.
</member>
diff --git a/doc/tools/make_rst.py b/doc/tools/make_rst.py
index 2aa4cb8ec1..469bb4a310 100755
--- a/doc/tools/make_rst.py
+++ b/doc/tools/make_rst.py
@@ -1401,7 +1401,7 @@ def make_method_signature(
if ref_type != "":
if ref_type == "operator":
out += ":ref:`{0}<class_{1}_{2}_{3}_{4}>` ".format(
- method_def.name,
+ method_def.name.replace("<", "\\<"), # So operator "<" gets correctly displayed.
class_def.name,
ref_type,
sanitize_operator_name(method_def.name, state),
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp
index a5dec393bb..abbc11847f 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.cpp
+++ b/drivers/gles3/rasterizer_canvas_gles3.cpp
@@ -135,7 +135,7 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
Size2i ssize = texture_storage->render_target_get_size(p_to_render_target);
Transform3D screen_transform;
- screen_transform.translate(-(ssize.width / 2.0f), -(ssize.height / 2.0f), 0.0f);
+ screen_transform.translate_local(-(ssize.width / 2.0f), -(ssize.height / 2.0f), 0.0f);
screen_transform.scale(Vector3(2.0f / ssize.width, 2.0f / ssize.height, 1.0f));
_update_transform_to_mat4(screen_transform, state_buffer.screen_transform);
_update_transform_2d_to_mat4(p_canvas_transform, state_buffer.canvas_transform);
@@ -183,7 +183,7 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
glBindBufferBase(GL_UNIFORM_BUFFER, BASE_UNIFORM_LOCATION, state.canvas_state_buffer);
glBufferData(GL_UNIFORM_BUFFER, sizeof(StateBuffer), &state_buffer, GL_STREAM_DRAW);
- GLuint global_buffer = material_storage->global_variables_get_uniform_buffer();
+ GLuint global_buffer = material_storage->global_shader_uniforms_get_uniform_buffer();
glBindBufferBase(GL_UNIFORM_BUFFER, GLOBAL_UNIFORM_LOCATION, global_buffer);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
@@ -1570,7 +1570,7 @@ RasterizerCanvasGLES3::RasterizerCanvasGLES3() {
glBindBuffer(GL_UNIFORM_BUFFER, 0);
String global_defines;
- global_defines += "#define MAX_GLOBAL_VARIABLES 256\n"; // TODO: this is arbitrary for now
+ global_defines += "#define MAX_GLOBAL_SHADER_UNIFORMS 256\n"; // TODO: this is arbitrary for now
global_defines += "#define MAX_LIGHTS " + itos(state.max_instances_per_batch) + "\n";
global_defines += "#define MAX_DRAW_DATA_INSTANCES " + itos(state.max_instances_per_batch) + "\n";
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index 043ccc0e94..26d84aa6a3 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -1733,7 +1733,7 @@ void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData *
// Fill Light lists here
//////////
- GLuint global_buffer = GLES3::MaterialStorage::get_singleton()->global_variables_get_uniform_buffer();
+ GLuint global_buffer = GLES3::MaterialStorage::get_singleton()->global_shader_uniforms_get_uniform_buffer();
glBindBufferBase(GL_UNIFORM_BUFFER, SCENE_GLOBALS_UNIFORM_LOCATION, global_buffer);
Color clear_color;
@@ -2270,7 +2270,7 @@ RID RasterizerSceneGLES3::render_buffers_create() {
return render_buffers_owner.make_rid(rb);
}
-void RasterizerSceneGLES3::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) {
+void RasterizerSceneGLES3::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) {
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
@@ -2465,7 +2465,7 @@ RasterizerSceneGLES3::RasterizerSceneGLES3() {
{
String global_defines;
- global_defines += "#define MAX_GLOBAL_VARIABLES 256\n"; // TODO: this is arbitrary for now
+ global_defines += "#define MAX_GLOBAL_SHADER_UNIFORMS 256\n"; // TODO: this is arbitrary for now
global_defines += "\n#define MAX_LIGHT_DATA_STRUCTS " + itos(config->max_renderable_lights) + "\n";
global_defines += "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(MAX_DIRECTIONAL_LIGHTS) + "\n";
global_defines += "\n#define MAX_FORWARD_LIGHTS " + itos(config->max_lights_per_object) + "\n";
@@ -2504,7 +2504,7 @@ void fragment() {
sky_globals.ggx_samples = GLOBAL_GET("rendering/reflections/sky_reflections/ggx_samples");
String global_defines;
- global_defines += "#define MAX_GLOBAL_VARIABLES 256\n"; // TODO: this is arbitrary for now
+ global_defines += "#define MAX_GLOBAL_SHADER_UNIFORMS 256\n"; // TODO: this is arbitrary for now
global_defines += "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(sky_globals.max_directional_lights) + "\n";
material_storage->shaders.sky_shader.initialize(global_defines);
sky_globals.shader_default_version = material_storage->shaders.sky_shader.version_create();
diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h
index 804eff8f26..e227b2df82 100644
--- a/drivers/gles3/rasterizer_scene_gles3.h
+++ b/drivers/gles3/rasterizer_scene_gles3.h
@@ -762,7 +762,7 @@ public:
}
RID render_buffers_create() override;
- void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override;
+ void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override;
void gi_set_use_half_resolution(bool p_enable) override;
void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_curve) override;
diff --git a/drivers/gles3/shaders/canvas_uniforms_inc.glsl b/drivers/gles3/shaders/canvas_uniforms_inc.glsl
index e08a15e59d..852dccf415 100644
--- a/drivers/gles3/shaders/canvas_uniforms_inc.glsl
+++ b/drivers/gles3/shaders/canvas_uniforms_inc.glsl
@@ -58,8 +58,8 @@ struct DrawData {
uvec4 lights;
};
-layout(std140) uniform GlobalVariableData { //ubo:1
- vec4 global_variables[MAX_GLOBAL_VARIABLES];
+layout(std140) uniform GlobalShaderUniformData { //ubo:1
+ vec4 global_shader_uniforms[MAX_GLOBAL_SHADER_UNIFORMS];
};
layout(std140) uniform CanvasData { //ubo:0
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
index 4f2be8bf60..cd88ba6cb7 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -104,8 +104,8 @@ layout(location = 14) in highp vec4 instance_xform2;
layout(location = 15) in highp uvec4 instance_color_custom_data; // Color packed into xy, Custom data into zw.
#endif
-layout(std140) uniform GlobalVariableData { //ubo:1
- vec4 global_variables[MAX_GLOBAL_VARIABLES];
+layout(std140) uniform GlobalShaderUniformData { //ubo:1
+ vec4 global_shader_uniforms[MAX_GLOBAL_SHADER_UNIFORMS];
};
layout(std140) uniform SceneData { // ubo:2
@@ -399,8 +399,8 @@ uniform samplerCube radiance_map; // texunit:-2
#endif
-layout(std140) uniform GlobalVariableData { //ubo:1
- vec4 global_variables[MAX_GLOBAL_VARIABLES];
+layout(std140) uniform GlobalShaderUniformData { //ubo:1
+ vec4 global_shader_uniforms[MAX_GLOBAL_SHADER_UNIFORMS];
};
/* Material Uniforms */
diff --git a/drivers/gles3/shaders/sky.glsl b/drivers/gles3/shaders/sky.glsl
index 50ab38bc31..eb1befe38e 100644
--- a/drivers/gles3/shaders/sky.glsl
+++ b/drivers/gles3/shaders/sky.glsl
@@ -42,8 +42,8 @@ uniform sampler2D half_res; //texunit:-2
uniform sampler2D quarter_res; //texunit:-3
#endif
-layout(std140) uniform GlobalVariableData { //ubo:1
- vec4 global_variables[MAX_GLOBAL_VARIABLES];
+layout(std140) uniform GlobalShaderUniformData { //ubo:1
+ vec4 global_shader_uniforms[MAX_GLOBAL_SHADER_UNIFORMS];
};
struct DirectionalLightData {
diff --git a/drivers/gles3/storage/material_storage.cpp b/drivers/gles3/storage/material_storage.cpp
index 4cd8dd0b14..117481faf5 100644
--- a/drivers/gles3/storage/material_storage.cpp
+++ b/drivers/gles3/storage/material_storage.cpp
@@ -997,7 +997,7 @@ void MaterialData::update_uniform_buffer(const HashMap<StringName, ShaderLanguag
if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) {
//this is a global variable, get the index to it
- GlobalVariables::Variable *gv = material_storage->global_variables.variables.getptr(E.key);
+ GlobalShaderUniforms::Variable *gv = material_storage->global_shader_uniforms.variables.getptr(E.key);
uint32_t index = 0;
if (gv) {
index = gv->buffer_index;
@@ -1053,9 +1053,9 @@ void MaterialData::update_uniform_buffer(const HashMap<StringName, ShaderLanguag
if (uses_global_buffer != (global_buffer_E != nullptr)) {
if (uses_global_buffer) {
- global_buffer_E = material_storage->global_variables.materials_using_buffer.push_back(self);
+ global_buffer_E = material_storage->global_shader_uniforms.materials_using_buffer.push_back(self);
} else {
- material_storage->global_variables.materials_using_buffer.erase(global_buffer_E);
+ material_storage->global_shader_uniforms.materials_using_buffer.erase(global_buffer_E);
global_buffer_E = nullptr;
}
}
@@ -1066,20 +1066,20 @@ MaterialData::~MaterialData() {
if (global_buffer_E) {
//unregister global buffers
- material_storage->global_variables.materials_using_buffer.erase(global_buffer_E);
+ material_storage->global_shader_uniforms.materials_using_buffer.erase(global_buffer_E);
}
if (global_texture_E) {
//unregister global textures
for (const KeyValue<StringName, uint64_t> &E : used_global_textures) {
- GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(E.key);
+ GlobalShaderUniforms::Variable *v = material_storage->global_shader_uniforms.variables.getptr(E.key);
if (v) {
v->texture_materials.erase(self);
}
}
//unregister material from those using global textures
- material_storage->global_variables.materials_using_texture.erase(global_texture_E);
+ material_storage->global_shader_uniforms.materials_using_texture.erase(global_texture_E);
}
if (uniform_buffer) {
@@ -1110,7 +1110,7 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet
if (p_texture_uniforms[i].global) {
uses_global_textures = true;
- GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(uniform_name);
+ GlobalShaderUniforms::Variable *v = material_storage->global_shader_uniforms.variables.getptr(uniform_name);
if (v) {
if (v->buffer_index >= 0) {
WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it changed type and is no longer a texture!.");
@@ -1282,7 +1282,7 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet
if (E.value != global_textures_pass) {
to_delete.push_back(E.key);
- GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(E.key);
+ GlobalShaderUniforms::Variable *v = material_storage->global_shader_uniforms.variables.getptr(E.key);
if (v) {
v->texture_materials.erase(self);
}
@@ -1296,9 +1296,9 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet
//handle registering/unregistering global textures
if (uses_global_textures != (global_texture_E != nullptr)) {
if (uses_global_textures) {
- global_texture_E = material_storage->global_variables.materials_using_texture.push_back(self);
+ global_texture_E = material_storage->global_shader_uniforms.materials_using_texture.push_back(self);
} else {
- material_storage->global_variables.materials_using_texture.erase(global_texture_E);
+ material_storage->global_shader_uniforms.materials_using_texture.erase(global_texture_E);
global_texture_E = nullptr;
}
}
@@ -1365,22 +1365,22 @@ MaterialStorage::MaterialStorage() {
material_data_request_func[RS::SHADER_SKY] = _create_sky_material_func;
material_data_request_func[RS::SHADER_FOG] = nullptr;
- static_assert(sizeof(GlobalVariables::Value) == 16);
+ static_assert(sizeof(GlobalShaderUniforms::Value) == 16);
- global_variables.buffer_size = MAX(4096, (int)GLOBAL_GET("rendering/limits/global_shader_variables/buffer_size"));
- if (global_variables.buffer_size > uint32_t(Config::get_singleton()->max_uniform_buffer_size)) {
- global_variables.buffer_size = uint32_t(Config::get_singleton()->max_uniform_buffer_size);
+ global_shader_uniforms.buffer_size = MAX(4096, (int)GLOBAL_GET("rendering/limits/global_shader_variables/buffer_size"));
+ if (global_shader_uniforms.buffer_size > uint32_t(Config::get_singleton()->max_uniform_buffer_size)) {
+ global_shader_uniforms.buffer_size = uint32_t(Config::get_singleton()->max_uniform_buffer_size);
WARN_PRINT("Project setting: rendering/limits/global_shader_variables/buffer_size exceeds maximum uniform buffer size of: " + itos(Config::get_singleton()->max_uniform_buffer_size));
}
- global_variables.buffer_values = memnew_arr(GlobalVariables::Value, global_variables.buffer_size);
- memset(global_variables.buffer_values, 0, sizeof(GlobalVariables::Value) * global_variables.buffer_size);
- global_variables.buffer_usage = memnew_arr(GlobalVariables::ValueUsage, global_variables.buffer_size);
- global_variables.buffer_dirty_regions = memnew_arr(bool, global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE);
- memset(global_variables.buffer_dirty_regions, 0, sizeof(bool) * global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE);
- glGenBuffers(1, &global_variables.buffer);
- glBindBuffer(GL_UNIFORM_BUFFER, global_variables.buffer);
- glBufferData(GL_UNIFORM_BUFFER, sizeof(GlobalVariables::Value) * global_variables.buffer_size, nullptr, GL_DYNAMIC_DRAW);
+ global_shader_uniforms.buffer_values = memnew_arr(GlobalShaderUniforms::Value, global_shader_uniforms.buffer_size);
+ memset(global_shader_uniforms.buffer_values, 0, sizeof(GlobalShaderUniforms::Value) * global_shader_uniforms.buffer_size);
+ global_shader_uniforms.buffer_usage = memnew_arr(GlobalShaderUniforms::ValueUsage, global_shader_uniforms.buffer_size);
+ global_shader_uniforms.buffer_dirty_regions = memnew_arr(bool, global_shader_uniforms.buffer_size / GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE);
+ memset(global_shader_uniforms.buffer_dirty_regions, 0, sizeof(bool) * global_shader_uniforms.buffer_size / GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE);
+ glGenBuffers(1, &global_shader_uniforms.buffer);
+ glBindBuffer(GL_UNIFORM_BUFFER, global_shader_uniforms.buffer);
+ glBufferData(GL_UNIFORM_BUFFER, sizeof(GlobalShaderUniforms::Value) * global_shader_uniforms.buffer_size, nullptr, GL_DYNAMIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
{
@@ -1674,7 +1674,7 @@ ShaderCompiler::DefaultIdentifierActions actions;
actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
actions.default_repeat = ShaderLanguage::REPEAT_ENABLE;
- actions.global_buffer_array_variable = "global_variables.data";
+ actions.global_buffer_array_variable = "global_shader_uniforms.data";
particles_shader.compiler.initialize(actions);
*/
@@ -1736,25 +1736,25 @@ ShaderCompiler::DefaultIdentifierActions actions;
MaterialStorage::~MaterialStorage() {
//shaders.copy.version_free(shaders.copy_version);
- memdelete_arr(global_variables.buffer_values);
- memdelete_arr(global_variables.buffer_usage);
- memdelete_arr(global_variables.buffer_dirty_regions);
- glDeleteBuffers(1, &global_variables.buffer);
+ memdelete_arr(global_shader_uniforms.buffer_values);
+ memdelete_arr(global_shader_uniforms.buffer_usage);
+ memdelete_arr(global_shader_uniforms.buffer_dirty_regions);
+ glDeleteBuffers(1, &global_shader_uniforms.buffer);
singleton = nullptr;
}
-/* GLOBAL VARIABLE API */
+/* GLOBAL SHADER UNIFORM API */
-int32_t MaterialStorage::_global_variable_allocate(uint32_t p_elements) {
+int32_t MaterialStorage::_global_shader_uniform_allocate(uint32_t p_elements) {
int32_t idx = 0;
- while (idx + p_elements <= global_variables.buffer_size) {
- if (global_variables.buffer_usage[idx].elements == 0) {
+ while (idx + p_elements <= global_shader_uniforms.buffer_size) {
+ if (global_shader_uniforms.buffer_usage[idx].elements == 0) {
bool valid = true;
for (uint32_t i = 1; i < p_elements; i++) {
- if (global_variables.buffer_usage[idx + i].elements > 0) {
+ if (global_shader_uniforms.buffer_usage[idx + i].elements > 0) {
valid = false;
- idx += i + global_variables.buffer_usage[idx + i].elements;
+ idx += i + global_shader_uniforms.buffer_usage[idx + i].elements;
break;
}
}
@@ -1765,17 +1765,17 @@ int32_t MaterialStorage::_global_variable_allocate(uint32_t p_elements) {
return idx;
} else {
- idx += global_variables.buffer_usage[idx].elements;
+ idx += global_shader_uniforms.buffer_usage[idx].elements;
}
}
return -1;
}
-void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::GlobalVariableType p_type, const Variant &p_value) {
+void MaterialStorage::_global_shader_uniform_store_in_buffer(int32_t p_index, RS::GlobalShaderUniformType p_type, const Variant &p_value) {
switch (p_type) {
case RS::GLOBAL_VAR_TYPE_BOOL: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
bool b = p_value;
bv.x = b ? 1.0 : 0.0;
bv.y = 0.0;
@@ -1784,7 +1784,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
} break;
case RS::GLOBAL_VAR_TYPE_BVEC2: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
uint32_t bvec = p_value;
bv.x = (bvec & 1) ? 1.0 : 0.0;
bv.y = (bvec & 2) ? 1.0 : 0.0;
@@ -1792,7 +1792,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0.0;
} break;
case RS::GLOBAL_VAR_TYPE_BVEC3: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
uint32_t bvec = p_value;
bv.x = (bvec & 1) ? 1.0 : 0.0;
bv.y = (bvec & 2) ? 1.0 : 0.0;
@@ -1800,7 +1800,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0.0;
} break;
case RS::GLOBAL_VAR_TYPE_BVEC4: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
uint32_t bvec = p_value;
bv.x = (bvec & 1) ? 1.0 : 0.0;
bv.y = (bvec & 2) ? 1.0 : 0.0;
@@ -1808,7 +1808,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = (bvec & 8) ? 1.0 : 0.0;
} break;
case RS::GLOBAL_VAR_TYPE_INT: {
- GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index];
int32_t v = p_value;
bv.x = v;
bv.y = 0;
@@ -1816,7 +1816,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0;
} break;
case RS::GLOBAL_VAR_TYPE_IVEC2: {
- GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index];
Vector2i v = p_value;
bv.x = v.x;
bv.y = v.y;
@@ -1824,7 +1824,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0;
} break;
case RS::GLOBAL_VAR_TYPE_IVEC3: {
- GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index];
Vector3i v = p_value;
bv.x = v.x;
bv.y = v.y;
@@ -1832,7 +1832,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0;
} break;
case RS::GLOBAL_VAR_TYPE_IVEC4: {
- GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index];
Vector<int32_t> v = p_value;
bv.x = v.size() >= 1 ? v[0] : 0;
bv.y = v.size() >= 2 ? v[1] : 0;
@@ -1840,7 +1840,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = v.size() >= 4 ? v[3] : 0;
} break;
case RS::GLOBAL_VAR_TYPE_RECT2I: {
- GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index];
Rect2i v = p_value;
bv.x = v.position.x;
bv.y = v.position.y;
@@ -1848,7 +1848,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = v.size.y;
} break;
case RS::GLOBAL_VAR_TYPE_UINT: {
- GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::ValueUInt &bv = *(GlobalShaderUniforms::ValueUInt *)&global_shader_uniforms.buffer_values[p_index];
uint32_t v = p_value;
bv.x = v;
bv.y = 0;
@@ -1856,7 +1856,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0;
} break;
case RS::GLOBAL_VAR_TYPE_UVEC2: {
- GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::ValueUInt &bv = *(GlobalShaderUniforms::ValueUInt *)&global_shader_uniforms.buffer_values[p_index];
Vector2i v = p_value;
bv.x = v.x;
bv.y = v.y;
@@ -1864,7 +1864,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0;
} break;
case RS::GLOBAL_VAR_TYPE_UVEC3: {
- GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::ValueUInt &bv = *(GlobalShaderUniforms::ValueUInt *)&global_shader_uniforms.buffer_values[p_index];
Vector3i v = p_value;
bv.x = v.x;
bv.y = v.y;
@@ -1872,7 +1872,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0;
} break;
case RS::GLOBAL_VAR_TYPE_UVEC4: {
- GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::ValueUInt &bv = *(GlobalShaderUniforms::ValueUInt *)&global_shader_uniforms.buffer_values[p_index];
Vector<int32_t> v = p_value;
bv.x = v.size() >= 1 ? v[0] : 0;
bv.y = v.size() >= 2 ? v[1] : 0;
@@ -1880,7 +1880,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = v.size() >= 4 ? v[3] : 0;
} break;
case RS::GLOBAL_VAR_TYPE_FLOAT: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
float v = p_value;
bv.x = v;
bv.y = 0;
@@ -1888,7 +1888,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0;
} break;
case RS::GLOBAL_VAR_TYPE_VEC2: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
Vector2 v = p_value;
bv.x = v.x;
bv.y = v.y;
@@ -1896,7 +1896,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0;
} break;
case RS::GLOBAL_VAR_TYPE_VEC3: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
Vector3 v = p_value;
bv.x = v.x;
bv.y = v.y;
@@ -1904,7 +1904,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0;
} break;
case RS::GLOBAL_VAR_TYPE_VEC4: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
Plane v = p_value;
bv.x = v.normal.x;
bv.y = v.normal.y;
@@ -1912,14 +1912,14 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = v.d;
} break;
case RS::GLOBAL_VAR_TYPE_COLOR: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
Color v = p_value;
bv.x = v.r;
bv.y = v.g;
bv.z = v.b;
bv.w = v.a;
- GlobalVariables::Value &bv_linear = global_variables.buffer_values[p_index + 1];
+ GlobalShaderUniforms::Value &bv_linear = global_shader_uniforms.buffer_values[p_index + 1];
//v = v.srgb_to_linear();
bv_linear.x = v.r;
bv_linear.y = v.g;
@@ -1928,7 +1928,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
} break;
case RS::GLOBAL_VAR_TYPE_RECT2: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
Rect2 v = p_value;
bv.x = v.position.x;
bv.y = v.position.y;
@@ -1936,7 +1936,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = v.size.y;
} break;
case RS::GLOBAL_VAR_TYPE_MAT2: {
- GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index];
Vector<float> m2 = p_value;
if (m2.size() < 4) {
m2.resize(4);
@@ -1953,7 +1953,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
} break;
case RS::GLOBAL_VAR_TYPE_MAT3: {
- GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index];
Basis v = p_value;
bv[0].x = v.rows[0][0];
bv[0].y = v.rows[1][0];
@@ -1972,7 +1972,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
} break;
case RS::GLOBAL_VAR_TYPE_MAT4: {
- GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index];
Vector<float> m2 = p_value;
if (m2.size() < 16) {
@@ -2001,7 +2001,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
} break;
case RS::GLOBAL_VAR_TYPE_TRANSFORM_2D: {
- GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index];
Transform2D v = p_value;
bv[0].x = v.columns[0][0];
bv[0].y = v.columns[0][1];
@@ -2020,7 +2020,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
} break;
case RS::GLOBAL_VAR_TYPE_TRANSFORM: {
- GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index];
Transform3D v = p_value;
bv[0].x = v.basis.rows[0][0];
bv[0].y = v.basis.rows[1][0];
@@ -2049,15 +2049,15 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
}
}
-void MaterialStorage::_global_variable_mark_buffer_dirty(int32_t p_index, int32_t p_elements) {
+void MaterialStorage::_global_shader_uniform_mark_buffer_dirty(int32_t p_index, int32_t p_elements) {
int32_t prev_chunk = -1;
for (int32_t i = 0; i < p_elements; i++) {
- int32_t chunk = (p_index + i) / GlobalVariables::BUFFER_DIRTY_REGION_SIZE;
+ int32_t chunk = (p_index + i) / GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE;
if (chunk != prev_chunk) {
- if (!global_variables.buffer_dirty_regions[chunk]) {
- global_variables.buffer_dirty_regions[chunk] = true;
- global_variables.buffer_dirty_region_count++;
+ if (!global_shader_uniforms.buffer_dirty_regions[chunk]) {
+ global_shader_uniforms.buffer_dirty_regions[chunk] = true;
+ global_shader_uniforms.buffer_dirty_region_count++;
}
}
@@ -2065,16 +2065,16 @@ void MaterialStorage::_global_variable_mark_buffer_dirty(int32_t p_index, int32_
}
}
-void MaterialStorage::global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) {
- ERR_FAIL_COND(global_variables.variables.has(p_name));
- GlobalVariables::Variable gv;
+void MaterialStorage::global_shader_uniform_add(const StringName &p_name, RS::GlobalShaderUniformType p_type, const Variant &p_value) {
+ ERR_FAIL_COND(global_shader_uniforms.variables.has(p_name));
+ GlobalShaderUniforms::Variable gv;
gv.type = p_type;
gv.value = p_value;
gv.buffer_index = -1;
if (p_type >= RS::GLOBAL_VAR_TYPE_SAMPLER2D) {
//is texture
- global_variables.must_update_texture_materials = true; //normally there are none
+ global_shader_uniforms.must_update_texture_materials = true; //normally there are none
} else {
gv.buffer_elements = 1;
if (p_type == RS::GLOBAL_VAR_TYPE_COLOR || p_type == RS::GLOBAL_VAR_TYPE_MAT2) {
@@ -2091,56 +2091,56 @@ void MaterialStorage::global_variable_add(const StringName &p_name, RS::GlobalVa
}
//is vector, allocate in buffer and update index
- gv.buffer_index = _global_variable_allocate(gv.buffer_elements);
+ gv.buffer_index = _global_shader_uniform_allocate(gv.buffer_elements);
ERR_FAIL_COND_MSG(gv.buffer_index < 0, vformat("Failed allocating global variable '%s' out of buffer memory. Consider increasing it in the Project Settings.", String(p_name)));
- global_variables.buffer_usage[gv.buffer_index].elements = gv.buffer_elements;
- _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value);
- _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
+ global_shader_uniforms.buffer_usage[gv.buffer_index].elements = gv.buffer_elements;
+ _global_shader_uniform_store_in_buffer(gv.buffer_index, gv.type, gv.value);
+ _global_shader_uniform_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
- global_variables.must_update_buffer_materials = true; //normally there are none
+ global_shader_uniforms.must_update_buffer_materials = true; //normally there are none
}
- global_variables.variables[p_name] = gv;
+ global_shader_uniforms.variables[p_name] = gv;
}
-void MaterialStorage::global_variable_remove(const StringName &p_name) {
- if (!global_variables.variables.has(p_name)) {
+void MaterialStorage::global_shader_uniform_remove(const StringName &p_name) {
+ if (!global_shader_uniforms.variables.has(p_name)) {
return;
}
- GlobalVariables::Variable &gv = global_variables.variables[p_name];
+ GlobalShaderUniforms::Variable &gv = global_shader_uniforms.variables[p_name];
if (gv.buffer_index >= 0) {
- global_variables.buffer_usage[gv.buffer_index].elements = 0;
- global_variables.must_update_buffer_materials = true;
+ global_shader_uniforms.buffer_usage[gv.buffer_index].elements = 0;
+ global_shader_uniforms.must_update_buffer_materials = true;
} else {
- global_variables.must_update_texture_materials = true;
+ global_shader_uniforms.must_update_texture_materials = true;
}
- global_variables.variables.erase(p_name);
+ global_shader_uniforms.variables.erase(p_name);
}
-Vector<StringName> MaterialStorage::global_variable_get_list() const {
+Vector<StringName> MaterialStorage::global_shader_uniform_get_list() const {
if (!Engine::get_singleton()->is_editor_hint()) {
ERR_FAIL_V_MSG(Vector<StringName>(), "This function should never be used outside the editor, it can severely damage performance.");
}
Vector<StringName> names;
- for (const KeyValue<StringName, GlobalVariables::Variable> &E : global_variables.variables) {
+ for (const KeyValue<StringName, GlobalShaderUniforms::Variable> &E : global_shader_uniforms.variables) {
names.push_back(E.key);
}
names.sort_custom<StringName::AlphCompare>();
return names;
}
-void MaterialStorage::global_variable_set(const StringName &p_name, const Variant &p_value) {
- ERR_FAIL_COND(!global_variables.variables.has(p_name));
- GlobalVariables::Variable &gv = global_variables.variables[p_name];
+void MaterialStorage::global_shader_uniform_set(const StringName &p_name, const Variant &p_value) {
+ ERR_FAIL_COND(!global_shader_uniforms.variables.has(p_name));
+ GlobalShaderUniforms::Variable &gv = global_shader_uniforms.variables[p_name];
gv.value = p_value;
if (gv.override.get_type() == Variant::NIL) {
if (gv.buffer_index >= 0) {
//buffer
- _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value);
- _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
+ _global_shader_uniform_store_in_buffer(gv.buffer_index, gv.type, gv.value);
+ _global_shader_uniform_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
} else {
//texture
MaterialStorage *material_storage = MaterialStorage::get_singleton();
@@ -2153,26 +2153,26 @@ void MaterialStorage::global_variable_set(const StringName &p_name, const Varian
}
}
-void MaterialStorage::global_variable_set_override(const StringName &p_name, const Variant &p_value) {
- if (!global_variables.variables.has(p_name)) {
+void MaterialStorage::global_shader_uniform_set_override(const StringName &p_name, const Variant &p_value) {
+ if (!global_shader_uniforms.variables.has(p_name)) {
return; //variable may not exist
}
ERR_FAIL_COND(p_value.get_type() == Variant::OBJECT);
- GlobalVariables::Variable &gv = global_variables.variables[p_name];
+ GlobalShaderUniforms::Variable &gv = global_shader_uniforms.variables[p_name];
gv.override = p_value;
if (gv.buffer_index >= 0) {
//buffer
if (gv.override.get_type() == Variant::NIL) {
- _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value);
+ _global_shader_uniform_store_in_buffer(gv.buffer_index, gv.type, gv.value);
} else {
- _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.override);
+ _global_shader_uniform_store_in_buffer(gv.buffer_index, gv.type, gv.override);
}
- _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
+ _global_shader_uniform_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
} else {
//texture
MaterialStorage *material_storage = MaterialStorage::get_singleton();
@@ -2184,35 +2184,35 @@ void MaterialStorage::global_variable_set_override(const StringName &p_name, con
}
}
-Variant MaterialStorage::global_variable_get(const StringName &p_name) const {
+Variant MaterialStorage::global_shader_uniform_get(const StringName &p_name) const {
if (!Engine::get_singleton()->is_editor_hint()) {
ERR_FAIL_V_MSG(Variant(), "This function should never be used outside the editor, it can severely damage performance.");
}
- if (!global_variables.variables.has(p_name)) {
+ if (!global_shader_uniforms.variables.has(p_name)) {
return Variant();
}
- return global_variables.variables[p_name].value;
+ return global_shader_uniforms.variables[p_name].value;
}
-RS::GlobalVariableType MaterialStorage::global_variable_get_type_internal(const StringName &p_name) const {
- if (!global_variables.variables.has(p_name)) {
+RS::GlobalShaderUniformType MaterialStorage::global_shader_uniform_get_type_internal(const StringName &p_name) const {
+ if (!global_shader_uniforms.variables.has(p_name)) {
return RS::GLOBAL_VAR_TYPE_MAX;
}
- return global_variables.variables[p_name].type;
+ return global_shader_uniforms.variables[p_name].type;
}
-RS::GlobalVariableType MaterialStorage::global_variable_get_type(const StringName &p_name) const {
+RS::GlobalShaderUniformType MaterialStorage::global_shader_uniform_get_type(const StringName &p_name) const {
if (!Engine::get_singleton()->is_editor_hint()) {
ERR_FAIL_V_MSG(RS::GLOBAL_VAR_TYPE_MAX, "This function should never be used outside the editor, it can severely damage performance.");
}
- return global_variable_get_type_internal(p_name);
+ return global_shader_uniform_get_type_internal(p_name);
}
-void MaterialStorage::global_variables_load_settings(bool p_load_textures) {
+void MaterialStorage::global_shader_uniforms_load_settings(bool p_load_textures) {
List<PropertyInfo> settings;
ProjectSettings::get_singleton()->get_property_list(&settings);
@@ -2257,11 +2257,11 @@ void MaterialStorage::global_variables_load_settings(bool p_load_textures) {
"samplerCube",
};
- RS::GlobalVariableType gvtype = RS::GLOBAL_VAR_TYPE_MAX;
+ RS::GlobalShaderUniformType gvtype = RS::GLOBAL_VAR_TYPE_MAX;
for (int i = 0; i < RS::GLOBAL_VAR_TYPE_MAX; i++) {
if (global_var_type_names[i] == type) {
- gvtype = RS::GlobalVariableType(i);
+ gvtype = RS::GlobalShaderUniformType(i);
break;
}
}
@@ -2283,47 +2283,47 @@ void MaterialStorage::global_variables_load_settings(bool p_load_textures) {
value = resource;
}
- if (global_variables.variables.has(name)) {
+ if (global_shader_uniforms.variables.has(name)) {
//has it, update it
- global_variable_set(name, value);
+ global_shader_uniform_set(name, value);
} else {
- global_variable_add(name, gvtype, value);
+ global_shader_uniform_add(name, gvtype, value);
}
}
}
}
-void MaterialStorage::global_variables_clear() {
- global_variables.variables.clear();
+void MaterialStorage::global_shader_uniforms_clear() {
+ global_shader_uniforms.variables.clear();
}
-GLuint MaterialStorage::global_variables_get_uniform_buffer() const {
- return global_variables.buffer;
+GLuint MaterialStorage::global_shader_uniforms_get_uniform_buffer() const {
+ return global_shader_uniforms.buffer;
}
-int32_t MaterialStorage::global_variables_instance_allocate(RID p_instance) {
- ERR_FAIL_COND_V(global_variables.instance_buffer_pos.has(p_instance), -1);
- int32_t pos = _global_variable_allocate(ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES);
- global_variables.instance_buffer_pos[p_instance] = pos; //save anyway
+int32_t MaterialStorage::global_shader_uniforms_instance_allocate(RID p_instance) {
+ ERR_FAIL_COND_V(global_shader_uniforms.instance_buffer_pos.has(p_instance), -1);
+ int32_t pos = _global_shader_uniform_allocate(ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES);
+ global_shader_uniforms.instance_buffer_pos[p_instance] = pos; //save anyway
ERR_FAIL_COND_V_MSG(pos < 0, -1, "Too many instances using shader instance variables. Increase buffer size in Project Settings.");
- global_variables.buffer_usage[pos].elements = ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES;
+ global_shader_uniforms.buffer_usage[pos].elements = ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES;
return pos;
}
-void MaterialStorage::global_variables_instance_free(RID p_instance) {
- ERR_FAIL_COND(!global_variables.instance_buffer_pos.has(p_instance));
- int32_t pos = global_variables.instance_buffer_pos[p_instance];
+void MaterialStorage::global_shader_uniforms_instance_free(RID p_instance) {
+ ERR_FAIL_COND(!global_shader_uniforms.instance_buffer_pos.has(p_instance));
+ int32_t pos = global_shader_uniforms.instance_buffer_pos[p_instance];
if (pos >= 0) {
- global_variables.buffer_usage[pos].elements = 0;
+ global_shader_uniforms.buffer_usage[pos].elements = 0;
}
- global_variables.instance_buffer_pos.erase(p_instance);
+ global_shader_uniforms.instance_buffer_pos.erase(p_instance);
}
-void MaterialStorage::global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) {
- if (!global_variables.instance_buffer_pos.has(p_instance)) {
+void MaterialStorage::global_shader_uniforms_instance_update(RID p_instance, int p_index, const Variant &p_value) {
+ if (!global_shader_uniforms.instance_buffer_pos.has(p_instance)) {
return; //just not allocated, ignore
}
- int32_t pos = global_variables.instance_buffer_pos[p_instance];
+ int32_t pos = global_shader_uniforms.instance_buffer_pos[p_instance];
if (pos < 0) {
return; //again, not allocated, ignore
@@ -2358,59 +2358,59 @@ void MaterialStorage::global_variables_instance_update(RID p_instance, int p_ind
pos += p_index;
- _fill_std140_variant_ubo_value(datatype, 0, p_value, (uint8_t *)&global_variables.buffer_values[pos]);
- _global_variable_mark_buffer_dirty(pos, 1);
+ _fill_std140_variant_ubo_value(datatype, 0, p_value, (uint8_t *)&global_shader_uniforms.buffer_values[pos]);
+ _global_shader_uniform_mark_buffer_dirty(pos, 1);
}
-void MaterialStorage::_update_global_variables() {
+void MaterialStorage::_update_global_shader_uniforms() {
MaterialStorage *material_storage = MaterialStorage::get_singleton();
- if (global_variables.buffer_dirty_region_count > 0) {
- uint32_t total_regions = global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE;
- if (total_regions / global_variables.buffer_dirty_region_count <= 4) {
+ if (global_shader_uniforms.buffer_dirty_region_count > 0) {
+ uint32_t total_regions = global_shader_uniforms.buffer_size / GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE;
+ if (total_regions / global_shader_uniforms.buffer_dirty_region_count <= 4) {
// 25% of regions dirty, just update all buffer
- glBindBuffer(GL_UNIFORM_BUFFER, global_variables.buffer);
- glBufferData(GL_UNIFORM_BUFFER, sizeof(GlobalVariables::Value) * global_variables.buffer_size, global_variables.buffer_values, GL_DYNAMIC_DRAW);
+ glBindBuffer(GL_UNIFORM_BUFFER, global_shader_uniforms.buffer);
+ glBufferData(GL_UNIFORM_BUFFER, sizeof(GlobalShaderUniforms::Value) * global_shader_uniforms.buffer_size, global_shader_uniforms.buffer_values, GL_DYNAMIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
- memset(global_variables.buffer_dirty_regions, 0, sizeof(bool) * total_regions);
+ memset(global_shader_uniforms.buffer_dirty_regions, 0, sizeof(bool) * total_regions);
} else {
- uint32_t region_byte_size = sizeof(GlobalVariables::Value) * GlobalVariables::BUFFER_DIRTY_REGION_SIZE;
- glBindBuffer(GL_UNIFORM_BUFFER, global_variables.buffer);
+ uint32_t region_byte_size = sizeof(GlobalShaderUniforms::Value) * GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE;
+ glBindBuffer(GL_UNIFORM_BUFFER, global_shader_uniforms.buffer);
for (uint32_t i = 0; i < total_regions; i++) {
- if (global_variables.buffer_dirty_regions[i]) {
- glBufferSubData(GL_UNIFORM_BUFFER, i * region_byte_size, region_byte_size, &global_variables.buffer_values[i * GlobalVariables::BUFFER_DIRTY_REGION_SIZE]);
- global_variables.buffer_dirty_regions[i] = false;
+ if (global_shader_uniforms.buffer_dirty_regions[i]) {
+ glBufferSubData(GL_UNIFORM_BUFFER, i * region_byte_size, region_byte_size, &global_shader_uniforms.buffer_values[i * GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE]);
+ global_shader_uniforms.buffer_dirty_regions[i] = false;
}
}
glBindBuffer(GL_UNIFORM_BUFFER, 0);
}
- global_variables.buffer_dirty_region_count = 0;
+ global_shader_uniforms.buffer_dirty_region_count = 0;
}
- if (global_variables.must_update_buffer_materials) {
+ if (global_shader_uniforms.must_update_buffer_materials) {
// only happens in the case of a buffer variable added or removed,
// so not often.
- for (const RID &E : global_variables.materials_using_buffer) {
+ for (const RID &E : global_shader_uniforms.materials_using_buffer) {
Material *material = material_storage->get_material(E);
ERR_CONTINUE(!material); //wtf
material_storage->_material_queue_update(material, true, false);
}
- global_variables.must_update_buffer_materials = false;
+ global_shader_uniforms.must_update_buffer_materials = false;
}
- if (global_variables.must_update_texture_materials) {
+ if (global_shader_uniforms.must_update_texture_materials) {
// only happens in the case of a buffer variable added or removed,
// so not often.
- for (const RID &E : global_variables.materials_using_texture) {
+ for (const RID &E : global_shader_uniforms.materials_using_texture) {
Material *material = material_storage->get_material(E);
ERR_CONTINUE(!material); //wtf
material_storage->_material_queue_update(material, false, true);
}
- global_variables.must_update_texture_materials = false;
+ global_shader_uniforms.must_update_texture_materials = false;
}
}
diff --git a/drivers/gles3/storage/material_storage.h b/drivers/gles3/storage/material_storage.h
index 91e1eee306..8fc15ddcba 100644
--- a/drivers/gles3/storage/material_storage.h
+++ b/drivers/gles3/storage/material_storage.h
@@ -365,15 +365,15 @@ struct SceneMaterialData : public MaterialData {
MaterialData *_create_scene_material_func(ShaderData *p_shader);
-/* Global variable structs */
-struct GlobalVariables {
+/* Global shader uniform structs */
+struct GlobalShaderUniforms {
enum {
BUFFER_DIRTY_REGION_SIZE = 1024
};
struct Variable {
HashSet<RID> texture_materials; // materials using this
- RS::GlobalVariableType type;
+ RS::GlobalShaderUniformType type;
Variant value;
Variant override;
int32_t buffer_index; //for vectors
@@ -429,13 +429,13 @@ private:
friend struct MaterialData;
static MaterialStorage *singleton;
- /* GLOBAL VARIABLE API */
+ /* GLOBAL SHADER UNIFORM API */
- GlobalVariables global_variables;
+ GlobalShaderUniforms global_shader_uniforms;
- int32_t _global_variable_allocate(uint32_t p_elements);
- void _global_variable_store_in_buffer(int32_t p_index, RS::GlobalVariableType p_type, const Variant &p_value);
- void _global_variable_mark_buffer_dirty(int32_t p_index, int32_t p_elements);
+ int32_t _global_shader_uniform_allocate(uint32_t p_elements);
+ void _global_shader_uniform_store_in_buffer(int32_t p_index, RS::GlobalShaderUniformType p_type, const Variant &p_value);
+ void _global_shader_uniform_mark_buffer_dirty(int32_t p_index, int32_t p_elements);
/* SHADER API */
@@ -508,28 +508,28 @@ public:
ShaderCompiler compiler_sky;
} shaders;
- /* GLOBAL VARIABLE API */
+ /* GLOBAL SHADER UNIFORM API */
- void _update_global_variables();
+ void _update_global_shader_uniforms();
- virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) override;
- virtual void global_variable_remove(const StringName &p_name) override;
- virtual Vector<StringName> global_variable_get_list() const override;
+ virtual void global_shader_uniform_add(const StringName &p_name, RS::GlobalShaderUniformType p_type, const Variant &p_value) override;
+ virtual void global_shader_uniform_remove(const StringName &p_name) override;
+ virtual Vector<StringName> global_shader_uniform_get_list() const override;
- virtual void global_variable_set(const StringName &p_name, const Variant &p_value) override;
- virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value) override;
- virtual Variant global_variable_get(const StringName &p_name) const override;
- virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const override;
- RS::GlobalVariableType global_variable_get_type_internal(const StringName &p_name) const;
+ virtual void global_shader_uniform_set(const StringName &p_name, const Variant &p_value) override;
+ virtual void global_shader_uniform_set_override(const StringName &p_name, const Variant &p_value) override;
+ virtual Variant global_shader_uniform_get(const StringName &p_name) const override;
+ virtual RS::GlobalShaderUniformType global_shader_uniform_get_type(const StringName &p_name) const override;
+ RS::GlobalShaderUniformType global_shader_uniform_get_type_internal(const StringName &p_name) const;
- virtual void global_variables_load_settings(bool p_load_textures = true) override;
- virtual void global_variables_clear() override;
+ virtual void global_shader_uniforms_load_settings(bool p_load_textures = true) override;
+ virtual void global_shader_uniforms_clear() override;
- virtual int32_t global_variables_instance_allocate(RID p_instance) override;
- virtual void global_variables_instance_free(RID p_instance) override;
- virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) override;
+ virtual int32_t global_shader_uniforms_instance_allocate(RID p_instance) override;
+ virtual void global_shader_uniforms_instance_free(RID p_instance) override;
+ virtual void global_shader_uniforms_instance_update(RID p_instance, int p_index, const Variant &p_value) override;
- GLuint global_variables_get_uniform_buffer() const;
+ GLuint global_shader_uniforms_get_uniform_buffer() const;
/* SHADER API */
diff --git a/drivers/gles3/storage/utilities.cpp b/drivers/gles3/storage/utilities.cpp
index a00210a2ab..654104722b 100644
--- a/drivers/gles3/storage/utilities.cpp
+++ b/drivers/gles3/storage/utilities.cpp
@@ -293,7 +293,7 @@ void Utilities::visibility_notifier_call(RID p_notifier, bool p_enter, bool p_de
/* MISC */
void Utilities::update_dirty_resources() {
- MaterialStorage::get_singleton()->_update_global_variables();
+ MaterialStorage::get_singleton()->_update_global_shader_uniforms();
MaterialStorage::get_singleton()->_update_queued_materials();
//MeshStorage::get_singleton()->_update_dirty_skeletons();
MeshStorage::get_singleton()->_update_dirty_multimeshes();
diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp
index 5f9eefe7fa..0979ae9e16 100644
--- a/drivers/vulkan/rendering_device_vulkan.cpp
+++ b/drivers/vulkan/rendering_device_vulkan.cpp
@@ -1835,7 +1835,8 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T
ERR_FAIL_V_MSG(RID(), "Format " + format_text + " does not support usage as atomic storage image.");
}
- if (p_format.usage_bits & TEXTURE_USAGE_VRS_ATTACHMENT_BIT && !(flags & VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR)) {
+ // Validation via VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR fails if VRS attachment is not supported.
+ if (p_format.usage_bits & TEXTURE_USAGE_VRS_ATTACHMENT_BIT && p_format.format != DATA_FORMAT_R8_UINT) {
ERR_FAIL_V_MSG(RID(), "Format " + format_text + " does not support usage as VRS attachment.");
}
}
@@ -3358,7 +3359,8 @@ bool RenderingDeviceVulkan::texture_is_format_supported_for_usage(DataFormat p_f
return false;
}
- if (p_usage & TEXTURE_USAGE_VRS_ATTACHMENT_BIT && !(flags & VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR)) {
+ // Validation via VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR fails if VRS attachment is not supported.
+ if (p_usage & TEXTURE_USAGE_VRS_ATTACHMENT_BIT && p_format != DATA_FORMAT_R8_UINT) {
return false;
}
diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp
index 234bfb944c..f01a83ea4c 100644
--- a/editor/animation_track_editor.cpp
+++ b/editor/animation_track_editor.cpp
@@ -3746,19 +3746,7 @@ void AnimationTrackEditor::_insert_track(bool p_reset_wanted, bool p_create_bezi
undo_redo->commit_action();
if (advance) {
- float step = animation->get_step();
- if (step == 0) {
- step = 1;
- }
-
- float pos = timeline->get_play_position();
-
- pos = Math::snapped(pos + step, step);
- if (pos > animation->get_length()) {
- pos = animation->get_length();
- }
- set_anim_pos(pos);
- emit_signal(SNAME("timeline_changed"), pos, true, false);
+ _edit_menu_pressed(EDIT_GOTO_NEXT_STEP_TIMELINE_ONLY);
}
}
@@ -4086,12 +4074,20 @@ void AnimationTrackEditor::_confirm_insert_list() {
}
TrackIndices next_tracks(animation.ptr(), reset_anim.ptr());
+ bool advance = false;
while (insert_data.size()) {
+ if (insert_data.front()->get().advance) {
+ advance = true;
+ }
next_tracks = _confirm_insert(insert_data.front()->get(), next_tracks, create_reset, reset_anim, insert_confirm_bezier->is_pressed());
insert_data.pop_front();
}
undo_redo->commit_action();
+
+ if (advance) {
+ _edit_menu_pressed(EDIT_GOTO_NEXT_STEP_TIMELINE_ONLY);
+ }
}
PropertyInfo AnimationTrackEditor::_find_hint_for_track(int p_idx, NodePath &r_base_path, Variant *r_current_val) {
@@ -5597,7 +5593,7 @@ void AnimationTrackEditor::goto_prev_step(bool p_from_mouse_event) {
emit_signal(SNAME("timeline_changed"), pos, true, false);
}
-void AnimationTrackEditor::goto_next_step(bool p_from_mouse_event) {
+void AnimationTrackEditor::goto_next_step(bool p_from_mouse_event, bool p_timeline_only) {
if (animation.is_null()) {
return;
}
@@ -5621,7 +5617,7 @@ void AnimationTrackEditor::goto_next_step(bool p_from_mouse_event) {
}
set_anim_pos(pos);
- emit_signal(SNAME("timeline_changed"), pos, true, false);
+ emit_signal(SNAME("timeline_changed"), pos, true, p_timeline_only);
}
void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
@@ -5969,8 +5965,9 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
_update_key_edit();
}
} break;
+ case EDIT_GOTO_NEXT_STEP_TIMELINE_ONLY:
case EDIT_GOTO_NEXT_STEP: {
- goto_next_step(false);
+ goto_next_step(false, p_option == EDIT_GOTO_NEXT_STEP_TIMELINE_ONLY);
} break;
case EDIT_GOTO_PREV_STEP: {
goto_prev_step(false);
diff --git a/editor/animation_track_editor.h b/editor/animation_track_editor.h
index dede2e9bbe..18ce2ded63 100644
--- a/editor/animation_track_editor.h
+++ b/editor/animation_track_editor.h
@@ -518,6 +518,7 @@ public:
EDIT_ADD_RESET_KEY,
EDIT_DELETE_SELECTION,
EDIT_GOTO_NEXT_STEP,
+ EDIT_GOTO_NEXT_STEP_TIMELINE_ONLY, // Next step without updating animation.
EDIT_GOTO_PREV_STEP,
EDIT_APPLY_RESET,
EDIT_OPTIMIZE_ANIMATION,
@@ -563,7 +564,7 @@ public:
void goto_prev_step(bool p_from_mouse_event);
/** If `p_from_mouse_event` is `true`, handle Shift key presses for precise snapping. */
- void goto_next_step(bool p_from_mouse_event);
+ void goto_next_step(bool p_from_mouse_event, bool p_timeline_only = false);
MenuButton *get_edit_menu();
AnimationTrackEditor();
diff --git a/editor/editor_asset_installer.cpp b/editor/editor_asset_installer.cpp
index 8fa486408e..8dc8a0ab6b 100644
--- a/editor/editor_asset_installer.cpp
+++ b/editor/editor_asset_installer.cpp
@@ -100,8 +100,8 @@ void EditorAssetInstaller::open(const String &p_path, int p_depth) {
extension_guess["tga"] = tree->get_theme_icon(SNAME("ImageTexture"), SNAME("EditorIcons"));
extension_guess["webp"] = tree->get_theme_icon(SNAME("ImageTexture"), SNAME("EditorIcons"));
- extension_guess["wav"] = tree->get_theme_icon(SNAME("AudioStreamSample"), SNAME("EditorIcons"));
- extension_guess["ogg"] = tree->get_theme_icon(SNAME("AudioStreamOGGVorbis"), SNAME("EditorIcons"));
+ extension_guess["wav"] = tree->get_theme_icon(SNAME("AudioStreamWAV"), SNAME("EditorIcons"));
+ extension_guess["ogg"] = tree->get_theme_icon(SNAME("AudioStreamOggVorbis"), SNAME("EditorIcons"));
extension_guess["mp3"] = tree->get_theme_icon(SNAME("AudioStreamMP3"), SNAME("EditorIcons"));
extension_guess["scn"] = tree->get_theme_icon(SNAME("PackedScene"), SNAME("EditorIcons"));
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 37329c92f3..8294e2229a 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -175,7 +175,6 @@
#include "editor/plugins/polygon_2d_editor_plugin.h"
#include "editor/plugins/polygon_3d_editor_plugin.h"
#include "editor/plugins/ray_cast_2d_editor_plugin.h"
-#include "editor/plugins/replication_editor_plugin.h"
#include "editor/plugins/resource_preloader_editor_plugin.h"
#include "editor/plugins/root_motion_editor_plugin.h"
#include "editor/plugins/script_editor_plugin.h"
@@ -1035,7 +1034,7 @@ void EditorNode::_sources_changed(bool p_exist) {
// Reload the global shader variables, but this time
// loading textures, as they are now properly imported.
- RenderingServer::get_singleton()->global_variables_load_settings(true);
+ RenderingServer::get_singleton()->global_shader_uniforms_load_settings(true);
// Start preview thread now that it's safe.
if (!singleton->cmdline_export_mode) {
@@ -7142,7 +7141,6 @@ EditorNode::EditorNode() {
add_editor_plugin(memnew(Path3DEditorPlugin));
add_editor_plugin(memnew(PhysicalBone3DEditorPlugin));
add_editor_plugin(memnew(Polygon3DEditorPlugin));
- add_editor_plugin(memnew(ReplicationEditorPlugin));
add_editor_plugin(memnew(ResourcePreloaderEditorPlugin));
add_editor_plugin(memnew(ShaderEditorPlugin));
add_editor_plugin(memnew(ShaderFileEditorPlugin));
diff --git a/editor/editor_paths.cpp b/editor/editor_paths.cpp
index a5c2fe093c..977af3cfae 100644
--- a/editor/editor_paths.cpp
+++ b/editor/editor_paths.cpp
@@ -153,8 +153,8 @@ EditorPaths::EditorPaths() {
}
}
- if (!dir->dir_exists("templates")) {
- dir->make_dir("templates");
+ if (!dir->dir_exists("export_templates")) {
+ dir->make_dir("export_templates");
}
}
diff --git a/editor/icons/AudioStreamOGGVorbis.svg b/editor/icons/AudioStreamOggVorbis.svg
index 2e54de9faa..2e54de9faa 100644
--- a/editor/icons/AudioStreamOGGVorbis.svg
+++ b/editor/icons/AudioStreamOggVorbis.svg
diff --git a/editor/icons/AudioStreamSample.svg b/editor/icons/AudioStreamWAV.svg
index 2e54de9faa..2e54de9faa 100644
--- a/editor/icons/AudioStreamSample.svg
+++ b/editor/icons/AudioStreamWAV.svg
diff --git a/editor/import/resource_importer_wav.cpp b/editor/import/resource_importer_wav.cpp
index f0ba1eb7a1..3a47bfb29f 100644
--- a/editor/import/resource_importer_wav.cpp
+++ b/editor/import/resource_importer_wav.cpp
@@ -33,7 +33,7 @@
#include "core/io/file_access.h"
#include "core/io/marshalls.h"
#include "core/io/resource_saver.h"
-#include "scene/resources/audio_stream_sample.h"
+#include "scene/resources/audio_stream_wav.h"
const float TRIM_DB_LIMIT = -50;
const int TRIM_FADE_OUT_FRAMES = 500;
@@ -55,7 +55,7 @@ String ResourceImporterWAV::get_save_extension() const {
}
String ResourceImporterWAV::get_resource_type() const {
- return "AudioStreamSample";
+ return "AudioStreamWAV";
}
bool ResourceImporterWAV::get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const {
@@ -86,7 +86,7 @@ void ResourceImporterWAV::get_import_options(const String &p_path, List<ImportOp
r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "force/max_rate_hz", PROPERTY_HINT_RANGE, "11025,192000,1,exp"), 44100));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "edit/trim"), false));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "edit/normalize"), false));
- // Keep the `edit/loop_mode` enum in sync with AudioStreamSample::LoopMode (note: +1 offset due to "Detect From WAV").
+ // Keep the `edit/loop_mode` enum in sync with AudioStreamWAV::LoopMode (note: +1 offset due to "Detect From WAV").
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "edit/loop_mode", PROPERTY_HINT_ENUM, "Detect From WAV,Disabled,Forward,Ping-Pong,Backward", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 0));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "edit/loop_begin"), 0));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "edit/loop_end"), -1));
@@ -130,7 +130,7 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s
int format_bits = 0;
int format_channels = 0;
- AudioStreamSample::LoopMode loop_mode = AudioStreamSample::LOOP_DISABLED;
+ AudioStreamWAV::LoopMode loop_mode = AudioStreamWAV::LOOP_DISABLED;
uint16_t compression_code = 1;
bool format_found = false;
bool data_found = false;
@@ -282,11 +282,11 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s
int loop_type = file->get_32();
if (loop_type == 0x00 || loop_type == 0x01 || loop_type == 0x02) {
if (loop_type == 0x00) {
- loop_mode = AudioStreamSample::LOOP_FORWARD;
+ loop_mode = AudioStreamWAV::LOOP_FORWARD;
} else if (loop_type == 0x01) {
- loop_mode = AudioStreamSample::LOOP_PINGPONG;
+ loop_mode = AudioStreamWAV::LOOP_PINGPONG;
} else if (loop_type == 0x02) {
- loop_mode = AudioStreamSample::LOOP_BACKWARD;
+ loop_mode = AudioStreamWAV::LOOP_BACKWARD;
}
loop_begin = file->get_32();
loop_end = file->get_32();
@@ -386,7 +386,7 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s
bool trim = p_options["edit/trim"];
- if (trim && (loop_mode != AudioStreamSample::LOOP_DISABLED) && format_channels > 0) {
+ if (trim && (loop_mode != AudioStreamWAV::LOOP_DISABLED) && format_channels > 0) {
int first = 0;
int last = (frames / format_channels) - 1;
bool found = false;
@@ -431,7 +431,7 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s
}
if (import_loop_mode >= 2) {
- loop_mode = (AudioStreamSample::LoopMode)(import_loop_mode - 1);
+ loop_mode = (AudioStreamWAV::LoopMode)(import_loop_mode - 1);
loop_begin = p_options["edit/loop_begin"];
loop_end = p_options["edit/loop_end"];
// Wrap around to max frames, so `-1` can be used to select the end, etc.
@@ -463,10 +463,10 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s
}
Vector<uint8_t> dst_data;
- AudioStreamSample::Format dst_format;
+ AudioStreamWAV::Format dst_format;
if (compression == 1) {
- dst_format = AudioStreamSample::FORMAT_IMA_ADPCM;
+ dst_format = AudioStreamWAV::FORMAT_IMA_ADPCM;
if (format_channels == 1) {
_compress_ima_adpcm(data, dst_data);
} else {
@@ -503,7 +503,7 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s
}
} else {
- dst_format = is16 ? AudioStreamSample::FORMAT_16_BITS : AudioStreamSample::FORMAT_8_BITS;
+ dst_format = is16 ? AudioStreamWAV::FORMAT_16_BITS : AudioStreamWAV::FORMAT_8_BITS;
dst_data.resize(data.size() * (is16 ? 2 : 1));
{
uint8_t *w = dst_data.ptrw();
@@ -521,7 +521,7 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s
}
}
- Ref<AudioStreamSample> sample;
+ Ref<AudioStreamWAV> sample;
sample.instantiate();
sample->set_data(dst_data);
sample->set_format(dst_format);
diff --git a/editor/import/scene_import_settings.cpp b/editor/import/scene_import_settings.cpp
index 0e2967dc42..1c39c425b1 100644
--- a/editor/import/scene_import_settings.cpp
+++ b/editor/import/scene_import_settings.cpp
@@ -502,7 +502,7 @@ void SceneImportSettings::_update_camera() {
Transform3D xf;
xf.basis = Basis(Vector3(1, 0, 0), rot_x) * Basis(Vector3(0, 1, 0), rot_y);
xf.origin = center;
- xf.translate(0, 0, camera_size);
+ xf.translate_local(0, 0, camera_size);
camera->set_transform(xf);
}
diff --git a/editor/plugins/animation_state_machine_editor.cpp b/editor/plugins/animation_state_machine_editor.cpp
index 1258b9a03c..93dc0ff3c9 100644
--- a/editor/plugins/animation_state_machine_editor.cpp
+++ b/editor/plugins/animation_state_machine_editor.cpp
@@ -1018,7 +1018,7 @@ void AnimationNodeStateMachineEditor::_add_animation_type(int p_index) {
anim->set_animation(animations_to_add[p_index]);
- String base_name = animations_to_add[p_index];
+ String base_name = animations_to_add[p_index].validate_node_name();
int base = 1;
String name = base_name;
while (state_machine->has_node(name)) {
diff --git a/editor/plugins/bone_map_editor_plugin.cpp b/editor/plugins/bone_map_editor_plugin.cpp
index 9a00bb93b8..3669971b1e 100644
--- a/editor/plugins/bone_map_editor_plugin.cpp
+++ b/editor/plugins/bone_map_editor_plugin.cpp
@@ -65,6 +65,9 @@ void BoneMapperButton::set_state(BoneMapState p_state) {
case BONE_MAP_STATE_SET: {
circle->set_modulate(EditorSettings::get_singleton()->get("editors/bone_mapper/handle_colors/set"));
} break;
+ case BONE_MAP_STATE_MISSING: {
+ circle->set_modulate(EditorSettings::get_singleton()->get("editors/bone_mapper/handle_colors/missing"));
+ } break;
case BONE_MAP_STATE_ERROR: {
circle->set_modulate(EditorSettings::get_singleton()->get("editors/bone_mapper/handle_colors/error"));
} break;
@@ -311,16 +314,48 @@ void BoneMapper::recreate_items() {
void BoneMapper::_update_state() {
int len = bone_mapper_buttons.size();
for (int i = 0; i < len; i++) {
- StringName sbn = bone_map->get_skeleton_bone_name(bone_mapper_buttons[i]->get_profile_bone_name());
- if (skeleton->find_bone(sbn) >= 0) {
+ StringName pbn = bone_mapper_buttons[i]->get_profile_bone_name();
+ StringName sbn = bone_map->get_skeleton_bone_name(pbn);
+ int bone_idx = skeleton->find_bone(sbn);
+ if (bone_idx >= 0) {
if (bone_map->get_skeleton_bone_name_count(sbn) == 1) {
- bone_mapper_buttons[i]->set_state(BoneMapperButton::BONE_MAP_STATE_SET);
+ Ref<SkeletonProfile> prof = bone_map->get_profile();
+
+ StringName parent_name = prof->get_bone_parent(prof->find_bone(pbn));
+ Vector<int> prof_parent_bones;
+ while (parent_name != StringName()) {
+ prof_parent_bones.push_back(skeleton->find_bone(bone_map->get_skeleton_bone_name(parent_name)));
+ if (prof->find_bone(parent_name) == -1) {
+ break;
+ }
+ parent_name = prof->get_bone_parent(prof->find_bone(parent_name));
+ }
+
+ int parent_id = skeleton->get_bone_parent(bone_idx);
+ Vector<int> skel_parent_bones;
+ while (parent_id >= 0) {
+ skel_parent_bones.push_back(parent_id);
+ parent_id = skeleton->get_bone_parent(parent_id);
+ }
+
+ bool is_broken = false;
+ for (int j = 0; j < prof_parent_bones.size(); j++) {
+ if (prof_parent_bones[j] != -1 && !skel_parent_bones.has(prof_parent_bones[j])) {
+ is_broken = true;
+ }
+ }
+
+ if (is_broken) {
+ bone_mapper_buttons[i]->set_state(BoneMapperButton::BONE_MAP_STATE_ERROR);
+ } else {
+ bone_mapper_buttons[i]->set_state(BoneMapperButton::BONE_MAP_STATE_SET);
+ }
} else {
bone_mapper_buttons[i]->set_state(BoneMapperButton::BONE_MAP_STATE_ERROR);
}
} else {
if (bone_mapper_buttons[i]->is_require()) {
- bone_mapper_buttons[i]->set_state(BoneMapperButton::BONE_MAP_STATE_ERROR);
+ bone_mapper_buttons[i]->set_state(BoneMapperButton::BONE_MAP_STATE_MISSING);
} else {
bone_mapper_buttons[i]->set_state(BoneMapperButton::BONE_MAP_STATE_UNSET);
}
@@ -441,9 +476,10 @@ void EditorInspectorPluginBoneMap::parse_begin(Object *p_object) {
BoneMapEditorPlugin::BoneMapEditorPlugin() {
// Register properties in editor settings.
+ EDITOR_DEF("editors/bone_mapper/handle_colors/unset", Color(0.3, 0.3, 0.3));
EDITOR_DEF("editors/bone_mapper/handle_colors/set", Color(0.1, 0.6, 0.25));
+ EDITOR_DEF("editors/bone_mapper/handle_colors/missing", Color(0.8, 0.2, 0.8));
EDITOR_DEF("editors/bone_mapper/handle_colors/error", Color(0.8, 0.2, 0.2));
- EDITOR_DEF("editors/bone_mapper/handle_colors/unset", Color(0.3, 0.3, 0.3));
Ref<EditorInspectorPluginBoneMap> inspector_plugin;
inspector_plugin.instantiate();
diff --git a/editor/plugins/bone_map_editor_plugin.h b/editor/plugins/bone_map_editor_plugin.h
index 79fb47505b..339547ea10 100644
--- a/editor/plugins/bone_map_editor_plugin.h
+++ b/editor/plugins/bone_map_editor_plugin.h
@@ -47,6 +47,7 @@ public:
enum BoneMapState {
BONE_MAP_STATE_UNSET,
BONE_MAP_STATE_SET,
+ BONE_MAP_STATE_MISSING,
BONE_MAP_STATE_ERROR
};
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index 82772178e0..19239b8650 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -2793,10 +2793,10 @@ void CanvasItemEditor::_draw_rulers() {
if (grid_snap_active || _is_grid_visible()) {
List<CanvasItem *> selection = _get_edited_canvas_items();
if (snap_relative && selection.size() > 0) {
- ruler_transform.translate(_get_encompassing_rect_from_list(selection).position);
+ ruler_transform.translate_local(_get_encompassing_rect_from_list(selection).position);
ruler_transform.scale_basis(grid_step * Math::pow(2.0, grid_step_multiplier));
} else {
- ruler_transform.translate(grid_offset);
+ ruler_transform.translate_local(grid_offset);
ruler_transform.scale_basis(grid_step * Math::pow(2.0, grid_step_multiplier));
}
while ((transform * ruler_transform).get_scale().x < 50 || (transform * ruler_transform).get_scale().y < 50) {
diff --git a/editor/plugins/curve_editor_plugin.cpp b/editor/plugins/curve_editor_plugin.cpp
index 66e58339ed..2954071054 100644
--- a/editor/plugins/curve_editor_plugin.cpp
+++ b/editor/plugins/curve_editor_plugin.cpp
@@ -542,11 +542,11 @@ void CurveEditor::update_view_transform() {
const Vector2 scale = view_size / world_rect.size;
Transform2D world_trans;
- world_trans.translate(-world_rect.position - Vector2(0, world_rect.size.y));
+ world_trans.translate_local(-world_rect.position - Vector2(0, world_rect.size.y));
world_trans.scale(Vector2(scale.x, -scale.y));
Transform2D view_trans;
- view_trans.translate(view_margin);
+ view_trans.translate_local(view_margin);
_world_to_view = view_trans * world_trans;
}
diff --git a/editor/plugins/node_3d_editor_gizmos.cpp b/editor/plugins/node_3d_editor_gizmos.cpp
index 77cf1f0064..1ac986ed36 100644
--- a/editor/plugins/node_3d_editor_gizmos.cpp
+++ b/editor/plugins/node_3d_editor_gizmos.cpp
@@ -5044,8 +5044,8 @@ Basis JointGizmosDrawer::look_body_toward_z(const Transform3D &p_joint_transform
void JointGizmosDrawer::draw_circle(Vector3::Axis p_axis, real_t p_radius, const Transform3D &p_offset, const Basis &p_base, real_t p_limit_lower, real_t p_limit_upper, Vector<Vector3> &r_points, bool p_inverse) {
if (p_limit_lower == p_limit_upper) {
- r_points.push_back(p_offset.translated(Vector3()).origin);
- r_points.push_back(p_offset.translated(p_base.xform(Vector3(0.5, 0, 0))).origin);
+ r_points.push_back(p_offset.translated_local(Vector3()).origin);
+ r_points.push_back(p_offset.translated_local(p_base.xform(Vector3(0.5, 0, 0))).origin);
} else {
if (p_limit_lower > p_limit_upper) {
@@ -5087,20 +5087,20 @@ void JointGizmosDrawer::draw_circle(Vector3::Axis p_axis, real_t p_radius, const
}
if (i == points - 1) {
- r_points.push_back(p_offset.translated(to).origin);
- r_points.push_back(p_offset.translated(Vector3()).origin);
+ r_points.push_back(p_offset.translated_local(to).origin);
+ r_points.push_back(p_offset.translated_local(Vector3()).origin);
}
if (i == 0) {
- r_points.push_back(p_offset.translated(from).origin);
- r_points.push_back(p_offset.translated(Vector3()).origin);
+ r_points.push_back(p_offset.translated_local(from).origin);
+ r_points.push_back(p_offset.translated_local(Vector3()).origin);
}
- r_points.push_back(p_offset.translated(from).origin);
- r_points.push_back(p_offset.translated(to).origin);
+ r_points.push_back(p_offset.translated_local(from).origin);
+ r_points.push_back(p_offset.translated_local(to).origin);
}
- r_points.push_back(p_offset.translated(Vector3(0, p_radius * 1.5, 0)).origin);
- r_points.push_back(p_offset.translated(Vector3()).origin);
+ r_points.push_back(p_offset.translated_local(Vector3(0, p_radius * 1.5, 0)).origin);
+ r_points.push_back(p_offset.translated_local(Vector3()).origin);
}
}
@@ -5116,17 +5116,17 @@ void JointGizmosDrawer::draw_cone(const Transform3D &p_offset, const Basis &p_ba
Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * w;
Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * w;
- r_points.push_back(p_offset.translated(p_base.xform(Vector3(d, a.x, a.y))).origin);
- r_points.push_back(p_offset.translated(p_base.xform(Vector3(d, b.x, b.y))).origin);
+ r_points.push_back(p_offset.translated_local(p_base.xform(Vector3(d, a.x, a.y))).origin);
+ r_points.push_back(p_offset.translated_local(p_base.xform(Vector3(d, b.x, b.y))).origin);
if (i % 90 == 0) {
- r_points.push_back(p_offset.translated(p_base.xform(Vector3(d, a.x, a.y))).origin);
- r_points.push_back(p_offset.translated(p_base.xform(Vector3())).origin);
+ r_points.push_back(p_offset.translated_local(p_base.xform(Vector3(d, a.x, a.y))).origin);
+ r_points.push_back(p_offset.translated_local(p_base.xform(Vector3())).origin);
}
}
- r_points.push_back(p_offset.translated(p_base.xform(Vector3())).origin);
- r_points.push_back(p_offset.translated(p_base.xform(Vector3(1, 0, 0))).origin);
+ r_points.push_back(p_offset.translated_local(p_base.xform(Vector3())).origin);
+ r_points.push_back(p_offset.translated_local(p_base.xform(Vector3(1, 0, 0))).origin);
/// Twist
float ts = Math::rad2deg(p_twist);
@@ -5140,8 +5140,8 @@ void JointGizmosDrawer::draw_cone(const Transform3D &p_offset, const Basis &p_ba
Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * w * c;
Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * w * cn;
- r_points.push_back(p_offset.translated(p_base.xform(Vector3(c, a.x, a.y))).origin);
- r_points.push_back(p_offset.translated(p_base.xform(Vector3(cn, b.x, b.y))).origin);
+ r_points.push_back(p_offset.translated_local(p_base.xform(Vector3(c, a.x, a.y))).origin);
+ r_points.push_back(p_offset.translated_local(p_base.xform(Vector3(cn, b.x, b.y))).origin);
}
}
@@ -5325,17 +5325,17 @@ void Joint3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
void Joint3DGizmoPlugin::CreatePinJointGizmo(const Transform3D &p_offset, Vector<Vector3> &r_cursor_points) {
float cs = 0.25;
- r_cursor_points.push_back(p_offset.translated(Vector3(+cs, 0, 0)).origin);
- r_cursor_points.push_back(p_offset.translated(Vector3(-cs, 0, 0)).origin);
- r_cursor_points.push_back(p_offset.translated(Vector3(0, +cs, 0)).origin);
- r_cursor_points.push_back(p_offset.translated(Vector3(0, -cs, 0)).origin);
- r_cursor_points.push_back(p_offset.translated(Vector3(0, 0, +cs)).origin);
- r_cursor_points.push_back(p_offset.translated(Vector3(0, 0, -cs)).origin);
+ r_cursor_points.push_back(p_offset.translated_local(Vector3(+cs, 0, 0)).origin);
+ r_cursor_points.push_back(p_offset.translated_local(Vector3(-cs, 0, 0)).origin);
+ r_cursor_points.push_back(p_offset.translated_local(Vector3(0, +cs, 0)).origin);
+ r_cursor_points.push_back(p_offset.translated_local(Vector3(0, -cs, 0)).origin);
+ r_cursor_points.push_back(p_offset.translated_local(Vector3(0, 0, +cs)).origin);
+ r_cursor_points.push_back(p_offset.translated_local(Vector3(0, 0, -cs)).origin);
}
void Joint3DGizmoPlugin::CreateHingeJointGizmo(const Transform3D &p_offset, const Transform3D &p_trs_joint, const Transform3D &p_trs_body_a, const Transform3D &p_trs_body_b, real_t p_limit_lower, real_t p_limit_upper, bool p_use_limit, Vector<Vector3> &r_common_points, Vector<Vector3> *r_body_a_points, Vector<Vector3> *r_body_b_points) {
- r_common_points.push_back(p_offset.translated(Vector3(0, 0, 0.5)).origin);
- r_common_points.push_back(p_offset.translated(Vector3(0, 0, -0.5)).origin);
+ r_common_points.push_back(p_offset.translated_local(Vector3(0, 0, 0.5)).origin);
+ r_common_points.push_back(p_offset.translated_local(Vector3(0, 0, -0.5)).origin);
if (!p_use_limit) {
p_limit_upper = -1;
@@ -5368,34 +5368,34 @@ void Joint3DGizmoPlugin::CreateSliderJointGizmo(const Transform3D &p_offset, con
p_linear_limit_upper = -p_linear_limit_upper;
float cs = 0.25;
- r_points.push_back(p_offset.translated(Vector3(0, 0, 0.5)).origin);
- r_points.push_back(p_offset.translated(Vector3(0, 0, -0.5)).origin);
+ r_points.push_back(p_offset.translated_local(Vector3(0, 0, 0.5)).origin);
+ r_points.push_back(p_offset.translated_local(Vector3(0, 0, -0.5)).origin);
if (p_linear_limit_lower >= p_linear_limit_upper) {
- r_points.push_back(p_offset.translated(Vector3(p_linear_limit_upper, 0, 0)).origin);
- r_points.push_back(p_offset.translated(Vector3(p_linear_limit_lower, 0, 0)).origin);
-
- r_points.push_back(p_offset.translated(Vector3(p_linear_limit_upper, -cs, -cs)).origin);
- r_points.push_back(p_offset.translated(Vector3(p_linear_limit_upper, -cs, cs)).origin);
- r_points.push_back(p_offset.translated(Vector3(p_linear_limit_upper, -cs, cs)).origin);
- r_points.push_back(p_offset.translated(Vector3(p_linear_limit_upper, cs, cs)).origin);
- r_points.push_back(p_offset.translated(Vector3(p_linear_limit_upper, cs, cs)).origin);
- r_points.push_back(p_offset.translated(Vector3(p_linear_limit_upper, cs, -cs)).origin);
- r_points.push_back(p_offset.translated(Vector3(p_linear_limit_upper, cs, -cs)).origin);
- r_points.push_back(p_offset.translated(Vector3(p_linear_limit_upper, -cs, -cs)).origin);
-
- r_points.push_back(p_offset.translated(Vector3(p_linear_limit_lower, -cs, -cs)).origin);
- r_points.push_back(p_offset.translated(Vector3(p_linear_limit_lower, -cs, cs)).origin);
- r_points.push_back(p_offset.translated(Vector3(p_linear_limit_lower, -cs, cs)).origin);
- r_points.push_back(p_offset.translated(Vector3(p_linear_limit_lower, cs, cs)).origin);
- r_points.push_back(p_offset.translated(Vector3(p_linear_limit_lower, cs, cs)).origin);
- r_points.push_back(p_offset.translated(Vector3(p_linear_limit_lower, cs, -cs)).origin);
- r_points.push_back(p_offset.translated(Vector3(p_linear_limit_lower, cs, -cs)).origin);
- r_points.push_back(p_offset.translated(Vector3(p_linear_limit_lower, -cs, -cs)).origin);
+ r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_upper, 0, 0)).origin);
+ r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_lower, 0, 0)).origin);
+
+ r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_upper, -cs, -cs)).origin);
+ r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_upper, -cs, cs)).origin);
+ r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_upper, -cs, cs)).origin);
+ r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_upper, cs, cs)).origin);
+ r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_upper, cs, cs)).origin);
+ r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_upper, cs, -cs)).origin);
+ r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_upper, cs, -cs)).origin);
+ r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_upper, -cs, -cs)).origin);
+
+ r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_lower, -cs, -cs)).origin);
+ r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_lower, -cs, cs)).origin);
+ r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_lower, -cs, cs)).origin);
+ r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_lower, cs, cs)).origin);
+ r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_lower, cs, cs)).origin);
+ r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_lower, cs, -cs)).origin);
+ r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_lower, cs, -cs)).origin);
+ r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_lower, -cs, -cs)).origin);
} else {
- r_points.push_back(p_offset.translated(Vector3(+cs * 2, 0, 0)).origin);
- r_points.push_back(p_offset.translated(Vector3(-cs * 2, 0, 0)).origin);
+ r_points.push_back(p_offset.translated_local(Vector3(+cs * 2, 0, 0)).origin);
+ r_points.push_back(p_offset.translated_local(Vector3(-cs * 2, 0, 0)).origin);
}
if (r_body_a_points) {
@@ -5518,13 +5518,13 @@ void Joint3DGizmoPlugin::CreateGeneric6DOFJointGizmo(
break;
}
-#define ADD_VTX(x, y, z) \
- { \
- Vector3 v; \
- v[a1] = (x); \
- v[a2] = (y); \
- v[a3] = (z); \
- r_points.push_back(p_offset.translated(v).origin); \
+#define ADD_VTX(x, y, z) \
+ { \
+ Vector3 v; \
+ v[a1] = (x); \
+ v[a2] = (y); \
+ v[a3] = (z); \
+ r_points.push_back(p_offset.translated_local(v).origin); \
}
if (enable_lin && lll >= lul) {
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index 44ab4e0a41..ffc60f9664 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -356,14 +356,14 @@ void Node3DEditorViewport::_update_camera(real_t p_interp_delta) {
Transform3D Node3DEditorViewport::to_camera_transform(const Cursor &p_cursor) const {
Transform3D camera_transform;
- camera_transform.translate(p_cursor.pos);
+ camera_transform.translate_local(p_cursor.pos);
camera_transform.basis.rotate(Vector3(1, 0, 0), -p_cursor.x_rot);
camera_transform.basis.rotate(Vector3(0, 1, 0), -p_cursor.y_rot);
if (orthogonal) {
- camera_transform.translate(0, 0, (get_zfar() - get_znear()) / 2.0);
+ camera_transform.translate_local(0, 0, (get_zfar() - get_znear()) / 2.0);
} else {
- camera_transform.translate(0, 0, p_cursor.distance);
+ camera_transform.translate_local(0, 0, p_cursor.distance);
}
return camera_transform;
@@ -515,7 +515,7 @@ void Node3DEditorViewport::_select_clicked(bool p_allow_locked) {
}
}
-ObjectID Node3DEditorViewport::_select_ray(const Point2 &p_pos) {
+ObjectID Node3DEditorViewport::_select_ray(const Point2 &p_pos) const {
Vector3 ray = _get_ray(p_pos);
Vector3 pos = _get_ray_pos(p_pos);
Vector2 shrinked_pos = p_pos / subviewport_container->get_stretch_shrink();
@@ -651,10 +651,10 @@ Vector3 Node3DEditorViewport::_get_screen_to_space(const Vector3 &p_vector3) {
Vector2 screen_he = cm.get_viewport_half_extents();
Transform3D camera_transform;
- camera_transform.translate(cursor.pos);
+ camera_transform.translate_local(cursor.pos);
camera_transform.basis.rotate(Vector3(1, 0, 0), -cursor.x_rot);
camera_transform.basis.rotate(Vector3(0, 1, 0), -cursor.y_rot);
- camera_transform.translate(0, 0, cursor.distance);
+ camera_transform.translate_local(0, 0, cursor.distance);
return camera_transform.xform(Vector3(((p_vector3.x / get_size().width) * 2.0 - 1.0) * screen_he.x, ((1.0 - (p_vector3.y / get_size().height)) * 2.0 - 1.0) * screen_he.y, -(get_znear() + p_vector3.z)));
}
@@ -1260,7 +1260,9 @@ void Node3DEditorViewport::_surface_mouse_enter() {
}
void Node3DEditorViewport::_surface_mouse_exit() {
- _remove_preview();
+ _remove_preview_node();
+ _reset_preview_material();
+ _remove_preview_material();
}
void Node3DEditorViewport::_surface_focus_enter() {
@@ -2100,7 +2102,7 @@ void Node3DEditorViewport::_nav_pan(Ref<InputEventWithModifiers> p_event, const
Transform3D camera_transform;
- camera_transform.translate(cursor.pos);
+ camera_transform.translate_local(cursor.pos);
camera_transform.basis.rotate(Vector3(1, 0, 0), -cursor.x_rot);
camera_transform.basis.rotate(Vector3(0, 1, 0), -cursor.y_rot);
const bool invert_x_axis = EditorSettings::get_singleton()->get("editors/3d/navigation/invert_x_axis");
@@ -2110,7 +2112,7 @@ void Node3DEditorViewport::_nav_pan(Ref<InputEventWithModifiers> p_event, const
(invert_y_axis ? -1 : 1) * p_relative.y * pan_speed,
0);
translation *= cursor.distance / DISTANCE_DEFAULT;
- camera_transform.translate(translation);
+ camera_transform.translate_local(translation);
cursor.pos = camera_transform.origin;
}
@@ -2423,8 +2425,8 @@ void Node3DEditorViewport::_project_settings_changed() {
const float fsr_sharpness = GLOBAL_GET("rendering/scaling_3d/fsr_sharpness");
viewport->set_fsr_sharpness(fsr_sharpness);
- const float fsr_mipmap_bias = GLOBAL_GET("rendering/scaling_3d/fsr_mipmap_bias");
- viewport->set_fsr_mipmap_bias(fsr_mipmap_bias);
+ const float texture_mipmap_bias = GLOBAL_GET("rendering/textures/default_filters/texture_mipmap_bias");
+ viewport->set_texture_mipmap_bias(texture_mipmap_bias);
}
void Node3DEditorViewport::_notification(int p_what) {
@@ -2520,14 +2522,14 @@ void Node3DEditorViewport::_notification(int p_what) {
const Vector3 offset(0.005, 0.005, 0.005);
Basis aabb_s;
aabb_s.scale(se->aabb.size + offset);
- t.translate(se->aabb.position - offset / 2);
+ t.translate_local(se->aabb.position - offset / 2);
t.basis = t.basis * aabb_s;
}
{
const Vector3 offset(0.01, 0.01, 0.01);
Basis aabb_s;
aabb_s.scale(se->aabb.size + offset);
- t_offset.translate(se->aabb.position - offset / 2);
+ t_offset.translate_local(se->aabb.position - offset / 2);
t_offset.basis = t_offset.basis * aabb_s;
}
@@ -2703,6 +2705,13 @@ void Node3DEditorViewport::_notification(int p_what) {
cinema_label->add_theme_style_override("normal", gui_base->get_theme_stylebox(SNAME("Information3dViewport"), SNAME("EditorStyles")));
locked_label->add_theme_style_override("normal", gui_base->get_theme_stylebox(SNAME("Information3dViewport"), SNAME("EditorStyles")));
} break;
+
+ case NOTIFICATION_DRAG_END: {
+ // Clear preview material when dropped outside applicable object.
+ if (spatial_editor->get_preview_material().is_valid() && !is_drag_successful()) {
+ _remove_preview_material();
+ }
+ } break;
}
}
@@ -3794,7 +3803,7 @@ Node *Node3DEditorViewport::_sanitize_preview_node(Node *p_node) const {
return p_node;
}
-void Node3DEditorViewport::_create_preview(const Vector<String> &files) const {
+void Node3DEditorViewport::_create_preview_node(const Vector<String> &files) const {
for (int i = 0; i < files.size(); i++) {
String path = files[i];
Ref<Resource> res = ResourceLoader::load(path);
@@ -3821,7 +3830,7 @@ void Node3DEditorViewport::_create_preview(const Vector<String> &files) const {
*preview_bounds = _calculate_spatial_bounds(preview_node);
}
-void Node3DEditorViewport::_remove_preview() {
+void Node3DEditorViewport::_remove_preview_node() {
if (preview_node->get_parent()) {
for (int i = preview_node->get_child_count() - 1; i >= 0; i--) {
Node *node = preview_node->get_child(i);
@@ -3832,6 +3841,106 @@ void Node3DEditorViewport::_remove_preview() {
}
}
+bool Node3DEditorViewport::_apply_preview_material(ObjectID p_target, const Point2 &p_point) const {
+ _reset_preview_material();
+
+ if (p_target.is_null()) {
+ return false;
+ }
+
+ spatial_editor->set_preview_material_target(p_target);
+
+ Object *target_inst = ObjectDB::get_instance(p_target);
+
+ bool is_ctrl = Input::get_singleton()->is_key_pressed(Key::CTRL);
+
+ MeshInstance3D *mesh_instance = Object::cast_to<MeshInstance3D>(target_inst);
+ if (is_ctrl && mesh_instance) {
+ Ref<Mesh> mesh = mesh_instance->get_mesh();
+ int surface_count = mesh->get_surface_count();
+
+ Vector3 world_ray = _get_ray(p_point);
+ Vector3 world_pos = _get_ray_pos(p_point);
+
+ int closest_surface = -1;
+ float closest_dist = 1e20;
+
+ Transform3D gt = mesh_instance->get_global_transform();
+
+ Transform3D ai = gt.affine_inverse();
+ Vector3 xform_ray = ai.basis.xform(world_ray).normalized();
+ Vector3 xform_pos = ai.xform(world_pos);
+
+ for (int surface = 0; surface < surface_count; surface++) {
+ Ref<TriangleMesh> surface_mesh = mesh->generate_surface_triangle_mesh(surface);
+
+ Vector3 rpos, rnorm;
+ if (surface_mesh->intersect_ray(xform_pos, xform_ray, rpos, rnorm)) {
+ Vector3 hitpos = gt.xform(rpos);
+
+ const real_t dist = world_pos.distance_to(hitpos);
+
+ if (dist < 0) {
+ continue;
+ }
+
+ if (dist < closest_dist) {
+ closest_surface = surface;
+ closest_dist = dist;
+ }
+ }
+ }
+
+ if (closest_surface == -1) {
+ return false;
+ }
+
+ if (spatial_editor->get_preview_material() != mesh_instance->get_surface_override_material(closest_surface)) {
+ spatial_editor->set_preview_material_surface(closest_surface);
+ spatial_editor->set_preview_reset_material(mesh_instance->get_surface_override_material(closest_surface));
+ mesh_instance->set_surface_override_material(closest_surface, spatial_editor->get_preview_material());
+ }
+
+ return true;
+ }
+
+ GeometryInstance3D *geometry_instance = Object::cast_to<GeometryInstance3D>(target_inst);
+ if (geometry_instance && spatial_editor->get_preview_material() != geometry_instance->get_material_override()) {
+ spatial_editor->set_preview_reset_material(geometry_instance->get_material_override());
+ geometry_instance->set_material_override(spatial_editor->get_preview_material());
+ return true;
+ }
+
+ return false;
+}
+
+void Node3DEditorViewport::_reset_preview_material() const {
+ ObjectID last_target = spatial_editor->get_preview_material_target();
+ if (last_target.is_null()) {
+ return;
+ }
+ Object *last_target_inst = ObjectDB::get_instance(last_target);
+
+ MeshInstance3D *mesh_instance = Object::cast_to<MeshInstance3D>(last_target_inst);
+ GeometryInstance3D *geometry_instance = Object::cast_to<GeometryInstance3D>(last_target_inst);
+ if (mesh_instance && spatial_editor->get_preview_material_surface() != -1) {
+ mesh_instance->set_surface_override_material(spatial_editor->get_preview_material_surface(), spatial_editor->get_preview_reset_material());
+ spatial_editor->set_preview_material_surface(-1);
+ } else if (geometry_instance) {
+ geometry_instance->set_material_override(spatial_editor->get_preview_reset_material());
+ }
+}
+
+void Node3DEditorViewport::_remove_preview_material() {
+ preview_material_label->hide();
+ preview_material_label_desc->hide();
+
+ spatial_editor->set_preview_material(Ref<Material>());
+ spatial_editor->set_preview_reset_material(Ref<Material>());
+ spatial_editor->set_preview_material_target(ObjectID());
+ spatial_editor->set_preview_material_surface(-1);
+}
+
bool Node3DEditorViewport::_cyclical_dependency_exists(const String &p_target_scene_path, Node *p_desired_node) {
if (p_desired_node->get_scene_file_path() == p_target_scene_path) {
return true;
@@ -3930,7 +4039,26 @@ bool Node3DEditorViewport::_create_instance(Node *parent, String &path, const Po
}
void Node3DEditorViewport::_perform_drop_data() {
- _remove_preview();
+ if (spatial_editor->get_preview_material_target().is_valid()) {
+ GeometryInstance3D *geometry_instance = Object::cast_to<GeometryInstance3D>(ObjectDB::get_instance(spatial_editor->get_preview_material_target()));
+ MeshInstance3D *mesh_instance = Object::cast_to<MeshInstance3D>(ObjectDB::get_instance(spatial_editor->get_preview_material_target()));
+ if (mesh_instance && spatial_editor->get_preview_material_surface() != -1) {
+ editor_data->get_undo_redo().create_action(vformat(TTR("Set Surface %d Override Material"), spatial_editor->get_preview_material_surface()));
+ editor_data->get_undo_redo().add_do_method(geometry_instance, "set_surface_override_material", spatial_editor->get_preview_material_surface(), spatial_editor->get_preview_material());
+ editor_data->get_undo_redo().add_undo_method(geometry_instance, "set_surface_override_material", spatial_editor->get_preview_material_surface(), spatial_editor->get_preview_reset_material());
+ editor_data->get_undo_redo().commit_action();
+ } else if (geometry_instance) {
+ editor_data->get_undo_redo().create_action(TTR("Set Material Override"));
+ editor_data->get_undo_redo().add_do_method(geometry_instance, "set_material_override", spatial_editor->get_preview_material());
+ editor_data->get_undo_redo().add_undo_method(geometry_instance, "set_material_override", spatial_editor->get_preview_reset_material());
+ editor_data->get_undo_redo().commit_action();
+ }
+
+ _remove_preview_material();
+ return;
+ }
+
+ _remove_preview_node();
Vector<String> error_files;
@@ -3968,7 +4096,7 @@ void Node3DEditorViewport::_perform_drop_data() {
bool Node3DEditorViewport::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const {
bool can_instantiate = false;
- if (!preview_node->is_inside_tree()) {
+ if (!preview_node->is_inside_tree() && spatial_editor->get_preview_material().is_null()) {
Dictionary d = p_data;
if (d.has("type") && (String(d["type"]) == "files")) {
Vector<String> files = d["files"];
@@ -3977,40 +4105,78 @@ bool Node3DEditorViewport::can_drop_data_fw(const Point2 &p_point, const Variant
ResourceLoader::get_recognized_extensions_for_type("PackedScene", &scene_extensions);
List<String> mesh_extensions;
ResourceLoader::get_recognized_extensions_for_type("Mesh", &mesh_extensions);
+ List<String> material_extensions;
+ ResourceLoader::get_recognized_extensions_for_type("Material", &material_extensions);
+ List<String> texture_extensions;
+ ResourceLoader::get_recognized_extensions_for_type("Texture", &texture_extensions);
for (int i = 0; i < files.size(); i++) {
// Check if dragged files with mesh or scene extension can be created at least once.
- if (mesh_extensions.find(files[i].get_extension()) || scene_extensions.find(files[i].get_extension())) {
+ if (mesh_extensions.find(files[i].get_extension()) ||
+ scene_extensions.find(files[i].get_extension()) ||
+ material_extensions.find(files[i].get_extension()) ||
+ texture_extensions.find(files[i].get_extension())) {
Ref<Resource> res = ResourceLoader::load(files[i]);
if (res.is_null()) {
continue;
}
Ref<PackedScene> scn = res;
+ Ref<Material> mat = res;
+ Ref<Texture2D> tex = res;
if (scn.is_valid()) {
Node *instantiated_scene = scn->instantiate(PackedScene::GEN_EDIT_STATE_INSTANCE);
if (!instantiated_scene) {
continue;
}
memdelete(instantiated_scene);
+ } else if (mat.is_valid()) {
+ Ref<BaseMaterial3D> base_mat = res;
+ Ref<ShaderMaterial> shader_mat = res;
+
+ if (base_mat.is_null() && !shader_mat.is_null()) {
+ break;
+ }
+
+ spatial_editor->set_preview_material(mat);
+ break;
+ } else if (tex.is_valid()) {
+ Ref<StandardMaterial3D> new_mat = memnew(StandardMaterial3D);
+ new_mat->set_texture(BaseMaterial3D::TEXTURE_ALBEDO, tex);
+
+ spatial_editor->set_preview_material(new_mat);
+ break;
+ } else {
+ continue;
}
can_instantiate = true;
break;
}
}
if (can_instantiate) {
- _create_preview(files);
+ _create_preview_node(files);
}
}
} else {
- can_instantiate = true;
+ if (preview_node->is_inside_tree()) {
+ can_instantiate = true;
+ }
}
if (can_instantiate) {
Transform3D global_transform = Transform3D(Basis(), _get_instance_position(p_point));
preview_node->set_global_transform(global_transform);
+ return true;
+ }
+
+ if (spatial_editor->get_preview_material().is_valid()) {
+ preview_material_label->show();
+ preview_material_label_desc->show();
+
+ ObjectID new_preview_material_target = _select_ray(p_point);
+ return _apply_preview_material(new_preview_material_target, p_point);
}
- return can_instantiate;
+ return false;
}
void Node3DEditorViewport::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) {
@@ -4048,7 +4214,7 @@ void Node3DEditorViewport::drop_data_fw(const Point2 &p_point, const Variant &p_
} else {
accept->set_text(TTR("Cannot drag and drop into multiple selected nodes."));
accept->popup_centered();
- _remove_preview();
+ _remove_preview_node();
return;
}
@@ -4699,6 +4865,23 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, int p
zoom_limit_label->hide();
surface->add_child(zoom_limit_label);
+ preview_material_label = memnew(Label);
+ preview_material_label->set_anchors_and_offsets_preset(LayoutPreset::PRESET_BOTTOM_LEFT);
+ preview_material_label->set_offset(Side::SIDE_TOP, -70 * EDSCALE);
+ preview_material_label->set_text(TTR("Overriding material..."));
+ preview_material_label->add_theme_color_override("font_color", Color(1, 1, 1, 1));
+ preview_material_label->hide();
+ surface->add_child(preview_material_label);
+
+ preview_material_label_desc = memnew(Label);
+ preview_material_label_desc->set_anchors_and_offsets_preset(LayoutPreset::PRESET_BOTTOM_LEFT);
+ preview_material_label_desc->set_offset(Side::SIDE_TOP, -50 * EDSCALE);
+ preview_material_label_desc->set_text(TTR("Drag and drop to override the material of any geometry node.\nHold Ctrl when dropping to override a specific surface."));
+ preview_material_label_desc->add_theme_color_override("font_color", Color(0.8, 0.8, 0.8, 1));
+ preview_material_label_desc->add_theme_constant_override("line_spacing", 0);
+ preview_material_label_desc->hide();
+ surface->add_child(preview_material_label_desc);
+
frame_time_gradient = memnew(Gradient);
// The color is set when the theme changes.
frame_time_gradient->add_point(0.5, Color());
@@ -8140,7 +8323,6 @@ void fragment() {
_preview_settings_changed();
}
}
-
Node3DEditor::~Node3DEditor() {
memdelete(preview_node);
}
diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h
index 244b461e16..4469271a38 100644
--- a/editor/plugins/node_3d_editor_plugin.h
+++ b/editor/plugins/node_3d_editor_plugin.h
@@ -227,6 +227,9 @@ private:
Label *locked_label = nullptr;
Label *zoom_limit_label = nullptr;
+ Label *preview_material_label = nullptr;
+ Label *preview_material_label_desc = nullptr;
+
VBoxContainer *top_right_vbox = nullptr;
ViewportRotationControl *rotation_control = nullptr;
Gradient *frame_time_gradient = nullptr;
@@ -244,7 +247,7 @@ private:
void _compute_edit(const Point2 &p_point);
void _clear_selected();
void _select_clicked(bool p_allow_locked);
- ObjectID _select_ray(const Point2 &p_pos);
+ ObjectID _select_ray(const Point2 &p_pos) const;
void _find_items_at_pos(const Point2 &p_pos, Vector<_RayResult> &r_results, bool p_include_locked);
Vector3 _get_ray_pos(const Vector2 &p_pos) const;
Vector3 _get_ray(const Vector2 &p_pos) const;
@@ -272,6 +275,7 @@ private:
float get_fov() const;
ObjectID clicked;
+ ObjectID material_target;
Vector<_RayResult> selection_results;
bool clicked_wants_append = false;
bool selection_in_progress = false;
@@ -399,8 +403,11 @@ private:
Node *_sanitize_preview_node(Node *p_node) const;
- void _create_preview(const Vector<String> &files) const;
- void _remove_preview();
+ void _create_preview_node(const Vector<String> &files) const;
+ void _remove_preview_node();
+ bool _apply_preview_material(ObjectID p_target, const Point2 &p_point) const;
+ void _reset_preview_material() const;
+ void _remove_preview_material();
bool _cyclical_dependency_exists(const String &p_target_scene_path, Node *p_desired_node);
bool _create_instance(Node *parent, String &path, const Point2 &p_point);
void _perform_drop_data();
@@ -593,6 +600,11 @@ private:
Node3D *preview_node = nullptr;
AABB preview_bounds;
+ Ref<Material> preview_material;
+ Ref<Material> preview_reset_material;
+ ObjectID preview_material_target;
+ int preview_material_surface = -1;
+
struct Gizmo {
bool visible = false;
real_t scale = 0;
@@ -850,6 +862,15 @@ public:
void set_can_preview(Camera3D *p_preview);
+ void set_preview_material(Ref<Material> p_material) { preview_material = p_material; }
+ Ref<Material> get_preview_material() { return preview_material; }
+ void set_preview_reset_material(Ref<Material> p_material) { preview_reset_material = p_material; }
+ Ref<Material> get_preview_reset_material() const { return preview_reset_material; }
+ void set_preview_material_target(ObjectID p_object_id) { preview_material_target = p_object_id; }
+ ObjectID get_preview_material_target() const { return preview_material_target; }
+ void set_preview_material_surface(int p_surface) { preview_material_surface = p_surface; }
+ int get_preview_material_surface() const { return preview_material_surface; }
+
Node3DEditorViewport *get_editor_viewport(int p_idx) {
ERR_FAIL_INDEX_V(p_idx, static_cast<int>(VIEWPORTS_COUNT), nullptr);
return viewports[p_idx];
diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp
index bdf566e991..54c72e4d27 100644
--- a/editor/plugins/shader_editor_plugin.cpp
+++ b/editor/plugins/shader_editor_plugin.cpp
@@ -309,9 +309,9 @@ void ShaderTextEditor::_check_shader_mode() {
}
}
-static ShaderLanguage::DataType _get_global_variable_type(const StringName &p_variable) {
- RS::GlobalVariableType gvt = RS::get_singleton()->global_variable_get_type(p_variable);
- return (ShaderLanguage::DataType)RS::global_variable_type_get_shader_datatype(gvt);
+static ShaderLanguage::DataType _get_global_shader_uniform_type(const StringName &p_variable) {
+ RS::GlobalShaderUniformType gvt = RS::get_singleton()->global_shader_uniform_get_type(p_variable);
+ return (ShaderLanguage::DataType)RS::global_shader_uniform_type_get_shader_datatype(gvt);
}
static String complete_from_path;
@@ -358,7 +358,7 @@ void ShaderTextEditor::_code_complete_script(const String &p_code, List<ScriptLa
ShaderLanguage sl;
String calltip;
ShaderLanguage::ShaderCompileInfo info;
- info.global_variable_type_func = _get_global_variable_type;
+ info.global_shader_uniform_type_func = _get_global_shader_uniform_type;
if (shader.is_null()) {
info.is_include = true;
@@ -448,7 +448,7 @@ void ShaderTextEditor::_validate_script() {
sl.set_warning_flags(flags);
ShaderLanguage::ShaderCompileInfo info;
- info.global_variable_type_func = _get_global_variable_type;
+ info.global_shader_uniform_type_func = _get_global_shader_uniform_type;
if (shader.is_null()) {
info.is_include = true;
diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
index 20e548acba..88bbd7f1dd 100644
--- a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
+++ b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
@@ -1822,7 +1822,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_unscaled_draw() {
Vector2i position = texture_region.get_center() + tile_set_atlas_source->get_tile_effective_texture_offset(coords, 0);
Transform2D xform = tile_atlas_control->get_parent_control()->get_transform();
- xform.translate(position);
+ xform.translate_local(position);
if (tools_button_group->get_pressed_button() == tool_select_button && selection.has({ coords, 0 })) {
continue;
@@ -1845,7 +1845,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_unscaled_draw() {
Vector2i position = texture_region.get_center() + tile_set_atlas_source->get_tile_effective_texture_offset(E.tile, 0);
Transform2D xform = tile_atlas_control->get_parent_control()->get_transform();
- xform.translate(position);
+ xform.translate_local(position);
TileMapCell cell;
cell.source_id = tile_set_atlas_source_id;
@@ -1989,7 +1989,7 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_unscaled_draw() {
Vector2 position = rect.get_center();
Transform2D xform = alternative_tiles_control->get_parent_control()->get_transform();
- xform.translate(position);
+ xform.translate_local(position);
if (tools_button_group->get_pressed_button() == tool_select_button && selection.has({ coords, alternative_tile })) {
continue;
@@ -2013,7 +2013,7 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_unscaled_draw() {
Vector2 position = rect.get_center();
Transform2D xform = alternative_tiles_control->get_parent_control()->get_transform();
- xform.translate(position);
+ xform.translate_local(position);
TileMapCell cell;
cell.source_id = tile_set_atlas_source_id;
diff --git a/editor/plugins/tiles/tiles_editor_plugin.cpp b/editor/plugins/tiles/tiles_editor_plugin.cpp
index 97553578ba..65dee0df1f 100644
--- a/editor/plugins/tiles/tiles_editor_plugin.cpp
+++ b/editor/plugins/tiles/tiles_editor_plugin.cpp
@@ -155,6 +155,9 @@ void TilesEditorPlugin::_update_editors() {
// Update the viewport.
CanvasItemEditor::get_singleton()->update_viewport();
+ // Make sure the tile set editor is visible if we have one assigned.
+ tileset_editor_button->set_visible(is_visible && tile_set.is_valid());
+
// Update visibility of bottom panel buttons.
if (tileset_editor_button->is_pressed() && !tile_set.is_valid()) {
if (tile_map) {
@@ -181,12 +184,14 @@ void TilesEditorPlugin::_notification(int p_what) {
}
void TilesEditorPlugin::make_visible(bool p_visible) {
- if (p_visible) {
+ is_visible = p_visible;
+
+ if (is_visible) {
// Disable and hide invalid editors.
TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
tileset_editor_button->set_visible(tile_set.is_valid());
tilemap_editor_button->set_visible(tile_map);
- if (tile_map) {
+ if (tile_map && !is_editing_tile_set) {
EditorNode::get_singleton()->make_bottom_panel_item_visible(tilemap_editor);
} else {
EditorNode::get_singleton()->make_bottom_panel_item_visible(tileset_editor);
@@ -345,6 +350,8 @@ void TilesEditorPlugin::edit(Object *p_object) {
// Update edited objects.
tile_set = Ref<TileSet>();
+ is_editing_tile_set = false;
+
if (p_object) {
if (p_object->is_class("TileMap")) {
tile_map_id = p_object->get_instance_id();
@@ -359,6 +366,7 @@ void TilesEditorPlugin::edit(Object *p_object) {
tile_map_id = ObjectID();
}
}
+ is_editing_tile_set = true;
EditorNode::get_singleton()->make_bottom_panel_item_visible(tileset_editor);
}
}
diff --git a/editor/plugins/tiles/tiles_editor_plugin.h b/editor/plugins/tiles/tiles_editor_plugin.h
index a22e782b34..b1fe6f8df6 100644
--- a/editor/plugins/tiles/tiles_editor_plugin.h
+++ b/editor/plugins/tiles/tiles_editor_plugin.h
@@ -53,9 +53,12 @@ public:
};
private:
+ bool is_visible = false;
+
bool tile_map_changed_needs_update = false;
ObjectID tile_map_id;
Ref<TileSet> tile_set;
+ bool is_editing_tile_set = false;
Button *tilemap_editor_button = nullptr;
TileMapEditor *tilemap_editor = nullptr;
diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp
index 69a125a029..d6d45b8210 100644
--- a/editor/plugins/visual_shader_editor_plugin.cpp
+++ b/editor/plugins/visual_shader_editor_plugin.cpp
@@ -4563,9 +4563,9 @@ void VisualShaderEditor::_preview_size_changed() {
preview_vbox->set_custom_minimum_size(preview_window->get_size());
}
-static ShaderLanguage::DataType _get_global_variable_type(const StringName &p_variable) {
- RS::GlobalVariableType gvt = RS::get_singleton()->global_variable_get_type(p_variable);
- return (ShaderLanguage::DataType)RS::global_variable_type_get_shader_datatype(gvt);
+static ShaderLanguage::DataType _get_global_shader_uniform_type(const StringName &p_variable) {
+ RS::GlobalShaderUniformType gvt = RS::get_singleton()->global_shader_uniform_get_type(p_variable);
+ return (ShaderLanguage::DataType)RS::global_shader_uniform_type_get_shader_datatype(gvt);
}
void VisualShaderEditor::_update_preview() {
@@ -4582,7 +4582,7 @@ void VisualShaderEditor::_update_preview() {
info.functions = ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(visual_shader->get_mode()));
info.render_modes = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(visual_shader->get_mode()));
info.shader_types = ShaderTypes::get_singleton()->get_types();
- info.global_variable_type_func = _get_global_variable_type;
+ info.global_shader_uniform_type_func = _get_global_shader_uniform_type;
ShaderLanguage sl;
diff --git a/editor/project_converter_3_to_4.cpp b/editor/project_converter_3_to_4.cpp
index 6437e19404..97013da05e 100644
--- a/editor/project_converter_3_to_4.cpp
+++ b/editor/project_converter_3_to_4.cpp
@@ -120,7 +120,7 @@ static const char *enum_renames[][2] = {
{ "JOINT_PIN", "JOINT_TYPE_PIN" }, // PhysicsServer2D
{ "JOINT_SLIDER", "JOINT_TYPE_SLIDER" }, // PhysicsServer3D
{ "KEY_CONTROL", "KEY_CTRL" }, // Globals
- { "LOOP_PING_PONG", "LOOP_PINGPONG" }, //AudioStreamSample
+ { "LOOP_PING_PONG", "LOOP_PINGPONG" }, // AudioStreamWAV
{ "MATH_RAND", "MATH_RANDF_RANGE" }, // VisualScriptBuiltinFunc
{ "MATH_RANDOM", "MATH_RANDI_RANGE" }, // VisualScriptBuiltinFunc
{ "MATH_STEPIFY", "MATH_STEP_DECIMALS" }, // VisualScriptBuiltinFunc
@@ -1250,7 +1250,9 @@ static const char *class_renames[][2] = {
{ "AnimatedSprite", "AnimatedSprite2D" },
{ "AnimationTreePlayer", "AnimationTree" },
{ "Area", "Area3D" }, // Be careful, this will be used everywhere
+ { "AudioStreamOGGVorbis", "AudioStreamOggVorbis" },
{ "AudioStreamRandomPitch", "AudioStreamRandomizer" },
+ { "AudioStreamSample", "AudioStreamWAV" },
{ "BakedLightmap", "LightmapGI" },
{ "BakedLightmapData", "LightmapGIData" },
{ "BitmapFont", "FontFile" },
diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp
index 077dfc60c0..be1ad1ca9c 100644
--- a/editor/project_settings_editor.cpp
+++ b/editor/project_settings_editor.cpp
@@ -669,10 +669,10 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
autoload_settings->connect("autoload_changed", callable_mp(this, &ProjectSettingsEditor::queue_save));
tab_container->add_child(autoload_settings);
- shaders_global_variables_editor = memnew(ShaderGlobalsEditor);
- shaders_global_variables_editor->set_name(TTR("Shader Globals"));
- shaders_global_variables_editor->connect("globals_changed", callable_mp(this, &ProjectSettingsEditor::queue_save));
- tab_container->add_child(shaders_global_variables_editor);
+ shaders_global_shader_uniforms_editor = memnew(ShaderGlobalsEditor);
+ shaders_global_shader_uniforms_editor->set_name(TTR("Shader Globals"));
+ shaders_global_shader_uniforms_editor->connect("globals_changed", callable_mp(this, &ProjectSettingsEditor::queue_save));
+ tab_container->add_child(shaders_global_shader_uniforms_editor);
plugin_settings = memnew(EditorPluginSettings);
plugin_settings->set_name(TTR("Plugins"));
diff --git a/editor/project_settings_editor.h b/editor/project_settings_editor.h
index 24d61db443..455aaae11c 100644
--- a/editor/project_settings_editor.h
+++ b/editor/project_settings_editor.h
@@ -55,7 +55,7 @@ class ProjectSettingsEditor : public AcceptDialog {
ActionMapEditor *action_map_editor = nullptr;
LocalizationEditor *localization_editor = nullptr;
EditorAutoloadSettings *autoload_settings = nullptr;
- ShaderGlobalsEditor *shaders_global_variables_editor = nullptr;
+ ShaderGlobalsEditor *shaders_global_shader_uniforms_editor = nullptr;
EditorPluginSettings *plugin_settings = nullptr;
LineEdit *search_box = nullptr;
diff --git a/editor/shader_globals_editor.cpp b/editor/shader_globals_editor.cpp
index 26bd3a5979..5bf7e958f6 100644
--- a/editor/shader_globals_editor.cpp
+++ b/editor/shader_globals_editor.cpp
@@ -79,7 +79,7 @@ protected:
}
bool _set(const StringName &p_name, const Variant &p_value) {
- Variant existing = RS::get_singleton()->global_variable_get(p_name);
+ Variant existing = RS::get_singleton()->global_shader_uniform_get(p_name);
if (existing.get_type() == Variant::NIL) {
return false;
@@ -88,9 +88,9 @@ protected:
UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
undo_redo->create_action(TTR("Set Shader Global Variable"));
- undo_redo->add_do_method(RS::get_singleton(), "global_variable_set", p_name, p_value);
- undo_redo->add_undo_method(RS::get_singleton(), "global_variable_set", p_name, existing);
- RS::GlobalVariableType type = RS::get_singleton()->global_variable_get_type(p_name);
+ undo_redo->add_do_method(RS::get_singleton(), "global_shader_uniform_set", p_name, p_value);
+ undo_redo->add_undo_method(RS::get_singleton(), "global_shader_uniform_set", p_name, existing);
+ RS::GlobalShaderUniformType type = RS::get_singleton()->global_shader_uniform_get_type(p_name);
Dictionary gv;
gv["type"] = global_var_type_names[type];
if (type >= RS::GLOBAL_VAR_TYPE_SAMPLER2D) {
@@ -117,17 +117,17 @@ protected:
}
bool _get(const StringName &p_name, Variant &r_ret) const {
- r_ret = RS::get_singleton()->global_variable_get(p_name);
+ r_ret = RS::get_singleton()->global_shader_uniform_get(p_name);
return r_ret.get_type() != Variant::NIL;
}
void _get_property_list(List<PropertyInfo> *p_list) const {
Vector<StringName> variables;
- variables = RS::get_singleton()->global_variable_get_list();
+ variables = RS::get_singleton()->global_shader_uniform_get_list();
for (int i = 0; i < variables.size(); i++) {
PropertyInfo pinfo;
pinfo.name = variables[i];
- switch (RS::get_singleton()->global_variable_get_type(variables[i])) {
+ switch (RS::get_singleton()->global_shader_uniform_get_type(variables[i])) {
case RS::GLOBAL_VAR_TYPE_BOOL: {
pinfo.type = Variant::BOOL;
} break;
@@ -241,7 +241,7 @@ public:
}
};
-static Variant create_var(RS::GlobalVariableType p_type) {
+static Variant create_var(RS::GlobalShaderUniformType p_type) {
switch (p_type) {
case RS::GLOBAL_VAR_TYPE_BOOL: {
return false;
@@ -376,12 +376,12 @@ static Variant create_var(RS::GlobalVariableType p_type) {
void ShaderGlobalsEditor::_variable_added() {
String var = variable_name->get_text().strip_edges();
if (var.is_empty() || !var.is_valid_identifier()) {
- EditorNode::get_singleton()->show_warning(TTR("Please specify a valid variable identifier name."));
+ EditorNode::get_singleton()->show_warning(TTR("Please specify a valid shader uniform identifier name."));
return;
}
- if (RenderingServer::get_singleton()->global_variable_get(var).get_type() != Variant::NIL) {
- EditorNode::get_singleton()->show_warning(vformat(TTR("Global variable '%s' already exists'"), var));
+ if (RenderingServer::get_singleton()->global_shader_uniform_get(var).get_type() != Variant::NIL) {
+ EditorNode::get_singleton()->show_warning(vformat(TTR("Global shader uniform '%s' already exists'"), var));
return;
}
@@ -395,11 +395,11 @@ void ShaderGlobalsEditor::_variable_added() {
UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
- Variant value = create_var(RS::GlobalVariableType(variable_type->get_selected()));
+ Variant value = create_var(RS::GlobalShaderUniformType(variable_type->get_selected()));
- undo_redo->create_action(TTR("Add Shader Global Variable"));
- undo_redo->add_do_method(RS::get_singleton(), "global_variable_add", var, RS::GlobalVariableType(variable_type->get_selected()), value);
- undo_redo->add_undo_method(RS::get_singleton(), "global_variable_remove", var);
+ undo_redo->create_action(TTR("Add Shader Global Uniform"));
+ undo_redo->add_do_method(RS::get_singleton(), "global_shader_uniform_add", var, RS::GlobalShaderUniformType(variable_type->get_selected()), value);
+ undo_redo->add_undo_method(RS::get_singleton(), "global_shader_uniform_remove", var);
Dictionary gv;
gv["type"] = global_var_type_names[variable_type->get_selected()];
gv["value"] = value;
@@ -414,9 +414,9 @@ void ShaderGlobalsEditor::_variable_added() {
void ShaderGlobalsEditor::_variable_deleted(const String &p_variable) {
UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
- undo_redo->create_action(TTR("Add Shader Global Variable"));
- undo_redo->add_do_method(RS::get_singleton(), "global_variable_remove", p_variable);
- undo_redo->add_undo_method(RS::get_singleton(), "global_variable_add", p_variable, RS::get_singleton()->global_variable_get_type(p_variable), RS::get_singleton()->global_variable_get(p_variable));
+ undo_redo->create_action(TTR("Add Shader Global Uniform"));
+ undo_redo->add_do_method(RS::get_singleton(), "global_shader_uniform_remove", p_variable);
+ undo_redo->add_undo_method(RS::get_singleton(), "global_shader_uniform_add", p_variable, RS::get_singleton()->global_shader_uniform_get_type(p_variable), RS::get_singleton()->global_shader_uniform_get(p_variable));
undo_redo->add_do_property(ProjectSettings::get_singleton(), "shader_globals/" + p_variable, Variant());
undo_redo->add_undo_property(ProjectSettings::get_singleton(), "shader_globals/" + p_variable, ProjectSettings::get_singleton()->get("shader_globals/" + p_variable));
diff --git a/main/main.cpp b/main/main.cpp
index 3f9fe34545..a9037806bf 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -343,6 +343,7 @@ void Main::print_help(const char *p_binary) {
OS::get_singleton()->print(" --resolution <W>x<H> Request window resolution.\n");
OS::get_singleton()->print(" --position <X>,<Y> Request window position.\n");
OS::get_singleton()->print(" --single-window Use a single window (no separate subwindows).\n");
+ OS::get_singleton()->print(" --xr-mode <mode> Select XR mode (default/off/on).\n");
OS::get_singleton()->print("\n");
OS::get_singleton()->print("Debug options:\n");
@@ -1181,6 +1182,25 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
OS::get_singleton()->disable_crash_handler();
} else if (I->get() == "--skip-breakpoints") {
skip_breakpoints = true;
+ } else if (I->get() == "--xr-mode") {
+ if (I->next()) {
+ String xr_mode = I->next()->get().to_lower();
+ N = I->next()->next();
+ if (xr_mode == "default") {
+ XRServer::set_xr_mode(XRServer::XRMODE_DEFAULT);
+ } else if (xr_mode == "off") {
+ XRServer::set_xr_mode(XRServer::XRMODE_OFF);
+ } else if (xr_mode == "on") {
+ XRServer::set_xr_mode(XRServer::XRMODE_ON);
+ } else {
+ OS::get_singleton()->print("Unknown --xr-mode argument \"%s\", aborting.\n", xr_mode.ascii().get_data());
+ goto error;
+ }
+ } else {
+ OS::get_singleton()->print("Missing --xr-mode argument, aborting.\n");
+ goto error;
+ }
+
} else {
main_args.push_back(I->get());
}
@@ -2078,7 +2098,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
// able to load resources, load the global shader variables.
// If running on editor, don't load the textures because the editor
// may want to import them first. Editor will reload those later.
- rendering_server->global_variables_load_settings(!editor);
+ rendering_server->global_shader_uniforms_load_settings(!editor);
}
_start_success = true;
@@ -2991,7 +3011,7 @@ void Main::cleanup(bool p_force) {
RenderingServer::get_singleton()->sync();
//clear global shader variables before scene and other graphics stuff are deinitialized.
- rendering_server->global_variables_clear();
+ rendering_server->global_shader_uniforms_clear();
if (xr_server) {
// Now that we're unregistering properly in plugins we need to keep access to xr_server for a little longer
diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp
index 0f09eb2020..56be4e65f0 100644
--- a/modules/csg/csg_shape.cpp
+++ b/modules/csg/csg_shape.cpp
@@ -1858,7 +1858,7 @@ CSGBrush *CSGPolygon3D::_build_brush() {
}
Transform3D facing = Transform3D().looking_at(direction, current_up);
- current_xform = base_xform.translated(current_point) * facing;
+ current_xform = base_xform.translated_local(current_point) * facing;
}
// Create the mesh.
@@ -1897,7 +1897,7 @@ CSGBrush *CSGPolygon3D::_build_brush() {
switch (mode) {
case MODE_DEPTH: {
- current_xform.translate(Vector3(0, 0, -depth));
+ current_xform.translate_local(Vector3(0, 0, -depth));
} break;
case MODE_SPIN: {
current_xform.rotate(Vector3(0, 1, 0), spin_step);
@@ -1945,7 +1945,7 @@ CSGBrush *CSGPolygon3D::_build_brush() {
}
Transform3D facing = Transform3D().looking_at(direction, current_up);
- current_xform = base_xform.translated(current_point) * facing;
+ current_xform = base_xform.translated_local(current_point) * facing;
} break;
}
diff --git a/modules/enet/enet_multiplayer_peer.cpp b/modules/enet/enet_multiplayer_peer.cpp
index cd94cc9425..dfdd08c9f4 100644
--- a/modules/enet/enet_multiplayer_peer.cpp
+++ b/modules/enet/enet_multiplayer_peer.cpp
@@ -441,15 +441,15 @@ Error ENetMultiplayerPeer::put_packet(const uint8_t *p_buffer, int p_buffer_size
channel = SYSCH_MAX + transfer_channel - 1;
} else {
switch (get_transfer_mode()) {
- case Multiplayer::TRANSFER_MODE_UNRELIABLE: {
+ case TRANSFER_MODE_UNRELIABLE: {
packet_flags = ENET_PACKET_FLAG_UNSEQUENCED | ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT;
channel = SYSCH_UNRELIABLE;
} break;
- case Multiplayer::TRANSFER_MODE_UNRELIABLE_ORDERED: {
+ case TRANSFER_MODE_UNRELIABLE_ORDERED: {
packet_flags = ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT;
channel = SYSCH_UNRELIABLE;
} break;
- case Multiplayer::TRANSFER_MODE_RELIABLE: {
+ case TRANSFER_MODE_RELIABLE: {
packet_flags = ENET_PACKET_FLAG_RELIABLE;
channel = SYSCH_RELIABLE;
} break;
diff --git a/modules/enet/enet_multiplayer_peer.h b/modules/enet/enet_multiplayer_peer.h
index 131aa04df1..3152068d46 100644
--- a/modules/enet/enet_multiplayer_peer.h
+++ b/modules/enet/enet_multiplayer_peer.h
@@ -32,7 +32,7 @@
#define ENET_MULTIPLAYER_PEER_H
#include "core/crypto/crypto.h"
-#include "core/multiplayer/multiplayer_peer.h"
+#include "scene/main/multiplayer_peer.h"
#include "enet_connection.h"
#include <enet/enet.h>
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp
index a34bf6ef82..4a3dbce2b9 100644
--- a/modules/gdscript/gdscript.cpp
+++ b/modules/gdscript/gdscript.cpp
@@ -954,8 +954,8 @@ void GDScript::get_members(HashSet<StringName> *p_members) {
}
}
-const Vector<Multiplayer::RPCConfig> GDScript::get_rpc_methods() const {
- return rpc_functions;
+const Variant GDScript::get_rpc_config() const {
+ return rpc_config;
}
Variant GDScript::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
@@ -1212,9 +1212,9 @@ void GDScript::_save_orphaned_subclasses() {
void GDScript::_init_rpc_methods_properties() {
// Copy the base rpc methods so we don't mask their IDs.
- rpc_functions.clear();
+ rpc_config.clear();
if (base.is_valid()) {
- rpc_functions = base->rpc_functions;
+ rpc_config = base->rpc_config.duplicate();
}
GDScript *cscript = this;
@@ -1222,12 +1222,9 @@ void GDScript::_init_rpc_methods_properties() {
while (cscript) {
// RPC Methods
for (KeyValue<StringName, GDScriptFunction *> &E : cscript->member_functions) {
- Multiplayer::RPCConfig config = E.value->get_rpc_config();
- if (config.rpc_mode != Multiplayer::RPC_MODE_DISABLED) {
- config.name = E.value->get_name();
- if (rpc_functions.find(config) == -1) {
- rpc_functions.push_back(config);
- }
+ Variant config = E.value->get_rpc_config();
+ if (config.get_type() != Variant::NIL) {
+ rpc_config[E.value->get_name()] = config;
}
}
@@ -1241,9 +1238,6 @@ void GDScript::_init_rpc_methods_properties() {
cscript = nullptr;
}
}
-
- // Sort so we are 100% that they are always the same.
- rpc_functions.sort_custom<Multiplayer::SortRPCConfig>();
}
GDScript::~GDScript() {
@@ -1408,9 +1402,7 @@ bool GDScriptInstance::get(const StringName &p_name, Variant &r_ret) const {
while (sl) {
HashMap<StringName, GDScriptFunction *>::ConstIterator E = sl->member_functions.find(p_name);
if (E) {
- Multiplayer::RPCConfig config;
- config.name = p_name;
- if (sptr->rpc_functions.find(config) != -1) {
+ if (sptr->rpc_config.has(p_name)) {
r_ret = Callable(memnew(GDScriptRPCCallable(this->owner, E->key)));
} else {
r_ret = Callable(this->owner, E->key);
@@ -1629,15 +1621,13 @@ ScriptLanguage *GDScriptInstance::get_language() {
return GDScriptLanguage::get_singleton();
}
-const Vector<Multiplayer::RPCConfig> GDScriptInstance::get_rpc_methods() const {
- return script->get_rpc_methods();
+const Variant GDScriptInstance::get_rpc_config() const {
+ return script->get_rpc_config();
}
void GDScriptInstance::reload_members() {
#ifdef DEBUG_ENABLED
- members.resize(script->member_indices.size()); //resize
-
Vector<Variant> new_members;
new_members.resize(script->member_indices.size());
@@ -1649,6 +1639,8 @@ void GDScriptInstance::reload_members() {
}
}
+ members.resize(new_members.size()); //resize
+
//apply
members = new_members;
diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h
index e9a206f48b..47de3ad088 100644
--- a/modules/gdscript/gdscript.h
+++ b/modules/gdscript/gdscript.h
@@ -87,7 +87,7 @@ class GDScript : public Script {
HashMap<StringName, MemberInfo> member_indices; //members are just indices to the instantiated script.
HashMap<StringName, Ref<GDScript>> subclasses;
HashMap<StringName, Vector<StringName>> _signals;
- Vector<Multiplayer::RPCConfig> rpc_functions;
+ Dictionary rpc_config;
#ifdef TOOLS_ENABLED
@@ -250,7 +250,7 @@ public:
virtual void get_constants(HashMap<StringName, Variant> *p_constants) override;
virtual void get_members(HashSet<StringName> *p_members) override;
- virtual const Vector<Multiplayer::RPCConfig> get_rpc_methods() const override;
+ virtual const Variant get_rpc_config() const override;
#ifdef TOOLS_ENABLED
virtual bool is_placeholder_fallback_enabled() const override { return placeholder_fallback_enabled; }
@@ -304,7 +304,7 @@ public:
void reload_members();
- virtual const Vector<Multiplayer::RPCConfig> get_rpc_methods() const;
+ virtual const Variant get_rpc_config() const;
GDScriptInstance();
~GDScriptInstance();
diff --git a/modules/gdscript/gdscript_byte_codegen.cpp b/modules/gdscript/gdscript_byte_codegen.cpp
index 8e4ca44e81..fa158591fd 100644
--- a/modules/gdscript/gdscript_byte_codegen.cpp
+++ b/modules/gdscript/gdscript_byte_codegen.cpp
@@ -158,7 +158,7 @@ void GDScriptByteCodeGenerator::end_parameters() {
function->default_arguments.reverse();
}
-void GDScriptByteCodeGenerator::write_start(GDScript *p_script, const StringName &p_function_name, bool p_static, Multiplayer::RPCConfig p_rpc_config, const GDScriptDataType &p_return_type) {
+void GDScriptByteCodeGenerator::write_start(GDScript *p_script, const StringName &p_function_name, bool p_static, Variant p_rpc_config, const GDScriptDataType &p_return_type) {
function = memnew(GDScriptFunction);
debug_stack = EngineDebugger::is_active();
diff --git a/modules/gdscript/gdscript_byte_codegen.h b/modules/gdscript/gdscript_byte_codegen.h
index ffc3178c83..7dd51845df 100644
--- a/modules/gdscript/gdscript_byte_codegen.h
+++ b/modules/gdscript/gdscript_byte_codegen.h
@@ -419,7 +419,7 @@ public:
virtual void start_block() override;
virtual void end_block() override;
- virtual void write_start(GDScript *p_script, const StringName &p_function_name, bool p_static, Multiplayer::RPCConfig p_rpc_config, const GDScriptDataType &p_return_type) override;
+ virtual void write_start(GDScript *p_script, const StringName &p_function_name, bool p_static, Variant p_rpc_config, const GDScriptDataType &p_return_type) override;
virtual GDScriptFunction *write_end() override;
#ifdef DEBUG_ENABLED
diff --git a/modules/gdscript/gdscript_codegen.h b/modules/gdscript/gdscript_codegen.h
index 7b5f133ec5..5972481c3a 100644
--- a/modules/gdscript/gdscript_codegen.h
+++ b/modules/gdscript/gdscript_codegen.h
@@ -31,7 +31,6 @@
#ifndef GDSCRIPT_CODEGEN_H
#define GDSCRIPT_CODEGEN_H
-#include "core/multiplayer/multiplayer.h"
#include "core/string/string_name.h"
#include "core/variant/variant.h"
#include "gdscript_function.h"
@@ -80,7 +79,7 @@ public:
virtual void start_block() = 0;
virtual void end_block() = 0;
- virtual void write_start(GDScript *p_script, const StringName &p_function_name, bool p_static, Multiplayer::RPCConfig p_rpc_config, const GDScriptDataType &p_return_type) = 0;
+ virtual void write_start(GDScript *p_script, const StringName &p_function_name, bool p_static, Variant p_rpc_config, const GDScriptDataType &p_return_type) = 0;
virtual GDScriptFunction *write_end() = 0;
#ifdef DEBUG_ENABLED
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index e36252ada5..00e8223b9a 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -1975,7 +1975,7 @@ GDScriptFunction *GDScriptCompiler::_parse_function(Error &r_error, GDScript *p_
StringName func_name;
bool is_static = false;
- Multiplayer::RPCConfig rpc_config;
+ Variant rpc_config;
GDScriptDataType return_type;
return_type.has_type = true;
return_type.kind = GDScriptDataType::BUILTIN;
diff --git a/modules/gdscript/gdscript_function.h b/modules/gdscript/gdscript_function.h
index 53c75648a0..e44038d6da 100644
--- a/modules/gdscript/gdscript_function.h
+++ b/modules/gdscript/gdscript_function.h
@@ -477,7 +477,7 @@ private:
int _initial_line = 0;
bool _static = false;
- Multiplayer::RPCConfig rpc_config;
+ Variant rpc_config;
GDScript *_script = nullptr;
@@ -599,7 +599,7 @@ public:
void disassemble(const Vector<String> &p_code_lines) const;
#endif
- _FORCE_INLINE_ Multiplayer::RPCConfig get_rpc_config() const { return rpc_config; }
+ _FORCE_INLINE_ const Variant get_rpc_config() const { return rpc_config; }
GDScriptFunction();
~GDScriptFunction();
};
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index e8fa2981ba..6f5397e1a3 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -35,6 +35,7 @@
#include "core/io/resource_loader.h"
#include "core/math/math_defs.h"
#include "gdscript.h"
+#include "scene/main/multiplayer_api.h"
#ifdef DEBUG_ENABLED
#include "core/os/os.h"
@@ -145,7 +146,7 @@ GDScriptParser::GDScriptParser() {
// Warning annotations.
register_annotation(MethodInfo("@warning_ignore", PropertyInfo(Variant::STRING, "warning")), AnnotationInfo::CLASS | AnnotationInfo::VARIABLE | AnnotationInfo::SIGNAL | AnnotationInfo::CONSTANT | AnnotationInfo::FUNCTION | AnnotationInfo::STATEMENT, &GDScriptParser::warning_annotations, varray(), true);
// Networking.
- register_annotation(MethodInfo("@rpc", PropertyInfo(Variant::STRING, "mode"), PropertyInfo(Variant::STRING, "sync"), PropertyInfo(Variant::STRING, "transfer_mode"), PropertyInfo(Variant::INT, "transfer_channel")), AnnotationInfo::FUNCTION, &GDScriptParser::network_annotations<Multiplayer::RPC_MODE_AUTHORITY>, varray("", "", "", 0), true);
+ register_annotation(MethodInfo("@rpc", PropertyInfo(Variant::STRING, "mode"), PropertyInfo(Variant::STRING, "sync"), PropertyInfo(Variant::STRING, "transfer_mode"), PropertyInfo(Variant::INT, "transfer_channel")), AnnotationInfo::FUNCTION, &GDScriptParser::rpc_annotation, varray("", "", "", 0), true);
}
GDScriptParser::~GDScriptParser() {
@@ -3867,16 +3868,21 @@ bool GDScriptParser::warning_annotations(const AnnotationNode *p_annotation, Nod
#endif // DEBUG_ENABLED
}
-template <Multiplayer::RPCMode t_mode>
-bool GDScriptParser::network_annotations(const AnnotationNode *p_annotation, Node *p_node) {
- ERR_FAIL_COND_V_MSG(p_node->type != Node::VARIABLE && p_node->type != Node::FUNCTION, false, vformat(R"("%s" annotation can only be applied to variables and functions.)", p_annotation->name));
+bool GDScriptParser::rpc_annotation(const AnnotationNode *p_annotation, Node *p_node) {
+ ERR_FAIL_COND_V_MSG(p_node->type != Node::FUNCTION, false, vformat(R"("%s" annotation can only be applied to functions.)", p_annotation->name));
- Multiplayer::RPCConfig rpc_config;
- rpc_config.rpc_mode = t_mode;
+ FunctionNode *function = static_cast<FunctionNode *>(p_node);
+ if (function->rpc_config.get_type() != Variant::NIL) {
+ push_error(R"(RPC annotations can only be used once per function.)", p_annotation);
+ return false;
+ }
+
+ Dictionary rpc_config;
+ rpc_config["rpc_mode"] = MultiplayerAPI::RPC_MODE_AUTHORITY;
if (p_annotation->resolved_arguments.size()) {
int last = p_annotation->resolved_arguments.size() - 1;
if (p_annotation->resolved_arguments[last].get_type() == Variant::INT) {
- rpc_config.channel = p_annotation->resolved_arguments[last].operator int();
+ rpc_config["channel"] = p_annotation->resolved_arguments[last].operator int();
last -= 1;
}
if (last > 3) {
@@ -3886,37 +3892,25 @@ bool GDScriptParser::network_annotations(const AnnotationNode *p_annotation, Nod
for (int i = last; i >= 0; i--) {
String mode = p_annotation->resolved_arguments[i].operator String();
if (mode == "any_peer") {
- rpc_config.rpc_mode = Multiplayer::RPC_MODE_ANY_PEER;
+ rpc_config["rpc_mode"] = MultiplayerAPI::RPC_MODE_ANY_PEER;
} else if (mode == "authority") {
- rpc_config.rpc_mode = Multiplayer::RPC_MODE_AUTHORITY;
+ rpc_config["rpc_mode"] = MultiplayerAPI::RPC_MODE_AUTHORITY;
} else if (mode == "call_local") {
- rpc_config.call_local = true;
+ rpc_config["call_local"] = true;
} else if (mode == "call_remote") {
- rpc_config.call_local = false;
+ rpc_config["call_local"] = false;
} else if (mode == "reliable") {
- rpc_config.transfer_mode = Multiplayer::TRANSFER_MODE_RELIABLE;
+ rpc_config["transfer_mode"] = MultiplayerPeer::TRANSFER_MODE_RELIABLE;
} else if (mode == "unreliable") {
- rpc_config.transfer_mode = Multiplayer::TRANSFER_MODE_UNRELIABLE;
+ rpc_config["transfer_mode"] = MultiplayerPeer::TRANSFER_MODE_UNRELIABLE;
} else if (mode == "unreliable_ordered") {
- rpc_config.transfer_mode = Multiplayer::TRANSFER_MODE_UNRELIABLE_ORDERED;
+ rpc_config["transfer_mode"] = MultiplayerPeer::TRANSFER_MODE_UNRELIABLE_ORDERED;
} else {
push_error(R"(Invalid RPC argument. Must be one of: 'call_local'/'call_remote' (local calls), 'any_peer'/'authority' (permission), 'reliable'/'unreliable'/'unreliable_ordered' (transfer mode).)", p_annotation);
}
}
}
- switch (p_node->type) {
- case Node::FUNCTION: {
- FunctionNode *function = static_cast<FunctionNode *>(p_node);
- if (function->rpc_config.rpc_mode != Multiplayer::RPC_MODE_DISABLED) {
- push_error(R"(RPC annotations can only be used once per function.)", p_annotation);
- return false;
- }
- function->rpc_config = rpc_config;
- break;
- }
- default:
- return false; // Unreachable.
- }
+ function->rpc_config = rpc_config;
return true;
}
diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h
index 9c97f98fbc..d4efab173b 100644
--- a/modules/gdscript/gdscript_parser.h
+++ b/modules/gdscript/gdscript_parser.h
@@ -32,7 +32,6 @@
#define GDSCRIPT_PARSER_H
#include "core/io/resource.h"
-#include "core/multiplayer/multiplayer.h"
#include "core/object/ref_counted.h"
#include "core/object/script_language.h"
#include "core/string/string_name.h"
@@ -750,7 +749,7 @@ public:
SuiteNode *body = nullptr;
bool is_static = false;
bool is_coroutine = false;
- Multiplayer::RPCConfig rpc_config;
+ Variant rpc_config;
MethodInfo info;
LambdaNode *source_lambda = nullptr;
#ifdef TOOLS_ENABLED
@@ -1371,8 +1370,7 @@ private:
template <PropertyUsageFlags t_usage>
bool export_group_annotations(const AnnotationNode *p_annotation, Node *p_target);
bool warning_annotations(const AnnotationNode *p_annotation, Node *p_target);
- template <Multiplayer::RPCMode t_mode>
- bool network_annotations(const AnnotationNode *p_annotation, Node *p_target);
+ bool rpc_annotation(const AnnotationNode *p_annotation, Node *p_target);
// Statements.
Node *parse_statement();
VariableNode *parse_variable();
diff --git a/modules/gdscript/gdscript_rpc_callable.cpp b/modules/gdscript/gdscript_rpc_callable.cpp
index 63ebd8acf5..4e12419357 100644
--- a/modules/gdscript/gdscript_rpc_callable.cpp
+++ b/modules/gdscript/gdscript_rpc_callable.cpp
@@ -76,11 +76,11 @@ GDScriptRPCCallable::GDScriptRPCCallable(Object *p_object, const StringName &p_m
ERR_FAIL_COND_MSG(!node, "RPC can only be defined on class that extends Node.");
}
-void GDScriptRPCCallable::rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const {
+Error GDScriptRPCCallable::rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const {
if (unlikely(!node)) {
r_call_error.error = Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL;
- return;
+ return ERR_UNCONFIGURED;
}
r_call_error.error = Callable::CallError::CALL_OK;
- node->rpcp(p_peer_id, method, p_arguments, p_argcount);
+ return node->rpcp(p_peer_id, method, p_arguments, p_argcount);
}
diff --git a/modules/gdscript/gdscript_rpc_callable.h b/modules/gdscript/gdscript_rpc_callable.h
index c8a91d6259..83b9c7e2df 100644
--- a/modules/gdscript/gdscript_rpc_callable.h
+++ b/modules/gdscript/gdscript_rpc_callable.h
@@ -52,7 +52,7 @@ public:
CompareLessFunc get_compare_less_func() const override;
ObjectID get_object() const override;
void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override;
- void rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const override;
+ Error rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const override;
GDScriptRPCCallable(Object *p_object, const StringName &p_method);
virtual ~GDScriptRPCCallable() = default;
diff --git a/modules/gdscript/gdscript_vm.cpp b/modules/gdscript/gdscript_vm.cpp
index 10365f8481..36ccb3d696 100644
--- a/modules/gdscript/gdscript_vm.cpp
+++ b/modules/gdscript/gdscript_vm.cpp
@@ -3295,6 +3295,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
int globalname_idx = _code_ptr[ip + 2];
GD_ERR_BREAK(globalname_idx < 0 || globalname_idx >= _global_names_count);
const StringName *globalname = &_global_names_ptr[globalname_idx];
+ GD_ERR_BREAK(!GDScriptLanguage::get_singleton()->get_named_globals_map().has(*globalname));
GET_INSTRUCTION_ARG(dst, 0);
*dst = GDScriptLanguage::get_singleton()->get_named_globals_map()[*globalname];
diff --git a/modules/gdscript/language_server/gdscript_extend_parser.cpp b/modules/gdscript/language_server/gdscript_extend_parser.cpp
index 03e93821c7..46a9b33eb0 100644
--- a/modules/gdscript/language_server/gdscript_extend_parser.cpp
+++ b/modules/gdscript/language_server/gdscript_extend_parser.cpp
@@ -690,9 +690,7 @@ Dictionary ExtendGDScriptParser::dump_function_api(const GDScriptParser::Functio
ERR_FAIL_NULL_V(p_func, func);
func["name"] = p_func->identifier->name;
func["return_type"] = p_func->get_datatype().to_string();
- func["rpc_mode"] = p_func->rpc_config.rpc_mode;
- func["rpc_transfer_mode"] = p_func->rpc_config.transfer_mode;
- func["rpc_transfer_channel"] = p_func->rpc_config.channel;
+ func["rpc_config"] = p_func->rpc_config;
Array parameters;
for (int i = 0; i < p_func->parameters.size(); i++) {
Dictionary arg;
diff --git a/modules/gridmap/editor/grid_map_editor_plugin.cpp b/modules/gridmap/editor/grid_map_editor_plugin.cpp
index f975d95079..fe4edf112b 100644
--- a/modules/gridmap/editor/grid_map_editor_plugin.cpp
+++ b/modules/gridmap/editor/grid_map_editor_plugin.cpp
@@ -545,7 +545,7 @@ void GridMapEditor::_update_paste_indicator() {
Basis rot;
rot.set_orthogonal_index(paste_indicator.orientation);
xf.basis = rot * xf.basis;
- xf.translate((-center * node->get_cell_size()) / scale);
+ xf.translate_local((-center * node->get_cell_size()) / scale);
RenderingServer::get_singleton()->instance_set_transform(paste_instance, node->get_global_transform() * xf);
@@ -553,7 +553,7 @@ void GridMapEditor::_update_paste_indicator() {
xf = Transform3D();
xf.origin = (paste_indicator.begin + (paste_indicator.current - paste_indicator.click) + center) * node->get_cell_size();
xf.basis = rot * xf.basis;
- xf.translate(item.grid_offset * node->get_cell_size());
+ xf.translate_local(item.grid_offset * node->get_cell_size());
Basis item_rot;
item_rot.set_orthogonal_index(item.orientation);
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index 1e4d82ca30..06793d25e0 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -2141,8 +2141,8 @@ bool CSharpInstance::refcount_decremented() {
return ref_dying;
}
-const Vector<Multiplayer::RPCConfig> CSharpInstance::get_rpc_methods() const {
- return script->get_rpc_methods();
+const Variant CSharpInstance::get_rpc_config() const {
+ return script->get_rpc_config();
}
void CSharpInstance::notification(int p_notification) {
@@ -3060,7 +3060,7 @@ void CSharpScript::update_script_class_info(Ref<CSharpScript> p_script) {
p_script->script_class->fetch_methods_with_godot_api_checks(p_script->native);
- p_script->rpc_functions.clear();
+ p_script->rpc_config.clear();
GDMonoClass *top = p_script->script_class;
while (top && top != p_script->native) {
@@ -3072,12 +3072,9 @@ void CSharpScript::update_script_class_info(Ref<CSharpScript> p_script) {
Vector<GDMonoMethod *> methods = top->get_all_methods();
for (int i = 0; i < methods.size(); i++) {
if (!methods[i]->is_static()) {
- Multiplayer::RPCConfig rpc_config = p_script->_member_get_rpc_config(methods[i]);
- if (rpc_config.rpc_mode != Multiplayer::RPC_MODE_DISABLED) {
- // RPC annotations can only be used once per method
- if (p_script->rpc_functions.find(rpc_config) == -1) {
- p_script->rpc_functions.push_back(rpc_config);
- }
+ const Variant rpc_config = p_script->_member_get_rpc_config(methods[i]);
+ if (rpc_config.get_type() != Variant::NIL) {
+ p_script->rpc_config[methods[i]->get_name()] = rpc_config;
}
}
}
@@ -3086,9 +3083,6 @@ void CSharpScript::update_script_class_info(Ref<CSharpScript> p_script) {
top = top->get_parent_class();
}
- // Sort so we are 100% that they are always the same.
- p_script->rpc_functions.sort_custom<Multiplayer::SortRPCConfig>();
-
p_script->load_script_signals(p_script->script_class, p_script->native);
}
@@ -3511,23 +3505,24 @@ int CSharpScript::get_member_line(const StringName &p_member) const {
return -1;
}
-Multiplayer::RPCConfig CSharpScript::_member_get_rpc_config(IMonoClassMember *p_member) const {
- Multiplayer::RPCConfig rpc_config;
+Variant CSharpScript::_member_get_rpc_config(IMonoClassMember *p_member) const {
+ Variant out;
MonoObject *rpc_attribute = p_member->get_attribute(CACHED_CLASS(RPCAttribute));
if (rpc_attribute != nullptr) {
- rpc_config.name = p_member->get_name();
- rpc_config.rpc_mode = (Multiplayer::RPCMode)CACHED_PROPERTY(RPCAttribute, Mode)->get_int_value(rpc_attribute);
- rpc_config.call_local = CACHED_PROPERTY(RPCAttribute, CallLocal)->get_bool_value(rpc_attribute);
- rpc_config.transfer_mode = (Multiplayer::TransferMode)CACHED_PROPERTY(RPCAttribute, TransferMode)->get_int_value(rpc_attribute);
- rpc_config.channel = CACHED_PROPERTY(RPCAttribute, TransferChannel)->get_int_value(rpc_attribute);
+ Dictionary rpc_config;
+ rpc_config["rpc_mode"] = CACHED_PROPERTY(RPCAttribute, Mode)->get_int_value(rpc_attribute);
+ rpc_config["call_local"] = CACHED_PROPERTY(RPCAttribute, CallLocal)->get_bool_value(rpc_attribute);
+ rpc_config["transfer_mode"] = CACHED_PROPERTY(RPCAttribute, TransferMode)->get_int_value(rpc_attribute);
+ rpc_config["channel"] = CACHED_PROPERTY(RPCAttribute, TransferChannel)->get_int_value(rpc_attribute);
+ out = rpc_config;
}
- return rpc_config;
+ return out;
}
-const Vector<Multiplayer::RPCConfig> CSharpScript::get_rpc_methods() const {
- return rpc_functions;
+const Variant CSharpScript::get_rpc_config() const {
+ return rpc_config;
}
Error CSharpScript::load_source_code(const String &p_path) {
diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h
index b17473470f..bd46a06a92 100644
--- a/modules/mono/csharp_script.h
+++ b/modules/mono/csharp_script.h
@@ -136,7 +136,7 @@ private:
HashMap<StringName, EventSignal> event_signals;
bool signals_invalidated = true;
- Vector<Multiplayer::RPCConfig> rpc_functions;
+ Dictionary rpc_config;
#ifdef TOOLS_ENABLED
List<PropertyInfo> exported_members_cache; // members_cache
@@ -179,7 +179,7 @@ private:
static void update_script_class_info(Ref<CSharpScript> p_script);
static void initialize_for_managed_type(Ref<CSharpScript> p_script, GDMonoClass *p_class, GDMonoClass *p_native);
- Multiplayer::RPCConfig _member_get_rpc_config(IMonoClassMember *p_member) const;
+ Variant _member_get_rpc_config(IMonoClassMember *p_member) const;
protected:
static void _bind_methods();
@@ -234,7 +234,7 @@ public:
int get_member_line(const StringName &p_member) const override;
- const Vector<Multiplayer::RPCConfig> get_rpc_methods() const override;
+ const Variant get_rpc_config() const override;
#ifdef TOOLS_ENABLED
bool is_placeholder_fallback_enabled() const override { return placeholder_fallback_enabled; }
@@ -311,7 +311,7 @@ public:
void refcount_incremented() override;
bool refcount_decremented() override;
- const Vector<Multiplayer::RPCConfig> get_rpc_methods() const override;
+ const Variant get_rpc_config() const override;
void notification(int p_notification) override;
void _call_notification(int p_notification);
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttribute.cs
index 0a1c8322d7..fb37838ffa 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttribute.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttribute.cs
@@ -5,8 +5,8 @@ namespace Godot
/// <summary>
/// Attribute that changes the RPC mode for the annotated <c>method</c> to the given <see cref="Mode"/>,
/// optionally specifying the <see cref="TransferMode"/> and <see cref="TransferChannel"/> (on supported peers).
- /// See <see cref="RPCMode"/> and <see cref="TransferMode"/>. By default, methods are not exposed to networking
- /// (and RPCs).
+ /// See <see cref="MultiplayerAPI.RPCMode"/> and <see cref="MultiplayerPeer.TransferModeEnum"/>.
+ /// By default, methods are not exposed to networking (and RPCs).
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class RPCAttribute : Attribute
@@ -14,7 +14,7 @@ namespace Godot
/// <summary>
/// RPC mode for the annotated method.
/// </summary>
- public RPCMode Mode { get; } = RPCMode.Disabled;
+ public MultiplayerAPI.RPCMode Mode { get; } = MultiplayerAPI.RPCMode.Disabled;
/// <summary>
/// If the method will also be called locally; otherwise, it is only called remotely.
@@ -24,7 +24,7 @@ namespace Godot
/// <summary>
/// Transfer mode for the annotated method.
/// </summary>
- public TransferMode TransferMode { get; set; } = TransferMode.Reliable;
+ public MultiplayerPeer.TransferModeEnum TransferMode { get; set; } = MultiplayerPeer.TransferModeEnum.Reliable;
/// <summary>
/// Transfer channel for the annotated mode.
@@ -35,7 +35,7 @@ namespace Godot
/// Constructs a <see cref="RPCAttribute"/> instance.
/// </summary>
/// <param name="mode">The RPC mode to use.</param>
- public RPCAttribute(RPCMode mode = RPCMode.Authority)
+ public RPCAttribute(MultiplayerAPI.RPCMode mode = MultiplayerAPI.RPCMode.Authority)
{
Mode = mode;
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs
index 89947899cb..e01db7b88c 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs
@@ -347,7 +347,7 @@ namespace Godot
/// </summary>
/// <param name="offset">The offset to translate by.</param>
/// <returns>The translated matrix.</returns>
- public Transform2D Translated(Vector2 offset)
+ public Transform2D TranslatedLocal(Vector2 offset)
{
Transform2D copy = this;
copy.origin += copy.BasisXform(offset);
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs
index 7b211b6577..41565bf680 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs
@@ -239,7 +239,7 @@ namespace Godot
/// </summary>
/// <param name="offset">The offset to translate by.</param>
/// <returns>The translated matrix.</returns>
- public Transform3D Translated(Vector3 offset)
+ public Transform3D TranslatedLocal(Vector3 offset)
{
return new Transform3D(basis, new Vector3
(
diff --git a/modules/multiplayer/SCsub b/modules/multiplayer/SCsub
new file mode 100644
index 0000000000..ff33655537
--- /dev/null
+++ b/modules/multiplayer/SCsub
@@ -0,0 +1,14 @@
+#!/usr/bin/env python
+
+Import("env")
+Import("env_modules")
+
+env_mp = env_modules.Clone()
+
+module_obj = []
+env_mp.add_source_files(module_obj, "*.cpp")
+
+if env["tools"]:
+ env_mp.add_source_files(module_obj, "editor/*.cpp")
+
+env.modules_sources += module_obj
diff --git a/modules/multiplayer/config.py b/modules/multiplayer/config.py
new file mode 100644
index 0000000000..414bf0afcf
--- /dev/null
+++ b/modules/multiplayer/config.py
@@ -0,0 +1,19 @@
+def can_build(env, platform):
+ return True
+
+
+def configure(env):
+ pass
+
+
+def get_doc_classes():
+ return [
+ "SceneReplicationConfig",
+ "SceneMultiplayer",
+ "MultiplayerSpawner",
+ "MultiplayerSynchronizer",
+ ]
+
+
+def get_doc_path():
+ return "doc_classes"
diff --git a/doc/classes/MultiplayerSpawner.xml b/modules/multiplayer/doc_classes/MultiplayerSpawner.xml
index 9de67068eb..44ab34f52c 100644
--- a/doc/classes/MultiplayerSpawner.xml
+++ b/modules/multiplayer/doc_classes/MultiplayerSpawner.xml
@@ -1,8 +1,9 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="MultiplayerSpawner" inherits="Node" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="MultiplayerSpawner" inherits="Node" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
<brief_description>
</brief_description>
<description>
+ This node uses [method MultiplayerAPI.object_configuration_add] to notify spawns passing the spawned node as the [code]object[/code] and itself as the [code]configuration[/code], and [method MultiplayerAPI.object_configuration_remove] to notify despawns in a similar way.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/MultiplayerSynchronizer.xml b/modules/multiplayer/doc_classes/MultiplayerSynchronizer.xml
index 3766491a6c..ebd1b50201 100644
--- a/doc/classes/MultiplayerSynchronizer.xml
+++ b/modules/multiplayer/doc_classes/MultiplayerSynchronizer.xml
@@ -1,8 +1,9 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="MultiplayerSynchronizer" inherits="Node" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="MultiplayerSynchronizer" inherits="Node" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
<brief_description>
</brief_description>
<description>
+ The [MultiplayerSynchronizer] uses [method MultiplayerAPI.object_configuration_add] to notify synchronization start passing the [Node] at [member root_path] as the [code]object[/code] and itself as the [code]configuration[/code], and uses [method MultiplayerAPI.object_configuration_remove] to notify synchronization end in a similar way.
</description>
<tutorials>
</tutorials>
diff --git a/modules/multiplayer/doc_classes/SceneMultiplayer.xml b/modules/multiplayer/doc_classes/SceneMultiplayer.xml
new file mode 100644
index 0000000000..0c3ed2d784
--- /dev/null
+++ b/modules/multiplayer/doc_classes/SceneMultiplayer.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="SceneMultiplayer" inherits="MultiplayerAPI" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
+ <brief_description>
+ High-level multiplayer API implementation.
+ </brief_description>
+ <description>
+ This class is the default implementation of [MultiplayerAPI], used to provide multiplayer functionalities in Godot Engine.
+ This implementation supports RPCs via [method Node.rpc] and [method Node.rpc_id] and requires [method MultiplayerAPI.rpc] to be passed a [Node] (it will fail for other object types).
+ This implementation additionally provide [SceneTree] replication via the [MultiplayerSpawner] and [MultiplayerSynchronizer] nodes, and the [SceneReplicationConfig] resource.
+ [b]Note:[/b] The high-level multiplayer API protocol is an implementation detail and isn't meant to be used by non-Godot servers. It may change without notice.
+ [b]Note:[/b] When exporting to Android, make sure to enable the [code]INTERNET[/code] permission in the Android export preset before exporting the project or using one-click deploy. Otherwise, network communication of any kind will be blocked by Android.
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ <method name="clear">
+ <return type="void" />
+ <description>
+ Clears the current SceneMultiplayer network state (you shouldn't call this unless you know what you are doing).
+ </description>
+ </method>
+ <method name="send_bytes">
+ <return type="int" enum="Error" />
+ <argument index="0" name="bytes" type="PackedByteArray" />
+ <argument index="1" name="id" type="int" default="0" />
+ <argument index="2" name="mode" type="int" enum="MultiplayerPeer.TransferMode" default="2" />
+ <argument index="3" name="channel" type="int" default="0" />
+ <description>
+ Sends the given raw [code]bytes[/code] to a specific peer identified by [code]id[/code] (see [method MultiplayerPeer.set_target_peer]). Default ID is [code]0[/code], i.e. broadcast to all peers.
+ </description>
+ </method>
+ </methods>
+ <members>
+ <member name="allow_object_decoding" type="bool" setter="set_allow_object_decoding" getter="is_object_decoding_allowed" default="false">
+ If [code]true[/code], the MultiplayerAPI will allow encoding and decoding of object during RPCs.
+ [b]Warning:[/b] Deserialized objects can contain code which gets executed. Do not use this option if the serialized object comes from untrusted sources to avoid potential security threat such as remote code execution.
+ </member>
+ <member name="refuse_new_connections" type="bool" setter="set_refuse_new_connections" getter="is_refusing_new_connections" default="false">
+ If [code]true[/code], the MultiplayerAPI's [member MultiplayerAPI.multiplayer_peer] refuses new incoming connections.
+ </member>
+ <member name="root_path" type="NodePath" setter="set_root_path" getter="get_root_path" default="NodePath(&quot;&quot;)">
+ The root path to use for RPCs and replication. Instead of an absolute path, a relative path will be used to find the node upon which the RPC should be executed.
+ This effectively allows to have different branches of the scene tree to be managed by different MultiplayerAPI, allowing for example to run both client and server in the same scene.
+ </member>
+ </members>
+ <signals>
+ <signal name="peer_packet">
+ <argument index="0" name="id" type="int" />
+ <argument index="1" name="packet" type="PackedByteArray" />
+ <description>
+ Emitted when this MultiplayerAPI's [member MultiplayerAPI.multiplayer_peer] receives a [code]packet[/code] with custom data (see [method send_bytes]). ID is the peer ID of the peer that sent the packet.
+ </description>
+ </signal>
+ </signals>
+</class>
diff --git a/doc/classes/SceneReplicationConfig.xml b/modules/multiplayer/doc_classes/SceneReplicationConfig.xml
index 62c108a477..1d6dec2f92 100644
--- a/doc/classes/SceneReplicationConfig.xml
+++ b/modules/multiplayer/doc_classes/SceneReplicationConfig.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="SceneReplicationConfig" inherits="Resource" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="SceneReplicationConfig" inherits="Resource" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
<brief_description>
</brief_description>
<description>
diff --git a/editor/plugins/replication_editor_plugin.cpp b/modules/multiplayer/editor/replication_editor_plugin.cpp
index 3e06a6739f..5891327db4 100644
--- a/editor/plugins/replication_editor_plugin.cpp
+++ b/modules/multiplayer/editor/replication_editor_plugin.cpp
@@ -33,9 +33,9 @@
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
#include "editor/inspector_dock.h"
+#include "modules/multiplayer/multiplayer_synchronizer.h"
#include "scene/gui/dialogs.h"
#include "scene/gui/tree.h"
-#include "scene/multiplayer/multiplayer_synchronizer.h"
void ReplicationEditor::_pick_node_filter_text_changed(const String &p_newtext) {
TreeItem *root_item = pick_node->get_scene_tree()->get_scene_tree()->get_root();
diff --git a/editor/plugins/replication_editor_plugin.h b/modules/multiplayer/editor/replication_editor_plugin.h
index df3d97f884..57fa4c82fa 100644
--- a/editor/plugins/replication_editor_plugin.h
+++ b/modules/multiplayer/editor/replication_editor_plugin.h
@@ -32,12 +32,13 @@
#define REPLICATION_EDITOR_PLUGIN_H
#include "editor/editor_plugin.h"
-#include "scene/resources/scene_replication_config.h"
#include "editor/editor_spin_slider.h"
#include "editor/property_editor.h"
#include "editor/property_selector.h"
+#include "../scene_replication_config.h"
+
class ConfirmationDialog;
class MultiplayerSynchronizer;
class Tree;
@@ -131,5 +132,17 @@ public:
ReplicationEditorPlugin();
~ReplicationEditorPlugin();
};
+#else
+class ReplicationEditorPlugin : public EditorPlugin {
+ GDCLASS(ReplicationEditorPlugin, EditorPlugin);
+
+public:
+ virtual void edit(Object *p_object) override {}
+ virtual bool handles(Object *p_object) const override { return false; }
+ virtual void make_visible(bool p_visible) override {}
+
+ ReplicationEditorPlugin() {}
+ ~ReplicationEditorPlugin() {}
+};
#endif // REPLICATION_EDITOR_PLUGIN_H
diff --git a/scene/multiplayer/multiplayer_spawner.cpp b/modules/multiplayer/multiplayer_spawner.cpp
index 8363d05e54..ca2fd1c023 100644
--- a/scene/multiplayer/multiplayer_spawner.cpp
+++ b/modules/multiplayer/multiplayer_spawner.cpp
@@ -31,7 +31,7 @@
#include "multiplayer_spawner.h"
#include "core/io/marshalls.h"
-#include "core/multiplayer/multiplayer_api.h"
+#include "scene/main/multiplayer_api.h"
#include "scene/main/window.h"
#include "scene/scene_string_names.h"
@@ -190,7 +190,7 @@ void MultiplayerSpawner::_notification(int p_what) {
if (node->is_connected(SceneStringNames::get_singleton()->ready, callable_mp(this, &MultiplayerSpawner::_node_ready))) {
node->disconnect(SceneStringNames::get_singleton()->ready, callable_mp(this, &MultiplayerSpawner::_node_ready));
}
- get_multiplayer()->despawn(node, this);
+ get_multiplayer()->object_configuration_remove(node, this);
}
tracked_nodes.clear();
} break;
@@ -236,7 +236,7 @@ void MultiplayerSpawner::_track(Node *p_node, const Variant &p_argument, int p_s
}
void MultiplayerSpawner::_node_ready(ObjectID p_id) {
- get_multiplayer()->spawn(ObjectDB::get_instance(p_id), this);
+ get_multiplayer()->object_configuration_add(ObjectDB::get_instance(p_id), this);
}
void MultiplayerSpawner::_node_exit(ObjectID p_id) {
@@ -244,7 +244,7 @@ void MultiplayerSpawner::_node_exit(ObjectID p_id) {
ERR_FAIL_COND(!node);
if (tracked_nodes.has(p_id)) {
tracked_nodes.erase(p_id);
- get_multiplayer()->despawn(node, this);
+ get_multiplayer()->object_configuration_remove(node, this);
}
}
diff --git a/scene/multiplayer/multiplayer_spawner.h b/modules/multiplayer/multiplayer_spawner.h
index 2c0eb9a2f0..80bb878a74 100644
--- a/scene/multiplayer/multiplayer_spawner.h
+++ b/modules/multiplayer/multiplayer_spawner.h
@@ -36,7 +36,8 @@
#include "core/templates/local_vector.h"
#include "core/variant/typed_array.h"
#include "scene/resources/packed_scene.h"
-#include "scene/resources/scene_replication_config.h"
+
+#include "scene_replication_config.h"
class MultiplayerSpawner : public Node {
GDCLASS(MultiplayerSpawner, Node);
diff --git a/scene/multiplayer/multiplayer_synchronizer.cpp b/modules/multiplayer/multiplayer_synchronizer.cpp
index e1b7433968..621d62c4c7 100644
--- a/scene/multiplayer/multiplayer_synchronizer.cpp
+++ b/modules/multiplayer/multiplayer_synchronizer.cpp
@@ -31,7 +31,7 @@
#include "multiplayer_synchronizer.h"
#include "core/config/engine.h"
-#include "core/multiplayer/multiplayer_api.h"
+#include "scene/main/multiplayer_api.h"
Object *MultiplayerSynchronizer::_get_prop_target(Object *p_obj, const NodePath &p_path) {
if (p_path.get_name_count() == 0) {
@@ -50,7 +50,7 @@ void MultiplayerSynchronizer::_stop() {
#endif
Node *node = is_inside_tree() ? get_node_or_null(root_path) : nullptr;
if (node) {
- get_multiplayer()->replication_stop(node, this);
+ get_multiplayer()->object_configuration_remove(node, this);
}
}
@@ -62,7 +62,7 @@ void MultiplayerSynchronizer::_start() {
#endif
Node *node = is_inside_tree() ? get_node_or_null(root_path) : nullptr;
if (node) {
- get_multiplayer()->replication_start(node, this);
+ get_multiplayer()->object_configuration_add(node, this);
_update_process();
}
}
@@ -293,9 +293,9 @@ void MultiplayerSynchronizer::set_multiplayer_authority(int p_peer_id, bool p_re
Node::set_multiplayer_authority(p_peer_id, p_recursive);
return;
}
- get_multiplayer()->replication_stop(node, this);
+ get_multiplayer()->object_configuration_remove(node, this);
Node::set_multiplayer_authority(p_peer_id, p_recursive);
- get_multiplayer()->replication_start(node, this);
+ get_multiplayer()->object_configuration_add(node, this);
}
MultiplayerSynchronizer::MultiplayerSynchronizer() {
diff --git a/scene/multiplayer/multiplayer_synchronizer.h b/modules/multiplayer/multiplayer_synchronizer.h
index 77c23b336d..e84d41db86 100644
--- a/scene/multiplayer/multiplayer_synchronizer.h
+++ b/modules/multiplayer/multiplayer_synchronizer.h
@@ -33,7 +33,7 @@
#include "scene/main/node.h"
-#include "scene/resources/scene_replication_config.h"
+#include "scene_replication_config.h"
class MultiplayerSynchronizer : public Node {
GDCLASS(MultiplayerSynchronizer, Node);
diff --git a/core/multiplayer/multiplayer.h b/modules/multiplayer/register_types.cpp
index f4c965b0f8..a2c524da80 100644
--- a/core/multiplayer/multiplayer.h
+++ b/modules/multiplayer/register_types.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* multiplayer.h */
+/* register_types.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,53 +28,33 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef MULTIPLAYER_H
-#define MULTIPLAYER_H
-
-#include "core/variant/binder_common.h"
-
-#include "core/string/string_name.h"
-
-namespace Multiplayer {
-
-enum TransferMode {
- TRANSFER_MODE_UNRELIABLE,
- TRANSFER_MODE_UNRELIABLE_ORDERED,
- TRANSFER_MODE_RELIABLE
-};
-
-enum RPCMode {
- RPC_MODE_DISABLED, // No rpc for this method, calls to this will be blocked (default)
- RPC_MODE_ANY_PEER, // Any peer can call this RPC
- RPC_MODE_AUTHORITY, // Only the node's multiplayer authority (server by default) can call this RPC
-};
-
-struct RPCConfig {
- StringName name;
- RPCMode rpc_mode = RPC_MODE_DISABLED;
- bool call_local = false;
- TransferMode transfer_mode = TRANSFER_MODE_RELIABLE;
- int channel = 0;
-
- bool operator==(RPCConfig const &p_other) const {
- return name == p_other.name;
+#include "register_types.h"
+
+#include "multiplayer_spawner.h"
+#include "multiplayer_synchronizer.h"
+#include "scene_multiplayer.h"
+#include "scene_replication_interface.h"
+#include "scene_rpc_interface.h"
+
+#ifdef TOOLS_ENABLED
+#include "editor/editor_plugin.h"
+#include "editor/replication_editor_plugin.h"
+#endif
+
+void initialize_multiplayer_module(ModuleInitializationLevel p_level) {
+ if (p_level == MODULE_INITIALIZATION_LEVEL_SCENE) {
+ GDREGISTER_CLASS(SceneReplicationConfig);
+ GDREGISTER_CLASS(MultiplayerSpawner);
+ GDREGISTER_CLASS(MultiplayerSynchronizer);
+ GDREGISTER_CLASS(SceneMultiplayer);
+ MultiplayerAPI::set_default_interface("SceneMultiplayer");
}
-};
-
-struct SortRPCConfig {
- StringName::AlphCompare compare;
- bool operator()(const RPCConfig &p_a, const RPCConfig &p_b) const {
- return compare(p_a.name, p_b.name);
+#ifdef TOOLS_ENABLED
+ if (p_level == MODULE_INITIALIZATION_LEVEL_EDITOR) {
+ EditorPlugins::add_by_type<ReplicationEditorPlugin>();
}
-};
-
-}; // namespace Multiplayer
-
-// This is needed for proper docs generation (i.e. not "Multiplayer."-prefixed).
-typedef Multiplayer::RPCMode RPCMode;
-typedef Multiplayer::TransferMode TransferMode;
-
-VARIANT_ENUM_CAST(RPCMode);
-VARIANT_ENUM_CAST(TransferMode);
+#endif
+}
-#endif // MULTIPLAYER_H
+void uninitialize_multiplayer_module(ModuleInitializationLevel p_level) {
+}
diff --git a/modules/multiplayer/register_types.h b/modules/multiplayer/register_types.h
new file mode 100644
index 0000000000..aca6cf46ed
--- /dev/null
+++ b/modules/multiplayer/register_types.h
@@ -0,0 +1,39 @@
+/*************************************************************************/
+/* register_types.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef MULTIPLAYER_REGISTER_TYPES_H
+#define MULTIPLAYER_REGISTER_TYPES_H
+
+#include "modules/register_module_types.h"
+
+void initialize_multiplayer_module(ModuleInitializationLevel p_level);
+void uninitialize_multiplayer_module(ModuleInitializationLevel p_level);
+
+#endif // MULTIPLAYER_REGISTER_TYPES_H
diff --git a/scene/multiplayer/scene_cache_interface.cpp b/modules/multiplayer/scene_cache_interface.cpp
index 79a7dc2d5a..4dc01321b9 100644
--- a/scene/multiplayer/scene_cache_interface.cpp
+++ b/modules/multiplayer/scene_cache_interface.cpp
@@ -34,13 +34,7 @@
#include "scene/main/node.h"
#include "scene/main/window.h"
-MultiplayerCacheInterface *SceneCacheInterface::_create(MultiplayerAPI *p_multiplayer) {
- return memnew(SceneCacheInterface(p_multiplayer));
-}
-
-void SceneCacheInterface::make_default() {
- MultiplayerAPI::create_default_cache_interface = _create;
-}
+#include "scene_multiplayer.h"
void SceneCacheInterface::on_peer_change(int p_id, bool p_connected) {
if (p_connected) {
@@ -98,7 +92,7 @@ void SceneCacheInterface::process_simplify_path(int p_from, const uint8_t *p_pac
Vector<uint8_t> packet;
packet.resize(1 + 1 + len);
- packet.write[0] = MultiplayerAPI::NETWORK_COMMAND_CONFIRM_PATH;
+ packet.write[0] = SceneMultiplayer::NETWORK_COMMAND_CONFIRM_PATH;
packet.write[1] = valid_rpc_checksum;
encode_cstring(pname.get_data(), &packet.write[2]);
@@ -110,7 +104,7 @@ void SceneCacheInterface::process_simplify_path(int p_from, const uint8_t *p_pac
#endif
multiplayer_peer->set_transfer_channel(0);
- multiplayer_peer->set_transfer_mode(Multiplayer::TRANSFER_MODE_RELIABLE);
+ multiplayer_peer->set_transfer_mode(MultiplayerPeer::TRANSFER_MODE_RELIABLE);
multiplayer_peer->set_target_peer(p_from);
multiplayer_peer->put_packet(packet.ptr(), packet.size());
}
@@ -150,7 +144,7 @@ Error SceneCacheInterface::_send_confirm_path(Node *p_node, NodePath p_path, Pat
packet.resize(1 + 4 + path_len + methods_md5_len);
int ofs = 0;
- packet.write[ofs] = MultiplayerAPI::NETWORK_COMMAND_SIMPLIFY_PATH;
+ packet.write[ofs] = SceneMultiplayer::NETWORK_COMMAND_SIMPLIFY_PATH;
ofs += 1;
ofs += encode_cstring(methods_md5.utf8().get_data(), &packet.write[ofs]);
@@ -170,7 +164,7 @@ Error SceneCacheInterface::_send_confirm_path(Node *p_node, NodePath p_path, Pat
for (int peer_id : p_peers) {
multiplayer_peer->set_target_peer(peer_id);
multiplayer_peer->set_transfer_channel(0);
- multiplayer_peer->set_transfer_mode(Multiplayer::TRANSFER_MODE_RELIABLE);
+ multiplayer_peer->set_transfer_mode(MultiplayerPeer::TRANSFER_MODE_RELIABLE);
err = multiplayer_peer->put_packet(packet.ptr(), packet.size());
ERR_FAIL_COND_V(err != OK, err);
// Insert into confirmed, but as false since it was not confirmed.
diff --git a/scene/multiplayer/scene_cache_interface.h b/modules/multiplayer/scene_cache_interface.h
index 6bfd683cf4..1e80792fe7 100644
--- a/scene/multiplayer/scene_cache_interface.h
+++ b/modules/multiplayer/scene_cache_interface.h
@@ -31,13 +31,15 @@
#ifndef SCENE_CACHE_INTERFACE_H
#define SCENE_CACHE_INTERFACE_H
-#include "core/multiplayer/multiplayer_api.h"
+#include "scene/main/multiplayer_api.h"
-class SceneCacheInterface : public MultiplayerCacheInterface {
- GDCLASS(SceneCacheInterface, MultiplayerCacheInterface);
+class SceneMultiplayer;
+
+class SceneCacheInterface : public RefCounted {
+ GDCLASS(SceneCacheInterface, RefCounted);
private:
- MultiplayerAPI *multiplayer = nullptr;
+ SceneMultiplayer *multiplayer = nullptr;
//path sent caches
struct PathSentCache {
@@ -61,23 +63,20 @@ private:
protected:
Error _send_confirm_path(Node *p_node, NodePath p_path, PathSentCache *psc, const List<int> &p_peers);
- static MultiplayerCacheInterface *_create(MultiplayerAPI *p_multiplayer);
public:
- static void make_default();
-
- virtual void clear() override;
- virtual void on_peer_change(int p_id, bool p_connected) override;
- virtual void process_simplify_path(int p_from, const uint8_t *p_packet, int p_packet_len) override;
- virtual void process_confirm_path(int p_from, const uint8_t *p_packet, int p_packet_len) override;
+ void clear();
+ void on_peer_change(int p_id, bool p_connected);
+ void process_simplify_path(int p_from, const uint8_t *p_packet, int p_packet_len);
+ void process_confirm_path(int p_from, const uint8_t *p_packet, int p_packet_len);
// Returns true if all peers have cached path.
- virtual bool send_object_cache(Object *p_obj, int p_target, int &p_id) override;
- virtual int make_object_cache(Object *p_obj) override;
- virtual Object *get_cached_object(int p_from, uint32_t p_cache_id) override;
- virtual bool is_cache_confirmed(NodePath p_path, int p_peer) override;
+ bool send_object_cache(Object *p_obj, int p_target, int &p_id);
+ int make_object_cache(Object *p_obj);
+ Object *get_cached_object(int p_from, uint32_t p_cache_id);
+ bool is_cache_confirmed(NodePath p_path, int p_peer);
- SceneCacheInterface(MultiplayerAPI *p_multiplayer) { multiplayer = p_multiplayer; }
+ SceneCacheInterface(SceneMultiplayer *p_multiplayer) { multiplayer = p_multiplayer; }
};
#endif // SCENE_CACHE_INTERFACE_H
diff --git a/modules/multiplayer/scene_multiplayer.cpp b/modules/multiplayer/scene_multiplayer.cpp
new file mode 100644
index 0000000000..3fc1eef366
--- /dev/null
+++ b/modules/multiplayer/scene_multiplayer.cpp
@@ -0,0 +1,332 @@
+/*************************************************************************/
+/* scene_multiplayer.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "scene_multiplayer.h"
+
+#include "core/debugger/engine_debugger.h"
+#include "core/io/marshalls.h"
+
+#include <stdint.h>
+
+#ifdef DEBUG_ENABLED
+#include "core/os/os.h"
+#endif
+
+#ifdef DEBUG_ENABLED
+void SceneMultiplayer::profile_bandwidth(const String &p_inout, int p_size) {
+ if (EngineDebugger::is_profiling("multiplayer")) {
+ Array values;
+ values.push_back(p_inout);
+ values.push_back(OS::get_singleton()->get_ticks_msec());
+ values.push_back(p_size);
+ EngineDebugger::profiler_add_frame_data("multiplayer", values);
+ }
+}
+#endif
+
+Error SceneMultiplayer::poll() {
+ if (!multiplayer_peer.is_valid() || multiplayer_peer->get_connection_status() == MultiplayerPeer::CONNECTION_DISCONNECTED) {
+ return ERR_UNCONFIGURED;
+ }
+
+ multiplayer_peer->poll();
+
+ if (!multiplayer_peer.is_valid()) { // It's possible that polling might have resulted in a disconnection, so check here.
+ return OK;
+ }
+
+ while (multiplayer_peer->get_available_packet_count()) {
+ int sender = multiplayer_peer->get_packet_peer();
+ const uint8_t *packet;
+ int len;
+
+ Error err = multiplayer_peer->get_packet(&packet, len);
+ ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Error getting packet! %d", err));
+
+ remote_sender_id = sender;
+ _process_packet(sender, packet, len);
+ remote_sender_id = 0;
+
+ if (!multiplayer_peer.is_valid()) {
+ return OK; // It's also possible that a packet or RPC caused a disconnection, so also check here.
+ }
+ }
+ replicator->on_network_process();
+ return OK;
+}
+
+void SceneMultiplayer::clear() {
+ connected_peers.clear();
+ packet_cache.clear();
+ cache->clear();
+}
+
+void SceneMultiplayer::set_root_path(const NodePath &p_path) {
+ ERR_FAIL_COND_MSG(!p_path.is_absolute() && !p_path.is_empty(), "SceneMultiplayer root path must be absolute.");
+ root_path = p_path;
+}
+
+NodePath SceneMultiplayer::get_root_path() const {
+ return root_path;
+}
+
+void SceneMultiplayer::set_multiplayer_peer(const Ref<MultiplayerPeer> &p_peer) {
+ if (p_peer == multiplayer_peer) {
+ return; // Nothing to do
+ }
+
+ ERR_FAIL_COND_MSG(p_peer.is_valid() && p_peer->get_connection_status() == MultiplayerPeer::CONNECTION_DISCONNECTED,
+ "Supplied MultiplayerPeer must be connecting or connected.");
+
+ if (multiplayer_peer.is_valid()) {
+ multiplayer_peer->disconnect("peer_connected", callable_mp(this, &SceneMultiplayer::_add_peer));
+ multiplayer_peer->disconnect("peer_disconnected", callable_mp(this, &SceneMultiplayer::_del_peer));
+ multiplayer_peer->disconnect("connection_succeeded", callable_mp(this, &SceneMultiplayer::_connected_to_server));
+ multiplayer_peer->disconnect("connection_failed", callable_mp(this, &SceneMultiplayer::_connection_failed));
+ multiplayer_peer->disconnect("server_disconnected", callable_mp(this, &SceneMultiplayer::_server_disconnected));
+ clear();
+ }
+
+ multiplayer_peer = p_peer;
+
+ if (multiplayer_peer.is_valid()) {
+ multiplayer_peer->connect("peer_connected", callable_mp(this, &SceneMultiplayer::_add_peer));
+ multiplayer_peer->connect("peer_disconnected", callable_mp(this, &SceneMultiplayer::_del_peer));
+ multiplayer_peer->connect("connection_succeeded", callable_mp(this, &SceneMultiplayer::_connected_to_server));
+ multiplayer_peer->connect("connection_failed", callable_mp(this, &SceneMultiplayer::_connection_failed));
+ multiplayer_peer->connect("server_disconnected", callable_mp(this, &SceneMultiplayer::_server_disconnected));
+ }
+ replicator->on_reset();
+}
+
+Ref<MultiplayerPeer> SceneMultiplayer::get_multiplayer_peer() {
+ return multiplayer_peer;
+}
+
+void SceneMultiplayer::_process_packet(int p_from, const uint8_t *p_packet, int p_packet_len) {
+ ERR_FAIL_COND_MSG(root_path.is_empty(), "Multiplayer root was not initialized. If you are using custom multiplayer, remember to set the root path via SceneMultiplayer.set_root_path before using it.");
+ ERR_FAIL_COND_MSG(p_packet_len < 1, "Invalid packet received. Size too small.");
+
+#ifdef DEBUG_ENABLED
+ profile_bandwidth("in", p_packet_len);
+#endif
+
+ // Extract the `packet_type` from the LSB three bits:
+ uint8_t packet_type = p_packet[0] & CMD_MASK;
+
+ switch (packet_type) {
+ case NETWORK_COMMAND_SIMPLIFY_PATH: {
+ cache->process_simplify_path(p_from, p_packet, p_packet_len);
+ } break;
+
+ case NETWORK_COMMAND_CONFIRM_PATH: {
+ cache->process_confirm_path(p_from, p_packet, p_packet_len);
+ } break;
+
+ case NETWORK_COMMAND_REMOTE_CALL: {
+ rpc->process_rpc(p_from, p_packet, p_packet_len);
+ } break;
+
+ case NETWORK_COMMAND_RAW: {
+ _process_raw(p_from, p_packet, p_packet_len);
+ } break;
+ case NETWORK_COMMAND_SPAWN: {
+ replicator->on_spawn_receive(p_from, p_packet, p_packet_len);
+ } break;
+ case NETWORK_COMMAND_DESPAWN: {
+ replicator->on_despawn_receive(p_from, p_packet, p_packet_len);
+ } break;
+ case NETWORK_COMMAND_SYNC: {
+ replicator->on_sync_receive(p_from, p_packet, p_packet_len);
+ } break;
+ }
+}
+
+void SceneMultiplayer::_add_peer(int p_id) {
+ connected_peers.insert(p_id);
+ cache->on_peer_change(p_id, true);
+ replicator->on_peer_change(p_id, true);
+ emit_signal(SNAME("peer_connected"), p_id);
+}
+
+void SceneMultiplayer::_del_peer(int p_id) {
+ replicator->on_peer_change(p_id, false);
+ cache->on_peer_change(p_id, false);
+ connected_peers.erase(p_id);
+ emit_signal(SNAME("peer_disconnected"), p_id);
+}
+
+void SceneMultiplayer::_connected_to_server() {
+ emit_signal(SNAME("connected_to_server"));
+}
+
+void SceneMultiplayer::_connection_failed() {
+ emit_signal(SNAME("connection_failed"));
+}
+
+void SceneMultiplayer::_server_disconnected() {
+ replicator->on_reset();
+ emit_signal(SNAME("server_disconnected"));
+}
+
+Error SceneMultiplayer::send_bytes(Vector<uint8_t> p_data, int p_to, MultiplayerPeer::TransferMode p_mode, int p_channel) {
+ ERR_FAIL_COND_V_MSG(p_data.size() < 1, ERR_INVALID_DATA, "Trying to send an empty raw packet.");
+ ERR_FAIL_COND_V_MSG(!multiplayer_peer.is_valid(), ERR_UNCONFIGURED, "Trying to send a raw packet while no multiplayer peer is active.");
+ ERR_FAIL_COND_V_MSG(multiplayer_peer->get_connection_status() != MultiplayerPeer::CONNECTION_CONNECTED, ERR_UNCONFIGURED, "Trying to send a raw packet via a multiplayer peer which is not connected.");
+
+ if (packet_cache.size() < p_data.size() + 1) {
+ packet_cache.resize(p_data.size() + 1);
+ }
+
+ const uint8_t *r = p_data.ptr();
+ packet_cache.write[0] = NETWORK_COMMAND_RAW;
+ memcpy(&packet_cache.write[1], &r[0], p_data.size());
+
+ multiplayer_peer->set_target_peer(p_to);
+ multiplayer_peer->set_transfer_channel(p_channel);
+ multiplayer_peer->set_transfer_mode(p_mode);
+
+ return multiplayer_peer->put_packet(packet_cache.ptr(), p_data.size() + 1);
+}
+
+void SceneMultiplayer::_process_raw(int p_from, const uint8_t *p_packet, int p_packet_len) {
+ ERR_FAIL_COND_MSG(p_packet_len < 2, "Invalid packet received. Size too small.");
+
+ Vector<uint8_t> out;
+ int len = p_packet_len - 1;
+ out.resize(len);
+ {
+ uint8_t *w = out.ptrw();
+ memcpy(&w[0], &p_packet[1], len);
+ }
+ emit_signal(SNAME("peer_packet"), p_from, out);
+}
+
+int SceneMultiplayer::get_unique_id() {
+ ERR_FAIL_COND_V_MSG(!multiplayer_peer.is_valid(), 0, "No multiplayer peer is assigned. Unable to get unique ID.");
+ return multiplayer_peer->get_unique_id();
+}
+
+void SceneMultiplayer::set_refuse_new_connections(bool p_refuse) {
+ ERR_FAIL_COND_MSG(!multiplayer_peer.is_valid(), "No multiplayer peer is assigned. Unable to set 'refuse_new_connections'.");
+ multiplayer_peer->set_refuse_new_connections(p_refuse);
+}
+
+bool SceneMultiplayer::is_refusing_new_connections() const {
+ ERR_FAIL_COND_V_MSG(!multiplayer_peer.is_valid(), false, "No multiplayer peer is assigned. Unable to get 'refuse_new_connections'.");
+ return multiplayer_peer->is_refusing_new_connections();
+}
+
+Vector<int> SceneMultiplayer::get_peer_ids() {
+ ERR_FAIL_COND_V_MSG(!multiplayer_peer.is_valid(), Vector<int>(), "No multiplayer peer is assigned. Assume no peers are connected.");
+
+ Vector<int> ret;
+ for (const int &E : connected_peers) {
+ ret.push_back(E);
+ }
+
+ return ret;
+}
+
+void SceneMultiplayer::set_allow_object_decoding(bool p_enable) {
+ allow_object_decoding = p_enable;
+}
+
+bool SceneMultiplayer::is_object_decoding_allowed() const {
+ return allow_object_decoding;
+}
+
+String SceneMultiplayer::get_rpc_md5(const Object *p_obj) {
+ return rpc->get_rpc_md5(p_obj);
+}
+
+Error SceneMultiplayer::rpcp(Object *p_obj, int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount) {
+ return rpc->rpcp(p_obj, p_peer_id, p_method, p_arg, p_argcount);
+}
+
+Error SceneMultiplayer::object_configuration_add(Object *p_obj, Variant p_config) {
+ if (p_obj == nullptr && p_config.get_type() == Variant::NODE_PATH) {
+ set_root_path(p_config);
+ return OK;
+ }
+ MultiplayerSpawner *spawner = Object::cast_to<MultiplayerSpawner>(p_config.get_validated_object());
+ MultiplayerSynchronizer *sync = Object::cast_to<MultiplayerSynchronizer>(p_config.get_validated_object());
+ if (spawner) {
+ return replicator->on_spawn(p_obj, p_config);
+ } else if (sync) {
+ return replicator->on_replication_start(p_obj, p_config);
+ }
+ return ERR_INVALID_PARAMETER;
+}
+
+Error SceneMultiplayer::object_configuration_remove(Object *p_obj, Variant p_config) {
+ if (p_obj == nullptr && p_config.get_type() == Variant::NODE_PATH) {
+ ERR_FAIL_COND_V(root_path != p_config.operator NodePath(), ERR_INVALID_PARAMETER);
+ set_root_path(NodePath());
+ return OK;
+ }
+ MultiplayerSpawner *spawner = Object::cast_to<MultiplayerSpawner>(p_config.get_validated_object());
+ MultiplayerSynchronizer *sync = Object::cast_to<MultiplayerSynchronizer>(p_config.get_validated_object());
+ if (spawner) {
+ return replicator->on_despawn(p_obj, p_config);
+ }
+ if (sync) {
+ return replicator->on_replication_stop(p_obj, p_config);
+ }
+ return ERR_INVALID_PARAMETER;
+}
+
+void SceneMultiplayer::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_root_path", "path"), &SceneMultiplayer::set_root_path);
+ ClassDB::bind_method(D_METHOD("get_root_path"), &SceneMultiplayer::get_root_path);
+ ClassDB::bind_method(D_METHOD("clear"), &SceneMultiplayer::clear);
+ ClassDB::bind_method(D_METHOD("set_refuse_new_connections", "refuse"), &SceneMultiplayer::set_refuse_new_connections);
+ ClassDB::bind_method(D_METHOD("is_refusing_new_connections"), &SceneMultiplayer::is_refusing_new_connections);
+ ClassDB::bind_method(D_METHOD("set_allow_object_decoding", "enable"), &SceneMultiplayer::set_allow_object_decoding);
+ ClassDB::bind_method(D_METHOD("is_object_decoding_allowed"), &SceneMultiplayer::is_object_decoding_allowed);
+ ClassDB::bind_method(D_METHOD("send_bytes", "bytes", "id", "mode", "channel"), &SceneMultiplayer::send_bytes, DEFVAL(MultiplayerPeer::TARGET_PEER_BROADCAST), DEFVAL(MultiplayerPeer::TRANSFER_MODE_RELIABLE), DEFVAL(0));
+
+ ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "root_path"), "set_root_path", "get_root_path");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_object_decoding"), "set_allow_object_decoding", "is_object_decoding_allowed");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "refuse_new_connections"), "set_refuse_new_connections", "is_refusing_new_connections");
+ ADD_PROPERTY_DEFAULT("refuse_new_connections", false);
+
+ ADD_SIGNAL(MethodInfo("peer_packet", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::PACKED_BYTE_ARRAY, "packet")));
+}
+
+SceneMultiplayer::SceneMultiplayer() {
+ replicator = Ref<SceneReplicationInterface>(memnew(SceneReplicationInterface(this)));
+ rpc = Ref<SceneRPCInterface>(memnew(SceneRPCInterface(this)));
+ cache = Ref<SceneCacheInterface>(memnew(SceneCacheInterface(this)));
+}
+
+SceneMultiplayer::~SceneMultiplayer() {
+ clear();
+}
diff --git a/modules/multiplayer/scene_multiplayer.h b/modules/multiplayer/scene_multiplayer.h
new file mode 100644
index 0000000000..a99cca7b21
--- /dev/null
+++ b/modules/multiplayer/scene_multiplayer.h
@@ -0,0 +1,136 @@
+/*************************************************************************/
+/* scene_multiplayer.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef SCENE_MULTIPLAYER_H
+#define SCENE_MULTIPLAYER_H
+
+#include "scene/main/multiplayer_api.h"
+
+#include "scene_cache_interface.h"
+#include "scene_replication_interface.h"
+#include "scene_rpc_interface.h"
+
+class SceneMultiplayer : public MultiplayerAPI {
+ GDCLASS(SceneMultiplayer, MultiplayerAPI);
+
+public:
+ enum NetworkCommands {
+ NETWORK_COMMAND_REMOTE_CALL = 0,
+ NETWORK_COMMAND_SIMPLIFY_PATH,
+ NETWORK_COMMAND_CONFIRM_PATH,
+ NETWORK_COMMAND_RAW,
+ NETWORK_COMMAND_SPAWN,
+ NETWORK_COMMAND_DESPAWN,
+ NETWORK_COMMAND_SYNC,
+ };
+
+ // For each command, the 4 MSB can contain custom flags, as defined by subsystems.
+ enum {
+ CMD_FLAG_0_SHIFT = 4,
+ CMD_FLAG_1_SHIFT = 5,
+ CMD_FLAG_2_SHIFT = 6,
+ CMD_FLAG_3_SHIFT = 7,
+ };
+
+ // This is the mask that will be used to extract the command.
+ enum {
+ CMD_MASK = 7, // 0x7 -> 0b00001111
+ };
+
+private:
+ Ref<MultiplayerPeer> multiplayer_peer;
+ HashSet<int> connected_peers;
+ int remote_sender_id = 0;
+ int remote_sender_override = 0;
+
+ Vector<uint8_t> packet_cache;
+
+ NodePath root_path;
+ bool allow_object_decoding = false;
+
+ Ref<SceneCacheInterface> cache;
+ Ref<SceneReplicationInterface> replicator;
+ Ref<SceneRPCInterface> rpc;
+
+protected:
+ static void _bind_methods();
+
+ void _process_packet(int p_from, const uint8_t *p_packet, int p_packet_len);
+ void _process_raw(int p_from, const uint8_t *p_packet, int p_packet_len);
+
+ void _add_peer(int p_id);
+ void _del_peer(int p_id);
+ void _connected_to_server();
+ void _connection_failed();
+ void _server_disconnected();
+
+public:
+ virtual void set_multiplayer_peer(const Ref<MultiplayerPeer> &p_peer) override;
+ virtual Ref<MultiplayerPeer> get_multiplayer_peer() override;
+
+ virtual Error poll() override;
+ virtual int get_unique_id() override;
+ virtual Vector<int> get_peer_ids() override;
+ virtual int get_remote_sender_id() override { return remote_sender_override ? remote_sender_override : remote_sender_id; }
+
+ virtual Error rpcp(Object *p_obj, int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount) override;
+
+ virtual Error object_configuration_add(Object *p_obj, Variant p_config) override;
+ virtual Error object_configuration_remove(Object *p_obj, Variant p_config) override;
+
+ void clear();
+
+ // Usually from object_configuration_add/remove
+ void set_root_path(const NodePath &p_path);
+ NodePath get_root_path() const;
+
+ Error send_bytes(Vector<uint8_t> p_data, int p_to = MultiplayerPeer::TARGET_PEER_BROADCAST, MultiplayerPeer::TransferMode p_mode = MultiplayerPeer::TRANSFER_MODE_RELIABLE, int p_channel = 0);
+ String get_rpc_md5(const Object *p_obj);
+
+ const HashSet<int> get_connected_peers() const { return connected_peers; }
+
+ void set_remote_sender_override(int p_id) { remote_sender_override = p_id; }
+ void set_refuse_new_connections(bool p_refuse);
+ bool is_refusing_new_connections() const;
+
+ void set_allow_object_decoding(bool p_enable);
+ bool is_object_decoding_allowed() const;
+
+ Ref<SceneCacheInterface> get_path_cache() { return cache; }
+
+#ifdef DEBUG_ENABLED
+ void profile_bandwidth(const String &p_inout, int p_size);
+#endif
+
+ SceneMultiplayer();
+ ~SceneMultiplayer();
+};
+
+#endif // SCENE_MULTIPLAYER_H
diff --git a/scene/resources/scene_replication_config.cpp b/modules/multiplayer/scene_replication_config.cpp
index 6789f9f7d5..ae06516b7b 100644
--- a/scene/resources/scene_replication_config.cpp
+++ b/modules/multiplayer/scene_replication_config.cpp
@@ -30,7 +30,7 @@
#include "scene_replication_config.h"
-#include "core/multiplayer/multiplayer_api.h"
+#include "scene/main/multiplayer_api.h"
#include "scene/main/node.h"
bool SceneReplicationConfig::_set(const StringName &p_name, const Variant &p_value) {
diff --git a/scene/resources/scene_replication_config.h b/modules/multiplayer/scene_replication_config.h
index ab3658d2a7..ab3658d2a7 100644
--- a/scene/resources/scene_replication_config.h
+++ b/modules/multiplayer/scene_replication_config.h
diff --git a/scene/multiplayer/scene_replication_interface.cpp b/modules/multiplayer/scene_replication_interface.cpp
index c616c5bb85..2dc0766fc3 100644
--- a/scene/multiplayer/scene_replication_interface.cpp
+++ b/modules/multiplayer/scene_replication_interface.cpp
@@ -32,21 +32,15 @@
#include "core/io/marshalls.h"
#include "scene/main/node.h"
-#include "scene/multiplayer/multiplayer_spawner.h"
-#include "scene/multiplayer/multiplayer_synchronizer.h"
+
+#include "multiplayer_spawner.h"
+#include "multiplayer_synchronizer.h"
+#include "scene_multiplayer.h"
#define MAKE_ROOM(m_amount) \
if (packet_cache.size() < m_amount) \
packet_cache.resize(m_amount);
-MultiplayerReplicationInterface *SceneReplicationInterface::_create(MultiplayerAPI *p_multiplayer) {
- return memnew(SceneReplicationInterface(p_multiplayer));
-}
-
-void SceneReplicationInterface::make_default() {
- MultiplayerAPI::create_default_replication_interface = _create;
-}
-
void SceneReplicationInterface::_free_remotes(int p_id) {
const HashMap<uint32_t, ObjectID> remotes = rep_state->peer_get_remotes(p_id);
for (const KeyValue<uint32_t, ObjectID> &E : remotes) {
@@ -239,7 +233,7 @@ Error SceneReplicationInterface::_update_spawn_visibility(int p_peer, const Obje
_make_spawn_packet(node, len);
for (int pid : to_spawn) {
int path_id;
- multiplayer->send_object_cache(spawner, pid, path_id);
+ multiplayer->get_path_cache()->send_object_cache(spawner, pid, path_id);
_send_raw(packet_cache.ptr(), len, pid, true);
rep_state->peer_add_spawn(pid, p_oid);
}
@@ -267,7 +261,7 @@ Error SceneReplicationInterface::_send_raw(const uint8_t *p_buffer, int p_size,
Ref<MultiplayerPeer> peer = multiplayer->get_multiplayer_peer();
peer->set_target_peer(p_peer);
peer->set_transfer_channel(0);
- peer->set_transfer_mode(p_reliable ? Multiplayer::TRANSFER_MODE_RELIABLE : Multiplayer::TRANSFER_MODE_UNRELIABLE);
+ peer->set_transfer_mode(p_reliable ? MultiplayerPeer::TRANSFER_MODE_RELIABLE : MultiplayerPeer::TRANSFER_MODE_UNRELIABLE);
return peer->put_packet(p_buffer, p_size);
}
@@ -306,12 +300,12 @@ Error SceneReplicationInterface::_make_spawn_packet(Node *p_node, int &r_len) {
}
// Encode scene ID, path ID, net ID, node name.
- int path_id = multiplayer->make_object_cache(spawner);
+ int path_id = multiplayer->get_path_cache()->make_object_cache(spawner);
CharString cname = p_node->get_name().operator String().utf8();
int nlen = encode_cstring(cname.get_data(), nullptr);
MAKE_ROOM(1 + 1 + 4 + 4 + 4 + nlen + (is_custom ? 4 + spawn_arg_size : 0) + state_size);
uint8_t *ptr = packet_cache.ptrw();
- ptr[0] = (uint8_t)MultiplayerAPI::NETWORK_COMMAND_SPAWN;
+ ptr[0] = (uint8_t)SceneMultiplayer::NETWORK_COMMAND_SPAWN;
ptr[1] = scene_id;
int ofs = 2;
ofs += encode_uint32(path_id, &ptr[ofs]);
@@ -339,7 +333,7 @@ Error SceneReplicationInterface::_make_despawn_packet(Node *p_node, int &r_len)
const ObjectID oid = p_node->get_instance_id();
MAKE_ROOM(5);
uint8_t *ptr = packet_cache.ptrw();
- ptr[0] = (uint8_t)MultiplayerAPI::NETWORK_COMMAND_DESPAWN;
+ ptr[0] = (uint8_t)SceneMultiplayer::NETWORK_COMMAND_DESPAWN;
int ofs = 1;
uint32_t nid = rep_state->get_net_id(oid);
ofs += encode_uint32(nid, &ptr[ofs]);
@@ -354,7 +348,7 @@ Error SceneReplicationInterface::on_spawn_receive(int p_from, const uint8_t *p_b
ofs += 1;
uint32_t node_target = decode_uint32(&p_buffer[ofs]);
ofs += 4;
- MultiplayerSpawner *spawner = Object::cast_to<MultiplayerSpawner>(multiplayer->get_cached_object(p_from, node_target));
+ MultiplayerSpawner *spawner = Object::cast_to<MultiplayerSpawner>(multiplayer->get_path_cache()->get_cached_object(p_from, node_target));
ERR_FAIL_COND_V(!spawner, ERR_DOES_NOT_EXIST);
ERR_FAIL_COND_V(p_from != spawner->get_multiplayer_authority(), ERR_UNAUTHORIZED);
@@ -431,7 +425,7 @@ void SceneReplicationInterface::_send_sync(int p_peer, uint64_t p_msec) {
}
MAKE_ROOM(sync_mtu);
uint8_t *ptr = packet_cache.ptrw();
- ptr[0] = MultiplayerAPI::NETWORK_COMMAND_SYNC;
+ ptr[0] = SceneMultiplayer::NETWORK_COMMAND_SYNC;
int ofs = 1;
ofs += encode_uint16(rep_state->peer_sync_next(p_peer), &ptr[1]);
// Can only send updates for already notified nodes.
@@ -447,7 +441,7 @@ void SceneReplicationInterface::_send_sync(int p_peer, uint64_t p_msec) {
uint32_t net_id = rep_state->get_net_id(oid);
if (net_id == 0 || (net_id & 0x80000000)) {
int path_id = 0;
- bool verified = multiplayer->send_object_cache(sync, p_peer, path_id);
+ bool verified = multiplayer->get_path_cache()->send_object_cache(sync, p_peer, path_id);
ERR_CONTINUE_MSG(path_id < 0, "This should never happen!");
if (net_id == 0) {
// First time path based ID.
@@ -499,7 +493,7 @@ Error SceneReplicationInterface::on_sync_receive(int p_from, const uint8_t *p_bu
ofs += 4;
Node *node = nullptr;
if (net_id & 0x80000000) {
- MultiplayerSynchronizer *sync = Object::cast_to<MultiplayerSynchronizer>(multiplayer->get_cached_object(p_from, net_id & 0x7FFFFFFF));
+ MultiplayerSynchronizer *sync = Object::cast_to<MultiplayerSynchronizer>(multiplayer->get_path_cache()->get_cached_object(p_from, net_id & 0x7FFFFFFF));
ERR_FAIL_COND_V(!sync || sync->get_multiplayer_authority() != p_from, ERR_UNAUTHORIZED);
node = sync->get_node(sync->get_root_path());
} else {
diff --git a/scene/multiplayer/scene_replication_interface.h b/modules/multiplayer/scene_replication_interface.h
index 9ddab2d383..8981647429 100644
--- a/scene/multiplayer/scene_replication_interface.h
+++ b/modules/multiplayer/scene_replication_interface.h
@@ -31,12 +31,14 @@
#ifndef SCENE_REPLICATION_INTERFACE_H
#define SCENE_REPLICATION_INTERFACE_H
-#include "core/multiplayer/multiplayer_api.h"
+#include "scene/main/multiplayer_api.h"
-#include "scene/multiplayer/scene_replication_state.h"
+#include "scene_replication_state.h"
-class SceneReplicationInterface : public MultiplayerReplicationInterface {
- GDCLASS(SceneReplicationInterface, MultiplayerReplicationInterface);
+class SceneMultiplayer;
+
+class SceneReplicationInterface : public RefCounted {
+ GDCLASS(SceneReplicationInterface, RefCounted);
private:
void _send_sync(int p_peer, uint64_t p_msec);
@@ -50,7 +52,7 @@ private:
void _free_remotes(int p_peer);
Ref<SceneReplicationState> rep_state;
- MultiplayerAPI *multiplayer = nullptr;
+ SceneMultiplayer *multiplayer = nullptr;
PackedByteArray packet_cache;
int sync_mtu = 1350; // Highly dependent on underlying protocol.
@@ -59,26 +61,23 @@ private:
const uint8_t *pending_buffer = nullptr;
int pending_buffer_size = 0;
-protected:
- static MultiplayerReplicationInterface *_create(MultiplayerAPI *p_multiplayer);
-
public:
static void make_default();
- virtual void on_reset() override;
- virtual void on_peer_change(int p_id, bool p_connected) override;
+ void on_reset();
+ void on_peer_change(int p_id, bool p_connected);
- virtual Error on_spawn(Object *p_obj, Variant p_config) override;
- virtual Error on_despawn(Object *p_obj, Variant p_config) override;
- virtual Error on_replication_start(Object *p_obj, Variant p_config) override;
- virtual Error on_replication_stop(Object *p_obj, Variant p_config) override;
- virtual void on_network_process() override;
+ Error on_spawn(Object *p_obj, Variant p_config);
+ Error on_despawn(Object *p_obj, Variant p_config);
+ Error on_replication_start(Object *p_obj, Variant p_config);
+ Error on_replication_stop(Object *p_obj, Variant p_config);
+ void on_network_process();
- virtual Error on_spawn_receive(int p_from, const uint8_t *p_buffer, int p_buffer_len) override;
- virtual Error on_despawn_receive(int p_from, const uint8_t *p_buffer, int p_buffer_len) override;
- virtual Error on_sync_receive(int p_from, const uint8_t *p_buffer, int p_buffer_len) override;
+ Error on_spawn_receive(int p_from, const uint8_t *p_buffer, int p_buffer_len);
+ Error on_despawn_receive(int p_from, const uint8_t *p_buffer, int p_buffer_len);
+ Error on_sync_receive(int p_from, const uint8_t *p_buffer, int p_buffer_len);
- SceneReplicationInterface(MultiplayerAPI *p_multiplayer) {
+ SceneReplicationInterface(SceneMultiplayer *p_multiplayer) {
rep_state.instantiate();
multiplayer = p_multiplayer;
}
diff --git a/scene/multiplayer/scene_replication_state.cpp b/modules/multiplayer/scene_replication_state.cpp
index f6a51ff9c7..5ad27e9a97 100644
--- a/scene/multiplayer/scene_replication_state.cpp
+++ b/modules/multiplayer/scene_replication_state.cpp
@@ -28,13 +28,13 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "scene/multiplayer/scene_replication_state.h"
+#include "scene_replication_state.h"
-#include "core/multiplayer/multiplayer_api.h"
-#include "scene/multiplayer/multiplayer_spawner.h"
-#include "scene/multiplayer/multiplayer_synchronizer.h"
#include "scene/scene_string_names.h"
+#include "multiplayer_spawner.h"
+#include "multiplayer_synchronizer.h"
+
SceneReplicationState::TrackedNode &SceneReplicationState::_track(const ObjectID &p_id) {
if (!tracked_nodes.has(p_id)) {
tracked_nodes[p_id] = TrackedNode(p_id);
diff --git a/scene/multiplayer/scene_replication_state.h b/modules/multiplayer/scene_replication_state.h
index 01b70b11b8..bdff6ae3b7 100644
--- a/scene/multiplayer/scene_replication_state.h
+++ b/modules/multiplayer/scene_replication_state.h
@@ -33,6 +33,9 @@
#include "core/object/ref_counted.h"
+#include "multiplayer_spawner.h"
+#include "multiplayer_synchronizer.h"
+
class MultiplayerSpawner;
class MultiplayerSynchronizer;
class Node;
diff --git a/scene/multiplayer/scene_rpc_interface.cpp b/modules/multiplayer/scene_rpc_interface.cpp
index 144a10c665..65090b9316 100644
--- a/scene/multiplayer/scene_rpc_interface.cpp
+++ b/modules/multiplayer/scene_rpc_interface.cpp
@@ -28,21 +28,28 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "scene/multiplayer/scene_rpc_interface.h"
+#include "scene_rpc_interface.h"
#include "core/debugger/engine_debugger.h"
#include "core/io/marshalls.h"
-#include "core/multiplayer/multiplayer_api.h"
+#include "scene/main/multiplayer_api.h"
#include "scene/main/node.h"
#include "scene/main/window.h"
-MultiplayerRPCInterface *SceneRPCInterface::_create(MultiplayerAPI *p_multiplayer) {
- return memnew(SceneRPCInterface(p_multiplayer));
-}
+#include "scene_multiplayer.h"
-void SceneRPCInterface::make_default() {
- MultiplayerAPI::create_default_rpc_interface = _create;
-}
+// The RPC meta is composed by a single byte that contains (starting from the least significant bit):
+// - `NetworkCommands` in the first four bits.
+// - `NetworkNodeIdCompression` in the next 2 bits.
+// - `NetworkNameIdCompression` in the next 1 bit.
+// - `byte_only_or_no_args` in the next 1 bit.
+#define NODE_ID_COMPRESSION_SHIFT SceneMultiplayer::CMD_FLAG_0_SHIFT
+#define NAME_ID_COMPRESSION_SHIFT SceneMultiplayer::CMD_FLAG_2_SHIFT
+#define BYTE_ONLY_OR_NO_ARGS_SHIFT SceneMultiplayer::CMD_FLAG_3_SHIFT
+
+#define NODE_ID_COMPRESSION_FLAG ((1 << NODE_ID_COMPRESSION_SHIFT) | (1 << (NODE_ID_COMPRESSION_SHIFT + 1)))
+#define NAME_ID_COMPRESSION_FLAG (1 << NAME_ID_COMPRESSION_SHIFT)
+#define BYTE_ONLY_OR_NO_ARGS_FLAG (1 << BYTE_ONLY_OR_NO_ARGS_SHIFT)
#ifdef DEBUG_ENABLED
_FORCE_INLINE_ void SceneRPCInterface::_profile_node_data(const String &p_what, ObjectID p_id) {
@@ -67,50 +74,58 @@ int get_packet_len(uint32_t p_node_target, int p_packet_len) {
}
}
-const Multiplayer::RPCConfig _get_rpc_config(const Node *p_node, const StringName &p_method, uint16_t &r_id) {
- const Vector<Multiplayer::RPCConfig> node_config = p_node->get_node_rpc_methods();
- for (int i = 0; i < node_config.size(); i++) {
- if (node_config[i].name == p_method) {
- r_id = ((uint16_t)i) | (1 << 15);
- return node_config[i];
- }
+void SceneRPCInterface::_parse_rpc_config(const Variant &p_config, bool p_for_node, RPCConfigCache &r_cache) {
+ if (p_config.get_type() == Variant::NIL) {
+ return;
}
- if (p_node->get_script_instance()) {
- const Vector<Multiplayer::RPCConfig> script_config = p_node->get_script_instance()->get_rpc_methods();
- for (int i = 0; i < script_config.size(); i++) {
- if (script_config[i].name == p_method) {
- r_id = (uint16_t)i;
- return script_config[i];
- }
+ ERR_FAIL_COND(p_config.get_type() != Variant::DICTIONARY);
+ const Dictionary config = p_config;
+ Array names = config.keys();
+ names.sort(); // Ensure ID order
+ for (int i = 0; i < names.size(); i++) {
+ ERR_CONTINUE(names[i].get_type() != Variant::STRING);
+ String name = names[i].operator String();
+ ERR_CONTINUE(config[name].get_type() != Variant::DICTIONARY);
+ ERR_CONTINUE(!config[name].operator Dictionary().has("rpc_mode"));
+ Dictionary dict = config[name];
+ RPCConfig cfg;
+ cfg.name = name;
+ cfg.rpc_mode = ((MultiplayerAPI::RPCMode)dict.get("rpc_mode", MultiplayerAPI::RPC_MODE_AUTHORITY).operator int());
+ cfg.transfer_mode = ((MultiplayerPeer::TransferMode)dict.get("transfer_mode", MultiplayerPeer::TRANSFER_MODE_RELIABLE).operator int());
+ cfg.call_local = dict.get("call_local", false).operator bool();
+ cfg.channel = dict.get("channel", 0).operator int();
+ uint16_t id = ((uint16_t)i);
+ if (p_for_node) {
+ id |= (1 << 15);
}
+ r_cache.configs[id] = cfg;
+ r_cache.ids[name] = id;
}
- return Multiplayer::RPCConfig();
}
-const Multiplayer::RPCConfig _get_rpc_config_by_id(Node *p_node, uint16_t p_id) {
- Vector<Multiplayer::RPCConfig> config;
- uint16_t id = p_id;
- if (id & (1 << 15)) {
- id = id & ~(1 << 15);
- config = p_node->get_node_rpc_methods();
- } else if (p_node->get_script_instance()) {
- config = p_node->get_script_instance()->get_rpc_methods();
+const SceneRPCInterface::RPCConfigCache &SceneRPCInterface::_get_node_config(const Node *p_node) {
+ const ObjectID oid = p_node->get_instance_id();
+ if (rpc_cache.has(oid)) {
+ return rpc_cache[oid];
}
- if (id < config.size()) {
- return config[id];
+ RPCConfigCache cache;
+ _parse_rpc_config(p_node->get_node_rpc_config(), true, cache);
+ if (p_node->get_script_instance()) {
+ _parse_rpc_config(p_node->get_script_instance()->get_rpc_config(), false, cache);
}
- return Multiplayer::RPCConfig();
+ rpc_cache[oid] = cache;
+ return rpc_cache[oid];
}
-_FORCE_INLINE_ bool _can_call_mode(Node *p_node, Multiplayer::RPCMode mode, int p_remote_id) {
+_FORCE_INLINE_ bool _can_call_mode(Node *p_node, MultiplayerAPI::RPCMode mode, int p_remote_id) {
switch (mode) {
- case Multiplayer::RPC_MODE_DISABLED: {
+ case MultiplayerAPI::RPC_MODE_DISABLED: {
return false;
} break;
- case Multiplayer::RPC_MODE_ANY_PEER: {
+ case MultiplayerAPI::RPC_MODE_ANY_PEER: {
return true;
} break;
- case Multiplayer::RPC_MODE_AUTHORITY: {
+ case MultiplayerAPI::RPC_MODE_AUTHORITY: {
return !p_node->is_multiplayer_authority() && p_remote_id == p_node->get_multiplayer_authority();
} break;
}
@@ -118,19 +133,13 @@ _FORCE_INLINE_ bool _can_call_mode(Node *p_node, Multiplayer::RPCMode mode, int
return false;
}
-String SceneRPCInterface::get_rpc_md5(const Object *p_obj) const {
+String SceneRPCInterface::get_rpc_md5(const Object *p_obj) {
const Node *node = Object::cast_to<Node>(p_obj);
ERR_FAIL_COND_V(!node, "");
+ const RPCConfigCache cache = _get_node_config(node);
String rpc_list;
- const Vector<Multiplayer::RPCConfig> node_config = node->get_node_rpc_methods();
- for (int i = 0; i < node_config.size(); i++) {
- rpc_list += String(node_config[i].name);
- }
- if (node->get_script_instance()) {
- const Vector<Multiplayer::RPCConfig> script_config = node->get_script_instance()->get_rpc_methods();
- for (int i = 0; i < script_config.size(); i++) {
- rpc_list += String(script_config[i].name);
- }
+ for (const KeyValue<uint16_t, RPCConfig> &config : cache.configs) {
+ rpc_list += String(config.value.name);
}
return rpc_list.md5_text();
}
@@ -159,7 +168,7 @@ Node *SceneRPCInterface::_process_get_node(int p_from, const uint8_t *p_packet,
return node;
} else {
// Use cached path.
- return Object::cast_to<Node>(multiplayer->get_cached_object(p_from, p_node_target));
+ return Object::cast_to<Node>(multiplayer->get_path_cache()->get_cached_object(p_from, p_node_target));
}
}
@@ -240,8 +249,9 @@ void SceneRPCInterface::_process_rpc(Node *p_node, const uint16_t p_rpc_method_i
ERR_FAIL_COND_MSG(p_offset > p_packet_len, "Invalid packet received. Size too small.");
// Check that remote can call the RPC on this node.
- const Multiplayer::RPCConfig config = _get_rpc_config_by_id(p_node, p_rpc_method_id);
- ERR_FAIL_COND(config.name == StringName());
+ const RPCConfigCache &cache_config = _get_node_config(p_node);
+ ERR_FAIL_COND(!cache_config.configs.has(p_rpc_method_id));
+ const RPCConfig &config = cache_config.configs[p_rpc_method_id];
bool can_call = _can_call_mode(p_node, config.rpc_mode, p_from);
ERR_FAIL_COND_MSG(!can_call, "RPC '" + String(config.name) + "' is not allowed on node " + p_node->get_path() + " from: " + itos(p_from) + ". Mode is " + itos((int)config.rpc_mode) + ", authority is " + itos(p_node->get_multiplayer_authority()) + ".");
@@ -286,7 +296,7 @@ void SceneRPCInterface::_process_rpc(Node *p_node, const uint16_t p_rpc_method_i
}
}
-void SceneRPCInterface::_send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, const Multiplayer::RPCConfig &p_config, const StringName &p_name, const Variant **p_arg, int p_argcount) {
+void SceneRPCInterface::_send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, const RPCConfig &p_config, const StringName &p_name, const Variant **p_arg, int p_argcount) {
Ref<MultiplayerPeer> peer = multiplayer->get_multiplayer_peer();
ERR_FAIL_COND_MSG(peer.is_null(), "Attempt to call RPC without active multiplayer peer.");
@@ -297,14 +307,14 @@ void SceneRPCInterface::_send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, con
ERR_FAIL_COND_MSG(p_argcount > 255, "Too many arguments (>255).");
if (p_to != 0 && !multiplayer->get_connected_peers().has(ABS(p_to))) {
- ERR_FAIL_COND_MSG(p_to == peer->get_unique_id(), "Attempt to call RPC on yourself! Peer unique ID: " + itos(peer->get_unique_id()) + ".");
+ ERR_FAIL_COND_MSG(p_to == multiplayer->get_unique_id(), "Attempt to call RPC on yourself! Peer unique ID: " + itos(multiplayer->get_unique_id()) + ".");
ERR_FAIL_MSG("Attempt to call RPC with unknown peer ID: " + itos(p_to) + ".");
}
// See if all peers have cached path (if so, call can be fast).
int psc_id;
- const bool has_all_peers = multiplayer->send_object_cache(p_from, p_to, psc_id);
+ const bool has_all_peers = multiplayer->get_path_cache()->send_object_cache(p_from, p_to, psc_id);
// Create base packet, lots of hardcode because it must be tight.
@@ -315,7 +325,7 @@ void SceneRPCInterface::_send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, con
packet_cache.resize(m_amount);
// Encode meta.
- uint8_t command_type = MultiplayerAPI::NETWORK_COMMAND_REMOTE_CALL;
+ uint8_t command_type = SceneMultiplayer::NETWORK_COMMAND_REMOTE_CALL;
uint8_t node_id_compression = UINT8_MAX;
uint8_t name_id_compression = UINT8_MAX;
bool byte_only_or_no_args = false;
@@ -426,7 +436,7 @@ void SceneRPCInterface::_send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, con
continue; // Continue, not for this peer.
}
- bool confirmed = multiplayer->is_cache_confirmed(from_path, P);
+ bool confirmed = multiplayer->get_path_cache()->is_cache_confirmed(from_path, P);
peer->set_target_peer(P); // To this one specifically.
@@ -443,22 +453,25 @@ void SceneRPCInterface::_send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, con
}
}
-void SceneRPCInterface::rpcp(Object *p_obj, int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount) {
+Error SceneRPCInterface::rpcp(Object *p_obj, int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount) {
Ref<MultiplayerPeer> peer = multiplayer->get_multiplayer_peer();
- ERR_FAIL_COND_MSG(!peer.is_valid(), "Trying to call an RPC while no multiplayer peer is active.");
+ ERR_FAIL_COND_V_MSG(!peer.is_valid(), ERR_UNCONFIGURED, "Trying to call an RPC while no multiplayer peer is active.");
Node *node = Object::cast_to<Node>(p_obj);
- ERR_FAIL_COND(!node);
- ERR_FAIL_COND_MSG(!node->is_inside_tree(), "Trying to call an RPC on a node which is not inside SceneTree.");
- ERR_FAIL_COND_MSG(peer->get_connection_status() != MultiplayerPeer::CONNECTION_CONNECTED, "Trying to call an RPC via a multiplayer peer which is not connected.");
+ ERR_FAIL_COND_V_MSG(!node || !node->is_inside_tree(), ERR_INVALID_PARAMETER, "The object must be a valid Node inside the SceneTree");
+ ERR_FAIL_COND_V_MSG(peer->get_connection_status() != MultiplayerPeer::CONNECTION_CONNECTED, ERR_CONNECTION_ERROR, "Trying to call an RPC via a multiplayer peer which is not connected.");
- int node_id = peer->get_unique_id();
+ int caller_id = multiplayer->get_unique_id();
bool call_local_native = false;
bool call_local_script = false;
- uint16_t rpc_id = UINT16_MAX;
- const Multiplayer::RPCConfig config = _get_rpc_config(node, p_method, rpc_id);
- ERR_FAIL_COND_MSG(config.name == StringName(),
+ const RPCConfigCache &config_cache = _get_node_config(node);
+ uint16_t rpc_id = config_cache.ids.has(p_method) ? config_cache.ids[p_method] : UINT16_MAX;
+ ERR_FAIL_COND_V_MSG(rpc_id == UINT16_MAX, ERR_INVALID_PARAMETER,
vformat("Unable to get the RPC configuration for the function \"%s\" at path: \"%s\". This happens when the method is missing or not marked for RPCs in the local script.", p_method, node->get_path()));
- if (p_peer_id == 0 || p_peer_id == node_id || (p_peer_id < 0 && p_peer_id != -node_id)) {
+ const RPCConfig &config = config_cache.configs[rpc_id];
+
+ ERR_FAIL_COND_V_MSG(p_peer_id == caller_id && !config.call_local, ERR_INVALID_PARAMETER, "RPC '" + p_method + "' on yourself is not allowed by selected mode.");
+
+ if (p_peer_id == 0 || p_peer_id == caller_id || (p_peer_id < 0 && p_peer_id != -caller_id)) {
if (rpc_id & (1 << 15)) {
call_local_native = config.call_local;
} else {
@@ -466,7 +479,7 @@ void SceneRPCInterface::rpcp(Object *p_obj, int p_peer_id, const StringName &p_m
}
}
- if (p_peer_id != node_id) {
+ if (p_peer_id != caller_id) {
#ifdef DEBUG_ENABLED
_profile_node_data("rpc_out", node->get_instance_id());
#endif
@@ -477,7 +490,7 @@ void SceneRPCInterface::rpcp(Object *p_obj, int p_peer_id, const StringName &p_m
if (call_local_native) {
Callable::CallError ce;
- multiplayer->set_remote_sender_override(peer->get_unique_id());
+ multiplayer->set_remote_sender_override(multiplayer->get_unique_id());
node->callp(p_method, p_arg, p_argcount, ce);
multiplayer->set_remote_sender_override(0);
@@ -485,7 +498,7 @@ void SceneRPCInterface::rpcp(Object *p_obj, int p_peer_id, const StringName &p_m
String error = Variant::get_call_error_text(node, p_method, p_arg, p_argcount, ce);
error = "rpc() aborted in local call: - " + error + ".";
ERR_PRINT(error);
- return;
+ return FAILED;
}
}
@@ -493,7 +506,7 @@ void SceneRPCInterface::rpcp(Object *p_obj, int p_peer_id, const StringName &p_m
Callable::CallError ce;
ce.error = Callable::CallError::CALL_OK;
- multiplayer->set_remote_sender_override(peer->get_unique_id());
+ multiplayer->set_remote_sender_override(multiplayer->get_unique_id());
node->get_script_instance()->callp(p_method, p_arg, p_argcount, ce);
multiplayer->set_remote_sender_override(0);
@@ -501,9 +514,8 @@ void SceneRPCInterface::rpcp(Object *p_obj, int p_peer_id, const StringName &p_m
String error = Variant::get_call_error_text(node, p_method, p_arg, p_argcount, ce);
error = "rpc() aborted in script local call: - " + error + ".";
ERR_PRINT(error);
- return;
+ return FAILED;
}
}
-
- ERR_FAIL_COND_MSG(p_peer_id == node_id && !config.call_local, "RPC '" + p_method + "' on yourself is not allowed by selected mode.");
+ return OK;
}
diff --git a/scene/multiplayer/scene_rpc_interface.h b/modules/multiplayer/scene_rpc_interface.h
index 86e1d0d280..aa9be525a2 100644
--- a/scene/multiplayer/scene_rpc_interface.h
+++ b/modules/multiplayer/scene_rpc_interface.h
@@ -31,13 +31,40 @@
#ifndef SCENE_RPC_INTERFACE_H
#define SCENE_RPC_INTERFACE_H
-#include "core/multiplayer/multiplayer.h"
-#include "core/multiplayer/multiplayer_api.h"
+#include "core/object/ref_counted.h"
+#include "scene/main/multiplayer_api.h"
-class SceneRPCInterface : public MultiplayerRPCInterface {
- GDCLASS(SceneRPCInterface, MultiplayerRPCInterface);
+class SceneMultiplayer;
+class Node;
+
+class SceneRPCInterface : public RefCounted {
+ GDCLASS(SceneRPCInterface, RefCounted);
private:
+ struct RPCConfig {
+ StringName name;
+ MultiplayerAPI::RPCMode rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED;
+ bool call_local = false;
+ MultiplayerPeer::TransferMode transfer_mode = MultiplayerPeer::TRANSFER_MODE_RELIABLE;
+ int channel = 0;
+
+ bool operator==(RPCConfig const &p_other) const {
+ return name == p_other.name;
+ }
+ };
+
+ struct RPCConfigCache {
+ HashMap<uint16_t, RPCConfig> configs;
+ HashMap<StringName, uint16_t> ids;
+ };
+
+ struct SortRPCConfig {
+ StringName::AlphCompare compare;
+ bool operator()(const RPCConfig &p_a, const RPCConfig &p_b) const {
+ return compare(p_a.name, p_b.name);
+ }
+ };
+
enum NetworkNodeIdCompression {
NETWORK_NODE_ID_COMPRESSION_8 = 0,
NETWORK_NODE_ID_COMPRESSION_16,
@@ -49,43 +76,27 @@ private:
NETWORK_NAME_ID_COMPRESSION_16,
};
- // The RPC meta is composed by a single byte that contains (starting from the least significant bit):
- // - `NetworkCommands` in the first four bits.
- // - `NetworkNodeIdCompression` in the next 2 bits.
- // - `NetworkNameIdCompression` in the next 1 bit.
- // - `byte_only_or_no_args` in the next 1 bit.
- enum {
- NODE_ID_COMPRESSION_SHIFT = MultiplayerAPI::CMD_FLAG_0_SHIFT, // 2 bits for this.
- NAME_ID_COMPRESSION_SHIFT = MultiplayerAPI::CMD_FLAG_2_SHIFT,
- BYTE_ONLY_OR_NO_ARGS_SHIFT = MultiplayerAPI::CMD_FLAG_3_SHIFT,
- };
-
- enum {
- NODE_ID_COMPRESSION_FLAG = (1 << NODE_ID_COMPRESSION_SHIFT) | (1 << (NODE_ID_COMPRESSION_SHIFT + 1)), // 2 bits for this.
- NAME_ID_COMPRESSION_FLAG = (1 << NAME_ID_COMPRESSION_SHIFT),
- BYTE_ONLY_OR_NO_ARGS_FLAG = (1 << BYTE_ONLY_OR_NO_ARGS_SHIFT),
- };
-
- MultiplayerAPI *multiplayer = nullptr;
+ SceneMultiplayer *multiplayer = nullptr;
Vector<uint8_t> packet_cache;
-protected:
- static MultiplayerRPCInterface *_create(MultiplayerAPI *p_multiplayer);
+ HashMap<ObjectID, RPCConfigCache> rpc_cache;
+protected:
_FORCE_INLINE_ void _profile_node_data(const String &p_what, ObjectID p_id);
void _process_rpc(Node *p_node, const uint16_t p_rpc_method_id, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset);
- void _send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, const Multiplayer::RPCConfig &p_config, const StringName &p_name, const Variant **p_arg, int p_argcount);
+ void _send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, const RPCConfig &p_config, const StringName &p_name, const Variant **p_arg, int p_argcount);
Node *_process_get_node(int p_from, const uint8_t *p_packet, uint32_t p_node_target, int p_packet_len);
-public:
- static void make_default();
+ void _parse_rpc_config(const Variant &p_config, bool p_for_node, RPCConfigCache &r_cache);
+ const RPCConfigCache &_get_node_config(const Node *p_node);
- virtual void rpcp(Object *p_obj, int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount) override;
- virtual void process_rpc(int p_from, const uint8_t *p_packet, int p_packet_len) override;
- virtual String get_rpc_md5(const Object *p_obj) const override;
+public:
+ Error rpcp(Object *p_obj, int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount);
+ void process_rpc(int p_from, const uint8_t *p_packet, int p_packet_len);
+ String get_rpc_md5(const Object *p_obj);
- SceneRPCInterface(MultiplayerAPI *p_multiplayer) { multiplayer = p_multiplayer; }
+ SceneRPCInterface(SceneMultiplayer *p_multiplayer) { multiplayer = p_multiplayer; }
};
#endif // SCENE_RPC_INTERFACE_H
diff --git a/modules/ogg/config.py b/modules/ogg/config.py
index 5a417ba8dd..f7ec4de6be 100644
--- a/modules/ogg/config.py
+++ b/modules/ogg/config.py
@@ -8,8 +8,8 @@ def configure(env):
def get_doc_classes():
return [
- "OGGPacketSequence",
- "OGGPacketSequencePlayback",
+ "OggPacketSequence",
+ "OggPacketSequencePlayback",
]
diff --git a/modules/ogg/doc_classes/OGGPacketSequence.xml b/modules/ogg/doc_classes/OggPacketSequence.xml
index bff3691ce0..d3bd4455d8 100644
--- a/modules/ogg/doc_classes/OGGPacketSequence.xml
+++ b/modules/ogg/doc_classes/OggPacketSequence.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="OGGPacketSequence" inherits="Resource" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
+<class name="OggPacketSequence" inherits="Resource" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
<brief_description>
- A sequence of OGG packets.
+ A sequence of Ogg packets.
</brief_description>
<description>
- A sequence of OGG packets.
+ A sequence of Ogg packets.
</description>
<tutorials>
</tutorials>
@@ -21,7 +21,7 @@
Contains the granule positions for each page in this packet sequence.
</member>
<member name="packet_data" type="Array" setter="set_packet_data" getter="get_packet_data" default="[]">
- Contains the raw packets that make up this OGGPacketSequence.
+ Contains the raw packets that make up this OggPacketSequence.
</member>
<member name="sampling_rate" type="float" setter="set_sampling_rate" getter="get_sampling_rate" default="0.0">
Holds sample rate information about this sequence. Must be set by another class that actually understands the codec.
diff --git a/modules/ogg/doc_classes/OGGPacketSequencePlayback.xml b/modules/ogg/doc_classes/OggPacketSequencePlayback.xml
index 11fc1f4cb6..5c0d75278b 100644
--- a/modules/ogg/doc_classes/OGGPacketSequencePlayback.xml
+++ b/modules/ogg/doc_classes/OggPacketSequencePlayback.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="OGGPacketSequencePlayback" inherits="RefCounted" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
+<class name="OggPacketSequencePlayback" inherits="RefCounted" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
<brief_description>
</brief_description>
<description>
diff --git a/modules/ogg/ogg_packet_sequence.cpp b/modules/ogg/ogg_packet_sequence.cpp
index e18fa9e590..de8bf4a087 100644
--- a/modules/ogg/ogg_packet_sequence.cpp
+++ b/modules/ogg/ogg_packet_sequence.cpp
@@ -31,7 +31,7 @@
#include "ogg_packet_sequence.h"
#include "core/variant/typed_array.h"
-void OGGPacketSequence::push_page(int64_t p_granule_pos, const Vector<PackedByteArray> &p_data) {
+void OggPacketSequence::push_page(int64_t p_granule_pos, const Vector<PackedByteArray> &p_data) {
Vector<PackedByteArray> data_stored;
for (int i = 0; i < p_data.size(); i++) {
data_stored.push_back(p_data[i]);
@@ -41,7 +41,7 @@ void OGGPacketSequence::push_page(int64_t p_granule_pos, const Vector<PackedByte
data_version++;
}
-void OGGPacketSequence::set_packet_data(const Array &p_data) {
+void OggPacketSequence::set_packet_data(const Array &p_data) {
data_version++; // Update the data version so old playbacks know that they can't rely on us anymore.
page_data.clear();
for (int page_idx = 0; page_idx < p_data.size(); page_idx++) {
@@ -54,7 +54,7 @@ void OGGPacketSequence::set_packet_data(const Array &p_data) {
}
}
-Array OGGPacketSequence::get_packet_data() const {
+Array OggPacketSequence::get_packet_data() const {
Array ret;
for (const Vector<PackedByteArray> &page : page_data) {
Array page_variant;
@@ -66,7 +66,7 @@ Array OGGPacketSequence::get_packet_data() const {
return ret;
}
-void OGGPacketSequence::set_packet_granule_positions(const Array &p_granule_positions) {
+void OggPacketSequence::set_packet_granule_positions(const Array &p_granule_positions) {
data_version++; // Update the data version so old playbacks know that they can't rely on us anymore.
page_granule_positions.clear();
for (int page_idx = 0; page_idx < p_granule_positions.size(); page_idx++) {
@@ -75,7 +75,7 @@ void OGGPacketSequence::set_packet_granule_positions(const Array &p_granule_posi
}
}
-Array OGGPacketSequence::get_packet_granule_positions() const {
+Array OggPacketSequence::get_packet_granule_positions() const {
Array ret;
for (int64_t granule_pos : page_granule_positions) {
ret.push_back(granule_pos);
@@ -83,22 +83,22 @@ Array OGGPacketSequence::get_packet_granule_positions() const {
return ret;
}
-void OGGPacketSequence::set_sampling_rate(float p_sampling_rate) {
+void OggPacketSequence::set_sampling_rate(float p_sampling_rate) {
sampling_rate = p_sampling_rate;
}
-float OGGPacketSequence::get_sampling_rate() const {
+float OggPacketSequence::get_sampling_rate() const {
return sampling_rate;
}
-int64_t OGGPacketSequence::get_final_granule_pos() const {
+int64_t OggPacketSequence::get_final_granule_pos() const {
if (!page_granule_positions.is_empty()) {
return page_granule_positions[page_granule_positions.size() - 1];
}
return -1;
}
-float OGGPacketSequence::get_length() const {
+float OggPacketSequence::get_length() const {
int64_t granule_pos = get_final_granule_pos();
if (granule_pos < 0) {
return 0;
@@ -106,33 +106,33 @@ float OGGPacketSequence::get_length() const {
return granule_pos / sampling_rate;
}
-Ref<OGGPacketSequencePlayback> OGGPacketSequence::instantiate_playback() {
- Ref<OGGPacketSequencePlayback> playback;
+Ref<OggPacketSequencePlayback> OggPacketSequence::instantiate_playback() {
+ Ref<OggPacketSequencePlayback> playback;
playback.instantiate();
- playback->ogg_packet_sequence = Ref<OGGPacketSequence>(this);
+ playback->ogg_packet_sequence = Ref<OggPacketSequence>(this);
playback->data_version = data_version;
return playback;
}
-void OGGPacketSequence::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_packet_data", "packet_data"), &OGGPacketSequence::set_packet_data);
- ClassDB::bind_method(D_METHOD("get_packet_data"), &OGGPacketSequence::get_packet_data);
+void OggPacketSequence::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_packet_data", "packet_data"), &OggPacketSequence::set_packet_data);
+ ClassDB::bind_method(D_METHOD("get_packet_data"), &OggPacketSequence::get_packet_data);
- ClassDB::bind_method(D_METHOD("set_packet_granule_positions", "granule_positions"), &OGGPacketSequence::set_packet_granule_positions);
- ClassDB::bind_method(D_METHOD("get_packet_granule_positions"), &OGGPacketSequence::get_packet_granule_positions);
+ ClassDB::bind_method(D_METHOD("set_packet_granule_positions", "granule_positions"), &OggPacketSequence::set_packet_granule_positions);
+ ClassDB::bind_method(D_METHOD("get_packet_granule_positions"), &OggPacketSequence::get_packet_granule_positions);
- ClassDB::bind_method(D_METHOD("set_sampling_rate", "sampling_rate"), &OGGPacketSequence::set_sampling_rate);
- ClassDB::bind_method(D_METHOD("get_sampling_rate"), &OGGPacketSequence::get_sampling_rate);
+ ClassDB::bind_method(D_METHOD("set_sampling_rate", "sampling_rate"), &OggPacketSequence::set_sampling_rate);
+ ClassDB::bind_method(D_METHOD("get_sampling_rate"), &OggPacketSequence::get_sampling_rate);
- ClassDB::bind_method(D_METHOD("get_length"), &OGGPacketSequence::get_length);
+ ClassDB::bind_method(D_METHOD("get_length"), &OggPacketSequence::get_length);
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "packet_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_packet_data", "get_packet_data");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "granule_positions", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_packet_granule_positions", "get_packet_granule_positions");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sampling_rate", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_sampling_rate", "get_sampling_rate");
}
-bool OGGPacketSequencePlayback::next_ogg_packet(ogg_packet **p_packet) const {
+bool OggPacketSequencePlayback::next_ogg_packet(ogg_packet **p_packet) const {
ERR_FAIL_COND_V(data_version != ogg_packet_sequence->data_version, false);
ERR_FAIL_COND_V(ogg_packet_sequence->page_data.is_empty(), false);
ERR_FAIL_COND_V(ogg_packet_sequence->page_granule_positions.is_empty(), false);
@@ -161,7 +161,7 @@ bool OGGPacketSequencePlayback::next_ogg_packet(ogg_packet **p_packet) const {
return true;
}
-uint32_t OGGPacketSequencePlayback::seek_page_internal(int64_t granule, uint32_t after_page_inclusive, uint32_t before_page_inclusive) {
+uint32_t OggPacketSequencePlayback::seek_page_internal(int64_t granule, uint32_t after_page_inclusive, uint32_t before_page_inclusive) {
// FIXME: This function needs better corner case handling.
if (before_page_inclusive == after_page_inclusive) {
return before_page_inclusive;
@@ -198,7 +198,7 @@ uint32_t OGGPacketSequencePlayback::seek_page_internal(int64_t granule, uint32_t
}
}
-bool OGGPacketSequencePlayback::seek_page(int64_t p_granule_pos) {
+bool OggPacketSequencePlayback::seek_page(int64_t p_granule_pos) {
int correct_page = seek_page_internal(p_granule_pos, 0, ogg_packet_sequence->page_data.size() - 1);
if (correct_page == -1) {
return false;
@@ -213,10 +213,10 @@ bool OGGPacketSequencePlayback::seek_page(int64_t p_granule_pos) {
return true;
}
-OGGPacketSequencePlayback::OGGPacketSequencePlayback() {
+OggPacketSequencePlayback::OggPacketSequencePlayback() {
packet = new ogg_packet();
}
-OGGPacketSequencePlayback::~OGGPacketSequencePlayback() {
+OggPacketSequencePlayback::~OggPacketSequencePlayback() {
delete packet;
}
diff --git a/modules/ogg/ogg_packet_sequence.h b/modules/ogg/ogg_packet_sequence.h
index 76b673c6ac..efd3b64a39 100644
--- a/modules/ogg/ogg_packet_sequence.h
+++ b/modules/ogg/ogg_packet_sequence.h
@@ -38,12 +38,12 @@
#include "core/variant/variant.h"
#include "thirdparty/libogg/ogg/ogg.h"
-class OGGPacketSequencePlayback;
+class OggPacketSequencePlayback;
-class OGGPacketSequence : public Resource {
- GDCLASS(OGGPacketSequence, Resource);
+class OggPacketSequence : public Resource {
+ GDCLASS(OggPacketSequence, Resource);
- friend class OGGPacketSequencePlayback;
+ friend class OggPacketSequencePlayback;
// List of pages, each of which is a list of packets on that page. The innermost PackedByteArrays contain complete ogg packets.
Vector<Vector<PackedByteArray>> page_data;
@@ -73,7 +73,7 @@ public:
void set_packet_granule_positions(const Array &p_granule_positions);
Array get_packet_granule_positions() const;
- // Sets a sampling rate associated with this object. OGGPacketSequence doesn't understand codecs,
+ // Sets a sampling rate associated with this object. OggPacketSequence doesn't understand codecs,
// so this value is naively stored as a convenience.
void set_sampling_rate(float p_sampling_rate);
@@ -86,18 +86,18 @@ public:
// Returns the granule position of the last page in this sequence.
int64_t get_final_granule_pos() const;
- Ref<OGGPacketSequencePlayback> instantiate_playback();
+ Ref<OggPacketSequencePlayback> instantiate_playback();
- OGGPacketSequence() {}
- virtual ~OGGPacketSequence() {}
+ OggPacketSequence() {}
+ virtual ~OggPacketSequence() {}
};
-class OGGPacketSequencePlayback : public RefCounted {
- GDCLASS(OGGPacketSequencePlayback, RefCounted);
+class OggPacketSequencePlayback : public RefCounted {
+ GDCLASS(OggPacketSequencePlayback, RefCounted);
- friend class OGGPacketSequence;
+ friend class OggPacketSequence;
- Ref<OGGPacketSequence> ogg_packet_sequence;
+ Ref<OggPacketSequence> ogg_packet_sequence;
mutable int64_t page_cursor = 0;
mutable int32_t packet_cursor = 0;
@@ -121,8 +121,8 @@ public:
// Returns true on success, false on failure.
bool seek_page(int64_t p_granule_pos);
- OGGPacketSequencePlayback();
- virtual ~OGGPacketSequencePlayback();
+ OggPacketSequencePlayback();
+ virtual ~OggPacketSequencePlayback();
};
#endif // OGG_PACKET_SEQUENCE_H
diff --git a/modules/ogg/register_types.cpp b/modules/ogg/register_types.cpp
index 01f04aa3d5..aca6d1e1f8 100644
--- a/modules/ogg/register_types.cpp
+++ b/modules/ogg/register_types.cpp
@@ -37,8 +37,8 @@ void initialize_ogg_module(ModuleInitializationLevel p_level) {
return;
}
- GDREGISTER_CLASS(OGGPacketSequence);
- GDREGISTER_CLASS(OGGPacketSequencePlayback);
+ GDREGISTER_CLASS(OggPacketSequence);
+ GDREGISTER_CLASS(OggPacketSequencePlayback);
}
void uninitialize_ogg_module(ModuleInitializationLevel p_level) {
diff --git a/modules/openxr/openxr_api.cpp b/modules/openxr/openxr_api.cpp
index 938b017e3a..92d074cb75 100644
--- a/modules/openxr/openxr_api.cpp
+++ b/modules/openxr/openxr_api.cpp
@@ -58,19 +58,14 @@ bool OpenXRAPI::openxr_is_enabled(bool p_check_run_in_editor) {
// @TODO we need an overrule switch so we can force enable openxr, i.e run "godot --openxr_enabled"
if (Engine::get_singleton()->is_editor_hint() && p_check_run_in_editor) {
-#ifdef TOOLS_ENABLED
// Disabled for now, using XR inside of the editor we'll be working on during the coming months.
return false;
-
- // bool enabled = GLOBAL_GET("xr/openxr/in_editor"); // EDITOR_GET("xr/openxr/in_editor");
- // return enabled;
-#else
- // we should never get here, editor hint won't be true if the editor isn't compiled in.
- return false;
-#endif
} else {
- bool enabled = GLOBAL_GET("xr/openxr/enabled");
- return enabled;
+ if (XRServer::get_xr_mode() == XRServer::XRMODE_DEFAULT) {
+ return GLOBAL_GET("xr/openxr/enabled");
+ } else {
+ return XRServer::get_xr_mode() == XRServer::XRMODE_ON;
+ }
}
}
diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp
index 742fa75bb7..1ef3723011 100644
--- a/modules/visual_script/visual_script.cpp
+++ b/modules/visual_script/visual_script.cpp
@@ -948,7 +948,7 @@ bool VisualScript::are_subnodes_edited() const {
}
#endif
-const Vector<Multiplayer::RPCConfig> VisualScript::get_rpc_methods() const {
+const Variant VisualScript::get_rpc_config() const {
return rpc_functions;
}
@@ -1012,22 +1012,16 @@ void VisualScript::_set_data(const Dictionary &p_data) {
for (const KeyValue<StringName, Function> &E : functions) {
if (E.value.func_id >= 0 && nodes.has(E.value.func_id)) {
Ref<VisualScriptFunction> vsf = nodes[E.value.func_id].node;
- if (vsf.is_valid()) {
- if (vsf->get_rpc_mode() != Multiplayer::RPC_MODE_DISABLED) {
- Multiplayer::RPCConfig nd;
- nd.name = E.key;
- nd.rpc_mode = vsf->get_rpc_mode();
- nd.transfer_mode = Multiplayer::TRANSFER_MODE_RELIABLE; // TODO
- if (rpc_functions.find(nd) == -1) {
- rpc_functions.push_back(nd);
- }
- }
+ if (!vsf.is_valid() || vsf->get_rpc_mode() == MultiplayerAPI::RPC_MODE_DISABLED) {
+ continue;
}
+ Dictionary nd;
+ nd["rpc_mode"] = vsf->get_rpc_mode();
+ nd["transfer_mode"] = MultiplayerPeer::TRANSFER_MODE_RELIABLE; // TODO
+ nd["call_local"] = false; // TODO
+ rpc_functions[E.key] = nd;
}
}
-
- // Sort so we are 100% that they are always the same.
- rpc_functions.sort_custom<Multiplayer::SortRPCConfig>();
}
Dictionary VisualScript::_get_data() const {
@@ -1811,8 +1805,8 @@ Ref<Script> VisualScriptInstance::get_script() const {
return script;
}
-const Vector<Multiplayer::RPCConfig> VisualScriptInstance::get_rpc_methods() const {
- return script->get_rpc_methods();
+const Variant VisualScriptInstance::get_rpc_config() const {
+ return script->get_rpc_config();
}
void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_owner) {
diff --git a/modules/visual_script/visual_script.h b/modules/visual_script/visual_script.h
index 716310f59b..14cb14e8d9 100644
--- a/modules/visual_script/visual_script.h
+++ b/modules/visual_script/visual_script.h
@@ -235,7 +235,7 @@ private:
HashMap<StringName, Function> functions;
HashMap<StringName, Variable> variables;
HashMap<StringName, Vector<Argument>> custom_signals;
- Vector<Multiplayer::RPCConfig> rpc_functions;
+ Dictionary rpc_functions;
HashMap<Object *, VisualScriptInstance *> instances;
@@ -363,7 +363,7 @@ public:
virtual int get_member_line(const StringName &p_member) const override;
- virtual const Vector<Multiplayer::RPCConfig> get_rpc_methods() const override;
+ virtual const Variant get_rpc_config() const override;
#ifdef TOOLS_ENABLED
virtual bool are_subnodes_edited() const;
@@ -444,7 +444,7 @@ public:
virtual ScriptLanguage *get_language();
- virtual const Vector<Multiplayer::RPCConfig> get_rpc_methods() const;
+ virtual const Variant get_rpc_config() const;
VisualScriptInstance();
~VisualScriptInstance();
diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp
index 41f5b28677..5907e6a489 100644
--- a/modules/visual_script/visual_script_nodes.cpp
+++ b/modules/visual_script/visual_script_nodes.cpp
@@ -90,7 +90,7 @@ bool VisualScriptFunction::_set(const StringName &p_name, const Variant &p_value
}
if (p_name == "rpc/mode") {
- rpc_mode = Multiplayer::RPCMode(int(p_value));
+ rpc_mode = MultiplayerAPI::RPCMode(int(p_value));
return true;
}
@@ -261,11 +261,11 @@ int VisualScriptFunction::get_argument_count() const {
return arguments.size();
}
-void VisualScriptFunction::set_rpc_mode(Multiplayer::RPCMode p_mode) {
+void VisualScriptFunction::set_rpc_mode(MultiplayerAPI::RPCMode p_mode) {
rpc_mode = p_mode;
}
-Multiplayer::RPCMode VisualScriptFunction::get_rpc_mode() const {
+MultiplayerAPI::RPCMode VisualScriptFunction::get_rpc_mode() const {
return rpc_mode;
}
@@ -311,14 +311,14 @@ void VisualScriptFunction::reset_state() {
stack_size = 256;
stack_less = false;
sequenced = true;
- rpc_mode = Multiplayer::RPC_MODE_DISABLED;
+ rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED;
}
VisualScriptFunction::VisualScriptFunction() {
stack_size = 256;
stack_less = false;
sequenced = true;
- rpc_mode = Multiplayer::RPC_MODE_DISABLED;
+ rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED;
}
void VisualScriptFunction::set_stack_less(bool p_enable) {
diff --git a/modules/visual_script/visual_script_nodes.h b/modules/visual_script/visual_script_nodes.h
index 18573f8682..35e3c490cd 100644
--- a/modules/visual_script/visual_script_nodes.h
+++ b/modules/visual_script/visual_script_nodes.h
@@ -33,6 +33,7 @@
#include "core/object/gdvirtual.gen.inc"
#include "core/object/script_language.h"
+#include "scene/main/multiplayer_api.h"
#include "visual_script.h"
class VisualScriptFunction : public VisualScriptNode {
@@ -49,7 +50,7 @@ class VisualScriptFunction : public VisualScriptNode {
bool stack_less;
int stack_size;
- Multiplayer::RPCMode rpc_mode;
+ MultiplayerAPI::RPCMode rpc_mode;
bool sequenced;
protected:
@@ -90,8 +91,8 @@ public:
void set_stack_size(int p_size);
int get_stack_size() const;
- void set_rpc_mode(Multiplayer::RPCMode p_mode);
- Multiplayer::RPCMode get_rpc_mode() const;
+ void set_rpc_mode(MultiplayerAPI::RPCMode p_mode);
+ MultiplayerAPI::RPCMode get_rpc_mode() const;
virtual VisualScriptNodeInstance *instantiate(VisualScriptInstance *p_instance) override;
diff --git a/modules/vorbis/audio_stream_ogg_vorbis.cpp b/modules/vorbis/audio_stream_ogg_vorbis.cpp
index 76f7317daa..8315eea614 100644
--- a/modules/vorbis/audio_stream_ogg_vorbis.cpp
+++ b/modules/vorbis/audio_stream_ogg_vorbis.cpp
@@ -34,7 +34,7 @@
#include "core/variant/typed_array.h"
#include "thirdparty/libogg/ogg/ogg.h"
-int AudioStreamPlaybackOGGVorbis::_mix_internal(AudioFrame *p_buffer, int p_frames) {
+int AudioStreamPlaybackOggVorbis::_mix_internal(AudioFrame *p_buffer, int p_frames) {
ERR_FAIL_COND_V(!ready, 0);
if (!active) {
@@ -141,7 +141,7 @@ int AudioStreamPlaybackOGGVorbis::_mix_internal(AudioFrame *p_buffer, int p_fram
return p_frames - todo;
}
-int AudioStreamPlaybackOGGVorbis::_mix_frames_vorbis(AudioFrame *p_buffer, int p_frames) {
+int AudioStreamPlaybackOggVorbis::_mix_frames_vorbis(AudioFrame *p_buffer, int p_frames) {
ERR_FAIL_COND_V(!ready, 0);
if (!have_samples_left) {
ogg_packet *packet = nullptr;
@@ -184,11 +184,11 @@ int AudioStreamPlaybackOGGVorbis::_mix_frames_vorbis(AudioFrame *p_buffer, int p
return frames;
}
-float AudioStreamPlaybackOGGVorbis::get_stream_sampling_rate() {
+float AudioStreamPlaybackOggVorbis::get_stream_sampling_rate() {
return vorbis_data->get_sampling_rate();
}
-bool AudioStreamPlaybackOGGVorbis::_alloc_vorbis() {
+bool AudioStreamPlaybackOggVorbis::_alloc_vorbis() {
vorbis_info_init(&info);
info_is_allocated = true;
vorbis_comment_init(&comment);
@@ -223,7 +223,7 @@ bool AudioStreamPlaybackOGGVorbis::_alloc_vorbis() {
return true;
}
-void AudioStreamPlaybackOGGVorbis::start(float p_from_pos) {
+void AudioStreamPlaybackOggVorbis::start(float p_from_pos) {
ERR_FAIL_COND(!ready);
loop_fade_remaining = FADE_SIZE;
active = true;
@@ -232,27 +232,27 @@ void AudioStreamPlaybackOGGVorbis::start(float p_from_pos) {
begin_resample();
}
-void AudioStreamPlaybackOGGVorbis::stop() {
+void AudioStreamPlaybackOggVorbis::stop() {
active = false;
}
-bool AudioStreamPlaybackOGGVorbis::is_playing() const {
+bool AudioStreamPlaybackOggVorbis::is_playing() const {
return active;
}
-int AudioStreamPlaybackOGGVorbis::get_loop_count() const {
+int AudioStreamPlaybackOggVorbis::get_loop_count() const {
return loops;
}
-float AudioStreamPlaybackOGGVorbis::get_playback_position() const {
+float AudioStreamPlaybackOggVorbis::get_playback_position() const {
return float(frames_mixed) / vorbis_data->get_sampling_rate();
}
-void AudioStreamPlaybackOGGVorbis::tag_used_streams() {
+void AudioStreamPlaybackOggVorbis::tag_used_streams() {
vorbis_stream->tag_used(get_playback_position());
}
-void AudioStreamPlaybackOGGVorbis::seek(float p_time) {
+void AudioStreamPlaybackOggVorbis::seek(float p_time) {
ERR_FAIL_COND(!ready);
ERR_FAIL_COND(vorbis_stream.is_null());
if (!active) {
@@ -370,7 +370,7 @@ void AudioStreamPlaybackOGGVorbis::seek(float p_time) {
}
}
-AudioStreamPlaybackOGGVorbis::~AudioStreamPlaybackOGGVorbis() {
+AudioStreamPlaybackOggVorbis::~AudioStreamPlaybackOggVorbis() {
if (block_is_allocated) {
vorbis_block_clear(&block);
}
@@ -385,13 +385,13 @@ AudioStreamPlaybackOGGVorbis::~AudioStreamPlaybackOGGVorbis() {
}
}
-Ref<AudioStreamPlayback> AudioStreamOGGVorbis::instantiate_playback() {
- Ref<AudioStreamPlaybackOGGVorbis> ovs;
+Ref<AudioStreamPlayback> AudioStreamOggVorbis::instantiate_playback() {
+ Ref<AudioStreamPlaybackOggVorbis> ovs;
ERR_FAIL_COND_V(packet_sequence.is_null(), nullptr);
ovs.instantiate();
- ovs->vorbis_stream = Ref<AudioStreamOGGVorbis>(this);
+ ovs->vorbis_stream = Ref<AudioStreamOggVorbis>(this);
ovs->vorbis_data = packet_sequence;
ovs->frames_mixed = 0;
ovs->active = false;
@@ -403,11 +403,11 @@ Ref<AudioStreamPlayback> AudioStreamOGGVorbis::instantiate_playback() {
return nullptr;
}
-String AudioStreamOGGVorbis::get_stream_name() const {
+String AudioStreamOggVorbis::get_stream_name() const {
return ""; //return stream_name;
}
-void AudioStreamOGGVorbis::maybe_update_info() {
+void AudioStreamOggVorbis::maybe_update_info() {
ERR_FAIL_COND(packet_sequence.is_null());
vorbis_info info;
@@ -417,7 +417,7 @@ void AudioStreamOGGVorbis::maybe_update_info() {
vorbis_info_init(&info);
vorbis_comment_init(&comment);
- Ref<OGGPacketSequencePlayback> packet_sequence_playback = packet_sequence->instantiate_playback();
+ Ref<OggPacketSequencePlayback> packet_sequence_playback = packet_sequence->instantiate_playback();
for (int i = 0; i < 3; i++) {
ogg_packet *packet;
@@ -443,90 +443,90 @@ void AudioStreamOGGVorbis::maybe_update_info() {
vorbis_info_clear(&info);
}
-void AudioStreamOGGVorbis::set_packet_sequence(Ref<OGGPacketSequence> p_packet_sequence) {
+void AudioStreamOggVorbis::set_packet_sequence(Ref<OggPacketSequence> p_packet_sequence) {
packet_sequence = p_packet_sequence;
if (packet_sequence.is_valid()) {
maybe_update_info();
}
}
-Ref<OGGPacketSequence> AudioStreamOGGVorbis::get_packet_sequence() const {
+Ref<OggPacketSequence> AudioStreamOggVorbis::get_packet_sequence() const {
return packet_sequence;
}
-void AudioStreamOGGVorbis::set_loop(bool p_enable) {
+void AudioStreamOggVorbis::set_loop(bool p_enable) {
loop = p_enable;
}
-bool AudioStreamOGGVorbis::has_loop() const {
+bool AudioStreamOggVorbis::has_loop() const {
return loop;
}
-void AudioStreamOGGVorbis::set_loop_offset(float p_seconds) {
+void AudioStreamOggVorbis::set_loop_offset(float p_seconds) {
loop_offset = p_seconds;
}
-float AudioStreamOGGVorbis::get_loop_offset() const {
+float AudioStreamOggVorbis::get_loop_offset() const {
return loop_offset;
}
-float AudioStreamOGGVorbis::get_length() const {
+float AudioStreamOggVorbis::get_length() const {
ERR_FAIL_COND_V(packet_sequence.is_null(), 0);
return packet_sequence->get_length();
}
-void AudioStreamOGGVorbis::set_bpm(double p_bpm) {
+void AudioStreamOggVorbis::set_bpm(double p_bpm) {
ERR_FAIL_COND(p_bpm < 0);
bpm = p_bpm;
emit_changed();
}
-double AudioStreamOGGVorbis::get_bpm() const {
+double AudioStreamOggVorbis::get_bpm() const {
return bpm;
}
-void AudioStreamOGGVorbis::set_beat_count(int p_beat_count) {
+void AudioStreamOggVorbis::set_beat_count(int p_beat_count) {
ERR_FAIL_COND(p_beat_count < 0);
beat_count = p_beat_count;
emit_changed();
}
-int AudioStreamOGGVorbis::get_beat_count() const {
+int AudioStreamOggVorbis::get_beat_count() const {
return beat_count;
}
-void AudioStreamOGGVorbis::set_bar_beats(int p_bar_beats) {
+void AudioStreamOggVorbis::set_bar_beats(int p_bar_beats) {
ERR_FAIL_COND(p_bar_beats < 2);
bar_beats = p_bar_beats;
emit_changed();
}
-int AudioStreamOGGVorbis::get_bar_beats() const {
+int AudioStreamOggVorbis::get_bar_beats() const {
return bar_beats;
}
-bool AudioStreamOGGVorbis::is_monophonic() const {
+bool AudioStreamOggVorbis::is_monophonic() const {
return false;
}
-void AudioStreamOGGVorbis::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_packet_sequence", "packet_sequence"), &AudioStreamOGGVorbis::set_packet_sequence);
- ClassDB::bind_method(D_METHOD("get_packet_sequence"), &AudioStreamOGGVorbis::get_packet_sequence);
+void AudioStreamOggVorbis::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_packet_sequence", "packet_sequence"), &AudioStreamOggVorbis::set_packet_sequence);
+ ClassDB::bind_method(D_METHOD("get_packet_sequence"), &AudioStreamOggVorbis::get_packet_sequence);
- ClassDB::bind_method(D_METHOD("set_loop", "enable"), &AudioStreamOGGVorbis::set_loop);
- ClassDB::bind_method(D_METHOD("has_loop"), &AudioStreamOGGVorbis::has_loop);
+ ClassDB::bind_method(D_METHOD("set_loop", "enable"), &AudioStreamOggVorbis::set_loop);
+ ClassDB::bind_method(D_METHOD("has_loop"), &AudioStreamOggVorbis::has_loop);
- ClassDB::bind_method(D_METHOD("set_loop_offset", "seconds"), &AudioStreamOGGVorbis::set_loop_offset);
- ClassDB::bind_method(D_METHOD("get_loop_offset"), &AudioStreamOGGVorbis::get_loop_offset);
+ ClassDB::bind_method(D_METHOD("set_loop_offset", "seconds"), &AudioStreamOggVorbis::set_loop_offset);
+ ClassDB::bind_method(D_METHOD("get_loop_offset"), &AudioStreamOggVorbis::get_loop_offset);
- ClassDB::bind_method(D_METHOD("set_bpm", "bpm"), &AudioStreamOGGVorbis::set_bpm);
- ClassDB::bind_method(D_METHOD("get_bpm"), &AudioStreamOGGVorbis::get_bpm);
+ ClassDB::bind_method(D_METHOD("set_bpm", "bpm"), &AudioStreamOggVorbis::set_bpm);
+ ClassDB::bind_method(D_METHOD("get_bpm"), &AudioStreamOggVorbis::get_bpm);
- ClassDB::bind_method(D_METHOD("set_beat_count", "count"), &AudioStreamOGGVorbis::set_beat_count);
- ClassDB::bind_method(D_METHOD("get_beat_count"), &AudioStreamOGGVorbis::get_beat_count);
+ ClassDB::bind_method(D_METHOD("set_beat_count", "count"), &AudioStreamOggVorbis::set_beat_count);
+ ClassDB::bind_method(D_METHOD("get_beat_count"), &AudioStreamOggVorbis::get_beat_count);
- ClassDB::bind_method(D_METHOD("set_bar_beats", "count"), &AudioStreamOGGVorbis::set_bar_beats);
- ClassDB::bind_method(D_METHOD("get_bar_beats"), &AudioStreamOGGVorbis::get_bar_beats);
+ ClassDB::bind_method(D_METHOD("set_bar_beats", "count"), &AudioStreamOggVorbis::set_bar_beats);
+ ClassDB::bind_method(D_METHOD("get_bar_beats"), &AudioStreamOggVorbis::get_bar_beats);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "packet_sequence", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_packet_sequence", "get_packet_sequence");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bpm", PROPERTY_HINT_RANGE, "0,400,0.01,or_greater"), "set_bpm", "get_bpm");
@@ -536,6 +536,6 @@ void AudioStreamOGGVorbis::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "loop_offset"), "set_loop_offset", "get_loop_offset");
}
-AudioStreamOGGVorbis::AudioStreamOGGVorbis() {}
+AudioStreamOggVorbis::AudioStreamOggVorbis() {}
-AudioStreamOGGVorbis::~AudioStreamOGGVorbis() {}
+AudioStreamOggVorbis::~AudioStreamOggVorbis() {}
diff --git a/modules/vorbis/audio_stream_ogg_vorbis.h b/modules/vorbis/audio_stream_ogg_vorbis.h
index 9b6d928d87..0350e1f761 100644
--- a/modules/vorbis/audio_stream_ogg_vorbis.h
+++ b/modules/vorbis/audio_stream_ogg_vorbis.h
@@ -36,10 +36,10 @@
#include "servers/audio/audio_stream.h"
#include "thirdparty/libvorbis/vorbis/codec.h"
-class AudioStreamOGGVorbis;
+class AudioStreamOggVorbis;
-class AudioStreamPlaybackOGGVorbis : public AudioStreamPlaybackResampled {
- GDCLASS(AudioStreamPlaybackOGGVorbis, AudioStreamPlaybackResampled);
+class AudioStreamPlaybackOggVorbis : public AudioStreamPlaybackResampled {
+ GDCLASS(AudioStreamPlaybackOggVorbis, AudioStreamPlaybackResampled);
uint32_t frames_mixed = 0;
bool active = false;
@@ -66,11 +66,11 @@ class AudioStreamPlaybackOGGVorbis : public AudioStreamPlaybackResampled {
bool have_samples_left = false;
bool have_packets_left = false;
- friend class AudioStreamOGGVorbis;
+ friend class AudioStreamOggVorbis;
- Ref<OGGPacketSequence> vorbis_data;
- Ref<OGGPacketSequencePlayback> vorbis_data_playback;
- Ref<AudioStreamOGGVorbis> vorbis_stream;
+ Ref<OggPacketSequence> vorbis_data;
+ Ref<OggPacketSequencePlayback> vorbis_data_playback;
+ Ref<AudioStreamOggVorbis> vorbis_stream;
int _mix_frames(AudioFrame *p_buffer, int p_frames);
int _mix_frames_vorbis(AudioFrame *p_buffer, int p_frames);
@@ -94,16 +94,16 @@ public:
virtual void tag_used_streams() override;
- AudioStreamPlaybackOGGVorbis() {}
- ~AudioStreamPlaybackOGGVorbis();
+ AudioStreamPlaybackOggVorbis() {}
+ ~AudioStreamPlaybackOggVorbis();
};
-class AudioStreamOGGVorbis : public AudioStream {
- GDCLASS(AudioStreamOGGVorbis, AudioStream);
+class AudioStreamOggVorbis : public AudioStream {
+ GDCLASS(AudioStreamOggVorbis, AudioStream);
OBJ_SAVE_TYPE(AudioStream); // Saves derived classes with common type so they can be interchanged.
RES_BASE_EXTENSION("oggvorbisstr");
- friend class AudioStreamPlaybackOGGVorbis;
+ friend class AudioStreamPlaybackOggVorbis;
int channels = 1;
float length = 0.0;
@@ -114,7 +114,7 @@ class AudioStreamOGGVorbis : public AudioStream {
// Also causes allocation and deallocation.
void maybe_update_info();
- Ref<OGGPacketSequence> packet_sequence;
+ Ref<OggPacketSequence> packet_sequence;
double bpm = 0;
int beat_count = 0;
@@ -142,15 +142,15 @@ public:
virtual Ref<AudioStreamPlayback> instantiate_playback() override;
virtual String get_stream_name() const override;
- void set_packet_sequence(Ref<OGGPacketSequence> p_packet_sequence);
- Ref<OGGPacketSequence> get_packet_sequence() const;
+ void set_packet_sequence(Ref<OggPacketSequence> p_packet_sequence);
+ Ref<OggPacketSequence> get_packet_sequence() const;
virtual float get_length() const override; //if supported, otherwise return 0
virtual bool is_monophonic() const override;
- AudioStreamOGGVorbis();
- virtual ~AudioStreamOGGVorbis();
+ AudioStreamOggVorbis();
+ virtual ~AudioStreamOggVorbis();
};
#endif // AUDIO_STREAM_OGG_VORBIS_H
diff --git a/modules/vorbis/config.py b/modules/vorbis/config.py
index 978eccb29f..7ce885a37a 100644
--- a/modules/vorbis/config.py
+++ b/modules/vorbis/config.py
@@ -8,8 +8,8 @@ def configure(env):
def get_doc_classes():
return [
- "AudioStreamOGGVorbis",
- "AudioStreamPlaybackOGGVorbis",
+ "AudioStreamOggVorbis",
+ "AudioStreamPlaybackOggVorbis",
]
diff --git a/modules/vorbis/doc_classes/AudioStreamOGGVorbis.xml b/modules/vorbis/doc_classes/AudioStreamOggVorbis.xml
index f87296dcd8..225ea4e6ae 100644
--- a/modules/vorbis/doc_classes/AudioStreamOGGVorbis.xml
+++ b/modules/vorbis/doc_classes/AudioStreamOggVorbis.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AudioStreamOGGVorbis" inherits="AudioStream" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
+<class name="AudioStreamOggVorbis" inherits="AudioStream" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
<brief_description>
</brief_description>
<description>
@@ -19,8 +19,8 @@
<member name="loop_offset" type="float" setter="set_loop_offset" getter="get_loop_offset" default="0.0">
Time in seconds at which the stream starts after being looped.
</member>
- <member name="packet_sequence" type="OGGPacketSequence" setter="set_packet_sequence" getter="get_packet_sequence">
- Contains the raw OGG data for this stream.
+ <member name="packet_sequence" type="OggPacketSequence" setter="set_packet_sequence" getter="get_packet_sequence">
+ Contains the raw Ogg data for this stream.
</member>
</members>
</class>
diff --git a/modules/vorbis/doc_classes/AudioStreamPlaybackOGGVorbis.xml b/modules/vorbis/doc_classes/AudioStreamPlaybackOggVorbis.xml
index 68aa46147f..0879c773ac 100644
--- a/modules/vorbis/doc_classes/AudioStreamPlaybackOGGVorbis.xml
+++ b/modules/vorbis/doc_classes/AudioStreamPlaybackOggVorbis.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AudioStreamPlaybackOGGVorbis" inherits="AudioStreamPlaybackResampled" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
+<class name="AudioStreamPlaybackOggVorbis" inherits="AudioStreamPlaybackResampled" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
<brief_description>
</brief_description>
<description>
diff --git a/modules/vorbis/register_types.cpp b/modules/vorbis/register_types.cpp
index 7f81f88cdb..84a71fe82d 100644
--- a/modules/vorbis/register_types.cpp
+++ b/modules/vorbis/register_types.cpp
@@ -40,13 +40,13 @@ void initialize_vorbis_module(ModuleInitializationLevel p_level) {
#ifdef TOOLS_ENABLED
if (Engine::get_singleton()->is_editor_hint()) {
- Ref<ResourceImporterOGGVorbis> ogg_vorbis_importer;
+ Ref<ResourceImporterOggVorbis> ogg_vorbis_importer;
ogg_vorbis_importer.instantiate();
ResourceFormatImporter::get_singleton()->add_importer(ogg_vorbis_importer);
}
#endif
- GDREGISTER_CLASS(AudioStreamOGGVorbis);
- GDREGISTER_CLASS(AudioStreamPlaybackOGGVorbis);
+ GDREGISTER_CLASS(AudioStreamOggVorbis);
+ GDREGISTER_CLASS(AudioStreamPlaybackOggVorbis);
}
void uninitialize_vorbis_module(ModuleInitializationLevel p_level) {
diff --git a/modules/vorbis/resource_importer_ogg_vorbis.cpp b/modules/vorbis/resource_importer_ogg_vorbis.cpp
index 9461d531fd..1ad1366d0b 100644
--- a/modules/vorbis/resource_importer_ogg_vorbis.cpp
+++ b/modules/vorbis/resource_importer_ogg_vorbis.cpp
@@ -40,39 +40,39 @@
#include "editor/import/audio_stream_import_settings.h"
#endif
-String ResourceImporterOGGVorbis::get_importer_name() const {
+String ResourceImporterOggVorbis::get_importer_name() const {
return "oggvorbisstr";
}
-String ResourceImporterOGGVorbis::get_visible_name() const {
+String ResourceImporterOggVorbis::get_visible_name() const {
return "oggvorbisstr";
}
-void ResourceImporterOGGVorbis::get_recognized_extensions(List<String> *p_extensions) const {
+void ResourceImporterOggVorbis::get_recognized_extensions(List<String> *p_extensions) const {
p_extensions->push_back("ogg");
}
-String ResourceImporterOGGVorbis::get_save_extension() const {
+String ResourceImporterOggVorbis::get_save_extension() const {
return "oggvorbisstr";
}
-String ResourceImporterOGGVorbis::get_resource_type() const {
- return "AudioStreamOGGVorbis";
+String ResourceImporterOggVorbis::get_resource_type() const {
+ return "AudioStreamOggVorbis";
}
-bool ResourceImporterOGGVorbis::get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const {
+bool ResourceImporterOggVorbis::get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const {
return true;
}
-int ResourceImporterOGGVorbis::get_preset_count() const {
+int ResourceImporterOggVorbis::get_preset_count() const {
return 0;
}
-String ResourceImporterOGGVorbis::get_preset_name(int p_idx) const {
+String ResourceImporterOggVorbis::get_preset_name(int p_idx) const {
return String();
}
-void ResourceImporterOGGVorbis::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const {
+void ResourceImporterOggVorbis::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const {
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "loop"), true));
r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "loop_offset"), 0));
r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "bpm", PROPERTY_HINT_RANGE, "0,400,0.01,or_greater"), 0));
@@ -80,9 +80,9 @@ void ResourceImporterOGGVorbis::get_import_options(const String &p_path, List<Im
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "bar_beats", PROPERTY_HINT_RANGE, "2,32,or_greater"), 4));
}
-Ref<AudioStreamOGGVorbis> ResourceImporterOGGVorbis::import_ogg_vorbis(const String &p_path) {
+Ref<AudioStreamOggVorbis> ResourceImporterOggVorbis::import_ogg_vorbis(const String &p_path) {
Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
- ERR_FAIL_COND_V_MSG(f.is_null(), Ref<AudioStreamOGGVorbis>(), "Cannot open file '" + p_path + "'.");
+ ERR_FAIL_COND_V_MSG(f.is_null(), Ref<AudioStreamOggVorbis>(), "Cannot open file '" + p_path + "'.");
uint64_t len = f->get_length();
@@ -92,10 +92,10 @@ Ref<AudioStreamOGGVorbis> ResourceImporterOGGVorbis::import_ogg_vorbis(const Str
f->get_buffer(w, len);
- Ref<AudioStreamOGGVorbis> ogg_vorbis_stream;
+ Ref<AudioStreamOggVorbis> ogg_vorbis_stream;
ogg_vorbis_stream.instantiate();
- Ref<OGGPacketSequence> ogg_packet_sequence;
+ Ref<OggPacketSequence> ogg_packet_sequence;
ogg_packet_sequence.instantiate();
ogg_stream_state stream_state;
@@ -110,16 +110,16 @@ Ref<AudioStreamOGGVorbis> ResourceImporterOGGVorbis::import_ogg_vorbis(const Str
size_t packet_count = 0;
bool done = false;
while (!done) {
- ERR_FAIL_COND_V_MSG((err = ogg_sync_check(&sync_state)), Ref<AudioStreamOGGVorbis>(), "Ogg sync error " + itos(err));
+ ERR_FAIL_COND_V_MSG((err = ogg_sync_check(&sync_state)), Ref<AudioStreamOggVorbis>(), "Ogg sync error " + itos(err));
while (ogg_sync_pageout(&sync_state, &page) != 1) {
if (cursor >= len) {
done = true;
break;
}
- ERR_FAIL_COND_V_MSG((err = ogg_sync_check(&sync_state)), Ref<AudioStreamOGGVorbis>(), "Ogg sync error " + itos(err));
+ ERR_FAIL_COND_V_MSG((err = ogg_sync_check(&sync_state)), Ref<AudioStreamOggVorbis>(), "Ogg sync error " + itos(err));
char *sync_buf = ogg_sync_buffer(&sync_state, OGG_SYNC_BUFFER_SIZE);
- ERR_FAIL_COND_V_MSG((err = ogg_sync_check(&sync_state)), Ref<AudioStreamOGGVorbis>(), "Ogg sync error " + itos(err));
- ERR_FAIL_COND_V(cursor > len, Ref<AudioStreamOGGVorbis>());
+ ERR_FAIL_COND_V_MSG((err = ogg_sync_check(&sync_state)), Ref<AudioStreamOggVorbis>(), "Ogg sync error " + itos(err));
+ ERR_FAIL_COND_V(cursor > len, Ref<AudioStreamOggVorbis>());
size_t copy_size = len - cursor;
if (copy_size > OGG_SYNC_BUFFER_SIZE) {
copy_size = OGG_SYNC_BUFFER_SIZE;
@@ -127,22 +127,22 @@ Ref<AudioStreamOGGVorbis> ResourceImporterOGGVorbis::import_ogg_vorbis(const Str
memcpy(sync_buf, &file_data[cursor], copy_size);
ogg_sync_wrote(&sync_state, copy_size);
cursor += copy_size;
- ERR_FAIL_COND_V_MSG((err = ogg_sync_check(&sync_state)), Ref<AudioStreamOGGVorbis>(), "Ogg sync error " + itos(err));
+ ERR_FAIL_COND_V_MSG((err = ogg_sync_check(&sync_state)), Ref<AudioStreamOggVorbis>(), "Ogg sync error " + itos(err));
}
if (done) {
break;
}
- ERR_FAIL_COND_V_MSG((err = ogg_sync_check(&sync_state)), Ref<AudioStreamOGGVorbis>(), "Ogg sync error " + itos(err));
+ ERR_FAIL_COND_V_MSG((err = ogg_sync_check(&sync_state)), Ref<AudioStreamOggVorbis>(), "Ogg sync error " + itos(err));
// Have a page now.
if (!initialized_stream) {
if (ogg_stream_init(&stream_state, ogg_page_serialno(&page))) {
- ERR_FAIL_V_MSG(Ref<AudioStreamOGGVorbis>(), "Failed allocating memory for OGG Vorbis stream.");
+ ERR_FAIL_V_MSG(Ref<AudioStreamOggVorbis>(), "Failed allocating memory for Ogg Vorbis stream.");
}
initialized_stream = true;
}
ogg_stream_pagein(&stream_state, &page);
- ERR_FAIL_COND_V_MSG((err = ogg_stream_check(&stream_state)), Ref<AudioStreamOGGVorbis>(), "Ogg stream error " + itos(err));
+ ERR_FAIL_COND_V_MSG((err = ogg_stream_check(&stream_state)), Ref<AudioStreamOggVorbis>(), "Ogg stream error " + itos(err));
int desync_iters = 0;
Vector<Vector<uint8_t>> packet_data;
@@ -153,7 +153,7 @@ Ref<AudioStreamOGGVorbis> ResourceImporterOGGVorbis::import_ogg_vorbis(const Str
if (err == -1) {
// According to the docs this is usually recoverable, but don't sit here spinning forever.
desync_iters++;
- ERR_FAIL_COND_V_MSG(desync_iters > 100, Ref<AudioStreamOGGVorbis>(), "Packet sync issue during ogg import");
+ ERR_FAIL_COND_V_MSG(desync_iters > 100, Ref<AudioStreamOggVorbis>(), "Packet sync issue during Ogg import");
continue;
} else if (err == 0) {
// Not enough data to fully reconstruct a packet. Go on to the next page.
@@ -186,7 +186,7 @@ Ref<AudioStreamOGGVorbis> ResourceImporterOGGVorbis::import_ogg_vorbis(const Str
ogg_sync_clear(&sync_state);
if (ogg_packet_sequence->get_packet_granule_positions().is_empty()) {
- ERR_FAIL_V_MSG(Ref<AudioStreamOGGVorbis>(), "OGG Vorbis decoding failed. Check that your data is a valid OGG Vorbis audio stream.");
+ ERR_FAIL_V_MSG(Ref<AudioStreamOggVorbis>(), "Ogg Vorbis decoding failed. Check that your data is a valid Ogg Vorbis audio stream.");
}
ogg_vorbis_stream->set_packet_sequence(ogg_packet_sequence);
@@ -196,26 +196,26 @@ Ref<AudioStreamOGGVorbis> ResourceImporterOGGVorbis::import_ogg_vorbis(const Str
#ifdef TOOLS_ENABLED
-bool ResourceImporterOGGVorbis::has_advanced_options() const {
+bool ResourceImporterOggVorbis::has_advanced_options() const {
return true;
}
-void ResourceImporterOGGVorbis::show_advanced_options(const String &p_path) {
- Ref<AudioStreamOGGVorbis> ogg_stream = import_ogg_vorbis(p_path);
+void ResourceImporterOggVorbis::show_advanced_options(const String &p_path) {
+ Ref<AudioStreamOggVorbis> ogg_stream = import_ogg_vorbis(p_path);
if (ogg_stream.is_valid()) {
AudioStreamImportSettings::get_singleton()->edit(p_path, "oggvorbisstr", ogg_stream);
}
}
#endif
-Error ResourceImporterOGGVorbis::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) {
+Error ResourceImporterOggVorbis::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) {
bool loop = p_options["loop"];
float loop_offset = p_options["loop_offset"];
double bpm = p_options["bpm"];
int beat_count = p_options["beat_count"];
int bar_beats = p_options["bar_beats"];
- Ref<AudioStreamOGGVorbis> ogg_vorbis_stream = import_ogg_vorbis(p_source_file);
+ Ref<AudioStreamOggVorbis> ogg_vorbis_stream = import_ogg_vorbis(p_source_file);
if (ogg_vorbis_stream.is_null()) {
return ERR_CANT_OPEN;
}
@@ -229,5 +229,5 @@ Error ResourceImporterOGGVorbis::import(const String &p_source_file, const Strin
return ResourceSaver::save(p_save_path + ".oggvorbisstr", ogg_vorbis_stream);
}
-ResourceImporterOGGVorbis::ResourceImporterOGGVorbis() {
+ResourceImporterOggVorbis::ResourceImporterOggVorbis() {
}
diff --git a/modules/vorbis/resource_importer_ogg_vorbis.h b/modules/vorbis/resource_importer_ogg_vorbis.h
index e6e98a29c1..a1a970e2cc 100644
--- a/modules/vorbis/resource_importer_ogg_vorbis.h
+++ b/modules/vorbis/resource_importer_ogg_vorbis.h
@@ -34,8 +34,8 @@
#include "audio_stream_ogg_vorbis.h"
#include "core/io/resource_importer.h"
-class ResourceImporterOGGVorbis : public ResourceImporter {
- GDCLASS(ResourceImporterOGGVorbis, ResourceImporter);
+class ResourceImporterOggVorbis : public ResourceImporter {
+ GDCLASS(ResourceImporterOggVorbis, ResourceImporter);
enum {
OGG_SYNC_BUFFER_SIZE = 8192,
@@ -44,7 +44,7 @@ class ResourceImporterOGGVorbis : public ResourceImporter {
private:
// virtual int get_samples_in_packet(Vector<uint8_t> p_packet) = 0;
- static Ref<AudioStreamOGGVorbis> import_ogg_vorbis(const String &p_path);
+ static Ref<AudioStreamOggVorbis> import_ogg_vorbis(const String &p_path);
public:
#ifdef TOOLS_ENABLED
@@ -63,7 +63,7 @@ public:
virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override;
- ResourceImporterOGGVorbis();
+ ResourceImporterOggVorbis();
};
#endif // RESOURCE_IMPORTER_OGG_VORBIS_H
diff --git a/modules/webrtc/doc_classes/WebRTCMultiplayerPeer.xml b/modules/webrtc/doc_classes/WebRTCMultiplayerPeer.xml
index 3996a002ed..df92097135 100644
--- a/modules/webrtc/doc_classes/WebRTCMultiplayerPeer.xml
+++ b/modules/webrtc/doc_classes/WebRTCMultiplayerPeer.xml
@@ -57,7 +57,7 @@
Initialize the multiplayer peer with the given [code]peer_id[/code] (must be between 1 and 2147483647).
If [code]server_compatibilty[/code] is [code]false[/code] (default), the multiplayer peer will be immediately in state [constant MultiplayerPeer.CONNECTION_CONNECTED] and [signal MultiplayerPeer.connection_succeeded] will not be emitted.
If [code]server_compatibilty[/code] is [code]true[/code] the peer will suppress all [signal MultiplayerPeer.peer_connected] signals until a peer with id [constant MultiplayerPeer.TARGET_PEER_SERVER] connects and then emit [signal MultiplayerPeer.connection_succeeded]. After that the signal [signal MultiplayerPeer.peer_connected] will be emitted for every already connected peer, and any new peer that might connect. If the server peer disconnects after that, signal [signal MultiplayerPeer.server_disconnected] will be emitted and state will become [constant MultiplayerPeer.CONNECTION_CONNECTED].
- You can optionally specify a [code]channels_config[/code] array of [enum TransferMode] which will be used to create extra channels (WebRTC only supports one transfer mode per channel).
+ You can optionally specify a [code]channels_config[/code] array of [enum MultiplayerPeer.TransferMode] which will be used to create extra channels (WebRTC only supports one transfer mode per channel).
</description>
</method>
<method name="remove_peer">
diff --git a/modules/webrtc/webrtc_multiplayer_peer.cpp b/modules/webrtc/webrtc_multiplayer_peer.cpp
index 6f68b84ad3..e03b6b2473 100644
--- a/modules/webrtc/webrtc_multiplayer_peer.cpp
+++ b/modules/webrtc/webrtc_multiplayer_peer.cpp
@@ -197,14 +197,14 @@ Error WebRTCMultiplayerPeer::initialize(int p_self_id, bool p_server_compat, Arr
cfg["ordered"] = true;
switch (mode) {
- case Multiplayer::TRANSFER_MODE_UNRELIABLE_ORDERED:
+ case TRANSFER_MODE_UNRELIABLE_ORDERED:
cfg["maxPacketLifetime"] = 1;
break;
- case Multiplayer::TRANSFER_MODE_UNRELIABLE:
+ case TRANSFER_MODE_UNRELIABLE:
cfg["maxPacketLifetime"] = 1;
cfg["ordered"] = false;
break;
- case Multiplayer::TRANSFER_MODE_RELIABLE:
+ case TRANSFER_MODE_RELIABLE:
break;
default:
ERR_FAIL_V_MSG(ERR_INVALID_PARAMETER, vformat("The 'channels_config' array must contain only enum values from 'MultiplayerPeer.Multiplayer::TransferMode'. Got: %d", mode));
@@ -339,13 +339,13 @@ Error WebRTCMultiplayerPeer::put_packet(const uint8_t *p_buffer, int p_buffer_si
int ch = get_transfer_channel();
if (ch == 0) {
switch (get_transfer_mode()) {
- case Multiplayer::TRANSFER_MODE_RELIABLE:
+ case TRANSFER_MODE_RELIABLE:
ch = CH_RELIABLE;
break;
- case Multiplayer::TRANSFER_MODE_UNRELIABLE_ORDERED:
+ case TRANSFER_MODE_UNRELIABLE_ORDERED:
ch = CH_ORDERED;
break;
- case Multiplayer::TRANSFER_MODE_UNRELIABLE:
+ case TRANSFER_MODE_UNRELIABLE:
ch = CH_UNRELIABLE;
break;
}
diff --git a/modules/webrtc/webrtc_multiplayer_peer.h b/modules/webrtc/webrtc_multiplayer_peer.h
index d4ed7ef7de..ea7c60036b 100644
--- a/modules/webrtc/webrtc_multiplayer_peer.h
+++ b/modules/webrtc/webrtc_multiplayer_peer.h
@@ -31,7 +31,7 @@
#ifndef WEBRTC_MULTIPLAYER_PEER_H
#define WEBRTC_MULTIPLAYER_PEER_H
-#include "core/multiplayer/multiplayer_peer.h"
+#include "scene/main/multiplayer_peer.h"
#include "webrtc_peer_connection.h"
class WebRTCMultiplayerPeer : public MultiplayerPeer {
diff --git a/modules/websocket/websocket_multiplayer_peer.h b/modules/websocket/websocket_multiplayer_peer.h
index db529a669d..3259e78b3b 100644
--- a/modules/websocket/websocket_multiplayer_peer.h
+++ b/modules/websocket/websocket_multiplayer_peer.h
@@ -32,8 +32,8 @@
#define WEBSOCKET_MULTIPLAYER_PEER_H
#include "core/error/error_list.h"
-#include "core/multiplayer/multiplayer_peer.h"
#include "core/templates/list.h"
+#include "scene/main/multiplayer_peer.h"
#include "websocket_peer.h"
class WebSocketMultiplayerPeer : public MultiplayerPeer {
diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp
index 76b354805c..c43a796170 100644
--- a/scene/2d/camera_2d.cpp
+++ b/scene/2d/camera_2d.cpp
@@ -247,8 +247,8 @@ void Camera2D::_notification(int p_what) {
add_to_group(canvas_group_name);
_update_process_callback();
- _update_scroll();
first = true;
+ _update_scroll();
} break;
case NOTIFICATION_EXIT_TREE: {
@@ -439,7 +439,9 @@ void Camera2D::clear_current() {
void Camera2D::set_limit(Side p_side, int p_limit) {
ERR_FAIL_INDEX((int)p_side, 4);
limit[p_side] = p_limit;
+ Point2 old_smoothed_camera_pos = smoothed_camera_pos;
_update_scroll();
+ smoothed_camera_pos = old_smoothed_camera_pos;
}
int Camera2D::get_limit(Side p_side) const {
diff --git a/scene/2d/ray_cast_2d.cpp b/scene/2d/ray_cast_2d.cpp
index 8953813452..68e5ffdcf9 100644
--- a/scene/2d/ray_cast_2d.cpp
+++ b/scene/2d/ray_cast_2d.cpp
@@ -240,7 +240,7 @@ void RayCast2D::_draw_debug_shape() {
Transform2D xf;
xf.rotate(target_position.angle());
- xf.translate(Vector2(no_line ? 0 : target_position.length() - arrow_size, 0));
+ xf.translate_local(Vector2(no_line ? 0 : target_position.length() - arrow_size, 0));
Vector<Vector2> pts = {
xf.xform(Vector2(arrow_size, 0)),
diff --git a/scene/2d/shape_cast_2d.cpp b/scene/2d/shape_cast_2d.cpp
index ae810156a2..7589af0924 100644
--- a/scene/2d/shape_cast_2d.cpp
+++ b/scene/2d/shape_cast_2d.cpp
@@ -237,7 +237,7 @@ void ShapeCast2D::_notification(int p_what) {
if (target_position != Vector2()) {
Transform2D xf;
xf.rotate(target_position.angle());
- xf.translate(Vector2(target_position.length(), 0));
+ xf.translate_local(Vector2(target_position.length(), 0));
draw_line(Vector2(), target_position, draw_col, 2);
diff --git a/scene/2d/touch_screen_button.cpp b/scene/2d/touch_screen_button.cpp
index 4a4a2a1da0..9dea69cd64 100644
--- a/scene/2d/touch_screen_button.cpp
+++ b/scene/2d/touch_screen_button.cpp
@@ -131,7 +131,7 @@ void TouchScreenButton::_notification(int p_what) {
pos = texture_normal->get_size() * 0.5;
}
- draw_set_transform_matrix(get_canvas_transform().translated(pos));
+ draw_set_transform_matrix(get_canvas_transform().translated_local(pos));
shape->draw(get_canvas_item(), draw_col);
}
} break;
@@ -258,7 +258,7 @@ bool TouchScreenButton::_is_point_inside(const Point2 &p_point) {
pos = texture_normal->get_size() * 0.5;
}
- touched = shape->collide(Transform2D().translated(pos), unit_rect, Transform2D(0, coord + Vector2(0.5, 0.5)));
+ touched = shape->collide(Transform2D().translated_local(pos), unit_rect, Transform2D(0, coord + Vector2(0.5, 0.5)));
}
if (bitmask.is_valid()) {
diff --git a/scene/3d/node_3d.cpp b/scene/3d/node_3d.cpp
index 04b1081516..1de85d57a3 100644
--- a/scene/3d/node_3d.cpp
+++ b/scene/3d/node_3d.cpp
@@ -733,7 +733,7 @@ void Node3D::rotate_z(real_t p_angle) {
void Node3D::translate(const Vector3 &p_offset) {
Transform3D t = get_transform();
- t.translate(p_offset);
+ t.translate_local(p_offset);
set_transform(t);
}
@@ -741,7 +741,7 @@ void Node3D::translate_object_local(const Vector3 &p_offset) {
Transform3D t = get_transform();
Transform3D s;
- s.translate(p_offset);
+ s.translate_local(p_offset);
set_transform(t * s);
}
diff --git a/scene/3d/path_3d.cpp b/scene/3d/path_3d.cpp
index 1f10337b4c..25226ad384 100644
--- a/scene/3d/path_3d.cpp
+++ b/scene/3d/path_3d.cpp
@@ -296,7 +296,7 @@ void PathFollow3D::_update_transform(bool p_update_xyz_rot) {
}
}
- t.translate(Vector3(h_offset, v_offset, 0));
+ t.translate_local(Vector3(h_offset, v_offset, 0));
} else {
t.origin = pos + Vector3(h_offset, v_offset, 0);
}
diff --git a/scene/SCsub b/scene/SCsub
index a7b23af598..92288211bb 100644
--- a/scene/SCsub
+++ b/scene/SCsub
@@ -9,7 +9,6 @@ env.add_source_files(env.scene_sources, "*.cpp")
# Chain load SCsubs
SConscript("main/SCsub")
-SConscript("multiplayer/SCsub")
SConscript("gui/SCsub")
if not env["disable_3d"]:
SConscript("3d/SCsub")
diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp
index bfe5ee335b..d9f603f136 100644
--- a/scene/gui/color_picker.cpp
+++ b/scene/gui/color_picker.cpp
@@ -998,10 +998,10 @@ void ColorPicker::_w_input(const Ref<InputEvent> &p_event) {
h = y / w_edit->get_size().height;
}
- if (current_mode == MODE_HSV) {
- color.set_hsv(h, s, v, color.a);
- } else if (current_mode == MODE_OKHSL) {
+ if (actual_shape == SHAPE_OKHSL_CIRCLE) {
color.set_ok_hsl(h, s, v, color.a);
+ } else {
+ color.set_hsv(h, s, v, color.a);
}
last_color = color;
diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp
index e298805aca..ce204c6aeb 100644
--- a/scene/main/canvas_item.cpp
+++ b/scene/main/canvas_item.cpp
@@ -64,9 +64,6 @@ void CanvasItem::_propagate_visibility_changed(bool p_parent_visible_in_tree) {
if (!visible) {
return;
}
- if (p_parent_visible_in_tree && first_draw) { // Avoid propagating it twice.
- first_draw = false;
- }
_handle_visibility_change(p_parent_visible_in_tree);
}
@@ -133,10 +130,6 @@ void CanvasItem::_update_callback() {
RenderingServer::get_singleton()->canvas_item_clear(get_canvas_item());
//todo updating = true - only allow drawing here
if (is_visible_in_tree()) {
- if (first_draw) {
- notification(NOTIFICATION_VISIBILITY_CHANGED);
- first_draw = false;
- }
drawing = true;
current_item_drawn = this;
notification(NOTIFICATION_DRAW);
@@ -268,7 +261,6 @@ void CanvasItem::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
ERR_FAIL_COND(!is_inside_tree());
- first_draw = true;
Node *parent = get_parent();
if (parent) {
@@ -307,6 +299,10 @@ void CanvasItem::_notification(int p_what) {
}
}
+ RenderingServer::get_singleton()->canvas_item_set_visible(canvas_item, is_visible_in_tree()); // The visibility of the parent may change.
+ if (is_visible_in_tree()) {
+ notification(NOTIFICATION_VISIBILITY_CHANGED); // Considered invisible until entered.
+ }
_enter_canvas();
_update_texture_filter_changed(false);
diff --git a/scene/main/canvas_item.h b/scene/main/canvas_item.h
index f5df6512ee..38e0be1683 100644
--- a/scene/main/canvas_item.h
+++ b/scene/main/canvas_item.h
@@ -83,7 +83,6 @@ private:
int light_mask = 1;
Window *window = nullptr;
- bool first_draw = false;
bool visible = true;
bool parent_visible_in_tree = false;
bool clip_children = false;
diff --git a/scene/main/multiplayer_api.cpp b/scene/main/multiplayer_api.cpp
new file mode 100644
index 0000000000..95574042a8
--- /dev/null
+++ b/scene/main/multiplayer_api.cpp
@@ -0,0 +1,416 @@
+/*************************************************************************/
+/* multiplayer_api.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "multiplayer_api.h"
+
+#include "core/debugger/engine_debugger.h"
+#include "core/io/marshalls.h"
+
+#include <stdint.h>
+
+#ifdef DEBUG_ENABLED
+#include "core/os/os.h"
+#endif
+
+StringName MultiplayerAPI::default_interface = StringName();
+
+void MultiplayerAPI::set_default_interface(const StringName &p_interface) {
+ ERR_FAIL_COND_MSG(!ClassDB::is_parent_class(p_interface, MultiplayerAPI::get_class_static()), vformat("Can't make %s the default multiplayer interface since it does not extend MultiplayerAPI.", p_interface));
+ default_interface = p_interface;
+}
+
+StringName MultiplayerAPI::get_default_interface() {
+ return default_interface;
+}
+
+Ref<MultiplayerAPI> MultiplayerAPI::create_default_interface() {
+ if (default_interface != StringName()) {
+ return Ref<MultiplayerAPI>(Object::cast_to<MultiplayerAPI>(ClassDB::instantiate(default_interface)));
+ }
+ return Ref<MultiplayerAPI>(memnew(MultiplayerAPIExtension));
+}
+
+// The variant is compressed and encoded; The first byte contains all the meta
+// information and the format is:
+// - The first LSB 5 bits are used for the variant type.
+// - The next two bits are used to store the encoding mode.
+// - The most significant is used to store the boolean value.
+#define VARIANT_META_TYPE_MASK 0x1F
+#define VARIANT_META_EMODE_MASK 0x60
+#define VARIANT_META_BOOL_MASK 0x80
+#define ENCODE_8 0 << 5
+#define ENCODE_16 1 << 5
+#define ENCODE_32 2 << 5
+#define ENCODE_64 3 << 5
+Error MultiplayerAPI::encode_and_compress_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bool p_allow_object_decoding) {
+ // Unreachable because `VARIANT_MAX` == 27 and `ENCODE_VARIANT_MASK` == 31
+ CRASH_COND(p_variant.get_type() > VARIANT_META_TYPE_MASK);
+
+ uint8_t *buf = r_buffer;
+ r_len = 0;
+ uint8_t encode_mode = 0;
+
+ switch (p_variant.get_type()) {
+ case Variant::BOOL: {
+ if (buf) {
+ // We still have 1 free bit in the meta, so let's use it.
+ buf[0] = (p_variant.operator bool()) ? (1 << 7) : 0;
+ buf[0] |= encode_mode | p_variant.get_type();
+ }
+ r_len += 1;
+ } break;
+ case Variant::INT: {
+ if (buf) {
+ // Reserve the first byte for the meta.
+ buf += 1;
+ }
+ r_len += 1;
+ int64_t val = p_variant;
+ if (val <= (int64_t)INT8_MAX && val >= (int64_t)INT8_MIN) {
+ // Use 8 bit
+ encode_mode = ENCODE_8;
+ if (buf) {
+ buf[0] = val;
+ }
+ r_len += 1;
+ } else if (val <= (int64_t)INT16_MAX && val >= (int64_t)INT16_MIN) {
+ // Use 16 bit
+ encode_mode = ENCODE_16;
+ if (buf) {
+ encode_uint16(val, buf);
+ }
+ r_len += 2;
+ } else if (val <= (int64_t)INT32_MAX && val >= (int64_t)INT32_MIN) {
+ // Use 32 bit
+ encode_mode = ENCODE_32;
+ if (buf) {
+ encode_uint32(val, buf);
+ }
+ r_len += 4;
+ } else {
+ // Use 64 bit
+ encode_mode = ENCODE_64;
+ if (buf) {
+ encode_uint64(val, buf);
+ }
+ r_len += 8;
+ }
+ // Store the meta
+ if (buf) {
+ buf -= 1;
+ buf[0] = encode_mode | p_variant.get_type();
+ }
+ } break;
+ default:
+ // Any other case is not yet compressed.
+ Error err = encode_variant(p_variant, r_buffer, r_len, p_allow_object_decoding);
+ if (err != OK) {
+ return err;
+ }
+ if (r_buffer) {
+ // The first byte is not used by the marshalling, so store the type
+ // so we know how to decompress and decode this variant.
+ r_buffer[0] = p_variant.get_type();
+ }
+ }
+
+ return OK;
+}
+
+Error MultiplayerAPI::decode_and_decompress_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int *r_len, bool p_allow_object_decoding) {
+ const uint8_t *buf = p_buffer;
+ int len = p_len;
+
+ ERR_FAIL_COND_V(len < 1, ERR_INVALID_DATA);
+ uint8_t type = buf[0] & VARIANT_META_TYPE_MASK;
+ uint8_t encode_mode = buf[0] & VARIANT_META_EMODE_MASK;
+
+ ERR_FAIL_COND_V(type >= Variant::VARIANT_MAX, ERR_INVALID_DATA);
+
+ switch (type) {
+ case Variant::BOOL: {
+ bool val = (buf[0] & VARIANT_META_BOOL_MASK) > 0;
+ r_variant = val;
+ if (r_len) {
+ *r_len = 1;
+ }
+ } break;
+ case Variant::INT: {
+ buf += 1;
+ len -= 1;
+ if (r_len) {
+ *r_len = 1;
+ }
+ if (encode_mode == ENCODE_8) {
+ // 8 bits.
+ ERR_FAIL_COND_V(len < 1, ERR_INVALID_DATA);
+ int8_t val = buf[0];
+ r_variant = val;
+ if (r_len) {
+ (*r_len) += 1;
+ }
+ } else if (encode_mode == ENCODE_16) {
+ // 16 bits.
+ ERR_FAIL_COND_V(len < 2, ERR_INVALID_DATA);
+ int16_t val = decode_uint16(buf);
+ r_variant = val;
+ if (r_len) {
+ (*r_len) += 2;
+ }
+ } else if (encode_mode == ENCODE_32) {
+ // 32 bits.
+ ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
+ int32_t val = decode_uint32(buf);
+ r_variant = val;
+ if (r_len) {
+ (*r_len) += 4;
+ }
+ } else {
+ // 64 bits.
+ ERR_FAIL_COND_V(len < 8, ERR_INVALID_DATA);
+ int64_t val = decode_uint64(buf);
+ r_variant = val;
+ if (r_len) {
+ (*r_len) += 8;
+ }
+ }
+ } break;
+ default:
+ Error err = decode_variant(r_variant, p_buffer, p_len, r_len, p_allow_object_decoding);
+ if (err != OK) {
+ return err;
+ }
+ }
+
+ return OK;
+}
+
+Error MultiplayerAPI::encode_and_compress_variants(const Variant **p_variants, int p_count, uint8_t *p_buffer, int &r_len, bool *r_raw, bool p_allow_object_decoding) {
+ r_len = 0;
+ int size = 0;
+
+ if (p_count == 0) {
+ if (r_raw) {
+ *r_raw = true;
+ }
+ return OK;
+ }
+
+ // Try raw encoding optimization.
+ if (r_raw && p_count == 1) {
+ *r_raw = false;
+ const Variant &v = *(p_variants[0]);
+ if (v.get_type() == Variant::PACKED_BYTE_ARRAY) {
+ *r_raw = true;
+ const PackedByteArray pba = v;
+ if (p_buffer) {
+ memcpy(p_buffer, pba.ptr(), pba.size());
+ }
+ r_len += pba.size();
+ } else {
+ encode_and_compress_variant(v, p_buffer, size, p_allow_object_decoding);
+ r_len += size;
+ }
+ return OK;
+ }
+
+ // Regular encoding.
+ for (int i = 0; i < p_count; i++) {
+ const Variant &v = *(p_variants[i]);
+ encode_and_compress_variant(v, p_buffer ? p_buffer + r_len : nullptr, size, p_allow_object_decoding);
+ r_len += size;
+ }
+ return OK;
+}
+
+Error MultiplayerAPI::decode_and_decompress_variants(Vector<Variant> &r_variants, const uint8_t *p_buffer, int p_len, int &r_len, bool p_raw, bool p_allow_object_decoding) {
+ r_len = 0;
+ int argc = r_variants.size();
+ if (argc == 0 && p_raw) {
+ return OK;
+ }
+ ERR_FAIL_COND_V(p_raw && argc != 1, ERR_INVALID_DATA);
+ if (p_raw) {
+ r_len = p_len;
+ PackedByteArray pba;
+ pba.resize(p_len);
+ memcpy(pba.ptrw(), p_buffer, p_len);
+ r_variants.write[0] = pba;
+ return OK;
+ }
+
+ Vector<Variant> args;
+ Vector<const Variant *> argp;
+ args.resize(argc);
+
+ for (int i = 0; i < argc; i++) {
+ ERR_FAIL_COND_V_MSG(r_len >= p_len, ERR_INVALID_DATA, "Invalid packet received. Size too small.");
+
+ int vlen;
+ Error err = MultiplayerAPI::decode_and_decompress_variant(r_variants.write[i], &p_buffer[r_len], p_len - r_len, &vlen, p_allow_object_decoding);
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Invalid packet received. Unable to decode state variable.");
+ r_len += vlen;
+ }
+ return OK;
+}
+
+Error MultiplayerAPI::_rpc_bind(int p_peer, Object *p_object, const StringName &p_method, Array p_args) {
+ Vector<Variant> args;
+ Vector<const Variant *> argsp;
+ args.resize(p_args.size());
+ argsp.resize(p_args.size());
+ Variant *ptr = args.ptrw();
+ const Variant **pptr = argsp.ptrw();
+ for (int i = 0; i < p_args.size(); i++) {
+ ptr[i] = p_args[i];
+ pptr[i] = &ptr[i];
+ }
+ return rpcp(p_object, p_peer, p_method, argsp.size() ? argsp.ptrw() : nullptr, argsp.size());
+}
+
+void MultiplayerAPI::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("has_multiplayer_peer"), &MultiplayerAPI::has_multiplayer_peer);
+ ClassDB::bind_method(D_METHOD("get_multiplayer_peer"), &MultiplayerAPI::get_multiplayer_peer);
+ ClassDB::bind_method(D_METHOD("set_multiplayer_peer", "peer"), &MultiplayerAPI::set_multiplayer_peer);
+ ClassDB::bind_method(D_METHOD("get_unique_id"), &MultiplayerAPI::get_unique_id);
+ ClassDB::bind_method(D_METHOD("is_server"), &MultiplayerAPI::is_server);
+ ClassDB::bind_method(D_METHOD("get_remote_sender_id"), &MultiplayerAPI::get_remote_sender_id);
+ ClassDB::bind_method(D_METHOD("poll"), &MultiplayerAPI::poll);
+ ClassDB::bind_method(D_METHOD("rpc", "peer", "object", "method", "arguments"), &MultiplayerAPI::_rpc_bind, DEFVAL(Array()));
+ ClassDB::bind_method(D_METHOD("object_configuration_add", "object", "configuration"), &MultiplayerAPI::object_configuration_add);
+ ClassDB::bind_method(D_METHOD("object_configuration_remove", "object", "configuration"), &MultiplayerAPI::object_configuration_remove);
+
+ ClassDB::bind_method(D_METHOD("get_peers"), &MultiplayerAPI::get_peer_ids);
+
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "multiplayer_peer", PROPERTY_HINT_RESOURCE_TYPE, "MultiplayerPeer", PROPERTY_USAGE_NONE), "set_multiplayer_peer", "get_multiplayer_peer");
+
+ ClassDB::bind_static_method("MultiplayerAPI", D_METHOD("set_default_interface", "interface_name"), &MultiplayerAPI::set_default_interface);
+ ClassDB::bind_static_method("MultiplayerAPI", D_METHOD("get_default_interface"), &MultiplayerAPI::get_default_interface);
+ ClassDB::bind_static_method("MultiplayerAPI", D_METHOD("create_default_interface"), &MultiplayerAPI::create_default_interface);
+
+ ADD_SIGNAL(MethodInfo("peer_connected", PropertyInfo(Variant::INT, "id")));
+ ADD_SIGNAL(MethodInfo("peer_disconnected", PropertyInfo(Variant::INT, "id")));
+ ADD_SIGNAL(MethodInfo("connected_to_server"));
+ ADD_SIGNAL(MethodInfo("connection_failed"));
+ ADD_SIGNAL(MethodInfo("server_disconnected"));
+
+ BIND_ENUM_CONSTANT(RPC_MODE_DISABLED);
+ BIND_ENUM_CONSTANT(RPC_MODE_ANY_PEER);
+ BIND_ENUM_CONSTANT(RPC_MODE_AUTHORITY);
+}
+
+/// MultiplayerAPIExtension
+
+Error MultiplayerAPIExtension::poll() {
+ int err;
+ if (GDVIRTUAL_CALL(_poll, err)) {
+ return (Error)err;
+ }
+ return OK;
+}
+
+void MultiplayerAPIExtension::set_multiplayer_peer(const Ref<MultiplayerPeer> &p_peer) {
+ GDVIRTUAL_CALL(_set_multiplayer_peer, p_peer);
+}
+
+Ref<MultiplayerPeer> MultiplayerAPIExtension::get_multiplayer_peer() {
+ Ref<MultiplayerPeer> peer;
+ if (GDVIRTUAL_CALL(_get_multiplayer_peer, peer)) {
+ return peer;
+ }
+ return nullptr;
+}
+
+int MultiplayerAPIExtension::get_unique_id() {
+ int id;
+ if (GDVIRTUAL_CALL(_get_unique_id, id)) {
+ return id;
+ }
+ return 1;
+}
+
+Vector<int> MultiplayerAPIExtension::get_peer_ids() {
+ Vector<int> ids;
+ if (GDVIRTUAL_CALL(_get_peer_ids, ids)) {
+ return ids;
+ }
+ return Vector<int>();
+}
+
+Error MultiplayerAPIExtension::rpcp(Object *p_obj, int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount) {
+ if (!GDVIRTUAL_IS_OVERRIDDEN(_rpc)) {
+ return ERR_UNAVAILABLE;
+ }
+ Array args;
+ for (int i = 0; i < p_argcount; i++) {
+ args.push_back(*p_arg[i]);
+ }
+ int ret;
+ if (GDVIRTUAL_CALL(_rpc, p_peer_id, p_obj, p_method, args, ret)) {
+ return (Error)ret;
+ }
+ return FAILED;
+}
+
+int MultiplayerAPIExtension::get_remote_sender_id() {
+ int id;
+ if (GDVIRTUAL_CALL(_get_remote_sender_id, id)) {
+ return id;
+ }
+ return 0;
+}
+
+Error MultiplayerAPIExtension::object_configuration_add(Object *p_object, Variant p_config) {
+ int err;
+ if (GDVIRTUAL_CALL(_object_configuration_add, p_object, p_config, err)) {
+ return (Error)err;
+ }
+ return ERR_UNAVAILABLE;
+}
+
+Error MultiplayerAPIExtension::object_configuration_remove(Object *p_object, Variant p_config) {
+ int err;
+ if (GDVIRTUAL_CALL(_object_configuration_remove, p_object, p_config, err)) {
+ return (Error)err;
+ }
+ return ERR_UNAVAILABLE;
+}
+
+void MultiplayerAPIExtension::_bind_methods() {
+ GDVIRTUAL_BIND(_poll);
+ GDVIRTUAL_BIND(_set_multiplayer_peer, "multiplayer_peer");
+ GDVIRTUAL_BIND(_get_multiplayer_peer);
+ GDVIRTUAL_BIND(_get_unique_id);
+ GDVIRTUAL_BIND(_get_peer_ids);
+ GDVIRTUAL_BIND(_rpc, "peer", "object", "method", "args");
+ GDVIRTUAL_BIND(_get_remote_sender_id);
+ GDVIRTUAL_BIND(_object_configuration_add, "object", "configuration");
+ GDVIRTUAL_BIND(_object_configuration_remove, "object", "configuration");
+}
diff --git a/scene/main/multiplayer_api.h b/scene/main/multiplayer_api.h
new file mode 100644
index 0000000000..c1d90d651e
--- /dev/null
+++ b/scene/main/multiplayer_api.h
@@ -0,0 +1,115 @@
+/*************************************************************************/
+/* multiplayer_api.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef MULTIPLAYER_API_H
+#define MULTIPLAYER_API_H
+
+#include "core/object/ref_counted.h"
+#include "scene/main/multiplayer_peer.h"
+
+class MultiplayerAPI : public RefCounted {
+ GDCLASS(MultiplayerAPI, RefCounted);
+
+private:
+ static StringName default_interface;
+
+protected:
+ static void _bind_methods();
+ Error _rpc_bind(int p_peer, Object *p_obj, const StringName &p_method, Array args = Array());
+
+public:
+ enum RPCMode {
+ RPC_MODE_DISABLED, // No rpc for this method, calls to this will be blocked (default)
+ RPC_MODE_ANY_PEER, // Any peer can call this RPC
+ RPC_MODE_AUTHORITY, // Only the node's multiplayer authority (server by default) can call this RPC
+ };
+
+ static Ref<MultiplayerAPI> create_default_interface();
+ static void set_default_interface(const StringName &p_interface);
+ static StringName get_default_interface();
+
+ static Error encode_and_compress_variant(const Variant &p_variant, uint8_t *p_buffer, int &r_len, bool p_allow_object_decoding);
+ static Error decode_and_decompress_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int *r_len, bool p_allow_object_decoding);
+ static Error encode_and_compress_variants(const Variant **p_variants, int p_count, uint8_t *p_buffer, int &r_len, bool *r_raw = nullptr, bool p_allow_object_decoding = false);
+ static Error decode_and_decompress_variants(Vector<Variant> &r_variants, const uint8_t *p_buffer, int p_len, int &r_len, bool p_raw = false, bool p_allow_object_decoding = false);
+
+ virtual Error poll() = 0;
+ virtual void set_multiplayer_peer(const Ref<MultiplayerPeer> &p_peer) = 0;
+ virtual Ref<MultiplayerPeer> get_multiplayer_peer() = 0;
+ virtual int get_unique_id() = 0;
+ virtual Vector<int> get_peer_ids() = 0;
+
+ virtual Error rpcp(Object *p_obj, int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount) = 0;
+ virtual int get_remote_sender_id() = 0;
+
+ virtual Error object_configuration_add(Object *p_object, Variant p_config) = 0;
+ virtual Error object_configuration_remove(Object *p_object, Variant p_config) = 0;
+
+ bool has_multiplayer_peer() { return get_multiplayer_peer().is_valid(); }
+ bool is_server() { return get_unique_id() == MultiplayerPeer::TARGET_PEER_SERVER; }
+
+ MultiplayerAPI() {}
+ virtual ~MultiplayerAPI() {}
+};
+
+VARIANT_ENUM_CAST(MultiplayerAPI::RPCMode);
+
+class MultiplayerAPIExtension : public MultiplayerAPI {
+ GDCLASS(MultiplayerAPIExtension, MultiplayerAPI);
+
+protected:
+ static void _bind_methods();
+
+public:
+ virtual Error poll() override;
+ virtual void set_multiplayer_peer(const Ref<MultiplayerPeer> &p_peer) override;
+ virtual Ref<MultiplayerPeer> get_multiplayer_peer() override;
+ virtual int get_unique_id() override;
+ virtual Vector<int> get_peer_ids() override;
+
+ virtual Error rpcp(Object *p_obj, int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount) override;
+ virtual int get_remote_sender_id() override;
+
+ virtual Error object_configuration_add(Object *p_object, Variant p_config) override;
+ virtual Error object_configuration_remove(Object *p_object, Variant p_config) override;
+
+ // Extensions
+ GDVIRTUAL0R(int, _poll);
+ GDVIRTUAL1(_set_multiplayer_peer, Ref<MultiplayerPeer>);
+ GDVIRTUAL0R(Ref<MultiplayerPeer>, _get_multiplayer_peer);
+ GDVIRTUAL0RC(int, _get_unique_id);
+ GDVIRTUAL0RC(PackedInt32Array, _get_peer_ids);
+ GDVIRTUAL4R(int, _rpc, int, Object *, StringName, Array);
+ GDVIRTUAL0RC(int, _get_remote_sender_id);
+ GDVIRTUAL2R(int, _object_configuration_add, Object *, Variant);
+ GDVIRTUAL2R(int, _object_configuration_remove, Object *, Variant);
+};
+
+#endif // MULTIPLAYER_API_H
diff --git a/core/multiplayer/multiplayer_peer.cpp b/scene/main/multiplayer_peer.cpp
index c7de7a1313..aad5baccab 100644
--- a/core/multiplayer/multiplayer_peer.cpp
+++ b/scene/main/multiplayer_peer.cpp
@@ -62,11 +62,11 @@ int MultiplayerPeer::get_transfer_channel() const {
return transfer_channel;
}
-void MultiplayerPeer::set_transfer_mode(Multiplayer::TransferMode p_mode) {
+void MultiplayerPeer::set_transfer_mode(TransferMode p_mode) {
transfer_mode = p_mode;
}
-Multiplayer::TransferMode MultiplayerPeer::get_transfer_mode() const {
+MultiplayerPeer::TransferMode MultiplayerPeer::get_transfer_mode() const {
return transfer_mode;
}
@@ -107,6 +107,10 @@ void MultiplayerPeer::_bind_methods() {
BIND_CONSTANT(TARGET_PEER_BROADCAST);
BIND_CONSTANT(TARGET_PEER_SERVER);
+ BIND_ENUM_CONSTANT(TRANSFER_MODE_UNRELIABLE);
+ BIND_ENUM_CONSTANT(TRANSFER_MODE_UNRELIABLE_ORDERED);
+ BIND_ENUM_CONSTANT(TRANSFER_MODE_RELIABLE);
+
ADD_SIGNAL(MethodInfo("peer_connected", PropertyInfo(Variant::INT, "id")));
ADD_SIGNAL(MethodInfo("peer_disconnected", PropertyInfo(Variant::INT, "id")));
ADD_SIGNAL(MethodInfo("server_disconnected"));
@@ -191,17 +195,17 @@ int MultiplayerPeerExtension::get_transfer_channel() const {
return MultiplayerPeer::get_transfer_channel();
}
-void MultiplayerPeerExtension::set_transfer_mode(Multiplayer::TransferMode p_mode) {
+void MultiplayerPeerExtension::set_transfer_mode(TransferMode p_mode) {
if (GDVIRTUAL_CALL(_set_transfer_mode, p_mode)) {
return;
}
MultiplayerPeer::set_transfer_mode(p_mode);
}
-Multiplayer::TransferMode MultiplayerPeerExtension::get_transfer_mode() const {
+MultiplayerPeer::TransferMode MultiplayerPeerExtension::get_transfer_mode() const {
int mode;
if (GDVIRTUAL_CALL(_get_transfer_mode, mode)) {
- return (Multiplayer::TransferMode)mode;
+ return (MultiplayerPeer::TransferMode)mode;
}
return MultiplayerPeer::get_transfer_mode();
}
diff --git a/core/multiplayer/multiplayer_peer.h b/scene/main/multiplayer_peer.h
index 91546832ce..8a012d7520 100644
--- a/core/multiplayer/multiplayer_peer.h
+++ b/scene/main/multiplayer_peer.h
@@ -32,7 +32,6 @@
#define MULTIPLAYER_PEER_H
#include "core/io/packet_peer.h"
-#include "core/multiplayer/multiplayer.h"
#include "core/object/gdvirtual.gen.inc"
#include "core/object/script_language.h"
@@ -41,12 +40,19 @@
class MultiplayerPeer : public PacketPeer {
GDCLASS(MultiplayerPeer, PacketPeer);
+public:
+ enum TransferMode {
+ TRANSFER_MODE_UNRELIABLE,
+ TRANSFER_MODE_UNRELIABLE_ORDERED,
+ TRANSFER_MODE_RELIABLE
+ };
+
protected:
static void _bind_methods();
private:
int transfer_channel = 0;
- Multiplayer::TransferMode transfer_mode = Multiplayer::TRANSFER_MODE_RELIABLE;
+ TransferMode transfer_mode = TRANSFER_MODE_RELIABLE;
bool refuse_connections = false;
public:
@@ -63,8 +69,8 @@ public:
virtual void set_transfer_channel(int p_channel);
virtual int get_transfer_channel() const;
- virtual void set_transfer_mode(Multiplayer::TransferMode p_mode);
- virtual Multiplayer::TransferMode get_transfer_mode() const;
+ virtual void set_transfer_mode(TransferMode p_mode);
+ virtual TransferMode get_transfer_mode() const;
virtual void set_refuse_new_connections(bool p_enable);
virtual bool is_refusing_new_connections() const;
@@ -86,6 +92,7 @@ public:
};
VARIANT_ENUM_CAST(MultiplayerPeer::ConnectionStatus);
+VARIANT_ENUM_CAST(MultiplayerPeer::TransferMode);
class MultiplayerPeerExtension : public MultiplayerPeer {
GDCLASS(MultiplayerPeerExtension, MultiplayerPeer);
@@ -105,8 +112,8 @@ public:
/* MultiplayerPeer */
virtual void set_transfer_channel(int p_channel) override;
virtual int get_transfer_channel() const override;
- virtual void set_transfer_mode(Multiplayer::TransferMode p_mode) override;
- virtual Multiplayer::TransferMode get_transfer_mode() const override;
+ virtual void set_transfer_mode(TransferMode p_mode) override;
+ virtual TransferMode get_transfer_mode() const override;
virtual void set_target_peer(int p_peer_id) override;
virtual int get_packet_peer() const override;
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index b4701637a4..4bf1936a65 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -33,12 +33,12 @@
#include "core/config/project_settings.h"
#include "core/core_string_names.h"
#include "core/io/resource_loader.h"
-#include "core/multiplayer/multiplayer_api.h"
#include "core/object/message_queue.h"
#include "core/string/print_string.h"
#include "instance_placeholder.h"
#include "scene/animation/tween.h"
#include "scene/debugger/scene_debugger.h"
+#include "scene/main/multiplayer_api.h"
#include "scene/resources/packed_scene.h"
#include "scene/scene_string_names.h"
#include "viewport.h"
@@ -582,35 +582,30 @@ bool Node::is_multiplayer_authority() const {
/***** RPC CONFIG ********/
-uint16_t Node::rpc_config(const StringName &p_method, Multiplayer::RPCMode p_rpc_mode, bool p_call_local, Multiplayer::TransferMode p_transfer_mode, int p_channel) {
- for (int i = 0; i < data.rpc_methods.size(); i++) {
- if (data.rpc_methods[i].name == p_method) {
- Multiplayer::RPCConfig &nd = data.rpc_methods.write[i];
- nd.rpc_mode = p_rpc_mode;
- nd.transfer_mode = p_transfer_mode;
- nd.call_local = p_call_local;
- nd.channel = p_channel;
- return i | (1 << 15);
- }
+void Node::rpc_config(const StringName &p_method, const Variant &p_config) {
+ if (data.rpc_config.get_type() != Variant::DICTIONARY) {
+ data.rpc_config = Dictionary();
+ }
+ Dictionary node_config = data.rpc_config;
+ if (p_config.get_type() == Variant::NIL) {
+ node_config.erase(p_method);
+ } else {
+ ERR_FAIL_COND(p_config.get_type() != Variant::DICTIONARY);
+ node_config[p_method] = p_config;
}
- // New method
- Multiplayer::RPCConfig nd;
- nd.name = p_method;
- nd.rpc_mode = p_rpc_mode;
- nd.transfer_mode = p_transfer_mode;
- nd.channel = p_channel;
- nd.call_local = p_call_local;
- data.rpc_methods.push_back(nd);
- return ((uint16_t)data.rpc_methods.size() - 1) | (1 << 15);
+}
+
+const Variant Node::get_node_rpc_config() const {
+ return data.rpc_config;
}
/***** RPC FUNCTIONS ********/
-void Node::_rpc_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
+Error Node::_rpc_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
if (p_argcount < 1) {
r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.argument = 1;
- return;
+ return ERR_INVALID_PARAMETER;
}
Variant::Type type = p_args[0]->get_type();
@@ -618,28 +613,28 @@ void Node::_rpc_bind(const Variant **p_args, int p_argcount, Callable::CallError
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = Variant::STRING_NAME;
- return;
+ return ERR_INVALID_PARAMETER;
}
StringName method = (*p_args[0]).operator StringName();
- rpcp(0, method, &p_args[1], p_argcount - 1);
-
+ Error err = rpcp(0, method, &p_args[1], p_argcount - 1);
r_error.error = Callable::CallError::CALL_OK;
+ return err;
}
-void Node::_rpc_id_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
+Error Node::_rpc_id_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
if (p_argcount < 2) {
r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.argument = 2;
- return;
+ return ERR_INVALID_PARAMETER;
}
if (p_args[0]->get_type() != Variant::INT) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = Variant::INT;
- return;
+ return ERR_INVALID_PARAMETER;
}
Variant::Type type = p_args[1]->get_type();
@@ -647,20 +642,35 @@ void Node::_rpc_id_bind(const Variant **p_args, int p_argcount, Callable::CallEr
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 1;
r_error.expected = Variant::STRING_NAME;
- return;
+ return ERR_INVALID_PARAMETER;
}
int peer_id = *p_args[0];
StringName method = (*p_args[1]).operator StringName();
- rpcp(peer_id, method, &p_args[2], p_argcount - 2);
-
+ Error err = rpcp(peer_id, method, &p_args[2], p_argcount - 2);
r_error.error = Callable::CallError::CALL_OK;
+ return err;
}
-void Node::rpcp(int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount) {
- ERR_FAIL_COND(!is_inside_tree());
- get_multiplayer()->rpcp(this, p_peer_id, p_method, p_arg, p_argcount);
+template <typename... VarArgs>
+Error Node::rpc(const StringName &p_method, VarArgs... p_args) {
+ return rpc_id(0, p_method, p_args...);
+}
+
+template <typename... VarArgs>
+Error Node::rpc_id(int p_peer_id, const StringName &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];
+ for (uint32_t i = 0; i < sizeof...(p_args); i++) {
+ argptrs[i] = &args[i];
+ }
+ return rpcp(p_peer_id, p_method, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
+}
+
+Error Node::rpcp(int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount) {
+ ERR_FAIL_COND_V(!is_inside_tree(), ERR_UNCONFIGURED);
+ return get_multiplayer()->rpcp(this, p_peer_id, p_method, p_arg, p_argcount);
}
Ref<MultiplayerAPI> Node::get_multiplayer() const {
@@ -670,10 +680,6 @@ Ref<MultiplayerAPI> Node::get_multiplayer() const {
return get_tree()->get_multiplayer(get_path());
}
-Vector<Multiplayer::RPCConfig> Node::get_node_rpc_methods() const {
- return data.rpc_methods;
-}
-
//////////// end of rpc
bool Node::can_process_notification(int p_what) const {
@@ -2888,7 +2894,7 @@ void Node::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_multiplayer_authority"), &Node::is_multiplayer_authority);
ClassDB::bind_method(D_METHOD("get_multiplayer"), &Node::get_multiplayer);
- ClassDB::bind_method(D_METHOD("rpc_config", "method", "rpc_mode", "call_local", "transfer_mode", "channel"), &Node::rpc_config, DEFVAL(false), DEFVAL(Multiplayer::TRANSFER_MODE_RELIABLE), DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("rpc_config", "method", "config"), &Node::rpc_config);
ClassDB::bind_method(D_METHOD("set_editor_description", "editor_description"), &Node::set_editor_description);
ClassDB::bind_method(D_METHOD("get_editor_description"), &Node::get_editor_description);
diff --git a/scene/main/node.h b/scene/main/node.h
index d978c03442..0645c68eb9 100644
--- a/scene/main/node.h
+++ b/scene/main/node.h
@@ -127,7 +127,7 @@ private:
Node *process_owner = nullptr;
int multiplayer_authority = 1; // Server by default.
- Vector<Multiplayer::RPCConfig> rpc_methods;
+ Variant rpc_config;
// Variables used to properly sort the node when processing, ignored otherwise.
// TODO: Should move all the stuff below to bits.
@@ -183,8 +183,8 @@ private:
TypedArray<Node> _get_children(bool p_include_internal = true) const;
Array _get_groups() const;
- void _rpc_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
- void _rpc_id_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
+ Error _rpc_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
+ Error _rpc_id_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
_FORCE_INLINE_ bool _is_internal_front() const { return data.parent && data.pos < data.parent->data.internal_children_front; }
_FORCE_INLINE_ bool _is_internal_back() const { return data.parent && data.pos >= data.parent->data.children.size() - data.parent->data.internal_children_back; }
@@ -491,30 +491,16 @@ public:
int get_multiplayer_authority() const;
bool is_multiplayer_authority() const;
- uint16_t rpc_config(const StringName &p_method, Multiplayer::RPCMode p_rpc_mode, bool p_call_local = false, Multiplayer::TransferMode p_transfer_mode = Multiplayer::TRANSFER_MODE_RELIABLE, int p_channel = 0); // config a local method for RPC
- Vector<Multiplayer::RPCConfig> get_node_rpc_methods() const;
+ void rpc_config(const StringName &p_method, const Variant &p_config); // config a local method for RPC
+ const Variant get_node_rpc_config() const;
template <typename... VarArgs>
- void rpc(const StringName &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];
- for (uint32_t i = 0; i < sizeof...(p_args); i++) {
- argptrs[i] = &args[i];
- }
- rpcp(0, p_method, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
- }
+ Error rpc(const StringName &p_method, VarArgs... p_args);
template <typename... VarArgs>
- void rpc_id(int p_peer_id, const StringName &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];
- for (uint32_t i = 0; i < sizeof...(p_args); i++) {
- argptrs[i] = &args[i];
- }
- rpcp(p_peer_id, p_method, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
- }
+ Error rpc_id(int p_peer_id, const StringName &p_method, VarArgs... p_args);
- void rpcp(int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount);
+ Error rpcp(int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount);
Ref<MultiplayerAPI> get_multiplayer() const;
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index 66482f65dc..644fb3e9cc 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -37,7 +37,6 @@
#include "core/io/image_loader.h"
#include "core/io/marshalls.h"
#include "core/io/resource_loader.h"
-#include "core/multiplayer/multiplayer_api.h"
#include "core/object/message_queue.h"
#include "core/os/keyboard.h"
#include "core/os/os.h"
@@ -45,6 +44,7 @@
#include "node.h"
#include "scene/animation/tween.h"
#include "scene/debugger/scene_debugger.h"
+#include "scene/main/multiplayer_api.h"
#include "scene/main/viewport.h"
#include "scene/resources/font.h"
#include "scene/resources/material.h"
@@ -1213,19 +1213,17 @@ void SceneTree::set_multiplayer(Ref<MultiplayerAPI> p_multiplayer, const NodePat
if (p_root_path.is_empty()) {
ERR_FAIL_COND(!p_multiplayer.is_valid());
if (multiplayer.is_valid()) {
- multiplayer->set_root_path(NodePath());
+ multiplayer->object_configuration_remove(nullptr, NodePath("/" + root->get_name()));
}
multiplayer = p_multiplayer;
- multiplayer->set_root_path("/" + root->get_name());
+ multiplayer->object_configuration_add(nullptr, NodePath("/" + root->get_name()));
} else {
+ if (custom_multiplayers.has(p_root_path)) {
+ custom_multiplayers[p_root_path]->object_configuration_remove(nullptr, p_root_path);
+ }
if (p_multiplayer.is_valid()) {
custom_multiplayers[p_root_path] = p_multiplayer;
- p_multiplayer->set_root_path(p_root_path);
- } else {
- if (custom_multiplayers.has(p_root_path)) {
- custom_multiplayers[p_root_path]->set_root_path(NodePath());
- custom_multiplayers.erase(p_root_path);
- }
+ p_multiplayer->object_configuration_add(nullptr, p_root_path);
}
}
}
@@ -1415,7 +1413,7 @@ SceneTree::SceneTree() {
#endif // _3D_DISABLED
// Initialize network state.
- set_multiplayer(Ref<MultiplayerAPI>(memnew(MultiplayerAPI)));
+ set_multiplayer(MultiplayerAPI::create_default_interface());
root->set_as_audio_listener_2d(true);
current_scene = nullptr;
diff --git a/scene/main/shader_globals_override.cpp b/scene/main/shader_globals_override.cpp
index 3b6055fcf7..a621aea9c8 100644
--- a/scene/main/shader_globals_override.cpp
+++ b/scene/main/shader_globals_override.cpp
@@ -64,9 +64,9 @@ bool ShaderGlobalsOverride::_set(const StringName &p_name, const Variant &p_valu
if (active) {
if (o->override.get_type() == Variant::OBJECT) {
RID tex_rid = p_value;
- RS::get_singleton()->global_variable_set_override(*r, tex_rid);
+ RS::get_singleton()->global_shader_uniform_set_override(*r, tex_rid);
} else {
- RS::get_singleton()->global_variable_set_override(*r, p_value);
+ RS::get_singleton()->global_shader_uniform_set_override(*r, p_value);
}
}
o->in_use = p_value.get_type() != Variant::NIL;
@@ -93,13 +93,13 @@ bool ShaderGlobalsOverride::_get(const StringName &p_name, Variant &r_ret) const
void ShaderGlobalsOverride::_get_property_list(List<PropertyInfo> *p_list) const {
Vector<StringName> variables;
- variables = RS::get_singleton()->global_variable_get_list();
+ variables = RS::get_singleton()->global_shader_uniform_get_list();
for (int i = 0; i < variables.size(); i++) {
PropertyInfo pinfo;
pinfo.name = "params/" + variables[i];
pinfo.usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE;
- switch (RS::get_singleton()->global_variable_get_type(variables[i])) {
+ switch (RS::get_singleton()->global_shader_uniform_get_type(variables[i])) {
case RS::GLOBAL_VAR_TYPE_BOOL: {
pinfo.type = Variant::BOOL;
} break;
@@ -234,9 +234,9 @@ void ShaderGlobalsOverride::_activate() {
if (o->in_use && o->override.get_type() != Variant::NIL) {
if (o->override.get_type() == Variant::OBJECT) {
RID tex_rid = o->override;
- RS::get_singleton()->global_variable_set_override(E.key, tex_rid);
+ RS::get_singleton()->global_shader_uniform_set_override(E.key, tex_rid);
} else {
- RS::get_singleton()->global_variable_set_override(E.key, o->override);
+ RS::get_singleton()->global_shader_uniform_set_override(E.key, o->override);
}
}
@@ -258,7 +258,7 @@ void ShaderGlobalsOverride::_notification(int p_what) {
for (const KeyValue<StringName, Override> &E : overrides) {
const Override *o = &E.value;
if (o->in_use) {
- RS::get_singleton()->global_variable_set_override(E.key, Variant());
+ RS::get_singleton()->global_shader_uniform_set_override(E.key, Variant());
}
}
}
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 7876b00202..4dd4c8419c 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -3631,17 +3631,17 @@ float Viewport::get_fsr_sharpness() const {
return fsr_sharpness;
}
-void Viewport::set_fsr_mipmap_bias(float p_fsr_mipmap_bias) {
- if (fsr_mipmap_bias == p_fsr_mipmap_bias) {
+void Viewport::set_texture_mipmap_bias(float p_texture_mipmap_bias) {
+ if (texture_mipmap_bias == p_texture_mipmap_bias) {
return;
}
- fsr_mipmap_bias = p_fsr_mipmap_bias;
- RS::get_singleton()->viewport_set_fsr_mipmap_bias(viewport, p_fsr_mipmap_bias);
+ texture_mipmap_bias = p_texture_mipmap_bias;
+ RS::get_singleton()->viewport_set_texture_mipmap_bias(viewport, p_texture_mipmap_bias);
}
-float Viewport::get_fsr_mipmap_bias() const {
- return fsr_mipmap_bias;
+float Viewport::get_texture_mipmap_bias() const {
+ return texture_mipmap_bias;
}
#endif // _3D_DISABLED
@@ -3783,8 +3783,8 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_fsr_sharpness", "fsr_sharpness"), &Viewport::set_fsr_sharpness);
ClassDB::bind_method(D_METHOD("get_fsr_sharpness"), &Viewport::get_fsr_sharpness);
- ClassDB::bind_method(D_METHOD("set_fsr_mipmap_bias", "fsr_mipmap_bias"), &Viewport::set_fsr_mipmap_bias);
- ClassDB::bind_method(D_METHOD("get_fsr_mipmap_bias"), &Viewport::get_fsr_mipmap_bias);
+ ClassDB::bind_method(D_METHOD("set_texture_mipmap_bias", "texture_mipmap_bias"), &Viewport::set_texture_mipmap_bias);
+ ClassDB::bind_method(D_METHOD("get_texture_mipmap_bias"), &Viewport::get_texture_mipmap_bias);
ClassDB::bind_method(D_METHOD("set_vrs_mode", "mode"), &Viewport::set_vrs_mode);
ClassDB::bind_method(D_METHOD("get_vrs_mode"), &Viewport::get_vrs_mode);
@@ -3814,7 +3814,7 @@ void Viewport::_bind_methods() {
ADD_GROUP("Scaling 3D", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "scaling_3d_mode", PROPERTY_HINT_ENUM, "Bilinear (Fastest),FSR 1.0 (Fast)"), "set_scaling_3d_mode", "get_scaling_3d_mode");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "scaling_3d_scale", PROPERTY_HINT_RANGE, "0.25,2.0,0.01"), "set_scaling_3d_scale", "get_scaling_3d_scale");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fsr_mipmap_bias", PROPERTY_HINT_RANGE, "-2,2,0.1"), "set_fsr_mipmap_bias", "get_fsr_mipmap_bias");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "texture_mipmap_bias", PROPERTY_HINT_RANGE, "-2,2,0.001"), "set_texture_mipmap_bias", "get_texture_mipmap_bias");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fsr_sharpness", PROPERTY_HINT_RANGE, "0,2,0.1"), "set_fsr_sharpness", "get_fsr_sharpness");
#endif
ADD_GROUP("Variable Rate Shading", "vrs_");
@@ -3988,8 +3988,8 @@ Viewport::Viewport() {
float fsr_sharpness = GLOBAL_GET("rendering/scaling_3d/fsr_sharpness");
set_fsr_sharpness(fsr_sharpness);
- float fsr_mipmap_bias = GLOBAL_GET("rendering/scaling_3d/fsr_mipmap_bias");
- set_fsr_mipmap_bias(fsr_mipmap_bias);
+ float texture_mipmap_bias = GLOBAL_GET("rendering/textures/default_filters/texture_mipmap_bias");
+ set_texture_mipmap_bias(texture_mipmap_bias);
#endif // _3D_DISABLED
set_sdf_oversize(sdf_oversize); // Set to server.
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index 58b05d23e0..4221baff06 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -304,7 +304,7 @@ private:
Scaling3DMode scaling_3d_mode = SCALING_3D_MODE_BILINEAR;
float scaling_3d_scale = 1.0;
float fsr_sharpness = 0.2f;
- float fsr_mipmap_bias = 0.0f;
+ float texture_mipmap_bias = 0.0f;
bool use_debanding = false;
float mesh_lod_threshold = 1.0;
bool use_occlusion_culling = false;
@@ -540,8 +540,8 @@ public:
void set_fsr_sharpness(float p_fsr_sharpness);
float get_fsr_sharpness() const;
- void set_fsr_mipmap_bias(float p_fsr_mipmap_bias);
- float get_fsr_mipmap_bias() const;
+ void set_texture_mipmap_bias(float p_texture_mipmap_bias);
+ float get_texture_mipmap_bias() const;
void set_use_debanding(bool p_use_debanding);
bool is_using_debanding() const;
diff --git a/scene/main/window.cpp b/scene/main/window.cpp
index 73e8f537d9..bd72858ae6 100644
--- a/scene/main/window.cpp
+++ b/scene/main/window.cpp
@@ -1516,7 +1516,7 @@ void Window::_validate_property(PropertyInfo &property) const {
Transform2D Window::get_screen_transform() const {
Transform2D embedder_transform = Transform2D();
if (_get_embedder()) {
- embedder_transform.translate(get_position());
+ embedder_transform.translate_local(get_position());
embedder_transform = _get_embedder()->get_screen_transform() * embedder_transform;
}
return embedder_transform * Viewport::get_screen_transform();
diff --git a/scene/multiplayer/SCsub b/scene/multiplayer/SCsub
deleted file mode 100644
index fc61250247..0000000000
--- a/scene/multiplayer/SCsub
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/usr/bin/env python
-
-Import("env")
-
-env.add_source_files(env.scene_sources, "*.cpp")
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index ef5ac36114..7c973e1d6f 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -130,18 +130,14 @@
#include "scene/main/http_request.h"
#include "scene/main/instance_placeholder.h"
#include "scene/main/missing_node.h"
+#include "scene/main/multiplayer_api.h"
#include "scene/main/resource_preloader.h"
#include "scene/main/scene_tree.h"
#include "scene/main/timer.h"
#include "scene/main/viewport.h"
#include "scene/main/window.h"
-#include "scene/multiplayer/multiplayer_spawner.h"
-#include "scene/multiplayer/multiplayer_synchronizer.h"
-#include "scene/multiplayer/scene_cache_interface.h"
-#include "scene/multiplayer/scene_replication_interface.h"
-#include "scene/multiplayer/scene_rpc_interface.h"
#include "scene/resources/animation_library.h"
-#include "scene/resources/audio_stream_sample.h"
+#include "scene/resources/audio_stream_wav.h"
#include "scene/resources/bit_map.h"
#include "scene/resources/bone_map.h"
#include "scene/resources/box_shape_3d.h"
@@ -322,9 +318,13 @@ void register_scene_types() {
GDREGISTER_ABSTRACT_CLASS(Viewport);
GDREGISTER_CLASS(SubViewport);
GDREGISTER_CLASS(ViewportTexture);
+
+ GDREGISTER_ABSTRACT_CLASS(MultiplayerPeer);
+ GDREGISTER_CLASS(MultiplayerPeerExtension);
+ GDREGISTER_ABSTRACT_CLASS(MultiplayerAPI);
+ GDREGISTER_CLASS(MultiplayerAPIExtension);
+
GDREGISTER_CLASS(HTTPRequest);
- GDREGISTER_CLASS(MultiplayerSpawner);
- GDREGISTER_CLASS(MultiplayerSynchronizer);
GDREGISTER_CLASS(Timer);
GDREGISTER_CLASS(CanvasLayer);
GDREGISTER_CLASS(CanvasModulate);
@@ -876,8 +876,6 @@ void register_scene_types() {
GDREGISTER_CLASS(LabelSettings);
- GDREGISTER_CLASS(SceneReplicationConfig);
-
GDREGISTER_CLASS(TextLine);
GDREGISTER_CLASS(TextParagraph);
@@ -904,7 +902,7 @@ void register_scene_types() {
GDREGISTER_CLASS(AudioStreamPlayer3D);
#endif
GDREGISTER_ABSTRACT_CLASS(VideoStream);
- GDREGISTER_CLASS(AudioStreamSample);
+ GDREGISTER_CLASS(AudioStreamWAV);
OS::get_singleton()->yield(); // may take time to init
@@ -1091,6 +1089,9 @@ void register_scene_types() {
ClassDB::add_compatibility_class("World", "World3D");
// Renamed during 4.0 alpha, added to ease transition between alphas.
+ ClassDB::add_compatibility_class("AudioStreamOGGVorbis", "AudioStreamOggVorbis");
+ ClassDB::add_compatibility_class("AudioStreamSample", "AudioStreamWAV");
+ ClassDB::add_compatibility_class("OGGPacketSequence", "OggPacketSequence");
ClassDB::add_compatibility_class("StreamCubemap", "CompressedCubemap");
ClassDB::add_compatibility_class("StreamCubemapArray", "CompressedCubemapArray");
ClassDB::add_compatibility_class("StreamTexture2D", "CompressedTexture2D");
@@ -1118,9 +1119,6 @@ void register_scene_types() {
}
SceneDebugger::initialize();
- SceneReplicationInterface::make_default();
- SceneRPCInterface::make_default();
- SceneCacheInterface::make_default();
}
void initialize_theme() {
diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp
index 7183accc66..19545167c8 100644
--- a/scene/resources/animation.cpp
+++ b/scene/resources/animation.cpp
@@ -2302,7 +2302,7 @@ Vector3 Animation::_cubic_interpolate(const Vector3 &p_pre_a, const Vector3 &p_a
}
Quaternion Animation::_cubic_interpolate(const Quaternion &p_pre_a, const Quaternion &p_a, const Quaternion &p_b, const Quaternion &p_post_b, real_t p_c) const {
- return p_a.cubic_slerp(p_b, p_pre_a, p_post_b, p_c);
+ return p_a.spherical_cubic_interpolate(p_b, p_pre_a, p_post_b, p_c);
}
Variant Animation::_cubic_interpolate(const Variant &p_pre_a, const Variant &p_a, const Variant &p_b, const Variant &p_post_b, real_t p_c) const {
@@ -2363,7 +2363,7 @@ Variant Animation::_cubic_interpolate(const Variant &p_pre_a, const Variant &p_a
Quaternion pa = p_pre_a;
Quaternion pb = p_post_b;
- return a.cubic_slerp(b, pa, pb, p_c);
+ return a.spherical_cubic_interpolate(b, pa, pb, p_c);
}
case Variant::AABB: {
AABB a = p_a;
diff --git a/scene/resources/audio_stream_sample.cpp b/scene/resources/audio_stream_wav.cpp
index dcd36284d4..a87c8272ea 100644
--- a/scene/resources/audio_stream_sample.cpp
+++ b/scene/resources/audio_stream_wav.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* audio_stream_sample.cpp */
+/* audio_stream_wav.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,13 +28,13 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "audio_stream_sample.h"
+#include "audio_stream_wav.h"
#include "core/io/file_access.h"
#include "core/io/marshalls.h"
-void AudioStreamPlaybackSample::start(float p_from_pos) {
- if (base->format == AudioStreamSample::FORMAT_IMA_ADPCM) {
+void AudioStreamPlaybackWAV::start(float p_from_pos) {
+ if (base->format == AudioStreamWAV::FORMAT_IMA_ADPCM) {
//no seeking in IMA_ADPCM
for (int i = 0; i < 2; i++) {
ima_adpcm[i].step_index = 0;
@@ -55,24 +55,24 @@ void AudioStreamPlaybackSample::start(float p_from_pos) {
active = true;
}
-void AudioStreamPlaybackSample::stop() {
+void AudioStreamPlaybackWAV::stop() {
active = false;
}
-bool AudioStreamPlaybackSample::is_playing() const {
+bool AudioStreamPlaybackWAV::is_playing() const {
return active;
}
-int AudioStreamPlaybackSample::get_loop_count() const {
+int AudioStreamPlaybackWAV::get_loop_count() const {
return 0;
}
-float AudioStreamPlaybackSample::get_playback_position() const {
+float AudioStreamPlaybackWAV::get_playback_position() const {
return float(offset >> MIX_FRAC_BITS) / base->mix_rate;
}
-void AudioStreamPlaybackSample::seek(float p_time) {
- if (base->format == AudioStreamSample::FORMAT_IMA_ADPCM) {
+void AudioStreamPlaybackWAV::seek(float p_time) {
+ if (base->format == AudioStreamWAV::FORMAT_IMA_ADPCM) {
return; //no seeking in ima-adpcm
}
@@ -87,7 +87,7 @@ void AudioStreamPlaybackSample::seek(float p_time) {
}
template <class Depth, bool is_stereo, bool is_ima_adpcm>
-void AudioStreamPlaybackSample::do_resample(const Depth *p_src, AudioFrame *p_dst, int64_t &offset, int32_t &increment, uint32_t amount, IMA_ADPCM_State *ima_adpcm) {
+void AudioStreamPlaybackWAV::do_resample(const Depth *p_src, AudioFrame *p_dst, int64_t &offset, int32_t &increment, uint32_t amount, IMA_ADPCM_State *ima_adpcm) {
// this function will be compiled branchless by any decent compiler
int32_t final, final_r, next, next_r;
@@ -124,7 +124,7 @@ void AudioStreamPlaybackSample::do_resample(const Depth *p_src, AudioFrame *p_ds
ima_adpcm[i].last_nibble++;
const uint8_t *src_ptr = (const uint8_t *)base->data;
- src_ptr += AudioStreamSample::DATA_PAD;
+ src_ptr += AudioStreamWAV::DATA_PAD;
uint8_t nbb = src_ptr[(ima_adpcm[i].last_nibble >> 1) * (is_stereo ? 2 : 1) + i];
nibble = (ima_adpcm[i].last_nibble & 1) ? (nbb >> 4) : (nbb & 0xF);
@@ -221,7 +221,7 @@ void AudioStreamPlaybackSample::do_resample(const Depth *p_src, AudioFrame *p_ds
}
}
-int AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) {
+int AudioStreamPlaybackWAV::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) {
if (!base->data || !active) {
for (int i = 0; i < p_frames; i++) {
p_buffer[i] = AudioFrame(0, 0);
@@ -231,13 +231,13 @@ int AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, int
int len = base->data_bytes;
switch (base->format) {
- case AudioStreamSample::FORMAT_8_BITS:
+ case AudioStreamWAV::FORMAT_8_BITS:
len /= 1;
break;
- case AudioStreamSample::FORMAT_16_BITS:
+ case AudioStreamWAV::FORMAT_16_BITS:
len /= 2;
break;
- case AudioStreamSample::FORMAT_IMA_ADPCM:
+ case AudioStreamWAV::FORMAT_IMA_ADPCM:
len *= 2;
break;
}
@@ -251,13 +251,13 @@ int AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, int
int64_t loop_begin_fp = ((int64_t)base->loop_begin << MIX_FRAC_BITS);
int64_t loop_end_fp = ((int64_t)base->loop_end << MIX_FRAC_BITS);
int64_t length_fp = ((int64_t)len << MIX_FRAC_BITS);
- int64_t begin_limit = (base->loop_mode != AudioStreamSample::LOOP_DISABLED) ? loop_begin_fp : 0;
- int64_t end_limit = (base->loop_mode != AudioStreamSample::LOOP_DISABLED) ? loop_end_fp : length_fp;
+ int64_t begin_limit = (base->loop_mode != AudioStreamWAV::LOOP_DISABLED) ? loop_begin_fp : 0;
+ int64_t end_limit = (base->loop_mode != AudioStreamWAV::LOOP_DISABLED) ? loop_end_fp : length_fp;
bool is_stereo = base->stereo;
int32_t todo = p_frames;
- if (base->loop_mode == AudioStreamSample::LOOP_BACKWARD) {
+ if (base->loop_mode == AudioStreamWAV::LOOP_BACKWARD) {
sign = -1;
}
@@ -271,20 +271,20 @@ int AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, int
//looping
- AudioStreamSample::LoopMode loop_format = base->loop_mode;
- AudioStreamSample::Format format = base->format;
+ AudioStreamWAV::LoopMode loop_format = base->loop_mode;
+ AudioStreamWAV::Format format = base->format;
/* audio data */
uint8_t *dataptr = (uint8_t *)base->data;
- const void *data = dataptr + AudioStreamSample::DATA_PAD;
+ const void *data = dataptr + AudioStreamWAV::DATA_PAD;
AudioFrame *dst_buff = p_buffer;
- if (format == AudioStreamSample::FORMAT_IMA_ADPCM) {
- if (loop_format != AudioStreamSample::LOOP_DISABLED) {
+ if (format == AudioStreamWAV::FORMAT_IMA_ADPCM) {
+ if (loop_format != AudioStreamWAV::LOOP_DISABLED) {
ima_adpcm[0].loop_pos = loop_begin_fp >> MIX_FRAC_BITS;
ima_adpcm[1].loop_pos = loop_begin_fp >> MIX_FRAC_BITS;
- loop_format = AudioStreamSample::LOOP_FORWARD;
+ loop_format = AudioStreamWAV::LOOP_FORWARD;
}
}
@@ -297,9 +297,9 @@ int AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, int
if (increment < 0) {
/* going backwards */
- if (loop_format != AudioStreamSample::LOOP_DISABLED && offset < loop_begin_fp) {
+ if (loop_format != AudioStreamWAV::LOOP_DISABLED && offset < loop_begin_fp) {
/* loopstart reached */
- if (loop_format == AudioStreamSample::LOOP_PINGPONG) {
+ if (loop_format == AudioStreamWAV::LOOP_PINGPONG) {
/* bounce ping pong */
offset = loop_begin_fp + (loop_begin_fp - offset);
increment = -increment;
@@ -317,10 +317,10 @@ int AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, int
}
} else {
/* going forward */
- if (loop_format != AudioStreamSample::LOOP_DISABLED && offset >= loop_end_fp) {
+ if (loop_format != AudioStreamWAV::LOOP_DISABLED && offset >= loop_end_fp) {
/* loopend reached */
- if (loop_format == AudioStreamSample::LOOP_PINGPONG) {
+ if (loop_format == AudioStreamWAV::LOOP_PINGPONG) {
/* bounce ping pong */
offset = loop_end_fp - (offset - loop_end_fp);
increment = -increment;
@@ -328,7 +328,7 @@ int AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, int
} else {
/* go to loop-begin */
- if (format == AudioStreamSample::FORMAT_IMA_ADPCM) {
+ if (format == AudioStreamWAV::FORMAT_IMA_ADPCM) {
for (int i = 0; i < 2; i++) {
ima_adpcm[i].step_index = ima_adpcm[i].loop_step_index;
ima_adpcm[i].predictor = ima_adpcm[i].loop_predictor;
@@ -366,14 +366,14 @@ int AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, int
todo -= target;
switch (base->format) {
- case AudioStreamSample::FORMAT_8_BITS: {
+ case AudioStreamWAV::FORMAT_8_BITS: {
if (is_stereo) {
do_resample<int8_t, true, false>((int8_t *)data, dst_buff, offset, increment, target, ima_adpcm);
} else {
do_resample<int8_t, false, false>((int8_t *)data, dst_buff, offset, increment, target, ima_adpcm);
}
} break;
- case AudioStreamSample::FORMAT_16_BITS: {
+ case AudioStreamWAV::FORMAT_16_BITS: {
if (is_stereo) {
do_resample<int16_t, true, false>((int16_t *)data, dst_buff, offset, increment, target, ima_adpcm);
} else {
@@ -381,7 +381,7 @@ int AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, int
}
} break;
- case AudioStreamSample::FORMAT_IMA_ADPCM: {
+ case AudioStreamWAV::FORMAT_IMA_ADPCM: {
if (is_stereo) {
do_resample<int8_t, true, true>((int8_t *)data, dst_buff, offset, increment, target, ima_adpcm);
} else {
@@ -406,73 +406,73 @@ int AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, int
return p_frames;
}
-void AudioStreamPlaybackSample::tag_used_streams() {
+void AudioStreamPlaybackWAV::tag_used_streams() {
base->tag_used(get_playback_position());
}
-AudioStreamPlaybackSample::AudioStreamPlaybackSample() {}
+AudioStreamPlaybackWAV::AudioStreamPlaybackWAV() {}
/////////////////////
-void AudioStreamSample::set_format(Format p_format) {
+void AudioStreamWAV::set_format(Format p_format) {
format = p_format;
}
-AudioStreamSample::Format AudioStreamSample::get_format() const {
+AudioStreamWAV::Format AudioStreamWAV::get_format() const {
return format;
}
-void AudioStreamSample::set_loop_mode(LoopMode p_loop_mode) {
+void AudioStreamWAV::set_loop_mode(LoopMode p_loop_mode) {
loop_mode = p_loop_mode;
}
-AudioStreamSample::LoopMode AudioStreamSample::get_loop_mode() const {
+AudioStreamWAV::LoopMode AudioStreamWAV::get_loop_mode() const {
return loop_mode;
}
-void AudioStreamSample::set_loop_begin(int p_frame) {
+void AudioStreamWAV::set_loop_begin(int p_frame) {
loop_begin = p_frame;
}
-int AudioStreamSample::get_loop_begin() const {
+int AudioStreamWAV::get_loop_begin() const {
return loop_begin;
}
-void AudioStreamSample::set_loop_end(int p_frame) {
+void AudioStreamWAV::set_loop_end(int p_frame) {
loop_end = p_frame;
}
-int AudioStreamSample::get_loop_end() const {
+int AudioStreamWAV::get_loop_end() const {
return loop_end;
}
-void AudioStreamSample::set_mix_rate(int p_hz) {
+void AudioStreamWAV::set_mix_rate(int p_hz) {
ERR_FAIL_COND(p_hz == 0);
mix_rate = p_hz;
}
-int AudioStreamSample::get_mix_rate() const {
+int AudioStreamWAV::get_mix_rate() const {
return mix_rate;
}
-void AudioStreamSample::set_stereo(bool p_enable) {
+void AudioStreamWAV::set_stereo(bool p_enable) {
stereo = p_enable;
}
-bool AudioStreamSample::is_stereo() const {
+bool AudioStreamWAV::is_stereo() const {
return stereo;
}
-float AudioStreamSample::get_length() const {
+float AudioStreamWAV::get_length() const {
int len = data_bytes;
switch (format) {
- case AudioStreamSample::FORMAT_8_BITS:
+ case AudioStreamWAV::FORMAT_8_BITS:
len /= 1;
break;
- case AudioStreamSample::FORMAT_16_BITS:
+ case AudioStreamWAV::FORMAT_16_BITS:
len /= 2;
break;
- case AudioStreamSample::FORMAT_IMA_ADPCM:
+ case AudioStreamWAV::FORMAT_IMA_ADPCM:
len *= 2;
break;
}
@@ -484,11 +484,11 @@ float AudioStreamSample::get_length() const {
return float(len) / mix_rate;
}
-bool AudioStreamSample::is_monophonic() const {
+bool AudioStreamWAV::is_monophonic() const {
return false;
}
-void AudioStreamSample::set_data(const Vector<uint8_t> &p_data) {
+void AudioStreamWAV::set_data(const Vector<uint8_t> &p_data) {
AudioServer::get_singleton()->lock();
if (data) {
memfree(data);
@@ -510,7 +510,7 @@ void AudioStreamSample::set_data(const Vector<uint8_t> &p_data) {
AudioServer::get_singleton()->unlock();
}
-Vector<uint8_t> AudioStreamSample::get_data() const {
+Vector<uint8_t> AudioStreamWAV::get_data() const {
Vector<uint8_t> pv;
if (data) {
@@ -525,8 +525,8 @@ Vector<uint8_t> AudioStreamSample::get_data() const {
return pv;
}
-Error AudioStreamSample::save_to_wav(const String &p_path) {
- if (format == AudioStreamSample::FORMAT_IMA_ADPCM) {
+Error AudioStreamWAV::save_to_wav(const String &p_path) {
+ if (format == AudioStreamWAV::FORMAT_IMA_ADPCM) {
WARN_PRINT("Saving IMA_ADPC samples are not supported yet");
return ERR_UNAVAILABLE;
}
@@ -544,13 +544,13 @@ Error AudioStreamSample::save_to_wav(const String &p_path) {
int byte_pr_sample = 0;
switch (format) {
- case AudioStreamSample::FORMAT_8_BITS:
+ case AudioStreamWAV::FORMAT_8_BITS:
byte_pr_sample = 1;
break;
- case AudioStreamSample::FORMAT_16_BITS:
+ case AudioStreamWAV::FORMAT_16_BITS:
byte_pr_sample = 2;
break;
- case AudioStreamSample::FORMAT_IMA_ADPCM:
+ case AudioStreamWAV::FORMAT_IMA_ADPCM:
byte_pr_sample = 4;
break;
}
@@ -583,19 +583,19 @@ Error AudioStreamSample::save_to_wav(const String &p_path) {
Vector<uint8_t> data = get_data();
const uint8_t *read_data = data.ptr();
switch (format) {
- case AudioStreamSample::FORMAT_8_BITS:
+ case AudioStreamWAV::FORMAT_8_BITS:
for (unsigned int i = 0; i < data_bytes; i++) {
uint8_t data_point = (read_data[i] + 128);
file->store_8(data_point);
}
break;
- case AudioStreamSample::FORMAT_16_BITS:
+ case AudioStreamWAV::FORMAT_16_BITS:
for (unsigned int i = 0; i < data_bytes / 2; i++) {
uint16_t data_point = decode_uint16(&read_data[i * 2]);
file->store_16(data_point);
}
break;
- case AudioStreamSample::FORMAT_IMA_ADPCM:
+ case AudioStreamWAV::FORMAT_IMA_ADPCM:
//Unimplemented
break;
}
@@ -603,40 +603,40 @@ Error AudioStreamSample::save_to_wav(const String &p_path) {
return OK;
}
-Ref<AudioStreamPlayback> AudioStreamSample::instantiate_playback() {
- Ref<AudioStreamPlaybackSample> sample;
+Ref<AudioStreamPlayback> AudioStreamWAV::instantiate_playback() {
+ Ref<AudioStreamPlaybackWAV> sample;
sample.instantiate();
- sample->base = Ref<AudioStreamSample>(this);
+ sample->base = Ref<AudioStreamWAV>(this);
return sample;
}
-String AudioStreamSample::get_stream_name() const {
+String AudioStreamWAV::get_stream_name() const {
return "";
}
-void AudioStreamSample::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_data", "data"), &AudioStreamSample::set_data);
- ClassDB::bind_method(D_METHOD("get_data"), &AudioStreamSample::get_data);
+void AudioStreamWAV::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_data", "data"), &AudioStreamWAV::set_data);
+ ClassDB::bind_method(D_METHOD("get_data"), &AudioStreamWAV::get_data);
- ClassDB::bind_method(D_METHOD("set_format", "format"), &AudioStreamSample::set_format);
- ClassDB::bind_method(D_METHOD("get_format"), &AudioStreamSample::get_format);
+ ClassDB::bind_method(D_METHOD("set_format", "format"), &AudioStreamWAV::set_format);
+ ClassDB::bind_method(D_METHOD("get_format"), &AudioStreamWAV::get_format);
- ClassDB::bind_method(D_METHOD("set_loop_mode", "loop_mode"), &AudioStreamSample::set_loop_mode);
- ClassDB::bind_method(D_METHOD("get_loop_mode"), &AudioStreamSample::get_loop_mode);
+ ClassDB::bind_method(D_METHOD("set_loop_mode", "loop_mode"), &AudioStreamWAV::set_loop_mode);
+ ClassDB::bind_method(D_METHOD("get_loop_mode"), &AudioStreamWAV::get_loop_mode);
- ClassDB::bind_method(D_METHOD("set_loop_begin", "loop_begin"), &AudioStreamSample::set_loop_begin);
- ClassDB::bind_method(D_METHOD("get_loop_begin"), &AudioStreamSample::get_loop_begin);
+ ClassDB::bind_method(D_METHOD("set_loop_begin", "loop_begin"), &AudioStreamWAV::set_loop_begin);
+ ClassDB::bind_method(D_METHOD("get_loop_begin"), &AudioStreamWAV::get_loop_begin);
- ClassDB::bind_method(D_METHOD("set_loop_end", "loop_end"), &AudioStreamSample::set_loop_end);
- ClassDB::bind_method(D_METHOD("get_loop_end"), &AudioStreamSample::get_loop_end);
+ ClassDB::bind_method(D_METHOD("set_loop_end", "loop_end"), &AudioStreamWAV::set_loop_end);
+ ClassDB::bind_method(D_METHOD("get_loop_end"), &AudioStreamWAV::get_loop_end);
- ClassDB::bind_method(D_METHOD("set_mix_rate", "mix_rate"), &AudioStreamSample::set_mix_rate);
- ClassDB::bind_method(D_METHOD("get_mix_rate"), &AudioStreamSample::get_mix_rate);
+ ClassDB::bind_method(D_METHOD("set_mix_rate", "mix_rate"), &AudioStreamWAV::set_mix_rate);
+ ClassDB::bind_method(D_METHOD("get_mix_rate"), &AudioStreamWAV::get_mix_rate);
- ClassDB::bind_method(D_METHOD("set_stereo", "stereo"), &AudioStreamSample::set_stereo);
- ClassDB::bind_method(D_METHOD("is_stereo"), &AudioStreamSample::is_stereo);
+ ClassDB::bind_method(D_METHOD("set_stereo", "stereo"), &AudioStreamWAV::set_stereo);
+ ClassDB::bind_method(D_METHOD("is_stereo"), &AudioStreamWAV::is_stereo);
- ClassDB::bind_method(D_METHOD("save_to_wav", "path"), &AudioStreamSample::save_to_wav);
+ ClassDB::bind_method(D_METHOD("save_to_wav", "path"), &AudioStreamWAV::save_to_wav);
ADD_PROPERTY(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_data", "get_data");
ADD_PROPERTY(PropertyInfo(Variant::INT, "format", PROPERTY_HINT_ENUM, "8-Bit,16-Bit,IMA-ADPCM"), "set_format", "get_format");
@@ -656,9 +656,9 @@ void AudioStreamSample::_bind_methods() {
BIND_ENUM_CONSTANT(LOOP_BACKWARD);
}
-AudioStreamSample::AudioStreamSample() {}
+AudioStreamWAV::AudioStreamWAV() {}
-AudioStreamSample::~AudioStreamSample() {
+AudioStreamWAV::~AudioStreamWAV() {
if (data) {
memfree(data);
data = nullptr;
diff --git a/scene/resources/audio_stream_sample.h b/scene/resources/audio_stream_wav.h
index 2e694cffe2..d800388d96 100644
--- a/scene/resources/audio_stream_sample.h
+++ b/scene/resources/audio_stream_wav.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* audio_stream_sample.h */
+/* audio_stream_wav.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,15 +28,15 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef AUDIO_STREAM_SAMPLE_H
-#define AUDIO_STREAM_SAMPLE_H
+#ifndef AUDIO_STREAM_WAV_H
+#define AUDIO_STREAM_WAV_H
#include "servers/audio/audio_stream.h"
-class AudioStreamSample;
+class AudioStreamWAV;
-class AudioStreamPlaybackSample : public AudioStreamPlayback {
- GDCLASS(AudioStreamPlaybackSample, AudioStreamPlayback);
+class AudioStreamPlaybackWAV : public AudioStreamPlayback {
+ GDCLASS(AudioStreamPlaybackWAV, AudioStreamPlayback);
enum {
MIX_FRAC_BITS = 13,
MIX_FRAC_LEN = (1 << MIX_FRAC_BITS),
@@ -57,8 +57,8 @@ class AudioStreamPlaybackSample : public AudioStreamPlayback {
int64_t offset = 0;
int sign = 1;
bool active = false;
- friend class AudioStreamSample;
- Ref<AudioStreamSample> base;
+ friend class AudioStreamWAV;
+ Ref<AudioStreamWAV> base;
template <class Depth, bool is_stereo, bool is_ima_adpcm>
void do_resample(const Depth *p_src, AudioFrame *p_dst, int64_t &offset, int32_t &increment, uint32_t amount, IMA_ADPCM_State *ima_adpcm);
@@ -77,11 +77,11 @@ public:
virtual void tag_used_streams() override;
- AudioStreamPlaybackSample();
+ AudioStreamPlaybackWAV();
};
-class AudioStreamSample : public AudioStream {
- GDCLASS(AudioStreamSample, AudioStream);
+class AudioStreamWAV : public AudioStream {
+ GDCLASS(AudioStreamWAV, AudioStream);
RES_BASE_EXTENSION("sample")
public:
@@ -100,7 +100,7 @@ public:
};
private:
- friend class AudioStreamPlaybackSample;
+ friend class AudioStreamPlaybackWAV;
enum {
DATA_PAD = 16 //padding for interpolation
@@ -149,11 +149,11 @@ public:
virtual Ref<AudioStreamPlayback> instantiate_playback() override;
virtual String get_stream_name() const override;
- AudioStreamSample();
- ~AudioStreamSample();
+ AudioStreamWAV();
+ ~AudioStreamWAV();
};
-VARIANT_ENUM_CAST(AudioStreamSample::Format)
-VARIANT_ENUM_CAST(AudioStreamSample::LoopMode)
+VARIANT_ENUM_CAST(AudioStreamWAV::Format)
+VARIANT_ENUM_CAST(AudioStreamWAV::LoopMode)
-#endif // AUDIO_STREAM_SAMPLE_H
+#endif // AUDIO_STREAM_WAV_H
diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp
index 3e7b0a2808..ec9db89794 100644
--- a/scene/resources/mesh.cpp
+++ b/scene/resources/mesh.cpp
@@ -260,6 +260,64 @@ Ref<TriangleMesh> Mesh::generate_triangle_mesh() const {
return triangle_mesh;
}
+Ref<TriangleMesh> Mesh::generate_surface_triangle_mesh(int p_surface) const {
+ ERR_FAIL_INDEX_V(p_surface, get_surface_count(), Ref<TriangleMesh>());
+
+ if (surface_triangle_meshes.size() != get_surface_count()) {
+ surface_triangle_meshes.resize(get_surface_count());
+ }
+
+ if (surface_triangle_meshes[p_surface].is_valid()) {
+ return surface_triangle_meshes[p_surface];
+ }
+
+ int facecount = 0;
+
+ if (surface_get_primitive_type(p_surface) != PRIMITIVE_TRIANGLES) {
+ return Ref<TriangleMesh>();
+ }
+
+ if (surface_get_format(p_surface) & ARRAY_FORMAT_INDEX) {
+ facecount += surface_get_array_index_len(p_surface);
+ } else {
+ facecount += surface_get_array_len(p_surface);
+ }
+
+ Vector<Vector3> faces;
+ faces.resize(facecount);
+ Vector3 *facesw = faces.ptrw();
+
+ Array a = surface_get_arrays(p_surface);
+ ERR_FAIL_COND_V(a.is_empty(), Ref<TriangleMesh>());
+
+ int vc = surface_get_array_len(p_surface);
+ Vector<Vector3> vertices = a[ARRAY_VERTEX];
+ const Vector3 *vr = vertices.ptr();
+ int widx = 0;
+
+ if (surface_get_format(p_surface) & ARRAY_FORMAT_INDEX) {
+ int ic = surface_get_array_index_len(p_surface);
+ Vector<int> indices = a[ARRAY_INDEX];
+ const int *ir = indices.ptr();
+
+ for (int j = 0; j < ic; j++) {
+ int index = ir[j];
+ facesw[widx++] = vr[index];
+ }
+
+ } else {
+ for (int j = 0; j < vc; j++) {
+ facesw[widx++] = vr[j];
+ }
+ }
+
+ Ref<TriangleMesh> triangle_mesh = Ref<TriangleMesh>(memnew(TriangleMesh));
+ triangle_mesh->create(faces);
+ surface_triangle_meshes.set(p_surface, triangle_mesh);
+
+ return triangle_mesh;
+}
+
void Mesh::generate_debug_mesh_lines(Vector<Vector3> &r_lines) {
if (debug_lines.size() > 0) {
r_lines = debug_lines;
@@ -320,6 +378,14 @@ Vector<Face3> Mesh::get_faces() const {
return Vector<Face3>();
}
+Vector<Face3> Mesh::get_surface_faces(int p_surface) const {
+ Ref<TriangleMesh> tm = generate_surface_triangle_mesh(p_surface);
+ if (tm.is_valid()) {
+ return tm->get_faces();
+ }
+ return Vector<Face3>();
+}
+
Ref<Shape3D> Mesh::create_convex_shape(bool p_clean, bool p_simplify) const {
if (p_simplify) {
ConvexDecompositionSettings settings;
diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h
index 0f3fae4179..142373ce7f 100644
--- a/scene/resources/mesh.h
+++ b/scene/resources/mesh.h
@@ -42,6 +42,7 @@ class Mesh : public Resource {
GDCLASS(Mesh, Resource);
mutable Ref<TriangleMesh> triangle_mesh; //cached
+ mutable Vector<Ref<TriangleMesh>> surface_triangle_meshes; //cached
mutable Vector<Vector3> debug_lines;
Size2i lightmap_size_hint;
@@ -161,7 +162,9 @@ public:
virtual AABB get_aabb() const;
Vector<Face3> get_faces() const;
+ Vector<Face3> get_surface_faces(int p_surface) const;
Ref<TriangleMesh> generate_triangle_mesh() const;
+ Ref<TriangleMesh> generate_surface_triangle_mesh(int p_surface) const;
void generate_debug_mesh_lines(Vector<Vector3> &r_lines);
void generate_debug_mesh_indices(Vector<Vector3> &r_points);
diff --git a/scene/resources/separation_ray_shape_2d.cpp b/scene/resources/separation_ray_shape_2d.cpp
index 0d6aee47d8..fea41061fd 100644
--- a/scene/resources/separation_ray_shape_2d.cpp
+++ b/scene/resources/separation_ray_shape_2d.cpp
@@ -57,7 +57,7 @@ void SeparationRayShape2D::draw(const RID &p_to_rid, const Color &p_color) {
Transform2D xf;
xf.rotate(target_position.angle());
- xf.translate(Vector2(no_line ? 0 : target_position.length() - arrow_size, 0));
+ xf.translate_local(Vector2(no_line ? 0 : target_position.length() - arrow_size, 0));
Vector<Vector2> pts = {
xf.xform(Vector2(arrow_size, 0)),
diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp
index 3cf643221b..5e0627a7d9 100644
--- a/scene/resources/visual_shader.cpp
+++ b/scene/resources/visual_shader.cpp
@@ -3751,7 +3751,7 @@ String VisualShaderNodeUniform::get_warning(Shader::Mode p_mode, VisualShader::T
}
return vformat(RTR("This uniform type does not support the '%s' qualifier."), qualifier_str);
} else if (qualifier == Qualifier::QUAL_GLOBAL) {
- RS::GlobalVariableType gvt = RS::get_singleton()->global_variable_get_type(uniform_name);
+ RS::GlobalShaderUniformType gvt = RS::get_singleton()->global_shader_uniform_get_type(uniform_name);
if (gvt == RS::GLOBAL_VAR_TYPE_MAX) {
return vformat(RTR("Global uniform '%s' does not exist.\nCreate it in the Project Settings."), uniform_name);
}
diff --git a/servers/audio/effects/audio_effect_record.cpp b/servers/audio/effects/audio_effect_record.cpp
index a6553e1431..fff6dbc32a 100644
--- a/servers/audio/effects/audio_effect_record.cpp
+++ b/servers/audio/effects/audio_effect_record.cpp
@@ -199,16 +199,16 @@ bool AudioEffectRecord::is_recording_active() const {
return recording_active;
}
-void AudioEffectRecord::set_format(AudioStreamSample::Format p_format) {
+void AudioEffectRecord::set_format(AudioStreamWAV::Format p_format) {
format = p_format;
}
-AudioStreamSample::Format AudioEffectRecord::get_format() const {
+AudioStreamWAV::Format AudioEffectRecord::get_format() const {
return format;
}
-Ref<AudioStreamSample> AudioEffectRecord::get_recording() const {
- AudioStreamSample::Format dst_format = format;
+Ref<AudioStreamWAV> AudioEffectRecord::get_recording() const {
+ AudioStreamWAV::Format dst_format = format;
bool stereo = true; //forcing mono is not implemented
Vector<uint8_t> dst_data;
@@ -216,7 +216,7 @@ Ref<AudioStreamSample> AudioEffectRecord::get_recording() const {
ERR_FAIL_COND_V(current_instance.is_null(), nullptr);
ERR_FAIL_COND_V(current_instance->recording_data.size() == 0, nullptr);
- if (dst_format == AudioStreamSample::FORMAT_8_BITS) {
+ if (dst_format == AudioStreamWAV::FORMAT_8_BITS) {
int data_size = current_instance->recording_data.size();
dst_data.resize(data_size);
uint8_t *w = dst_data.ptrw();
@@ -225,7 +225,7 @@ Ref<AudioStreamSample> AudioEffectRecord::get_recording() const {
int8_t v = CLAMP(current_instance->recording_data[i] * 128, -128, 127);
w[i] = v;
}
- } else if (dst_format == AudioStreamSample::FORMAT_16_BITS) {
+ } else if (dst_format == AudioStreamWAV::FORMAT_16_BITS) {
int data_size = current_instance->recording_data.size();
dst_data.resize(data_size * 2);
uint8_t *w = dst_data.ptrw();
@@ -234,7 +234,7 @@ Ref<AudioStreamSample> AudioEffectRecord::get_recording() const {
int16_t v = CLAMP(current_instance->recording_data[i] * 32768, -32768, 32767);
encode_uint16(v, &w[i * 2]);
}
- } else if (dst_format == AudioStreamSample::FORMAT_IMA_ADPCM) {
+ } else if (dst_format == AudioStreamWAV::FORMAT_IMA_ADPCM) {
//byte interleave
Vector<float> left;
Vector<float> right;
@@ -273,12 +273,12 @@ Ref<AudioStreamSample> AudioEffectRecord::get_recording() const {
ERR_PRINT("Format not implemented.");
}
- Ref<AudioStreamSample> sample;
+ Ref<AudioStreamWAV> sample;
sample.instantiate();
sample->set_data(dst_data);
sample->set_format(dst_format);
sample->set_mix_rate(AudioServer::get_singleton()->get_mix_rate());
- sample->set_loop_mode(AudioStreamSample::LOOP_DISABLED);
+ sample->set_loop_mode(AudioStreamWAV::LOOP_DISABLED);
sample->set_loop_begin(0);
sample->set_loop_end(0);
sample->set_stereo(stereo);
@@ -297,6 +297,6 @@ void AudioEffectRecord::_bind_methods() {
}
AudioEffectRecord::AudioEffectRecord() {
- format = AudioStreamSample::FORMAT_16_BITS;
+ format = AudioStreamWAV::FORMAT_16_BITS;
recording_active = false;
}
diff --git a/servers/audio/effects/audio_effect_record.h b/servers/audio/effects/audio_effect_record.h
index b23b63dbd8..e89d8adbde 100644
--- a/servers/audio/effects/audio_effect_record.h
+++ b/servers/audio/effects/audio_effect_record.h
@@ -35,7 +35,7 @@
#include "core/io/marshalls.h"
#include "core/os/os.h"
#include "core/os/thread.h"
-#include "scene/resources/audio_stream_sample.h"
+#include "scene/resources/audio_stream_wav.h"
#include "servers/audio/audio_effect.h"
#include "servers/audio_server.h"
@@ -85,7 +85,7 @@ class AudioEffectRecord : public AudioEffect {
bool recording_active;
Ref<AudioEffectRecordInstance> current_instance;
- AudioStreamSample::Format format;
+ AudioStreamWAV::Format format;
void ensure_thread_stopped();
@@ -96,9 +96,9 @@ public:
Ref<AudioEffectInstance> instantiate() override;
void set_recording_active(bool p_record);
bool is_recording_active() const;
- void set_format(AudioStreamSample::Format p_format);
- AudioStreamSample::Format get_format() const;
- Ref<AudioStreamSample> get_recording() const;
+ void set_format(AudioStreamWAV::Format p_format);
+ AudioStreamWAV::Format get_format() const;
+ Ref<AudioStreamWAV> get_recording() const;
AudioEffectRecord();
};
diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp
index 1054073377..9052f8e05e 100644
--- a/servers/audio_server.cpp
+++ b/servers/audio_server.cpp
@@ -39,7 +39,7 @@
#include "core/os/os.h"
#include "core/string/string_name.h"
#include "core/templates/pair.h"
-#include "scene/resources/audio_stream_sample.h"
+#include "scene/resources/audio_stream_wav.h"
#include "servers/audio/audio_driver_dummy.h"
#include "servers/audio/effects/audio_effect_compressor.h"
diff --git a/servers/audio_server.h b/servers/audio_server.h
index 287a18ecde..5613267909 100644
--- a/servers/audio_server.h
+++ b/servers/audio_server.h
@@ -43,7 +43,7 @@
class AudioDriverDummy;
class AudioStream;
-class AudioStreamSample;
+class AudioStreamWAV;
class AudioStreamPlayback;
class AudioDriver {
diff --git a/servers/rendering/dummy/rasterizer_scene_dummy.h b/servers/rendering/dummy/rasterizer_scene_dummy.h
index 0fb0ab22a6..be98770b90 100644
--- a/servers/rendering/dummy/rasterizer_scene_dummy.h
+++ b/servers/rendering/dummy/rasterizer_scene_dummy.h
@@ -144,7 +144,7 @@ public:
void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) override {}
RID render_buffers_create() override { return RID(); }
- void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override {}
+ void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override {}
void gi_set_use_half_resolution(bool p_enable) override {}
void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_curve) override {}
diff --git a/servers/rendering/dummy/storage/material_storage.h b/servers/rendering/dummy/storage/material_storage.h
index 6721284b23..55c42330cf 100644
--- a/servers/rendering/dummy/storage/material_storage.h
+++ b/servers/rendering/dummy/storage/material_storage.h
@@ -38,23 +38,23 @@ namespace RendererDummy {
class MaterialStorage : public RendererMaterialStorage {
public:
- /* GLOBAL VARIABLE API */
+ /* GLOBAL SHADER UNIFORM API */
- virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) override {}
- virtual void global_variable_remove(const StringName &p_name) override {}
- virtual Vector<StringName> global_variable_get_list() const override { return Vector<StringName>(); }
+ virtual void global_shader_uniform_add(const StringName &p_name, RS::GlobalShaderUniformType p_type, const Variant &p_value) override {}
+ virtual void global_shader_uniform_remove(const StringName &p_name) override {}
+ virtual Vector<StringName> global_shader_uniform_get_list() const override { return Vector<StringName>(); }
- virtual void global_variable_set(const StringName &p_name, const Variant &p_value) override {}
- virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value) override {}
- virtual Variant global_variable_get(const StringName &p_name) const override { return Variant(); }
- virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const override { return RS::GLOBAL_VAR_TYPE_MAX; }
+ virtual void global_shader_uniform_set(const StringName &p_name, const Variant &p_value) override {}
+ virtual void global_shader_uniform_set_override(const StringName &p_name, const Variant &p_value) override {}
+ virtual Variant global_shader_uniform_get(const StringName &p_name) const override { return Variant(); }
+ virtual RS::GlobalShaderUniformType global_shader_uniform_get_type(const StringName &p_name) const override { return RS::GLOBAL_VAR_TYPE_MAX; }
- virtual void global_variables_load_settings(bool p_load_textures = true) override {}
- virtual void global_variables_clear() override {}
+ virtual void global_shader_uniforms_load_settings(bool p_load_textures = true) override {}
+ virtual void global_shader_uniforms_clear() override {}
- virtual int32_t global_variables_instance_allocate(RID p_instance) override { return 0; }
- virtual void global_variables_instance_free(RID p_instance) override {}
- virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) override {}
+ virtual int32_t global_shader_uniforms_instance_allocate(RID p_instance) override { return 0; }
+ virtual void global_shader_uniforms_instance_free(RID p_instance) override {}
+ virtual void global_shader_uniforms_instance_update(RID p_instance, int p_index, const Variant &p_value) override {}
/* SHADER API */
diff --git a/servers/rendering/renderer_compositor.cpp b/servers/rendering/renderer_compositor.cpp
index b331ec2c1d..80e71a0df3 100644
--- a/servers/rendering/renderer_compositor.cpp
+++ b/servers/rendering/renderer_compositor.cpp
@@ -33,6 +33,7 @@
#include "core/config/project_settings.h"
#include "core/os/os.h"
#include "core/string/print_string.h"
+#include "servers/xr_server.h"
RendererCompositor *(*RendererCompositor::_create_func)() = nullptr;
bool RendererCompositor::low_end = false;
@@ -46,7 +47,11 @@ bool RendererCompositor::is_xr_enabled() const {
}
RendererCompositor::RendererCompositor() {
- xr_enabled = GLOBAL_GET("xr/shaders/enabled");
+ if (XRServer::get_xr_mode() == XRServer::XRMODE_DEFAULT) {
+ xr_enabled = GLOBAL_GET("xr/shaders/enabled");
+ } else {
+ xr_enabled = XRServer::get_xr_mode() == XRServer::XRMODE_ON;
+ }
}
RendererCanvasRender *RendererCanvasRender::singleton = nullptr;
diff --git a/servers/rendering/renderer_rd/environment/fog.cpp b/servers/rendering/renderer_rd/environment/fog.cpp
index b99ac7e5d6..fba04c0db4 100644
--- a/servers/rendering/renderer_rd/environment/fog.cpp
+++ b/servers/rendering/renderer_rd/environment/fog.cpp
@@ -276,7 +276,7 @@ ALBEDO = vec3(1.0);
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 2;
- u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer());
+ u.append_id(RendererRD::MaterialStorage::get_singleton()->global_shader_uniforms_get_storage_buffer());
uniforms.push_back(u);
}
diff --git a/servers/rendering/renderer_rd/environment/sky.cpp b/servers/rendering/renderer_rd/environment/sky.cpp
index 112126aa1f..228d2673f2 100644
--- a/servers/rendering/renderer_rd/environment/sky.cpp
+++ b/servers/rendering/renderer_rd/environment/sky.cpp
@@ -912,7 +912,7 @@ void SkyRD::init() {
actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
actions.default_repeat = ShaderLanguage::REPEAT_ENABLE;
- actions.global_buffer_array_variable = "global_variables.data";
+ actions.global_buffer_array_variable = "global_shader_uniforms.data";
sky_shader.compiler.initialize(actions);
}
@@ -970,7 +970,7 @@ void sky() {
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 1;
- u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer());
+ u.append_id(RendererRD::MaterialStorage::get_singleton()->global_shader_uniforms_get_storage_buffer());
uniforms.push_back(u);
}
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
index 7f290cc5e4..6f200220f0 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
@@ -2381,7 +2381,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 14;
- u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer());
+ u.append_id(RendererRD::MaterialStorage::get_singleton()->global_shader_uniforms_get_storage_buffer());
uniforms.push_back(u);
}
diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
index 6f4a7f6a84..c84a4469ae 100644
--- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
@@ -788,7 +788,7 @@ void SceneShaderForwardClustered::init(const String p_defines) {
actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
actions.default_repeat = ShaderLanguage::REPEAT_ENABLE;
- actions.global_buffer_array_variable = "global_variables.data";
+ actions.global_buffer_array_variable = "global_shader_uniforms.data";
actions.instance_uniform_index_variable = "instances.data[instance_index_interp].instance_uniforms_ofs";
compiler.initialize(actions);
diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
index e0fa116222..a179688487 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
@@ -1330,7 +1330,7 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 14;
- u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer());
+ u.append_id(RendererRD::MaterialStorage::get_singleton()->global_shader_uniforms_get_storage_buffer());
uniforms.push_back(u);
}
diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
index ba8ee62b3f..c6eac298e7 100644
--- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
@@ -685,7 +685,7 @@ void SceneShaderForwardMobile::init(const String p_defines) {
actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
actions.default_repeat = ShaderLanguage::REPEAT_ENABLE;
- actions.global_buffer_array_variable = "global_variables.data";
+ actions.global_buffer_array_variable = "global_shader_uniforms.data";
actions.instance_uniform_index_variable = "draw_call.instance_uniforms_ofs";
actions.apply_luminance_multiplier = true; // apply luminance multiplier to screen texture
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
index a58cdd5066..0b59ca6931 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
@@ -1031,7 +1031,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 9;
- u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer());
+ u.append_id(RendererRD::MaterialStorage::get_singleton()->global_shader_uniforms_get_storage_buffer());
uniforms.push_back(u);
}
@@ -1304,7 +1304,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
Size2i ssize = texture_storage->render_target_get_size(p_to_render_target);
Transform3D screen_transform;
- screen_transform.translate(-(ssize.width / 2.0f), -(ssize.height / 2.0f), 0.0f);
+ screen_transform.translate_local(-(ssize.width / 2.0f), -(ssize.height / 2.0f), 0.0f);
screen_transform.scale(Vector3(2.0f / ssize.width, 2.0f / ssize.height, 1.0f));
_update_transform_to_mat4(screen_transform, state_buffer.screen_transform);
_update_transform_2d_to_mat4(p_canvas_transform, state_buffer.canvas_transform);
@@ -2469,7 +2469,7 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() {
actions.default_repeat = ShaderLanguage::REPEAT_DISABLE;
actions.base_varying_index = 4;
- actions.global_buffer_array_variable = "global_variables.data";
+ actions.global_buffer_array_variable = "global_shader_uniforms.data";
shader.compiler.initialize(actions);
}
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index fb68173c93..cf231fa4ef 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -2448,7 +2448,7 @@ bool RendererSceneRenderRD::_render_buffers_can_be_storage() {
return true;
}
-void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) {
+void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
@@ -2459,11 +2459,9 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
p_internal_width = p_width;
}
- if (p_width != p_internal_width) {
- float fsr_mipmap_bias = -log2f(p_width / p_internal_width) + p_fsr_mipmap_bias;
- material_storage->sampler_rd_configure_custom(fsr_mipmap_bias);
- update_uniform_sets();
- }
+ const float texture_mipmap_bias = -log2f(p_width / p_internal_width) + p_texture_mipmap_bias;
+ material_storage->sampler_rd_configure_custom(texture_mipmap_bias);
+ update_uniform_sets();
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
index 9dc3909246..09ec2a9efd 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
@@ -1105,7 +1105,7 @@ public:
virtual RD::DataFormat _render_buffers_get_color_format();
virtual bool _render_buffers_can_be_storage();
virtual RID render_buffers_create() override;
- virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override;
+ virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override;
virtual void gi_set_use_half_resolution(bool p_enable) override;
RID render_buffers_get_depth_texture(RID p_render_buffers);
diff --git a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl
index 12f57b0178..2ea6965c09 100644
--- a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl
@@ -138,10 +138,10 @@ layout(set = 0, binding = 7) uniform texture2D sdf_texture;
layout(set = 0, binding = 8) uniform sampler material_samplers[12];
-layout(set = 0, binding = 9, std430) restrict readonly buffer GlobalVariableData {
+layout(set = 0, binding = 9, std430) restrict readonly buffer GlobalShaderUniformData {
vec4 data[];
}
-global_variables;
+global_shader_uniforms;
/* SET1: Is reserved for the material */
diff --git a/servers/rendering/renderer_rd/shaders/environment/sky.glsl b/servers/rendering/renderer_rd/shaders/environment/sky.glsl
index 5b4594da99..e825020a4e 100644
--- a/servers/rendering/renderer_rd/shaders/environment/sky.glsl
+++ b/servers/rendering/renderer_rd/shaders/environment/sky.glsl
@@ -77,10 +77,10 @@ params;
layout(set = 0, binding = 0) uniform sampler material_samplers[12];
-layout(set = 0, binding = 1, std430) restrict readonly buffer GlobalVariableData {
+layout(set = 0, binding = 1, std430) restrict readonly buffer GlobalShaderUniformData {
vec4 data[];
}
-global_variables;
+global_shader_uniforms;
layout(set = 0, binding = 2, std140) uniform SceneData {
bool volumetric_fog_enabled;
diff --git a/servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl
index fb3c725b1f..4658afd02d 100644
--- a/servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl
+++ b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl
@@ -28,10 +28,10 @@ layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in;
layout(set = 0, binding = 1) uniform sampler material_samplers[12];
-layout(set = 0, binding = 2, std430) restrict readonly buffer GlobalVariableData {
+layout(set = 0, binding = 2, std430) restrict readonly buffer GlobalShaderUniformData {
vec4 data[];
}
-global_variables;
+global_shader_uniforms;
layout(push_constant, std430) uniform Params {
vec3 position;
diff --git a/servers/rendering/renderer_rd/shaders/particles.glsl b/servers/rendering/renderer_rd/shaders/particles.glsl
index acb62b812e..4369bddc83 100644
--- a/servers/rendering/renderer_rd/shaders/particles.glsl
+++ b/servers/rendering/renderer_rd/shaders/particles.glsl
@@ -25,10 +25,10 @@ layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
layout(set = 0, binding = 1) uniform sampler material_samplers[12];
-layout(set = 0, binding = 2, std430) restrict readonly buffer GlobalVariableData {
+layout(set = 0, binding = 2, std430) restrict readonly buffer GlobalShaderUniformData {
vec4 data[];
}
-global_variables;
+global_shader_uniforms;
/* Set 1: FRAME AND PARTICLE DATA */
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl
index 0c23de96c3..f0717294ef 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl
@@ -129,10 +129,10 @@ layout(set = 0, binding = 13, std430) restrict readonly buffer Decals {
}
decals;
-layout(set = 0, binding = 14, std430) restrict readonly buffer GlobalVariableData {
+layout(set = 0, binding = 14, std430) restrict readonly buffer GlobalShaderUniformData {
vec4 data[];
}
-global_variables;
+global_shader_uniforms;
struct SDFVoxelGICascadeData {
vec3 position;
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl
index 7413d8730a..98ad674ce0 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl
@@ -118,10 +118,10 @@ layout(set = 0, binding = 13, std430) restrict readonly buffer Decals {
}
decals;
-layout(set = 0, binding = 14, std430) restrict readonly buffer GlobalVariableData {
+layout(set = 0, binding = 14, std430) restrict readonly buffer GlobalShaderUniformData {
highp vec4 data[];
}
-global_variables;
+global_shader_uniforms;
/* Set 1: Render Pass (changes per render pass) */
diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
index 23d05de942..0bac26213b 100644
--- a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
@@ -967,7 +967,7 @@ void MaterialData::update_uniform_buffer(const HashMap<StringName, ShaderLanguag
if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) {
//this is a global variable, get the index to it
- GlobalVariables::Variable *gv = material_storage->global_variables.variables.getptr(E.key);
+ GlobalShaderUniforms::Variable *gv = material_storage->global_shader_uniforms.variables.getptr(E.key);
uint32_t index = 0;
if (gv) {
index = gv->buffer_index;
@@ -1023,9 +1023,9 @@ void MaterialData::update_uniform_buffer(const HashMap<StringName, ShaderLanguag
if (uses_global_buffer != (global_buffer_E != nullptr)) {
if (uses_global_buffer) {
- global_buffer_E = material_storage->global_variables.materials_using_buffer.push_back(self);
+ global_buffer_E = material_storage->global_shader_uniforms.materials_using_buffer.push_back(self);
} else {
- material_storage->global_variables.materials_using_buffer.erase(global_buffer_E);
+ material_storage->global_shader_uniforms.materials_using_buffer.erase(global_buffer_E);
global_buffer_E = nullptr;
}
}
@@ -1036,20 +1036,20 @@ MaterialData::~MaterialData() {
if (global_buffer_E) {
//unregister global buffers
- material_storage->global_variables.materials_using_buffer.erase(global_buffer_E);
+ material_storage->global_shader_uniforms.materials_using_buffer.erase(global_buffer_E);
}
if (global_texture_E) {
//unregister global textures
for (const KeyValue<StringName, uint64_t> &E : used_global_textures) {
- GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(E.key);
+ GlobalShaderUniforms::Variable *v = material_storage->global_shader_uniforms.variables.getptr(E.key);
if (v) {
v->texture_materials.erase(self);
}
}
//unregister material from those using global textures
- material_storage->global_variables.materials_using_texture.erase(global_texture_E);
+ material_storage->global_shader_uniforms.materials_using_texture.erase(global_texture_E);
}
if (uniform_buffer.is_valid()) {
@@ -1079,7 +1079,7 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet
if (p_texture_uniforms[i].global) {
uses_global_textures = true;
- GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(uniform_name);
+ GlobalShaderUniforms::Variable *v = material_storage->global_shader_uniforms.variables.getptr(uniform_name);
if (v) {
if (v->buffer_index >= 0) {
WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it changed type and is no longer a texture!.");
@@ -1249,7 +1249,7 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet
if (E.value != global_textures_pass) {
to_delete.push_back(E.key);
- GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(E.key);
+ GlobalShaderUniforms::Variable *v = material_storage->global_shader_uniforms.variables.getptr(E.key);
if (v) {
v->texture_materials.erase(self);
}
@@ -1263,9 +1263,9 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet
//handle registering/unregistering global textures
if (uses_global_textures != (global_texture_E != nullptr)) {
if (uses_global_textures) {
- global_texture_E = material_storage->global_variables.materials_using_texture.push_back(self);
+ global_texture_E = material_storage->global_shader_uniforms.materials_using_texture.push_back(self);
} else {
- material_storage->global_variables.materials_using_texture.erase(global_texture_E);
+ material_storage->global_shader_uniforms.materials_using_texture.erase(global_texture_E);
global_texture_E = nullptr;
}
}
@@ -1497,22 +1497,22 @@ MaterialStorage::MaterialStorage() {
shader_data_request_func[i] = nullptr;
}
- static_assert(sizeof(GlobalVariables::Value) == 16);
+ static_assert(sizeof(GlobalShaderUniforms::Value) == 16);
- global_variables.buffer_size = MAX(4096, (int)GLOBAL_GET("rendering/limits/global_shader_variables/buffer_size"));
- global_variables.buffer_values = memnew_arr(GlobalVariables::Value, global_variables.buffer_size);
- memset(global_variables.buffer_values, 0, sizeof(GlobalVariables::Value) * global_variables.buffer_size);
- global_variables.buffer_usage = memnew_arr(GlobalVariables::ValueUsage, global_variables.buffer_size);
- global_variables.buffer_dirty_regions = memnew_arr(bool, global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE);
- memset(global_variables.buffer_dirty_regions, 0, sizeof(bool) * global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE);
- global_variables.buffer = RD::get_singleton()->storage_buffer_create(sizeof(GlobalVariables::Value) * global_variables.buffer_size);
+ global_shader_uniforms.buffer_size = MAX(4096, (int)GLOBAL_GET("rendering/limits/global_shader_variables/buffer_size"));
+ global_shader_uniforms.buffer_values = memnew_arr(GlobalShaderUniforms::Value, global_shader_uniforms.buffer_size);
+ memset(global_shader_uniforms.buffer_values, 0, sizeof(GlobalShaderUniforms::Value) * global_shader_uniforms.buffer_size);
+ global_shader_uniforms.buffer_usage = memnew_arr(GlobalShaderUniforms::ValueUsage, global_shader_uniforms.buffer_size);
+ global_shader_uniforms.buffer_dirty_regions = memnew_arr(bool, global_shader_uniforms.buffer_size / GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE);
+ memset(global_shader_uniforms.buffer_dirty_regions, 0, sizeof(bool) * global_shader_uniforms.buffer_size / GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE);
+ global_shader_uniforms.buffer = RD::get_singleton()->storage_buffer_create(sizeof(GlobalShaderUniforms::Value) * global_shader_uniforms.buffer_size);
}
MaterialStorage::~MaterialStorage() {
- memdelete_arr(global_variables.buffer_values);
- memdelete_arr(global_variables.buffer_usage);
- memdelete_arr(global_variables.buffer_dirty_regions);
- RD::get_singleton()->free(global_variables.buffer);
+ memdelete_arr(global_shader_uniforms.buffer_values);
+ memdelete_arr(global_shader_uniforms.buffer_usage);
+ memdelete_arr(global_shader_uniforms.buffer_dirty_regions);
+ RD::get_singleton()->free(global_shader_uniforms.buffer);
// buffers
@@ -1633,17 +1633,17 @@ void MaterialStorage::sampler_rd_configure_custom(float p_mipmap_bias) {
}
}
-/* GLOBAL VARIABLE API */
+/* GLOBAL SHADER UNIFORM API */
-int32_t MaterialStorage::_global_variable_allocate(uint32_t p_elements) {
+int32_t MaterialStorage::_global_shader_uniform_allocate(uint32_t p_elements) {
int32_t idx = 0;
- while (idx + p_elements <= global_variables.buffer_size) {
- if (global_variables.buffer_usage[idx].elements == 0) {
+ while (idx + p_elements <= global_shader_uniforms.buffer_size) {
+ if (global_shader_uniforms.buffer_usage[idx].elements == 0) {
bool valid = true;
for (uint32_t i = 1; i < p_elements; i++) {
- if (global_variables.buffer_usage[idx + i].elements > 0) {
+ if (global_shader_uniforms.buffer_usage[idx + i].elements > 0) {
valid = false;
- idx += i + global_variables.buffer_usage[idx + i].elements;
+ idx += i + global_shader_uniforms.buffer_usage[idx + i].elements;
break;
}
}
@@ -1654,17 +1654,17 @@ int32_t MaterialStorage::_global_variable_allocate(uint32_t p_elements) {
return idx;
} else {
- idx += global_variables.buffer_usage[idx].elements;
+ idx += global_shader_uniforms.buffer_usage[idx].elements;
}
}
return -1;
}
-void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::GlobalVariableType p_type, const Variant &p_value) {
+void MaterialStorage::_global_shader_uniform_store_in_buffer(int32_t p_index, RS::GlobalShaderUniformType p_type, const Variant &p_value) {
switch (p_type) {
case RS::GLOBAL_VAR_TYPE_BOOL: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
bool b = p_value;
bv.x = b ? 1.0 : 0.0;
bv.y = 0.0;
@@ -1673,7 +1673,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
} break;
case RS::GLOBAL_VAR_TYPE_BVEC2: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
uint32_t bvec = p_value;
bv.x = (bvec & 1) ? 1.0 : 0.0;
bv.y = (bvec & 2) ? 1.0 : 0.0;
@@ -1681,7 +1681,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0.0;
} break;
case RS::GLOBAL_VAR_TYPE_BVEC3: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
uint32_t bvec = p_value;
bv.x = (bvec & 1) ? 1.0 : 0.0;
bv.y = (bvec & 2) ? 1.0 : 0.0;
@@ -1689,7 +1689,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0.0;
} break;
case RS::GLOBAL_VAR_TYPE_BVEC4: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
uint32_t bvec = p_value;
bv.x = (bvec & 1) ? 1.0 : 0.0;
bv.y = (bvec & 2) ? 1.0 : 0.0;
@@ -1697,7 +1697,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = (bvec & 8) ? 1.0 : 0.0;
} break;
case RS::GLOBAL_VAR_TYPE_INT: {
- GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index];
int32_t v = p_value;
bv.x = v;
bv.y = 0;
@@ -1705,7 +1705,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0;
} break;
case RS::GLOBAL_VAR_TYPE_IVEC2: {
- GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index];
Vector2i v = p_value;
bv.x = v.x;
bv.y = v.y;
@@ -1713,7 +1713,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0;
} break;
case RS::GLOBAL_VAR_TYPE_IVEC3: {
- GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index];
Vector3i v = p_value;
bv.x = v.x;
bv.y = v.y;
@@ -1721,7 +1721,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0;
} break;
case RS::GLOBAL_VAR_TYPE_IVEC4: {
- GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index];
Vector<int32_t> v = p_value;
bv.x = v.size() >= 1 ? v[0] : 0;
bv.y = v.size() >= 2 ? v[1] : 0;
@@ -1729,7 +1729,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = v.size() >= 4 ? v[3] : 0;
} break;
case RS::GLOBAL_VAR_TYPE_RECT2I: {
- GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index];
Rect2i v = p_value;
bv.x = v.position.x;
bv.y = v.position.y;
@@ -1737,7 +1737,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = v.size.y;
} break;
case RS::GLOBAL_VAR_TYPE_UINT: {
- GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::ValueUInt &bv = *(GlobalShaderUniforms::ValueUInt *)&global_shader_uniforms.buffer_values[p_index];
uint32_t v = p_value;
bv.x = v;
bv.y = 0;
@@ -1745,7 +1745,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0;
} break;
case RS::GLOBAL_VAR_TYPE_UVEC2: {
- GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::ValueUInt &bv = *(GlobalShaderUniforms::ValueUInt *)&global_shader_uniforms.buffer_values[p_index];
Vector2i v = p_value;
bv.x = v.x;
bv.y = v.y;
@@ -1753,7 +1753,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0;
} break;
case RS::GLOBAL_VAR_TYPE_UVEC3: {
- GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::ValueUInt &bv = *(GlobalShaderUniforms::ValueUInt *)&global_shader_uniforms.buffer_values[p_index];
Vector3i v = p_value;
bv.x = v.x;
bv.y = v.y;
@@ -1761,7 +1761,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0;
} break;
case RS::GLOBAL_VAR_TYPE_UVEC4: {
- GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::ValueUInt &bv = *(GlobalShaderUniforms::ValueUInt *)&global_shader_uniforms.buffer_values[p_index];
Vector<int32_t> v = p_value;
bv.x = v.size() >= 1 ? v[0] : 0;
bv.y = v.size() >= 2 ? v[1] : 0;
@@ -1769,7 +1769,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = v.size() >= 4 ? v[3] : 0;
} break;
case RS::GLOBAL_VAR_TYPE_FLOAT: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
float v = p_value;
bv.x = v;
bv.y = 0;
@@ -1777,7 +1777,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0;
} break;
case RS::GLOBAL_VAR_TYPE_VEC2: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
Vector2 v = p_value;
bv.x = v.x;
bv.y = v.y;
@@ -1785,7 +1785,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0;
} break;
case RS::GLOBAL_VAR_TYPE_VEC3: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
Vector3 v = p_value;
bv.x = v.x;
bv.y = v.y;
@@ -1793,7 +1793,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0;
} break;
case RS::GLOBAL_VAR_TYPE_VEC4: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
Plane v = p_value;
bv.x = v.normal.x;
bv.y = v.normal.y;
@@ -1801,14 +1801,14 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = v.d;
} break;
case RS::GLOBAL_VAR_TYPE_COLOR: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
Color v = p_value;
bv.x = v.r;
bv.y = v.g;
bv.z = v.b;
bv.w = v.a;
- GlobalVariables::Value &bv_linear = global_variables.buffer_values[p_index + 1];
+ GlobalShaderUniforms::Value &bv_linear = global_shader_uniforms.buffer_values[p_index + 1];
v = v.srgb_to_linear();
bv_linear.x = v.r;
bv_linear.y = v.g;
@@ -1817,7 +1817,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
} break;
case RS::GLOBAL_VAR_TYPE_RECT2: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
Rect2 v = p_value;
bv.x = v.position.x;
bv.y = v.position.y;
@@ -1825,7 +1825,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = v.size.y;
} break;
case RS::GLOBAL_VAR_TYPE_MAT2: {
- GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index];
Vector<float> m2 = p_value;
if (m2.size() < 4) {
m2.resize(4);
@@ -1842,7 +1842,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
} break;
case RS::GLOBAL_VAR_TYPE_MAT3: {
- GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index];
Basis v = p_value;
bv[0].x = v.rows[0][0];
bv[0].y = v.rows[1][0];
@@ -1861,7 +1861,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
} break;
case RS::GLOBAL_VAR_TYPE_MAT4: {
- GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index];
Vector<float> m2 = p_value;
if (m2.size() < 16) {
@@ -1890,7 +1890,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
} break;
case RS::GLOBAL_VAR_TYPE_TRANSFORM_2D: {
- GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index];
Transform2D v = p_value;
bv[0].x = v.columns[0][0];
bv[0].y = v.columns[0][1];
@@ -1909,7 +1909,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
} break;
case RS::GLOBAL_VAR_TYPE_TRANSFORM: {
- GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index];
Transform3D v = p_value;
bv[0].x = v.basis.rows[0][0];
bv[0].y = v.basis.rows[1][0];
@@ -1938,15 +1938,15 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
}
}
-void MaterialStorage::_global_variable_mark_buffer_dirty(int32_t p_index, int32_t p_elements) {
+void MaterialStorage::_global_shader_uniform_mark_buffer_dirty(int32_t p_index, int32_t p_elements) {
int32_t prev_chunk = -1;
for (int32_t i = 0; i < p_elements; i++) {
- int32_t chunk = (p_index + i) / GlobalVariables::BUFFER_DIRTY_REGION_SIZE;
+ int32_t chunk = (p_index + i) / GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE;
if (chunk != prev_chunk) {
- if (!global_variables.buffer_dirty_regions[chunk]) {
- global_variables.buffer_dirty_regions[chunk] = true;
- global_variables.buffer_dirty_region_count++;
+ if (!global_shader_uniforms.buffer_dirty_regions[chunk]) {
+ global_shader_uniforms.buffer_dirty_regions[chunk] = true;
+ global_shader_uniforms.buffer_dirty_region_count++;
}
}
@@ -1954,16 +1954,16 @@ void MaterialStorage::_global_variable_mark_buffer_dirty(int32_t p_index, int32_
}
}
-void MaterialStorage::global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) {
- ERR_FAIL_COND(global_variables.variables.has(p_name));
- GlobalVariables::Variable gv;
+void MaterialStorage::global_shader_uniform_add(const StringName &p_name, RS::GlobalShaderUniformType p_type, const Variant &p_value) {
+ ERR_FAIL_COND(global_shader_uniforms.variables.has(p_name));
+ GlobalShaderUniforms::Variable gv;
gv.type = p_type;
gv.value = p_value;
gv.buffer_index = -1;
if (p_type >= RS::GLOBAL_VAR_TYPE_SAMPLER2D) {
//is texture
- global_variables.must_update_texture_materials = true; //normally there are none
+ global_shader_uniforms.must_update_texture_materials = true; //normally there are none
} else {
gv.buffer_elements = 1;
if (p_type == RS::GLOBAL_VAR_TYPE_COLOR || p_type == RS::GLOBAL_VAR_TYPE_MAT2) {
@@ -1980,56 +1980,56 @@ void MaterialStorage::global_variable_add(const StringName &p_name, RS::GlobalVa
}
//is vector, allocate in buffer and update index
- gv.buffer_index = _global_variable_allocate(gv.buffer_elements);
+ gv.buffer_index = _global_shader_uniform_allocate(gv.buffer_elements);
ERR_FAIL_COND_MSG(gv.buffer_index < 0, vformat("Failed allocating global variable '%s' out of buffer memory. Consider increasing it in the Project Settings.", String(p_name)));
- global_variables.buffer_usage[gv.buffer_index].elements = gv.buffer_elements;
- _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value);
- _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
+ global_shader_uniforms.buffer_usage[gv.buffer_index].elements = gv.buffer_elements;
+ _global_shader_uniform_store_in_buffer(gv.buffer_index, gv.type, gv.value);
+ _global_shader_uniform_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
- global_variables.must_update_buffer_materials = true; //normally there are none
+ global_shader_uniforms.must_update_buffer_materials = true; //normally there are none
}
- global_variables.variables[p_name] = gv;
+ global_shader_uniforms.variables[p_name] = gv;
}
-void MaterialStorage::global_variable_remove(const StringName &p_name) {
- if (!global_variables.variables.has(p_name)) {
+void MaterialStorage::global_shader_uniform_remove(const StringName &p_name) {
+ if (!global_shader_uniforms.variables.has(p_name)) {
return;
}
- const GlobalVariables::Variable &gv = global_variables.variables[p_name];
+ const GlobalShaderUniforms::Variable &gv = global_shader_uniforms.variables[p_name];
if (gv.buffer_index >= 0) {
- global_variables.buffer_usage[gv.buffer_index].elements = 0;
- global_variables.must_update_buffer_materials = true;
+ global_shader_uniforms.buffer_usage[gv.buffer_index].elements = 0;
+ global_shader_uniforms.must_update_buffer_materials = true;
} else {
- global_variables.must_update_texture_materials = true;
+ global_shader_uniforms.must_update_texture_materials = true;
}
- global_variables.variables.erase(p_name);
+ global_shader_uniforms.variables.erase(p_name);
}
-Vector<StringName> MaterialStorage::global_variable_get_list() const {
+Vector<StringName> MaterialStorage::global_shader_uniform_get_list() const {
if (!Engine::get_singleton()->is_editor_hint()) {
ERR_FAIL_V_MSG(Vector<StringName>(), "This function should never be used outside the editor, it can severely damage performance.");
}
Vector<StringName> names;
- for (const KeyValue<StringName, GlobalVariables::Variable> &E : global_variables.variables) {
+ for (const KeyValue<StringName, GlobalShaderUniforms::Variable> &E : global_shader_uniforms.variables) {
names.push_back(E.key);
}
names.sort_custom<StringName::AlphCompare>();
return names;
}
-void MaterialStorage::global_variable_set(const StringName &p_name, const Variant &p_value) {
- ERR_FAIL_COND(!global_variables.variables.has(p_name));
- GlobalVariables::Variable &gv = global_variables.variables[p_name];
+void MaterialStorage::global_shader_uniform_set(const StringName &p_name, const Variant &p_value) {
+ ERR_FAIL_COND(!global_shader_uniforms.variables.has(p_name));
+ GlobalShaderUniforms::Variable &gv = global_shader_uniforms.variables[p_name];
gv.value = p_value;
if (gv.override.get_type() == Variant::NIL) {
if (gv.buffer_index >= 0) {
//buffer
- _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value);
- _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
+ _global_shader_uniform_store_in_buffer(gv.buffer_index, gv.type, gv.value);
+ _global_shader_uniform_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
} else {
//texture
MaterialStorage *material_storage = MaterialStorage::get_singleton();
@@ -2042,26 +2042,26 @@ void MaterialStorage::global_variable_set(const StringName &p_name, const Varian
}
}
-void MaterialStorage::global_variable_set_override(const StringName &p_name, const Variant &p_value) {
- if (!global_variables.variables.has(p_name)) {
+void MaterialStorage::global_shader_uniform_set_override(const StringName &p_name, const Variant &p_value) {
+ if (!global_shader_uniforms.variables.has(p_name)) {
return; //variable may not exist
}
ERR_FAIL_COND(p_value.get_type() == Variant::OBJECT);
- GlobalVariables::Variable &gv = global_variables.variables[p_name];
+ GlobalShaderUniforms::Variable &gv = global_shader_uniforms.variables[p_name];
gv.override = p_value;
if (gv.buffer_index >= 0) {
//buffer
if (gv.override.get_type() == Variant::NIL) {
- _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value);
+ _global_shader_uniform_store_in_buffer(gv.buffer_index, gv.type, gv.value);
} else {
- _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.override);
+ _global_shader_uniform_store_in_buffer(gv.buffer_index, gv.type, gv.override);
}
- _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
+ _global_shader_uniform_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
} else {
//texture
MaterialStorage *material_storage = MaterialStorage::get_singleton();
@@ -2073,35 +2073,35 @@ void MaterialStorage::global_variable_set_override(const StringName &p_name, con
}
}
-Variant MaterialStorage::global_variable_get(const StringName &p_name) const {
+Variant MaterialStorage::global_shader_uniform_get(const StringName &p_name) const {
if (!Engine::get_singleton()->is_editor_hint()) {
ERR_FAIL_V_MSG(Variant(), "This function should never be used outside the editor, it can severely damage performance.");
}
- if (!global_variables.variables.has(p_name)) {
+ if (!global_shader_uniforms.variables.has(p_name)) {
return Variant();
}
- return global_variables.variables[p_name].value;
+ return global_shader_uniforms.variables[p_name].value;
}
-RS::GlobalVariableType MaterialStorage::global_variable_get_type_internal(const StringName &p_name) const {
- if (!global_variables.variables.has(p_name)) {
+RS::GlobalShaderUniformType MaterialStorage::global_shader_uniform_get_type_internal(const StringName &p_name) const {
+ if (!global_shader_uniforms.variables.has(p_name)) {
return RS::GLOBAL_VAR_TYPE_MAX;
}
- return global_variables.variables[p_name].type;
+ return global_shader_uniforms.variables[p_name].type;
}
-RS::GlobalVariableType MaterialStorage::global_variable_get_type(const StringName &p_name) const {
+RS::GlobalShaderUniformType MaterialStorage::global_shader_uniform_get_type(const StringName &p_name) const {
if (!Engine::get_singleton()->is_editor_hint()) {
ERR_FAIL_V_MSG(RS::GLOBAL_VAR_TYPE_MAX, "This function should never be used outside the editor, it can severely damage performance.");
}
- return global_variable_get_type_internal(p_name);
+ return global_shader_uniform_get_type_internal(p_name);
}
-void MaterialStorage::global_variables_load_settings(bool p_load_textures) {
+void MaterialStorage::global_shader_uniforms_load_settings(bool p_load_textures) {
List<PropertyInfo> settings;
ProjectSettings::get_singleton()->get_property_list(&settings);
@@ -2146,11 +2146,11 @@ void MaterialStorage::global_variables_load_settings(bool p_load_textures) {
"samplerCube",
};
- RS::GlobalVariableType gvtype = RS::GLOBAL_VAR_TYPE_MAX;
+ RS::GlobalShaderUniformType gvtype = RS::GLOBAL_VAR_TYPE_MAX;
for (int i = 0; i < RS::GLOBAL_VAR_TYPE_MAX; i++) {
if (global_var_type_names[i] == type) {
- gvtype = RS::GlobalVariableType(i);
+ gvtype = RS::GlobalShaderUniformType(i);
break;
}
}
@@ -2172,47 +2172,47 @@ void MaterialStorage::global_variables_load_settings(bool p_load_textures) {
value = resource;
}
- if (global_variables.variables.has(name)) {
+ if (global_shader_uniforms.variables.has(name)) {
//has it, update it
- global_variable_set(name, value);
+ global_shader_uniform_set(name, value);
} else {
- global_variable_add(name, gvtype, value);
+ global_shader_uniform_add(name, gvtype, value);
}
}
}
}
-void MaterialStorage::global_variables_clear() {
- global_variables.variables.clear(); //not right but for now enough
+void MaterialStorage::global_shader_uniforms_clear() {
+ global_shader_uniforms.variables.clear(); //not right but for now enough
}
-RID MaterialStorage::global_variables_get_storage_buffer() const {
- return global_variables.buffer;
+RID MaterialStorage::global_shader_uniforms_get_storage_buffer() const {
+ return global_shader_uniforms.buffer;
}
-int32_t MaterialStorage::global_variables_instance_allocate(RID p_instance) {
- ERR_FAIL_COND_V(global_variables.instance_buffer_pos.has(p_instance), -1);
- int32_t pos = _global_variable_allocate(ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES);
- global_variables.instance_buffer_pos[p_instance] = pos; //save anyway
+int32_t MaterialStorage::global_shader_uniforms_instance_allocate(RID p_instance) {
+ ERR_FAIL_COND_V(global_shader_uniforms.instance_buffer_pos.has(p_instance), -1);
+ int32_t pos = _global_shader_uniform_allocate(ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES);
+ global_shader_uniforms.instance_buffer_pos[p_instance] = pos; //save anyway
ERR_FAIL_COND_V_MSG(pos < 0, -1, "Too many instances using shader instance variables. Increase buffer size in Project Settings.");
- global_variables.buffer_usage[pos].elements = ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES;
+ global_shader_uniforms.buffer_usage[pos].elements = ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES;
return pos;
}
-void MaterialStorage::global_variables_instance_free(RID p_instance) {
- ERR_FAIL_COND(!global_variables.instance_buffer_pos.has(p_instance));
- int32_t pos = global_variables.instance_buffer_pos[p_instance];
+void MaterialStorage::global_shader_uniforms_instance_free(RID p_instance) {
+ ERR_FAIL_COND(!global_shader_uniforms.instance_buffer_pos.has(p_instance));
+ int32_t pos = global_shader_uniforms.instance_buffer_pos[p_instance];
if (pos >= 0) {
- global_variables.buffer_usage[pos].elements = 0;
+ global_shader_uniforms.buffer_usage[pos].elements = 0;
}
- global_variables.instance_buffer_pos.erase(p_instance);
+ global_shader_uniforms.instance_buffer_pos.erase(p_instance);
}
-void MaterialStorage::global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) {
- if (!global_variables.instance_buffer_pos.has(p_instance)) {
+void MaterialStorage::global_shader_uniforms_instance_update(RID p_instance, int p_index, const Variant &p_value) {
+ if (!global_shader_uniforms.instance_buffer_pos.has(p_instance)) {
return; //just not allocated, ignore
}
- int32_t pos = global_variables.instance_buffer_pos[p_instance];
+ int32_t pos = global_shader_uniforms.instance_buffer_pos[p_instance];
if (pos < 0) {
return; //again, not allocated, ignore
@@ -2247,57 +2247,57 @@ void MaterialStorage::global_variables_instance_update(RID p_instance, int p_ind
pos += p_index;
- _fill_std140_variant_ubo_value(datatype, 0, p_value, (uint8_t *)&global_variables.buffer_values[pos], true); //instances always use linear color in this renderer
- _global_variable_mark_buffer_dirty(pos, 1);
+ _fill_std140_variant_ubo_value(datatype, 0, p_value, (uint8_t *)&global_shader_uniforms.buffer_values[pos], true); //instances always use linear color in this renderer
+ _global_shader_uniform_mark_buffer_dirty(pos, 1);
}
-void MaterialStorage::_update_global_variables() {
+void MaterialStorage::_update_global_shader_uniforms() {
MaterialStorage *material_storage = MaterialStorage::get_singleton();
- if (global_variables.buffer_dirty_region_count > 0) {
- uint32_t total_regions = global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE;
- if (total_regions / global_variables.buffer_dirty_region_count <= 4) {
+ if (global_shader_uniforms.buffer_dirty_region_count > 0) {
+ uint32_t total_regions = global_shader_uniforms.buffer_size / GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE;
+ if (total_regions / global_shader_uniforms.buffer_dirty_region_count <= 4) {
// 25% of regions dirty, just update all buffer
- RD::get_singleton()->buffer_update(global_variables.buffer, 0, sizeof(GlobalVariables::Value) * global_variables.buffer_size, global_variables.buffer_values);
- memset(global_variables.buffer_dirty_regions, 0, sizeof(bool) * total_regions);
+ RD::get_singleton()->buffer_update(global_shader_uniforms.buffer, 0, sizeof(GlobalShaderUniforms::Value) * global_shader_uniforms.buffer_size, global_shader_uniforms.buffer_values);
+ memset(global_shader_uniforms.buffer_dirty_regions, 0, sizeof(bool) * total_regions);
} else {
- uint32_t region_byte_size = sizeof(GlobalVariables::Value) * GlobalVariables::BUFFER_DIRTY_REGION_SIZE;
+ uint32_t region_byte_size = sizeof(GlobalShaderUniforms::Value) * GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE;
for (uint32_t i = 0; i < total_regions; i++) {
- if (global_variables.buffer_dirty_regions[i]) {
- RD::get_singleton()->buffer_update(global_variables.buffer, i * region_byte_size, region_byte_size, &global_variables.buffer_values[i * GlobalVariables::BUFFER_DIRTY_REGION_SIZE]);
+ if (global_shader_uniforms.buffer_dirty_regions[i]) {
+ RD::get_singleton()->buffer_update(global_shader_uniforms.buffer, i * region_byte_size, region_byte_size, &global_shader_uniforms.buffer_values[i * GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE]);
- global_variables.buffer_dirty_regions[i] = false;
+ global_shader_uniforms.buffer_dirty_regions[i] = false;
}
}
}
- global_variables.buffer_dirty_region_count = 0;
+ global_shader_uniforms.buffer_dirty_region_count = 0;
}
- if (global_variables.must_update_buffer_materials) {
+ if (global_shader_uniforms.must_update_buffer_materials) {
// only happens in the case of a buffer variable added or removed,
// so not often.
- for (const RID &E : global_variables.materials_using_buffer) {
+ for (const RID &E : global_shader_uniforms.materials_using_buffer) {
Material *material = material_storage->get_material(E);
ERR_CONTINUE(!material); //wtf
material_storage->_material_queue_update(material, true, false);
}
- global_variables.must_update_buffer_materials = false;
+ global_shader_uniforms.must_update_buffer_materials = false;
}
- if (global_variables.must_update_texture_materials) {
+ if (global_shader_uniforms.must_update_texture_materials) {
// only happens in the case of a buffer variable added or removed,
// so not often.
- for (const RID &E : global_variables.materials_using_texture) {
+ for (const RID &E : global_shader_uniforms.materials_using_texture) {
Material *material = material_storage->get_material(E);
ERR_CONTINUE(!material); //wtf
material_storage->_material_queue_update(material, false, true);
}
- global_variables.must_update_texture_materials = false;
+ global_shader_uniforms.must_update_texture_materials = false;
}
}
diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.h b/servers/rendering/renderer_rd/storage_rd/material_storage.h
index d5c9980150..ad40a86dd0 100644
--- a/servers/rendering/renderer_rd/storage_rd/material_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/material_storage.h
@@ -135,15 +135,15 @@ struct Material {
update_element(this) {}
};
-/* Global variable structs */
-struct GlobalVariables {
+/* Global shader uniform structs */
+struct GlobalShaderUniforms {
enum {
BUFFER_DIRTY_REGION_SIZE = 1024
};
struct Variable {
HashSet<RID> texture_materials; // materials using this
- RS::GlobalVariableType type;
+ RS::GlobalShaderUniformType type;
Variant value;
Variant override;
int32_t buffer_index; //for vectors
@@ -209,13 +209,13 @@ private:
RID quad_index_buffer;
RID quad_index_array;
- /* GLOBAL VARIABLE API */
+ /* GLOBAL SHADER UNIFORM API */
- GlobalVariables global_variables;
+ GlobalShaderUniforms global_shader_uniforms;
- int32_t _global_variable_allocate(uint32_t p_elements);
- void _global_variable_store_in_buffer(int32_t p_index, RS::GlobalVariableType p_type, const Variant &p_value);
- void _global_variable_mark_buffer_dirty(int32_t p_index, int32_t p_elements);
+ int32_t _global_shader_uniform_allocate(uint32_t p_elements);
+ void _global_shader_uniform_store_in_buffer(int32_t p_index, RS::GlobalShaderUniformType p_type, const Variant &p_value);
+ void _global_shader_uniform_mark_buffer_dirty(int32_t p_index, int32_t p_elements);
/* SHADER API */
@@ -333,28 +333,28 @@ public:
RID get_quad_index_array() { return quad_index_array; }
- /* GLOBAL VARIABLE API */
+ /* GLOBAL SHADER UNIFORM API */
- void _update_global_variables();
+ void _update_global_shader_uniforms();
- virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) override;
- virtual void global_variable_remove(const StringName &p_name) override;
- virtual Vector<StringName> global_variable_get_list() const override;
+ virtual void global_shader_uniform_add(const StringName &p_name, RS::GlobalShaderUniformType p_type, const Variant &p_value) override;
+ virtual void global_shader_uniform_remove(const StringName &p_name) override;
+ virtual Vector<StringName> global_shader_uniform_get_list() const override;
- virtual void global_variable_set(const StringName &p_name, const Variant &p_value) override;
- virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value) override;
- virtual Variant global_variable_get(const StringName &p_name) const override;
- virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const override;
- RS::GlobalVariableType global_variable_get_type_internal(const StringName &p_name) const;
+ virtual void global_shader_uniform_set(const StringName &p_name, const Variant &p_value) override;
+ virtual void global_shader_uniform_set_override(const StringName &p_name, const Variant &p_value) override;
+ virtual Variant global_shader_uniform_get(const StringName &p_name) const override;
+ virtual RS::GlobalShaderUniformType global_shader_uniform_get_type(const StringName &p_name) const override;
+ RS::GlobalShaderUniformType global_shader_uniform_get_type_internal(const StringName &p_name) const;
- virtual void global_variables_load_settings(bool p_load_textures = true) override;
- virtual void global_variables_clear() override;
+ virtual void global_shader_uniforms_load_settings(bool p_load_textures = true) override;
+ virtual void global_shader_uniforms_clear() override;
- virtual int32_t global_variables_instance_allocate(RID p_instance) override;
- virtual void global_variables_instance_free(RID p_instance) override;
- virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) override;
+ virtual int32_t global_shader_uniforms_instance_allocate(RID p_instance) override;
+ virtual void global_shader_uniforms_instance_free(RID p_instance) override;
+ virtual void global_shader_uniforms_instance_update(RID p_instance, int p_index, const Variant &p_value) override;
- RID global_variables_get_storage_buffer() const;
+ RID global_shader_uniforms_get_storage_buffer() const;
/* SHADER API */
diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
index 75977c5bc9..1e5511eeda 100644
--- a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
@@ -112,7 +112,7 @@ ParticlesStorage::ParticlesStorage() {
actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
actions.default_repeat = ShaderLanguage::REPEAT_ENABLE;
- actions.global_buffer_array_variable = "global_variables.data";
+ actions.global_buffer_array_variable = "global_shader_uniforms.data";
particles_shader.compiler.initialize(actions);
}
@@ -164,7 +164,7 @@ void process() {
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 2;
- u.append_id(material_storage->global_variables_get_storage_buffer());
+ u.append_id(material_storage->global_shader_uniforms_get_storage_buffer());
uniforms.push_back(u);
}
diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
index abf364b8b4..6d7ea5184a 100644
--- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
@@ -398,9 +398,8 @@ TextureStorage::TextureStorage() {
tformat.format = RD::DATA_FORMAT_R8_UINT;
tformat.width = 4;
tformat.height = 4;
- tformat.array_layers = 1;
tformat.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_VRS_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
- tformat.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+ tformat.texture_type = RD::TEXTURE_TYPE_2D;
Vector<uint8_t> pv;
pv.resize(4 * 4);
diff --git a/servers/rendering/renderer_rd/storage_rd/utilities.cpp b/servers/rendering/renderer_rd/storage_rd/utilities.cpp
index a1f62c16c7..b4dccfabc7 100644
--- a/servers/rendering/renderer_rd/storage_rd/utilities.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/utilities.cpp
@@ -272,7 +272,7 @@ String Utilities::get_captured_timestamp_name(uint32_t p_index) const {
/* MISC */
void Utilities::update_dirty_resources() {
- MaterialStorage::get_singleton()->_update_global_variables(); //must do before materials, so it can queue them for update
+ MaterialStorage::get_singleton()->_update_global_shader_uniforms(); //must do before materials, so it can queue them for update
MaterialStorage::get_singleton()->_update_queued_materials();
MeshStorage::get_singleton()->_update_dirty_multimeshes();
MeshStorage::get_singleton()->_update_dirty_skeletons();
diff --git a/servers/rendering/renderer_scene.h b/servers/rendering/renderer_scene.h
index bc95dd033f..852fe89cd0 100644
--- a/servers/rendering/renderer_scene.h
+++ b/servers/rendering/renderer_scene.h
@@ -306,7 +306,7 @@ public:
virtual RID render_buffers_create() = 0;
- virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) = 0;
+ virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) = 0;
virtual void gi_set_use_half_resolution(bool p_enable) = 0;
diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp
index 7e9be504f8..368bbb63f5 100644
--- a/servers/rendering/renderer_scene_cull.cpp
+++ b/servers/rendering/renderer_scene_cull.cpp
@@ -1441,7 +1441,7 @@ void RendererSceneCull::instance_geometry_set_shader_parameter(RID p_instance, c
E->value.value = p_value;
if (E->value.index >= 0 && instance->instance_allocated_shader_parameters) {
//update directly
- RSG::material_storage->global_variables_instance_update(p_instance, E->value.index, p_value);
+ RSG::material_storage->global_shader_uniforms_instance_update(p_instance, E->value.index, p_value);
}
}
}
@@ -3850,16 +3850,16 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
if (p_instance->instance_allocated_shader_parameters != (p_instance->instance_shader_parameters.size() > 0)) {
p_instance->instance_allocated_shader_parameters = (p_instance->instance_shader_parameters.size() > 0);
if (p_instance->instance_allocated_shader_parameters) {
- p_instance->instance_allocated_shader_parameters_offset = RSG::material_storage->global_variables_instance_allocate(p_instance->self);
+ p_instance->instance_allocated_shader_parameters_offset = RSG::material_storage->global_shader_uniforms_instance_allocate(p_instance->self);
geom->geometry_instance->set_instance_shader_parameters_offset(p_instance->instance_allocated_shader_parameters_offset);
for (const KeyValue<StringName, Instance::InstanceShaderParameter> &E : p_instance->instance_shader_parameters) {
if (E.value.value.get_type() != Variant::NIL) {
- RSG::material_storage->global_variables_instance_update(p_instance->self, E.value.index, E.value.value);
+ RSG::material_storage->global_shader_uniforms_instance_update(p_instance->self, E.value.index, E.value.value);
}
}
} else {
- RSG::material_storage->global_variables_instance_free(p_instance->self);
+ RSG::material_storage->global_shader_uniforms_instance_free(p_instance->self);
p_instance->instance_allocated_shader_parameters_offset = -1;
geom->geometry_instance->set_instance_shader_parameters_offset(-1);
}
@@ -3955,7 +3955,7 @@ bool RendererSceneCull::free(RID p_rid) {
if (instance->instance_allocated_shader_parameters) {
//free the used shader parameters
- RSG::material_storage->global_variables_instance_free(instance->self);
+ RSG::material_storage->global_shader_uniforms_instance_free(instance->self);
}
update_dirty_instances(); //in case something changed this
diff --git a/servers/rendering/renderer_scene_render.h b/servers/rendering/renderer_scene_render.h
index 7f43bf6b54..7f70f4b939 100644
--- a/servers/rendering/renderer_scene_render.h
+++ b/servers/rendering/renderer_scene_render.h
@@ -341,7 +341,7 @@ public:
virtual void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) = 0;
virtual RID render_buffers_create() = 0;
- virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) = 0;
+ virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) = 0;
virtual void gi_set_use_half_resolution(bool p_enable) = 0;
virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_limit) = 0;
diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp
index 0e26de8bcb..118bf532b3 100644
--- a/servers/rendering/renderer_viewport.cpp
+++ b/servers/rendering/renderer_viewport.cpp
@@ -138,7 +138,7 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) {
p_viewport->internal_size = Size2(render_width, render_height);
- RSG::scene->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, render_width, render_height, width, height, p_viewport->fsr_sharpness, p_viewport->fsr_mipmap_bias, p_viewport->msaa, p_viewport->screen_space_aa, p_viewport->use_taa, p_viewport->use_debanding, p_viewport->get_view_count());
+ RSG::scene->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, render_width, render_height, width, height, p_viewport->fsr_sharpness, p_viewport->texture_mipmap_bias, p_viewport->msaa, p_viewport->screen_space_aa, p_viewport->use_taa, p_viewport->use_debanding, p_viewport->get_view_count());
}
}
}
@@ -746,11 +746,11 @@ void RendererViewport::viewport_set_fsr_sharpness(RID p_viewport, float p_sharpn
_configure_3d_render_buffers(viewport);
}
-void RendererViewport::viewport_set_fsr_mipmap_bias(RID p_viewport, float p_mipmap_bias) {
+void RendererViewport::viewport_set_texture_mipmap_bias(RID p_viewport, float p_mipmap_bias) {
Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
- viewport->fsr_mipmap_bias = p_mipmap_bias;
+ viewport->texture_mipmap_bias = p_mipmap_bias;
_configure_3d_render_buffers(viewport);
}
diff --git a/servers/rendering/renderer_viewport.h b/servers/rendering/renderer_viewport.h
index 4647fbd8c3..5e37c96336 100644
--- a/servers/rendering/renderer_viewport.h
+++ b/servers/rendering/renderer_viewport.h
@@ -59,7 +59,7 @@ public:
RS::ViewportScaling3DMode scaling_3d_mode = RenderingServer::VIEWPORT_SCALING_3D_MODE_BILINEAR;
float scaling_3d_scale = 1.0;
float fsr_sharpness = 0.2f;
- float fsr_mipmap_bias = 0.0f;
+ float texture_mipmap_bias = 0.0f;
bool fsr_enabled = false;
RS::ViewportUpdateMode update_mode = RenderingServer::VIEWPORT_UPDATE_WHEN_VISIBLE;
RID render_target;
@@ -229,7 +229,7 @@ public:
void viewport_set_scaling_3d_mode(RID p_viewport, RS::ViewportScaling3DMode p_mode);
void viewport_set_scaling_3d_scale(RID p_viewport, float p_scaling_3d_scale);
void viewport_set_fsr_sharpness(RID p_viewport, float p_sharpness);
- void viewport_set_fsr_mipmap_bias(RID p_viewport, float p_mipmap_bias);
+ void viewport_set_texture_mipmap_bias(RID p_viewport, float p_mipmap_bias);
void viewport_set_update_mode(RID p_viewport, RS::ViewportUpdateMode p_mode);
void viewport_set_vflip(RID p_viewport, bool p_enable);
diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h
index f093f43a82..21a94b88f2 100644
--- a/servers/rendering/rendering_server_default.h
+++ b/servers/rendering/rendering_server_default.h
@@ -591,7 +591,7 @@ public:
FUNC2(viewport_set_scaling_3d_mode, RID, ViewportScaling3DMode)
FUNC2(viewport_set_scaling_3d_scale, RID, float)
FUNC2(viewport_set_fsr_sharpness, RID, float)
- FUNC2(viewport_set_fsr_mipmap_bias, RID, float)
+ FUNC2(viewport_set_texture_mipmap_bias, RID, float)
FUNC2(viewport_set_update_mode, RID, ViewportUpdateMode)
@@ -900,7 +900,7 @@ public:
FUNC1(canvas_set_shadow_texture_size, int)
- /* GLOBAL VARIABLES */
+ /* GLOBAL SHADER UNIFORMS */
#undef server_name
#undef ServerName
@@ -908,16 +908,16 @@ public:
#define ServerName RendererMaterialStorage
#define server_name RSG::material_storage
- FUNC3(global_variable_add, const StringName &, GlobalVariableType, const Variant &)
- FUNC1(global_variable_remove, const StringName &)
- FUNC0RC(Vector<StringName>, global_variable_get_list)
- FUNC2(global_variable_set, const StringName &, const Variant &)
- FUNC2(global_variable_set_override, const StringName &, const Variant &)
- FUNC1RC(GlobalVariableType, global_variable_get_type, const StringName &)
- FUNC1RC(Variant, global_variable_get, const StringName &)
+ FUNC3(global_shader_uniform_add, const StringName &, GlobalShaderUniformType, const Variant &)
+ FUNC1(global_shader_uniform_remove, const StringName &)
+ FUNC0RC(Vector<StringName>, global_shader_uniform_get_list)
+ FUNC2(global_shader_uniform_set, const StringName &, const Variant &)
+ FUNC2(global_shader_uniform_set_override, const StringName &, const Variant &)
+ FUNC1RC(GlobalShaderUniformType, global_shader_uniform_get_type, const StringName &)
+ FUNC1RC(Variant, global_shader_uniform_get, const StringName &)
- FUNC1(global_variables_load_settings, bool)
- FUNC0(global_variables_clear)
+ FUNC1(global_shader_uniforms_load_settings, bool)
+ FUNC0(global_shader_uniforms_clear)
#undef server_name
#undef ServerName
diff --git a/servers/rendering/shader_compiler.cpp b/servers/rendering/shader_compiler.cpp
index e291246d01..7637eae4a6 100644
--- a/servers/rendering/shader_compiler.cpp
+++ b/servers/rendering/shader_compiler.cpp
@@ -370,7 +370,7 @@ void ShaderCompiler::_dump_function_deps(const SL::ShaderNode *p_node, const Str
}
}
-static String _get_global_variable_from_type_and_index(const String &p_buffer, const String &p_index, ShaderLanguage::DataType p_type) {
+static String _get_global_shader_uniform_from_type_and_index(const String &p_buffer, const String &p_index, ShaderLanguage::DataType p_type) {
switch (p_type) {
case ShaderLanguage::TYPE_BOOL: {
return "(" + p_buffer + "[" + p_index + "].x != 0.0)";
@@ -903,11 +903,11 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
if (u.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) {
code = actions.base_uniform_string + _mkid(vnode->name); //texture, use as is
//global variable, this means the code points to an index to the global table
- code = _get_global_variable_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
+ code = _get_global_shader_uniform_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
} else if (u.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
//instance variable, index it as such
code = "(" + p_default_actions.instance_uniform_index_variable + "+" + itos(u.instance_index) + ")";
- code = _get_global_variable_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
+ code = _get_global_shader_uniform_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
} else {
//regular uniform, index from UBO
code = actions.base_uniform_string + _mkid(vnode->name);
@@ -1003,11 +1003,11 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
if (u.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) {
code = actions.base_uniform_string + _mkid(anode->name); //texture, use as is
//global variable, this means the code points to an index to the global table
- code = _get_global_variable_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
+ code = _get_global_shader_uniform_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
} else if (u.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
//instance variable, index it as such
code = "(" + p_default_actions.instance_uniform_index_variable + "+" + itos(u.instance_index) + ")";
- code = _get_global_variable_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
+ code = _get_global_shader_uniform_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
} else {
//regular uniform, index from UBO
code = actions.base_uniform_string + _mkid(anode->name);
@@ -1309,8 +1309,8 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
}
ShaderLanguage::DataType ShaderCompiler::_get_variable_type(const StringName &p_type) {
- RS::GlobalVariableType gvt = RS::get_singleton()->global_variable_get_type(p_type);
- return (ShaderLanguage::DataType)RS::global_variable_type_get_shader_datatype(gvt);
+ RS::GlobalShaderUniformType gvt = RS::get_singleton()->global_shader_uniform_get_type(p_type);
+ return (ShaderLanguage::DataType)RS::global_shader_uniform_type_get_shader_datatype(gvt);
}
Error ShaderCompiler::compile(RS::ShaderMode p_mode, const String &p_code, IdentifierActions *p_actions, const String &p_path, GeneratedCode &r_gen_code) {
@@ -1318,7 +1318,7 @@ Error ShaderCompiler::compile(RS::ShaderMode p_mode, const String &p_code, Ident
info.functions = ShaderTypes::get_singleton()->get_functions(p_mode);
info.render_modes = ShaderTypes::get_singleton()->get_modes(p_mode);
info.shader_types = ShaderTypes::get_singleton()->get_types();
- info.global_variable_type_func = _get_variable_type;
+ info.global_shader_uniform_type_func = _get_variable_type;
Error err = parser.compile(p_code, info);
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index bb41b06189..2dd0f7006b 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -8277,7 +8277,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
if (is_uniform) {
if (uniform_scope == ShaderNode::Uniform::SCOPE_GLOBAL && Engine::get_singleton()->is_editor_hint()) { // Type checking for global uniforms is not allowed outside the editor.
//validate global uniform
- DataType gvtype = global_var_get_type_func(name);
+ DataType gvtype = global_shader_uniform_get_type_func(name);
if (gvtype == TYPE_MAX) {
_set_error(vformat(RTR("Global uniform '%s' does not exist. Create it in Project Settings."), String(name)));
return ERR_PARSE_ERROR;
@@ -9652,7 +9652,7 @@ Error ShaderLanguage::compile(const String &p_code, const ShaderCompileInfo &p_i
is_shader_inc = p_info.is_include;
code = p_code;
- global_var_get_type_func = p_info.global_variable_type_func;
+ global_shader_uniform_get_type_func = p_info.global_shader_uniform_type_func;
varying_function_names = p_info.varying_function_names;
@@ -9681,7 +9681,7 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
varying_function_names = p_info.varying_function_names;
nodes = nullptr;
- global_var_get_type_func = p_info.global_variable_type_func;
+ global_shader_uniform_get_type_func = p_info.global_shader_uniform_type_func;
shader = alloc_node<ShaderNode>();
_parse_shader(p_info.functions, p_info.render_modes, p_info.shader_types);
diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h
index 42023f25d7..09160e2949 100644
--- a/servers/rendering/shader_language.h
+++ b/servers/rendering/shader_language.h
@@ -869,7 +869,7 @@ public:
};
static bool has_builtin(const HashMap<StringName, ShaderLanguage::FunctionInfo> &p_functions, const StringName &p_name);
- typedef DataType (*GlobalVariableGetTypeFunc)(const StringName &p_name);
+ typedef DataType (*GlobalShaderUniformGetTypeFunc)(const StringName &p_name);
struct FilePosition {
String file;
@@ -887,7 +887,7 @@ private:
static const KeyWord keyword_list[];
- GlobalVariableGetTypeFunc global_var_get_type_func = nullptr;
+ GlobalShaderUniformGetTypeFunc global_shader_uniform_get_type_func = nullptr;
bool error_set = false;
String error_str;
@@ -1113,7 +1113,7 @@ public:
Vector<ModeInfo> render_modes;
VaryingFunctionNames varying_function_names = VaryingFunctionNames();
HashSet<String> shader_types;
- GlobalVariableGetTypeFunc global_variable_type_func = nullptr;
+ GlobalShaderUniformGetTypeFunc global_shader_uniform_type_func = nullptr;
bool is_include = false;
};
diff --git a/servers/rendering/storage/material_storage.h b/servers/rendering/storage/material_storage.h
index 3566502144..6347b22240 100644
--- a/servers/rendering/storage/material_storage.h
+++ b/servers/rendering/storage/material_storage.h
@@ -38,22 +38,22 @@ class RendererMaterialStorage {
public:
virtual ~RendererMaterialStorage(){};
- /* GLOBAL VARIABLE API */
- virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) = 0;
- virtual void global_variable_remove(const StringName &p_name) = 0;
- virtual Vector<StringName> global_variable_get_list() const = 0;
-
- virtual void global_variable_set(const StringName &p_name, const Variant &p_value) = 0;
- virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value) = 0;
- virtual Variant global_variable_get(const StringName &p_name) const = 0;
- virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const = 0;
-
- virtual void global_variables_load_settings(bool p_load_textures = true) = 0;
- virtual void global_variables_clear() = 0;
-
- virtual int32_t global_variables_instance_allocate(RID p_instance) = 0;
- virtual void global_variables_instance_free(RID p_instance) = 0;
- virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) = 0;
+ /* GLOBAL SHADER UNIFORM API */
+ virtual void global_shader_uniform_add(const StringName &p_name, RS::GlobalShaderUniformType p_type, const Variant &p_value) = 0;
+ virtual void global_shader_uniform_remove(const StringName &p_name) = 0;
+ virtual Vector<StringName> global_shader_uniform_get_list() const = 0;
+
+ virtual void global_shader_uniform_set(const StringName &p_name, const Variant &p_value) = 0;
+ virtual void global_shader_uniform_set_override(const StringName &p_name, const Variant &p_value) = 0;
+ virtual Variant global_shader_uniform_get(const StringName &p_name) const = 0;
+ virtual RS::GlobalShaderUniformType global_shader_uniform_get_type(const StringName &p_name) const = 0;
+
+ virtual void global_shader_uniforms_load_settings(bool p_load_textures = true) = 0;
+ virtual void global_shader_uniforms_clear() = 0;
+
+ virtual int32_t global_shader_uniforms_instance_allocate(RID p_instance) = 0;
+ virtual void global_shader_uniforms_instance_free(RID p_instance) = 0;
+ virtual void global_shader_uniforms_instance_update(RID p_instance, int p_index, const Variant &p_value) = 0;
/* SHADER API */
virtual RID shader_allocate() = 0;
diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp
index 73405dcbed..6269b05d99 100644
--- a/servers/rendering_server.cpp
+++ b/servers/rendering_server.cpp
@@ -1410,7 +1410,7 @@ Array RenderingServer::_mesh_surface_get_skeleton_aabb_bind(RID p_mesh, int p_su
}
#endif
-int RenderingServer::global_variable_type_get_shader_datatype(GlobalVariableType p_type) {
+int RenderingServer::global_shader_uniform_type_get_shader_datatype(GlobalShaderUniformType p_type) {
switch (p_type) {
case RS::GLOBAL_VAR_TYPE_BOOL:
return ShaderLanguage::TYPE_BOOL;
@@ -2184,7 +2184,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("viewport_set_scaling_3d_mode", "viewport", "scaling_3d_mode"), &RenderingServer::viewport_set_scaling_3d_mode);
ClassDB::bind_method(D_METHOD("viewport_set_scaling_3d_scale", "viewport", "scale"), &RenderingServer::viewport_set_scaling_3d_scale);
ClassDB::bind_method(D_METHOD("viewport_set_fsr_sharpness", "viewport", "sharpness"), &RenderingServer::viewport_set_fsr_sharpness);
- ClassDB::bind_method(D_METHOD("viewport_set_fsr_mipmap_bias", "viewport", "mipmap_bias"), &RenderingServer::viewport_set_fsr_mipmap_bias);
+ ClassDB::bind_method(D_METHOD("viewport_set_texture_mipmap_bias", "viewport", "mipmap_bias"), &RenderingServer::viewport_set_texture_mipmap_bias);
ClassDB::bind_method(D_METHOD("viewport_set_update_mode", "viewport", "update_mode"), &RenderingServer::viewport_set_update_mode);
ClassDB::bind_method(D_METHOD("viewport_set_clear_mode", "viewport", "clear_mode"), &RenderingServer::viewport_set_clear_mode);
ClassDB::bind_method(D_METHOD("viewport_get_texture", "viewport"), &RenderingServer::viewport_get_texture);
@@ -2690,15 +2690,15 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE);
BIND_ENUM_CONSTANT(CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE);
- /* GLOBAL VARIABLES */
+ /* GLOBAL SHADER UNIFORMS */
- ClassDB::bind_method(D_METHOD("global_variable_add", "name", "type", "default_value"), &RenderingServer::global_variable_add);
- ClassDB::bind_method(D_METHOD("global_variable_remove", "name"), &RenderingServer::global_variable_remove);
- ClassDB::bind_method(D_METHOD("global_variable_get_list"), &RenderingServer::global_variable_get_list);
- ClassDB::bind_method(D_METHOD("global_variable_set", "name", "value"), &RenderingServer::global_variable_set);
- ClassDB::bind_method(D_METHOD("global_variable_set_override", "name", "value"), &RenderingServer::global_variable_set_override);
- ClassDB::bind_method(D_METHOD("global_variable_get", "name"), &RenderingServer::global_variable_get);
- ClassDB::bind_method(D_METHOD("global_variable_get_type", "name"), &RenderingServer::global_variable_get_type);
+ ClassDB::bind_method(D_METHOD("global_shader_uniform_add", "name", "type", "default_value"), &RenderingServer::global_shader_uniform_add);
+ ClassDB::bind_method(D_METHOD("global_shader_uniform_remove", "name"), &RenderingServer::global_shader_uniform_remove);
+ ClassDB::bind_method(D_METHOD("global_shader_uniform_get_list"), &RenderingServer::global_shader_uniform_get_list);
+ ClassDB::bind_method(D_METHOD("global_shader_uniform_set", "name", "value"), &RenderingServer::global_shader_uniform_set);
+ ClassDB::bind_method(D_METHOD("global_shader_uniform_set_override", "name", "value"), &RenderingServer::global_shader_uniform_set_override);
+ ClassDB::bind_method(D_METHOD("global_shader_uniform_get", "name"), &RenderingServer::global_shader_uniform_get);
+ ClassDB::bind_method(D_METHOD("global_shader_uniform_get_type", "name"), &RenderingServer::global_shader_uniform_get_type);
BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_BOOL);
BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_BVEC2);
@@ -2946,7 +2946,7 @@ void RenderingServer::init() {
GLOBAL_DEF("rendering/scaling_3d/mode", 0);
GLOBAL_DEF("rendering/scaling_3d/scale", 1.0);
GLOBAL_DEF("rendering/scaling_3d/fsr_sharpness", 0.2f);
- GLOBAL_DEF("rendering/scaling_3d/fsr_mipmap_bias", 0.0f);
+ GLOBAL_DEF("rendering/textures/default_filters/texture_mipmap_bias", 0.0f);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/scaling_3d/mode",
PropertyInfo(Variant::INT,
"rendering/scaling_3d/mode",
@@ -2961,10 +2961,10 @@ void RenderingServer::init() {
PropertyInfo(Variant::FLOAT,
"rendering/scaling_3d/fsr_sharpness",
PROPERTY_HINT_RANGE, "0,2,0.1"));
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/scaling_3d/fsr_mipmap_bias",
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/textures/default_filters/texture_mipmap_bias",
PropertyInfo(Variant::FLOAT,
- "rendering/scaling_3d/fsr_mipmap_bias",
- PROPERTY_HINT_RANGE, "-2,2,0.1"));
+ "rendering/textures/default_filters/texture_mipmap_bias",
+ PROPERTY_HINT_RANGE, "-2,2,0.001"));
GLOBAL_DEF("rendering/textures/decals/filter", DECAL_FILTER_LINEAR_MIPMAPS);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/textures/decals/filter", PropertyInfo(Variant::INT, "rendering/textures/decals/filter", PROPERTY_HINT_ENUM, "Nearest (Fast),Nearest+Mipmaps,Linear,Linear+Mipmaps,Linear+Mipmaps Anisotropic (Slow)"));
diff --git a/servers/rendering_server.h b/servers/rendering_server.h
index dcb2683add..1f2012ac8d 100644
--- a/servers/rendering_server.h
+++ b/servers/rendering_server.h
@@ -797,7 +797,7 @@ public:
virtual void viewport_set_scaling_3d_mode(RID p_viewport, ViewportScaling3DMode p_scaling_3d_mode) = 0;
virtual void viewport_set_scaling_3d_scale(RID p_viewport, float p_scaling_3d_scale) = 0;
virtual void viewport_set_fsr_sharpness(RID p_viewport, float p_fsr_sharpness) = 0;
- virtual void viewport_set_fsr_mipmap_bias(RID p_viewport, float p_fsr_mipmap_bias) = 0;
+ virtual void viewport_set_texture_mipmap_bias(RID p_viewport, float p_texture_mipmap_bias) = 0;
enum ViewportUpdateMode {
VIEWPORT_UPDATE_DISABLED,
@@ -1425,9 +1425,9 @@ public:
virtual void canvas_set_shadow_texture_size(int p_size) = 0;
- /* GLOBAL VARIABLES */
+ /* GLOBAL SHADER UNIFORMS */
- enum GlobalVariableType {
+ enum GlobalShaderUniformType {
GLOBAL_VAR_TYPE_BOOL,
GLOBAL_VAR_TYPE_BVEC2,
GLOBAL_VAR_TYPE_BVEC3,
@@ -1459,20 +1459,20 @@ public:
GLOBAL_VAR_TYPE_MAX
};
- virtual void global_variable_add(const StringName &p_name, GlobalVariableType p_type, const Variant &p_value) = 0;
- virtual void global_variable_remove(const StringName &p_name) = 0;
- virtual Vector<StringName> global_variable_get_list() const = 0;
+ virtual void global_shader_uniform_add(const StringName &p_name, GlobalShaderUniformType p_type, const Variant &p_value) = 0;
+ virtual void global_shader_uniform_remove(const StringName &p_name) = 0;
+ virtual Vector<StringName> global_shader_uniform_get_list() const = 0;
- virtual void global_variable_set(const StringName &p_name, const Variant &p_value) = 0;
- virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value) = 0;
+ virtual void global_shader_uniform_set(const StringName &p_name, const Variant &p_value) = 0;
+ virtual void global_shader_uniform_set_override(const StringName &p_name, const Variant &p_value) = 0;
- virtual Variant global_variable_get(const StringName &p_name) const = 0;
- virtual GlobalVariableType global_variable_get_type(const StringName &p_name) const = 0;
+ virtual Variant global_shader_uniform_get(const StringName &p_name) const = 0;
+ virtual GlobalShaderUniformType global_shader_uniform_get_type(const StringName &p_name) const = 0;
- virtual void global_variables_load_settings(bool p_load_textures) = 0;
- virtual void global_variables_clear() = 0;
+ virtual void global_shader_uniforms_load_settings(bool p_load_textures) = 0;
+ virtual void global_shader_uniforms_clear() = 0;
- static int global_variable_type_get_shader_datatype(GlobalVariableType p_type);
+ static int global_shader_uniform_type_get_shader_datatype(GlobalShaderUniformType p_type);
/* FREE */
@@ -1648,7 +1648,7 @@ VARIANT_ENUM_CAST(RenderingServer::CanvasLightMode);
VARIANT_ENUM_CAST(RenderingServer::CanvasLightBlendMode);
VARIANT_ENUM_CAST(RenderingServer::CanvasLightShadowFilter);
VARIANT_ENUM_CAST(RenderingServer::CanvasOccluderPolygonCullMode);
-VARIANT_ENUM_CAST(RenderingServer::GlobalVariableType);
+VARIANT_ENUM_CAST(RenderingServer::GlobalShaderUniformType);
VARIANT_ENUM_CAST(RenderingServer::RenderingInfo);
VARIANT_ENUM_CAST(RenderingServer::Features);
VARIANT_ENUM_CAST(RenderingServer::CanvasTextureChannel);
diff --git a/servers/xr_server.cpp b/servers/xr_server.cpp
index ad61aa94bc..990281d96d 100644
--- a/servers/xr_server.cpp
+++ b/servers/xr_server.cpp
@@ -33,6 +33,16 @@
#include "xr/xr_interface.h"
#include "xr/xr_positional_tracker.h"
+XRServer::XRMode XRServer::xr_mode = XRMODE_DEFAULT;
+
+XRServer::XRMode XRServer::get_xr_mode() {
+ return xr_mode;
+}
+
+void XRServer::set_xr_mode(XRServer::XRMode p_mode) {
+ xr_mode = p_mode;
+}
+
XRServer *XRServer::singleton = nullptr;
XRServer *XRServer::get_singleton() {
diff --git a/servers/xr_server.h b/servers/xr_server.h
index d9188d2de1..74128bfb54 100644
--- a/servers/xr_server.h
+++ b/servers/xr_server.h
@@ -57,6 +57,12 @@ class XRServer : public Object {
_THREAD_SAFE_CLASS_
public:
+ enum XRMode {
+ XRMODE_DEFAULT, /* Default behaviour, means we check project settings */
+ XRMODE_OFF, /* Ignore project settings, disable OpenXR, disable shaders */
+ XRMODE_ON, /* Ignore project settings, enable OpenXR, enable shaders, run editor in VR (if applicable) */
+ };
+
enum TrackerType {
TRACKER_HEAD = 0x01, /* tracks the position of the players head (or in case of handheld AR, location of the phone) */
TRACKER_CONTROLLER = 0x02, /* tracks a controller */
@@ -75,6 +81,8 @@ public:
};
private:
+ static XRMode xr_mode;
+
Vector<Ref<XRInterface>> interfaces;
Dictionary trackers;
@@ -90,6 +98,9 @@ protected:
static void _bind_methods();
public:
+ static XRMode get_xr_mode();
+ static void set_xr_mode(XRMode p_mode);
+
static XRServer *get_singleton();
/*
diff --git a/tests/core/object/test_object.h b/tests/core/object/test_object.h
index 5b9d9cab53..88a3e4ccad 100644
--- a/tests/core/object/test_object.h
+++ b/tests/core/object/test_object.h
@@ -95,8 +95,8 @@ public:
Ref<Script> get_script() const override {
return Ref<Script>();
}
- const Vector<Multiplayer::RPCConfig> get_rpc_methods() const override {
- return Vector<Multiplayer::RPCConfig>();
+ const Variant get_rpc_config() const override {
+ return Variant();
}
ScriptLanguage *get_language() override {
return nullptr;
diff --git a/tests/test_main.cpp b/tests/test_main.cpp
index e71f2edba3..13cbc7f8aa 100644
--- a/tests/test_main.cpp
+++ b/tests/test_main.cpp
@@ -257,7 +257,7 @@ struct GodotTestCaseListener : public doctest::IReporter {
if (RenderingServer::get_singleton()) {
RenderingServer::get_singleton()->sync();
- RenderingServer::get_singleton()->global_variables_clear();
+ RenderingServer::get_singleton()->global_shader_uniforms_clear();
RenderingServer::get_singleton()->finish();
memdelete(RenderingServer::get_singleton());
}