summaryrefslogtreecommitdiff
path: root/servers
diff options
context:
space:
mode:
Diffstat (limited to 'servers')
-rw-r--r--servers/SCsub1
-rw-r--r--servers/audio/audio_driver_dummy.cpp2
-rw-r--r--servers/audio/audio_rb_resampler.cpp5
-rw-r--r--servers/audio/audio_stream.cpp145
-rw-r--r--servers/audio/audio_stream.h54
-rw-r--r--servers/audio/effects/audio_effect_capture.h1
-rw-r--r--servers/audio/effects/audio_effect_pitch_shift.cpp2
-rw-r--r--servers/audio/effects/audio_stream_generator.cpp7
-rw-r--r--servers/audio/effects/audio_stream_generator.h3
-rw-r--r--servers/audio_server.cpp493
-rw-r--r--servers/audio_server.h90
-rw-r--r--servers/display_server.cpp6
-rw-r--r--servers/display_server.h1
-rw-r--r--servers/physics_2d/area_2d_sw.cpp31
-rw-r--r--servers/physics_2d/area_2d_sw.h35
-rw-r--r--servers/physics_2d/area_pair_2d_sw.cpp67
-rw-r--r--servers/physics_2d/area_pair_2d_sw.h6
-rw-r--r--servers/physics_2d/body_2d_sw.cpp300
-rw-r--r--servers/physics_2d/body_2d_sw.h185
-rw-r--r--servers/physics_2d/body_direct_state_2d_sw.cpp178
-rw-r--r--servers/physics_2d/body_direct_state_2d_sw.h91
-rw-r--r--servers/physics_2d/body_pair_2d_sw.cpp4
-rw-r--r--servers/physics_2d/body_pair_2d_sw.h18
-rw-r--r--servers/physics_2d/broad_phase_2d_bvh.cpp3
-rw-r--r--servers/physics_2d/broad_phase_2d_bvh.h8
-rw-r--r--servers/physics_2d/collision_object_2d_sw.cpp10
-rw-r--r--servers/physics_2d/collision_object_2d_sw.h31
-rw-r--r--servers/physics_2d/collision_solver_2d_sat.cpp70
-rw-r--r--servers/physics_2d/collision_solver_2d_sw.cpp132
-rw-r--r--servers/physics_2d/collision_solver_2d_sw.h10
-rw-r--r--servers/physics_2d/constraint_2d_sw.h6
-rw-r--r--servers/physics_2d/joints_2d_sw.cpp21
-rw-r--r--servers/physics_2d/joints_2d_sw.h37
-rw-r--r--servers/physics_2d/physics_server_2d_sw.cpp331
-rw-r--r--servers/physics_2d/physics_server_2d_sw.h48
-rw-r--r--servers/physics_2d/physics_server_2d_wrap_mt.cpp2
-rw-r--r--servers/physics_2d/physics_server_2d_wrap_mt.h24
-rw-r--r--servers/physics_2d/shape_2d_sw.cpp87
-rw-r--r--servers/physics_2d/shape_2d_sw.h76
-rw-r--r--servers/physics_2d/space_2d_sw.cpp177
-rw-r--r--servers/physics_2d/space_2d_sw.h68
-rw-r--r--servers/physics_2d/step_2d_sw.cpp4
-rw-r--r--servers/physics_2d/step_2d_sw.h2
-rw-r--r--servers/physics_3d/area_3d_sw.cpp52
-rw-r--r--servers/physics_3d/area_3d_sw.h56
-rw-r--r--servers/physics_3d/area_pair_3d_sw.cpp69
-rw-r--r--servers/physics_3d/area_pair_3d_sw.h6
-rw-r--r--servers/physics_3d/body_3d_sw.cpp344
-rw-r--r--servers/physics_3d/body_3d_sw.h174
-rw-r--r--servers/physics_3d/body_direct_state_3d_sw.cpp190
-rw-r--r--servers/physics_3d/body_direct_state_3d_sw.h94
-rw-r--r--servers/physics_3d/body_pair_3d_sw.h20
-rw-r--r--servers/physics_3d/broad_phase_3d_bvh.cpp3
-rw-r--r--servers/physics_3d/broad_phase_3d_bvh.h8
-rw-r--r--servers/physics_3d/collision_object_3d_sw.cpp6
-rw-r--r--servers/physics_3d/collision_object_3d_sw.h18
-rw-r--r--servers/physics_3d/collision_solver_3d_sat.cpp49
-rw-r--r--servers/physics_3d/collision_solver_3d_sw.cpp117
-rw-r--r--servers/physics_3d/collision_solver_3d_sw.h12
-rw-r--r--servers/physics_3d/gjk_epa.cpp2
-rw-r--r--servers/physics_3d/joints/cone_twist_joint_3d_sw.cpp12
-rw-r--r--servers/physics_3d/joints/cone_twist_joint_3d_sw.h38
-rw-r--r--servers/physics_3d/joints/generic_6dof_joint_3d_sw.h79
-rw-r--r--servers/physics_3d/joints/hinge_joint_3d_sw.cpp30
-rw-r--r--servers/physics_3d/joints/hinge_joint_3d_sw.h36
-rw-r--r--servers/physics_3d/joints/jacobian_entry_3d_sw.h2
-rw-r--r--servers/physics_3d/joints/pin_joint_3d_sw.cpp5
-rw-r--r--servers/physics_3d/joints/pin_joint_3d_sw.h12
-rw-r--r--servers/physics_3d/joints/slider_joint_3d_sw.cpp37
-rw-r--r--servers/physics_3d/joints/slider_joint_3d_sw.h83
-rw-r--r--servers/physics_3d/physics_server_3d_sw.cpp423
-rw-r--r--servers/physics_3d/physics_server_3d_sw.h35
-rw-r--r--servers/physics_3d/physics_server_3d_wrap_mt.cpp3
-rw-r--r--servers/physics_3d/physics_server_3d_wrap_mt.h18
-rw-r--r--servers/physics_3d/shape_3d_sw.cpp556
-rw-r--r--servers/physics_3d/shape_3d_sw.h115
-rw-r--r--servers/physics_3d/soft_body_3d_sw.cpp142
-rw-r--r--servers/physics_3d/soft_body_3d_sw.h11
-rw-r--r--servers/physics_3d/space_3d_sw.cpp293
-rw-r--r--servers/physics_3d/space_3d_sw.h48
-rw-r--r--servers/physics_3d/step_3d_sw.cpp10
-rw-r--r--servers/physics_3d/step_3d_sw.h2
-rw-r--r--servers/physics_server_2d.cpp138
-rw-r--r--servers/physics_server_2d.h119
-rw-r--r--servers/physics_server_3d.cpp210
-rw-r--r--servers/physics_server_3d.h157
-rw-r--r--servers/register_server_types.cpp29
-rw-r--r--servers/rendering/rasterizer_dummy.h13
-rw-r--r--servers/rendering/renderer_canvas_cull.cpp234
-rw-r--r--servers/rendering/renderer_canvas_cull.h3
-rw-r--r--servers/rendering/renderer_canvas_render.h5
-rw-r--r--servers/rendering/renderer_compositor.h3
-rw-r--r--servers/rendering/renderer_rd/cluster_builder_rd.h2
-rw-r--r--servers/rendering/renderer_rd/effects_rd.cpp11
-rw-r--r--servers/rendering/renderer_rd/effects_rd.h5
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp20
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h2
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp44
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h1
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp40
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h3
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp44
-rw-r--r--servers/rendering/renderer_rd/pipeline_cache_rd.cpp6
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp79
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.h8
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.cpp28
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.h3
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp3
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_environment_rd.h3
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp35
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_gi_rd.h7
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp363
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.h79
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp99
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_sky_rd.h13
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.cpp1505
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.h103
-rw-r--r--servers/rendering/renderer_rd/shader_compiler_rd.cpp146
-rw-r--r--servers/rendering/renderer_rd/shader_compiler_rd.h2
-rw-r--r--servers/rendering/renderer_rd/shader_rd.cpp26
-rw-r--r--servers/rendering/renderer_rd/shader_rd.h2
-rw-r--r--servers/rendering/renderer_rd/shaders/blit.glsl6
-rw-r--r--servers/rendering/renderer_rd/shaders/blur_raster.glsl2
-rw-r--r--servers/rendering/renderer_rd/shaders/bokeh_dof_raster.glsl2
-rw-r--r--servers/rendering/renderer_rd/shaders/canvas.glsl37
-rw-r--r--servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl2
-rw-r--r--servers/rendering/renderer_rd/shaders/cluster_render.glsl2
-rw-r--r--servers/rendering/renderer_rd/shaders/cubemap_roughness_inc.glsl4
-rw-r--r--servers/rendering/renderer_rd/shaders/gi.glsl4
-rw-r--r--servers/rendering/renderer_rd/shaders/giprobe_write.glsl47
-rw-r--r--servers/rendering/renderer_rd/shaders/luminance_reduce_raster_inc.glsl2
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl17
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl2
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl16
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl21
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl2
-rw-r--r--servers/rendering/renderer_rd/shaders/sdfgi_debug_probes.glsl2
-rw-r--r--servers/rendering/renderer_rd/shaders/sky.glsl15
-rw-r--r--servers/rendering/renderer_rd/shaders/tonemap.glsl96
-rw-r--r--servers/rendering/renderer_rd/shaders/voxel_gi.glsl162
-rw-r--r--servers/rendering/renderer_rd/shaders/voxel_gi_debug.glsl5
-rw-r--r--servers/rendering/renderer_scene.h2
-rw-r--r--servers/rendering/renderer_scene_cull.cpp124
-rw-r--r--servers/rendering/renderer_scene_cull.h4
-rw-r--r--servers/rendering/renderer_scene_occlusion_cull.h24
-rw-r--r--servers/rendering/renderer_scene_render.cpp8
-rw-r--r--servers/rendering/renderer_scene_render.h2
-rw-r--r--servers/rendering/renderer_storage.cpp20
-rw-r--r--servers/rendering/renderer_viewport.cpp207
-rw-r--r--servers/rendering/renderer_viewport.h12
-rw-r--r--servers/rendering/rendering_device.cpp18
-rw-r--r--servers/rendering/rendering_device.h21
-rw-r--r--servers/rendering/rendering_device_binds.cpp6
-rw-r--r--servers/rendering/rendering_device_binds.h10
-rw-r--r--servers/rendering/rendering_server_default.cpp5
-rw-r--r--servers/rendering/rendering_server_default.h4
-rw-r--r--servers/rendering/shader_language.cpp1622
-rw-r--r--servers/rendering/shader_language.h20
-rw-r--r--servers/rendering/shader_warnings.cpp8
-rw-r--r--servers/rendering_server.cpp36
-rw-r--r--servers/rendering_server.h10
-rw-r--r--servers/text/SCsub5
-rw-r--r--servers/text/text_server_extension.cpp1281
-rw-r--r--servers/text/text_server_extension.h427
-rw-r--r--servers/text_server.cpp948
-rw-r--r--servers/text_server.h399
-rw-r--r--servers/xr/xr_interface.cpp72
-rw-r--r--servers/xr/xr_interface.h29
-rw-r--r--servers/xr/xr_interface_extension.cpp267
-rw-r--r--servers/xr/xr_interface_extension.h109
-rw-r--r--servers/xr_server.cpp22
-rw-r--r--servers/xr_server.h7
172 files changed, 10553 insertions, 5297 deletions
diff --git a/servers/SCsub b/servers/SCsub
index 121990f2e1..76c11724d3 100644
--- a/servers/SCsub
+++ b/servers/SCsub
@@ -11,6 +11,7 @@ SConscript("physics_3d/SCsub")
SConscript("physics_2d/SCsub")
SConscript("rendering/SCsub")
SConscript("audio/SCsub")
+SConscript("text/SCsub")
lib = env.add_library("servers", env.servers_sources)
diff --git a/servers/audio/audio_driver_dummy.cpp b/servers/audio/audio_driver_dummy.cpp
index a28dcb1015..47799dce96 100644
--- a/servers/audio/audio_driver_dummy.cpp
+++ b/servers/audio/audio_driver_dummy.cpp
@@ -46,7 +46,7 @@ Error AudioDriverDummy::init() {
int latency = GLOBAL_GET("audio/driver/output_latency");
buffer_frames = closest_power_of_2(latency * mix_rate / 1000);
- samples_in = memnew_arr(int32_t, buffer_frames * channels);
+ samples_in = memnew_arr(int32_t, (size_t)buffer_frames * channels);
thread.start(AudioDriverDummy::thread_func, this);
diff --git a/servers/audio/audio_rb_resampler.cpp b/servers/audio/audio_rb_resampler.cpp
index 3c8a1469cd..d9c442facf 100644
--- a/servers/audio/audio_rb_resampler.cpp
+++ b/servers/audio/audio_rb_resampler.cpp
@@ -176,8 +176,9 @@ Error AudioRBResampler::setup(int p_channels, int p_src_mix_rate, int p_target_m
rb_bits = desired_rb_bits;
rb_len = (1 << rb_bits);
rb_mask = rb_len - 1;
- rb = memnew_arr(float, rb_len *p_channels);
- read_buf = memnew_arr(float, rb_len *p_channels);
+ const size_t array_size = rb_len * (size_t)p_channels;
+ rb = memnew_arr(float, array_size);
+ read_buf = memnew_arr(float, array_size);
}
src_mix_rate = p_src_mix_rate;
diff --git a/servers/audio/audio_stream.cpp b/servers/audio/audio_stream.cpp
index f3fa857682..c098a97906 100644
--- a/servers/audio/audio_stream.cpp
+++ b/servers/audio/audio_stream.cpp
@@ -33,6 +33,65 @@
#include "core/config/project_settings.h"
#include "core/os/os.h"
+void AudioStreamPlayback::start(float p_from_pos) {
+ if (GDVIRTUAL_CALL(_start, p_from_pos)) {
+ return;
+ }
+ ERR_FAIL_MSG("AudioStreamPlayback::start unimplemented!");
+}
+void AudioStreamPlayback::stop() {
+ if (GDVIRTUAL_CALL(_stop)) {
+ return;
+ }
+ ERR_FAIL_MSG("AudioStreamPlayback::stop unimplemented!");
+}
+bool AudioStreamPlayback::is_playing() const {
+ bool ret;
+ if (GDVIRTUAL_CALL(_is_playing, ret)) {
+ return ret;
+ }
+ ERR_FAIL_V_MSG(false, "AudioStreamPlayback::is_playing unimplemented!");
+}
+
+int AudioStreamPlayback::get_loop_count() const {
+ int ret;
+ if (GDVIRTUAL_CALL(_get_loop_count, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+float AudioStreamPlayback::get_playback_position() const {
+ float ret;
+ if (GDVIRTUAL_CALL(_get_playback_position, ret)) {
+ return ret;
+ }
+ ERR_FAIL_V_MSG(0, "AudioStreamPlayback::get_playback_position unimplemented!");
+}
+void AudioStreamPlayback::seek(float p_time) {
+ if (GDVIRTUAL_CALL(_seek, p_time)) {
+ return;
+ }
+}
+
+int AudioStreamPlayback::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) {
+ int ret;
+ if (GDVIRTUAL_CALL(_mix, p_buffer, p_rate_scale, p_frames, ret)) {
+ return ret;
+ }
+ WARN_PRINT_ONCE("AudioStreamPlayback::mix unimplemented!");
+ return 0;
+}
+
+void AudioStreamPlayback::_bind_methods() {
+ GDVIRTUAL_BIND(_start, "from_pos")
+ GDVIRTUAL_BIND(_stop)
+ GDVIRTUAL_BIND(_is_playing)
+ GDVIRTUAL_BIND(_get_loop_count)
+ GDVIRTUAL_BIND(_get_playback_position)
+ GDVIRTUAL_BIND(_seek, "position")
+ GDVIRTUAL_BIND(_mix, "buffer", "rate_scale", "frames");
+}
//////////////////////////////
void AudioStreamPlaybackResampled::_begin_resample() {
@@ -46,12 +105,14 @@ void AudioStreamPlaybackResampled::_begin_resample() {
mix_offset = 0;
}
-void AudioStreamPlaybackResampled::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) {
+int AudioStreamPlaybackResampled::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) {
float target_rate = AudioServer::get_singleton()->get_mix_rate();
float playback_speed_scale = AudioServer::get_singleton()->get_playback_speed_scale();
uint64_t mix_increment = uint64_t(((get_stream_sampling_rate() * p_rate_scale * playback_speed_scale) / double(target_rate)) * double(FP_LEN));
+ int mixed_frames_total = p_frames;
+
for (int i = 0; i < p_frames; i++) {
uint32_t idx = CUBIC_INTERP_HISTORY + uint32_t(mix_offset >> FP_BITS);
//standard cubic interpolation (great quality/performance ratio)
@@ -62,6 +123,11 @@ void AudioStreamPlaybackResampled::mix(AudioFrame *p_buffer, float p_rate_scale,
AudioFrame y2 = internal_buffer[idx - 1];
AudioFrame y3 = internal_buffer[idx - 0];
+ if (idx <= internal_buffer_end && idx >= internal_buffer_end && mixed_frames_total == p_frames) {
+ // The internal buffer ends somewhere in this range, and we haven't yet recorded the number of good frames we have.
+ mixed_frames_total = i;
+ }
+
float mu2 = mu * mu;
AudioFrame a0 = 3 * y1 - 3 * y2 + y3 - y0;
AudioFrame a1 = 2 * y0 - 5 * y1 + 4 * y2 - y3;
@@ -78,7 +144,14 @@ void AudioStreamPlaybackResampled::mix(AudioFrame *p_buffer, float p_rate_scale,
internal_buffer[2] = internal_buffer[INTERNAL_BUFFER_LEN + 2];
internal_buffer[3] = internal_buffer[INTERNAL_BUFFER_LEN + 3];
if (is_playing()) {
- _mix_internal(internal_buffer + 4, INTERNAL_BUFFER_LEN);
+ int mixed_frames = _mix_internal(internal_buffer + 4, INTERNAL_BUFFER_LEN);
+ if (mixed_frames != INTERNAL_BUFFER_LEN) {
+ // internal_buffer[mixed_frames] is the first frame of silence.
+ internal_buffer_end = mixed_frames;
+ } else {
+ // The internal buffer does not contain the first frame of silence.
+ internal_buffer_end = -1;
+ }
} else {
//fill with silence, not playing
for (int j = 0; j < INTERNAL_BUFFER_LEN; ++j) {
@@ -88,12 +161,49 @@ void AudioStreamPlaybackResampled::mix(AudioFrame *p_buffer, float p_rate_scale,
mix_offset -= (INTERNAL_BUFFER_LEN << FP_BITS);
}
}
+ return mixed_frames_total;
}
////////////////////////////////
+Ref<AudioStreamPlayback> AudioStream::instance_playback() {
+ Ref<AudioStreamPlayback> ret;
+ if (GDVIRTUAL_CALL(_instance_playback, ret)) {
+ return ret;
+ }
+ ERR_FAIL_V_MSG(Ref<AudioStreamPlayback>(), "Method must be implemented!");
+}
+String AudioStream::get_stream_name() const {
+ String ret;
+ if (GDVIRTUAL_CALL(_get_stream_name, ret)) {
+ return ret;
+ }
+ return String();
+}
+
+float AudioStream::get_length() const {
+ float ret;
+ if (GDVIRTUAL_CALL(_get_length, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+bool AudioStream::is_monophonic() const {
+ bool ret;
+ if (GDVIRTUAL_CALL(_is_monophonic, ret)) {
+ return ret;
+ }
+ return true;
+}
+
void AudioStream::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_length"), &AudioStream::get_length);
+ ClassDB::bind_method(D_METHOD("is_monophonic"), &AudioStream::is_monophonic);
+ GDVIRTUAL_BIND(_instance_playback);
+ GDVIRTUAL_BIND(_get_stream_name);
+ GDVIRTUAL_BIND(_get_length);
+ GDVIRTUAL_BIND(_is_monophonic);
}
////////////////////////////////
@@ -121,13 +231,17 @@ float AudioStreamMicrophone::get_length() const {
return 0;
}
+bool AudioStreamMicrophone::is_monophonic() const {
+ return true;
+}
+
void AudioStreamMicrophone::_bind_methods() {
}
AudioStreamMicrophone::AudioStreamMicrophone() {
}
-void AudioStreamPlaybackMicrophone::_mix_internal(AudioFrame *p_buffer, int p_frames) {
+int AudioStreamPlaybackMicrophone::_mix_internal(AudioFrame *p_buffer, int p_frames) {
AudioDriver::get_singleton()->lock();
Vector<int32_t> buf = AudioDriver::get_singleton()->get_input_buffer();
@@ -138,6 +252,8 @@ void AudioStreamPlaybackMicrophone::_mix_internal(AudioFrame *p_buffer, int p_fr
unsigned int input_position = AudioDriver::get_singleton()->get_input_position();
#endif
+ int mixed_frames = p_frames;
+
if (playback_delay > input_size) {
for (int i = 0; i < p_frames; i++) {
p_buffer[i] = AudioFrame(0.0f, 0.0f);
@@ -157,6 +273,9 @@ void AudioStreamPlaybackMicrophone::_mix_internal(AudioFrame *p_buffer, int p_fr
p_buffer[i] = AudioFrame(l, r);
} else {
+ if (mixed_frames == p_frames) {
+ mixed_frames = i;
+ }
p_buffer[i] = AudioFrame(0.0f, 0.0f);
}
}
@@ -169,10 +288,12 @@ void AudioStreamPlaybackMicrophone::_mix_internal(AudioFrame *p_buffer, int p_fr
#endif
AudioDriver::get_singleton()->unlock();
+
+ return mixed_frames;
}
-void AudioStreamPlaybackMicrophone::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) {
- AudioStreamPlaybackResampled::mix(p_buffer, p_rate_scale, p_frames);
+int AudioStreamPlaybackMicrophone::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) {
+ return AudioStreamPlaybackResampled::mix(p_buffer, p_rate_scale, p_frames);
}
float AudioStreamPlaybackMicrophone::get_stream_sampling_rate() {
@@ -281,6 +402,14 @@ float AudioStreamRandomPitch::get_length() const {
return 0;
}
+bool AudioStreamRandomPitch::is_monophonic() const {
+ if (audio_stream.is_valid()) {
+ return audio_stream->is_monophonic();
+ }
+
+ return true; // It doesn't really matter what we return here, but no sense instancing a many playbacks of a null stream.
+}
+
void AudioStreamRandomPitch::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_audio_stream", "stream"), &AudioStreamRandomPitch::set_audio_stream);
ClassDB::bind_method(D_METHOD("get_audio_stream"), &AudioStreamRandomPitch::get_audio_stream);
@@ -345,16 +474,18 @@ void AudioStreamPlaybackRandomPitch::seek(float p_time) {
}
}
-void AudioStreamPlaybackRandomPitch::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) {
+int AudioStreamPlaybackRandomPitch::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) {
if (playing.is_valid()) {
- playing->mix(p_buffer, p_rate_scale * pitch_scale, p_frames);
+ return playing->mix(p_buffer, p_rate_scale * pitch_scale, p_frames);
} else {
for (int i = 0; i < p_frames; i++) {
p_buffer[i] = AudioFrame(0, 0);
}
+ return p_frames;
}
}
AudioStreamPlaybackRandomPitch::~AudioStreamPlaybackRandomPitch() {
random_pitch->playbacks.erase(this);
}
+/////////////////////////////////////////////
diff --git a/servers/audio/audio_stream.h b/servers/audio/audio_stream.h
index 0d426f99b2..12d4343f5c 100644
--- a/servers/audio/audio_stream.h
+++ b/servers/audio/audio_stream.h
@@ -36,20 +36,33 @@
#include "servers/audio/audio_filter_sw.h"
#include "servers/audio_server.h"
+#include "core/object/gdvirtual.gen.inc"
+#include "core/object/script_language.h"
+#include "core/variant/native_ptr.h"
+
class AudioStreamPlayback : public RefCounted {
GDCLASS(AudioStreamPlayback, RefCounted);
+protected:
+ static void _bind_methods();
+ GDVIRTUAL1(_start, float)
+ GDVIRTUAL0(_stop)
+ GDVIRTUAL0RC(bool, _is_playing)
+ GDVIRTUAL0RC(int, _get_loop_count)
+ GDVIRTUAL0RC(float, _get_playback_position)
+ GDVIRTUAL1(_seek, float)
+ GDVIRTUAL3R(int, _mix, GDNativePtr<AudioFrame>, float, int)
public:
- virtual void start(float p_from_pos = 0.0) = 0;
- virtual void stop() = 0;
- virtual bool is_playing() const = 0;
+ virtual void start(float p_from_pos = 0.0);
+ virtual void stop();
+ virtual bool is_playing() const;
- virtual int get_loop_count() const = 0; //times it looped
+ virtual int get_loop_count() const; //times it looped
- virtual float get_playback_position() const = 0;
- virtual void seek(float p_time) = 0;
+ virtual float get_playback_position() const;
+ virtual void seek(float p_time);
- virtual void mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) = 0;
+ virtual int mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames);
};
class AudioStreamPlaybackResampled : public AudioStreamPlayback {
@@ -64,15 +77,17 @@ class AudioStreamPlaybackResampled : public AudioStreamPlayback {
};
AudioFrame internal_buffer[INTERNAL_BUFFER_LEN + CUBIC_INTERP_HISTORY];
+ unsigned int internal_buffer_end = -1;
uint64_t mix_offset;
protected:
void _begin_resample();
- virtual void _mix_internal(AudioFrame *p_buffer, int p_frames) = 0;
+ // Returns the number of frames that were mixed.
+ virtual int _mix_internal(AudioFrame *p_buffer, int p_frames) = 0;
virtual float get_stream_sampling_rate() = 0;
public:
- virtual void mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) override;
+ virtual int mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) override;
AudioStreamPlaybackResampled() { mix_offset = 0; }
};
@@ -84,11 +99,17 @@ class AudioStream : public Resource {
protected:
static void _bind_methods();
+ GDVIRTUAL0RC(Ref<AudioStreamPlayback>, _instance_playback)
+ GDVIRTUAL0RC(String, _get_stream_name)
+ GDVIRTUAL0RC(float, _get_length)
+ GDVIRTUAL0RC(bool, _is_monophonic)
+
public:
- virtual Ref<AudioStreamPlayback> instance_playback() = 0;
- virtual String get_stream_name() const = 0;
+ virtual Ref<AudioStreamPlayback> instance_playback();
+ virtual String get_stream_name() const;
- virtual float get_length() const = 0; //if supported, otherwise return 0
+ virtual float get_length() const;
+ virtual bool is_monophonic() const;
};
// Microphone
@@ -110,6 +131,8 @@ public:
virtual float get_length() const override; //if supported, otherwise return 0
+ virtual bool is_monophonic() const override;
+
AudioStreamMicrophone();
};
@@ -123,11 +146,11 @@ class AudioStreamPlaybackMicrophone : public AudioStreamPlaybackResampled {
Ref<AudioStreamMicrophone> microphone;
protected:
- virtual void _mix_internal(AudioFrame *p_buffer, int p_frames) override;
+ virtual int _mix_internal(AudioFrame *p_buffer, int p_frames) override;
virtual float get_stream_sampling_rate() override;
public:
- virtual void mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) override;
+ virtual int mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) override;
virtual void start(float p_from_pos = 0.0) override;
virtual void stop() override;
@@ -168,6 +191,7 @@ public:
virtual String get_stream_name() const override;
virtual float get_length() const override; //if supported, otherwise return 0
+ virtual bool is_monophonic() const override;
AudioStreamRandomPitch();
};
@@ -191,7 +215,7 @@ public:
virtual float get_playback_position() const override;
virtual void seek(float p_time) override;
- virtual void mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) override;
+ virtual int mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) override;
~AudioStreamPlaybackRandomPitch();
};
diff --git a/servers/audio/effects/audio_effect_capture.h b/servers/audio/effects/audio_effect_capture.h
index 7f50fc4965..bb1d03be8c 100644
--- a/servers/audio/effects/audio_effect_capture.h
+++ b/servers/audio/effects/audio_effect_capture.h
@@ -34,6 +34,7 @@
#include "core/config/engine.h"
#include "core/math/audio_frame.h"
#include "core/object/ref_counted.h"
+#include "core/templates/ring_buffer.h"
#include "core/templates/vector.h"
#include "servers/audio/audio_effect.h"
#include "servers/audio_server.h"
diff --git a/servers/audio/effects/audio_effect_pitch_shift.cpp b/servers/audio/effects/audio_effect_pitch_shift.cpp
index bfbaeee3f3..d6c396e0a5 100644
--- a/servers/audio/effects/audio_effect_pitch_shift.cpp
+++ b/servers/audio/effects/audio_effect_pitch_shift.cpp
@@ -40,7 +40,7 @@
*
* NAME: smbPitchShift.cpp
* VERSION: 1.2
-* HOME URL: http://blogs.zynaptiq.com/bernsee
+* HOME URL: https://blogs.zynaptiq.com/bernsee
* KNOWN BUGS: none
*
* SYNOPSIS: Routine for doing pitch shifting while maintaining
diff --git a/servers/audio/effects/audio_stream_generator.cpp b/servers/audio/effects/audio_stream_generator.cpp
index bced2997ce..447acf53a4 100644
--- a/servers/audio/effects/audio_stream_generator.cpp
+++ b/servers/audio/effects/audio_stream_generator.cpp
@@ -64,6 +64,10 @@ float AudioStreamGenerator::get_length() const {
return 0;
}
+bool AudioStreamGenerator::is_monophonic() const {
+ return true;
+}
+
void AudioStreamGenerator::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_mix_rate", "hz"), &AudioStreamGenerator::set_mix_rate);
ClassDB::bind_method(D_METHOD("get_mix_rate"), &AudioStreamGenerator::get_mix_rate);
@@ -138,7 +142,7 @@ void AudioStreamGeneratorPlayback::clear_buffer() {
mixed = 0;
}
-void AudioStreamGeneratorPlayback::_mix_internal(AudioFrame *p_buffer, int p_frames) {
+int AudioStreamGeneratorPlayback::_mix_internal(AudioFrame *p_buffer, int p_frames) {
int read_amount = buffer.data_left();
if (p_frames < read_amount) {
read_amount = p_frames;
@@ -156,6 +160,7 @@ void AudioStreamGeneratorPlayback::_mix_internal(AudioFrame *p_buffer, int p_fra
}
mixed += p_frames / generator->get_mix_rate();
+ return read_amount < p_frames ? read_amount : p_frames;
}
float AudioStreamGeneratorPlayback::get_stream_sampling_rate() {
diff --git a/servers/audio/effects/audio_stream_generator.h b/servers/audio/effects/audio_stream_generator.h
index 5d46771f4d..918589f6d0 100644
--- a/servers/audio/effects/audio_stream_generator.h
+++ b/servers/audio/effects/audio_stream_generator.h
@@ -54,6 +54,7 @@ public:
virtual String get_stream_name() const override;
virtual float get_length() const override;
+ virtual bool is_monophonic() const override;
AudioStreamGenerator();
};
@@ -67,7 +68,7 @@ class AudioStreamGeneratorPlayback : public AudioStreamPlaybackResampled {
AudioStreamGenerator *generator;
protected:
- virtual void _mix_internal(AudioFrame *p_buffer, int p_frames) override;
+ virtual int _mix_internal(AudioFrame *p_buffer, int p_frames) override;
virtual float get_stream_sampling_rate() override;
static void _bind_methods();
diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp
index 4c54188cb2..a420134626 100644
--- a/servers/audio_server.cpp
+++ b/servers/audio_server.cpp
@@ -32,13 +32,19 @@
#include "core/config/project_settings.h"
#include "core/debugger/engine_debugger.h"
+#include "core/error/error_macros.h"
#include "core/io/file_access.h"
#include "core/io/resource_loader.h"
+#include "core/math/audio_frame.h"
#include "core/os/os.h"
+#include "core/string/string_name.h"
+#include "core/templates/pair.h"
#include "scene/resources/audio_stream_sample.h"
#include "servers/audio/audio_driver_dummy.h"
#include "servers/audio/effects/audio_effect_compressor.h"
+#include <cstring>
+
#ifdef TOOLS_ENABLED
#define MARK_EDITED set_edited(true);
#else
@@ -190,6 +196,7 @@ int AudioDriverManager::get_driver_count() {
void AudioDriverManager::initialize(int p_driver) {
GLOBAL_DEF_RST("audio/driver/enable_input", false);
GLOBAL_DEF_RST("audio/driver/mix_rate", DEFAULT_MIX_RATE);
+ GLOBAL_DEF_RST("audio/driver/mix_rate.web", 0); // Safer default output_latency for web (use browser default).
GLOBAL_DEF_RST("audio/driver/output_latency", DEFAULT_OUTPUT_LATENCY);
GLOBAL_DEF_RST("audio/driver/output_latency.web", 50); // Safer default output_latency for web.
@@ -234,6 +241,7 @@ AudioDriver *AudioDriverManager::get_driver(int p_driver) {
//////////////////////////////////////////////
void AudioServer::_driver_process(int p_frames, int32_t *p_buffer) {
+ mix_count++;
int todo = p_frames;
#ifdef DEBUG_ENABLED
@@ -331,10 +339,144 @@ void AudioServer::_mix_step() {
bus->soloed = false;
}
}
+ for (CallbackItem *ci : mix_callback_list) {
+ ci->callback(ci->userdata);
+ }
+
+ for (AudioStreamPlaybackListNode *playback : playback_list) {
+ // Paused streams are no-ops. Don't even mix audio from the stream playback.
+ if (playback->state.load() == AudioStreamPlaybackListNode::PAUSED) {
+ continue;
+ }
+
+ bool fading_out = playback->state.load() == AudioStreamPlaybackListNode::FADE_OUT_TO_DELETION || playback->state.load() == AudioStreamPlaybackListNode::FADE_OUT_TO_PAUSE;
- //make callbacks for mixing the audio
- for (Set<CallbackItem>::Element *E = callbacks.front(); E; E = E->next()) {
- E->get().callback(E->get().userdata);
+ AudioFrame *buf = mix_buffer.ptrw();
+
+ // Copy the lookeahead buffer into the mix buffer.
+ for (int i = 0; i < LOOKAHEAD_BUFFER_SIZE; i++) {
+ buf[i] = playback->lookahead[i];
+ }
+
+ // Mix the audio stream
+ unsigned int mixed_frames = playback->stream_playback->mix(&buf[LOOKAHEAD_BUFFER_SIZE], playback->pitch_scale.get(), buffer_size);
+
+ if (mixed_frames != buffer_size) {
+ // We know we have at least the size of our lookahead buffer for fade-out purposes.
+
+ float fadeout_base = 0.94;
+ float fadeout_coefficient = 1;
+ static_assert(LOOKAHEAD_BUFFER_SIZE == 64, "Update fadeout_base and comment here if you change LOOKAHEAD_BUFFER_SIZE.");
+ // 0.94 ^ 64 = 0.01906. There might still be a pop but it'll be way better than if we didn't do this.
+ for (unsigned int idx = mixed_frames; idx < buffer_size; idx++) {
+ fadeout_coefficient *= fadeout_base;
+ buf[idx] *= fadeout_coefficient;
+ }
+ AudioStreamPlaybackListNode::PlaybackState new_state;
+ new_state = AudioStreamPlaybackListNode::AWAITING_DELETION;
+ playback->state.store(new_state);
+ } else {
+ // Move the last little bit of what we just mixed into our lookahead buffer.
+ for (int i = 0; i < LOOKAHEAD_BUFFER_SIZE; i++) {
+ playback->lookahead[i] = buf[buffer_size + i];
+ }
+ }
+
+ AudioStreamPlaybackBusDetails *ptr = playback->bus_details.load();
+ ERR_FAIL_COND(ptr == nullptr);
+ // By putting null into the bus details pointers, we're taking ownership of their memory for the duration of this mix.
+ AudioStreamPlaybackBusDetails bus_details = *ptr;
+
+ // Mix to any active buses.
+ for (int idx = 0; idx < MAX_BUSES_PER_PLAYBACK; idx++) {
+ if (!bus_details.bus_active[idx]) {
+ continue;
+ }
+ int bus_idx = thread_find_bus_index(bus_details.bus[idx]);
+
+ int prev_bus_idx = -1;
+ for (int search_idx = 0; search_idx < MAX_BUSES_PER_PLAYBACK; search_idx++) {
+ if (!playback->prev_bus_details->bus_active[search_idx]) {
+ continue;
+ }
+ if (playback->prev_bus_details->bus[search_idx].hash() == bus_details.bus[idx].hash()) {
+ prev_bus_idx = search_idx;
+ }
+ }
+
+ for (int channel_idx = 0; channel_idx < channel_count; channel_idx++) {
+ AudioFrame *channel_buf = thread_get_channel_mix_buffer(bus_idx, channel_idx);
+ if (fading_out) {
+ bus_details.volume[idx][channel_idx] = AudioFrame(0, 0);
+ }
+ AudioFrame channel_vol = bus_details.volume[idx][channel_idx];
+
+ AudioFrame prev_channel_vol = AudioFrame(0, 0);
+ if (prev_bus_idx != -1) {
+ prev_channel_vol = playback->prev_bus_details->volume[prev_bus_idx][channel_idx];
+ }
+ _mix_step_for_channel(channel_buf, buf, prev_channel_vol, channel_vol, playback->attenuation_filter_cutoff_hz.get(), playback->highshelf_gain.get(), &playback->filter_process[channel_idx * 2], &playback->filter_process[channel_idx * 2 + 1]);
+ }
+ }
+
+ // Now go through and fade-out any buses that were being played to previously that we missed by going through current data.
+ for (int idx = 0; idx < MAX_BUSES_PER_PLAYBACK; idx++) {
+ if (!playback->prev_bus_details->bus_active[idx]) {
+ continue;
+ }
+ int bus_idx = thread_find_bus_index(playback->prev_bus_details->bus[idx]);
+
+ int current_bus_idx = -1;
+ for (int search_idx = 0; search_idx < MAX_BUSES_PER_PLAYBACK; search_idx++) {
+ if (bus_details.bus[search_idx] == playback->prev_bus_details->bus[idx]) {
+ current_bus_idx = search_idx;
+ }
+ }
+ if (current_bus_idx != -1) {
+ // If we found a corresponding bus in the current bus assignments, we've already mixed to this bus.
+ continue;
+ }
+
+ for (int channel_idx = 0; channel_idx < channel_count; channel_idx++) {
+ AudioFrame *channel_buf = thread_get_channel_mix_buffer(bus_idx, channel_idx);
+ AudioFrame prev_channel_vol = playback->prev_bus_details->volume[idx][channel_idx];
+ // Fade out to silence
+ _mix_step_for_channel(channel_buf, buf, prev_channel_vol, AudioFrame(0, 0), playback->attenuation_filter_cutoff_hz.get(), playback->highshelf_gain.get(), &playback->filter_process[channel_idx * 2], &playback->filter_process[channel_idx * 2 + 1]);
+ }
+ }
+
+ // Copy the bus details we mixed with to the previous bus details to maintain volume ramps.
+ std::copy(std::begin(bus_details.bus_active), std::end(bus_details.bus_active), std::begin(playback->prev_bus_details->bus_active));
+ std::copy(std::begin(bus_details.bus), std::end(bus_details.bus), std::begin(playback->prev_bus_details->bus));
+ for (int bus_idx = 0; bus_idx < MAX_BUSES_PER_PLAYBACK; bus_idx++) {
+ std::copy(std::begin(bus_details.volume[bus_idx]), std::end(bus_details.volume[bus_idx]), std::begin(playback->prev_bus_details->volume[bus_idx]));
+ }
+
+ switch (playback->state.load()) {
+ case AudioStreamPlaybackListNode::AWAITING_DELETION:
+ case AudioStreamPlaybackListNode::FADE_OUT_TO_DELETION:
+ playback_list.erase(playback, [](AudioStreamPlaybackListNode *p) {
+ if (p->prev_bus_details)
+ delete p->prev_bus_details;
+ if (p->bus_details)
+ delete p->bus_details;
+ p->stream_playback.unref();
+ delete p;
+ });
+ break;
+ case AudioStreamPlaybackListNode::FADE_OUT_TO_PAUSE: {
+ // Pause the stream.
+ AudioStreamPlaybackListNode::PlaybackState old_state, new_state;
+ do {
+ old_state = playback->state.load();
+ new_state = AudioStreamPlaybackListNode::PAUSED;
+ } while (!playback->state.compare_exchange_strong(/* expected= */ old_state, new_state));
+ } break;
+ case AudioStreamPlaybackListNode::PLAYING:
+ case AudioStreamPlaybackListNode::PAUSED:
+ // No-op!
+ break;
+ }
}
for (int i = buses.size() - 1; i >= 0; i--) {
@@ -464,6 +606,53 @@ void AudioServer::_mix_step() {
to_mix = buffer_size;
}
+void AudioServer::_mix_step_for_channel(AudioFrame *p_out_buf, AudioFrame *p_source_buf, AudioFrame p_vol_start, AudioFrame p_vol_final, float p_attenuation_filter_cutoff_hz, float p_highshelf_gain, AudioFilterSW::Processor *p_processor_l, AudioFilterSW::Processor *p_processor_r) {
+ if (p_highshelf_gain != 0) {
+ AudioFilterSW filter;
+ filter.set_mode(AudioFilterSW::HIGHSHELF);
+ filter.set_sampling_rate(AudioServer::get_singleton()->get_mix_rate());
+ filter.set_cutoff(p_attenuation_filter_cutoff_hz);
+ filter.set_resonance(1);
+ filter.set_stages(1);
+ filter.set_gain(p_highshelf_gain);
+
+ ERR_FAIL_COND(p_processor_l == nullptr);
+ ERR_FAIL_COND(p_processor_r == nullptr);
+
+ bool is_just_started = p_vol_start.l == 0 && p_vol_start.r == 0;
+ p_processor_l->set_filter(&filter, /* clear_history= */ is_just_started);
+ p_processor_l->update_coeffs(buffer_size);
+ p_processor_r->set_filter(&filter, /* clear_history= */ is_just_started);
+ p_processor_r->update_coeffs(buffer_size);
+
+ for (unsigned int frame_idx = 0; frame_idx < buffer_size; frame_idx++) {
+ // Make this buffer size invariant if buffer_size ever becomes a project setting.
+ float lerp_param = (float)frame_idx / buffer_size;
+ AudioFrame vol = p_vol_final * lerp_param + (1 - lerp_param) * p_vol_start;
+ AudioFrame mixed = vol * p_source_buf[frame_idx];
+ p_processor_l->process_one_interp(mixed.l);
+ p_processor_r->process_one_interp(mixed.r);
+ p_out_buf[frame_idx] += mixed;
+ }
+
+ } else {
+ for (unsigned int frame_idx = 0; frame_idx < buffer_size; frame_idx++) {
+ // Make this buffer size invariant if buffer_size ever becomes a project setting.
+ float lerp_param = (float)frame_idx / buffer_size;
+ p_out_buf[frame_idx] += (p_vol_final * lerp_param + (1 - lerp_param) * p_vol_start) * p_source_buf[frame_idx];
+ }
+ }
+}
+
+AudioServer::AudioStreamPlaybackListNode *AudioServer::_find_playback_list_node(Ref<AudioStreamPlayback> p_playback) {
+ for (AudioStreamPlaybackListNode *playback_list_node : playback_list) {
+ if (playback_list_node->stream_playback == p_playback) {
+ return playback_list_node;
+ }
+ }
+ return nullptr;
+}
+
bool AudioServer::thread_has_channel_mix_buffer(int p_bus, int p_buffer) const {
if (p_bus < 0 || p_bus >= buses.size()) {
return false;
@@ -923,9 +1112,223 @@ float AudioServer::get_playback_speed_scale() const {
return playback_speed_scale;
}
+void AudioServer::start_playback_stream(Ref<AudioStreamPlayback> p_playback, StringName p_bus, Vector<AudioFrame> p_volume_db_vector, float p_start_time, float p_pitch_scale) {
+ ERR_FAIL_COND(p_playback.is_null());
+
+ Map<StringName, Vector<AudioFrame>> map;
+ map[p_bus] = p_volume_db_vector;
+
+ start_playback_stream(p_playback, map, p_start_time, p_pitch_scale);
+}
+
+void AudioServer::start_playback_stream(Ref<AudioStreamPlayback> p_playback, Map<StringName, Vector<AudioFrame>> p_bus_volumes, float p_start_time, float p_pitch_scale, float p_highshelf_gain, float p_attenuation_cutoff_hz) {
+ ERR_FAIL_COND(p_playback.is_null());
+
+ AudioStreamPlaybackListNode *playback_node = new AudioStreamPlaybackListNode();
+ playback_node->stream_playback = p_playback;
+ playback_node->stream_playback->start(p_start_time);
+
+ AudioStreamPlaybackBusDetails *new_bus_details = new AudioStreamPlaybackBusDetails();
+ int idx = 0;
+ for (KeyValue<StringName, Vector<AudioFrame>> pair : p_bus_volumes) {
+ ERR_FAIL_COND(pair.value.size() < channel_count);
+ ERR_FAIL_COND(pair.value.size() != MAX_CHANNELS_PER_BUS);
+
+ new_bus_details->bus_active[idx] = true;
+ new_bus_details->bus[idx] = pair.key;
+ for (int channel_idx = 0; channel_idx < MAX_CHANNELS_PER_BUS; channel_idx++) {
+ new_bus_details->volume[idx][channel_idx] = pair.value[channel_idx];
+ }
+ }
+ playback_node->bus_details = new_bus_details;
+ playback_node->prev_bus_details = new AudioStreamPlaybackBusDetails();
+
+ playback_node->pitch_scale.set(p_pitch_scale);
+ playback_node->highshelf_gain.set(p_highshelf_gain);
+ playback_node->attenuation_filter_cutoff_hz.set(p_attenuation_cutoff_hz);
+
+ memset(playback_node->prev_bus_details->volume, 0, sizeof(playback_node->prev_bus_details->volume));
+
+ for (AudioFrame &frame : playback_node->lookahead) {
+ frame = AudioFrame(0, 0);
+ }
+
+ playback_node->state.store(AudioStreamPlaybackListNode::PLAYING);
+
+ playback_list.insert(playback_node);
+}
+
+void AudioServer::stop_playback_stream(Ref<AudioStreamPlayback> p_playback) {
+ ERR_FAIL_COND(p_playback.is_null());
+
+ AudioStreamPlaybackListNode *playback_node = _find_playback_list_node(p_playback);
+ if (!playback_node) {
+ return;
+ }
+
+ AudioStreamPlaybackListNode::PlaybackState new_state, old_state;
+ do {
+ old_state = playback_node->state.load();
+ if (old_state == AudioStreamPlaybackListNode::AWAITING_DELETION) {
+ break; // Don't fade out again.
+ }
+ new_state = AudioStreamPlaybackListNode::FADE_OUT_TO_DELETION;
+
+ } while (!playback_node->state.compare_exchange_strong(old_state, new_state));
+}
+
+void AudioServer::set_playback_bus_exclusive(Ref<AudioStreamPlayback> p_playback, StringName p_bus, Vector<AudioFrame> p_volumes) {
+ ERR_FAIL_COND(p_volumes.size() != MAX_CHANNELS_PER_BUS);
+
+ Map<StringName, Vector<AudioFrame>> map;
+ map[p_bus] = p_volumes;
+
+ set_playback_bus_volumes_linear(p_playback, map);
+}
+
+void AudioServer::set_playback_bus_volumes_linear(Ref<AudioStreamPlayback> p_playback, Map<StringName, Vector<AudioFrame>> p_bus_volumes) {
+ ERR_FAIL_COND(p_bus_volumes.size() > MAX_BUSES_PER_PLAYBACK);
+
+ AudioStreamPlaybackListNode *playback_node = _find_playback_list_node(p_playback);
+ if (!playback_node) {
+ return;
+ }
+ AudioStreamPlaybackBusDetails *old_bus_details, *new_bus_details = new AudioStreamPlaybackBusDetails();
+
+ int idx = 0;
+ for (KeyValue<StringName, Vector<AudioFrame>> pair : p_bus_volumes) {
+ if (idx >= MAX_BUSES_PER_PLAYBACK) {
+ break;
+ }
+ ERR_FAIL_COND(pair.value.size() < channel_count);
+ ERR_FAIL_COND(pair.value.size() != MAX_CHANNELS_PER_BUS);
+
+ new_bus_details->bus_active[idx] = true;
+ new_bus_details->bus[idx] = pair.key;
+ for (int channel_idx = 0; channel_idx < MAX_CHANNELS_PER_BUS; channel_idx++) {
+ new_bus_details->volume[idx][channel_idx] = pair.value[channel_idx];
+ }
+ idx++;
+ }
+
+ do {
+ old_bus_details = playback_node->bus_details.load();
+ } while (!playback_node->bus_details.compare_exchange_strong(old_bus_details, new_bus_details));
+
+ bus_details_graveyard.insert(old_bus_details);
+}
+
+void AudioServer::set_playback_all_bus_volumes_linear(Ref<AudioStreamPlayback> p_playback, Vector<AudioFrame> p_volumes) {
+ ERR_FAIL_COND(p_playback.is_null());
+ ERR_FAIL_COND(p_volumes.size() != MAX_CHANNELS_PER_BUS);
+
+ Map<StringName, Vector<AudioFrame>> map;
+
+ AudioStreamPlaybackListNode *playback_node = _find_playback_list_node(p_playback);
+ if (!playback_node) {
+ return;
+ }
+ for (int bus_idx = 0; bus_idx < MAX_BUSES_PER_PLAYBACK; bus_idx++) {
+ if (playback_node->bus_details.load()->bus_active[bus_idx]) {
+ map[playback_node->bus_details.load()->bus[bus_idx]] = p_volumes;
+ }
+ }
+
+ set_playback_bus_volumes_linear(p_playback, map);
+}
+
+void AudioServer::set_playback_pitch_scale(Ref<AudioStreamPlayback> p_playback, float p_pitch_scale) {
+ ERR_FAIL_COND(p_playback.is_null());
+
+ AudioStreamPlaybackListNode *playback_node = _find_playback_list_node(p_playback);
+ if (!playback_node) {
+ return;
+ }
+
+ playback_node->pitch_scale.set(p_pitch_scale);
+}
+
+void AudioServer::set_playback_paused(Ref<AudioStreamPlayback> p_playback, bool p_paused) {
+ ERR_FAIL_COND(p_playback.is_null());
+
+ AudioStreamPlaybackListNode *playback_node = _find_playback_list_node(p_playback);
+ if (!playback_node) {
+ return;
+ }
+
+ AudioStreamPlaybackListNode::PlaybackState new_state, old_state;
+ do {
+ old_state = playback_node->state.load();
+ new_state = p_paused ? AudioStreamPlaybackListNode::FADE_OUT_TO_PAUSE : AudioStreamPlaybackListNode::PLAYING;
+ if (!p_paused && old_state == AudioStreamPlaybackListNode::PLAYING) {
+ return; // No-op.
+ }
+ if (p_paused && (old_state == AudioStreamPlaybackListNode::PAUSED || old_state == AudioStreamPlaybackListNode::FADE_OUT_TO_PAUSE)) {
+ return; // No-op.
+ }
+
+ } while (!playback_node->state.compare_exchange_strong(old_state, new_state));
+}
+
+void AudioServer::set_playback_highshelf_params(Ref<AudioStreamPlayback> p_playback, float p_gain, float p_attenuation_cutoff_hz) {
+ ERR_FAIL_COND(p_playback.is_null());
+
+ AudioStreamPlaybackListNode *playback_node = _find_playback_list_node(p_playback);
+ if (!playback_node) {
+ return;
+ }
+
+ playback_node->attenuation_filter_cutoff_hz.set(p_attenuation_cutoff_hz);
+ playback_node->highshelf_gain.set(p_gain);
+}
+
+bool AudioServer::is_playback_active(Ref<AudioStreamPlayback> p_playback) {
+ ERR_FAIL_COND_V(p_playback.is_null(), false);
+
+ AudioStreamPlaybackListNode *playback_node = _find_playback_list_node(p_playback);
+ if (!playback_node) {
+ return false;
+ }
+
+ return playback_node->state.load() == AudioStreamPlaybackListNode::PLAYING;
+}
+
+float AudioServer::get_playback_position(Ref<AudioStreamPlayback> p_playback) {
+ ERR_FAIL_COND_V(p_playback.is_null(), 0);
+
+ AudioStreamPlaybackListNode *playback_node = _find_playback_list_node(p_playback);
+ if (!playback_node) {
+ return 0;
+ }
+
+ return playback_node->stream_playback->get_playback_position();
+}
+
+bool AudioServer::is_playback_paused(Ref<AudioStreamPlayback> p_playback) {
+ ERR_FAIL_COND_V(p_playback.is_null(), false);
+
+ AudioStreamPlaybackListNode *playback_node = _find_playback_list_node(p_playback);
+ if (!playback_node) {
+ return false;
+ }
+
+ return playback_node->state.load() == AudioStreamPlaybackListNode::PAUSED || playback_node->state.load() == AudioStreamPlaybackListNode::FADE_OUT_TO_PAUSE;
+}
+
+uint64_t AudioServer::get_mix_count() const {
+ return mix_count;
+}
+
+void AudioServer::notify_listener_changed() {
+ for (CallbackItem *ci : listener_changed_callback_list) {
+ ci->callback(ci->userdata);
+ }
+}
+
void AudioServer::init_channels_and_buffers() {
channel_count = get_channel_count();
temp_buffer.resize(channel_count);
+ mix_buffer.resize(buffer_size + LOOKAHEAD_BUFFER_SIZE);
for (int i = 0; i < temp_buffer.size(); i++) {
temp_buffer.write[i].resize(buffer_size);
@@ -943,7 +1346,7 @@ void AudioServer::init() {
channel_disable_threshold_db = GLOBAL_DEF_RST("audio/buses/channel_disable_threshold_db", -60.0);
channel_disable_frames = float(GLOBAL_DEF_RST("audio/buses/channel_disable_time", 2.0)) * get_mix_rate();
ProjectSettings::get_singleton()->set_custom_property_info("audio/buses/channel_disable_time", PropertyInfo(Variant::FLOAT, "audio/buses/channel_disable_time", PROPERTY_HINT_RANGE, "0,5,0.01,or_greater"));
- buffer_size = 1024; //hardcoded for now
+ buffer_size = 512; //hardcoded for now
init_channels_and_buffers();
@@ -1030,9 +1433,22 @@ void AudioServer::update() {
prof_time = 0;
#endif
- for (Set<CallbackItem>::Element *E = update_callbacks.front(); E; E = E->next()) {
- E->get().callback(E->get().userdata);
+ for (CallbackItem *ci : update_callback_list) {
+ ci->callback(ci->userdata);
+ }
+ mix_callback_list.maybe_cleanup();
+ update_callback_list.maybe_cleanup();
+ listener_changed_callback_list.maybe_cleanup();
+ playback_list.maybe_cleanup();
+ for (AudioStreamPlaybackBusDetails *bus_details : bus_details_graveyard_frame_old) {
+ bus_details_graveyard_frame_old.erase(bus_details, [](AudioStreamPlaybackBusDetails *d) { delete d; });
+ }
+ for (AudioStreamPlaybackBusDetails *bus_details : bus_details_graveyard) {
+ bus_details_graveyard_frame_old.insert(bus_details);
+ bus_details_graveyard.erase(bus_details);
}
+ bus_details_graveyard.maybe_cleanup();
+ bus_details_graveyard_frame_old.maybe_cleanup();
}
void AudioServer::load_default_bus_layout() {
@@ -1098,40 +1514,49 @@ double AudioServer::get_time_since_last_mix() const {
AudioServer *AudioServer::singleton = nullptr;
-void AudioServer::add_callback(AudioCallback p_callback, void *p_userdata) {
- lock();
- CallbackItem ci;
- ci.callback = p_callback;
- ci.userdata = p_userdata;
- callbacks.insert(ci);
- unlock();
+void AudioServer::add_update_callback(AudioCallback p_callback, void *p_userdata) {
+ CallbackItem *ci = new CallbackItem();
+ ci->callback = p_callback;
+ ci->userdata = p_userdata;
+ update_callback_list.insert(ci);
}
-void AudioServer::remove_callback(AudioCallback p_callback, void *p_userdata) {
- lock();
- CallbackItem ci;
- ci.callback = p_callback;
- ci.userdata = p_userdata;
- callbacks.erase(ci);
- unlock();
+void AudioServer::remove_update_callback(AudioCallback p_callback, void *p_userdata) {
+ for (CallbackItem *ci : update_callback_list) {
+ if (ci->callback == p_callback && ci->userdata == p_userdata) {
+ update_callback_list.erase(ci, [](CallbackItem *c) { delete c; });
+ }
+ }
}
-void AudioServer::add_update_callback(AudioCallback p_callback, void *p_userdata) {
- lock();
- CallbackItem ci;
- ci.callback = p_callback;
- ci.userdata = p_userdata;
- update_callbacks.insert(ci);
- unlock();
+void AudioServer::add_mix_callback(AudioCallback p_callback, void *p_userdata) {
+ CallbackItem *ci = new CallbackItem();
+ ci->callback = p_callback;
+ ci->userdata = p_userdata;
+ mix_callback_list.insert(ci);
}
-void AudioServer::remove_update_callback(AudioCallback p_callback, void *p_userdata) {
- lock();
- CallbackItem ci;
- ci.callback = p_callback;
- ci.userdata = p_userdata;
- update_callbacks.erase(ci);
- unlock();
+void AudioServer::remove_mix_callback(AudioCallback p_callback, void *p_userdata) {
+ for (CallbackItem *ci : mix_callback_list) {
+ if (ci->callback == p_callback && ci->userdata == p_userdata) {
+ mix_callback_list.erase(ci, [](CallbackItem *c) { delete c; });
+ }
+ }
+}
+
+void AudioServer::add_listener_changed_callback(AudioCallback p_callback, void *p_userdata) {
+ CallbackItem *ci = new CallbackItem();
+ ci->callback = p_callback;
+ ci->userdata = p_userdata;
+ listener_changed_callback_list.insert(ci);
+}
+
+void AudioServer::remove_listener_changed_callback(AudioCallback p_callback, void *p_userdata) {
+ for (CallbackItem *ci : listener_changed_callback_list) {
+ if (ci->callback == p_callback && ci->userdata == p_userdata) {
+ listener_changed_callback_list.erase(ci, [](CallbackItem *c) { delete c; });
+ }
+ }
}
void AudioServer::set_bus_layout(const Ref<AudioBusLayout> &p_bus_layout) {
diff --git a/servers/audio_server.h b/servers/audio_server.h
index 7974c4a2ad..46873845dc 100644
--- a/servers/audio_server.h
+++ b/servers/audio_server.h
@@ -34,12 +34,17 @@
#include "core/math/audio_frame.h"
#include "core/object/class_db.h"
#include "core/os/os.h"
+#include "core/templates/safe_list.h"
#include "core/variant/variant.h"
#include "servers/audio/audio_effect.h"
+#include "servers/audio/audio_filter_sw.h"
+
+#include <atomic>
class AudioDriverDummy;
class AudioStream;
class AudioStreamSample;
+class AudioStreamPlayback;
class AudioDriver {
static AudioDriver *singleton;
@@ -155,7 +160,10 @@ public:
};
enum {
- AUDIO_DATA_INVALID_ID = -1
+ AUDIO_DATA_INVALID_ID = -1,
+ MAX_CHANNELS_PER_BUS = 4,
+ MAX_BUSES_PER_PLAYBACK = 6,
+ LOOKAHEAD_BUFFER_SIZE = 64,
};
typedef void (*AudioCallback)(void *p_userdata);
@@ -219,7 +227,46 @@ private:
int index_cache;
};
+ struct AudioStreamPlaybackBusDetails {
+ bool bus_active[MAX_BUSES_PER_PLAYBACK] = { false, false, false, false, false, false };
+ StringName bus[MAX_BUSES_PER_PLAYBACK];
+ AudioFrame volume[MAX_BUSES_PER_PLAYBACK][MAX_CHANNELS_PER_BUS];
+ };
+
+ struct AudioStreamPlaybackListNode {
+ enum PlaybackState {
+ PAUSED = 0, // Paused. Keep this stream playback around though so it can be restarted.
+ PLAYING = 1, // Playing. Fading may still be necessary if volume changes!
+ FADE_OUT_TO_PAUSE = 2, // About to pause.
+ FADE_OUT_TO_DELETION = 3, // About to stop.
+ AWAITING_DELETION = 4,
+ };
+ // If zero or positive, a place in the stream to seek to during the next mix.
+ SafeNumeric<float> setseek;
+ SafeNumeric<float> pitch_scale;
+ SafeNumeric<float> highshelf_gain;
+ SafeNumeric<float> attenuation_filter_cutoff_hz; // This isn't used unless highshelf_gain is nonzero.
+ AudioFilterSW::Processor filter_process[8];
+ // Updating this ref after the list node is created breaks consistency guarantees, don't do it!
+ Ref<AudioStreamPlayback> stream_playback;
+ // Playback state determines the fate of a particular AudioStreamListNode during the mix step. Must be atomically replaced.
+ std::atomic<PlaybackState> state = AWAITING_DELETION;
+ // This data should only ever be modified by an atomic replacement of the pointer.
+ std::atomic<AudioStreamPlaybackBusDetails *> bus_details = nullptr;
+ // Previous bus details should only be accessed on the audio thread.
+ AudioStreamPlaybackBusDetails *prev_bus_details = nullptr;
+ // The next few samples are stored here so we have some time to fade audio out if it ends abruptly at the beginning of the next mix.
+ AudioFrame lookahead[LOOKAHEAD_BUFFER_SIZE];
+ };
+
+ SafeList<AudioStreamPlaybackListNode *> playback_list;
+ SafeList<AudioStreamPlaybackBusDetails *> bus_details_graveyard;
+
+ // TODO document if this is necessary.
+ SafeList<AudioStreamPlaybackBusDetails *> bus_details_graveyard_frame_old;
+
Vector<Vector<AudioFrame>> temp_buffer; //temp_buffer for each level
+ Vector<AudioFrame> mix_buffer;
Vector<Bus *> buses;
Map<StringName, Bus *> bus_map;
@@ -230,18 +277,19 @@ private:
void init_channels_and_buffers();
void _mix_step();
+ void _mix_step_for_channel(AudioFrame *p_out_buf, AudioFrame *p_source_buf, AudioFrame p_vol_start, AudioFrame p_vol_final, float p_attenuation_filter_cutoff_hz, float p_highshelf_gain, AudioFilterSW::Processor *p_processor_l, AudioFilterSW::Processor *p_processor_r);
+
+ // Should only be called on the main thread.
+ AudioStreamPlaybackListNode *_find_playback_list_node(Ref<AudioStreamPlayback> p_playback);
struct CallbackItem {
AudioCallback callback;
void *userdata;
-
- bool operator<(const CallbackItem &p_item) const {
- return (callback == p_item.callback ? userdata < p_item.userdata : callback < p_item.callback);
- }
};
- Set<CallbackItem> callbacks;
- Set<CallbackItem> update_callbacks;
+ SafeList<CallbackItem *> update_callback_list;
+ SafeList<CallbackItem *> mix_callback_list;
+ SafeList<CallbackItem *> listener_changed_callback_list;
friend class AudioDriver;
void _driver_process(int p_frames, int32_t *p_buffer);
@@ -319,6 +367,27 @@ public:
void set_playback_speed_scale(float p_scale);
float get_playback_speed_scale() const;
+ // Convenience method.
+ void start_playback_stream(Ref<AudioStreamPlayback> p_playback, StringName p_bus, Vector<AudioFrame> p_volume_db_vector, float p_start_time = 0, float p_pitch_scale = 1);
+ // Expose all parameters.
+ void start_playback_stream(Ref<AudioStreamPlayback> p_playback, Map<StringName, Vector<AudioFrame>> p_bus_volumes, float p_start_time = 0, float p_pitch_scale = 1, float p_highshelf_gain = 0, float p_attenuation_cutoff_hz = 0);
+ void stop_playback_stream(Ref<AudioStreamPlayback> p_playback);
+
+ void set_playback_bus_exclusive(Ref<AudioStreamPlayback> p_playback, StringName p_bus, Vector<AudioFrame> p_volumes);
+ void set_playback_bus_volumes_linear(Ref<AudioStreamPlayback> p_playback, Map<StringName, Vector<AudioFrame>> p_bus_volumes);
+ void set_playback_all_bus_volumes_linear(Ref<AudioStreamPlayback> p_playback, Vector<AudioFrame> p_volumes);
+ void set_playback_pitch_scale(Ref<AudioStreamPlayback> p_playback, float p_pitch_scale);
+ void set_playback_paused(Ref<AudioStreamPlayback> p_playback, bool p_paused);
+ void set_playback_highshelf_params(Ref<AudioStreamPlayback> p_playback, float p_gain, float p_attenuation_cutoff_hz);
+
+ bool is_playback_active(Ref<AudioStreamPlayback> p_playback);
+ float get_playback_position(Ref<AudioStreamPlayback> p_playback);
+ bool is_playback_paused(Ref<AudioStreamPlayback> p_playback);
+
+ uint64_t get_mix_count() const;
+
+ void notify_listener_changed();
+
virtual void init();
virtual void finish();
virtual void update();
@@ -340,12 +409,15 @@ public:
virtual double get_time_to_next_mix() const;
virtual double get_time_since_last_mix() const;
- void add_callback(AudioCallback p_callback, void *p_userdata);
- void remove_callback(AudioCallback p_callback, void *p_userdata);
+ void add_listener_changed_callback(AudioCallback p_callback, void *p_userdata);
+ void remove_listener_changed_callback(AudioCallback p_callback, void *p_userdata);
void add_update_callback(AudioCallback p_callback, void *p_userdata);
void remove_update_callback(AudioCallback p_callback, void *p_userdata);
+ void add_mix_callback(AudioCallback p_callback, void *p_userdata);
+ void remove_mix_callback(AudioCallback p_callback, void *p_userdata);
+
void set_bus_layout(const Ref<AudioBusLayout> &p_bus_layout);
Ref<AudioBusLayout> generate_bus_layout() const;
diff --git a/servers/display_server.cpp b/servers/display_server.cpp
index 3d44484033..3897e5e7c2 100644
--- a/servers/display_server.cpp
+++ b/servers/display_server.cpp
@@ -285,6 +285,10 @@ String DisplayServer::keyboard_get_layout_name(int p_index) const {
return "Not supported";
}
+Key DisplayServer::keyboard_get_keycode_from_physical(Key p_keycode) const {
+ ERR_FAIL_V_MSG(p_keycode, "Not supported by this display server.");
+}
+
void DisplayServer::force_process_and_drop_events() {
}
@@ -452,6 +456,7 @@ void DisplayServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("keyboard_set_current_layout", "index"), &DisplayServer::keyboard_set_current_layout);
ClassDB::bind_method(D_METHOD("keyboard_get_layout_language", "index"), &DisplayServer::keyboard_get_layout_language);
ClassDB::bind_method(D_METHOD("keyboard_get_layout_name", "index"), &DisplayServer::keyboard_get_layout_name);
+ ClassDB::bind_method(D_METHOD("keyboard_get_keycode_from_physical", "keycode"), &DisplayServer::keyboard_get_keycode_from_physical);
ClassDB::bind_method(D_METHOD("process_events"), &DisplayServer::process_events);
ClassDB::bind_method(D_METHOD("force_process_and_drop_events"), &DisplayServer::force_process_and_drop_events);
@@ -605,4 +610,5 @@ DisplayServer::DisplayServer() {
}
DisplayServer::~DisplayServer() {
+ singleton = nullptr;
}
diff --git a/servers/display_server.h b/servers/display_server.h
index 788206768c..f411a72aa3 100644
--- a/servers/display_server.h
+++ b/servers/display_server.h
@@ -343,6 +343,7 @@ public:
virtual void keyboard_set_current_layout(int p_index);
virtual String keyboard_get_layout_language(int p_index) const;
virtual String keyboard_get_layout_name(int p_index) const;
+ virtual Key keyboard_get_keycode_from_physical(Key p_keycode) const;
virtual int tablet_get_driver_count() const { return 1; };
virtual String tablet_get_driver_name(int p_driver) const { return "default"; };
diff --git a/servers/physics_2d/area_2d_sw.cpp b/servers/physics_2d/area_2d_sw.cpp
index 532cb259b3..c85b1575e3 100644
--- a/servers/physics_2d/area_2d_sw.cpp
+++ b/servers/physics_2d/area_2d_sw.cpp
@@ -274,22 +274,31 @@ void Area2DSW::call_queries() {
}
}
+void Area2DSW::compute_gravity(const Vector2 &p_position, Vector2 &r_gravity) const {
+ if (is_gravity_point()) {
+ const real_t gravity_distance_scale = get_gravity_distance_scale();
+ Vector2 v = get_transform().xform(get_gravity_vector()) - p_position;
+ if (gravity_distance_scale > 0) {
+ const real_t v_length = v.length();
+ if (v_length > 0) {
+ const real_t v_scaled = v_length * gravity_distance_scale;
+ r_gravity = (v.normalized() * (get_gravity() / (v_scaled * v_scaled)));
+ } else {
+ r_gravity = Vector2();
+ }
+ } else {
+ r_gravity = v.normalized() * get_gravity();
+ }
+ } else {
+ r_gravity = get_gravity_vector() * get_gravity();
+ }
+}
+
Area2DSW::Area2DSW() :
CollisionObject2DSW(TYPE_AREA),
monitor_query_list(this),
moved_list(this) {
_set_static(true); //areas are not active by default
- space_override_mode = PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED;
- gravity = 9.80665;
- gravity_vector = Vector2(0, -1);
- gravity_is_point = false;
- gravity_distance_scale = 0;
- point_attenuation = 1;
-
- angular_damp = 1.0;
- linear_damp = 0.1;
- priority = 0;
- monitorable = false;
}
Area2DSW::~Area2DSW() {
diff --git a/servers/physics_2d/area_2d_sw.h b/servers/physics_2d/area_2d_sw.h
index 3bf603b30d..0b7c791ed5 100644
--- a/servers/physics_2d/area_2d_sw.h
+++ b/servers/physics_2d/area_2d_sw.h
@@ -34,23 +34,22 @@
#include "collision_object_2d_sw.h"
#include "core/templates/self_list.h"
#include "servers/physics_server_2d.h"
-//#include "servers/physics_3d/query_sw.h"
class Space2DSW;
class Body2DSW;
class Constraint2DSW;
class Area2DSW : public CollisionObject2DSW {
- PhysicsServer2D::AreaSpaceOverrideMode space_override_mode;
- real_t gravity;
- Vector2 gravity_vector;
- bool gravity_is_point;
- real_t gravity_distance_scale;
- real_t point_attenuation;
- real_t linear_damp;
- real_t angular_damp;
- int priority;
- bool monitorable;
+ PhysicsServer2D::AreaSpaceOverrideMode space_override_mode = PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED;
+ real_t gravity = 9.80665;
+ Vector2 gravity_vector = Vector2(0, -1);
+ bool gravity_is_point = false;
+ real_t gravity_distance_scale = 0.0;
+ real_t point_attenuation = 1.0;
+ real_t linear_damp = 0.1;
+ real_t angular_damp = 1.0;
+ int priority = 0;
+ bool monitorable = false;
ObjectID monitor_callback_id;
StringName monitor_callback_method;
@@ -64,8 +63,8 @@ class Area2DSW : public CollisionObject2DSW {
struct BodyKey {
RID rid;
ObjectID instance_id;
- uint32_t body_shape;
- uint32_t area_shape;
+ uint32_t body_shape = 0;
+ uint32_t area_shape = 0;
_FORCE_INLINE_ bool operator<(const BodyKey &p_key) const {
if (rid == p_key.rid) {
@@ -85,26 +84,20 @@ class Area2DSW : public CollisionObject2DSW {
};
struct BodyState {
- int state;
+ int state = 0;
_FORCE_INLINE_ void inc() { state++; }
_FORCE_INLINE_ void dec() { state--; }
- _FORCE_INLINE_ BodyState() { state = 0; }
};
Map<BodyKey, BodyState> monitored_bodies;
Map<BodyKey, BodyState> monitored_areas;
- //virtual void shape_changed_notify(Shape2DSW *p_shape);
- //virtual void shape_deleted_notify(Shape2DSW *p_shape);
Set<Constraint2DSW *> constraints;
virtual void _shapes_changed();
void _queue_monitor_update();
public:
- //_FORCE_INLINE_ const Matrix32& get_inverse_transform() const { return inverse_transform; }
- //_FORCE_INLINE_ SpaceSW* get_owner() { return owner; }
-
void set_monitor_callback(ObjectID p_id, const StringName &p_method);
_FORCE_INLINE_ bool has_monitor_callback() const { return monitor_callback_id.is_valid(); }
@@ -161,6 +154,8 @@ public:
void call_queries();
+ void compute_gravity(const Vector2 &p_position, Vector2 &r_gravity) const;
+
Area2DSW();
~Area2DSW();
};
diff --git a/servers/physics_2d/area_pair_2d_sw.cpp b/servers/physics_2d/area_pair_2d_sw.cpp
index 5ca16cb6fc..4f1148c26f 100644
--- a/servers/physics_2d/area_pair_2d_sw.cpp
+++ b/servers/physics_2d/area_pair_2d_sw.cpp
@@ -33,7 +33,7 @@
bool AreaPair2DSW::setup(real_t p_step) {
bool result = false;
- if (area->interacts_with(body) && CollisionSolver2DSW::solve(body->get_shape(body_shape), body->get_transform() * body->get_shape_transform(body_shape), Vector2(), area->get_shape(area_shape), area->get_transform() * area->get_shape_transform(area_shape), Vector2(), nullptr, this)) {
+ if (area->collides_with(body) && CollisionSolver2DSW::solve(body->get_shape(body_shape), body->get_transform() * body->get_shape_transform(body_shape), Vector2(), area->get_shape(area_shape), area->get_transform() * area->get_shape_transform(area_shape), Vector2(), nullptr, this)) {
result = true;
}
@@ -109,46 +109,51 @@ AreaPair2DSW::~AreaPair2DSW() {
//////////////////////////////////
bool Area2Pair2DSW::setup(real_t p_step) {
- bool result = false;
- if (area_a->interacts_with(area_b) && CollisionSolver2DSW::solve(area_a->get_shape(shape_a), area_a->get_transform() * area_a->get_shape_transform(shape_a), Vector2(), area_b->get_shape(shape_b), area_b->get_transform() * area_b->get_shape_transform(shape_b), Vector2(), nullptr, this)) {
- result = true;
+ bool result_a = area_a->collides_with(area_b);
+ bool result_b = area_b->collides_with(area_a);
+ if ((result_a || result_b) && !CollisionSolver2DSW::solve(area_a->get_shape(shape_a), area_a->get_transform() * area_a->get_shape_transform(shape_a), Vector2(), area_b->get_shape(shape_b), area_b->get_transform() * area_b->get_shape_transform(shape_b), Vector2(), nullptr, this)) {
+ result_a = false;
+ result_b = false;
}
- process_collision = false;
- if (result != colliding) {
- if (area_b->has_area_monitor_callback() && area_a->is_monitorable()) {
- process_collision = true;
- } else if (area_a->has_area_monitor_callback() && area_b->is_monitorable()) {
+ bool process_collision = false;
+
+ process_collision_a = false;
+ if (result_a != colliding_a) {
+ if (area_a->has_area_monitor_callback() && area_b->is_monitorable()) {
+ process_collision_a = true;
process_collision = true;
}
+ colliding_a = result_a;
+ }
- colliding = result;
+ process_collision_b = false;
+ if (result_b != colliding_b) {
+ if (area_b->has_area_monitor_callback() && area_a->is_monitorable()) {
+ process_collision_b = true;
+ process_collision = true;
+ }
+ colliding_b = result_b;
}
return process_collision;
}
bool Area2Pair2DSW::pre_solve(real_t p_step) {
- if (!process_collision) {
- return false;
+ if (process_collision_a) {
+ if (colliding_a) {
+ area_a->add_area_to_query(area_b, shape_b, shape_a);
+ } else {
+ area_a->remove_area_from_query(area_b, shape_b, shape_a);
+ }
}
- if (colliding) {
- if (area_b->has_area_monitor_callback() && area_a->is_monitorable()) {
+ if (process_collision_b) {
+ if (colliding_b) {
area_b->add_area_to_query(area_a, shape_a, shape_b);
- }
-
- if (area_a->has_area_monitor_callback() && area_b->is_monitorable()) {
- area_a->add_area_to_query(area_b, shape_b, shape_a);
- }
- } else {
- if (area_b->has_area_monitor_callback() && area_a->is_monitorable()) {
+ } else {
area_b->remove_area_from_query(area_a, shape_a, shape_b);
}
-
- if (area_a->has_area_monitor_callback() && area_b->is_monitorable()) {
- area_a->remove_area_from_query(area_b, shape_b, shape_a);
- }
}
return false; // Never do any post solving.
@@ -168,16 +173,18 @@ Area2Pair2DSW::Area2Pair2DSW(Area2DSW *p_area_a, int p_shape_a, Area2DSW *p_area
}
Area2Pair2DSW::~Area2Pair2DSW() {
- if (colliding) {
- if (area_b->has_area_monitor_callback()) {
- area_b->remove_area_from_query(area_a, shape_a, shape_b);
- }
-
+ if (colliding_a) {
if (area_a->has_area_monitor_callback()) {
area_a->remove_area_from_query(area_b, shape_b, shape_a);
}
}
+ if (colliding_b) {
+ if (area_b->has_area_monitor_callback()) {
+ area_b->remove_area_from_query(area_a, shape_a, shape_b);
+ }
+ }
+
area_a->remove_constraint(this);
area_b->remove_constraint(this);
}
diff --git a/servers/physics_2d/area_pair_2d_sw.h b/servers/physics_2d/area_pair_2d_sw.h
index 4632a307d9..66e9f1afee 100644
--- a/servers/physics_2d/area_pair_2d_sw.h
+++ b/servers/physics_2d/area_pair_2d_sw.h
@@ -57,8 +57,10 @@ class Area2Pair2DSW : public Constraint2DSW {
Area2DSW *area_b = nullptr;
int shape_a = 0;
int shape_b = 0;
- bool colliding = false;
- bool process_collision = false;
+ bool colliding_a = false;
+ bool colliding_b = false;
+ bool process_collision_a = false;
+ bool process_collision_b = false;
public:
virtual bool setup(real_t p_step) override;
diff --git a/servers/physics_2d/body_2d_sw.cpp b/servers/physics_2d/body_2d_sw.cpp
index 7aa2f9b7de..38b98b7bca 100644
--- a/servers/physics_2d/body_2d_sw.cpp
+++ b/servers/physics_2d/body_2d_sw.cpp
@@ -29,51 +29,77 @@
/*************************************************************************/
#include "body_2d_sw.h"
+
#include "area_2d_sw.h"
-#include "physics_server_2d_sw.h"
+#include "body_direct_state_2d_sw.h"
#include "space_2d_sw.h"
-void Body2DSW::_update_inertia() {
- if (!user_inertia && get_space() && !inertia_update_list.in_list()) {
- get_space()->body_add_to_inertia_update_list(&inertia_update_list);
+void Body2DSW::_mass_properties_changed() {
+ if (get_space() && !mass_properties_update_list.in_list() && (calculate_inertia || calculate_center_of_mass)) {
+ get_space()->body_add_to_mass_properties_update_list(&mass_properties_update_list);
}
}
-void Body2DSW::update_inertias() {
+void Body2DSW::update_mass_properties() {
//update shapes and motions
switch (mode) {
case PhysicsServer2D::BODY_MODE_DYNAMIC: {
- if (user_inertia) {
- _inv_inertia = inertia > 0 ? (1.0 / inertia) : 0;
- break;
- }
- //update tensor for allshapes, not the best way but should be somehow OK. (inspired from bullet)
real_t total_area = 0;
-
for (int i = 0; i < get_shape_count(); i++) {
+ if (is_shape_disabled(i)) {
+ continue;
+ }
total_area += get_shape_aabb(i).get_area();
}
- inertia = 0;
+ if (calculate_center_of_mass) {
+ // We have to recompute the center of mass.
+ center_of_mass = Vector2();
- for (int i = 0; i < get_shape_count(); i++) {
- if (is_shape_disabled(i)) {
- continue;
+ if (total_area != 0.0) {
+ for (int i = 0; i < get_shape_count(); i++) {
+ if (is_shape_disabled(i)) {
+ continue;
+ }
+
+ real_t area = get_shape_aabb(i).get_area();
+
+ real_t mass = area * this->mass / total_area;
+
+ // NOTE: we assume that the shape origin is also its center of mass.
+ center_of_mass += mass * get_shape_transform(i).get_origin();
+ }
+
+ center_of_mass /= mass;
}
+ }
+
+ if (calculate_inertia) {
+ inertia = 0;
+
+ for (int i = 0; i < get_shape_count(); i++) {
+ if (is_shape_disabled(i)) {
+ continue;
+ }
- const Shape2DSW *shape = get_shape(i);
+ const Shape2DSW *shape = get_shape(i);
- real_t area = get_shape_aabb(i).get_area();
+ real_t area = get_shape_aabb(i).get_area();
+ if (area == 0.0) {
+ continue;
+ }
- real_t mass = area * this->mass / total_area;
+ real_t mass = area * this->mass / total_area;
- Transform2D mtx = get_shape_transform(i);
- Vector2 scale = mtx.get_scale();
- inertia += shape->get_moment_of_inertia(mass, scale) + mass * mtx.get_origin().length_squared();
+ Transform2D mtx = get_shape_transform(i);
+ Vector2 scale = mtx.get_scale();
+ Vector2 shape_origin = mtx.get_origin() - center_of_mass;
+ inertia += shape->get_moment_of_inertia(mass, scale) + mass * shape_origin.length_squared();
+ }
}
- _inv_inertia = inertia > 0 ? (1.0 / inertia) : 0;
+ _inv_inertia = inertia > 0.0 ? (1.0 / inertia) : 0.0;
if (mass) {
_inv_mass = 1.0 / mass;
@@ -87,15 +113,18 @@ void Body2DSW::update_inertias() {
_inv_inertia = 0;
_inv_mass = 0;
} break;
- case PhysicsServer2D::BODY_MODE_DYNAMIC_LOCKED: {
+ case PhysicsServer2D::BODY_MODE_DYNAMIC_LINEAR: {
_inv_inertia = 0;
_inv_mass = 1.0 / mass;
} break;
}
- //_update_inertia_tensor();
+}
- //_update_shapes();
+void Body2DSW::reset_mass_properties() {
+ calculate_inertia = true;
+ calculate_center_of_mass = true;
+ _mass_properties_changed();
}
void Body2DSW::set_active(bool p_active) {
@@ -117,7 +146,7 @@ void Body2DSW::set_active(bool p_active) {
}
}
-void Body2DSW::set_param(PhysicsServer2D::BodyParameter p_param, real_t p_value) {
+void Body2DSW::set_param(PhysicsServer2D::BodyParameter p_param, const Variant &p_value) {
switch (p_param) {
case PhysicsServer2D::BODY_PARAM_BOUNCE: {
bounce = p_value;
@@ -126,21 +155,32 @@ void Body2DSW::set_param(PhysicsServer2D::BodyParameter p_param, real_t p_value)
friction = p_value;
} break;
case PhysicsServer2D::BODY_PARAM_MASS: {
- ERR_FAIL_COND(p_value <= 0);
- mass = p_value;
- _update_inertia();
-
+ real_t mass_value = p_value;
+ ERR_FAIL_COND(mass_value <= 0);
+ mass = mass_value;
+ if (mode >= PhysicsServer2D::BODY_MODE_DYNAMIC) {
+ _mass_properties_changed();
+ }
} break;
case PhysicsServer2D::BODY_PARAM_INERTIA: {
- if (p_value <= 0) {
- user_inertia = false;
- _update_inertia();
+ real_t inertia_value = p_value;
+ if (inertia_value <= 0.0) {
+ calculate_inertia = true;
+ if (mode == PhysicsServer2D::BODY_MODE_DYNAMIC) {
+ _mass_properties_changed();
+ }
} else {
- user_inertia = true;
- inertia = p_value;
- _inv_inertia = 1.0 / p_value;
+ calculate_inertia = false;
+ inertia = inertia_value;
+ if (mode == PhysicsServer2D::BODY_MODE_DYNAMIC) {
+ _inv_inertia = 1.0 / inertia;
+ }
}
} break;
+ case PhysicsServer2D::BODY_PARAM_CENTER_OF_MASS: {
+ calculate_center_of_mass = false;
+ center_of_mass = p_value;
+ } break;
case PhysicsServer2D::BODY_PARAM_GRAVITY_SCALE: {
gravity_scale = p_value;
} break;
@@ -155,7 +195,7 @@ void Body2DSW::set_param(PhysicsServer2D::BodyParameter p_param, real_t p_value)
}
}
-real_t Body2DSW::get_param(PhysicsServer2D::BodyParameter p_param) const {
+Variant Body2DSW::get_param(PhysicsServer2D::BodyParameter p_param) const {
switch (p_param) {
case PhysicsServer2D::BODY_PARAM_BOUNCE: {
return bounce;
@@ -169,6 +209,9 @@ real_t Body2DSW::get_param(PhysicsServer2D::BodyParameter p_param) const {
case PhysicsServer2D::BODY_PARAM_INERTIA: {
return inertia;
}
+ case PhysicsServer2D::BODY_PARAM_CENTER_OF_MASS: {
+ return center_of_mass;
+ }
case PhysicsServer2D::BODY_PARAM_GRAVITY_SCALE: {
return gravity_scale;
}
@@ -206,26 +249,22 @@ void Body2DSW::set_mode(PhysicsServer2D::BodyMode p_mode) {
} break;
case PhysicsServer2D::BODY_MODE_DYNAMIC: {
_inv_mass = mass > 0 ? (1.0 / mass) : 0;
- _inv_inertia = inertia > 0 ? (1.0 / inertia) : 0;
+ if (!calculate_inertia) {
+ _inv_inertia = 1.0 / inertia;
+ }
+ _mass_properties_changed();
_set_static(false);
set_active(true);
} break;
- case PhysicsServer2D::BODY_MODE_DYNAMIC_LOCKED: {
+ case PhysicsServer2D::BODY_MODE_DYNAMIC_LINEAR: {
_inv_mass = mass > 0 ? (1.0 / mass) : 0;
_inv_inertia = 0;
+ angular_velocity = 0;
_set_static(false);
set_active(true);
- angular_velocity = 0;
- } break;
- }
- if (p_mode == PhysicsServer2D::BODY_MODE_DYNAMIC && _inv_inertia == 0) {
- _update_inertia();
+ }
}
- /*
- if (get_space())
- _update_queries();
- */
}
PhysicsServer2D::BodyMode Body2DSW::get_mode() const {
@@ -233,7 +272,7 @@ PhysicsServer2D::BodyMode Body2DSW::get_mode() const {
}
void Body2DSW::_shapes_changed() {
- _update_inertia();
+ _mass_properties_changed();
wakeup_neighbours();
}
@@ -268,11 +307,13 @@ void Body2DSW::set_state(PhysicsServer2D::BodyState p_state, const Variant &p_va
} break;
case PhysicsServer2D::BODY_STATE_LINEAR_VELOCITY: {
linear_velocity = p_variant;
+ constant_linear_velocity = linear_velocity;
wakeup();
} break;
case PhysicsServer2D::BODY_STATE_ANGULAR_VELOCITY: {
angular_velocity = p_variant;
+ constant_angular_velocity = angular_velocity;
wakeup();
} break;
@@ -295,7 +336,7 @@ void Body2DSW::set_state(PhysicsServer2D::BodyState p_state, const Variant &p_va
} break;
case PhysicsServer2D::BODY_STATE_CAN_SLEEP: {
can_sleep = p_variant;
- if (mode == PhysicsServer2D::BODY_MODE_DYNAMIC && !active && !can_sleep) {
+ if (mode >= PhysicsServer2D::BODY_MODE_DYNAMIC && !active && !can_sleep) {
set_active(true);
}
@@ -329,8 +370,8 @@ void Body2DSW::set_space(Space2DSW *p_space) {
if (get_space()) {
wakeup_neighbours();
- if (inertia_update_list.in_list()) {
- get_space()->body_remove_from_inertia_update_list(&inertia_update_list);
+ if (mass_properties_update_list.in_list()) {
+ get_space()->body_remove_from_mass_properties_update_list(&mass_properties_update_list);
}
if (active_list.in_list()) {
get_space()->body_remove_from_active_list(&active_list);
@@ -343,26 +384,17 @@ void Body2DSW::set_space(Space2DSW *p_space) {
_set_space(p_space);
if (get_space()) {
- _update_inertia();
+ _mass_properties_changed();
if (active) {
get_space()->body_add_to_active_list(&active_list);
}
}
-
- first_integration = false;
}
-void Body2DSW::_compute_area_gravity_and_dampenings(const Area2DSW *p_area) {
- if (p_area->is_gravity_point()) {
- if (p_area->get_gravity_distance_scale() > 0) {
- Vector2 v = p_area->get_transform().xform(p_area->get_gravity_vector()) - get_transform().get_origin();
- gravity += v.normalized() * (p_area->get_gravity() / Math::pow(v.length() * p_area->get_gravity_distance_scale() + 1, 2));
- } else {
- gravity += (p_area->get_transform().xform(p_area->get_gravity_vector()) - get_transform().get_origin()).normalized() * p_area->get_gravity();
- }
- } else {
- gravity += p_area->get_gravity_vector() * p_area->get_gravity();
- }
+void Body2DSW::_compute_area_gravity_and_damping(const Area2DSW *p_area) {
+ Vector2 area_gravity;
+ p_area->compute_gravity(get_transform().get_origin(), area_gravity);
+ gravity += area_gravity;
area_linear_damp += p_area->get_linear_damp();
area_angular_damp += p_area->get_angular_damp();
@@ -391,7 +423,7 @@ void Body2DSW::integrate_forces(real_t p_step) {
switch (mode) {
case PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE:
case PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: {
- _compute_area_gravity_and_dampenings(aa[i].area);
+ _compute_area_gravity_and_damping(aa[i].area);
stopped = mode == PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE;
} break;
case PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE:
@@ -399,7 +431,7 @@ void Body2DSW::integrate_forces(real_t p_step) {
gravity = Vector2(0, 0);
area_angular_damp = 0;
area_linear_damp = 0;
- _compute_area_gravity_and_dampenings(aa[i].area);
+ _compute_area_gravity_and_damping(aa[i].area);
stopped = mode == PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE;
} break;
default: {
@@ -408,7 +440,7 @@ void Body2DSW::integrate_forces(real_t p_step) {
}
}
if (!stopped) {
- _compute_area_gravity_and_dampenings(def_area);
+ _compute_area_gravity_and_damping(def_area);
}
gravity *= gravity_scale;
@@ -435,10 +467,10 @@ void Body2DSW::integrate_forces(real_t p_step) {
if (mode == PhysicsServer2D::BODY_MODE_KINEMATIC) {
//compute motion, angular and etc. velocities from prev transform
motion = new_transform.get_origin() - get_transform().get_origin();
- linear_velocity = motion / p_step;
+ linear_velocity = constant_linear_velocity + motion / p_step;
real_t rot = new_transform.get_rotation() - get_transform().get_rotation();
- angular_velocity = remainder(rot, 2.0 * Math_PI) / p_step;
+ angular_velocity = constant_angular_velocity + remainder(rot, 2.0 * Math_PI) / p_step;
do_motion = true;
@@ -450,7 +482,7 @@ void Body2DSW::integrate_forces(real_t p_step) {
*/
} else {
- if (!omit_force_integration && !first_integration) {
+ if (!omit_force_integration) {
//overridden by direct state query
Vector2 force = gravity * mass;
@@ -484,7 +516,6 @@ void Body2DSW::integrate_forces(real_t p_step) {
//motion=linear_velocity*p_step;
- first_integration = false;
biased_angular_velocity = 0;
biased_linear_velocity = Vector2();
@@ -502,7 +533,7 @@ void Body2DSW::integrate_velocities(real_t p_step) {
return;
}
- if (fi_callback) {
+ if (fi_callback_data || body_state_callback) {
get_space()->body_add_to_state_query_list(&direct_state_query_list);
}
@@ -521,14 +552,22 @@ void Body2DSW::integrate_velocities(real_t p_step) {
real_t angle = get_transform().get_rotation() + total_angular_velocity * p_step;
Vector2 pos = get_transform().get_origin() + total_linear_velocity * p_step;
+ real_t center_of_mass_distance = center_of_mass.length();
+ if (center_of_mass_distance > CMP_EPSILON) {
+ // Calculate displacement due to center of mass offset.
+ real_t prev_angle = get_transform().get_rotation();
+ real_t angle_base = Math::atan2(center_of_mass.y, center_of_mass.x);
+ Vector2 point1(Math::cos(angle_base + prev_angle), Math::sin(angle_base + prev_angle));
+ Vector2 point2(Math::cos(angle_base + angle), Math::sin(angle_base + angle));
+ pos += center_of_mass_distance * (point1 - point2);
+ }
+
_set_transform(Transform2D(angle, pos), continuous_cd_mode == PhysicsServer2D::CCD_MODE_DISABLED);
_set_inv_transform(get_transform().inverse());
if (continuous_cd_mode != PhysicsServer2D::CCD_MODE_DISABLED) {
new_transform = get_transform();
}
-
- //_update_inertia_tensor();
}
void Body2DSW::wakeup_neighbours() {
@@ -542,7 +581,7 @@ void Body2DSW::wakeup_neighbours() {
continue;
}
Body2DSW *b = n[i];
- if (b->mode != PhysicsServer2D::BODY_MODE_DYNAMIC) {
+ if (b->mode < PhysicsServer2D::BODY_MODE_DYNAMIC) {
continue;
}
@@ -554,27 +593,27 @@ void Body2DSW::wakeup_neighbours() {
}
void Body2DSW::call_queries() {
- if (fi_callback) {
- PhysicsDirectBodyState2DSW *dbs = PhysicsDirectBodyState2DSW::singleton;
- dbs->body = this;
-
- Variant v = dbs;
- const Variant *vp[2] = { &v, &fi_callback->callback_udata };
-
- Object *obj = fi_callback->callable.get_object();
- if (!obj) {
+ if (fi_callback_data) {
+ if (!fi_callback_data->callable.get_object()) {
set_force_integration_callback(Callable());
} else {
+ Variant direct_state_variant = get_direct_state();
+ const Variant *vp[2] = { &direct_state_variant, &fi_callback_data->udata };
+
Callable::CallError ce;
Variant rv;
- if (fi_callback->callback_udata.get_type() != Variant::NIL) {
- fi_callback->callable.call(vp, 2, rv, ce);
+ if (fi_callback_data->udata.get_type() != Variant::NIL) {
+ fi_callback_data->callable.call(vp, 2, rv, ce);
} else {
- fi_callback->callable.call(vp, 1, rv, ce);
+ fi_callback_data->callable.call(vp, 1, rv, ce);
}
}
}
+
+ if (body_state_callback) {
+ (body_state_callback)(body_state_callback_instance, get_direct_state());
+ }
}
bool Body2DSW::sleep_test(real_t p_step) {
@@ -594,78 +633,45 @@ bool Body2DSW::sleep_test(real_t p_step) {
}
}
+void Body2DSW::set_state_sync_callback(void *p_instance, PhysicsServer2D::BodyStateCallback p_callback) {
+ body_state_callback_instance = p_instance;
+ body_state_callback = p_callback;
+}
+
void Body2DSW::set_force_integration_callback(const Callable &p_callable, const Variant &p_udata) {
- if (fi_callback) {
- memdelete(fi_callback);
- fi_callback = nullptr;
+ if (p_callable.get_object()) {
+ if (!fi_callback_data) {
+ fi_callback_data = memnew(ForceIntegrationCallbackData);
+ }
+ fi_callback_data->callable = p_callable;
+ fi_callback_data->udata = p_udata;
+ } else if (fi_callback_data) {
+ memdelete(fi_callback_data);
+ fi_callback_data = nullptr;
}
+}
- if (p_callable.get_object()) {
- fi_callback = memnew(ForceIntegrationCallback);
- fi_callback->callable = p_callable;
- fi_callback->callback_udata = p_udata;
+PhysicsDirectBodyState2DSW *Body2DSW::get_direct_state() {
+ if (!direct_state) {
+ direct_state = memnew(PhysicsDirectBodyState2DSW);
+ direct_state->body = this;
}
+ return direct_state;
}
Body2DSW::Body2DSW() :
CollisionObject2DSW(TYPE_BODY),
active_list(this),
- inertia_update_list(this),
+ mass_properties_update_list(this),
direct_state_query_list(this) {
- mode = PhysicsServer2D::BODY_MODE_DYNAMIC;
- active = true;
- angular_velocity = 0;
- biased_angular_velocity = 0;
- mass = 1;
- inertia = 0;
- user_inertia = false;
- _inv_inertia = 0;
- _inv_mass = 1;
- bounce = 0;
- friction = 1;
- omit_force_integration = false;
- applied_torque = 0;
- island_step = 0;
_set_static(false);
- first_time_kinematic = false;
- linear_damp = -1;
- angular_damp = -1;
- area_angular_damp = 0;
- area_linear_damp = 0;
- contact_count = 0;
- gravity_scale = 1.0;
- first_integration = false;
-
- still_time = 0;
- continuous_cd_mode = PhysicsServer2D::CCD_MODE_DISABLED;
- can_sleep = true;
- fi_callback = nullptr;
}
Body2DSW::~Body2DSW() {
- if (fi_callback) {
- memdelete(fi_callback);
- }
-}
-
-PhysicsDirectBodyState2DSW *PhysicsDirectBodyState2DSW::singleton = nullptr;
-
-PhysicsDirectSpaceState2D *PhysicsDirectBodyState2DSW::get_space_state() {
- return body->get_space()->get_direct_state();
-}
-
-Variant PhysicsDirectBodyState2DSW::get_contact_collider_shape_metadata(int p_contact_idx) const {
- ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Variant());
-
- if (!PhysicsServer2DSW::singletonsw->body_owner.owns(body->contacts[p_contact_idx].collider)) {
- return Variant();
+ if (fi_callback_data) {
+ memdelete(fi_callback_data);
}
- Body2DSW *other = PhysicsServer2DSW::singletonsw->body_owner.getornull(body->contacts[p_contact_idx].collider);
-
- int sidx = body->contacts[p_contact_idx].collider_shape;
- if (sidx < 0 || sidx >= other->get_shape_count()) {
- return Variant();
+ if (direct_state) {
+ memdelete(direct_state);
}
-
- return other->get_shape_metadata(sidx);
}
diff --git a/servers/physics_2d/body_2d_sw.h b/servers/physics_2d/body_2d_sw.h
index 74bef433dc..822ff76fae 100644
--- a/servers/physics_2d/body_2d_sw.h
+++ b/servers/physics_2d/body_2d_sw.h
@@ -38,58 +38,66 @@
#include "core/templates/vset.h"
class Constraint2DSW;
+class PhysicsDirectBodyState2DSW;
class Body2DSW : public CollisionObject2DSW {
- PhysicsServer2D::BodyMode mode;
+ PhysicsServer2D::BodyMode mode = PhysicsServer2D::BODY_MODE_DYNAMIC;
Vector2 biased_linear_velocity;
- real_t biased_angular_velocity;
+ real_t biased_angular_velocity = 0.0;
Vector2 linear_velocity;
- real_t angular_velocity;
+ real_t angular_velocity = 0.0;
- real_t linear_damp;
- real_t angular_damp;
- real_t gravity_scale;
+ Vector2 constant_linear_velocity;
+ real_t constant_angular_velocity = 0.0;
- real_t mass;
- real_t inertia;
- real_t bounce;
- real_t friction;
+ real_t linear_damp = -1.0;
+ real_t angular_damp = -1.0;
+ real_t gravity_scale = 1.0;
- real_t _inv_mass;
- real_t _inv_inertia;
- bool user_inertia;
+ real_t bounce = 0.0;
+ real_t friction = 1.0;
+
+ real_t mass = 1.0;
+ real_t _inv_mass = 1.0;
+
+ real_t inertia = 0.0;
+ real_t _inv_inertia = 0.0;
+
+ Vector2 center_of_mass;
+
+ bool calculate_inertia = true;
+ bool calculate_center_of_mass = true;
Vector2 gravity;
- real_t area_linear_damp;
- real_t area_angular_damp;
+ real_t area_linear_damp = 0.0;
+ real_t area_angular_damp = 0.0;
- real_t still_time;
+ real_t still_time = 0.0;
Vector2 applied_force;
- real_t applied_torque;
+ real_t applied_torque = 0.0;
SelfList<Body2DSW> active_list;
- SelfList<Body2DSW> inertia_update_list;
+ SelfList<Body2DSW> mass_properties_update_list;
SelfList<Body2DSW> direct_state_query_list;
VSet<RID> exceptions;
- PhysicsServer2D::CCDMode continuous_cd_mode;
- bool omit_force_integration;
- bool active;
- bool can_sleep;
- bool first_time_kinematic;
- bool first_integration;
- void _update_inertia();
+ PhysicsServer2D::CCDMode continuous_cd_mode = PhysicsServer2D::CCD_MODE_DISABLED;
+ bool omit_force_integration = false;
+ bool active = true;
+ bool can_sleep = true;
+ bool first_time_kinematic = false;
+ void _mass_properties_changed();
virtual void _shapes_changed();
Transform2D new_transform;
List<Pair<Constraint2DSW *, int>> constraint_list;
struct AreaCMP {
- Area2DSW *area;
- int refCount;
+ Area2DSW *area = nullptr;
+ int refCount = 0;
_FORCE_INLINE_ bool operator==(const AreaCMP &p_cmp) const { return area->get_self() == p_cmp.area->get_self(); }
_FORCE_INLINE_ bool operator<(const AreaCMP &p_cmp) const { return area->get_priority() < p_cmp.area->get_priority(); }
_FORCE_INLINE_ AreaCMP() {}
@@ -104,34 +112,42 @@ class Body2DSW : public CollisionObject2DSW {
struct Contact {
Vector2 local_pos;
Vector2 local_normal;
- real_t depth;
- int local_shape;
+ real_t depth = 0.0;
+ int local_shape = 0;
Vector2 collider_pos;
- int collider_shape;
+ int collider_shape = 0;
ObjectID collider_instance_id;
RID collider;
Vector2 collider_velocity_at_pos;
};
Vector<Contact> contacts; //no contacts by default
- int contact_count;
+ int contact_count = 0;
+
+ void *body_state_callback_instance = nullptr;
+ PhysicsServer2D::BodyStateCallback body_state_callback = nullptr;
- struct ForceIntegrationCallback {
+ struct ForceIntegrationCallbackData {
Callable callable;
- Variant callback_udata;
+ Variant udata;
};
- ForceIntegrationCallback *fi_callback;
+ ForceIntegrationCallbackData *fi_callback_data = nullptr;
- uint64_t island_step;
+ PhysicsDirectBodyState2DSW *direct_state = nullptr;
- _FORCE_INLINE_ void _compute_area_gravity_and_dampenings(const Area2DSW *p_area);
+ uint64_t island_step = 0;
+
+ _FORCE_INLINE_ void _compute_area_gravity_and_damping(const Area2DSW *p_area);
friend class PhysicsDirectBodyState2DSW; // i give up, too many functions to expose
public:
+ void set_state_sync_callback(void *p_instance, PhysicsServer2D::BodyStateCallback p_callback);
void set_force_integration_callback(const Callable &p_callable, const Variant &p_udata = Variant());
+ PhysicsDirectBodyState2DSW *get_direct_state();
+
_FORCE_INLINE_ void add_area(Area2DSW *p_area) {
int index = areas.find(AreaCMP(p_area));
if (index > -1) {
@@ -198,7 +214,7 @@ public:
_FORCE_INLINE_ void apply_impulse(const Vector2 &p_impulse, const Vector2 &p_position = Vector2()) {
linear_velocity += p_impulse * _inv_mass;
- angular_velocity += _inv_inertia * p_position.cross(p_impulse);
+ angular_velocity += _inv_inertia * (p_position - center_of_mass).cross(p_impulse);
}
_FORCE_INLINE_ void apply_torque_impulse(real_t p_torque) {
@@ -207,7 +223,7 @@ public:
_FORCE_INLINE_ void apply_bias_impulse(const Vector2 &p_impulse, const Vector2 &p_position = Vector2()) {
biased_linear_velocity += p_impulse * _inv_mass;
- biased_angular_velocity += _inv_inertia * p_position.cross(p_impulse);
+ biased_angular_velocity += _inv_inertia * (p_position - center_of_mass).cross(p_impulse);
}
void set_active(bool p_active);
@@ -220,8 +236,8 @@ public:
set_active(true);
}
- void set_param(PhysicsServer2D::BodyParameter p_param, real_t);
- real_t get_param(PhysicsServer2D::BodyParameter p_param) const;
+ void set_param(PhysicsServer2D::BodyParameter p_param, const Variant &p_value);
+ Variant get_param(PhysicsServer2D::BodyParameter p_param) const;
void set_mode(PhysicsServer2D::BodyMode p_mode);
PhysicsServer2D::BodyMode get_mode() const;
@@ -241,7 +257,7 @@ public:
_FORCE_INLINE_ void add_force(const Vector2 &p_force, const Vector2 &p_position = Vector2()) {
applied_force += p_force;
- applied_torque += p_position.cross(p_force);
+ applied_torque += (p_position - center_of_mass).cross(p_force);
}
_FORCE_INLINE_ void add_torque(real_t p_torque) {
@@ -253,8 +269,10 @@ public:
void set_space(Space2DSW *p_space);
- void update_inertias();
+ void update_mass_properties();
+ void reset_mass_properties();
+ _FORCE_INLINE_ Vector2 get_center_of_mass() const { return center_of_mass; }
_FORCE_INLINE_ real_t get_inv_mass() const { return _inv_mass; }
_FORCE_INLINE_ real_t get_inv_inertia() const { return _inv_inertia; }
_FORCE_INLINE_ real_t get_friction() const { return friction; }
@@ -332,87 +350,4 @@ void Body2DSW::add_contact(const Vector2 &p_local_pos, const Vector2 &p_local_no
c[idx].collider_velocity_at_pos = p_collider_velocity_at_pos;
}
-class PhysicsDirectBodyState2DSW : public PhysicsDirectBodyState2D {
- GDCLASS(PhysicsDirectBodyState2DSW, PhysicsDirectBodyState2D);
-
-public:
- static PhysicsDirectBodyState2DSW *singleton;
- Body2DSW *body;
- real_t step;
-
- virtual Vector2 get_total_gravity() const override { return body->gravity; } // get gravity vector working on this body space/area
- virtual real_t get_total_angular_damp() const override { return body->area_angular_damp; } // get density of this body space/area
- virtual real_t get_total_linear_damp() const override { return body->area_linear_damp; } // get density of this body space/area
-
- virtual real_t get_inverse_mass() const override { return body->get_inv_mass(); } // get the mass
- virtual real_t get_inverse_inertia() const override { return body->get_inv_inertia(); } // get density of this body space
-
- virtual void set_linear_velocity(const Vector2 &p_velocity) override { body->set_linear_velocity(p_velocity); }
- virtual Vector2 get_linear_velocity() const override { return body->get_linear_velocity(); }
-
- virtual void set_angular_velocity(real_t p_velocity) override { body->set_angular_velocity(p_velocity); }
- virtual real_t get_angular_velocity() const override { return body->get_angular_velocity(); }
-
- virtual void set_transform(const Transform2D &p_transform) override { body->set_state(PhysicsServer2D::BODY_STATE_TRANSFORM, p_transform); }
- virtual Transform2D get_transform() const override { return body->get_transform(); }
-
- virtual Vector2 get_velocity_at_local_position(const Vector2 &p_position) const override { return body->get_velocity_in_local_point(p_position); }
-
- virtual void add_central_force(const Vector2 &p_force) override { body->add_central_force(p_force); }
- virtual void add_force(const Vector2 &p_force, const Vector2 &p_position = Vector2()) override { body->add_force(p_force, p_position); }
- virtual void add_torque(real_t p_torque) override { body->add_torque(p_torque); }
- virtual void apply_central_impulse(const Vector2 &p_impulse) override { body->apply_central_impulse(p_impulse); }
- virtual void apply_impulse(const Vector2 &p_impulse, const Vector2 &p_position = Vector2()) override { body->apply_impulse(p_impulse, p_position); }
- virtual void apply_torque_impulse(real_t p_torque) override { body->apply_torque_impulse(p_torque); }
-
- virtual void set_sleep_state(bool p_enable) override { body->set_active(!p_enable); }
- virtual bool is_sleeping() const override { return !body->is_active(); }
-
- virtual int get_contact_count() const override { return body->contact_count; }
-
- virtual Vector2 get_contact_local_position(int p_contact_idx) const override {
- ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector2());
- return body->contacts[p_contact_idx].local_pos;
- }
- virtual Vector2 get_contact_local_normal(int p_contact_idx) const override {
- ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector2());
- return body->contacts[p_contact_idx].local_normal;
- }
- virtual int get_contact_local_shape(int p_contact_idx) const override {
- ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, -1);
- return body->contacts[p_contact_idx].local_shape;
- }
-
- virtual RID get_contact_collider(int p_contact_idx) const override {
- ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, RID());
- return body->contacts[p_contact_idx].collider;
- }
- virtual Vector2 get_contact_collider_position(int p_contact_idx) const override {
- ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector2());
- return body->contacts[p_contact_idx].collider_pos;
- }
- virtual ObjectID get_contact_collider_id(int p_contact_idx) const override {
- ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, ObjectID());
- return body->contacts[p_contact_idx].collider_instance_id;
- }
- virtual int get_contact_collider_shape(int p_contact_idx) const override {
- ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, 0);
- return body->contacts[p_contact_idx].collider_shape;
- }
- virtual Variant get_contact_collider_shape_metadata(int p_contact_idx) const override;
-
- virtual Vector2 get_contact_collider_velocity_at_position(int p_contact_idx) const override {
- ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector2());
- return body->contacts[p_contact_idx].collider_velocity_at_pos;
- }
-
- virtual PhysicsDirectSpaceState2D *get_space_state() override;
-
- virtual real_t get_step() const override { return step; }
- PhysicsDirectBodyState2DSW() {
- singleton = this;
- body = nullptr;
- }
-};
-
#endif // BODY_2D_SW_H
diff --git a/servers/physics_2d/body_direct_state_2d_sw.cpp b/servers/physics_2d/body_direct_state_2d_sw.cpp
new file mode 100644
index 0000000000..b0673b9006
--- /dev/null
+++ b/servers/physics_2d/body_direct_state_2d_sw.cpp
@@ -0,0 +1,178 @@
+/*************************************************************************/
+/* body_direct_state_2d_sw.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 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 "body_direct_state_2d_sw.h"
+
+#include "body_2d_sw.h"
+#include "physics_server_2d_sw.h"
+#include "space_2d_sw.h"
+
+Vector2 PhysicsDirectBodyState2DSW::get_total_gravity() const {
+ return body->gravity;
+}
+
+real_t PhysicsDirectBodyState2DSW::get_total_angular_damp() const {
+ return body->area_angular_damp;
+}
+
+real_t PhysicsDirectBodyState2DSW::get_total_linear_damp() const {
+ return body->area_linear_damp;
+}
+
+Vector2 PhysicsDirectBodyState2DSW::get_center_of_mass() const {
+ return body->get_center_of_mass();
+}
+
+real_t PhysicsDirectBodyState2DSW::get_inverse_mass() const {
+ return body->get_inv_mass();
+}
+
+real_t PhysicsDirectBodyState2DSW::get_inverse_inertia() const {
+ return body->get_inv_inertia();
+}
+
+void PhysicsDirectBodyState2DSW::set_linear_velocity(const Vector2 &p_velocity) {
+ body->wakeup();
+ body->set_linear_velocity(p_velocity);
+}
+
+Vector2 PhysicsDirectBodyState2DSW::get_linear_velocity() const {
+ return body->get_linear_velocity();
+}
+
+void PhysicsDirectBodyState2DSW::set_angular_velocity(real_t p_velocity) {
+ body->wakeup();
+ body->set_angular_velocity(p_velocity);
+}
+
+real_t PhysicsDirectBodyState2DSW::get_angular_velocity() const {
+ return body->get_angular_velocity();
+}
+
+void PhysicsDirectBodyState2DSW::set_transform(const Transform2D &p_transform) {
+ body->set_state(PhysicsServer2D::BODY_STATE_TRANSFORM, p_transform);
+}
+
+Transform2D PhysicsDirectBodyState2DSW::get_transform() const {
+ return body->get_transform();
+}
+
+Vector2 PhysicsDirectBodyState2DSW::get_velocity_at_local_position(const Vector2 &p_position) const {
+ return body->get_velocity_in_local_point(p_position);
+}
+
+void PhysicsDirectBodyState2DSW::add_central_force(const Vector2 &p_force) {
+ body->wakeup();
+ body->add_central_force(p_force);
+}
+
+void PhysicsDirectBodyState2DSW::add_force(const Vector2 &p_force, const Vector2 &p_position) {
+ body->wakeup();
+ body->add_force(p_force, p_position);
+}
+
+void PhysicsDirectBodyState2DSW::add_torque(real_t p_torque) {
+ body->wakeup();
+ body->add_torque(p_torque);
+}
+
+void PhysicsDirectBodyState2DSW::apply_central_impulse(const Vector2 &p_impulse) {
+ body->wakeup();
+ body->apply_central_impulse(p_impulse);
+}
+
+void PhysicsDirectBodyState2DSW::apply_impulse(const Vector2 &p_impulse, const Vector2 &p_position) {
+ body->wakeup();
+ body->apply_impulse(p_impulse, p_position);
+}
+
+void PhysicsDirectBodyState2DSW::apply_torque_impulse(real_t p_torque) {
+ body->wakeup();
+ body->apply_torque_impulse(p_torque);
+}
+
+void PhysicsDirectBodyState2DSW::set_sleep_state(bool p_enable) {
+ body->set_active(!p_enable);
+}
+
+bool PhysicsDirectBodyState2DSW::is_sleeping() const {
+ return !body->is_active();
+}
+
+int PhysicsDirectBodyState2DSW::get_contact_count() const {
+ return body->contact_count;
+}
+
+Vector2 PhysicsDirectBodyState2DSW::get_contact_local_position(int p_contact_idx) const {
+ ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector2());
+ return body->contacts[p_contact_idx].local_pos;
+}
+
+Vector2 PhysicsDirectBodyState2DSW::get_contact_local_normal(int p_contact_idx) const {
+ ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector2());
+ return body->contacts[p_contact_idx].local_normal;
+}
+
+int PhysicsDirectBodyState2DSW::get_contact_local_shape(int p_contact_idx) const {
+ ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, -1);
+ return body->contacts[p_contact_idx].local_shape;
+}
+
+RID PhysicsDirectBodyState2DSW::get_contact_collider(int p_contact_idx) const {
+ ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, RID());
+ return body->contacts[p_contact_idx].collider;
+}
+Vector2 PhysicsDirectBodyState2DSW::get_contact_collider_position(int p_contact_idx) const {
+ ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector2());
+ return body->contacts[p_contact_idx].collider_pos;
+}
+
+ObjectID PhysicsDirectBodyState2DSW::get_contact_collider_id(int p_contact_idx) const {
+ ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, ObjectID());
+ return body->contacts[p_contact_idx].collider_instance_id;
+}
+
+int PhysicsDirectBodyState2DSW::get_contact_collider_shape(int p_contact_idx) const {
+ ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, 0);
+ return body->contacts[p_contact_idx].collider_shape;
+}
+
+Vector2 PhysicsDirectBodyState2DSW::get_contact_collider_velocity_at_position(int p_contact_idx) const {
+ ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector2());
+ return body->contacts[p_contact_idx].collider_velocity_at_pos;
+}
+
+PhysicsDirectSpaceState2D *PhysicsDirectBodyState2DSW::get_space_state() {
+ return body->get_space()->get_direct_state();
+}
+
+real_t PhysicsDirectBodyState2DSW::get_step() const {
+ return body->get_space()->get_last_step();
+}
diff --git a/servers/physics_2d/body_direct_state_2d_sw.h b/servers/physics_2d/body_direct_state_2d_sw.h
new file mode 100644
index 0000000000..4266b24842
--- /dev/null
+++ b/servers/physics_2d/body_direct_state_2d_sw.h
@@ -0,0 +1,91 @@
+/*************************************************************************/
+/* body_direct_state_2d_sw.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 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 BODY_DIRECT_STATE_2D_SW_H
+#define BODY_DIRECT_STATE_2D_SW_H
+
+#include "servers/physics_server_2d.h"
+
+class Body2DSW;
+
+class PhysicsDirectBodyState2DSW : public PhysicsDirectBodyState2D {
+ GDCLASS(PhysicsDirectBodyState2DSW, PhysicsDirectBodyState2D);
+
+public:
+ Body2DSW *body = nullptr;
+
+ virtual Vector2 get_total_gravity() const override;
+ virtual real_t get_total_angular_damp() const override;
+ virtual real_t get_total_linear_damp() const override;
+
+ virtual Vector2 get_center_of_mass() const override;
+ virtual real_t get_inverse_mass() const override;
+ virtual real_t get_inverse_inertia() const override;
+
+ virtual void set_linear_velocity(const Vector2 &p_velocity) override;
+ virtual Vector2 get_linear_velocity() const override;
+
+ virtual void set_angular_velocity(real_t p_velocity) override;
+ virtual real_t get_angular_velocity() const override;
+
+ virtual void set_transform(const Transform2D &p_transform) override;
+ virtual Transform2D get_transform() const override;
+
+ virtual Vector2 get_velocity_at_local_position(const Vector2 &p_position) const override;
+
+ virtual void add_central_force(const Vector2 &p_force) override;
+ virtual void add_force(const Vector2 &p_force, const Vector2 &p_position = Vector2()) override;
+ virtual void add_torque(real_t p_torque) override;
+ virtual void apply_central_impulse(const Vector2 &p_impulse) override;
+ virtual void apply_impulse(const Vector2 &p_impulse, const Vector2 &p_position = Vector2()) override;
+ virtual void apply_torque_impulse(real_t p_torque) override;
+
+ virtual void set_sleep_state(bool p_enable) override;
+ virtual bool is_sleeping() const override;
+
+ virtual int get_contact_count() const override;
+
+ virtual Vector2 get_contact_local_position(int p_contact_idx) const override;
+ virtual Vector2 get_contact_local_normal(int p_contact_idx) const override;
+ virtual int get_contact_local_shape(int p_contact_idx) const override;
+
+ virtual RID get_contact_collider(int p_contact_idx) const override;
+ virtual Vector2 get_contact_collider_position(int p_contact_idx) const override;
+ virtual ObjectID get_contact_collider_id(int p_contact_idx) const override;
+ virtual int get_contact_collider_shape(int p_contact_idx) const override;
+
+ virtual Vector2 get_contact_collider_velocity_at_position(int p_contact_idx) const override;
+
+ virtual PhysicsDirectSpaceState2D *get_space_state() override;
+
+ virtual real_t get_step() const override;
+};
+
+#endif // BODY_2D_SW_H
diff --git a/servers/physics_2d/body_pair_2d_sw.cpp b/servers/physics_2d/body_pair_2d_sw.cpp
index 91d747b492..8bcc4609f4 100644
--- a/servers/physics_2d/body_pair_2d_sw.cpp
+++ b/servers/physics_2d/body_pair_2d_sw.cpp
@@ -298,7 +298,7 @@ bool BodyPair2DSW::setup(real_t p_step) {
}
if (!prev_collided) {
- if (A->is_shape_set_as_one_way_collision(shape_A)) {
+ if (shape_B_ptr->allows_one_way_collision() && A->is_shape_set_as_one_way_collision(shape_A)) {
Vector2 direction = xform_A.get_axis(1).normalized();
bool valid = false;
for (int i = 0; i < contact_count; i++) {
@@ -319,7 +319,7 @@ bool BodyPair2DSW::setup(real_t p_step) {
}
}
- if (B->is_shape_set_as_one_way_collision(shape_B)) {
+ if (shape_A_ptr->allows_one_way_collision() && B->is_shape_set_as_one_way_collision(shape_B)) {
Vector2 direction = xform_B.get_axis(1).normalized();
bool valid = false;
for (int i = 0; i < contact_count; i++) {
diff --git a/servers/physics_2d/body_pair_2d_sw.h b/servers/physics_2d/body_pair_2d_sw.h
index 849a7e2430..db4f3eba69 100644
--- a/servers/physics_2d/body_pair_2d_sw.h
+++ b/servers/physics_2d/body_pair_2d_sw.h
@@ -59,17 +59,17 @@ class BodyPair2DSW : public Constraint2DSW {
Vector2 position;
Vector2 normal;
Vector2 local_A, local_B;
- real_t acc_normal_impulse; // accumulated normal impulse (Pn)
- real_t acc_tangent_impulse; // accumulated tangent impulse (Pt)
- real_t acc_bias_impulse; // accumulated normal impulse for position bias (Pnb)
- real_t mass_normal, mass_tangent;
- real_t bias;
+ real_t acc_normal_impulse = 0.0; // accumulated normal impulse (Pn)
+ real_t acc_tangent_impulse = 0.0; // accumulated tangent impulse (Pt)
+ real_t acc_bias_impulse = 0.0; // accumulated normal impulse for position bias (Pnb)
+ real_t mass_normal, mass_tangent = 0.0;
+ real_t bias = 0.0;
- real_t depth;
- bool active;
+ real_t depth = 0.0;
+ bool active = false;
Vector2 rA, rB;
- bool reused;
- real_t bounce;
+ bool reused = false;
+ real_t bounce = 0.0;
};
Vector2 offset_B; //use local A coordinates to avoid numerical issues on collision detection
diff --git a/servers/physics_2d/broad_phase_2d_bvh.cpp b/servers/physics_2d/broad_phase_2d_bvh.cpp
index 5f53f4a012..0df7086c5a 100644
--- a/servers/physics_2d/broad_phase_2d_bvh.cpp
+++ b/servers/physics_2d/broad_phase_2d_bvh.cpp
@@ -110,7 +110,4 @@ BroadPhase2DSW *BroadPhase2DBVH::_create() {
BroadPhase2DBVH::BroadPhase2DBVH() {
bvh.set_pair_callback(_pair_callback, this);
bvh.set_unpair_callback(_unpair_callback, this);
- pair_callback = nullptr;
- pair_userdata = nullptr;
- unpair_userdata = nullptr;
}
diff --git a/servers/physics_2d/broad_phase_2d_bvh.h b/servers/physics_2d/broad_phase_2d_bvh.h
index 6c11d2561b..ea02a98417 100644
--- a/servers/physics_2d/broad_phase_2d_bvh.h
+++ b/servers/physics_2d/broad_phase_2d_bvh.h
@@ -42,10 +42,10 @@ class BroadPhase2DBVH : public BroadPhase2DSW {
static void *_pair_callback(void *, uint32_t, CollisionObject2DSW *, int, uint32_t, CollisionObject2DSW *, int);
static void _unpair_callback(void *, uint32_t, CollisionObject2DSW *, int, uint32_t, CollisionObject2DSW *, int, void *);
- PairCallback pair_callback;
- void *pair_userdata;
- UnpairCallback unpair_callback;
- void *unpair_userdata;
+ PairCallback pair_callback = nullptr;
+ void *pair_userdata = nullptr;
+ UnpairCallback unpair_callback = nullptr;
+ void *unpair_userdata = nullptr;
public:
// 0 is an invalid ID
diff --git a/servers/physics_2d/collision_object_2d_sw.cpp b/servers/physics_2d/collision_object_2d_sw.cpp
index 5d1ef83165..bc7d277152 100644
--- a/servers/physics_2d/collision_object_2d_sw.cpp
+++ b/servers/physics_2d/collision_object_2d_sw.cpp
@@ -61,11 +61,6 @@ void CollisionObject2DSW::set_shape(int p_index, Shape2DSW *p_shape) {
}
}
-void CollisionObject2DSW::set_shape_metadata(int p_index, const Variant &p_metadata) {
- ERR_FAIL_INDEX(p_index, shapes.size());
- shapes.write[p_index].metadata = p_metadata;
-}
-
void CollisionObject2DSW::set_shape_transform(int p_index, const Transform2D &p_transform) {
ERR_FAIL_INDEX(p_index, shapes.size());
@@ -244,10 +239,5 @@ void CollisionObject2DSW::_shape_changed() {
CollisionObject2DSW::CollisionObject2DSW(Type p_type) :
pending_shape_update_list(this) {
- _static = true;
type = p_type;
- space = nullptr;
- collision_mask = 1;
- collision_layer = 1;
- pickable = true;
}
diff --git a/servers/physics_2d/collision_object_2d_sw.h b/servers/physics_2d/collision_object_2d_sw.h
index 55ffa9b1b8..ca258a906a 100644
--- a/servers/physics_2d/collision_object_2d_sw.h
+++ b/servers/physics_2d/collision_object_2d_sw.h
@@ -50,32 +50,26 @@ private:
RID self;
ObjectID instance_id;
ObjectID canvas_instance_id;
- bool pickable;
+ bool pickable = true;
struct Shape {
Transform2D xform;
Transform2D xform_inv;
- BroadPhase2DSW::ID bpid;
+ BroadPhase2DSW::ID bpid = 0;
Rect2 aabb_cache; //for rayqueries
- Shape2DSW *shape;
- Variant metadata;
- bool disabled;
- bool one_way_collision;
- real_t one_way_collision_margin;
- Shape() {
- disabled = false;
- one_way_collision = false;
- one_way_collision_margin = 0;
- }
+ Shape2DSW *shape = nullptr;
+ bool disabled = false;
+ bool one_way_collision = false;
+ real_t one_way_collision_margin = 0.0;
};
Vector<Shape> shapes;
- Space2DSW *space;
+ Space2DSW *space = nullptr;
Transform2D transform;
Transform2D inv_transform;
- uint32_t collision_mask;
- uint32_t collision_layer;
- bool _static;
+ uint32_t collision_mask = 1;
+ uint32_t collision_layer = 1;
+ bool _static = true;
SelfList<CollisionObject2DSW> pending_shape_update_list;
@@ -115,7 +109,6 @@ public:
void add_shape(Shape2DSW *p_shape, const Transform2D &p_transform = Transform2D(), bool p_disabled = false);
void set_shape(int p_index, Shape2DSW *p_shape);
void set_shape_transform(int p_index, const Transform2D &p_transform);
- void set_shape_metadata(int p_index, const Variant &p_metadata);
_FORCE_INLINE_ int get_shape_count() const { return shapes.size(); }
_FORCE_INLINE_ Shape2DSW *get_shape(int p_index) const {
@@ -134,10 +127,6 @@ public:
CRASH_BAD_INDEX(p_index, shapes.size());
return shapes[p_index].aabb_cache;
}
- _FORCE_INLINE_ const Variant &get_shape_metadata(int p_index) const {
- CRASH_BAD_INDEX(p_index, shapes.size());
- return shapes[p_index].metadata;
- }
_FORCE_INLINE_ const Transform2D &get_transform() const { return transform; }
_FORCE_INLINE_ const Transform2D &get_inv_transform() const { return inv_transform; }
diff --git a/servers/physics_2d/collision_solver_2d_sat.cpp b/servers/physics_2d/collision_solver_2d_sat.cpp
index 30a99d3d74..2e67cc6520 100644
--- a/servers/physics_2d/collision_solver_2d_sat.cpp
+++ b/servers/physics_2d/collision_solver_2d_sat.cpp
@@ -34,11 +34,11 @@
struct _CollectorCallback2D {
CollisionSolver2DSW::CallbackResult callback;
- void *userdata;
- bool swap;
- bool collided;
+ void *userdata = nullptr;
+ bool swap = false;
+ bool collided = false;
Vector2 normal;
- Vector2 *sep_axis;
+ Vector2 *sep_axis = nullptr;
_FORCE_INLINE_ void call(const Vector2 &p_point_A, const Vector2 &p_point_B) {
/*
@@ -75,9 +75,9 @@ _FORCE_INLINE_ static void _generate_contacts_point_edge(const Vector2 *p_points
}
struct _generate_contacts_Pair {
- bool a;
- int idx;
- real_t d;
+ bool a = false;
+ int idx = 0;
+ real_t d = 0.0;
_FORCE_INLINE_ bool operator<(const _generate_contacts_Pair &l) const { return d < l.d; }
};
@@ -146,10 +146,10 @@ static void _generate_contacts_from_supports(const Vector2 *p_points_A, int p_po
}
};
- int pointcount_B;
- int pointcount_A;
- const Vector2 *points_A;
- const Vector2 *points_B;
+ int pointcount_B = 0;
+ int pointcount_A = 0;
+ const Vector2 *points_A = nullptr;
+ const Vector2 *points_B = nullptr;
if (p_point_count_A > p_point_count_B) {
//swap
@@ -177,18 +177,20 @@ static void _generate_contacts_from_supports(const Vector2 *p_points_A, int p_po
template <class ShapeA, class ShapeB, bool castA = false, bool castB = false, bool withMargin = false>
class SeparatorAxisTest2D {
- const ShapeA *shape_A;
- const ShapeB *shape_B;
- const Transform2D *transform_A;
- const Transform2D *transform_B;
- real_t best_depth;
+ const ShapeA *shape_A = nullptr;
+ const ShapeB *shape_B = nullptr;
+ const Transform2D *transform_A = nullptr;
+ const Transform2D *transform_B = nullptr;
+ real_t best_depth = 1e15;
Vector2 best_axis;
- int best_axis_count;
- int best_axis_index;
+#ifdef DEBUG_ENABLED
+ int best_axis_count = 0;
+ int best_axis_index = -1;
+#endif
Vector2 motion_A;
Vector2 motion_B;
- real_t margin_A;
- real_t margin_B;
+ real_t margin_A = 0.0;
+ real_t margin_B = 0.0;
_CollectorCallback2D *callback;
public:
@@ -364,19 +366,13 @@ public:
_FORCE_INLINE_ SeparatorAxisTest2D(const ShapeA *p_shape_A, const Transform2D &p_transform_a, const ShapeB *p_shape_B, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_A = Vector2(), const Vector2 &p_motion_B = Vector2(), real_t p_margin_A = 0, real_t p_margin_B = 0) {
margin_A = p_margin_A;
margin_B = p_margin_B;
- best_depth = 1e15;
shape_A = p_shape_A;
shape_B = p_shape_B;
transform_A = &p_transform_a;
transform_B = &p_transform_b;
motion_A = p_motion_A;
motion_B = p_motion_B;
-
callback = p_collector;
-#ifdef DEBUG_ENABLED
- best_axis_count = 0;
- best_axis_index = -1;
-#endif
}
};
@@ -1114,12 +1110,14 @@ static void _collision_convex_polygon_convex_polygon(const Shape2DSW *p_a, const
bool sat_2d_calculate_penetration(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Vector2 &p_motion_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, CollisionSolver2DSW::CallbackResult p_result_callback, void *p_userdata, bool p_swap, Vector2 *sep_axis, real_t p_margin_A, real_t p_margin_B) {
PhysicsServer2D::ShapeType type_A = p_shape_A->get_type();
- ERR_FAIL_COND_V(type_A == PhysicsServer2D::SHAPE_WORLD_MARGIN, false);
+ ERR_FAIL_COND_V(type_A == PhysicsServer2D::SHAPE_WORLD_BOUNDARY, false);
+ ERR_FAIL_COND_V(type_A == PhysicsServer2D::SHAPE_SEPARATION_RAY, false);
ERR_FAIL_COND_V(p_shape_A->is_concave(), false);
PhysicsServer2D::ShapeType type_B = p_shape_B->get_type();
- ERR_FAIL_COND_V(type_B == PhysicsServer2D::SHAPE_WORLD_MARGIN, false);
+ ERR_FAIL_COND_V(type_B == PhysicsServer2D::SHAPE_WORLD_BOUNDARY, false);
+ ERR_FAIL_COND_V(type_B == PhysicsServer2D::SHAPE_SEPARATION_RAY, false);
ERR_FAIL_COND_V(p_shape_B->is_concave(), false);
static const CollisionFunc collision_table[5][5] = {
@@ -1382,23 +1380,23 @@ bool sat_2d_calculate_penetration(const Shape2DSW *p_shape_A, const Transform2D
if (p_margin_A || p_margin_B) {
if (*motion_A == Vector2() && *motion_B == Vector2()) {
- collision_func = collision_table_margin[type_A - 1][type_B - 1];
+ collision_func = collision_table_margin[type_A - 2][type_B - 2];
} else if (*motion_A != Vector2() && *motion_B == Vector2()) {
- collision_func = collision_table_castA_margin[type_A - 1][type_B - 1];
+ collision_func = collision_table_castA_margin[type_A - 2][type_B - 2];
} else if (*motion_A == Vector2() && *motion_B != Vector2()) {
- collision_func = collision_table_castB_margin[type_A - 1][type_B - 1];
+ collision_func = collision_table_castB_margin[type_A - 2][type_B - 2];
} else {
- collision_func = collision_table_castA_castB_margin[type_A - 1][type_B - 1];
+ collision_func = collision_table_castA_castB_margin[type_A - 2][type_B - 2];
}
} else {
if (*motion_A == Vector2() && *motion_B == Vector2()) {
- collision_func = collision_table[type_A - 1][type_B - 1];
+ collision_func = collision_table[type_A - 2][type_B - 2];
} else if (*motion_A != Vector2() && *motion_B == Vector2()) {
- collision_func = collision_table_castA[type_A - 1][type_B - 1];
+ collision_func = collision_table_castA[type_A - 2][type_B - 2];
} else if (*motion_A == Vector2() && *motion_B != Vector2()) {
- collision_func = collision_table_castB[type_A - 1][type_B - 1];
+ collision_func = collision_table_castB[type_A - 2][type_B - 2];
} else {
- collision_func = collision_table_castA_castB[type_A - 1][type_B - 1];
+ collision_func = collision_table_castA_castB[type_A - 2][type_B - 2];
}
}
diff --git a/servers/physics_2d/collision_solver_2d_sw.cpp b/servers/physics_2d/collision_solver_2d_sw.cpp
index 8f8a4a862c..527bb1b0b2 100644
--- a/servers/physics_2d/collision_solver_2d_sw.cpp
+++ b/servers/physics_2d/collision_solver_2d_sw.cpp
@@ -34,14 +34,14 @@
#define collision_solver sat_2d_calculate_penetration
//#define collision_solver gjk_epa_calculate_penetration
-bool CollisionSolver2DSW::solve_static_world_margin(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result) {
- const WorldMarginShape2DSW *world_margin = static_cast<const WorldMarginShape2DSW *>(p_shape_A);
- if (p_shape_B->get_type() == PhysicsServer2D::SHAPE_WORLD_MARGIN) {
+bool CollisionSolver2DSW::solve_static_world_boundary(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result) {
+ const WorldBoundaryShape2DSW *world_boundary = static_cast<const WorldBoundaryShape2DSW *>(p_shape_A);
+ if (p_shape_B->get_type() == PhysicsServer2D::SHAPE_WORLD_BOUNDARY) {
return false;
}
- Vector2 n = p_transform_A.basis_xform(world_margin->get_normal()).normalized();
- Vector2 p = p_transform_A.xform(world_margin->get_normal() * world_margin->get_d());
+ Vector2 n = p_transform_A.basis_xform(world_boundary->get_normal()).normalized();
+ Vector2 p = p_transform_A.xform(world_boundary->get_normal() * world_boundary->get_d());
real_t d = n.dot(p);
Vector2 supports[2];
@@ -73,40 +73,99 @@ bool CollisionSolver2DSW::solve_static_world_margin(const Shape2DSW *p_shape_A,
return found;
}
+bool CollisionSolver2DSW::solve_separation_ray(const Shape2DSW *p_shape_A, const Vector2 &p_motion_A, const Transform2D &p_transform_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, Vector2 *r_sep_axis, real_t p_margin) {
+ const SeparationRayShape2DSW *ray = static_cast<const SeparationRayShape2DSW *>(p_shape_A);
+ if (p_shape_B->get_type() == PhysicsServer2D::SHAPE_SEPARATION_RAY) {
+ return false;
+ }
+
+ Vector2 from = p_transform_A.get_origin();
+ Vector2 to = from + p_transform_A[1] * (ray->get_length() + p_margin);
+ if (p_motion_A != Vector2()) {
+ //not the best but should be enough
+ Vector2 normal = (to - from).normalized();
+ to += normal * MAX(0.0, normal.dot(p_motion_A));
+ }
+ Vector2 support_A = to;
+
+ Transform2D invb = p_transform_B.affine_inverse();
+ from = invb.xform(from);
+ to = invb.xform(to);
+
+ Vector2 p, n;
+ if (!p_shape_B->intersect_segment(from, to, p, n)) {
+ if (r_sep_axis) {
+ *r_sep_axis = p_transform_A[1].normalized();
+ }
+ return false;
+ }
+
+ // Discard contacts when the ray is fully contained inside the shape.
+ if (n == Vector2()) {
+ if (r_sep_axis) {
+ *r_sep_axis = p_transform_A[1].normalized();
+ }
+ return false;
+ }
+
+ // Discard contacts in the wrong direction.
+ if (n.dot(from - to) < CMP_EPSILON) {
+ if (r_sep_axis) {
+ *r_sep_axis = p_transform_A[1].normalized();
+ }
+ return false;
+ }
+
+ Vector2 support_B = p_transform_B.xform(p);
+ if (ray->get_slide_on_slope()) {
+ Vector2 global_n = invb.basis_xform_inv(n).normalized();
+ support_B = support_A + (support_B - support_A).length() * global_n;
+ }
+
+ if (p_result_callback) {
+ if (p_swap_result) {
+ p_result_callback(support_B, support_A, p_userdata);
+ } else {
+ p_result_callback(support_A, support_B, p_userdata);
+ }
+ }
+ return true;
+}
+
struct _ConcaveCollisionInfo2D {
- const Transform2D *transform_A;
- const Shape2DSW *shape_A;
- const Transform2D *transform_B;
+ const Transform2D *transform_A = nullptr;
+ const Shape2DSW *shape_A = nullptr;
+ const Transform2D *transform_B = nullptr;
Vector2 motion_A;
Vector2 motion_B;
- real_t margin_A;
- real_t margin_B;
+ real_t margin_A = 0.0;
+ real_t margin_B = 0.0;
CollisionSolver2DSW::CallbackResult result_callback;
- void *userdata;
- bool swap_result;
- bool collided;
- int aabb_tests;
- int collisions;
- Vector2 *sep_axis;
+ void *userdata = nullptr;
+ bool swap_result = false;
+ bool collided = false;
+ int aabb_tests = 0;
+ int collisions = 0;
+ Vector2 *sep_axis = nullptr;
};
-void CollisionSolver2DSW::concave_callback(void *p_userdata, Shape2DSW *p_convex) {
+bool CollisionSolver2DSW::concave_callback(void *p_userdata, Shape2DSW *p_convex) {
_ConcaveCollisionInfo2D &cinfo = *(_ConcaveCollisionInfo2D *)(p_userdata);
cinfo.aabb_tests++;
- if (!cinfo.result_callback && cinfo.collided) {
- return; //already collided and no contacts requested, don't test anymore
- }
bool collided = collision_solver(cinfo.shape_A, *cinfo.transform_A, cinfo.motion_A, p_convex, *cinfo.transform_B, cinfo.motion_B, cinfo.result_callback, cinfo.userdata, cinfo.swap_result, cinfo.sep_axis, cinfo.margin_A, cinfo.margin_B);
if (!collided) {
- return;
+ return false;
}
cinfo.collided = true;
cinfo.collisions++;
+
+ // Stop at first collision if contacts are not needed.
+ return !cinfo.result_callback;
}
-bool CollisionSolver2DSW::solve_concave(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Vector2 &p_motion_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, Vector2 *sep_axis, real_t p_margin_A, real_t p_margin_B) {
+bool CollisionSolver2DSW::solve_concave(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Vector2 &p_motion_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, Vector2 *r_sep_axis, real_t p_margin_A, real_t p_margin_B) {
const ConcaveShape2DSW *concave_B = static_cast<const ConcaveShape2DSW *>(p_shape_B);
_ConcaveCollisionInfo2D cinfo;
@@ -119,7 +178,7 @@ bool CollisionSolver2DSW::solve_concave(const Shape2DSW *p_shape_A, const Transf
cinfo.swap_result = p_swap_result;
cinfo.collided = false;
cinfo.collisions = 0;
- cinfo.sep_axis = sep_axis;
+ cinfo.sep_axis = r_sep_axis;
cinfo.margin_A = p_margin_A;
cinfo.margin_B = p_margin_B;
@@ -150,7 +209,7 @@ bool CollisionSolver2DSW::solve_concave(const Shape2DSW *p_shape_A, const Transf
return cinfo.collided;
}
-bool CollisionSolver2DSW::solve(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Vector2 &p_motion_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, CallbackResult p_result_callback, void *p_userdata, Vector2 *sep_axis, real_t p_margin_A, real_t p_margin_B) {
+bool CollisionSolver2DSW::solve(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Vector2 &p_motion_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, CallbackResult p_result_callback, void *p_userdata, Vector2 *r_sep_axis, real_t p_margin_A, real_t p_margin_B) {
PhysicsServer2D::ShapeType type_A = p_shape_A->get_type();
PhysicsServer2D::ShapeType type_B = p_shape_B->get_type();
bool concave_A = p_shape_A->is_concave();
@@ -166,15 +225,26 @@ bool CollisionSolver2DSW::solve(const Shape2DSW *p_shape_A, const Transform2D &p
swap = true;
}
- if (type_A == PhysicsServer2D::SHAPE_WORLD_MARGIN) {
- if (type_B == PhysicsServer2D::SHAPE_WORLD_MARGIN) {
+ if (type_A == PhysicsServer2D::SHAPE_WORLD_BOUNDARY) {
+ if (type_B == PhysicsServer2D::SHAPE_WORLD_BOUNDARY) {
return false;
}
if (swap) {
- return solve_static_world_margin(p_shape_B, p_transform_B, p_shape_A, p_transform_A, p_result_callback, p_userdata, true);
+ return solve_static_world_boundary(p_shape_B, p_transform_B, p_shape_A, p_transform_A, p_result_callback, p_userdata, true);
+ } else {
+ return solve_static_world_boundary(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false);
+ }
+
+ } else if (type_A == PhysicsServer2D::SHAPE_SEPARATION_RAY) {
+ if (type_B == PhysicsServer2D::SHAPE_SEPARATION_RAY) {
+ return false; //no ray-ray
+ }
+
+ if (swap) {
+ return solve_separation_ray(p_shape_B, p_motion_B, p_transform_B, p_shape_A, p_transform_A, p_result_callback, p_userdata, true, r_sep_axis, p_margin_B);
} else {
- return solve_static_world_margin(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false);
+ return solve_separation_ray(p_shape_A, p_motion_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false, r_sep_axis, p_margin_A);
}
} else if (concave_B) {
@@ -183,12 +253,12 @@ bool CollisionSolver2DSW::solve(const Shape2DSW *p_shape_A, const Transform2D &p
}
if (!swap) {
- return solve_concave(p_shape_A, p_transform_A, p_motion_A, p_shape_B, p_transform_B, p_motion_B, p_result_callback, p_userdata, false, sep_axis, margin_A, margin_B);
+ return solve_concave(p_shape_A, p_transform_A, p_motion_A, p_shape_B, p_transform_B, p_motion_B, p_result_callback, p_userdata, false, r_sep_axis, margin_A, margin_B);
} else {
- return solve_concave(p_shape_B, p_transform_B, p_motion_B, p_shape_A, p_transform_A, p_motion_A, p_result_callback, p_userdata, true, sep_axis, margin_A, margin_B);
+ return solve_concave(p_shape_B, p_transform_B, p_motion_B, p_shape_A, p_transform_A, p_motion_A, p_result_callback, p_userdata, true, r_sep_axis, margin_A, margin_B);
}
} else {
- return collision_solver(p_shape_A, p_transform_A, p_motion_A, p_shape_B, p_transform_B, p_motion_B, p_result_callback, p_userdata, false, sep_axis, margin_A, margin_B);
+ return collision_solver(p_shape_A, p_transform_A, p_motion_A, p_shape_B, p_transform_B, p_motion_B, p_result_callback, p_userdata, false, r_sep_axis, margin_A, margin_B);
}
}
diff --git a/servers/physics_2d/collision_solver_2d_sw.h b/servers/physics_2d/collision_solver_2d_sw.h
index 17c0c2fe70..b87247b89a 100644
--- a/servers/physics_2d/collision_solver_2d_sw.h
+++ b/servers/physics_2d/collision_solver_2d_sw.h
@@ -38,13 +38,13 @@ public:
typedef void (*CallbackResult)(const Vector2 &p_point_A, const Vector2 &p_point_B, void *p_userdata);
private:
- static bool solve_static_world_margin(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result);
- static void concave_callback(void *p_userdata, Shape2DSW *p_convex);
- static bool solve_concave(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Vector2 &p_motion_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, Vector2 *sep_axis = nullptr, real_t p_margin_A = 0, real_t p_margin_B = 0);
- static bool solve_raycast(const Shape2DSW *p_shape_A, const Vector2 &p_motion_A, const Transform2D &p_transform_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, Vector2 *sep_axis = nullptr);
+ static bool solve_static_world_boundary(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result);
+ static bool concave_callback(void *p_userdata, Shape2DSW *p_convex);
+ static bool solve_concave(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Vector2 &p_motion_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, Vector2 *r_sep_axis = nullptr, real_t p_margin_A = 0, real_t p_margin_B = 0);
+ static bool solve_separation_ray(const Shape2DSW *p_shape_A, const Vector2 &p_motion_A, const Transform2D &p_transform_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, Vector2 *r_sep_axis = nullptr, real_t p_margin = 0);
public:
- static bool solve(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Vector2 &p_motion_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, CallbackResult p_result_callback, void *p_userdata, Vector2 *sep_axis = nullptr, real_t p_margin_A = 0, real_t p_margin_B = 0);
+ static bool solve(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Vector2 &p_motion_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, CallbackResult p_result_callback, void *p_userdata, Vector2 *r_sep_axis = nullptr, real_t p_margin_A = 0, real_t p_margin_B = 0);
};
#endif // COLLISION_SOLVER_2D_SW_H
diff --git a/servers/physics_2d/constraint_2d_sw.h b/servers/physics_2d/constraint_2d_sw.h
index 5e8dfbe570..df300d666d 100644
--- a/servers/physics_2d/constraint_2d_sw.h
+++ b/servers/physics_2d/constraint_2d_sw.h
@@ -36,8 +36,8 @@
class Constraint2DSW {
Body2DSW **_body_ptr;
int _body_count;
- uint64_t island_step;
- bool disabled_collisions_between_bodies;
+ uint64_t island_step = 0;
+ bool disabled_collisions_between_bodies = true;
RID self;
@@ -45,8 +45,6 @@ protected:
Constraint2DSW(Body2DSW **p_body_ptr = nullptr, int p_body_count = 0) {
_body_ptr = p_body_ptr;
_body_count = p_body_count;
- island_step = 0;
- disabled_collisions_between_bodies = true;
}
public:
diff --git a/servers/physics_2d/joints_2d_sw.cpp b/servers/physics_2d/joints_2d_sw.cpp
index 5a0a628fbc..b46397b8e6 100644
--- a/servers/physics_2d/joints_2d_sw.cpp
+++ b/servers/physics_2d/joints_2d_sw.cpp
@@ -64,17 +64,17 @@ void Joint2DSW::copy_settings_from(Joint2DSW *p_joint) {
}
static inline real_t k_scalar(Body2DSW *a, Body2DSW *b, const Vector2 &rA, const Vector2 &rB, const Vector2 &n) {
- real_t value = 0;
+ real_t value = 0.0;
{
value += a->get_inv_mass();
- real_t rcn = rA.cross(n);
+ real_t rcn = (rA - a->get_center_of_mass()).cross(n);
value += a->get_inv_inertia() * rcn * rcn;
}
if (b) {
value += b->get_inv_mass();
- real_t rcn = rB.cross(n);
+ real_t rcn = (rB - b->get_center_of_mass()).cross(n);
value += b->get_inv_inertia() * rcn * rcn;
}
@@ -83,9 +83,9 @@ static inline real_t k_scalar(Body2DSW *a, Body2DSW *b, const Vector2 &rA, const
static inline Vector2
relative_velocity(Body2DSW *a, Body2DSW *b, Vector2 rA, Vector2 rB) {
- Vector2 sum = a->get_linear_velocity() - rA.orthogonal() * a->get_angular_velocity();
+ Vector2 sum = a->get_linear_velocity() - (rA - a->get_center_of_mass()).orthogonal() * a->get_angular_velocity();
if (b) {
- return (b->get_linear_velocity() - rB.orthogonal() * b->get_angular_velocity()) - sum;
+ return (b->get_linear_velocity() - (rB - b->get_center_of_mass()).orthogonal() * b->get_angular_velocity()) - sum;
} else {
return -sum;
}
@@ -172,11 +172,11 @@ bool PinJoint2DSW::pre_solve(real_t p_step) {
void PinJoint2DSW::solve(real_t p_step) {
// compute relative velocity
- Vector2 vA = A->get_linear_velocity() - custom_cross(rA, A->get_angular_velocity());
+ Vector2 vA = A->get_linear_velocity() - custom_cross(rA - A->get_center_of_mass(), A->get_angular_velocity());
Vector2 rel_vel;
if (B) {
- rel_vel = B->get_linear_velocity() - custom_cross(rB, B->get_angular_velocity()) - vA;
+ rel_vel = B->get_linear_velocity() - custom_cross(rB - B->get_center_of_mass(), B->get_angular_velocity()) - vA;
} else {
rel_vel = -vA;
}
@@ -213,8 +213,6 @@ PinJoint2DSW::PinJoint2DSW(const Vector2 &p_pos, Body2DSW *p_body_a, Body2DSW *p
anchor_A = p_body_a->get_inv_transform().xform(p_pos);
anchor_B = p_body_b ? p_body_b->get_inv_transform().xform(p_pos) : p_pos;
- softness = 0;
-
p_body_a->add_constraint(this, 0);
if (p_body_b) {
p_body_b->add_constraint(this, 1);
@@ -238,6 +236,9 @@ k_tensor(Body2DSW *a, Body2DSW *b, Vector2 r1, Vector2 r2, Vector2 *k1, Vector2
k21 = 0.0f;
k22 = m_sum;
+ r1 -= a->get_center_of_mass();
+ r2 -= b->get_center_of_mass();
+
// add the influence from r1
real_t a_i_inv = a->get_inv_inertia();
real_t r1xsq = r1.x * r1.x * a_i_inv;
@@ -479,8 +480,6 @@ DampedSpringJoint2DSW::DampedSpringJoint2DSW(const Vector2 &p_anchor_a, const Ve
anchor_B = B->get_inv_transform().xform(p_anchor_b);
rest_length = p_anchor_a.distance_to(p_anchor_b);
- stiffness = 20;
- damping = 1.5;
A->add_constraint(this, 0);
B->add_constraint(this, 1);
diff --git a/servers/physics_2d/joints_2d_sw.h b/servers/physics_2d/joints_2d_sw.h
index ccc5c585a0..e2a7c0c91e 100644
--- a/servers/physics_2d/joints_2d_sw.h
+++ b/servers/physics_2d/joints_2d_sw.h
@@ -35,9 +35,9 @@
#include "constraint_2d_sw.h"
class Joint2DSW : public Constraint2DSW {
- real_t max_force;
- real_t bias;
- real_t max_bias;
+ real_t bias = 0;
+ real_t max_bias = 3.40282e+38;
+ real_t max_force = 3.40282e+38;
protected:
bool dynamic_A = false;
@@ -61,10 +61,7 @@ public:
virtual PhysicsServer2D::JointType get_type() const { return PhysicsServer2D::JOINT_TYPE_MAX; }
Joint2DSW(Body2DSW **p_body_ptr = nullptr, int p_body_count = 0) :
- Constraint2DSW(p_body_ptr, p_body_count) {
- bias = 0;
- max_force = max_bias = 3.40282e+38;
- };
+ Constraint2DSW(p_body_ptr, p_body_count) {}
virtual ~Joint2DSW() {
for (int i = 0; i < get_body_count(); i++) {
@@ -83,7 +80,7 @@ class PinJoint2DSW : public Joint2DSW {
Body2DSW *B;
};
- Body2DSW *_arr[2];
+ Body2DSW *_arr[2] = { nullptr, nullptr };
};
Transform2D M;
@@ -92,7 +89,7 @@ class PinJoint2DSW : public Joint2DSW {
Vector2 anchor_B;
Vector2 bias;
Vector2 P;
- real_t softness;
+ real_t softness = 0.0;
public:
virtual PhysicsServer2D::JointType get_type() const override { return PhysicsServer2D::JOINT_TYPE_PIN; }
@@ -114,7 +111,7 @@ class GrooveJoint2DSW : public Joint2DSW {
Body2DSW *B;
};
- Body2DSW *_arr[2];
+ Body2DSW *_arr[2] = { nullptr, nullptr };
};
Vector2 A_groove_1;
@@ -123,13 +120,13 @@ class GrooveJoint2DSW : public Joint2DSW {
Vector2 B_anchor;
Vector2 jn_acc;
Vector2 gbias;
- real_t jn_max;
- real_t clamp;
+ real_t jn_max = 0.0;
+ real_t clamp = 0.0;
Vector2 xf_normal;
Vector2 rA, rB;
Vector2 k1, k2;
- bool correct;
+ bool correct = false;
public:
virtual PhysicsServer2D::JointType get_type() const override { return PhysicsServer2D::JOINT_TYPE_GROOVE; }
@@ -148,22 +145,22 @@ class DampedSpringJoint2DSW : public Joint2DSW {
Body2DSW *B;
};
- Body2DSW *_arr[2];
+ Body2DSW *_arr[2] = { nullptr, nullptr };
};
Vector2 anchor_A;
Vector2 anchor_B;
- real_t rest_length;
- real_t damping;
- real_t stiffness;
+ real_t rest_length = 0.0;
+ real_t damping = 1.5;
+ real_t stiffness = 20.0;
Vector2 rA, rB;
Vector2 n;
Vector2 j;
- real_t n_mass;
- real_t target_vrn;
- real_t v_coef;
+ real_t n_mass = 0.0;
+ real_t target_vrn = 0.0;
+ real_t v_coef = 0.0;
public:
virtual PhysicsServer2D::JointType get_type() const override { return PhysicsServer2D::JOINT_TYPE_DAMPED_SPRING; }
diff --git a/servers/physics_2d/physics_server_2d_sw.cpp b/servers/physics_2d/physics_server_2d_sw.cpp
index 88c097453e..c2205e33b0 100644
--- a/servers/physics_2d/physics_server_2d_sw.cpp
+++ b/servers/physics_2d/physics_server_2d_sw.cpp
@@ -30,6 +30,7 @@
#include "physics_server_2d_sw.h"
+#include "body_direct_state_2d_sw.h"
#include "broad_phase_2d_bvh.h"
#include "collision_solver_2d_sw.h"
#include "core/config/project_settings.h"
@@ -42,8 +43,11 @@
RID PhysicsServer2DSW::_shape_create(ShapeType p_shape) {
Shape2DSW *shape = nullptr;
switch (p_shape) {
- case SHAPE_WORLD_MARGIN: {
- shape = memnew(WorldMarginShape2DSW);
+ case SHAPE_WORLD_BOUNDARY: {
+ shape = memnew(WorldBoundaryShape2DSW);
+ } break;
+ case SHAPE_SEPARATION_RAY: {
+ shape = memnew(SeparationRayShape2DSW);
} break;
case SHAPE_SEGMENT: {
shape = memnew(SegmentShape2DSW);
@@ -75,8 +79,12 @@ RID PhysicsServer2DSW::_shape_create(ShapeType p_shape) {
return id;
}
-RID PhysicsServer2DSW::world_margin_shape_create() {
- return _shape_create(SHAPE_WORLD_MARGIN);
+RID PhysicsServer2DSW::world_boundary_shape_create() {
+ return _shape_create(SHAPE_WORLD_BOUNDARY);
+}
+
+RID PhysicsServer2DSW::separation_ray_shape_create() {
+ return _shape_create(SHAPE_SEPARATION_RAY);
}
RID PhysicsServer2DSW::segment_shape_create() {
@@ -104,32 +112,32 @@ RID PhysicsServer2DSW::concave_polygon_shape_create() {
}
void PhysicsServer2DSW::shape_set_data(RID p_shape, const Variant &p_data) {
- Shape2DSW *shape = shape_owner.getornull(p_shape);
+ Shape2DSW *shape = shape_owner.get_or_null(p_shape);
ERR_FAIL_COND(!shape);
shape->set_data(p_data);
};
void PhysicsServer2DSW::shape_set_custom_solver_bias(RID p_shape, real_t p_bias) {
- Shape2DSW *shape = shape_owner.getornull(p_shape);
+ Shape2DSW *shape = shape_owner.get_or_null(p_shape);
ERR_FAIL_COND(!shape);
shape->set_custom_bias(p_bias);
}
PhysicsServer2D::ShapeType PhysicsServer2DSW::shape_get_type(RID p_shape) const {
- const Shape2DSW *shape = shape_owner.getornull(p_shape);
+ const Shape2DSW *shape = shape_owner.get_or_null(p_shape);
ERR_FAIL_COND_V(!shape, SHAPE_CUSTOM);
return shape->get_type();
};
Variant PhysicsServer2DSW::shape_get_data(RID p_shape) const {
- const Shape2DSW *shape = shape_owner.getornull(p_shape);
+ const Shape2DSW *shape = shape_owner.get_or_null(p_shape);
ERR_FAIL_COND_V(!shape, Variant());
ERR_FAIL_COND_V(!shape->is_configured(), Variant());
return shape->get_data();
};
real_t PhysicsServer2DSW::shape_get_custom_solver_bias(RID p_shape) const {
- const Shape2DSW *shape = shape_owner.getornull(p_shape);
+ const Shape2DSW *shape = shape_owner.get_or_null(p_shape);
ERR_FAIL_COND_V(!shape, 0);
return shape->get_custom_bias();
}
@@ -185,9 +193,9 @@ void PhysicsServer2DSW::_shape_col_cbk(const Vector2 &p_point_A, const Vector2 &
}
bool PhysicsServer2DSW::shape_collide(RID p_shape_A, const Transform2D &p_xform_A, const Vector2 &p_motion_A, RID p_shape_B, const Transform2D &p_xform_B, const Vector2 &p_motion_B, Vector2 *r_results, int p_result_max, int &r_result_count) {
- Shape2DSW *shape_A = shape_owner.getornull(p_shape_A);
+ Shape2DSW *shape_A = shape_owner.get_or_null(p_shape_A);
ERR_FAIL_COND_V(!shape_A, false);
- Shape2DSW *shape_B = shape_owner.getornull(p_shape_B);
+ Shape2DSW *shape_B = shape_owner.get_or_null(p_shape_B);
ERR_FAIL_COND_V(!shape_B, false);
if (p_result_max == 0) {
@@ -210,7 +218,7 @@ RID PhysicsServer2DSW::space_create() {
RID id = space_owner.make_rid(space);
space->set_self(id);
RID area_id = area_create();
- Area2DSW *area = area_owner.getornull(area_id);
+ Area2DSW *area = area_owner.get_or_null(area_id);
ERR_FAIL_COND_V(!area, RID());
space->set_default_area(area);
area->set_space(space);
@@ -220,7 +228,7 @@ RID PhysicsServer2DSW::space_create() {
};
void PhysicsServer2DSW::space_set_active(RID p_space, bool p_active) {
- Space2DSW *space = space_owner.getornull(p_space);
+ Space2DSW *space = space_owner.get_or_null(p_space);
ERR_FAIL_COND(!space);
if (p_active) {
active_spaces.insert(space);
@@ -230,45 +238,45 @@ void PhysicsServer2DSW::space_set_active(RID p_space, bool p_active) {
}
bool PhysicsServer2DSW::space_is_active(RID p_space) const {
- const Space2DSW *space = space_owner.getornull(p_space);
+ const Space2DSW *space = space_owner.get_or_null(p_space);
ERR_FAIL_COND_V(!space, false);
return active_spaces.has(space);
}
void PhysicsServer2DSW::space_set_param(RID p_space, SpaceParameter p_param, real_t p_value) {
- Space2DSW *space = space_owner.getornull(p_space);
+ Space2DSW *space = space_owner.get_or_null(p_space);
ERR_FAIL_COND(!space);
space->set_param(p_param, p_value);
}
real_t PhysicsServer2DSW::space_get_param(RID p_space, SpaceParameter p_param) const {
- const Space2DSW *space = space_owner.getornull(p_space);
+ const Space2DSW *space = space_owner.get_or_null(p_space);
ERR_FAIL_COND_V(!space, 0);
return space->get_param(p_param);
}
void PhysicsServer2DSW::space_set_debug_contacts(RID p_space, int p_max_contacts) {
- Space2DSW *space = space_owner.getornull(p_space);
+ Space2DSW *space = space_owner.get_or_null(p_space);
ERR_FAIL_COND(!space);
space->set_debug_contacts(p_max_contacts);
}
Vector<Vector2> PhysicsServer2DSW::space_get_contacts(RID p_space) const {
- Space2DSW *space = space_owner.getornull(p_space);
+ Space2DSW *space = space_owner.get_or_null(p_space);
ERR_FAIL_COND_V(!space, Vector<Vector2>());
return space->get_debug_contacts();
}
int PhysicsServer2DSW::space_get_contact_count(RID p_space) const {
- Space2DSW *space = space_owner.getornull(p_space);
+ Space2DSW *space = space_owner.get_or_null(p_space);
ERR_FAIL_COND_V(!space, 0);
return space->get_debug_contact_count();
}
PhysicsDirectSpaceState2D *PhysicsServer2DSW::space_get_direct_state(RID p_space) {
- Space2DSW *space = space_owner.getornull(p_space);
+ Space2DSW *space = space_owner.get_or_null(p_space);
ERR_FAIL_COND_V(!space, nullptr);
ERR_FAIL_COND_V_MSG((using_threads && !doing_sync) || space->is_locked(), nullptr, "Space state is inaccessible right now, wait for iteration or physics process notification.");
@@ -283,12 +291,12 @@ RID PhysicsServer2DSW::area_create() {
};
void PhysicsServer2DSW::area_set_space(RID p_area, RID p_space) {
- Area2DSW *area = area_owner.getornull(p_area);
+ Area2DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND(!area);
Space2DSW *space = nullptr;
if (p_space.is_valid()) {
- space = space_owner.getornull(p_space);
+ space = space_owner.get_or_null(p_space);
ERR_FAIL_COND(!space);
}
@@ -301,7 +309,7 @@ void PhysicsServer2DSW::area_set_space(RID p_area, RID p_space) {
};
RID PhysicsServer2DSW::area_get_space(RID p_area) const {
- Area2DSW *area = area_owner.getornull(p_area);
+ Area2DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND_V(!area, RID());
Space2DSW *space = area->get_space();
@@ -312,34 +320,34 @@ RID PhysicsServer2DSW::area_get_space(RID p_area) const {
};
void PhysicsServer2DSW::area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) {
- Area2DSW *area = area_owner.getornull(p_area);
+ Area2DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND(!area);
area->set_space_override_mode(p_mode);
}
PhysicsServer2D::AreaSpaceOverrideMode PhysicsServer2DSW::area_get_space_override_mode(RID p_area) const {
- const Area2DSW *area = area_owner.getornull(p_area);
+ const Area2DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND_V(!area, AREA_SPACE_OVERRIDE_DISABLED);
return area->get_space_override_mode();
}
void PhysicsServer2DSW::area_add_shape(RID p_area, RID p_shape, const Transform2D &p_transform, bool p_disabled) {
- Area2DSW *area = area_owner.getornull(p_area);
+ Area2DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND(!area);
- Shape2DSW *shape = shape_owner.getornull(p_shape);
+ Shape2DSW *shape = shape_owner.get_or_null(p_shape);
ERR_FAIL_COND(!shape);
area->add_shape(shape, p_transform, p_disabled);
}
void PhysicsServer2DSW::area_set_shape(RID p_area, int p_shape_idx, RID p_shape) {
- Area2DSW *area = area_owner.getornull(p_area);
+ Area2DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND(!area);
- Shape2DSW *shape = shape_owner.getornull(p_shape);
+ Shape2DSW *shape = shape_owner.get_or_null(p_shape);
ERR_FAIL_COND(!shape);
ERR_FAIL_COND(!shape->is_configured());
@@ -347,14 +355,14 @@ void PhysicsServer2DSW::area_set_shape(RID p_area, int p_shape_idx, RID p_shape)
}
void PhysicsServer2DSW::area_set_shape_transform(RID p_area, int p_shape_idx, const Transform2D &p_transform) {
- Area2DSW *area = area_owner.getornull(p_area);
+ Area2DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND(!area);
area->set_shape_transform(p_shape_idx, p_transform);
}
void PhysicsServer2DSW::area_set_shape_disabled(RID p_area, int p_shape, bool p_disabled) {
- Area2DSW *area = area_owner.getornull(p_area);
+ Area2DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND(!area);
ERR_FAIL_INDEX(p_shape, area->get_shape_count());
FLUSH_QUERY_CHECK(area);
@@ -363,14 +371,14 @@ void PhysicsServer2DSW::area_set_shape_disabled(RID p_area, int p_shape, bool p_
}
int PhysicsServer2DSW::area_get_shape_count(RID p_area) const {
- Area2DSW *area = area_owner.getornull(p_area);
+ Area2DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND_V(!area, -1);
return area->get_shape_count();
}
RID PhysicsServer2DSW::area_get_shape(RID p_area, int p_shape_idx) const {
- Area2DSW *area = area_owner.getornull(p_area);
+ Area2DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND_V(!area, RID());
Shape2DSW *shape = area->get_shape(p_shape_idx);
@@ -380,21 +388,21 @@ RID PhysicsServer2DSW::area_get_shape(RID p_area, int p_shape_idx) const {
}
Transform2D PhysicsServer2DSW::area_get_shape_transform(RID p_area, int p_shape_idx) const {
- Area2DSW *area = area_owner.getornull(p_area);
+ Area2DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND_V(!area, Transform2D());
return area->get_shape_transform(p_shape_idx);
}
void PhysicsServer2DSW::area_remove_shape(RID p_area, int p_shape_idx) {
- Area2DSW *area = area_owner.getornull(p_area);
+ Area2DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND(!area);
area->remove_shape(p_shape_idx);
}
void PhysicsServer2DSW::area_clear_shapes(RID p_area) {
- Area2DSW *area = area_owner.getornull(p_area);
+ Area2DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND(!area);
while (area->get_shape_count()) {
@@ -404,86 +412,86 @@ void PhysicsServer2DSW::area_clear_shapes(RID p_area) {
void PhysicsServer2DSW::area_attach_object_instance_id(RID p_area, ObjectID p_id) {
if (space_owner.owns(p_area)) {
- Space2DSW *space = space_owner.getornull(p_area);
+ Space2DSW *space = space_owner.get_or_null(p_area);
p_area = space->get_default_area()->get_self();
}
- Area2DSW *area = area_owner.getornull(p_area);
+ Area2DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND(!area);
area->set_instance_id(p_id);
}
ObjectID PhysicsServer2DSW::area_get_object_instance_id(RID p_area) const {
if (space_owner.owns(p_area)) {
- Space2DSW *space = space_owner.getornull(p_area);
+ Space2DSW *space = space_owner.get_or_null(p_area);
p_area = space->get_default_area()->get_self();
}
- Area2DSW *area = area_owner.getornull(p_area);
+ Area2DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND_V(!area, ObjectID());
return area->get_instance_id();
}
void PhysicsServer2DSW::area_attach_canvas_instance_id(RID p_area, ObjectID p_id) {
if (space_owner.owns(p_area)) {
- Space2DSW *space = space_owner.getornull(p_area);
+ Space2DSW *space = space_owner.get_or_null(p_area);
p_area = space->get_default_area()->get_self();
}
- Area2DSW *area = area_owner.getornull(p_area);
+ Area2DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND(!area);
area->set_canvas_instance_id(p_id);
}
ObjectID PhysicsServer2DSW::area_get_canvas_instance_id(RID p_area) const {
if (space_owner.owns(p_area)) {
- Space2DSW *space = space_owner.getornull(p_area);
+ Space2DSW *space = space_owner.get_or_null(p_area);
p_area = space->get_default_area()->get_self();
}
- Area2DSW *area = area_owner.getornull(p_area);
+ Area2DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND_V(!area, ObjectID());
return area->get_canvas_instance_id();
}
void PhysicsServer2DSW::area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value) {
if (space_owner.owns(p_area)) {
- Space2DSW *space = space_owner.getornull(p_area);
+ Space2DSW *space = space_owner.get_or_null(p_area);
p_area = space->get_default_area()->get_self();
}
- Area2DSW *area = area_owner.getornull(p_area);
+ Area2DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND(!area);
area->set_param(p_param, p_value);
};
void PhysicsServer2DSW::area_set_transform(RID p_area, const Transform2D &p_transform) {
- Area2DSW *area = area_owner.getornull(p_area);
+ Area2DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND(!area);
area->set_transform(p_transform);
};
Variant PhysicsServer2DSW::area_get_param(RID p_area, AreaParameter p_param) const {
if (space_owner.owns(p_area)) {
- Space2DSW *space = space_owner.getornull(p_area);
+ Space2DSW *space = space_owner.get_or_null(p_area);
p_area = space->get_default_area()->get_self();
}
- Area2DSW *area = area_owner.getornull(p_area);
+ Area2DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND_V(!area, Variant());
return area->get_param(p_param);
};
Transform2D PhysicsServer2DSW::area_get_transform(RID p_area) const {
- Area2DSW *area = area_owner.getornull(p_area);
+ Area2DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND_V(!area, Transform2D());
return area->get_transform();
};
void PhysicsServer2DSW::area_set_pickable(RID p_area, bool p_pickable) {
- Area2DSW *area = area_owner.getornull(p_area);
+ Area2DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND(!area);
area->set_pickable(p_pickable);
}
void PhysicsServer2DSW::area_set_monitorable(RID p_area, bool p_monitorable) {
- Area2DSW *area = area_owner.getornull(p_area);
+ Area2DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND(!area);
FLUSH_QUERY_CHECK(area);
@@ -491,28 +499,28 @@ void PhysicsServer2DSW::area_set_monitorable(RID p_area, bool p_monitorable) {
}
void PhysicsServer2DSW::area_set_collision_mask(RID p_area, uint32_t p_mask) {
- Area2DSW *area = area_owner.getornull(p_area);
+ Area2DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND(!area);
area->set_collision_mask(p_mask);
}
void PhysicsServer2DSW::area_set_collision_layer(RID p_area, uint32_t p_layer) {
- Area2DSW *area = area_owner.getornull(p_area);
+ Area2DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND(!area);
area->set_collision_layer(p_layer);
}
void PhysicsServer2DSW::area_set_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) {
- Area2DSW *area = area_owner.getornull(p_area);
+ Area2DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND(!area);
area->set_monitor_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method);
}
void PhysicsServer2DSW::area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) {
- Area2DSW *area = area_owner.getornull(p_area);
+ Area2DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND(!area);
area->set_area_monitor_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method);
@@ -528,11 +536,11 @@ RID PhysicsServer2DSW::body_create() {
}
void PhysicsServer2DSW::body_set_space(RID p_body, RID p_space) {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
Space2DSW *space = nullptr;
if (p_space.is_valid()) {
- space = space_owner.getornull(p_space);
+ space = space_owner.get_or_null(p_space);
ERR_FAIL_COND(!space);
}
@@ -545,7 +553,7 @@ void PhysicsServer2DSW::body_set_space(RID p_body, RID p_space) {
};
RID PhysicsServer2DSW::body_get_space(RID p_body) const {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!body, RID());
Space2DSW *space = body->get_space();
@@ -556,7 +564,7 @@ RID PhysicsServer2DSW::body_get_space(RID p_body) const {
};
void PhysicsServer2DSW::body_set_mode(RID p_body, BodyMode p_mode) {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
FLUSH_QUERY_CHECK(body);
@@ -564,27 +572,27 @@ void PhysicsServer2DSW::body_set_mode(RID p_body, BodyMode p_mode) {
};
PhysicsServer2D::BodyMode PhysicsServer2DSW::body_get_mode(RID p_body) const {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!body, BODY_MODE_STATIC);
return body->get_mode();
};
void PhysicsServer2DSW::body_add_shape(RID p_body, RID p_shape, const Transform2D &p_transform, bool p_disabled) {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
- Shape2DSW *shape = shape_owner.getornull(p_shape);
+ Shape2DSW *shape = shape_owner.get_or_null(p_shape);
ERR_FAIL_COND(!shape);
body->add_shape(shape, p_transform, p_disabled);
}
void PhysicsServer2DSW::body_set_shape(RID p_body, int p_shape_idx, RID p_shape) {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
- Shape2DSW *shape = shape_owner.getornull(p_shape);
+ Shape2DSW *shape = shape_owner.get_or_null(p_shape);
ERR_FAIL_COND(!shape);
ERR_FAIL_COND(!shape->is_configured());
@@ -592,33 +600,21 @@ void PhysicsServer2DSW::body_set_shape(RID p_body, int p_shape_idx, RID p_shape)
}
void PhysicsServer2DSW::body_set_shape_transform(RID p_body, int p_shape_idx, const Transform2D &p_transform) {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
body->set_shape_transform(p_shape_idx, p_transform);
}
-void PhysicsServer2DSW::body_set_shape_metadata(RID p_body, int p_shape_idx, const Variant &p_metadata) {
- Body2DSW *body = body_owner.getornull(p_body);
- ERR_FAIL_COND(!body);
- body->set_shape_metadata(p_shape_idx, p_metadata);
-}
-
-Variant PhysicsServer2DSW::body_get_shape_metadata(RID p_body, int p_shape_idx) const {
- Body2DSW *body = body_owner.getornull(p_body);
- ERR_FAIL_COND_V(!body, Variant());
- return body->get_shape_metadata(p_shape_idx);
-}
-
int PhysicsServer2DSW::body_get_shape_count(RID p_body) const {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!body, -1);
return body->get_shape_count();
}
RID PhysicsServer2DSW::body_get_shape(RID p_body, int p_shape_idx) const {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!body, RID());
Shape2DSW *shape = body->get_shape(p_shape_idx);
@@ -628,21 +624,21 @@ RID PhysicsServer2DSW::body_get_shape(RID p_body, int p_shape_idx) const {
}
Transform2D PhysicsServer2DSW::body_get_shape_transform(RID p_body, int p_shape_idx) const {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!body, Transform2D());
return body->get_shape_transform(p_shape_idx);
}
void PhysicsServer2DSW::body_remove_shape(RID p_body, int p_shape_idx) {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
body->remove_shape(p_shape_idx);
}
void PhysicsServer2DSW::body_clear_shapes(RID p_body) {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
while (body->get_shape_count()) {
@@ -651,7 +647,7 @@ void PhysicsServer2DSW::body_clear_shapes(RID p_body) {
}
void PhysicsServer2DSW::body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled) {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
ERR_FAIL_INDEX(p_shape_idx, body->get_shape_count());
FLUSH_QUERY_CHECK(body);
@@ -660,7 +656,7 @@ void PhysicsServer2DSW::body_set_shape_disabled(RID p_body, int p_shape_idx, boo
}
void PhysicsServer2DSW::body_set_shape_as_one_way_collision(RID p_body, int p_shape_idx, bool p_enable, real_t p_margin) {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
ERR_FAIL_INDEX(p_shape_idx, body->get_shape_count());
FLUSH_QUERY_CHECK(body);
@@ -669,102 +665,109 @@ void PhysicsServer2DSW::body_set_shape_as_one_way_collision(RID p_body, int p_sh
}
void PhysicsServer2DSW::body_set_continuous_collision_detection_mode(RID p_body, CCDMode p_mode) {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
body->set_continuous_collision_detection_mode(p_mode);
}
PhysicsServer2DSW::CCDMode PhysicsServer2DSW::body_get_continuous_collision_detection_mode(RID p_body) const {
- const Body2DSW *body = body_owner.getornull(p_body);
+ const Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!body, CCD_MODE_DISABLED);
return body->get_continuous_collision_detection_mode();
}
void PhysicsServer2DSW::body_attach_object_instance_id(RID p_body, ObjectID p_id) {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
body->set_instance_id(p_id);
};
ObjectID PhysicsServer2DSW::body_get_object_instance_id(RID p_body) const {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!body, ObjectID());
return body->get_instance_id();
};
void PhysicsServer2DSW::body_attach_canvas_instance_id(RID p_body, ObjectID p_id) {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
body->set_canvas_instance_id(p_id);
};
ObjectID PhysicsServer2DSW::body_get_canvas_instance_id(RID p_body) const {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!body, ObjectID());
return body->get_canvas_instance_id();
};
void PhysicsServer2DSW::body_set_collision_layer(RID p_body, uint32_t p_layer) {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
body->set_collision_layer(p_layer);
};
uint32_t PhysicsServer2DSW::body_get_collision_layer(RID p_body) const {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!body, 0);
return body->get_collision_layer();
};
void PhysicsServer2DSW::body_set_collision_mask(RID p_body, uint32_t p_mask) {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
body->set_collision_mask(p_mask);
};
uint32_t PhysicsServer2DSW::body_get_collision_mask(RID p_body) const {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!body, 0);
return body->get_collision_mask();
};
-void PhysicsServer2DSW::body_set_param(RID p_body, BodyParameter p_param, real_t p_value) {
- Body2DSW *body = body_owner.getornull(p_body);
+void PhysicsServer2DSW::body_set_param(RID p_body, BodyParameter p_param, const Variant &p_value) {
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
body->set_param(p_param, p_value);
};
-real_t PhysicsServer2DSW::body_get_param(RID p_body, BodyParameter p_param) const {
- Body2DSW *body = body_owner.getornull(p_body);
+Variant PhysicsServer2DSW::body_get_param(RID p_body, BodyParameter p_param) const {
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!body, 0);
return body->get_param(p_param);
};
+void PhysicsServer2DSW::body_reset_mass_properties(RID p_body) {
+ Body2DSW *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ return body->reset_mass_properties();
+}
+
void PhysicsServer2DSW::body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
body->set_state(p_state, p_variant);
};
Variant PhysicsServer2DSW::body_get_state(RID p_body, BodyState p_state) const {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!body, Variant());
return body->get_state(p_state);
};
void PhysicsServer2DSW::body_set_applied_force(RID p_body, const Vector2 &p_force) {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
body->set_applied_force(p_force);
@@ -772,13 +775,13 @@ void PhysicsServer2DSW::body_set_applied_force(RID p_body, const Vector2 &p_forc
};
Vector2 PhysicsServer2DSW::body_get_applied_force(RID p_body) const {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!body, Vector2());
return body->get_applied_force();
};
void PhysicsServer2DSW::body_set_applied_torque(RID p_body, real_t p_torque) {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
body->set_applied_torque(p_torque);
@@ -786,14 +789,14 @@ void PhysicsServer2DSW::body_set_applied_torque(RID p_body, real_t p_torque) {
};
real_t PhysicsServer2DSW::body_get_applied_torque(RID p_body) const {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!body, 0);
return body->get_applied_torque();
};
void PhysicsServer2DSW::body_apply_central_impulse(RID p_body, const Vector2 &p_impulse) {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
body->apply_central_impulse(p_impulse);
@@ -801,7 +804,7 @@ void PhysicsServer2DSW::body_apply_central_impulse(RID p_body, const Vector2 &p_
}
void PhysicsServer2DSW::body_apply_torque_impulse(RID p_body, real_t p_torque) {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
_update_shapes();
@@ -811,7 +814,7 @@ void PhysicsServer2DSW::body_apply_torque_impulse(RID p_body, real_t p_torque) {
}
void PhysicsServer2DSW::body_apply_impulse(RID p_body, const Vector2 &p_impulse, const Vector2 &p_position) {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
_update_shapes();
@@ -821,7 +824,7 @@ void PhysicsServer2DSW::body_apply_impulse(RID p_body, const Vector2 &p_impulse,
};
void PhysicsServer2DSW::body_add_central_force(RID p_body, const Vector2 &p_force) {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
body->add_central_force(p_force);
@@ -829,7 +832,7 @@ void PhysicsServer2DSW::body_add_central_force(RID p_body, const Vector2 &p_forc
};
void PhysicsServer2DSW::body_add_force(RID p_body, const Vector2 &p_force, const Vector2 &p_position) {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
body->add_force(p_force, p_position);
@@ -837,7 +840,7 @@ void PhysicsServer2DSW::body_add_force(RID p_body, const Vector2 &p_force, const
};
void PhysicsServer2DSW::body_add_torque(RID p_body, real_t p_torque) {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
body->add_torque(p_torque);
@@ -845,7 +848,7 @@ void PhysicsServer2DSW::body_add_torque(RID p_body, real_t p_torque) {
};
void PhysicsServer2DSW::body_set_axis_velocity(RID p_body, const Vector2 &p_axis_velocity) {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
_update_shapes();
@@ -859,7 +862,7 @@ void PhysicsServer2DSW::body_set_axis_velocity(RID p_body, const Vector2 &p_axis
};
void PhysicsServer2DSW::body_add_collision_exception(RID p_body, RID p_body_b) {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
body->add_exception(p_body_b);
@@ -867,7 +870,7 @@ void PhysicsServer2DSW::body_add_collision_exception(RID p_body, RID p_body_b) {
};
void PhysicsServer2DSW::body_remove_collision_exception(RID p_body, RID p_body_b) {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
body->remove_exception(p_body_b);
@@ -875,7 +878,7 @@ void PhysicsServer2DSW::body_remove_collision_exception(RID p_body, RID p_body_b
};
void PhysicsServer2DSW::body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions) {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
for (int i = 0; i < body->get_exceptions().size(); i++) {
@@ -884,49 +887,55 @@ void PhysicsServer2DSW::body_get_collision_exceptions(RID p_body, List<RID> *p_e
};
void PhysicsServer2DSW::body_set_contacts_reported_depth_threshold(RID p_body, real_t p_threshold) {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
};
real_t PhysicsServer2DSW::body_get_contacts_reported_depth_threshold(RID p_body) const {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!body, 0);
return 0;
};
void PhysicsServer2DSW::body_set_omit_force_integration(RID p_body, bool p_omit) {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
body->set_omit_force_integration(p_omit);
};
bool PhysicsServer2DSW::body_is_omitting_force_integration(RID p_body) const {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!body, false);
return body->get_omit_force_integration();
};
void PhysicsServer2DSW::body_set_max_contacts_reported(RID p_body, int p_contacts) {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
body->set_max_contacts_reported(p_contacts);
}
int PhysicsServer2DSW::body_get_max_contacts_reported(RID p_body) const {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!body, -1);
return body->get_max_contacts_reported();
}
+void PhysicsServer2DSW::body_set_state_sync_callback(RID p_body, void *p_instance, BodyStateCallback p_callback) {
+ Body2DSW *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+ body->set_state_sync_callback(p_instance, p_callback);
+}
+
void PhysicsServer2DSW::body_set_force_integration_callback(RID p_body, const Callable &p_callable, const Variant &p_udata) {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
body->set_force_integration_callback(p_callable, p_udata);
}
bool PhysicsServer2DSW::body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, Vector2 *r_results, int p_result_max, int &r_result_count) {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!body, false);
ERR_FAIL_INDEX_V(p_body_shape, body->get_shape_count(), false);
@@ -934,36 +943,32 @@ bool PhysicsServer2DSW::body_collide_shape(RID p_body, int p_body_shape, RID p_s
}
void PhysicsServer2DSW::body_set_pickable(RID p_body, bool p_pickable) {
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
body->set_pickable(p_pickable);
}
-bool PhysicsServer2DSW::body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin, MotionResult *r_result, const Set<RID> &p_exclude) {
- Body2DSW *body = body_owner.getornull(p_body);
+bool PhysicsServer2DSW::body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result) {
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!body, false);
ERR_FAIL_COND_V(!body->get_space(), false);
ERR_FAIL_COND_V(body->get_space()->is_locked(), false);
_update_shapes();
- return body->get_space()->test_body_motion(body, p_from, p_motion, p_margin, r_result, p_exclude);
+ return body->get_space()->test_body_motion(body, p_parameters, r_result);
}
PhysicsDirectBodyState2D *PhysicsServer2DSW::body_get_direct_state(RID p_body) {
ERR_FAIL_COND_V_MSG((using_threads && !doing_sync), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification.");
- if (!body_owner.owns(p_body)) {
- return nullptr;
- }
-
- Body2DSW *body = body_owner.getornull(p_body);
+ Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!body, nullptr);
+
ERR_FAIL_COND_V(!body->get_space(), nullptr);
ERR_FAIL_COND_V_MSG(body->get_space()->is_locked(), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification.");
- direct_state->body = body;
- return direct_state;
+ return body->get_direct_state();
}
/* JOINT API */
@@ -976,7 +981,7 @@ RID PhysicsServer2DSW::joint_create() {
}
void PhysicsServer2DSW::joint_clear(RID p_joint) {
- Joint2DSW *joint = joint_owner.getornull(p_joint);
+ Joint2DSW *joint = joint_owner.get_or_null(p_joint);
if (joint->get_type() != JOINT_TYPE_MAX) {
Joint2DSW *empty_joint = memnew(Joint2DSW);
empty_joint->copy_settings_from(joint);
@@ -987,7 +992,7 @@ void PhysicsServer2DSW::joint_clear(RID p_joint) {
}
void PhysicsServer2DSW::joint_set_param(RID p_joint, JointParam p_param, real_t p_value) {
- Joint2DSW *joint = joint_owner.getornull(p_joint);
+ Joint2DSW *joint = joint_owner.get_or_null(p_joint);
ERR_FAIL_COND(!joint);
switch (p_param) {
@@ -1004,7 +1009,7 @@ void PhysicsServer2DSW::joint_set_param(RID p_joint, JointParam p_param, real_t
}
real_t PhysicsServer2DSW::joint_get_param(RID p_joint, JointParam p_param) const {
- const Joint2DSW *joint = joint_owner.getornull(p_joint);
+ const Joint2DSW *joint = joint_owner.get_or_null(p_joint);
ERR_FAIL_COND_V(!joint, -1);
switch (p_param) {
@@ -1023,7 +1028,7 @@ real_t PhysicsServer2DSW::joint_get_param(RID p_joint, JointParam p_param) const
}
void PhysicsServer2DSW::joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable) {
- Joint2DSW *joint = joint_owner.getornull(p_joint);
+ Joint2DSW *joint = joint_owner.get_or_null(p_joint);
ERR_FAIL_COND(!joint);
joint->disable_collisions_between_bodies(p_disable);
@@ -1043,22 +1048,22 @@ void PhysicsServer2DSW::joint_disable_collisions_between_bodies(RID p_joint, con
}
bool PhysicsServer2DSW::joint_is_disabled_collisions_between_bodies(RID p_joint) const {
- const Joint2DSW *joint = joint_owner.getornull(p_joint);
+ const Joint2DSW *joint = joint_owner.get_or_null(p_joint);
ERR_FAIL_COND_V(!joint, true);
return joint->is_disabled_collisions_between_bodies();
}
void PhysicsServer2DSW::joint_make_pin(RID p_joint, const Vector2 &p_pos, RID p_body_a, RID p_body_b) {
- Body2DSW *A = body_owner.getornull(p_body_a);
+ Body2DSW *A = body_owner.get_or_null(p_body_a);
ERR_FAIL_COND(!A);
Body2DSW *B = nullptr;
if (body_owner.owns(p_body_b)) {
- B = body_owner.getornull(p_body_b);
+ B = body_owner.get_or_null(p_body_b);
ERR_FAIL_COND(!B);
}
- Joint2DSW *prev_joint = joint_owner.getornull(p_joint);
+ Joint2DSW *prev_joint = joint_owner.get_or_null(p_joint);
ERR_FAIL_COND(prev_joint == nullptr);
Joint2DSW *joint = memnew(PinJoint2DSW(p_pos, A, B));
@@ -1069,13 +1074,13 @@ void PhysicsServer2DSW::joint_make_pin(RID p_joint, const Vector2 &p_pos, RID p_
}
void PhysicsServer2DSW::joint_make_groove(RID p_joint, const Vector2 &p_a_groove1, const Vector2 &p_a_groove2, const Vector2 &p_b_anchor, RID p_body_a, RID p_body_b) {
- Body2DSW *A = body_owner.getornull(p_body_a);
+ Body2DSW *A = body_owner.get_or_null(p_body_a);
ERR_FAIL_COND(!A);
- Body2DSW *B = body_owner.getornull(p_body_b);
+ Body2DSW *B = body_owner.get_or_null(p_body_b);
ERR_FAIL_COND(!B);
- Joint2DSW *prev_joint = joint_owner.getornull(p_joint);
+ Joint2DSW *prev_joint = joint_owner.get_or_null(p_joint);
ERR_FAIL_COND(prev_joint == nullptr);
Joint2DSW *joint = memnew(GrooveJoint2DSW(p_a_groove1, p_a_groove2, p_b_anchor, A, B));
@@ -1086,13 +1091,13 @@ void PhysicsServer2DSW::joint_make_groove(RID p_joint, const Vector2 &p_a_groove
}
void PhysicsServer2DSW::joint_make_damped_spring(RID p_joint, const Vector2 &p_anchor_a, const Vector2 &p_anchor_b, RID p_body_a, RID p_body_b) {
- Body2DSW *A = body_owner.getornull(p_body_a);
+ Body2DSW *A = body_owner.get_or_null(p_body_a);
ERR_FAIL_COND(!A);
- Body2DSW *B = body_owner.getornull(p_body_b);
+ Body2DSW *B = body_owner.get_or_null(p_body_b);
ERR_FAIL_COND(!B);
- Joint2DSW *prev_joint = joint_owner.getornull(p_joint);
+ Joint2DSW *prev_joint = joint_owner.get_or_null(p_joint);
ERR_FAIL_COND(prev_joint == nullptr);
Joint2DSW *joint = memnew(DampedSpringJoint2DSW(p_anchor_a, p_anchor_b, A, B));
@@ -1103,7 +1108,7 @@ void PhysicsServer2DSW::joint_make_damped_spring(RID p_joint, const Vector2 &p_a
}
void PhysicsServer2DSW::pin_joint_set_param(RID p_joint, PinJointParam p_param, real_t p_value) {
- Joint2DSW *j = joint_owner.getornull(p_joint);
+ Joint2DSW *j = joint_owner.get_or_null(p_joint);
ERR_FAIL_COND(!j);
ERR_FAIL_COND(j->get_type() != JOINT_TYPE_PIN);
@@ -1112,7 +1117,7 @@ void PhysicsServer2DSW::pin_joint_set_param(RID p_joint, PinJointParam p_param,
}
real_t PhysicsServer2DSW::pin_joint_get_param(RID p_joint, PinJointParam p_param) const {
- Joint2DSW *j = joint_owner.getornull(p_joint);
+ Joint2DSW *j = joint_owner.get_or_null(p_joint);
ERR_FAIL_COND_V(!j, 0);
ERR_FAIL_COND_V(j->get_type() != JOINT_TYPE_PIN, 0);
@@ -1121,7 +1126,7 @@ real_t PhysicsServer2DSW::pin_joint_get_param(RID p_joint, PinJointParam p_param
}
void PhysicsServer2DSW::damped_spring_joint_set_param(RID p_joint, DampedSpringParam p_param, real_t p_value) {
- Joint2DSW *j = joint_owner.getornull(p_joint);
+ Joint2DSW *j = joint_owner.get_or_null(p_joint);
ERR_FAIL_COND(!j);
ERR_FAIL_COND(j->get_type() != JOINT_TYPE_DAMPED_SPRING);
@@ -1130,7 +1135,7 @@ void PhysicsServer2DSW::damped_spring_joint_set_param(RID p_joint, DampedSpringP
}
real_t PhysicsServer2DSW::damped_spring_joint_get_param(RID p_joint, DampedSpringParam p_param) const {
- Joint2DSW *j = joint_owner.getornull(p_joint);
+ Joint2DSW *j = joint_owner.get_or_null(p_joint);
ERR_FAIL_COND_V(!j, 0);
ERR_FAIL_COND_V(j->get_type() != JOINT_TYPE_DAMPED_SPRING, 0);
@@ -1139,7 +1144,7 @@ real_t PhysicsServer2DSW::damped_spring_joint_get_param(RID p_joint, DampedSprin
}
PhysicsServer2D::JointType PhysicsServer2DSW::joint_get_type(RID p_joint) const {
- Joint2DSW *joint = joint_owner.getornull(p_joint);
+ Joint2DSW *joint = joint_owner.get_or_null(p_joint);
ERR_FAIL_COND_V(!joint, JOINT_TYPE_PIN);
return joint->get_type();
@@ -1149,7 +1154,7 @@ void PhysicsServer2DSW::free(RID p_rid) {
_update_shapes(); // just in case
if (shape_owner.owns(p_rid)) {
- Shape2DSW *shape = shape_owner.getornull(p_rid);
+ Shape2DSW *shape = shape_owner.get_or_null(p_rid);
while (shape->get_owners().size()) {
ShapeOwner2DSW *so = shape->get_owners().front()->key();
@@ -1159,7 +1164,7 @@ void PhysicsServer2DSW::free(RID p_rid) {
shape_owner.free(p_rid);
memdelete(shape);
} else if (body_owner.owns(p_rid)) {
- Body2DSW *body = body_owner.getornull(p_rid);
+ Body2DSW *body = body_owner.get_or_null(p_rid);
/*
if (body->get_state_query())
@@ -1179,7 +1184,7 @@ void PhysicsServer2DSW::free(RID p_rid) {
memdelete(body);
} else if (area_owner.owns(p_rid)) {
- Area2DSW *area = area_owner.getornull(p_rid);
+ Area2DSW *area = area_owner.get_or_null(p_rid);
/*
if (area->get_monitor_query())
@@ -1195,7 +1200,7 @@ void PhysicsServer2DSW::free(RID p_rid) {
area_owner.free(p_rid);
memdelete(area);
} else if (space_owner.owns(p_rid)) {
- Space2DSW *space = space_owner.getornull(p_rid);
+ Space2DSW *space = space_owner.get_or_null(p_rid);
while (space->get_objects().size()) {
CollisionObject2DSW *co = (CollisionObject2DSW *)space->get_objects().front()->get();
@@ -1207,7 +1212,7 @@ void PhysicsServer2DSW::free(RID p_rid) {
space_owner.free(p_rid);
memdelete(space);
} else if (joint_owner.owns(p_rid)) {
- Joint2DSW *joint = joint_owner.getornull(p_rid);
+ Joint2DSW *joint = joint_owner.get_or_null(p_rid);
joint_owner.free(p_rid);
memdelete(joint);
@@ -1227,10 +1232,8 @@ void PhysicsServer2DSW::set_collision_iterations(int p_iterations) {
void PhysicsServer2DSW::init() {
doing_sync = false;
- last_step = 0.001;
iterations = 8; // 8?
stepper = memnew(Step2DSW);
- direct_state = memnew(PhysicsDirectBodyState2DSW);
};
void PhysicsServer2DSW::step(real_t p_step) {
@@ -1240,8 +1243,6 @@ void PhysicsServer2DSW::step(real_t p_step) {
_update_shapes();
- last_step = p_step;
- PhysicsDirectBodyState2DSW::singleton->step = p_step;
island_count = 0;
active_objects = 0;
collision_pairs = 0;
@@ -1313,7 +1314,6 @@ void PhysicsServer2DSW::end_sync() {
void PhysicsServer2DSW::finish() {
memdelete(stepper);
- memdelete(direct_state);
};
void PhysicsServer2DSW::_update_shapes() {
@@ -1345,10 +1345,5 @@ PhysicsServer2DSW::PhysicsServer2DSW(bool p_using_threads) {
singletonsw = this;
BroadPhase2DSW::create_func = BroadPhase2DBVH::_create;
- active = true;
- island_count = 0;
- active_objects = 0;
- collision_pairs = 0;
using_threads = p_using_threads;
- flushing_queries = false;
};
diff --git a/servers/physics_2d/physics_server_2d_sw.h b/servers/physics_2d/physics_server_2d_sw.h
index 3610f43f93..b8e375a087 100644
--- a/servers/physics_2d/physics_server_2d_sw.h
+++ b/servers/physics_2d/physics_server_2d_sw.h
@@ -43,24 +43,21 @@ class PhysicsServer2DSW : public PhysicsServer2D {
friend class PhysicsDirectSpaceState2DSW;
friend class PhysicsDirectBodyState2DSW;
- bool active;
- int iterations;
- bool doing_sync;
- real_t last_step;
+ bool active = true;
+ int iterations = 0;
+ bool doing_sync = false;
- int island_count;
- int active_objects;
- int collision_pairs;
+ int island_count = 0;
+ int active_objects = 0;
+ int collision_pairs = 0;
- bool using_threads;
+ bool using_threads = false;
- bool flushing_queries;
+ bool flushing_queries = false;
- Step2DSW *stepper;
+ Step2DSW *stepper = nullptr;
Set<const Space2DSW *> active_spaces;
- PhysicsDirectBodyState2DSW *direct_state;
-
mutable RID_PtrOwner<Shape2DSW, true> shape_owner;
mutable RID_PtrOwner<Space2DSW, true> space_owner;
mutable RID_PtrOwner<Area2DSW, true> area_owner;
@@ -79,15 +76,16 @@ class PhysicsServer2DSW : public PhysicsServer2D {
public:
struct CollCbkData {
Vector2 valid_dir;
- real_t valid_depth;
- int max;
- int amount;
- int passed;
- int invalid_by_dir;
- Vector2 *ptr;
+ real_t valid_depth = 0.0;
+ int max = 0;
+ int amount = 0;
+ int passed = 0;
+ int invalid_by_dir = 0;
+ Vector2 *ptr = nullptr;
};
- virtual RID world_margin_shape_create() override;
+ virtual RID world_boundary_shape_create() override;
+ virtual RID separation_ray_shape_create() override;
virtual RID segment_shape_create() override;
virtual RID circle_shape_create() override;
virtual RID rectangle_shape_create() override;
@@ -179,12 +177,10 @@ public:
virtual void body_add_shape(RID p_body, RID p_shape, const Transform2D &p_transform = Transform2D(), bool p_disabled = false) override;
virtual void body_set_shape(RID p_body, int p_shape_idx, RID p_shape) override;
virtual void body_set_shape_transform(RID p_body, int p_shape_idx, const Transform2D &p_transform) override;
- virtual void body_set_shape_metadata(RID p_body, int p_shape_idx, const Variant &p_metadata) override;
virtual int body_get_shape_count(RID p_body) const override;
virtual RID body_get_shape(RID p_body, int p_shape_idx) const override;
virtual Transform2D body_get_shape_transform(RID p_body, int p_shape_idx) const override;
- virtual Variant body_get_shape_metadata(RID p_body, int p_shape_idx) const override;
virtual void body_remove_shape(RID p_body, int p_shape_idx) override;
virtual void body_clear_shapes(RID p_body) override;
@@ -207,8 +203,10 @@ public:
virtual void body_set_collision_mask(RID p_body, uint32_t p_mask) override;
virtual uint32_t body_get_collision_mask(RID p_body) const override;
- virtual void body_set_param(RID p_body, BodyParameter p_param, real_t p_value) override;
- virtual real_t body_get_param(RID p_body, BodyParameter p_param) const override;
+ virtual void body_set_param(RID p_body, BodyParameter p_param, const Variant &p_value) override;
+ virtual Variant body_get_param(RID p_body, BodyParameter p_param) const override;
+
+ virtual void body_reset_mass_properties(RID p_body) override;
virtual void body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) override;
virtual Variant body_get_state(RID p_body, BodyState p_state) const override;
@@ -241,12 +239,14 @@ public:
virtual void body_set_max_contacts_reported(RID p_body, int p_contacts) override;
virtual int body_get_max_contacts_reported(RID p_body) const override;
+ virtual void body_set_state_sync_callback(RID p_body, void *p_instance, BodyStateCallback p_callback) override;
virtual void body_set_force_integration_callback(RID p_body, const Callable &p_callable, const Variant &p_udata = Variant()) override;
+
virtual bool body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, Vector2 *r_results, int p_result_max, int &r_result_count) override;
virtual void body_set_pickable(RID p_body, bool p_pickable) override;
- virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin = 0.08, MotionResult *r_result = nullptr, const Set<RID> &p_exclude = Set<RID>()) override;
+ virtual bool body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result = nullptr) override;
// this function only works on physics process, errors and returns null otherwise
virtual PhysicsDirectBodyState2D *body_get_direct_state(RID p_body) override;
diff --git a/servers/physics_2d/physics_server_2d_wrap_mt.cpp b/servers/physics_2d/physics_server_2d_wrap_mt.cpp
index 930b19c2cb..33070bf42d 100644
--- a/servers/physics_2d/physics_server_2d_wrap_mt.cpp
+++ b/servers/physics_2d/physics_server_2d_wrap_mt.cpp
@@ -119,7 +119,6 @@ PhysicsServer2DWrapMT::PhysicsServer2DWrapMT(PhysicsServer2D *p_contained, bool
command_queue(p_create_thread) {
physics_2d_server = p_contained;
create_thread = p_create_thread;
- step_pending = 0;
pool_max_size = GLOBAL_GET("memory/limits/multithreaded_server/rid_pool_prealloc");
@@ -130,7 +129,6 @@ PhysicsServer2DWrapMT::PhysicsServer2DWrapMT(PhysicsServer2D *p_contained, bool
}
main_thread = Thread::get_caller_id();
- first_frame = true;
}
PhysicsServer2DWrapMT::~PhysicsServer2DWrapMT() {
diff --git a/servers/physics_2d/physics_server_2d_wrap_mt.h b/servers/physics_2d/physics_server_2d_wrap_mt.h
index b93178919d..8d9e366661 100644
--- a/servers/physics_2d/physics_server_2d_wrap_mt.h
+++ b/servers/physics_2d/physics_server_2d_wrap_mt.h
@@ -56,19 +56,19 @@ class PhysicsServer2DWrapMT : public PhysicsServer2D {
SafeFlag exit;
Thread thread;
SafeFlag step_thread_up;
- bool create_thread;
+ bool create_thread = false;
Semaphore step_sem;
- int step_pending;
+ int step_pending = 0;
void thread_step(real_t p_delta);
void thread_flush();
void thread_exit();
- bool first_frame;
+ bool first_frame = true;
Mutex alloc_mutex;
- int pool_max_size;
+ int pool_max_size = 0;
public:
#define ServerName PhysicsServer2D
@@ -79,7 +79,8 @@ public:
#include "servers/server_wrap_mt_common.h"
//FUNC1RID(shape,ShapeType); todo fix
- FUNCRID(world_margin_shape)
+ FUNCRID(world_boundary_shape)
+ FUNCRID(separation_ray_shape)
FUNCRID(segment_shape)
FUNCRID(circle_shape)
FUNCRID(rectangle_shape)
@@ -183,11 +184,9 @@ public:
FUNC4(body_add_shape, RID, RID, const Transform2D &, bool);
FUNC3(body_set_shape, RID, int, RID);
FUNC3(body_set_shape_transform, RID, int, const Transform2D &);
- FUNC3(body_set_shape_metadata, RID, int, const Variant &);
FUNC1RC(int, body_get_shape_count, RID);
FUNC2RC(Transform2D, body_get_shape_transform, RID, int);
- FUNC2RC(Variant, body_get_shape_metadata, RID, int);
FUNC2RC(RID, body_get_shape, RID, int);
FUNC3(body_set_shape_disabled, RID, int, bool);
@@ -211,8 +210,10 @@ public:
FUNC2(body_set_collision_mask, RID, uint32_t);
FUNC1RC(uint32_t, body_get_collision_mask, RID);
- FUNC3(body_set_param, RID, BodyParameter, real_t);
- FUNC2RC(real_t, body_get_param, RID, BodyParameter);
+ FUNC3(body_set_param, RID, BodyParameter, const Variant &);
+ FUNC2RC(Variant, body_get_param, RID, BodyParameter);
+
+ FUNC1(body_reset_mass_properties, RID);
FUNC3(body_set_state, RID, BodyState, const Variant &);
FUNC2RC(Variant, body_get_state, RID, BodyState);
@@ -244,6 +245,7 @@ public:
FUNC2(body_set_omit_force_integration, RID, bool);
FUNC1RC(bool, body_is_omitting_force_integration, RID);
+ FUNC3(body_set_state_sync_callback, RID, void *, BodyStateCallback);
FUNC3(body_set_force_integration_callback, RID, const Callable &, const Variant &);
bool body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, Vector2 *r_results, int p_result_max, int &r_result_count) override {
@@ -252,9 +254,9 @@ public:
FUNC2(body_set_pickable, RID, bool);
- bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin = 0.08, MotionResult *r_result = nullptr, const Set<RID> &p_exclude = Set<RID>()) override {
+ bool body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result = nullptr) override {
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false);
- return physics_2d_server->body_test_motion(p_body, p_from, p_motion, p_margin, r_result, p_exclude);
+ return physics_2d_server->body_test_motion(p_body, p_parameters, r_result);
}
// this function only works on physics process, errors and returns null otherwise
diff --git a/servers/physics_2d/shape_2d_sw.cpp b/servers/physics_2d/shape_2d_sw.cpp
index b3e4ca84c3..bde882ac24 100644
--- a/servers/physics_2d/shape_2d_sw.cpp
+++ b/servers/physics_2d/shape_2d_sw.cpp
@@ -36,8 +36,8 @@
void Shape2DSW::configure(const Rect2 &p_aabb) {
aabb = p_aabb;
configured = true;
- for (Map<ShapeOwner2DSW *, int>::Element *E = owners.front(); E; E = E->next()) {
- ShapeOwner2DSW *co = (ShapeOwner2DSW *)E->key();
+ for (const KeyValue<ShapeOwner2DSW *, int> &E : owners) {
+ ShapeOwner2DSW *co = (ShapeOwner2DSW *)E.key;
co->_shape_changed();
}
}
@@ -75,11 +75,6 @@ const Map<ShapeOwner2DSW *, int> &Shape2DSW::get_owners() const {
return owners;
}
-Shape2DSW::Shape2DSW() {
- custom_bias = 0;
- configured = false;
-}
-
Shape2DSW::~Shape2DSW() {
ERR_FAIL_COND(owners.size());
}
@@ -88,15 +83,15 @@ Shape2DSW::~Shape2DSW() {
/*********************************************************/
/*********************************************************/
-void WorldMarginShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const {
+void WorldBoundaryShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const {
r_amount = 0;
}
-bool WorldMarginShape2DSW::contains_point(const Vector2 &p_point) const {
+bool WorldBoundaryShape2DSW::contains_point(const Vector2 &p_point) const {
return normal.dot(p_point) < d;
}
-bool WorldMarginShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const {
+bool WorldBoundaryShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const {
Vector2 segment = p_begin - p_end;
real_t den = normal.dot(segment);
@@ -118,11 +113,11 @@ bool WorldMarginShape2DSW::intersect_segment(const Vector2 &p_begin, const Vecto
return true;
}
-real_t WorldMarginShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const {
+real_t WorldBoundaryShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const {
return 0;
}
-void WorldMarginShape2DSW::set_data(const Variant &p_data) {
+void WorldBoundaryShape2DSW::set_data(const Variant &p_data) {
ERR_FAIL_COND(p_data.get_type() != Variant::ARRAY);
Array arr = p_data;
ERR_FAIL_COND(arr.size() != 2);
@@ -131,7 +126,7 @@ void WorldMarginShape2DSW::set_data(const Variant &p_data) {
configure(Rect2(Vector2(-1e4, -1e4), Vector2(1e4 * 2, 1e4 * 2)));
}
-Variant WorldMarginShape2DSW::get_data() const {
+Variant WorldBoundaryShape2DSW::get_data() const {
Array arr;
arr.resize(2);
arr[0] = normal;
@@ -143,6 +138,46 @@ Variant WorldMarginShape2DSW::get_data() const {
/*********************************************************/
/*********************************************************/
+void SeparationRayShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const {
+ r_amount = 1;
+
+ if (p_normal.y > 0) {
+ *r_supports = Vector2(0, length);
+ } else {
+ *r_supports = Vector2();
+ }
+}
+
+bool SeparationRayShape2DSW::contains_point(const Vector2 &p_point) const {
+ return false;
+}
+
+bool SeparationRayShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const {
+ return false; //rays can't be intersected
+}
+
+real_t SeparationRayShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const {
+ return 0; //rays are mass-less
+}
+
+void SeparationRayShape2DSW::set_data(const Variant &p_data) {
+ Dictionary d = p_data;
+ length = d["length"];
+ slide_on_slope = d["slide_on_slope"];
+ configure(Rect2(0, 0, 0.001, length));
+}
+
+Variant SeparationRayShape2DSW::get_data() const {
+ Dictionary d;
+ d["length"] = length;
+ d["slide_on_slope"] = slide_on_slope;
+ return d;
+}
+
+/*********************************************************/
+/*********************************************************/
+/*********************************************************/
+
void SegmentShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const {
if (Math::abs(p_normal.dot(n)) > _SEGMENT_IS_VALID_SUPPORT_THRESHOLD) {
r_supports[0] = a;
@@ -530,14 +565,7 @@ bool ConvexPolygonShape2DSW::intersect_segment(const Vector2 &p_begin, const Vec
}
}
- if (inters) {
- if (n.dot(r_normal) > 0) {
- r_normal = -r_normal;
- }
- }
-
- //return get_aabb().intersects_segment(p_begin,p_end,&r_point,&r_normal);
- return inters; //todo
+ return inters;
}
real_t ConvexPolygonShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const {
@@ -619,11 +647,6 @@ Variant ConvexPolygonShape2DSW::get_data() const {
return dvr;
}
-ConvexPolygonShape2DSW::ConvexPolygonShape2DSW() {
- points = nullptr;
- point_count = 0;
-}
-
ConvexPolygonShape2DSW::~ConvexPolygonShape2DSW() {
if (points) {
memdelete_arr(points);
@@ -852,9 +875,9 @@ void ConcavePolygonShape2DSW::set_data(const Variant &p_data) {
points.resize(pointmap.size());
aabb.position = pointmap.front()->key();
- for (Map<Point2, int>::Element *E = pointmap.front(); E; E = E->next()) {
- aabb.expand_to(E->key());
- points.write[E->get()] = E->key();
+ for (const KeyValue<Point2, int> &E : pointmap) {
+ aabb.expand_to(E.key);
+ points.write[E.value] = E.key;
}
Vector<BVH> main_vbh;
@@ -888,7 +911,7 @@ Variant ConcavePolygonShape2DSW::get_data() const {
return rsegments;
}
-void ConcavePolygonShape2DSW::cull(const Rect2 &p_local_aabb, Callback p_callback, void *p_userdata) const {
+void ConcavePolygonShape2DSW::cull(const Rect2 &p_local_aabb, QueryCallback p_callback, void *p_userdata) const {
uint32_t *stack = (uint32_t *)alloca(sizeof(int) * bvh_depth);
enum {
@@ -936,7 +959,9 @@ void ConcavePolygonShape2DSW::cull(const Rect2 &p_local_aabb, Callback p_callbac
SegmentShape2DSW ss(a, b, (b - a).orthogonal().normalized());
- p_callback(p_userdata, &ss);
+ if (p_callback(p_userdata, &ss)) {
+ return;
+ }
stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node;
} else {
diff --git a/servers/physics_2d/shape_2d_sw.h b/servers/physics_2d/shape_2d_sw.h
index 45d3379dfa..c118826284 100644
--- a/servers/physics_2d/shape_2d_sw.h
+++ b/servers/physics_2d/shape_2d_sw.h
@@ -47,8 +47,8 @@ public:
class Shape2DSW {
RID self;
Rect2 aabb;
- bool configured;
- real_t custom_bias;
+ bool configured = false;
+ real_t custom_bias = 0.0;
Map<ShapeOwner2DSW *, int> owners;
@@ -64,6 +64,8 @@ public:
_FORCE_INLINE_ Rect2 get_aabb() const { return aabb; }
_FORCE_INLINE_ bool is_configured() const { return configured; }
+ virtual bool allows_one_way_collision() const { return true; }
+
virtual bool is_concave() const { return false; }
virtual bool contains_point(const Vector2 &p_point) const = 0;
@@ -119,8 +121,7 @@ public:
}
}
}
-
- Shape2DSW();
+ Shape2DSW() {}
virtual ~Shape2DSW();
};
@@ -140,15 +141,15 @@ public:
r_max = MAX(maxa, maxb); \
}
-class WorldMarginShape2DSW : public Shape2DSW {
+class WorldBoundaryShape2DSW : public Shape2DSW {
Vector2 normal;
- real_t d;
+ real_t d = 0.0;
public:
_FORCE_INLINE_ Vector2 get_normal() const { return normal; }
_FORCE_INLINE_ real_t get_d() const { return d; }
- virtual PhysicsServer2D::ShapeType get_type() const override { return PhysicsServer2D::SHAPE_WORLD_MARGIN; }
+ virtual PhysicsServer2D::ShapeType get_type() const override { return PhysicsServer2D::SHAPE_WORLD_BOUNDARY; }
virtual void project_rangev(const Vector2 &p_normal, const Transform2D &p_transform, real_t &r_min, real_t &r_max) const override { project_range(p_normal, p_transform, r_min, r_max); }
virtual void get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const override;
@@ -177,6 +178,43 @@ public:
}
};
+class SeparationRayShape2DSW : public Shape2DSW {
+ real_t length = 0.0;
+ bool slide_on_slope = false;
+
+public:
+ _FORCE_INLINE_ real_t get_length() const { return length; }
+ _FORCE_INLINE_ bool get_slide_on_slope() const { return slide_on_slope; }
+
+ virtual PhysicsServer2D::ShapeType get_type() const override { return PhysicsServer2D::SHAPE_SEPARATION_RAY; }
+
+ virtual bool allows_one_way_collision() const override { return false; }
+
+ virtual void project_rangev(const Vector2 &p_normal, const Transform2D &p_transform, real_t &r_min, real_t &r_max) const override { project_range(p_normal, p_transform, r_min, r_max); }
+ virtual void get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const override;
+
+ virtual bool contains_point(const Vector2 &p_point) const override;
+ virtual bool intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const override;
+ virtual real_t get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const override;
+
+ virtual void set_data(const Variant &p_data) override;
+ virtual Variant get_data() const override;
+
+ _FORCE_INLINE_ void project_range(const Vector2 &p_normal, const Transform2D &p_transform, real_t &r_min, real_t &r_max) const {
+ //real large
+ r_max = p_normal.dot(p_transform.get_origin());
+ r_min = p_normal.dot(p_transform.xform(Vector2(0, length)));
+ if (r_max < r_min) {
+ SWAP(r_max, r_min);
+ }
+ }
+
+ DEFAULT_PROJECT_RANGE_CAST
+
+ _FORCE_INLINE_ SeparationRayShape2DSW() {}
+ _FORCE_INLINE_ SeparationRayShape2DSW(real_t p_length) { length = p_length; }
+};
+
class SegmentShape2DSW : public Shape2DSW {
Vector2 a;
Vector2 b;
@@ -327,8 +365,8 @@ public:
};
class CapsuleShape2DSW : public Shape2DSW {
- real_t radius;
- real_t height;
+ real_t radius = 0.0;
+ real_t height = 0.0;
public:
_FORCE_INLINE_ const real_t &get_radius() const { return radius; }
@@ -373,8 +411,8 @@ class ConvexPolygonShape2DSW : public Shape2DSW {
Vector2 normal; //normal to next segment
};
- Point *points;
- int point_count;
+ Point *points = nullptr;
+ int point_count = 0;
public:
_FORCE_INLINE_ int get_point_count() const { return point_count; }
@@ -419,21 +457,23 @@ public:
DEFAULT_PROJECT_RANGE_CAST
- ConvexPolygonShape2DSW();
+ ConvexPolygonShape2DSW() {}
~ConvexPolygonShape2DSW();
};
class ConcaveShape2DSW : public Shape2DSW {
public:
virtual bool is_concave() const override { return true; }
- typedef void (*Callback)(void *p_userdata, Shape2DSW *p_convex);
- virtual void cull(const Rect2 &p_local_aabb, Callback p_callback, void *p_userdata) const = 0;
+ // Returns true to stop the query.
+ typedef bool (*QueryCallback)(void *p_userdata, Shape2DSW *p_convex);
+
+ virtual void cull(const Rect2 &p_local_aabb, QueryCallback p_callback, void *p_userdata) const = 0;
};
class ConcavePolygonShape2DSW : public ConcaveShape2DSW {
struct Segment {
- int points[2];
+ int points[2] = {};
};
Vector<Segment> segments;
@@ -441,11 +481,11 @@ class ConcavePolygonShape2DSW : public ConcaveShape2DSW {
struct BVH {
Rect2 aabb;
- int left, right;
+ int left = 0, right = 0;
};
Vector<BVH> bvh;
- int bvh_depth;
+ int bvh_depth = 0;
struct BVH_CompareX {
_FORCE_INLINE_ bool operator()(const BVH &a, const BVH &b) const {
@@ -486,7 +526,7 @@ public:
virtual void set_data(const Variant &p_data) override;
virtual Variant get_data() const override;
- virtual void cull(const Rect2 &p_local_aabb, Callback p_callback, void *p_userdata) const override;
+ virtual void cull(const Rect2 &p_local_aabb, QueryCallback p_callback, void *p_userdata) const override;
DEFAULT_PROJECT_RANGE_CAST
};
diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp
index f04f3ab583..dd0780b5ff 100644
--- a/servers/physics_2d/space_2d_sw.cpp
+++ b/servers/physics_2d/space_2d_sw.cpp
@@ -34,6 +34,9 @@
#include "core/os/os.h"
#include "core/templates/pair.h"
#include "physics_server_2d_sw.h"
+
+#define TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR 0.05
+
_FORCE_INLINE_ static bool _can_collide_with(CollisionObject2DSW *p_object, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
if (!(p_object->get_collision_layer() & p_collision_mask)) {
return false;
@@ -102,7 +105,6 @@ int PhysicsDirectSpaceState2DSW::_intersect_point_impl(const Vector2 &p_point, S
}
r_results[cc].rid = col_obj->get_self();
r_results[cc].shape = shape_idx;
- r_results[cc].metadata = col_obj->get_shape_metadata(shape_idx);
cc++;
}
@@ -190,7 +192,6 @@ bool PhysicsDirectSpaceState2DSW::intersect_ray(const Vector2 &p_from, const Vec
r_result.collider = ObjectDB::get_instance(r_result.collider_id);
}
r_result.normal = res_normal;
- r_result.metadata = res_obj->get_shape_metadata(res_shape);
r_result.position = res_point;
r_result.rid = res_obj->get_self();
r_result.shape = res_shape;
@@ -203,7 +204,7 @@ int PhysicsDirectSpaceState2DSW::intersect_shape(const RID &p_shape, const Trans
return 0;
}
- Shape2DSW *shape = PhysicsServer2DSW::singletonsw->shape_owner.getornull(p_shape);
+ Shape2DSW *shape = PhysicsServer2DSW::singletonsw->shape_owner.get_or_null(p_shape);
ERR_FAIL_COND_V(!shape, 0);
Rect2 aabb = p_xform.xform(shape->get_aabb());
@@ -239,7 +240,6 @@ int PhysicsDirectSpaceState2DSW::intersect_shape(const RID &p_shape, const Trans
}
r_results[cc].rid = col_obj->get_self();
r_results[cc].shape = shape_idx;
- r_results[cc].metadata = col_obj->get_shape_metadata(shape_idx);
cc++;
}
@@ -248,7 +248,7 @@ int PhysicsDirectSpaceState2DSW::intersect_shape(const RID &p_shape, const Trans
}
bool PhysicsDirectSpaceState2DSW::cast_motion(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
- Shape2DSW *shape = PhysicsServer2DSW::singletonsw->shape_owner.getornull(p_shape);
+ Shape2DSW *shape = PhysicsServer2DSW::singletonsw->shape_owner.get_or_null(p_shape);
ERR_FAIL_COND_V(!shape, false);
Rect2 aabb = p_xform.xform(shape->get_aabb());
@@ -335,7 +335,7 @@ bool PhysicsDirectSpaceState2DSW::collide_shape(RID p_shape, const Transform2D &
return false;
}
- Shape2DSW *shape = PhysicsServer2DSW::singletonsw->shape_owner.getornull(p_shape);
+ Shape2DSW *shape = PhysicsServer2DSW::singletonsw->shape_owner.get_or_null(p_shape);
ERR_FAIL_COND_V(!shape, 0);
Rect2 aabb = p_shape_xform.xform(shape->get_aabb());
@@ -383,18 +383,18 @@ bool PhysicsDirectSpaceState2DSW::collide_shape(RID p_shape, const Transform2D &
}
struct _RestCallbackData2D {
- const CollisionObject2DSW *object;
- const CollisionObject2DSW *best_object;
- int local_shape;
- int best_local_shape;
- int shape;
- int best_shape;
+ const CollisionObject2DSW *object = nullptr;
+ const CollisionObject2DSW *best_object = nullptr;
+ int local_shape = 0;
+ int best_local_shape = 0;
+ int shape = 0;
+ int best_shape = 0;
Vector2 best_contact;
Vector2 best_normal;
- real_t best_len;
+ real_t best_len = 0.0;
Vector2 valid_dir;
- real_t valid_depth;
- real_t min_allowed_depth;
+ real_t valid_depth = 0.0;
+ real_t min_allowed_depth = 0.0;
};
static void _rest_cbk_result(const Vector2 &p_point_A, const Vector2 &p_point_B, void *p_userdata) {
@@ -432,9 +432,11 @@ static void _rest_cbk_result(const Vector2 &p_point_A, const Vector2 &p_point_B,
}
bool PhysicsDirectSpaceState2DSW::rest_info(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
- Shape2DSW *shape = PhysicsServer2DSW::singletonsw->shape_owner.getornull(p_shape);
+ Shape2DSW *shape = PhysicsServer2DSW::singletonsw->shape_owner.get_or_null(p_shape);
ERR_FAIL_COND_V(!shape, 0);
+ real_t min_contact_depth = p_margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR;
+
Rect2 aabb = p_shape_xform.xform(shape->get_aabb());
aabb = aabb.merge(Rect2(aabb.position + p_motion, aabb.size)); //motion
aabb = aabb.grow(p_margin);
@@ -445,7 +447,7 @@ bool PhysicsDirectSpaceState2DSW::rest_info(RID p_shape, const Transform2D &p_sh
rcd.best_len = 0;
rcd.best_object = nullptr;
rcd.best_shape = 0;
- rcd.min_allowed_depth = space->test_motion_min_contact_depth;
+ rcd.min_allowed_depth = min_contact_depth;
for (int i = 0; i < amount; i++) {
if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) {
@@ -479,10 +481,9 @@ bool PhysicsDirectSpaceState2DSW::rest_info(RID p_shape, const Transform2D &p_sh
r_info->normal = rcd.best_normal;
r_info->point = rcd.best_contact;
r_info->rid = rcd.best_object->get_self();
- r_info->metadata = rcd.best_object->get_shape_metadata(rcd.best_shape);
if (rcd.best_object->get_type() == CollisionObject2DSW::TYPE_BODY) {
const Body2DSW *body = static_cast<const Body2DSW *>(rcd.best_object);
- Vector2 rel_vec = r_info->point - body->get_transform().get_origin();
+ Vector2 rel_vec = r_info->point - (body->get_transform().get_origin() + body->get_center_of_mass());
r_info->linear_velocity = Vector2(-body->get_angular_velocity() * rel_vec.y, body->get_angular_velocity() * rel_vec.x) + body->get_linear_velocity();
} else {
@@ -492,10 +493,6 @@ bool PhysicsDirectSpaceState2DSW::rest_info(RID p_shape, const Transform2D &p_sh
return true;
}
-PhysicsDirectSpaceState2DSW::PhysicsDirectSpaceState2DSW() {
- space = nullptr;
-}
-
////////////////////////////////////////////////////////////////////////////////////////////////////////////
int Space2DSW::_cull_aabb_for_body(Body2DSW *p_body, const Rect2 &p_aabb) {
@@ -528,7 +525,7 @@ int Space2DSW::_cull_aabb_for_body(Body2DSW *p_body, const Rect2 &p_aabb) {
return amount;
}
-bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin, PhysicsServer2D::MotionResult *r_result, const Set<RID> &p_exclude) {
+bool Space2DSW::test_body_motion(Body2DSW *p_body, const PhysicsServer2D::MotionParameters &p_parameters, PhysicsServer2D::MotionResult *r_result) {
//give me back regular physics engine logic
//this is madness
//and most people using this function will think
@@ -560,23 +557,25 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
if (!shapes_found) {
if (r_result) {
*r_result = PhysicsServer2D::MotionResult();
- r_result->travel = p_motion;
+ r_result->travel = p_parameters.motion;
}
return false;
}
// Undo the currently transform the physics server is aware of and apply the provided one
- body_aabb = p_from.xform(p_body->get_inv_transform().xform(body_aabb));
- body_aabb = body_aabb.grow(p_margin);
+ body_aabb = p_parameters.from.xform(p_body->get_inv_transform().xform(body_aabb));
+ body_aabb = body_aabb.grow(p_parameters.margin);
static const int max_excluded_shape_pairs = 32;
ExcludedShapeSW excluded_shape_pairs[max_excluded_shape_pairs];
int excluded_shape_pair_count = 0;
- real_t motion_length = p_motion.length();
- Vector2 motion_normal = p_motion / motion_length;
+ real_t min_contact_depth = p_parameters.margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR;
+
+ real_t motion_length = p_parameters.motion.length();
+ Vector2 motion_normal = p_parameters.motion / motion_length;
- Transform2D body_transform = p_from;
+ Transform2D body_transform = p_parameters.from;
bool recovered = false;
@@ -613,7 +612,10 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
for (int i = 0; i < amount; i++) {
const CollisionObject2DSW *col_obj = intersection_query_results[i];
- if (p_exclude.has(col_obj->get_self())) {
+ if (p_parameters.exclude_bodies.has(col_obj->get_self())) {
+ continue;
+ }
+ if (p_parameters.exclude_objects.has(col_obj->get_instance_id())) {
continue;
}
@@ -621,11 +623,11 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
Transform2D col_obj_shape_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
- if (col_obj->is_shape_set_as_one_way_collision(shape_idx)) {
+ if (body_shape->allows_one_way_collision() && col_obj->is_shape_set_as_one_way_collision(shape_idx)) {
cbk.valid_dir = col_obj_shape_xform.get_axis(1).normalized();
real_t owc_margin = col_obj->get_shape_one_way_collision_margin(shape_idx);
- cbk.valid_depth = MAX(owc_margin, p_margin); //user specified, but never less than actual margin or it won't work
+ cbk.valid_depth = MAX(owc_margin, p_parameters.margin); //user specified, but never less than actual margin or it won't work
cbk.invalid_by_dir = 0;
if (col_obj->get_type() == CollisionObject2DSW::TYPE_BODY) {
@@ -634,7 +636,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
//fix for moving platforms (kinematic and dynamic), margin is increased by how much it moved in the given direction
Vector2 lv = b->get_linear_velocity();
//compute displacement from linear velocity
- Vector2 motion = lv * PhysicsDirectBodyState2DSW::singleton->step;
+ Vector2 motion = lv * last_step;
real_t motion_len = motion.length();
motion.normalize();
cbk.valid_depth += motion_len * MAX(motion.dot(-cbk.valid_dir), 0.0);
@@ -650,7 +652,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
bool did_collide = false;
Shape2DSW *against_shape = col_obj->get_shape(shape_idx);
- if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), cbkres, cbkptr, nullptr, p_margin)) {
+ if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), cbkres, cbkptr, nullptr, p_parameters.margin)) {
did_collide = cbk.passed > current_passed; //more passed, so collision actually existed
}
@@ -675,6 +677,8 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
break;
}
+ recovered = true;
+
Vector2 recover_motion;
for (int i = 0; i < cbk.amount; i++) {
Vector2 a = sr[i * 2 + 0];
@@ -686,9 +690,9 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
// Compute depth on recovered motion.
real_t depth = n.dot(a + recover_motion) - d;
- if (depth > 0.0) {
+ if (depth > min_contact_depth + CMP_EPSILON) {
// Only recover if there is penetration.
- recover_motion -= n * depth * 0.4;
+ recover_motion -= n * (depth - min_contact_depth) * 0.4;
}
}
@@ -697,8 +701,6 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
break;
}
- recovered = true;
-
body_transform.elements[2] += recover_motion;
body_aabb.position += recover_motion;
@@ -715,7 +717,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
// STEP 2 ATTEMPT MOTION
Rect2 motion_aabb = body_aabb;
- motion_aabb.position += p_motion;
+ motion_aabb.position += p_parameters.motion;
motion_aabb = motion_aabb.merge(body_aabb);
int amount = _cull_aabb_for_body(p_body, motion_aabb);
@@ -726,6 +728,16 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
}
Shape2DSW *body_shape = p_body->get_shape(body_shape_idx);
+
+ // Colliding separation rays allows to properly snap to the ground,
+ // otherwise it's not needed in regular motion.
+ if (!p_parameters.collide_separation_ray && (body_shape->get_type() == PhysicsServer2D::SHAPE_SEPARATION_RAY)) {
+ // When slide on slope is on, separation ray shape acts like a regular shape.
+ if (!static_cast<SeparationRayShape2DSW *>(body_shape)->get_slide_on_slope()) {
+ continue;
+ }
+ }
+
Transform2D body_shape_xform = body_transform * p_body->get_shape_transform(body_shape_idx);
bool stuck = false;
@@ -735,9 +747,13 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
for (int i = 0; i < amount; i++) {
const CollisionObject2DSW *col_obj = intersection_query_results[i];
- if (p_exclude.has(col_obj->get_self())) {
+ if (p_parameters.exclude_bodies.has(col_obj->get_self())) {
+ continue;
+ }
+ if (p_parameters.exclude_objects.has(col_obj->get_instance_id())) {
continue;
}
+
int col_shape_idx = intersection_query_subindex_results[i];
Shape2DSW *against_shape = col_obj->get_shape(col_shape_idx);
@@ -756,13 +772,13 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
Transform2D col_obj_shape_xform = col_obj->get_transform() * col_obj->get_shape_transform(col_shape_idx);
//test initial overlap, does it collide if going all the way?
- if (!CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_motion, against_shape, col_obj_shape_xform, Vector2(), nullptr, nullptr, nullptr, 0)) {
+ if (!CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_parameters.motion, against_shape, col_obj_shape_xform, Vector2(), nullptr, nullptr, nullptr, 0)) {
continue;
}
//test initial overlap
if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), nullptr, nullptr, nullptr, 0)) {
- if (col_obj->is_shape_set_as_one_way_collision(col_shape_idx)) {
+ if (body_shape->allows_one_way_collision() && col_obj->is_shape_set_as_one_way_collision(col_shape_idx)) {
Vector2 direction = col_obj_shape_xform.get_axis(1).normalized();
if (motion_normal.dot(direction) < 0) {
continue;
@@ -781,7 +797,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
real_t fraction = low + (hi - low) * fraction_coeff;
Vector2 sep = motion_normal; //important optimization for this to work fast enough
- bool collided = CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_motion * fraction, against_shape, col_obj_shape_xform, Vector2(), nullptr, nullptr, &sep, 0);
+ bool collided = CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_parameters.motion * fraction, against_shape, col_obj_shape_xform, Vector2(), nullptr, nullptr, &sep, 0);
if (collided) {
hi = fraction;
@@ -806,7 +822,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
}
}
- if (col_obj->is_shape_set_as_one_way_collision(col_shape_idx)) {
+ if (body_shape->allows_one_way_collision() && col_obj->is_shape_set_as_one_way_collision(col_shape_idx)) {
Vector2 cd[2];
PhysicsServer2DSW::CollCbkData cbk;
cbk.max = 1;
@@ -818,7 +834,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
cbk.valid_depth = 10e20;
Vector2 sep = motion_normal; //important optimization for this to work fast enough
- bool collided = CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_motion * (hi + contact_max_allowed_penetration), col_obj->get_shape(col_shape_idx), col_obj_shape_xform, Vector2(), PhysicsServer2DSW::_shape_col_cbk, &cbk, &sep, 0);
+ bool collided = CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_parameters.motion * (hi + contact_max_allowed_penetration), col_obj->get_shape(col_shape_idx), col_obj_shape_xform, Vector2(), PhysicsServer2DSW::_shape_col_cbk, &cbk, &sep, 0);
if (!collided || cbk.amount == 0) {
continue;
}
@@ -856,7 +872,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
//it collided, let's get the rest info in unsafe advance
Transform2D ugt = body_transform;
- ugt.elements[2] += p_motion * unsafe;
+ ugt.elements[2] += p_parameters.motion * unsafe;
_RestCallbackData2D rcd;
rcd.best_len = 0;
@@ -864,7 +880,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
rcd.best_shape = 0;
// Allowed depth can't be lower than motion length, in order to handle contacts at low speed.
- rcd.min_allowed_depth = MIN(motion_length, test_motion_min_contact_depth);
+ rcd.min_allowed_depth = MIN(motion_length, min_contact_depth);
int from_shape = best_shape != -1 ? best_shape : 0;
int to_shape = best_shape != -1 ? best_shape + 1 : p_body->get_shape_count();
@@ -877,13 +893,16 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
Transform2D body_shape_xform = ugt * p_body->get_shape_transform(j);
Shape2DSW *body_shape = p_body->get_shape(j);
- body_aabb.position += p_motion * unsafe;
+ body_aabb.position += p_parameters.motion * unsafe;
int amount = _cull_aabb_for_body(p_body, body_aabb);
for (int i = 0; i < amount; i++) {
const CollisionObject2DSW *col_obj = intersection_query_results[i];
- if (p_exclude.has(col_obj->get_self())) {
+ if (p_parameters.exclude_bodies.has(col_obj->get_self())) {
+ continue;
+ }
+ if (p_parameters.exclude_objects.has(col_obj->get_instance_id())) {
continue;
}
@@ -904,11 +923,11 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
Transform2D col_obj_shape_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
- if (col_obj->is_shape_set_as_one_way_collision(shape_idx)) {
+ if (body_shape->allows_one_way_collision() && col_obj->is_shape_set_as_one_way_collision(shape_idx)) {
rcd.valid_dir = col_obj_shape_xform.get_axis(1).normalized();
real_t owc_margin = col_obj->get_shape_one_way_collision_margin(shape_idx);
- rcd.valid_depth = MAX(owc_margin, p_margin); //user specified, but never less than actual margin or it won't work
+ rcd.valid_depth = MAX(owc_margin, p_parameters.margin); //user specified, but never less than actual margin or it won't work
if (col_obj->get_type() == CollisionObject2DSW::TYPE_BODY) {
const Body2DSW *b = static_cast<const Body2DSW *>(col_obj);
@@ -916,7 +935,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
//fix for moving platforms (kinematic and dynamic), margin is increased by how much it moved in the given direction
Vector2 lv = b->get_linear_velocity();
//compute displacement from linear velocity
- Vector2 motion = lv * PhysicsDirectBodyState2DSW::singleton->step;
+ Vector2 motion = lv * last_step;
real_t motion_len = motion.length();
motion.normalize();
rcd.valid_depth += motion_len * MAX(motion.dot(-rcd.valid_dir), 0.0);
@@ -930,7 +949,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
rcd.object = col_obj;
rcd.shape = shape_idx;
rcd.local_shape = j;
- bool sc = CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), _rest_cbk_result, &rcd, nullptr, p_margin);
+ bool sc = CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), _rest_cbk_result, &rcd, nullptr, p_parameters.margin);
if (!sc) {
continue;
}
@@ -948,15 +967,14 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
r_result->collision_depth = rcd.best_len;
r_result->collision_safe_fraction = safe;
r_result->collision_unsafe_fraction = unsafe;
- r_result->collider_metadata = rcd.best_object->get_shape_metadata(rcd.best_shape);
const Body2DSW *body = static_cast<const Body2DSW *>(rcd.best_object);
- Vector2 rel_vec = r_result->collision_point - body->get_transform().get_origin();
+ Vector2 rel_vec = r_result->collision_point - (body->get_transform().get_origin() + body->get_center_of_mass());
r_result->collider_velocity = Vector2(-body->get_angular_velocity() * rel_vec.y, body->get_angular_velocity() * rel_vec.x) + body->get_linear_velocity();
- r_result->travel = safe * p_motion;
- r_result->remainder = p_motion - safe * p_motion;
- r_result->travel += (body_transform.get_origin() - p_from.get_origin());
+ r_result->travel = safe * p_parameters.motion;
+ r_result->remainder = p_parameters.motion - safe * p_parameters.motion;
+ r_result->travel += (body_transform.get_origin() - p_parameters.from.get_origin());
}
collided = true;
@@ -964,9 +982,9 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
}
if (!collided && r_result) {
- r_result->travel = p_motion;
+ r_result->travel = p_parameters.motion;
r_result->remainder = Vector2();
- r_result->travel += (body_transform.get_origin() - p_from.get_origin());
+ r_result->travel += (body_transform.get_origin() - p_parameters.from.get_origin());
}
return collided;
@@ -1031,12 +1049,12 @@ void Space2DSW::body_remove_from_active_list(SelfList<Body2DSW> *p_body) {
active_list.remove(p_body);
}
-void Space2DSW::body_add_to_inertia_update_list(SelfList<Body2DSW> *p_body) {
- inertia_update_list.add(p_body);
+void Space2DSW::body_add_to_mass_properties_update_list(SelfList<Body2DSW> *p_body) {
+ mass_properties_update_list.add(p_body);
}
-void Space2DSW::body_remove_from_inertia_update_list(SelfList<Body2DSW> *p_body) {
- inertia_update_list.remove(p_body);
+void Space2DSW::body_remove_from_mass_properties_update_list(SelfList<Body2DSW> *p_body) {
+ mass_properties_update_list.remove(p_body);
}
BroadPhase2DSW *Space2DSW::get_broadphase() {
@@ -1102,9 +1120,9 @@ void Space2DSW::call_queries() {
void Space2DSW::setup() {
contact_debug_count = 0;
- while (inertia_update_list.first()) {
- inertia_update_list.first()->self()->update_inertias();
- inertia_update_list.remove(inertia_update_list.first());
+ while (mass_properties_update_list.first()) {
+ mass_properties_update_list.first()->self()->update_mass_properties();
+ mass_properties_update_list.remove(mass_properties_update_list.first());
}
}
@@ -1135,9 +1153,6 @@ void Space2DSW::set_param(PhysicsServer2D::SpaceParameter p_param, real_t p_valu
case PhysicsServer2D::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS:
constraint_bias = p_value;
break;
- case PhysicsServer2D::SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH:
- test_motion_min_contact_depth = p_value;
- break;
}
}
@@ -1157,8 +1172,6 @@ real_t Space2DSW::get_param(PhysicsServer2D::SpaceParameter p_param) const {
return body_time_to_sleep;
case PhysicsServer2D::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS:
return constraint_bias;
- case PhysicsServer2D::SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH:
- return test_motion_min_contact_depth;
}
return 0;
}
@@ -1180,19 +1193,6 @@ PhysicsDirectSpaceState2DSW *Space2DSW::get_direct_state() {
}
Space2DSW::Space2DSW() {
- collision_pairs = 0;
- active_objects = 0;
- island_count = 0;
-
- contact_debug_count = 0;
-
- locked = false;
- contact_recycle_radius = 1.0;
- contact_max_separation = 1.5;
- contact_max_allowed_penetration = 0.3;
- test_motion_min_contact_depth = 0.005;
-
- constraint_bias = 0.2;
body_linear_velocity_sleep_threshold = GLOBAL_DEF("physics/2d/sleep_threshold_linear", 2.0);
body_angular_velocity_sleep_threshold = GLOBAL_DEF("physics/2d/sleep_threshold_angular", Math::deg2rad(8.0));
body_time_to_sleep = GLOBAL_DEF("physics/2d/time_before_sleep", 0.5);
@@ -1201,14 +1201,9 @@ Space2DSW::Space2DSW() {
broadphase = BroadPhase2DSW::create_func();
broadphase->set_pair_callback(_broadphase_pair, this);
broadphase->set_unpair_callback(_broadphase_unpair, this);
- area = nullptr;
direct_access = memnew(PhysicsDirectSpaceState2DSW);
direct_access->space = this;
-
- for (int i = 0; i < ELAPSED_TIME_MAX; i++) {
- elapsed_time[i] = 0;
- }
}
Space2DSW::~Space2DSW() {
diff --git a/servers/physics_2d/space_2d_sw.h b/servers/physics_2d/space_2d_sw.h
index 3be36852b0..746b5c6c9a 100644
--- a/servers/physics_2d/space_2d_sw.h
+++ b/servers/physics_2d/space_2d_sw.h
@@ -47,17 +47,17 @@ class PhysicsDirectSpaceState2DSW : public PhysicsDirectSpaceState2D {
int _intersect_point_impl(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_point, bool p_filter_by_canvas = false, ObjectID p_canvas_instance_id = ObjectID());
public:
- Space2DSW *space;
+ Space2DSW *space = nullptr;
- virtual int intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_point = false) override;
- virtual int intersect_point_on_canvas(const Vector2 &p_point, ObjectID p_canvas_instance_id, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_point = false) override;
- virtual bool intersect_ray(const Vector2 &p_from, const Vector2 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
- virtual int intersect_shape(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
- virtual bool cast_motion(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
- virtual bool collide_shape(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, Vector2 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
- virtual bool rest_info(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
+ virtual int intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_point = false) override;
+ virtual int intersect_point_on_canvas(const Vector2 &p_point, ObjectID p_canvas_instance_id, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_point = false) override;
+ virtual bool intersect_ray(const Vector2 &p_from, const Vector2 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
+ virtual int intersect_shape(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
+ virtual bool cast_motion(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
+ virtual bool collide_shape(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, Vector2 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
+ virtual bool rest_info(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
- PhysicsDirectSpaceState2DSW();
+ PhysicsDirectSpaceState2DSW() {}
};
class Space2DSW {
@@ -74,19 +74,19 @@ public:
private:
struct ExcludedShapeSW {
- Shape2DSW *local_shape;
- const CollisionObject2DSW *against_object;
- int against_shape_index;
+ Shape2DSW *local_shape = nullptr;
+ const CollisionObject2DSW *against_object = nullptr;
+ int against_shape_index = 0;
};
- uint64_t elapsed_time[ELAPSED_TIME_MAX];
+ uint64_t elapsed_time[ELAPSED_TIME_MAX] = {};
- PhysicsDirectSpaceState2DSW *direct_access;
+ PhysicsDirectSpaceState2DSW *direct_access = nullptr;
RID self;
BroadPhase2DSW *broadphase;
SelfList<Body2DSW>::List active_list;
- SelfList<Body2DSW>::List inertia_update_list;
+ SelfList<Body2DSW>::List mass_properties_update_list;
SelfList<Body2DSW>::List state_query_list;
SelfList<Area2DSW>::List monitor_query_list;
SelfList<Area2DSW>::List area_moved_list;
@@ -96,13 +96,12 @@ private:
Set<CollisionObject2DSW *> objects;
- Area2DSW *area;
+ Area2DSW *area = nullptr;
- real_t contact_recycle_radius;
- real_t contact_max_separation;
- real_t contact_max_allowed_penetration;
- real_t constraint_bias;
- real_t test_motion_min_contact_depth;
+ real_t contact_recycle_radius = 1.0;
+ real_t contact_max_separation = 1.5;
+ real_t contact_max_allowed_penetration = 0.3;
+ real_t constraint_bias = 0.2;
enum {
INTERSECTION_QUERY_MAX = 2048
@@ -111,20 +110,22 @@ private:
CollisionObject2DSW *intersection_query_results[INTERSECTION_QUERY_MAX];
int intersection_query_subindex_results[INTERSECTION_QUERY_MAX];
- real_t body_linear_velocity_sleep_threshold;
- real_t body_angular_velocity_sleep_threshold;
- real_t body_time_to_sleep;
+ real_t body_linear_velocity_sleep_threshold = 0.0;
+ real_t body_angular_velocity_sleep_threshold = 0.0;
+ real_t body_time_to_sleep = 0.0;
- bool locked;
+ bool locked = false;
- int island_count;
- int active_objects;
- int collision_pairs;
+ real_t last_step = 0.001;
+
+ int island_count = 0;
+ int active_objects = 0;
+ int collision_pairs = 0;
int _cull_aabb_for_body(Body2DSW *p_body, const Rect2 &p_aabb);
Vector<Vector2> contact_debug;
- int contact_debug_count;
+ int contact_debug_count = 0;
friend class PhysicsDirectSpaceState2DSW;
@@ -138,8 +139,8 @@ public:
const SelfList<Body2DSW>::List &get_active_body_list() const;
void body_add_to_active_list(SelfList<Body2DSW> *p_body);
void body_remove_from_active_list(SelfList<Body2DSW> *p_body);
- void body_add_to_inertia_update_list(SelfList<Body2DSW> *p_body);
- void body_remove_from_inertia_update_list(SelfList<Body2DSW> *p_body);
+ void body_add_to_mass_properties_update_list(SelfList<Body2DSW> *p_body);
+ void body_remove_from_mass_properties_update_list(SelfList<Body2DSW> *p_body);
void area_add_to_moved_list(SelfList<Area2DSW> *p_area);
void area_remove_from_moved_list(SelfList<Area2DSW> *p_area);
const SelfList<Area2DSW>::List &get_moved_area_list() const;
@@ -172,6 +173,9 @@ public:
void lock();
void unlock();
+ real_t get_last_step() const { return last_step; }
+ void set_last_step(real_t p_step) { last_step = p_step; }
+
void set_param(PhysicsServer2D::SpaceParameter p_param, real_t p_value);
real_t get_param(PhysicsServer2D::SpaceParameter p_param) const;
@@ -183,7 +187,7 @@ public:
int get_collision_pairs() const { return collision_pairs; }
- bool test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin, PhysicsServer2D::MotionResult *r_result, const Set<RID> &p_exclude = Set<RID>());
+ bool test_body_motion(Body2DSW *p_body, const PhysicsServer2D::MotionParameters &p_parameters, PhysicsServer2D::MotionResult *r_result);
void set_debug_contacts(int p_amount) { contact_debug.resize(p_amount); }
_FORCE_INLINE_ bool is_debugging_contacts() const { return !contact_debug.is_empty(); }
diff --git a/servers/physics_2d/step_2d_sw.cpp b/servers/physics_2d/step_2d_sw.cpp
index 8b30160cc1..a03e30f850 100644
--- a/servers/physics_2d/step_2d_sw.cpp
+++ b/servers/physics_2d/step_2d_sw.cpp
@@ -129,6 +129,8 @@ void Step2DSW::step(Space2DSW *p_space, real_t p_delta, int p_iterations) {
p_space->setup(); //update inertias, etc
+ p_space->set_last_step(p_delta);
+
iterations = p_iterations;
delta = p_delta;
@@ -294,8 +296,6 @@ void Step2DSW::step(Space2DSW *p_space, real_t p_delta, int p_iterations) {
}
Step2DSW::Step2DSW() {
- _step = 1;
-
body_islands.reserve(BODY_ISLAND_COUNT_RESERVE);
constraint_islands.reserve(ISLAND_COUNT_RESERVE);
all_constraints.reserve(CONSTRAINT_COUNT_RESERVE);
diff --git a/servers/physics_2d/step_2d_sw.h b/servers/physics_2d/step_2d_sw.h
index c51fd73a79..de8e76cc99 100644
--- a/servers/physics_2d/step_2d_sw.h
+++ b/servers/physics_2d/step_2d_sw.h
@@ -37,7 +37,7 @@
#include "core/templates/thread_work_pool.h"
class Step2DSW {
- uint64_t _step;
+ uint64_t _step = 1;
int iterations = 0;
real_t delta = 0.0;
diff --git a/servers/physics_3d/area_3d_sw.cpp b/servers/physics_3d/area_3d_sw.cpp
index 364f63e4ad..630ab7e229 100644
--- a/servers/physics_3d/area_3d_sw.cpp
+++ b/servers/physics_3d/area_3d_sw.cpp
@@ -163,6 +163,20 @@ void Area3DSW::set_param(PhysicsServer3D::AreaParameter p_param, const Variant &
case PhysicsServer3D::AREA_PARAM_PRIORITY:
priority = p_value;
break;
+ case PhysicsServer3D::AREA_PARAM_WIND_FORCE_MAGNITUDE:
+ ERR_FAIL_COND_MSG(wind_force_magnitude < 0, "Wind force magnitude must be a non-negative real number, but a negative number was specified.");
+ wind_force_magnitude = p_value;
+ break;
+ case PhysicsServer3D::AREA_PARAM_WIND_SOURCE:
+ wind_source = p_value;
+ break;
+ case PhysicsServer3D::AREA_PARAM_WIND_DIRECTION:
+ wind_direction = p_value;
+ break;
+ case PhysicsServer3D::AREA_PARAM_WIND_ATTENUATION_FACTOR:
+ ERR_FAIL_COND_MSG(wind_attenuation_factor < 0, "Wind attenuation factor must be a non-negative real number, but a negative number was specified.");
+ wind_attenuation_factor = p_value;
+ break;
}
}
@@ -184,6 +198,14 @@ Variant Area3DSW::get_param(PhysicsServer3D::AreaParameter p_param) const {
return angular_damp;
case PhysicsServer3D::AREA_PARAM_PRIORITY:
return priority;
+ case PhysicsServer3D::AREA_PARAM_WIND_FORCE_MAGNITUDE:
+ return wind_force_magnitude;
+ case PhysicsServer3D::AREA_PARAM_WIND_SOURCE:
+ return wind_source;
+ case PhysicsServer3D::AREA_PARAM_WIND_DIRECTION:
+ return wind_direction;
+ case PhysicsServer3D::AREA_PARAM_WIND_ATTENUATION_FACTOR:
+ return wind_attenuation_factor;
}
return Variant();
@@ -282,22 +304,32 @@ void Area3DSW::call_queries() {
}
}
+void Area3DSW::compute_gravity(const Vector3 &p_position, Vector3 &r_gravity) const {
+ if (is_gravity_point()) {
+ const real_t gravity_distance_scale = get_gravity_distance_scale();
+ Vector3 v = get_transform().xform(get_gravity_vector()) - p_position;
+ if (gravity_distance_scale > 0) {
+ const real_t v_length = v.length();
+ if (v_length > 0) {
+ const real_t v_scaled = v_length * gravity_distance_scale;
+ r_gravity = (v.normalized() * (get_gravity() / (v_scaled * v_scaled)));
+ } else {
+ r_gravity = Vector3();
+ }
+ } else {
+ r_gravity = v.normalized() * get_gravity();
+ }
+ } else {
+ r_gravity = get_gravity_vector() * get_gravity();
+ }
+}
+
Area3DSW::Area3DSW() :
CollisionObject3DSW(TYPE_AREA),
monitor_query_list(this),
moved_list(this) {
_set_static(true); //areas are never active
- space_override_mode = PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED;
- gravity = 9.80665;
- gravity_vector = Vector3(0, -1, 0);
- gravity_is_point = false;
- gravity_distance_scale = 0;
- point_attenuation = 1;
- angular_damp = 0.1;
- linear_damp = 0.1;
- priority = 0;
set_ray_pickable(false);
- monitorable = false;
}
Area3DSW::~Area3DSW() {
diff --git a/servers/physics_3d/area_3d_sw.h b/servers/physics_3d/area_3d_sw.h
index 5959ee1e95..af5c23949c 100644
--- a/servers/physics_3d/area_3d_sw.h
+++ b/servers/physics_3d/area_3d_sw.h
@@ -34,7 +34,6 @@
#include "collision_object_3d_sw.h"
#include "core/templates/self_list.h"
#include "servers/physics_server_3d.h"
-//#include "servers/physics_3d/query_sw.h"
class Space3DSW;
class Body3DSW;
@@ -42,16 +41,20 @@ class SoftBody3DSW;
class Constraint3DSW;
class Area3DSW : public CollisionObject3DSW {
- PhysicsServer3D::AreaSpaceOverrideMode space_override_mode;
- real_t gravity;
- Vector3 gravity_vector;
- bool gravity_is_point;
- real_t gravity_distance_scale;
- real_t point_attenuation;
- real_t linear_damp;
- real_t angular_damp;
- int priority;
- bool monitorable;
+ PhysicsServer3D::AreaSpaceOverrideMode space_override_mode = PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED;
+ real_t gravity = 9.80665;
+ Vector3 gravity_vector = Vector3(0, -1, 0);
+ bool gravity_is_point = false;
+ real_t gravity_distance_scale = 0.0;
+ real_t point_attenuation = 1.0;
+ real_t linear_damp = 0.1;
+ real_t angular_damp = 0.1;
+ real_t wind_force_magnitude = 0.0;
+ real_t wind_attenuation_factor = 0.0;
+ Vector3 wind_source;
+ Vector3 wind_direction;
+ int priority = 0;
+ bool monitorable = false;
ObjectID monitor_callback_id;
StringName monitor_callback_method;
@@ -65,8 +68,8 @@ class Area3DSW : public CollisionObject3DSW {
struct BodyKey {
RID rid;
ObjectID instance_id;
- uint32_t body_shape;
- uint32_t area_shape;
+ uint32_t body_shape = 0;
+ uint32_t area_shape = 0;
_FORCE_INLINE_ bool operator<(const BodyKey &p_key) const {
if (rid == p_key.rid) {
@@ -87,28 +90,21 @@ class Area3DSW : public CollisionObject3DSW {
};
struct BodyState {
- int state;
+ int state = 0;
_FORCE_INLINE_ void inc() { state++; }
_FORCE_INLINE_ void dec() { state--; }
- _FORCE_INLINE_ BodyState() { state = 0; }
};
Map<BodyKey, BodyState> monitored_soft_bodies;
Map<BodyKey, BodyState> monitored_bodies;
Map<BodyKey, BodyState> monitored_areas;
- //virtual void shape_changed_notify(ShapeSW *p_shape);
- //virtual void shape_deleted_notify(ShapeSW *p_shape);
-
Set<Constraint3DSW *> constraints;
virtual void _shapes_changed();
void _queue_monitor_update();
public:
- //_FORCE_INLINE_ const Transform& get_inverse_transform() const { return inverse_transform; }
- //_FORCE_INLINE_ SpaceSW* get_owner() { return owner; }
-
void set_monitor_callback(ObjectID p_id, const StringName &p_method);
_FORCE_INLINE_ bool has_monitor_callback() const { return monitor_callback_id.is_valid(); }
@@ -154,6 +150,18 @@ public:
_FORCE_INLINE_ void set_priority(int p_priority) { priority = p_priority; }
_FORCE_INLINE_ int get_priority() const { return priority; }
+ _FORCE_INLINE_ void set_wind_force_magnitude(real_t p_wind_force_magnitude) { wind_force_magnitude = p_wind_force_magnitude; }
+ _FORCE_INLINE_ real_t get_wind_force_magnitude() const { return wind_force_magnitude; }
+
+ _FORCE_INLINE_ void set_wind_attenuation_factor(real_t p_wind_attenuation_factor) { wind_attenuation_factor = p_wind_attenuation_factor; }
+ _FORCE_INLINE_ real_t get_wind_attenuation_factor() const { return wind_attenuation_factor; }
+
+ _FORCE_INLINE_ void set_wind_source(const Vector3 &p_wind_source) { wind_source = p_wind_source; }
+ _FORCE_INLINE_ const Vector3 &get_wind_source() const { return wind_source; }
+
+ _FORCE_INLINE_ void set_wind_direction(const Vector3 &p_wind_direction) { wind_direction = p_wind_direction; }
+ _FORCE_INLINE_ const Vector3 &get_wind_direction() const { return wind_direction; }
+
_FORCE_INLINE_ void add_constraint(Constraint3DSW *p_constraint) { constraints.insert(p_constraint); }
_FORCE_INLINE_ void remove_constraint(Constraint3DSW *p_constraint) { constraints.erase(p_constraint); }
_FORCE_INLINE_ const Set<Constraint3DSW *> &get_constraints() const { return constraints; }
@@ -168,6 +176,8 @@ public:
void call_queries();
+ void compute_gravity(const Vector3 &p_position, Vector3 &r_gravity) const;
+
Area3DSW();
~Area3DSW();
};
@@ -221,8 +231,8 @@ void Area3DSW::remove_area_from_query(Area3DSW *p_area, uint32_t p_area_shape, u
}
struct AreaCMP {
- Area3DSW *area;
- int refCount;
+ Area3DSW *area = nullptr;
+ int refCount = 0;
_FORCE_INLINE_ bool operator==(const AreaCMP &p_cmp) const { return area->get_self() == p_cmp.area->get_self(); }
_FORCE_INLINE_ bool operator<(const AreaCMP &p_cmp) const { return area->get_priority() < p_cmp.area->get_priority(); }
_FORCE_INLINE_ AreaCMP() {}
diff --git a/servers/physics_3d/area_pair_3d_sw.cpp b/servers/physics_3d/area_pair_3d_sw.cpp
index e740565da6..bf4f0035b4 100644
--- a/servers/physics_3d/area_pair_3d_sw.cpp
+++ b/servers/physics_3d/area_pair_3d_sw.cpp
@@ -33,7 +33,7 @@
bool AreaPair3DSW::setup(real_t p_step) {
bool result = false;
- if (area->interacts_with(body) && CollisionSolver3DSW::solve_static(body->get_shape(body_shape), body->get_transform() * body->get_shape_transform(body_shape), area->get_shape(area_shape), area->get_transform() * area->get_shape_transform(area_shape), nullptr, this)) {
+ if (area->collides_with(body) && CollisionSolver3DSW::solve_static(body->get_shape(body_shape), body->get_transform() * body->get_shape_transform(body_shape), area->get_shape(area_shape), area->get_transform() * area->get_shape_transform(area_shape), nullptr, this)) {
result = true;
}
@@ -109,46 +109,51 @@ AreaPair3DSW::~AreaPair3DSW() {
////////////////////////////////////////////////////
bool Area2Pair3DSW::setup(real_t p_step) {
- bool result = false;
- if (area_a->interacts_with(area_b) && CollisionSolver3DSW::solve_static(area_a->get_shape(shape_a), area_a->get_transform() * area_a->get_shape_transform(shape_a), area_b->get_shape(shape_b), area_b->get_transform() * area_b->get_shape_transform(shape_b), nullptr, this)) {
- result = true;
+ bool result_a = area_a->collides_with(area_b);
+ bool result_b = area_b->collides_with(area_a);
+ if ((result_a || result_b) && !CollisionSolver3DSW::solve_static(area_a->get_shape(shape_a), area_a->get_transform() * area_a->get_shape_transform(shape_a), area_b->get_shape(shape_b), area_b->get_transform() * area_b->get_shape_transform(shape_b), nullptr, this)) {
+ result_a = false;
+ result_b = false;
}
- process_collision = false;
- if (result != colliding) {
- if (area_b->has_area_monitor_callback() && area_a->is_monitorable()) {
- process_collision = true;
- } else if (area_a->has_area_monitor_callback() && area_b->is_monitorable()) {
+ bool process_collision = false;
+
+ process_collision_a = false;
+ if (result_a != colliding_a) {
+ if (area_a->has_area_monitor_callback() && area_b->is_monitorable()) {
+ process_collision_a = true;
process_collision = true;
}
+ colliding_a = result_a;
+ }
- colliding = result;
+ process_collision_b = false;
+ if (result_b != colliding_b) {
+ if (area_b->has_area_monitor_callback() && area_a->is_monitorable()) {
+ process_collision_b = true;
+ process_collision = true;
+ }
+ colliding_b = result_b;
}
return process_collision;
}
bool Area2Pair3DSW::pre_solve(real_t p_step) {
- if (!process_collision) {
- return false;
+ if (process_collision_a) {
+ if (colliding_a) {
+ area_a->add_area_to_query(area_b, shape_b, shape_a);
+ } else {
+ area_a->remove_area_from_query(area_b, shape_b, shape_a);
+ }
}
- if (colliding) {
- if (area_b->has_area_monitor_callback() && area_a->is_monitorable()) {
+ if (process_collision_b) {
+ if (colliding_b) {
area_b->add_area_to_query(area_a, shape_a, shape_b);
- }
-
- if (area_a->has_area_monitor_callback() && area_b->is_monitorable()) {
- area_a->add_area_to_query(area_b, shape_b, shape_a);
- }
- } else {
- if (area_b->has_area_monitor_callback() && area_a->is_monitorable()) {
+ } else {
area_b->remove_area_from_query(area_a, shape_a, shape_b);
}
-
- if (area_a->has_area_monitor_callback() && area_b->is_monitorable()) {
- area_a->remove_area_from_query(area_b, shape_b, shape_a);
- }
}
return false; // Never do any post solving.
@@ -168,16 +173,18 @@ Area2Pair3DSW::Area2Pair3DSW(Area3DSW *p_area_a, int p_shape_a, Area3DSW *p_area
}
Area2Pair3DSW::~Area2Pair3DSW() {
- if (colliding) {
- if (area_b->has_area_monitor_callback()) {
- area_b->remove_area_from_query(area_a, shape_a, shape_b);
- }
-
+ if (colliding_a) {
if (area_a->has_area_monitor_callback()) {
area_a->remove_area_from_query(area_b, shape_b, shape_a);
}
}
+ if (colliding_b) {
+ if (area_b->has_area_monitor_callback()) {
+ area_b->remove_area_from_query(area_a, shape_a, shape_b);
+ }
+ }
+
area_a->remove_constraint(this);
area_b->remove_constraint(this);
}
@@ -187,7 +194,7 @@ Area2Pair3DSW::~Area2Pair3DSW() {
bool AreaSoftBodyPair3DSW::setup(real_t p_step) {
bool result = false;
if (
- area->interacts_with(soft_body) &&
+ area->collides_with(soft_body) &&
CollisionSolver3DSW::solve_static(
soft_body->get_shape(soft_body_shape),
soft_body->get_transform() * soft_body->get_shape_transform(soft_body_shape),
diff --git a/servers/physics_3d/area_pair_3d_sw.h b/servers/physics_3d/area_pair_3d_sw.h
index 8cc9e9ad63..4572dcbb23 100644
--- a/servers/physics_3d/area_pair_3d_sw.h
+++ b/servers/physics_3d/area_pair_3d_sw.h
@@ -58,8 +58,10 @@ class Area2Pair3DSW : public Constraint3DSW {
Area3DSW *area_b;
int shape_a;
int shape_b;
- bool colliding = false;
- bool process_collision = false;
+ bool colliding_a = false;
+ bool colliding_b = false;
+ bool process_collision_a = false;
+ bool process_collision_b = false;
public:
virtual bool setup(real_t p_step) override;
diff --git a/servers/physics_3d/body_3d_sw.cpp b/servers/physics_3d/body_3d_sw.cpp
index 0c4079332d..069374d122 100644
--- a/servers/physics_3d/body_3d_sw.cpp
+++ b/servers/physics_3d/body_3d_sw.cpp
@@ -29,12 +29,14 @@
/*************************************************************************/
#include "body_3d_sw.h"
+
#include "area_3d_sw.h"
+#include "body_direct_state_3d_sw.h"
#include "space_3d_sw.h"
-void Body3DSW::_update_inertia() {
- if (get_space() && !inertia_update_list.in_list()) {
- get_space()->body_add_to_inertia_update_list(&inertia_update_list);
+void Body3DSW::_mass_properties_changed() {
+ if (get_space() && !mass_properties_update_list.in_list() && (calculate_inertia || calculate_center_of_mass)) {
+ get_space()->body_add_to_mass_properties_update_list(&mass_properties_update_list);
}
}
@@ -42,7 +44,7 @@ void Body3DSW::_update_transform_dependant() {
center_of_mass = get_transform().basis.xform(center_of_mass_local);
principal_inertia_axes = get_transform().basis * principal_inertia_axes_local;
- // update inertia tensor
+ // Update inertia tensor.
Basis tb = principal_inertia_axes;
Basis tbt = tb.transposed();
Basis diag;
@@ -50,74 +52,95 @@ void Body3DSW::_update_transform_dependant() {
_inv_inertia_tensor = tb * diag * tbt;
}
-void Body3DSW::update_inertias() {
+void Body3DSW::update_mass_properties() {
// Update shapes and motions.
switch (mode) {
case PhysicsServer3D::BODY_MODE_DYNAMIC: {
- // Update tensor for all shapes, not the best way but should be somehow OK. (inspired from bullet)
real_t total_area = 0;
-
for (int i = 0; i < get_shape_count(); i++) {
+ if (is_shape_disabled(i)) {
+ continue;
+ }
+
total_area += get_shape_area(i);
}
- // We have to recompute the center of mass.
- center_of_mass_local.zero();
+ if (calculate_center_of_mass) {
+ // We have to recompute the center of mass.
+ center_of_mass_local.zero();
- if (total_area != 0.0) {
- for (int i = 0; i < get_shape_count(); i++) {
- real_t area = get_shape_area(i);
+ if (total_area != 0.0) {
+ for (int i = 0; i < get_shape_count(); i++) {
+ if (is_shape_disabled(i)) {
+ continue;
+ }
- real_t mass = area * this->mass / total_area;
+ real_t area = get_shape_area(i);
- // NOTE: we assume that the shape origin is also its center of mass.
- center_of_mass_local += mass * get_shape_transform(i).origin;
- }
+ real_t mass = area * this->mass / total_area;
+
+ // NOTE: we assume that the shape origin is also its center of mass.
+ center_of_mass_local += mass * get_shape_transform(i).origin;
+ }
- center_of_mass_local /= mass;
+ center_of_mass_local /= mass;
+ }
}
- // Recompute the inertia tensor.
- Basis inertia_tensor;
- inertia_tensor.set_zero();
- bool inertia_set = false;
+ if (calculate_inertia) {
+ // Recompute the inertia tensor.
+ Basis inertia_tensor;
+ inertia_tensor.set_zero();
+ bool inertia_set = false;
- for (int i = 0; i < get_shape_count(); i++) {
- if (is_shape_disabled(i)) {
- continue;
- }
+ for (int i = 0; i < get_shape_count(); i++) {
+ if (is_shape_disabled(i)) {
+ continue;
+ }
- real_t area = get_shape_area(i);
- if (area == 0.0) {
- continue;
- }
+ real_t area = get_shape_area(i);
+ if (area == 0.0) {
+ continue;
+ }
+
+ inertia_set = true;
- inertia_set = true;
+ const Shape3DSW *shape = get_shape(i);
- const Shape3DSW *shape = get_shape(i);
+ real_t mass = area * this->mass / total_area;
- real_t mass = area * this->mass / total_area;
+ Basis shape_inertia_tensor = Basis::from_scale(shape->get_moment_of_inertia(mass));
+ Transform3D shape_transform = get_shape_transform(i);
+ Basis shape_basis = shape_transform.basis.orthonormalized();
- Basis shape_inertia_tensor = shape->get_moment_of_inertia(mass).to_diagonal_matrix();
- Transform3D shape_transform = get_shape_transform(i);
- Basis shape_basis = shape_transform.basis.orthonormalized();
+ // NOTE: we don't take the scale of collision shapes into account when computing the inertia tensor!
+ shape_inertia_tensor = shape_basis * shape_inertia_tensor * shape_basis.transposed();
- // NOTE: we don't take the scale of collision shapes into account when computing the inertia tensor!
- shape_inertia_tensor = shape_basis * shape_inertia_tensor * shape_basis.transposed();
+ Vector3 shape_origin = shape_transform.origin - center_of_mass_local;
+ inertia_tensor += shape_inertia_tensor + (Basis() * shape_origin.dot(shape_origin) - shape_origin.outer(shape_origin)) * mass;
+ }
- Vector3 shape_origin = shape_transform.origin - center_of_mass_local;
- inertia_tensor += shape_inertia_tensor + (Basis() * shape_origin.dot(shape_origin) - shape_origin.outer(shape_origin)) * mass;
- }
+ // Set the inertia to a valid value when there are no valid shapes.
+ if (!inertia_set) {
+ inertia_tensor = Basis();
+ }
- // Set the inertia to a valid value when there are no valid shapes.
- if (!inertia_set) {
- inertia_tensor.set_diagonal(Vector3(1.0, 1.0, 1.0));
- }
+ // Handle partial custom inertia.
+ if (inertia.x > 0.0) {
+ inertia_tensor[0][0] = inertia.x;
+ }
+ if (inertia.y > 0.0) {
+ inertia_tensor[1][1] = inertia.y;
+ }
+ if (inertia.z > 0.0) {
+ inertia_tensor[2][2] = inertia.z;
+ }
- // Compute the principal axes of inertia.
- principal_inertia_axes_local = inertia_tensor.diagonalize().transposed();
- _inv_inertia = inertia_tensor.get_main_diagonal().inverse();
+ // Compute the principal axes of inertia.
+ principal_inertia_axes_local = inertia_tensor.diagonalize().transposed();
+ _inv_inertia = inertia_tensor.get_main_diagonal().inverse();
+ }
if (mass) {
_inv_mass = 1.0 / mass;
@@ -126,24 +149,27 @@ void Body3DSW::update_inertias() {
}
} break;
-
case PhysicsServer3D::BODY_MODE_KINEMATIC:
case PhysicsServer3D::BODY_MODE_STATIC: {
- _inv_inertia_tensor.set_zero();
+ _inv_inertia = Vector3();
_inv_mass = 0;
} break;
- case PhysicsServer3D::BODY_MODE_DYNAMIC_LOCKED: {
+ case PhysicsServer3D::BODY_MODE_DYNAMIC_LINEAR: {
_inv_inertia_tensor.set_zero();
_inv_mass = 1.0 / mass;
} break;
}
- //_update_shapes();
-
_update_transform_dependant();
}
+void Body3DSW::reset_mass_properties() {
+ calculate_inertia = true;
+ calculate_center_of_mass = true;
+ _mass_properties_changed();
+}
+
void Body3DSW::set_active(bool p_active) {
if (active == p_active) {
return;
@@ -163,7 +189,7 @@ void Body3DSW::set_active(bool p_active) {
}
}
-void Body3DSW::set_param(PhysicsServer3D::BodyParameter p_param, real_t p_value) {
+void Body3DSW::set_param(PhysicsServer3D::BodyParameter p_param, const Variant &p_value) {
switch (p_param) {
case PhysicsServer3D::BODY_PARAM_BOUNCE: {
bounce = p_value;
@@ -172,10 +198,33 @@ void Body3DSW::set_param(PhysicsServer3D::BodyParameter p_param, real_t p_value)
friction = p_value;
} break;
case PhysicsServer3D::BODY_PARAM_MASS: {
- ERR_FAIL_COND(p_value <= 0);
- mass = p_value;
- _update_inertia();
-
+ real_t mass_value = p_value;
+ ERR_FAIL_COND(mass_value <= 0);
+ mass = mass_value;
+ if (mode >= PhysicsServer3D::BODY_MODE_DYNAMIC) {
+ _mass_properties_changed();
+ }
+ } break;
+ case PhysicsServer3D::BODY_PARAM_INERTIA: {
+ inertia = p_value;
+ if ((inertia.x <= 0.0) || (inertia.y <= 0.0) || (inertia.z <= 0.0)) {
+ calculate_inertia = true;
+ if (mode == PhysicsServer3D::BODY_MODE_DYNAMIC) {
+ _mass_properties_changed();
+ }
+ } else {
+ calculate_inertia = false;
+ if (mode == PhysicsServer3D::BODY_MODE_DYNAMIC) {
+ principal_inertia_axes_local = Basis();
+ _inv_inertia = inertia.inverse();
+ _update_transform_dependant();
+ }
+ }
+ } break;
+ case PhysicsServer3D::BODY_PARAM_CENTER_OF_MASS: {
+ calculate_center_of_mass = false;
+ center_of_mass_local = p_value;
+ _update_transform_dependant();
} break;
case PhysicsServer3D::BODY_PARAM_GRAVITY_SCALE: {
gravity_scale = p_value;
@@ -191,7 +240,7 @@ void Body3DSW::set_param(PhysicsServer3D::BodyParameter p_param, real_t p_value)
}
}
-real_t Body3DSW::get_param(PhysicsServer3D::BodyParameter p_param) const {
+Variant Body3DSW::get_param(PhysicsServer3D::BodyParameter p_param) const {
switch (p_param) {
case PhysicsServer3D::BODY_PARAM_BOUNCE: {
return bounce;
@@ -202,6 +251,16 @@ real_t Body3DSW::get_param(PhysicsServer3D::BodyParameter p_param) const {
case PhysicsServer3D::BODY_PARAM_MASS: {
return mass;
} break;
+ case PhysicsServer3D::BODY_PARAM_INERTIA: {
+ if (mode == PhysicsServer3D::BODY_MODE_DYNAMIC) {
+ return _inv_inertia.inverse();
+ } else {
+ return Vector3();
+ }
+ } break;
+ case PhysicsServer3D::BODY_PARAM_CENTER_OF_MASS: {
+ return center_of_mass;
+ } break;
case PhysicsServer3D::BODY_PARAM_GRAVITY_SCALE: {
return gravity_scale;
} break;
@@ -224,40 +283,42 @@ void Body3DSW::set_mode(PhysicsServer3D::BodyMode p_mode) {
mode = p_mode;
switch (p_mode) {
- //CLEAR UP EVERYTHING IN CASE IT NOT WORKS!
case PhysicsServer3D::BODY_MODE_STATIC:
case PhysicsServer3D::BODY_MODE_KINEMATIC: {
_set_inv_transform(get_transform().affine_inverse());
_inv_mass = 0;
+ _inv_inertia = Vector3();
_set_static(p_mode == PhysicsServer3D::BODY_MODE_STATIC);
- //set_active(p_mode==PhysicsServer3D::BODY_MODE_KINEMATIC);
set_active(p_mode == PhysicsServer3D::BODY_MODE_KINEMATIC && contacts.size());
linear_velocity = Vector3();
angular_velocity = Vector3();
if (mode == PhysicsServer3D::BODY_MODE_KINEMATIC && prev != mode) {
first_time_kinematic = true;
}
+ _update_transform_dependant();
} break;
case PhysicsServer3D::BODY_MODE_DYNAMIC: {
_inv_mass = mass > 0 ? (1.0 / mass) : 0;
+ if (!calculate_inertia) {
+ principal_inertia_axes_local = Basis();
+ _inv_inertia = inertia.inverse();
+ _update_transform_dependant();
+ }
+ _mass_properties_changed();
_set_static(false);
set_active(true);
} break;
- case PhysicsServer3D::BODY_MODE_DYNAMIC_LOCKED: {
+ case PhysicsServer3D::BODY_MODE_DYNAMIC_LINEAR: {
_inv_mass = mass > 0 ? (1.0 / mass) : 0;
+ _inv_inertia = Vector3();
+ angular_velocity = Vector3();
+ _update_transform_dependant();
_set_static(false);
set_active(true);
- angular_velocity = Vector3();
- } break;
+ }
}
-
- _update_inertia();
- /*
- if (get_space())
- _update_queries();
- */
}
PhysicsServer3D::BodyMode Body3DSW::get_mode() const {
@@ -265,7 +326,7 @@ PhysicsServer3D::BodyMode Body3DSW::get_mode() const {
}
void Body3DSW::_shapes_changed() {
- _update_inertia();
+ _mass_properties_changed();
}
void Body3DSW::set_state(PhysicsServer3D::BodyState p_state, const Variant &p_variant) {
@@ -300,10 +361,12 @@ void Body3DSW::set_state(PhysicsServer3D::BodyState p_state, const Variant &p_va
} break;
case PhysicsServer3D::BODY_STATE_LINEAR_VELOCITY: {
linear_velocity = p_variant;
+ constant_linear_velocity = linear_velocity;
wakeup();
} break;
case PhysicsServer3D::BODY_STATE_ANGULAR_VELOCITY: {
angular_velocity = p_variant;
+ constant_angular_velocity = angular_velocity;
wakeup();
} break;
@@ -324,7 +387,7 @@ void Body3DSW::set_state(PhysicsServer3D::BodyState p_state, const Variant &p_va
} break;
case PhysicsServer3D::BODY_STATE_CAN_SLEEP: {
can_sleep = p_variant;
- if (mode == PhysicsServer3D::BODY_MODE_DYNAMIC && !active && !can_sleep) {
+ if (mode >= PhysicsServer3D::BODY_MODE_DYNAMIC && !active && !can_sleep) {
set_active(true);
}
@@ -356,8 +419,8 @@ Variant Body3DSW::get_state(PhysicsServer3D::BodyState p_state) const {
void Body3DSW::set_space(Space3DSW *p_space) {
if (get_space()) {
- if (inertia_update_list.in_list()) {
- get_space()->body_remove_from_inertia_update_list(&inertia_update_list);
+ if (mass_properties_update_list.in_list()) {
+ get_space()->body_remove_from_mass_properties_update_list(&mass_properties_update_list);
}
if (active_list.in_list()) {
get_space()->body_remove_from_active_list(&active_list);
@@ -370,26 +433,17 @@ void Body3DSW::set_space(Space3DSW *p_space) {
_set_space(p_space);
if (get_space()) {
- _update_inertia();
+ _mass_properties_changed();
if (active) {
get_space()->body_add_to_active_list(&active_list);
}
}
-
- first_integration = true;
}
-void Body3DSW::_compute_area_gravity_and_dampenings(const Area3DSW *p_area) {
- if (p_area->is_gravity_point()) {
- if (p_area->get_gravity_distance_scale() > 0) {
- Vector3 v = p_area->get_transform().xform(p_area->get_gravity_vector()) - get_transform().get_origin();
- gravity += v.normalized() * (p_area->get_gravity() / Math::pow(v.length() * p_area->get_gravity_distance_scale() + 1, 2));
- } else {
- gravity += (p_area->get_transform().xform(p_area->get_gravity_vector()) - get_transform().get_origin()).normalized() * p_area->get_gravity();
- }
- } else {
- gravity += p_area->get_gravity_vector() * p_area->get_gravity();
- }
+void Body3DSW::_compute_area_gravity_and_damping(const Area3DSW *p_area) {
+ Vector3 area_gravity;
+ p_area->compute_gravity(get_transform().get_origin(), area_gravity);
+ gravity += area_gravity;
area_linear_damp += p_area->get_linear_damp();
area_angular_damp += p_area->get_angular_damp();
@@ -431,7 +485,7 @@ void Body3DSW::integrate_forces(real_t p_step) {
switch (mode) {
case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE:
case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: {
- _compute_area_gravity_and_dampenings(aa[i].area);
+ _compute_area_gravity_and_damping(aa[i].area);
stopped = mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE;
} break;
case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE:
@@ -439,7 +493,7 @@ void Body3DSW::integrate_forces(real_t p_step) {
gravity = Vector3(0, 0, 0);
area_angular_damp = 0;
area_linear_damp = 0;
- _compute_area_gravity_and_dampenings(aa[i].area);
+ _compute_area_gravity_and_damping(aa[i].area);
stopped = mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE;
} break;
default: {
@@ -449,7 +503,7 @@ void Body3DSW::integrate_forces(real_t p_step) {
}
if (!stopped) {
- _compute_area_gravity_and_dampenings(def_area);
+ _compute_area_gravity_and_damping(def_area);
}
gravity *= gravity_scale;
@@ -478,7 +532,7 @@ void Body3DSW::integrate_forces(real_t p_step) {
//compute motion, angular and etc. velocities from prev transform
motion = new_transform.origin - get_transform().origin;
do_motion = true;
- linear_velocity = motion / p_step;
+ linear_velocity = constant_linear_velocity + motion / p_step;
//compute a FAKE angular velocity, not so easy
Basis rot = new_transform.basis.orthonormalized() * get_transform().basis.orthonormalized().transposed();
@@ -487,9 +541,9 @@ void Body3DSW::integrate_forces(real_t p_step) {
rot.get_axis_angle(axis, angle);
axis.normalize();
- angular_velocity = axis * (angle / p_step);
+ angular_velocity = constant_angular_velocity + axis * (angle / p_step);
} else {
- if (!omit_force_integration && !first_integration) {
+ if (!omit_force_integration) {
//overridden by direct state query
Vector3 force = gravity * mass;
@@ -523,7 +577,6 @@ void Body3DSW::integrate_forces(real_t p_step) {
applied_force = Vector3();
applied_torque = Vector3();
- first_integration = false;
//motion=linear_velocity*p_step;
@@ -543,7 +596,7 @@ void Body3DSW::integrate_velocities(real_t p_step) {
return;
}
- if (fi_callback) {
+ if (fi_callback_data || body_state_callback) {
get_space()->body_add_to_state_query_list(&direct_state_query_list);
}
@@ -600,11 +653,6 @@ void Body3DSW::integrate_velocities(real_t p_step) {
_set_inv_transform(get_transform().inverse());
_update_transform_dependant();
-
- /*
- if (fi_callback) {
- get_space()->body_add_to_state_query_list(&direct_state_query_list);
- */
}
/*
@@ -640,17 +688,17 @@ void BodySW::simulate_motion(const Transform3D& p_xform,real_t p_step) {
*/
void Body3DSW::wakeup_neighbours() {
- for (Map<Constraint3DSW *, int>::Element *E = constraint_map.front(); E; E = E->next()) {
- const Constraint3DSW *c = E->key();
+ for (const KeyValue<Constraint3DSW *, int> &E : constraint_map) {
+ const Constraint3DSW *c = E.key;
Body3DSW **n = c->get_body_ptr();
int bc = c->get_body_count();
for (int i = 0; i < bc; i++) {
- if (i == E->get()) {
+ if (i == E.value) {
continue;
}
Body3DSW *b = n[i];
- if (b->mode != PhysicsServer3D::BODY_MODE_DYNAMIC) {
+ if (b->mode < PhysicsServer3D::BODY_MODE_DYNAMIC) {
continue;
}
@@ -662,24 +710,23 @@ void Body3DSW::wakeup_neighbours() {
}
void Body3DSW::call_queries() {
- if (fi_callback) {
- PhysicsDirectBodyState3DSW *dbs = PhysicsDirectBodyState3DSW::singleton;
- dbs->body = this;
-
- Variant v = dbs;
-
- Object *obj = fi_callback->callable.get_object();
- if (!obj) {
+ if (fi_callback_data) {
+ if (!fi_callback_data->callable.get_object()) {
set_force_integration_callback(Callable());
} else {
- const Variant *vp[2] = { &v, &fi_callback->udata };
+ Variant direct_state_variant = get_direct_state();
+ const Variant *vp[2] = { &direct_state_variant, &fi_callback_data->udata };
Callable::CallError ce;
- int argc = (fi_callback->udata.get_type() == Variant::NIL) ? 1 : 2;
+ int argc = (fi_callback_data->udata.get_type() == Variant::NIL) ? 1 : 2;
Variant rv;
- fi_callback->callable.call(vp, argc, rv, ce);
+ fi_callback_data->callable.call(vp, argc, rv, ce);
}
}
+
+ if (body_state_callback_instance) {
+ (body_state_callback)(body_state_callback_instance, get_direct_state());
+ }
}
bool Body3DSW::sleep_test(real_t p_step) {
@@ -699,60 +746,45 @@ bool Body3DSW::sleep_test(real_t p_step) {
}
}
+void Body3DSW::set_state_sync_callback(void *p_instance, PhysicsServer3D::BodyStateCallback p_callback) {
+ body_state_callback_instance = p_instance;
+ body_state_callback = p_callback;
+}
+
void Body3DSW::set_force_integration_callback(const Callable &p_callable, const Variant &p_udata) {
- if (fi_callback) {
- memdelete(fi_callback);
- fi_callback = nullptr;
+ if (p_callable.get_object()) {
+ if (!fi_callback_data) {
+ fi_callback_data = memnew(ForceIntegrationCallbackData);
+ }
+ fi_callback_data->callable = p_callable;
+ fi_callback_data->udata = p_udata;
+ } else if (fi_callback_data) {
+ memdelete(fi_callback_data);
+ fi_callback_data = nullptr;
}
+}
- if (p_callable.get_object()) {
- fi_callback = memnew(ForceIntegrationCallback);
- fi_callback->callable = p_callable;
- fi_callback->udata = p_udata;
+PhysicsDirectBodyState3DSW *Body3DSW::get_direct_state() {
+ if (!direct_state) {
+ direct_state = memnew(PhysicsDirectBodyState3DSW);
+ direct_state->body = this;
}
+ return direct_state;
}
Body3DSW::Body3DSW() :
CollisionObject3DSW(TYPE_BODY),
-
active_list(this),
- inertia_update_list(this),
+ mass_properties_update_list(this),
direct_state_query_list(this) {
- mode = PhysicsServer3D::BODY_MODE_DYNAMIC;
- active = true;
-
- mass = 1;
- _inv_mass = 1;
- bounce = 0;
- friction = 1;
- omit_force_integration = false;
- //applied_torque=0;
- island_step = 0;
- first_time_kinematic = false;
- first_integration = false;
_set_static(false);
-
- contact_count = 0;
- gravity_scale = 1.0;
- linear_damp = -1;
- angular_damp = -1;
- area_angular_damp = 0;
- area_linear_damp = 0;
-
- still_time = 0;
- continuous_cd = false;
- can_sleep = true;
- fi_callback = nullptr;
}
Body3DSW::~Body3DSW() {
- if (fi_callback) {
- memdelete(fi_callback);
+ if (fi_callback_data) {
+ memdelete(fi_callback_data);
+ }
+ if (direct_state) {
+ memdelete(direct_state);
}
-}
-
-PhysicsDirectBodyState3DSW *PhysicsDirectBodyState3DSW::singleton = nullptr;
-
-PhysicsDirectSpaceState3D *PhysicsDirectBodyState3DSW::get_space_state() {
- return body->get_space()->get_direct_state();
}
diff --git a/servers/physics_3d/body_3d_sw.h b/servers/physics_3d/body_3d_sw.h
index efb114a325..fc47040389 100644
--- a/servers/physics_3d/body_3d_sw.h
+++ b/servers/physics_3d/body_3d_sw.h
@@ -28,34 +28,39 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef BODY_SW_H
-#define BODY_SW_H
+#ifndef BODY_3D_SW_H
+#define BODY_3D_SW_H
#include "area_3d_sw.h"
#include "collision_object_3d_sw.h"
#include "core/templates/vset.h"
class Constraint3DSW;
+class PhysicsDirectBodyState3DSW;
class Body3DSW : public CollisionObject3DSW {
- PhysicsServer3D::BodyMode mode;
+ PhysicsServer3D::BodyMode mode = PhysicsServer3D::BODY_MODE_DYNAMIC;
Vector3 linear_velocity;
Vector3 angular_velocity;
+ Vector3 constant_linear_velocity;
+ Vector3 constant_angular_velocity;
+
Vector3 biased_linear_velocity;
Vector3 biased_angular_velocity;
- real_t mass;
- real_t bounce;
- real_t friction;
+ real_t mass = 1.0;
+ real_t bounce = 0.0;
+ real_t friction = 1.0;
+ Vector3 inertia;
- real_t linear_damp;
- real_t angular_damp;
- real_t gravity_scale;
+ real_t linear_damp = -1.0;
+ real_t angular_damp = -1.0;
+ real_t gravity_scale = 1.0;
uint16_t locked_axis = 0;
- real_t _inv_mass;
+ real_t _inv_mass = 1.0;
Vector3 _inv_inertia; // Relative to the principal axes of inertia
// Relative to the local frame of reference
@@ -67,30 +72,32 @@ class Body3DSW : public CollisionObject3DSW {
Basis principal_inertia_axes;
Vector3 center_of_mass;
+ bool calculate_inertia = true;
+ bool calculate_center_of_mass = true;
+
Vector3 gravity;
- real_t still_time;
+ real_t still_time = 0.0;
Vector3 applied_force;
Vector3 applied_torque;
- real_t area_angular_damp;
- real_t area_linear_damp;
+ real_t area_angular_damp = 0.0;
+ real_t area_linear_damp = 0.0;
SelfList<Body3DSW> active_list;
- SelfList<Body3DSW> inertia_update_list;
+ SelfList<Body3DSW> mass_properties_update_list;
SelfList<Body3DSW> direct_state_query_list;
VSet<RID> exceptions;
- bool omit_force_integration;
- bool active;
+ bool omit_force_integration = false;
+ bool active = true;
- bool first_integration;
+ bool continuous_cd = false;
+ bool can_sleep = true;
+ bool first_time_kinematic = false;
- bool continuous_cd;
- bool can_sleep;
- bool first_time_kinematic;
- void _update_inertia();
+ void _mass_properties_changed();
virtual void _shapes_changed();
Transform3D new_transform;
@@ -101,36 +108,44 @@ class Body3DSW : public CollisionObject3DSW {
struct Contact {
Vector3 local_pos;
Vector3 local_normal;
- real_t depth;
- int local_shape;
+ real_t depth = 0.0;
+ int local_shape = 0;
Vector3 collider_pos;
- int collider_shape;
+ int collider_shape = 0;
ObjectID collider_instance_id;
RID collider;
Vector3 collider_velocity_at_pos;
};
Vector<Contact> contacts; //no contacts by default
- int contact_count;
+ int contact_count = 0;
+
+ void *body_state_callback_instance = nullptr;
+ PhysicsServer3D::BodyStateCallback body_state_callback = nullptr;
- struct ForceIntegrationCallback {
+ struct ForceIntegrationCallbackData {
Callable callable;
Variant udata;
};
- ForceIntegrationCallback *fi_callback;
+ ForceIntegrationCallbackData *fi_callback_data = nullptr;
- uint64_t island_step;
+ PhysicsDirectBodyState3DSW *direct_state = nullptr;
- _FORCE_INLINE_ void _compute_area_gravity_and_dampenings(const Area3DSW *p_area);
+ uint64_t island_step = 0;
+
+ _FORCE_INLINE_ void _compute_area_gravity_and_damping(const Area3DSW *p_area);
_FORCE_INLINE_ void _update_transform_dependant();
friend class PhysicsDirectBodyState3DSW; // i give up, too many functions to expose
public:
+ void set_state_sync_callback(void *p_instance, PhysicsServer3D::BodyStateCallback p_callback);
void set_force_integration_callback(const Callable &p_callable, const Variant &p_udata = Variant());
+ PhysicsDirectBodyState3DSW *get_direct_state();
+
_FORCE_INLINE_ void add_area(Area3DSW *p_area) {
int index = areas.find(AreaCMP(p_area));
if (index > -1) {
@@ -242,8 +257,8 @@ public:
set_active(true);
}
- void set_param(PhysicsServer3D::BodyParameter p_param, real_t);
- real_t get_param(PhysicsServer3D::BodyParameter p_param) const;
+ void set_param(PhysicsServer3D::BodyParameter p_param, const Variant &p_value);
+ Variant get_param(PhysicsServer3D::BodyParameter p_param) const;
void set_mode(PhysicsServer3D::BodyMode p_mode);
PhysicsServer3D::BodyMode get_mode() const;
@@ -262,7 +277,8 @@ public:
void set_space(Space3DSW *p_space);
- void update_inertias();
+ void update_mass_properties();
+ void reset_mass_properties();
_FORCE_INLINE_ real_t get_inv_mass() const { return _inv_mass; }
_FORCE_INLINE_ const Vector3 &get_inv_inertia() const { return _inv_inertia; }
@@ -349,96 +365,4 @@ void Body3DSW::add_contact(const Vector3 &p_local_pos, const Vector3 &p_local_no
c[idx].collider_velocity_at_pos = p_collider_velocity_at_pos;
}
-class PhysicsDirectBodyState3DSW : public PhysicsDirectBodyState3D {
- GDCLASS(PhysicsDirectBodyState3DSW, PhysicsDirectBodyState3D);
-
-public:
- static PhysicsDirectBodyState3DSW *singleton;
- Body3DSW *body;
- real_t step;
-
- virtual Vector3 get_total_gravity() const override { return body->gravity; } // get gravity vector working on this body space/area
- virtual real_t get_total_angular_damp() const override { return body->area_angular_damp; } // get density of this body space/area
- virtual real_t get_total_linear_damp() const override { return body->area_linear_damp; } // get density of this body space/area
-
- virtual Vector3 get_center_of_mass() const override { return body->get_center_of_mass(); }
- virtual Basis get_principal_inertia_axes() const override { return body->get_principal_inertia_axes(); }
-
- virtual real_t get_inverse_mass() const override { return body->get_inv_mass(); } // get the mass
- virtual Vector3 get_inverse_inertia() const override { return body->get_inv_inertia(); } // get density of this body space
- virtual Basis get_inverse_inertia_tensor() const override { return body->get_inv_inertia_tensor(); } // get density of this body space
-
- virtual void set_linear_velocity(const Vector3 &p_velocity) override { body->set_linear_velocity(p_velocity); }
- virtual Vector3 get_linear_velocity() const override { return body->get_linear_velocity(); }
-
- virtual void set_angular_velocity(const Vector3 &p_velocity) override { body->set_angular_velocity(p_velocity); }
- virtual Vector3 get_angular_velocity() const override { return body->get_angular_velocity(); }
-
- virtual void set_transform(const Transform3D &p_transform) override { body->set_state(PhysicsServer3D::BODY_STATE_TRANSFORM, p_transform); }
- virtual Transform3D get_transform() const override { return body->get_transform(); }
-
- virtual Vector3 get_velocity_at_local_position(const Vector3 &p_position) const override { return body->get_velocity_in_local_point(p_position); }
-
- virtual void add_central_force(const Vector3 &p_force) override { body->add_central_force(p_force); }
- virtual void add_force(const Vector3 &p_force, const Vector3 &p_position = Vector3()) override {
- body->add_force(p_force, p_position);
- }
- virtual void add_torque(const Vector3 &p_torque) override { body->add_torque(p_torque); }
- virtual void apply_central_impulse(const Vector3 &p_impulse) override { body->apply_central_impulse(p_impulse); }
- virtual void apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position = Vector3()) override {
- body->apply_impulse(p_impulse, p_position);
- }
- virtual void apply_torque_impulse(const Vector3 &p_impulse) override { body->apply_torque_impulse(p_impulse); }
-
- virtual void set_sleep_state(bool p_sleep) override { body->set_active(!p_sleep); }
- virtual bool is_sleeping() const override { return !body->is_active(); }
-
- virtual int get_contact_count() const override { return body->contact_count; }
-
- virtual Vector3 get_contact_local_position(int p_contact_idx) const override {
- ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector3());
- return body->contacts[p_contact_idx].local_pos;
- }
- virtual Vector3 get_contact_local_normal(int p_contact_idx) const override {
- ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector3());
- return body->contacts[p_contact_idx].local_normal;
- }
- virtual real_t get_contact_impulse(int p_contact_idx) const override {
- return 0.0f; // Only implemented for bullet
- }
- virtual int get_contact_local_shape(int p_contact_idx) const override {
- ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, -1);
- return body->contacts[p_contact_idx].local_shape;
- }
-
- virtual RID get_contact_collider(int p_contact_idx) const override {
- ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, RID());
- return body->contacts[p_contact_idx].collider;
- }
- virtual Vector3 get_contact_collider_position(int p_contact_idx) const override {
- ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector3());
- return body->contacts[p_contact_idx].collider_pos;
- }
- virtual ObjectID get_contact_collider_id(int p_contact_idx) const override {
- ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, ObjectID());
- return body->contacts[p_contact_idx].collider_instance_id;
- }
- virtual int get_contact_collider_shape(int p_contact_idx) const override {
- ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, 0);
- return body->contacts[p_contact_idx].collider_shape;
- }
- virtual Vector3 get_contact_collider_velocity_at_position(int p_contact_idx) const override {
- ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector3());
- return body->contacts[p_contact_idx].collider_velocity_at_pos;
- }
-
- virtual PhysicsDirectSpaceState3D *get_space_state() override;
-
- virtual real_t get_step() const override { return step; }
- PhysicsDirectBodyState3DSW() {
- singleton = this;
- body = nullptr;
- }
-};
-
-#endif // BODY__SW_H
+#endif // BODY_3D_SW_H
diff --git a/servers/physics_3d/body_direct_state_3d_sw.cpp b/servers/physics_3d/body_direct_state_3d_sw.cpp
new file mode 100644
index 0000000000..d61a6ac8e4
--- /dev/null
+++ b/servers/physics_3d/body_direct_state_3d_sw.cpp
@@ -0,0 +1,190 @@
+/*************************************************************************/
+/* body_direct_state_3d_sw.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 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 "body_direct_state_3d_sw.h"
+
+#include "body_3d_sw.h"
+#include "space_3d_sw.h"
+
+Vector3 PhysicsDirectBodyState3DSW::get_total_gravity() const {
+ return body->gravity;
+}
+
+real_t PhysicsDirectBodyState3DSW::get_total_angular_damp() const {
+ return body->area_angular_damp;
+}
+
+real_t PhysicsDirectBodyState3DSW::get_total_linear_damp() const {
+ return body->area_linear_damp;
+}
+
+Vector3 PhysicsDirectBodyState3DSW::get_center_of_mass() const {
+ return body->get_center_of_mass();
+}
+
+Basis PhysicsDirectBodyState3DSW::get_principal_inertia_axes() const {
+ return body->get_principal_inertia_axes();
+}
+
+real_t PhysicsDirectBodyState3DSW::get_inverse_mass() const {
+ return body->get_inv_mass();
+}
+
+Vector3 PhysicsDirectBodyState3DSW::get_inverse_inertia() const {
+ return body->get_inv_inertia();
+}
+
+Basis PhysicsDirectBodyState3DSW::get_inverse_inertia_tensor() const {
+ return body->get_inv_inertia_tensor();
+}
+
+void PhysicsDirectBodyState3DSW::set_linear_velocity(const Vector3 &p_velocity) {
+ body->wakeup();
+ body->set_linear_velocity(p_velocity);
+}
+
+Vector3 PhysicsDirectBodyState3DSW::get_linear_velocity() const {
+ return body->get_linear_velocity();
+}
+
+void PhysicsDirectBodyState3DSW::set_angular_velocity(const Vector3 &p_velocity) {
+ body->wakeup();
+ body->set_angular_velocity(p_velocity);
+}
+
+Vector3 PhysicsDirectBodyState3DSW::get_angular_velocity() const {
+ return body->get_angular_velocity();
+}
+
+void PhysicsDirectBodyState3DSW::set_transform(const Transform3D &p_transform) {
+ body->set_state(PhysicsServer3D::BODY_STATE_TRANSFORM, p_transform);
+}
+
+Transform3D PhysicsDirectBodyState3DSW::get_transform() const {
+ return body->get_transform();
+}
+
+Vector3 PhysicsDirectBodyState3DSW::get_velocity_at_local_position(const Vector3 &p_position) const {
+ return body->get_velocity_in_local_point(p_position);
+}
+
+void PhysicsDirectBodyState3DSW::add_central_force(const Vector3 &p_force) {
+ body->wakeup();
+ body->add_central_force(p_force);
+}
+
+void PhysicsDirectBodyState3DSW::add_force(const Vector3 &p_force, const Vector3 &p_position) {
+ body->wakeup();
+ body->add_force(p_force, p_position);
+}
+
+void PhysicsDirectBodyState3DSW::add_torque(const Vector3 &p_torque) {
+ body->wakeup();
+ body->add_torque(p_torque);
+}
+
+void PhysicsDirectBodyState3DSW::apply_central_impulse(const Vector3 &p_impulse) {
+ body->wakeup();
+ body->apply_central_impulse(p_impulse);
+}
+
+void PhysicsDirectBodyState3DSW::apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position) {
+ body->wakeup();
+ body->apply_impulse(p_impulse, p_position);
+}
+
+void PhysicsDirectBodyState3DSW::apply_torque_impulse(const Vector3 &p_impulse) {
+ body->wakeup();
+ body->apply_torque_impulse(p_impulse);
+}
+
+void PhysicsDirectBodyState3DSW::set_sleep_state(bool p_sleep) {
+ body->set_active(!p_sleep);
+}
+
+bool PhysicsDirectBodyState3DSW::is_sleeping() const {
+ return !body->is_active();
+}
+
+int PhysicsDirectBodyState3DSW::get_contact_count() const {
+ return body->contact_count;
+}
+
+Vector3 PhysicsDirectBodyState3DSW::get_contact_local_position(int p_contact_idx) const {
+ ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector3());
+ return body->contacts[p_contact_idx].local_pos;
+}
+
+Vector3 PhysicsDirectBodyState3DSW::get_contact_local_normal(int p_contact_idx) const {
+ ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector3());
+ return body->contacts[p_contact_idx].local_normal;
+}
+
+real_t PhysicsDirectBodyState3DSW::get_contact_impulse(int p_contact_idx) const {
+ return 0.0f; // Only implemented for bullet
+}
+
+int PhysicsDirectBodyState3DSW::get_contact_local_shape(int p_contact_idx) const {
+ ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, -1);
+ return body->contacts[p_contact_idx].local_shape;
+}
+
+RID PhysicsDirectBodyState3DSW::get_contact_collider(int p_contact_idx) const {
+ ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, RID());
+ return body->contacts[p_contact_idx].collider;
+}
+
+Vector3 PhysicsDirectBodyState3DSW::get_contact_collider_position(int p_contact_idx) const {
+ ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector3());
+ return body->contacts[p_contact_idx].collider_pos;
+}
+
+ObjectID PhysicsDirectBodyState3DSW::get_contact_collider_id(int p_contact_idx) const {
+ ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, ObjectID());
+ return body->contacts[p_contact_idx].collider_instance_id;
+}
+
+int PhysicsDirectBodyState3DSW::get_contact_collider_shape(int p_contact_idx) const {
+ ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, 0);
+ return body->contacts[p_contact_idx].collider_shape;
+}
+
+Vector3 PhysicsDirectBodyState3DSW::get_contact_collider_velocity_at_position(int p_contact_idx) const {
+ ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector3());
+ return body->contacts[p_contact_idx].collider_velocity_at_pos;
+}
+
+PhysicsDirectSpaceState3D *PhysicsDirectBodyState3DSW::get_space_state() {
+ return body->get_space()->get_direct_state();
+}
+
+real_t PhysicsDirectBodyState3DSW::get_step() const {
+ return body->get_space()->get_last_step();
+}
diff --git a/servers/physics_3d/body_direct_state_3d_sw.h b/servers/physics_3d/body_direct_state_3d_sw.h
new file mode 100644
index 0000000000..5132376715
--- /dev/null
+++ b/servers/physics_3d/body_direct_state_3d_sw.h
@@ -0,0 +1,94 @@
+/*************************************************************************/
+/* body_direct_state_3d_sw.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 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 BODY_DIRECT_STATE_3D_SW_H
+#define BODY_DIRECT_STATE_3D_SW_H
+
+#include "servers/physics_server_3d.h"
+
+class Body3DSW;
+
+class PhysicsDirectBodyState3DSW : public PhysicsDirectBodyState3D {
+ GDCLASS(PhysicsDirectBodyState3DSW, PhysicsDirectBodyState3D);
+
+public:
+ Body3DSW *body = nullptr;
+
+ virtual Vector3 get_total_gravity() const override;
+ virtual real_t get_total_angular_damp() const override;
+ virtual real_t get_total_linear_damp() const override;
+
+ virtual Vector3 get_center_of_mass() const override;
+ virtual Basis get_principal_inertia_axes() const override;
+
+ virtual real_t get_inverse_mass() const override;
+ virtual Vector3 get_inverse_inertia() const override;
+ virtual Basis get_inverse_inertia_tensor() const override;
+
+ virtual void set_linear_velocity(const Vector3 &p_velocity) override;
+ virtual Vector3 get_linear_velocity() const override;
+
+ virtual void set_angular_velocity(const Vector3 &p_velocity) override;
+ virtual Vector3 get_angular_velocity() const override;
+
+ virtual void set_transform(const Transform3D &p_transform) override;
+ virtual Transform3D get_transform() const override;
+
+ virtual Vector3 get_velocity_at_local_position(const Vector3 &p_position) const override;
+
+ virtual void add_central_force(const Vector3 &p_force) override;
+ virtual void add_force(const Vector3 &p_force, const Vector3 &p_position = Vector3()) override;
+ virtual void add_torque(const Vector3 &p_torque) override;
+ virtual void apply_central_impulse(const Vector3 &p_impulse) override;
+ virtual void apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position = Vector3()) override;
+ virtual void apply_torque_impulse(const Vector3 &p_impulse) override;
+
+ virtual void set_sleep_state(bool p_sleep) override;
+ virtual bool is_sleeping() const override;
+
+ virtual int get_contact_count() const override;
+
+ virtual Vector3 get_contact_local_position(int p_contact_idx) const override;
+ virtual Vector3 get_contact_local_normal(int p_contact_idx) const override;
+ virtual real_t get_contact_impulse(int p_contact_idx) const override;
+ virtual int get_contact_local_shape(int p_contact_idx) const override;
+
+ virtual RID get_contact_collider(int p_contact_idx) const override;
+ virtual Vector3 get_contact_collider_position(int p_contact_idx) const override;
+ virtual ObjectID get_contact_collider_id(int p_contact_idx) const override;
+ virtual int get_contact_collider_shape(int p_contact_idx) const override;
+ virtual Vector3 get_contact_collider_velocity_at_position(int p_contact_idx) const override;
+
+ virtual PhysicsDirectSpaceState3D *get_space_state() override;
+
+ virtual real_t get_step() const override;
+};
+
+#endif // BODY_DIRECT_STATE_3D_SW_H
diff --git a/servers/physics_3d/body_pair_3d_sw.h b/servers/physics_3d/body_pair_3d_sw.h
index 19d6a46880..01afb07e13 100644
--- a/servers/physics_3d/body_pair_3d_sw.h
+++ b/servers/physics_3d/body_pair_3d_sw.h
@@ -41,18 +41,18 @@ protected:
struct Contact {
Vector3 position;
Vector3 normal;
- int index_A, index_B;
+ int index_A = 0, index_B = 0;
Vector3 local_A, local_B;
- real_t acc_normal_impulse; // accumulated normal impulse (Pn)
+ real_t acc_normal_impulse = 0.0; // accumulated normal impulse (Pn)
Vector3 acc_tangent_impulse; // accumulated tangent impulse (Pt)
- real_t acc_bias_impulse; // accumulated normal impulse for position bias (Pnb)
- real_t acc_bias_impulse_center_of_mass; // accumulated normal impulse for position bias applied to com
- real_t mass_normal;
- real_t bias;
- real_t bounce;
-
- real_t depth;
- bool active;
+ real_t acc_bias_impulse = 0.0; // accumulated normal impulse for position bias (Pnb)
+ real_t acc_bias_impulse_center_of_mass = 0.0; // accumulated normal impulse for position bias applied to com
+ real_t mass_normal = 0.0;
+ real_t bias = 0.0;
+ real_t bounce = 0.0;
+
+ real_t depth = 0.0;
+ bool active = false;
Vector3 rA, rB; // Offset in world orientation with respect to center of mass
};
diff --git a/servers/physics_3d/broad_phase_3d_bvh.cpp b/servers/physics_3d/broad_phase_3d_bvh.cpp
index f9f64f786d..d89e0e1f6d 100644
--- a/servers/physics_3d/broad_phase_3d_bvh.cpp
+++ b/servers/physics_3d/broad_phase_3d_bvh.cpp
@@ -114,7 +114,4 @@ BroadPhase3DSW *BroadPhase3DBVH::_create() {
BroadPhase3DBVH::BroadPhase3DBVH() {
bvh.set_pair_callback(_pair_callback, this);
bvh.set_unpair_callback(_unpair_callback, this);
- pair_callback = nullptr;
- pair_userdata = nullptr;
- unpair_userdata = nullptr;
}
diff --git a/servers/physics_3d/broad_phase_3d_bvh.h b/servers/physics_3d/broad_phase_3d_bvh.h
index 30b8b7f2aa..03131c9db2 100644
--- a/servers/physics_3d/broad_phase_3d_bvh.h
+++ b/servers/physics_3d/broad_phase_3d_bvh.h
@@ -40,10 +40,10 @@ class BroadPhase3DBVH : public BroadPhase3DSW {
static void *_pair_callback(void *, uint32_t, CollisionObject3DSW *, int, uint32_t, CollisionObject3DSW *, int);
static void _unpair_callback(void *, uint32_t, CollisionObject3DSW *, int, uint32_t, CollisionObject3DSW *, int, void *);
- PairCallback pair_callback;
- void *pair_userdata;
- UnpairCallback unpair_callback;
- void *unpair_userdata;
+ PairCallback pair_callback = nullptr;
+ void *pair_userdata = nullptr;
+ UnpairCallback unpair_callback = nullptr;
+ void *unpair_userdata = nullptr;
public:
// 0 is an invalid ID
diff --git a/servers/physics_3d/collision_object_3d_sw.cpp b/servers/physics_3d/collision_object_3d_sw.cpp
index 24c7d7b85c..098f627d11 100644
--- a/servers/physics_3d/collision_object_3d_sw.cpp
+++ b/servers/physics_3d/collision_object_3d_sw.cpp
@@ -236,11 +236,5 @@ void CollisionObject3DSW::_shape_changed() {
CollisionObject3DSW::CollisionObject3DSW(Type p_type) :
pending_shape_update_list(this) {
- _static = true;
type = p_type;
- space = nullptr;
-
- collision_layer = 1;
- collision_mask = 1;
- ray_pickable = true;
}
diff --git a/servers/physics_3d/collision_object_3d_sw.h b/servers/physics_3d/collision_object_3d_sw.h
index 6ffab54645..3aa48946b7 100644
--- a/servers/physics_3d/collision_object_3d_sw.h
+++ b/servers/physics_3d/collision_object_3d_sw.h
@@ -56,26 +56,24 @@ private:
Type type;
RID self;
ObjectID instance_id;
- uint32_t collision_layer;
- uint32_t collision_mask;
+ uint32_t collision_layer = 1;
+ uint32_t collision_mask = 1;
struct Shape {
Transform3D xform;
Transform3D xform_inv;
BroadPhase3DSW::ID bpid;
AABB aabb_cache; //for rayqueries
- real_t area_cache;
- Shape3DSW *shape;
- bool disabled;
-
- Shape() { disabled = false; }
+ real_t area_cache = 0.0;
+ Shape3DSW *shape = nullptr;
+ bool disabled = false;
};
Vector<Shape> shapes;
- Space3DSW *space;
+ Space3DSW *space = nullptr;
Transform3D transform;
Transform3D inv_transform;
- bool _static;
+ bool _static = true;
SelfList<CollisionObject3DSW> pending_shape_update_list;
@@ -102,7 +100,7 @@ protected:
virtual void _shapes_changed() = 0;
void _set_space(Space3DSW *p_space);
- bool ray_pickable;
+ bool ray_pickable = true;
CollisionObject3DSW(Type p_type);
diff --git a/servers/physics_3d/collision_solver_3d_sat.cpp b/servers/physics_3d/collision_solver_3d_sat.cpp
index 6e6a2cb9e7..86150f41a0 100644
--- a/servers/physics_3d/collision_solver_3d_sat.cpp
+++ b/servers/physics_3d/collision_solver_3d_sat.cpp
@@ -66,11 +66,11 @@
struct _CollectorCallback {
CollisionSolver3DSW::CallbackResult callback;
- void *userdata;
- bool swap;
- bool collided;
+ void *userdata = nullptr;
+ bool swap = false;
+ bool collided = false;
Vector3 normal;
- Vector3 *prev_axis;
+ Vector3 *prev_axis = nullptr;
_FORCE_INLINE_ void call(const Vector3 &p_point_A, const Vector3 &p_point_B) {
if (swap) {
@@ -183,7 +183,7 @@ static void _generate_contacts_edge_circle(const Vector3 *p_points_A, int p_poin
real_t circle_B_radius = circle_B_line_1.length();
Vector3 circle_B_normal = circle_B_line_1.cross(circle_B_line_2).normalized();
- Plane circle_plane(circle_B_pos, circle_B_normal);
+ Plane circle_plane(circle_B_normal, circle_B_pos);
static const int max_clip = 2;
Vector3 contact_points[max_clip];
@@ -299,7 +299,7 @@ static void _generate_contacts_face_face(const Vector3 *p_points_A, int p_point_
Vector3 clip_normal = (edge0_B - edge1_B).cross(plane_B.normal).normalized();
// make a clip plane
- Plane clip(edge0_B, clip_normal);
+ Plane clip(clip_normal, edge0_B);
// avoid double clip if A is edge
int dst_idx = 0;
bool edge = clipbuf_len == 2;
@@ -385,7 +385,7 @@ static void _generate_contacts_face_circle(const Vector3 *p_points_A, int p_poin
// Clip face with circle plane.
Vector3 circle_B_normal = circle_B_line_1.cross(circle_B_line_2).normalized();
- Plane circle_plane(circle_B_pos, circle_B_normal);
+ Plane circle_plane(circle_B_normal, circle_B_pos);
static const int max_clip = 32;
Vector3 contact_points[max_clip];
@@ -522,7 +522,7 @@ static void _generate_contacts_circle_circle(const Vector3 *p_points_A, int p_po
}
}
- Plane circle_B_plane(circle_B_pos, circle_B_normal);
+ Plane circle_B_plane(circle_B_normal, circle_B_pos);
// Generate contact points.
for (int i = 0; i < num_points; i++) {
@@ -606,15 +606,15 @@ static void _generate_contacts_from_supports(const Vector3 *p_points_A, int p_po
template <class ShapeA, class ShapeB, bool withMargin = false>
class SeparatorAxisTest {
- const ShapeA *shape_A;
- const ShapeB *shape_B;
- const Transform3D *transform_A;
- const Transform3D *transform_B;
- real_t best_depth;
+ const ShapeA *shape_A = nullptr;
+ const ShapeB *shape_B = nullptr;
+ const Transform3D *transform_A = nullptr;
+ const Transform3D *transform_B = nullptr;
+ real_t best_depth = 1e15;
Vector3 best_axis;
- _CollectorCallback *callback;
- real_t margin_A;
- real_t margin_B;
+ _CollectorCallback *callback = nullptr;
+ real_t margin_A = 0.0;
+ real_t margin_B = 0.0;
Vector3 separator_axis;
public:
@@ -749,7 +749,6 @@ public:
}
_FORCE_INLINE_ SeparatorAxisTest(const ShapeA *p_shape_A, const Transform3D &p_transform_A, const ShapeB *p_shape_B, const Transform3D &p_transform_B, _CollectorCallback *p_callback, real_t p_margin_A = 0, real_t p_margin_B = 0) {
- best_depth = 1e15;
shape_A = p_shape_A;
shape_B = p_shape_B;
transform_A = &p_transform_A;
@@ -1195,7 +1194,7 @@ static void _collision_box_capsule(const Shape3DSW *p_a, const Transform3D &p_tr
}
//Vector3 axis = (point - cyl_axis * cyl_axis.dot(point)).normalized();
- Vector3 axis = Plane(cyl_axis, 0).project(point).normalized();
+ Vector3 axis = Plane(cyl_axis).project(point).normalized();
if (!separator.test_axis(axis)) {
return;
@@ -1304,7 +1303,7 @@ static void _collision_box_cylinder(const Shape3DSW *p_a, const Transform3D &p_t
// Points of A, cylinder lateral surface.
for (int i = 0; i < 8; i++) {
const Vector3 &point = vertices_A[i];
- Vector3 axis = Plane(cyl_axis, 0).project(point).normalized();
+ Vector3 axis = Plane(cyl_axis).project(point).normalized();
if (!separator.test_axis(axis)) {
return;
@@ -1986,7 +1985,7 @@ static void _collision_cylinder_face(const Shape3DSW *p_a, const Transform3D &p_
// Points of B, cylinder lateral surface.
for (int i = 0; i < 3; i++) {
const Vector3 &point = vertex[i];
- Vector3 axis = Plane(cyl_axis, 0).project(point).normalized();
+ Vector3 axis = Plane(cyl_axis).project(point).normalized();
if (axis.dot(normal) < 0.0) {
axis *= -1.0;
}
@@ -2272,12 +2271,14 @@ static void _collision_convex_polygon_face(const Shape3DSW *p_a, const Transform
bool sat_calculate_penetration(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CollisionSolver3DSW::CallbackResult p_result_callback, void *p_userdata, bool p_swap, Vector3 *r_prev_axis, real_t p_margin_a, real_t p_margin_b) {
PhysicsServer3D::ShapeType type_A = p_shape_A->get_type();
- ERR_FAIL_COND_V(type_A == PhysicsServer3D::SHAPE_PLANE, false);
+ ERR_FAIL_COND_V(type_A == PhysicsServer3D::SHAPE_WORLD_BOUNDARY, false);
+ ERR_FAIL_COND_V(type_A == PhysicsServer3D::SHAPE_SEPARATION_RAY, false);
ERR_FAIL_COND_V(p_shape_A->is_concave(), false);
PhysicsServer3D::ShapeType type_B = p_shape_B->get_type();
- ERR_FAIL_COND_V(type_B == PhysicsServer3D::SHAPE_PLANE, false);
+ ERR_FAIL_COND_V(type_B == PhysicsServer3D::SHAPE_WORLD_BOUNDARY, false);
+ ERR_FAIL_COND_V(type_B == PhysicsServer3D::SHAPE_SEPARATION_RAY, false);
ERR_FAIL_COND_V(p_shape_B->is_concave(), false);
static const CollisionFunc collision_table[6][6] = {
@@ -2382,10 +2383,10 @@ bool sat_calculate_penetration(const Shape3DSW *p_shape_A, const Transform3D &p_
CollisionFunc collision_func;
if (margin_A != 0.0 || margin_B != 0.0) {
- collision_func = collision_table_margin[type_A - 1][type_B - 1];
+ collision_func = collision_table_margin[type_A - 2][type_B - 2];
} else {
- collision_func = collision_table[type_A - 1][type_B - 1];
+ collision_func = collision_table[type_A - 2][type_B - 2];
}
ERR_FAIL_COND_V(!collision_func, false);
diff --git a/servers/physics_3d/collision_solver_3d_sw.cpp b/servers/physics_3d/collision_solver_3d_sw.cpp
index dcecac1c73..96f1936668 100644
--- a/servers/physics_3d/collision_solver_3d_sw.cpp
+++ b/servers/physics_3d/collision_solver_3d_sw.cpp
@@ -37,12 +37,12 @@
#define collision_solver sat_calculate_penetration
//#define collision_solver gjk_epa_calculate_penetration
-bool CollisionSolver3DSW::solve_static_plane(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result) {
- const PlaneShape3DSW *plane = static_cast<const PlaneShape3DSW *>(p_shape_A);
- if (p_shape_B->get_type() == PhysicsServer3D::SHAPE_PLANE) {
+bool CollisionSolver3DSW::solve_static_world_boundary(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result) {
+ const WorldBoundaryShape3DSW *world_boundary = static_cast<const WorldBoundaryShape3DSW *>(p_shape_A);
+ if (p_shape_B->get_type() == PhysicsServer3D::SHAPE_WORLD_BOUNDARY) {
return false;
}
- Plane p = p_transform_A.xform(plane->get_plane());
+ Plane p = p_transform_A.xform(world_boundary->get_plane());
static const int max_supports = 16;
Vector3 supports[max_supports];
@@ -89,6 +89,49 @@ bool CollisionSolver3DSW::solve_static_plane(const Shape3DSW *p_shape_A, const T
return found;
}
+bool CollisionSolver3DSW::solve_separation_ray(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin) {
+ const SeparationRayShape3DSW *ray = static_cast<const SeparationRayShape3DSW *>(p_shape_A);
+
+ Vector3 from = p_transform_A.origin;
+ Vector3 to = from + p_transform_A.basis.get_axis(2) * (ray->get_length() + p_margin);
+ Vector3 support_A = to;
+
+ Transform3D ai = p_transform_B.affine_inverse();
+
+ from = ai.xform(from);
+ to = ai.xform(to);
+
+ Vector3 p, n;
+ if (!p_shape_B->intersect_segment(from, to, p, n)) {
+ return false;
+ }
+
+ // Discard contacts when the ray is fully contained inside the shape.
+ if (n == Vector3()) {
+ return false;
+ }
+
+ // Discard contacts in the wrong direction.
+ if (n.dot(from - to) < CMP_EPSILON) {
+ return false;
+ }
+
+ Vector3 support_B = p_transform_B.xform(p);
+ if (ray->get_slide_on_slope()) {
+ Vector3 global_n = ai.basis.xform_inv(n).normalized();
+ support_B = support_A + (support_B - support_A).length() * global_n;
+ }
+
+ if (p_result_callback) {
+ if (p_swap_result) {
+ p_result_callback(support_B, 0, support_A, 0, p_userdata);
+ } else {
+ p_result_callback(support_A, 0, support_B, 0, p_userdata);
+ }
+ }
+ return true;
+}
+
struct _SoftBodyContactCollisionInfo {
int node_index = 0;
CollisionSolver3DSW::CallbackResult result_callback = nullptr;
@@ -135,17 +178,17 @@ bool CollisionSolver3DSW::soft_body_query_callback(uint32_t p_node_index, void *
transform_B.origin = query_cinfo.node_transform.xform(node_position);
query_cinfo.contact_info.node_index = p_node_index;
- solve_static(query_cinfo.shape_A, query_cinfo.transform_A, query_cinfo.shape_B, transform_B, soft_body_contact_callback, &query_cinfo.contact_info);
+ bool collided = solve_static(query_cinfo.shape_A, query_cinfo.transform_A, query_cinfo.shape_B, transform_B, soft_body_contact_callback, &query_cinfo.contact_info);
#ifdef DEBUG_ENABLED
++query_cinfo.node_query_count;
#endif
- // Continue with the query.
- return false;
+ // Stop at first collision if contacts are not needed.
+ return (collided && !query_cinfo.contact_info.result_callback);
}
-void CollisionSolver3DSW::soft_body_concave_callback(void *p_userdata, Shape3DSW *p_convex) {
+bool CollisionSolver3DSW::soft_body_concave_callback(void *p_userdata, Shape3DSW *p_convex) {
_SoftBodyQueryInfo &query_cinfo = *(_SoftBodyQueryInfo *)(p_userdata);
query_cinfo.shape_A = p_convex;
@@ -167,9 +210,14 @@ void CollisionSolver3DSW::soft_body_concave_callback(void *p_userdata, Shape3DSW
query_cinfo.soft_body->query_aabb(shape_aabb, soft_body_query_callback, &query_cinfo);
+ bool collided = (query_cinfo.contact_info.contact_count > 0);
+
#ifdef DEBUG_ENABLED
++query_cinfo.convex_query_count;
#endif
+
+ // Stop at first collision if contacts are not needed.
+ return (collided && !query_cinfo.contact_info.result_callback);
}
bool CollisionSolver3DSW::solve_soft_body(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result) {
@@ -243,17 +291,20 @@ struct _ConcaveCollisionInfo {
Vector3 close_A, close_B;
};
-void CollisionSolver3DSW::concave_callback(void *p_userdata, Shape3DSW *p_convex) {
+bool CollisionSolver3DSW::concave_callback(void *p_userdata, Shape3DSW *p_convex) {
_ConcaveCollisionInfo &cinfo = *(_ConcaveCollisionInfo *)(p_userdata);
cinfo.aabb_tests++;
bool collided = collision_solver(cinfo.shape_A, *cinfo.transform_A, p_convex, *cinfo.transform_B, cinfo.result_callback, cinfo.userdata, cinfo.swap_result, nullptr, cinfo.margin_A, cinfo.margin_B);
if (!collided) {
- return;
+ return false;
}
cinfo.collided = true;
cinfo.collisions++;
+
+ // Stop at first collision if contacts are not needed.
+ return !cinfo.result_callback;
}
bool CollisionSolver3DSW::solve_concave(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin_A, real_t p_margin_B) {
@@ -314,8 +365,11 @@ bool CollisionSolver3DSW::solve_static(const Shape3DSW *p_shape_A, const Transfo
swap = true;
}
- if (type_A == PhysicsServer3D::SHAPE_PLANE) {
- if (type_B == PhysicsServer3D::SHAPE_PLANE) {
+ if (type_A == PhysicsServer3D::SHAPE_WORLD_BOUNDARY) {
+ if (type_B == PhysicsServer3D::SHAPE_WORLD_BOUNDARY) {
+ return false;
+ }
+ if (type_B == PhysicsServer3D::SHAPE_SEPARATION_RAY) {
return false;
}
if (type_B == PhysicsServer3D::SHAPE_SOFT_BODY) {
@@ -323,9 +377,20 @@ bool CollisionSolver3DSW::solve_static(const Shape3DSW *p_shape_A, const Transfo
}
if (swap) {
- return solve_static_plane(p_shape_B, p_transform_B, p_shape_A, p_transform_A, p_result_callback, p_userdata, true);
+ return solve_static_world_boundary(p_shape_B, p_transform_B, p_shape_A, p_transform_A, p_result_callback, p_userdata, true);
+ } else {
+ return solve_static_world_boundary(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false);
+ }
+
+ } else if (type_A == PhysicsServer3D::SHAPE_SEPARATION_RAY) {
+ if (type_B == PhysicsServer3D::SHAPE_SEPARATION_RAY) {
+ return false;
+ }
+
+ if (swap) {
+ return solve_separation_ray(p_shape_B, p_transform_B, p_shape_A, p_transform_A, p_result_callback, p_userdata, true, p_margin_B);
} else {
- return solve_static_plane(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false);
+ return solve_separation_ray(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false, p_margin_A);
}
} else if (type_B == PhysicsServer3D::SHAPE_SOFT_BODY) {
@@ -356,19 +421,18 @@ bool CollisionSolver3DSW::solve_static(const Shape3DSW *p_shape_A, const Transfo
}
}
-void CollisionSolver3DSW::concave_distance_callback(void *p_userdata, Shape3DSW *p_convex) {
+bool CollisionSolver3DSW::concave_distance_callback(void *p_userdata, Shape3DSW *p_convex) {
_ConcaveCollisionInfo &cinfo = *(_ConcaveCollisionInfo *)(p_userdata);
cinfo.aabb_tests++;
- if (cinfo.collided) {
- return;
- }
Vector3 close_A, close_B;
cinfo.collided = !gjk_epa_calculate_distance(cinfo.shape_A, *cinfo.transform_A, p_convex, *cinfo.transform_B, close_A, close_B);
if (cinfo.collided) {
- return;
+ // No need to process any more result.
+ return true;
}
+
if (!cinfo.tested || close_A.distance_squared_to(close_B) < cinfo.close_A.distance_squared_to(cinfo.close_B)) {
cinfo.close_A = close_A;
cinfo.close_B = close_B;
@@ -376,14 +440,15 @@ void CollisionSolver3DSW::concave_distance_callback(void *p_userdata, Shape3DSW
}
cinfo.collisions++;
+ return false;
}
-bool CollisionSolver3DSW::solve_distance_plane(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, Vector3 &r_point_A, Vector3 &r_point_B) {
- const PlaneShape3DSW *plane = static_cast<const PlaneShape3DSW *>(p_shape_A);
- if (p_shape_B->get_type() == PhysicsServer3D::SHAPE_PLANE) {
+bool CollisionSolver3DSW::solve_distance_world_boundary(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, Vector3 &r_point_A, Vector3 &r_point_B) {
+ const WorldBoundaryShape3DSW *world_boundary = static_cast<const WorldBoundaryShape3DSW *>(p_shape_A);
+ if (p_shape_B->get_type() == PhysicsServer3D::SHAPE_WORLD_BOUNDARY) {
return false;
}
- Plane p = p_transform_A.xform(plane->get_plane());
+ Plane p = p_transform_A.xform(world_boundary->get_plane());
static const int max_supports = 16;
Vector3 supports[max_supports];
@@ -435,9 +500,9 @@ bool CollisionSolver3DSW::solve_distance(const Shape3DSW *p_shape_A, const Trans
return false;
}
- if (p_shape_B->get_type() == PhysicsServer3D::SHAPE_PLANE) {
+ if (p_shape_B->get_type() == PhysicsServer3D::SHAPE_WORLD_BOUNDARY) {
Vector3 a, b;
- bool col = solve_distance_plane(p_shape_B, p_transform_B, p_shape_A, p_transform_A, a, b);
+ bool col = solve_distance_world_boundary(p_shape_B, p_transform_B, p_shape_A, p_transform_A, a, b);
r_point_A = b;
r_point_B = a;
return !col;
@@ -482,7 +547,7 @@ bool CollisionSolver3DSW::solve_distance(const Shape3DSW *p_shape_A, const Trans
real_t smin, smax;
if (use_cc_hint) {
- cc_hint_aabb.project_range_in_plane(Plane(axis, 0), smin, smax);
+ cc_hint_aabb.project_range_in_plane(Plane(axis), smin, smax);
} else {
p_shape_A->project_range(axis, rel_transform, smin, smax);
}
diff --git a/servers/physics_3d/collision_solver_3d_sw.h b/servers/physics_3d/collision_solver_3d_sw.h
index a5dd7d48eb..0a9ea7c0eb 100644
--- a/servers/physics_3d/collision_solver_3d_sw.h
+++ b/servers/physics_3d/collision_solver_3d_sw.h
@@ -40,14 +40,14 @@ public:
private:
static bool soft_body_query_callback(uint32_t p_node_index, void *p_userdata);
static void soft_body_contact_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata);
- static void soft_body_concave_callback(void *p_userdata, Shape3DSW *p_convex);
- static void concave_callback(void *p_userdata, Shape3DSW *p_convex);
- static bool solve_static_plane(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result);
- static bool solve_ray(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result);
+ static bool soft_body_concave_callback(void *p_userdata, Shape3DSW *p_convex);
+ static bool concave_callback(void *p_userdata, Shape3DSW *p_convex);
+ static bool solve_static_world_boundary(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result);
+ static bool solve_separation_ray(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin = 0);
static bool solve_soft_body(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result);
static bool solve_concave(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin_A = 0, real_t p_margin_B = 0);
- static void concave_distance_callback(void *p_userdata, Shape3DSW *p_convex);
- static bool solve_distance_plane(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, Vector3 &r_point_A, Vector3 &r_point_B);
+ static bool concave_distance_callback(void *p_userdata, Shape3DSW *p_convex);
+ static bool solve_distance_world_boundary(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, Vector3 &r_point_A, Vector3 &r_point_B);
public:
static bool solve_static(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, Vector3 *r_sep_axis = nullptr, real_t p_margin_A = 0, real_t p_margin_B = 0);
diff --git a/servers/physics_3d/gjk_epa.cpp b/servers/physics_3d/gjk_epa.cpp
index 2df991563d..a1dbdd0a70 100644
--- a/servers/physics_3d/gjk_epa.cpp
+++ b/servers/physics_3d/gjk_epa.cpp
@@ -96,7 +96,7 @@ struct sResults {
Vector3 witnesses[2];
Vector3 normal;
- real_t distance;
+ real_t distance = 0.0;
};
// Shorthands
diff --git a/servers/physics_3d/joints/cone_twist_joint_3d_sw.cpp b/servers/physics_3d/joints/cone_twist_joint_3d_sw.cpp
index 7315e9c709..bb9cc1bf67 100644
--- a/servers/physics_3d/joints/cone_twist_joint_3d_sw.cpp
+++ b/servers/physics_3d/joints/cone_twist_joint_3d_sw.cpp
@@ -92,20 +92,8 @@ ConeTwistJoint3DSW::ConeTwistJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Trans
m_rbAFrame = rbAFrame;
m_rbBFrame = rbBFrame;
- m_swingSpan1 = Math_TAU / 8.0;
- m_swingSpan2 = Math_TAU / 8.0;
- m_twistSpan = Math_TAU;
- m_biasFactor = 0.3f;
- m_relaxationFactor = 1.0f;
-
- m_angularOnly = false;
- m_solveTwistLimit = false;
- m_solveSwingLimit = false;
-
A->add_constraint(this, 0);
B->add_constraint(this, 1);
-
- m_appliedImpulse = 0;
}
bool ConeTwistJoint3DSW::setup(real_t p_timestep) {
diff --git a/servers/physics_3d/joints/cone_twist_joint_3d_sw.h b/servers/physics_3d/joints/cone_twist_joint_3d_sw.h
index 608847352c..bf7e593820 100644
--- a/servers/physics_3d/joints/cone_twist_joint_3d_sw.h
+++ b/servers/physics_3d/joints/cone_twist_joint_3d_sw.h
@@ -67,39 +67,39 @@ public:
Body3DSW *B;
};
- Body3DSW *_arr[2];
+ Body3DSW *_arr[2] = { nullptr, nullptr };
};
- JacobianEntry3DSW m_jac[3]; //3 orthogonal linear constraints
+ JacobianEntry3DSW m_jac[3] = {}; //3 orthogonal linear constraints
- real_t m_appliedImpulse;
+ real_t m_appliedImpulse = 0.0;
Transform3D m_rbAFrame;
Transform3D m_rbBFrame;
- real_t m_limitSoftness;
- real_t m_biasFactor;
- real_t m_relaxationFactor;
+ real_t m_limitSoftness = 0.0;
+ real_t m_biasFactor = 0.3;
+ real_t m_relaxationFactor = 1.0;
- real_t m_swingSpan1;
- real_t m_swingSpan2;
- real_t m_twistSpan;
+ real_t m_swingSpan1 = Math_TAU / 8.0;
+ real_t m_swingSpan2 = 0.0;
+ real_t m_twistSpan = 0.0;
Vector3 m_swingAxis;
Vector3 m_twistAxis;
- real_t m_kSwing;
- real_t m_kTwist;
+ real_t m_kSwing = 0.0;
+ real_t m_kTwist = 0.0;
- real_t m_twistLimitSign;
- real_t m_swingCorrection;
- real_t m_twistCorrection;
+ real_t m_twistLimitSign = 0.0;
+ real_t m_swingCorrection = 0.0;
+ real_t m_twistCorrection = 0.0;
- real_t m_accSwingLimitImpulse;
- real_t m_accTwistLimitImpulse;
+ real_t m_accSwingLimitImpulse = 0.0;
+ real_t m_accTwistLimitImpulse = 0.0;
- bool m_angularOnly;
- bool m_solveTwistLimit;
- bool m_solveSwingLimit;
+ bool m_angularOnly = false;
+ bool m_solveTwistLimit = false;
+ bool m_solveSwingLimit = false;
public:
virtual PhysicsServer3D::JointType get_type() const override { return PhysicsServer3D::JOINT_TYPE_CONE_TWIST; }
diff --git a/servers/physics_3d/joints/generic_6dof_joint_3d_sw.h b/servers/physics_3d/joints/generic_6dof_joint_3d_sw.h
index d0f3dbbd35..6492e40393 100644
--- a/servers/physics_3d/joints/generic_6dof_joint_3d_sw.h
+++ b/servers/physics_3d/joints/generic_6dof_joint_3d_sw.h
@@ -65,43 +65,28 @@ class G6DOFRotationalLimitMotor3DSW {
public:
//! limit_parameters
//!@{
- real_t m_loLimit; //!< joint limit
- real_t m_hiLimit; //!< joint limit
- real_t m_targetVelocity; //!< target motor velocity
- real_t m_maxMotorForce; //!< max force on motor
- real_t m_maxLimitForce; //!< max force on limit
- real_t m_damping; //!< Damping.
- real_t m_limitSoftness; //! Relaxation factor
- real_t m_ERP; //!< Error tolerance factor when joint is at limit
- real_t m_bounce; //!< restitution factor
- bool m_enableMotor;
- bool m_enableLimit;
+ real_t m_loLimit = -1e30; //!< joint limit
+ real_t m_hiLimit = 1e30; //!< joint limit
+ real_t m_targetVelocity = 0.0; //!< target motor velocity
+ real_t m_maxMotorForce = 0.1; //!< max force on motor
+ real_t m_maxLimitForce = 300.0; //!< max force on limit
+ real_t m_damping = 1.0; //!< Damping.
+ real_t m_limitSoftness = 0.5; //! Relaxation factor
+ real_t m_ERP = 0.5; //!< Error tolerance factor when joint is at limit
+ real_t m_bounce = 0.0; //!< restitution factor
+ bool m_enableMotor = false;
+ bool m_enableLimit = false;
//!@}
//! temp_variables
//!@{
- real_t m_currentLimitError; //!< How much is violated this limit
- int m_currentLimit; //!< 0=free, 1=at lo limit, 2=at hi limit
- real_t m_accumulatedImpulse;
+ real_t m_currentLimitError = 0.0; //!< How much is violated this limit
+ int m_currentLimit = 0; //!< 0=free, 1=at lo limit, 2=at hi limit
+ real_t m_accumulatedImpulse = 0.0;
//!@}
- G6DOFRotationalLimitMotor3DSW() {
- m_accumulatedImpulse = 0.f;
- m_targetVelocity = 0;
- m_maxMotorForce = 0.1f;
- m_maxLimitForce = 300.0f;
- m_loLimit = -1e30;
- m_hiLimit = 1e30;
- m_ERP = 0.5f;
- m_bounce = 0.0f;
- m_damping = 1.0f;
- m_limitSoftness = 0.5f;
- m_currentLimit = 0;
- m_currentLimitError = 0;
- m_enableMotor = false;
- m_enableLimit = false;
- }
+ G6DOFRotationalLimitMotor3DSW() {}
//! Is limited
bool isLimited() {
@@ -125,30 +110,16 @@ public:
class G6DOFTranslationalLimitMotor3DSW {
public:
- Vector3 m_lowerLimit; //!< the constraint lower limits
- Vector3 m_upperLimit; //!< the constraint upper limits
- Vector3 m_accumulatedImpulse;
+ Vector3 m_lowerLimit = Vector3(0.0, 0.0, 0.0); //!< the constraint lower limits
+ Vector3 m_upperLimit = Vector3(0.0, 0.0, 0.0); //!< the constraint upper limits
+ Vector3 m_accumulatedImpulse = Vector3(0.0, 0.0, 0.0);
//! Linear_Limit_parameters
//!@{
- Vector3 m_limitSoftness; //!< Softness for linear limit
- Vector3 m_damping; //!< Damping for linear limit
- Vector3 m_restitution; //! Bounce parameter for linear limit
+ Vector3 m_limitSoftness = Vector3(0.7, 0.7, 0.7); //!< Softness for linear limit
+ Vector3 m_damping = Vector3(1.0, 1.0, 1.0); //!< Damping for linear limit
+ Vector3 m_restitution = Vector3(0.5, 0.5, 0.5); //! Bounce parameter for linear limit
//!@}
- bool enable_limit[3];
-
- G6DOFTranslationalLimitMotor3DSW() {
- m_lowerLimit = Vector3(0.f, 0.f, 0.f);
- m_upperLimit = Vector3(0.f, 0.f, 0.f);
- m_accumulatedImpulse = Vector3(0.f, 0.f, 0.f);
-
- m_limitSoftness = Vector3(1, 1, 1) * 0.7f;
- m_damping = Vector3(1, 1, 1) * real_t(1.0f);
- m_restitution = Vector3(1, 1, 1) * real_t(0.5f);
-
- enable_limit[0] = true;
- enable_limit[1] = true;
- enable_limit[2] = true;
- }
+ bool enable_limit[3] = { true, true, true };
//! Test limit
/*!
@@ -180,7 +151,7 @@ protected:
Body3DSW *B;
};
- Body3DSW *_arr[2];
+ Body3DSW *_arr[2] = { nullptr, nullptr };
};
//! relative_frames
@@ -208,7 +179,7 @@ protected:
protected:
//! temporal variables
//!@{
- real_t m_timeStep;
+ real_t m_timeStep = 0.0;
Transform3D m_calculatedTransformA;
Transform3D m_calculatedTransformB;
Vector3 m_calculatedAxisAngleDiff;
@@ -216,7 +187,7 @@ protected:
Vector3 m_AnchorPos; // point between pivots of bodies A and B to solve linear axes
- bool m_useLinearReferenceFrameA;
+ bool m_useLinearReferenceFrameA = false;
//!@}
diff --git a/servers/physics_3d/joints/hinge_joint_3d_sw.cpp b/servers/physics_3d/joints/hinge_joint_3d_sw.cpp
index b928f18231..a45fcf7eb5 100644
--- a/servers/physics_3d/joints/hinge_joint_3d_sw.cpp
+++ b/servers/physics_3d/joints/hinge_joint_3d_sw.cpp
@@ -79,21 +79,6 @@ HingeJoint3DSW::HingeJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform3D &
m_rbBFrame.basis[1][2] *= real_t(-1.);
m_rbBFrame.basis[2][2] *= real_t(-1.);
- //start with free
- m_lowerLimit = Math_PI;
- m_upperLimit = -Math_PI;
-
- m_useLimit = false;
- m_biasFactor = 0.3f;
- m_relaxationFactor = 1.0f;
- m_limitSoftness = 0.9f;
- m_solveLimit = false;
-
- tau = 0.3;
-
- m_angularOnly = false;
- m_enableAngularMotor = false;
-
A->add_constraint(this, 0);
B->add_constraint(this, 1);
}
@@ -135,21 +120,6 @@ HingeJoint3DSW::HingeJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Vector3 &pivo
rbAxisB1.y, rbAxisB2.y, -axisInB.y,
rbAxisB1.z, rbAxisB2.z, -axisInB.z);
- //start with free
- m_lowerLimit = Math_PI;
- m_upperLimit = -Math_PI;
-
- m_useLimit = false;
- m_biasFactor = 0.3f;
- m_relaxationFactor = 1.0f;
- m_limitSoftness = 0.9f;
- m_solveLimit = false;
-
- tau = 0.3;
-
- m_angularOnly = false;
- m_enableAngularMotor = false;
-
A->add_constraint(this, 0);
B->add_constraint(this, 1);
}
diff --git a/servers/physics_3d/joints/hinge_joint_3d_sw.h b/servers/physics_3d/joints/hinge_joint_3d_sw.h
index 22eb2f4660..a4ceff9ffe 100644
--- a/servers/physics_3d/joints/hinge_joint_3d_sw.h
+++ b/servers/physics_3d/joints/hinge_joint_3d_sw.h
@@ -60,7 +60,7 @@ class HingeJoint3DSW : public Joint3DSW {
Body3DSW *B;
};
- Body3DSW *_arr[2];
+ Body3DSW *_arr[2] = {};
};
JacobianEntry3DSW m_jac[3]; //3 orthogonal linear constraints
@@ -69,31 +69,31 @@ class HingeJoint3DSW : public Joint3DSW {
Transform3D m_rbAFrame; // constraint axii. Assumes z is hinge axis.
Transform3D m_rbBFrame;
- real_t m_motorTargetVelocity;
- real_t m_maxMotorImpulse;
+ real_t m_motorTargetVelocity = 0.0;
+ real_t m_maxMotorImpulse = 0.0;
- real_t m_limitSoftness;
- real_t m_biasFactor;
- real_t m_relaxationFactor;
+ real_t m_limitSoftness = 0.9;
+ real_t m_biasFactor = 0.3;
+ real_t m_relaxationFactor = 1.0;
- real_t m_lowerLimit;
- real_t m_upperLimit;
+ real_t m_lowerLimit = Math_PI;
+ real_t m_upperLimit = -Math_PI;
- real_t m_kHinge;
+ real_t m_kHinge = 0.0;
- real_t m_limitSign;
- real_t m_correction;
+ real_t m_limitSign = 0.0;
+ real_t m_correction = 0.0;
- real_t m_accLimitImpulse;
+ real_t m_accLimitImpulse = 0.0;
- real_t tau;
+ real_t tau = 0.3;
- bool m_useLimit;
- bool m_angularOnly;
- bool m_enableAngularMotor;
- bool m_solveLimit;
+ bool m_useLimit = false;
+ bool m_angularOnly = false;
+ bool m_enableAngularMotor = false;
+ bool m_solveLimit = false;
- real_t m_appliedImpulse;
+ real_t m_appliedImpulse = 0.0;
public:
virtual PhysicsServer3D::JointType get_type() const override { return PhysicsServer3D::JOINT_TYPE_HINGE; }
diff --git a/servers/physics_3d/joints/jacobian_entry_3d_sw.h b/servers/physics_3d/joints/jacobian_entry_3d_sw.h
index 6afa70c816..7294ff78e3 100644
--- a/servers/physics_3d/joints/jacobian_entry_3d_sw.h
+++ b/servers/physics_3d/joints/jacobian_entry_3d_sw.h
@@ -163,7 +163,7 @@ public:
Vector3 m_0MinvJt;
Vector3 m_1MinvJt;
//Optimization: can be stored in the w/last component of one of the vectors
- real_t m_Adiag;
+ real_t m_Adiag = 1.0;
};
#endif // JACOBIAN_ENTRY_SW_H
diff --git a/servers/physics_3d/joints/pin_joint_3d_sw.cpp b/servers/physics_3d/joints/pin_joint_3d_sw.cpp
index 8eb84d1c2f..f41151ec0e 100644
--- a/servers/physics_3d/joints/pin_joint_3d_sw.cpp
+++ b/servers/physics_3d/joints/pin_joint_3d_sw.cpp
@@ -171,11 +171,6 @@ PinJoint3DSW::PinJoint3DSW(Body3DSW *p_body_a, const Vector3 &p_pos_a, Body3DSW
m_pivotInA = p_pos_a;
m_pivotInB = p_pos_b;
- m_tau = 0.3;
- m_damping = 1;
- m_impulseClamp = 0;
- m_appliedImpulse = 0;
-
A->add_constraint(this, 0);
B->add_constraint(this, 1);
}
diff --git a/servers/physics_3d/joints/pin_joint_3d_sw.h b/servers/physics_3d/joints/pin_joint_3d_sw.h
index 3d91452850..79af48f2a5 100644
--- a/servers/physics_3d/joints/pin_joint_3d_sw.h
+++ b/servers/physics_3d/joints/pin_joint_3d_sw.h
@@ -60,15 +60,15 @@ class PinJoint3DSW : public Joint3DSW {
Body3DSW *B;
};
- Body3DSW *_arr[2];
+ Body3DSW *_arr[2] = {};
};
- real_t m_tau; //bias
- real_t m_damping;
- real_t m_impulseClamp;
- real_t m_appliedImpulse;
+ real_t m_tau = 0.3; //bias
+ real_t m_damping = 1.0;
+ real_t m_impulseClamp = 0.0;
+ real_t m_appliedImpulse = 0.0;
- JacobianEntry3DSW m_jac[3]; //3 orthogonal linear constraints
+ JacobianEntry3DSW m_jac[3] = {}; //3 orthogonal linear constraints
Vector3 m_pivotInA;
Vector3 m_pivotInB;
diff --git a/servers/physics_3d/joints/slider_joint_3d_sw.cpp b/servers/physics_3d/joints/slider_joint_3d_sw.cpp
index 1895fe1e2e..e10ed436d5 100644
--- a/servers/physics_3d/joints/slider_joint_3d_sw.cpp
+++ b/servers/physics_3d/joints/slider_joint_3d_sw.cpp
@@ -72,41 +72,6 @@ static _FORCE_INLINE_ real_t atan2fast(real_t y, real_t x) {
return (y < 0.0f) ? -angle : angle;
}
-void SliderJoint3DSW::initParams() {
- m_lowerLinLimit = real_t(1.0);
- m_upperLinLimit = real_t(-1.0);
- m_lowerAngLimit = real_t(0.);
- m_upperAngLimit = real_t(0.);
- m_softnessDirLin = SLIDER_CONSTRAINT_DEF_SOFTNESS;
- m_restitutionDirLin = SLIDER_CONSTRAINT_DEF_RESTITUTION;
- m_dampingDirLin = real_t(0.);
- m_softnessDirAng = SLIDER_CONSTRAINT_DEF_SOFTNESS;
- m_restitutionDirAng = SLIDER_CONSTRAINT_DEF_RESTITUTION;
- m_dampingDirAng = real_t(0.);
- m_softnessOrthoLin = SLIDER_CONSTRAINT_DEF_SOFTNESS;
- m_restitutionOrthoLin = SLIDER_CONSTRAINT_DEF_RESTITUTION;
- m_dampingOrthoLin = SLIDER_CONSTRAINT_DEF_DAMPING;
- m_softnessOrthoAng = SLIDER_CONSTRAINT_DEF_SOFTNESS;
- m_restitutionOrthoAng = SLIDER_CONSTRAINT_DEF_RESTITUTION;
- m_dampingOrthoAng = SLIDER_CONSTRAINT_DEF_DAMPING;
- m_softnessLimLin = SLIDER_CONSTRAINT_DEF_SOFTNESS;
- m_restitutionLimLin = SLIDER_CONSTRAINT_DEF_RESTITUTION;
- m_dampingLimLin = SLIDER_CONSTRAINT_DEF_DAMPING;
- m_softnessLimAng = SLIDER_CONSTRAINT_DEF_SOFTNESS;
- m_restitutionLimAng = SLIDER_CONSTRAINT_DEF_RESTITUTION;
- m_dampingLimAng = SLIDER_CONSTRAINT_DEF_DAMPING;
-
- m_poweredLinMotor = false;
- m_targetLinMotorVelocity = real_t(0.);
- m_maxLinMotorForce = real_t(0.);
- m_accumulatedLinMotorImpulse = real_t(0.0);
-
- m_poweredAngMotor = false;
- m_targetAngMotorVelocity = real_t(0.);
- m_maxAngMotorForce = real_t(0.);
- m_accumulatedAngMotorImpulse = real_t(0.0);
-} // SliderJointSW::initParams()
-
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
@@ -120,8 +85,6 @@ SliderJoint3DSW::SliderJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform3D
A->add_constraint(this, 0);
B->add_constraint(this, 1);
-
- initParams();
} // SliderJointSW::SliderJointSW()
//-----------------------------------------------------------------------------
diff --git a/servers/physics_3d/joints/slider_joint_3d_sw.h b/servers/physics_3d/joints/slider_joint_3d_sw.h
index f357bbd67a..d32ad9469e 100644
--- a/servers/physics_3d/joints/slider_joint_3d_sw.h
+++ b/servers/physics_3d/joints/slider_joint_3d_sw.h
@@ -73,53 +73,53 @@ protected:
Body3DSW *B;
};
- Body3DSW *_arr[2];
+ Body3DSW *_arr[2] = { nullptr, nullptr };
};
Transform3D m_frameInA;
Transform3D m_frameInB;
// linear limits
- real_t m_lowerLinLimit;
- real_t m_upperLinLimit;
+ real_t m_lowerLinLimit = 1.0;
+ real_t m_upperLinLimit = -1.0;
// angular limits
- real_t m_lowerAngLimit;
- real_t m_upperAngLimit;
+ real_t m_lowerAngLimit = 0.0;
+ real_t m_upperAngLimit = 0.0;
// softness, restitution and damping for different cases
// DirLin - moving inside linear limits
// LimLin - hitting linear limit
// DirAng - moving inside angular limits
// LimAng - hitting angular limit
// OrthoLin, OrthoAng - against constraint axis
- real_t m_softnessDirLin;
- real_t m_restitutionDirLin;
- real_t m_dampingDirLin;
- real_t m_softnessDirAng;
- real_t m_restitutionDirAng;
- real_t m_dampingDirAng;
- real_t m_softnessLimLin;
- real_t m_restitutionLimLin;
- real_t m_dampingLimLin;
- real_t m_softnessLimAng;
- real_t m_restitutionLimAng;
- real_t m_dampingLimAng;
- real_t m_softnessOrthoLin;
- real_t m_restitutionOrthoLin;
- real_t m_dampingOrthoLin;
- real_t m_softnessOrthoAng;
- real_t m_restitutionOrthoAng;
- real_t m_dampingOrthoAng;
+ real_t m_softnessDirLin = SLIDER_CONSTRAINT_DEF_SOFTNESS;
+ real_t m_restitutionDirLin = SLIDER_CONSTRAINT_DEF_RESTITUTION;
+ real_t m_dampingDirLin = 0.0;
+ real_t m_softnessDirAng = SLIDER_CONSTRAINT_DEF_SOFTNESS;
+ real_t m_restitutionDirAng = SLIDER_CONSTRAINT_DEF_RESTITUTION;
+ real_t m_dampingDirAng = 0.0;
+ real_t m_softnessLimLin = SLIDER_CONSTRAINT_DEF_SOFTNESS;
+ real_t m_restitutionLimLin = SLIDER_CONSTRAINT_DEF_RESTITUTION;
+ real_t m_dampingLimLin = SLIDER_CONSTRAINT_DEF_DAMPING;
+ real_t m_softnessLimAng = SLIDER_CONSTRAINT_DEF_SOFTNESS;
+ real_t m_restitutionLimAng = SLIDER_CONSTRAINT_DEF_RESTITUTION;
+ real_t m_dampingLimAng = SLIDER_CONSTRAINT_DEF_DAMPING;
+ real_t m_softnessOrthoLin = SLIDER_CONSTRAINT_DEF_SOFTNESS;
+ real_t m_restitutionOrthoLin = SLIDER_CONSTRAINT_DEF_RESTITUTION;
+ real_t m_dampingOrthoLin = SLIDER_CONSTRAINT_DEF_DAMPING;
+ real_t m_softnessOrthoAng = SLIDER_CONSTRAINT_DEF_SOFTNESS;
+ real_t m_restitutionOrthoAng = SLIDER_CONSTRAINT_DEF_RESTITUTION;
+ real_t m_dampingOrthoAng = SLIDER_CONSTRAINT_DEF_DAMPING;
// for interlal use
- bool m_solveLinLim;
- bool m_solveAngLim;
+ bool m_solveLinLim = false;
+ bool m_solveAngLim = false;
- JacobianEntry3DSW m_jacLin[3];
- real_t m_jacLinDiagABInv[3];
+ JacobianEntry3DSW m_jacLin[3] = {};
+ real_t m_jacLinDiagABInv[3] = {};
- JacobianEntry3DSW m_jacAng[3];
+ JacobianEntry3DSW m_jacAng[3] = {};
- real_t m_timeStep;
+ real_t m_timeStep = 0.0;
Transform3D m_calculatedTransformA;
Transform3D m_calculatedTransformB;
@@ -132,23 +132,20 @@ protected:
Vector3 m_relPosA;
Vector3 m_relPosB;
- real_t m_linPos;
+ real_t m_linPos = 0.0;
- real_t m_angDepth;
- real_t m_kAngle;
+ real_t m_angDepth = 0.0;
+ real_t m_kAngle = 0.0;
- bool m_poweredLinMotor;
- real_t m_targetLinMotorVelocity;
- real_t m_maxLinMotorForce;
- real_t m_accumulatedLinMotorImpulse;
+ bool m_poweredLinMotor = false;
+ real_t m_targetLinMotorVelocity = 0.0;
+ real_t m_maxLinMotorForce = 0.0;
+ real_t m_accumulatedLinMotorImpulse = 0.0;
- bool m_poweredAngMotor;
- real_t m_targetAngMotorVelocity;
- real_t m_maxAngMotorForce;
- real_t m_accumulatedAngMotorImpulse;
-
- //------------------------
- void initParams();
+ bool m_poweredAngMotor = false;
+ real_t m_targetAngMotorVelocity = 0.0;
+ real_t m_maxAngMotorForce = 0.0;
+ real_t m_accumulatedAngMotorImpulse = 0.0;
public:
// constructors
diff --git a/servers/physics_3d/physics_server_3d_sw.cpp b/servers/physics_3d/physics_server_3d_sw.cpp
index fbb374bd74..b16e199a03 100644
--- a/servers/physics_3d/physics_server_3d_sw.cpp
+++ b/servers/physics_3d/physics_server_3d_sw.cpp
@@ -30,6 +30,7 @@
#include "physics_server_3d_sw.h"
+#include "body_direct_state_3d_sw.h"
#include "broad_phase_3d_bvh.h"
#include "core/debugger/engine_debugger.h"
#include "core/os/os.h"
@@ -42,8 +43,14 @@
#define FLUSH_QUERY_CHECK(m_object) \
ERR_FAIL_COND_MSG(m_object->get_space() && flushing_queries, "Can't change this state while flushing queries. Use call_deferred() or set_deferred() to change monitoring state instead.");
-RID PhysicsServer3DSW::plane_shape_create() {
- Shape3DSW *shape = memnew(PlaneShape3DSW);
+RID PhysicsServer3DSW::world_boundary_shape_create() {
+ Shape3DSW *shape = memnew(WorldBoundaryShape3DSW);
+ RID rid = shape_owner.make_rid(shape);
+ shape->set_self(rid);
+ return rid;
+}
+RID PhysicsServer3DSW::separation_ray_shape_create() {
+ Shape3DSW *shape = memnew(SeparationRayShape3DSW);
RID rid = shape_owner.make_rid(shape);
shape->set_self(rid);
return rid;
@@ -95,25 +102,25 @@ RID PhysicsServer3DSW::custom_shape_create() {
}
void PhysicsServer3DSW::shape_set_data(RID p_shape, const Variant &p_data) {
- Shape3DSW *shape = shape_owner.getornull(p_shape);
+ Shape3DSW *shape = shape_owner.get_or_null(p_shape);
ERR_FAIL_COND(!shape);
shape->set_data(p_data);
};
void PhysicsServer3DSW::shape_set_custom_solver_bias(RID p_shape, real_t p_bias) {
- Shape3DSW *shape = shape_owner.getornull(p_shape);
+ Shape3DSW *shape = shape_owner.get_or_null(p_shape);
ERR_FAIL_COND(!shape);
shape->set_custom_bias(p_bias);
}
PhysicsServer3D::ShapeType PhysicsServer3DSW::shape_get_type(RID p_shape) const {
- const Shape3DSW *shape = shape_owner.getornull(p_shape);
+ const Shape3DSW *shape = shape_owner.get_or_null(p_shape);
ERR_FAIL_COND_V(!shape, SHAPE_CUSTOM);
return shape->get_type();
};
Variant PhysicsServer3DSW::shape_get_data(RID p_shape) const {
- const Shape3DSW *shape = shape_owner.getornull(p_shape);
+ const Shape3DSW *shape = shape_owner.get_or_null(p_shape);
ERR_FAIL_COND_V(!shape, Variant());
ERR_FAIL_COND_V(!shape->is_configured(), Variant());
return shape->get_data();
@@ -127,7 +134,7 @@ real_t PhysicsServer3DSW::shape_get_margin(RID p_shape) const {
}
real_t PhysicsServer3DSW::shape_get_custom_solver_bias(RID p_shape) const {
- const Shape3DSW *shape = shape_owner.getornull(p_shape);
+ const Shape3DSW *shape = shape_owner.get_or_null(p_shape);
ERR_FAIL_COND_V(!shape, 0);
return shape->get_custom_bias();
}
@@ -137,7 +144,7 @@ RID PhysicsServer3DSW::space_create() {
RID id = space_owner.make_rid(space);
space->set_self(id);
RID area_id = area_create();
- Area3DSW *area = area_owner.getornull(area_id);
+ Area3DSW *area = area_owner.get_or_null(area_id);
ERR_FAIL_COND_V(!area, RID());
space->set_default_area(area);
area->set_space(space);
@@ -151,7 +158,7 @@ RID PhysicsServer3DSW::space_create() {
};
void PhysicsServer3DSW::space_set_active(RID p_space, bool p_active) {
- Space3DSW *space = space_owner.getornull(p_space);
+ Space3DSW *space = space_owner.get_or_null(p_space);
ERR_FAIL_COND(!space);
if (p_active) {
active_spaces.insert(space);
@@ -161,27 +168,27 @@ void PhysicsServer3DSW::space_set_active(RID p_space, bool p_active) {
}
bool PhysicsServer3DSW::space_is_active(RID p_space) const {
- const Space3DSW *space = space_owner.getornull(p_space);
+ const Space3DSW *space = space_owner.get_or_null(p_space);
ERR_FAIL_COND_V(!space, false);
return active_spaces.has(space);
}
void PhysicsServer3DSW::space_set_param(RID p_space, SpaceParameter p_param, real_t p_value) {
- Space3DSW *space = space_owner.getornull(p_space);
+ Space3DSW *space = space_owner.get_or_null(p_space);
ERR_FAIL_COND(!space);
space->set_param(p_param, p_value);
}
real_t PhysicsServer3DSW::space_get_param(RID p_space, SpaceParameter p_param) const {
- const Space3DSW *space = space_owner.getornull(p_space);
+ const Space3DSW *space = space_owner.get_or_null(p_space);
ERR_FAIL_COND_V(!space, 0);
return space->get_param(p_param);
}
PhysicsDirectSpaceState3D *PhysicsServer3DSW::space_get_direct_state(RID p_space) {
- Space3DSW *space = space_owner.getornull(p_space);
+ Space3DSW *space = space_owner.get_or_null(p_space);
ERR_FAIL_COND_V(!space, nullptr);
ERR_FAIL_COND_V_MSG((using_threads && !doing_sync) || space->is_locked(), nullptr, "Space state is inaccessible right now, wait for iteration or physics process notification.");
@@ -189,19 +196,19 @@ PhysicsDirectSpaceState3D *PhysicsServer3DSW::space_get_direct_state(RID p_space
}
void PhysicsServer3DSW::space_set_debug_contacts(RID p_space, int p_max_contacts) {
- Space3DSW *space = space_owner.getornull(p_space);
+ Space3DSW *space = space_owner.get_or_null(p_space);
ERR_FAIL_COND(!space);
space->set_debug_contacts(p_max_contacts);
}
Vector<Vector3> PhysicsServer3DSW::space_get_contacts(RID p_space) const {
- Space3DSW *space = space_owner.getornull(p_space);
+ Space3DSW *space = space_owner.get_or_null(p_space);
ERR_FAIL_COND_V(!space, Vector<Vector3>());
return space->get_debug_contacts();
}
int PhysicsServer3DSW::space_get_contact_count(RID p_space) const {
- Space3DSW *space = space_owner.getornull(p_space);
+ Space3DSW *space = space_owner.get_or_null(p_space);
ERR_FAIL_COND_V(!space, 0);
return space->get_debug_contact_count();
}
@@ -214,12 +221,12 @@ RID PhysicsServer3DSW::area_create() {
};
void PhysicsServer3DSW::area_set_space(RID p_area, RID p_space) {
- Area3DSW *area = area_owner.getornull(p_area);
+ Area3DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND(!area);
Space3DSW *space = nullptr;
if (p_space.is_valid()) {
- space = space_owner.getornull(p_space);
+ space = space_owner.get_or_null(p_space);
ERR_FAIL_COND(!space);
}
@@ -232,7 +239,7 @@ void PhysicsServer3DSW::area_set_space(RID p_area, RID p_space) {
};
RID PhysicsServer3DSW::area_get_space(RID p_area) const {
- Area3DSW *area = area_owner.getornull(p_area);
+ Area3DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND_V(!area, RID());
Space3DSW *space = area->get_space();
@@ -243,34 +250,34 @@ RID PhysicsServer3DSW::area_get_space(RID p_area) const {
};
void PhysicsServer3DSW::area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) {
- Area3DSW *area = area_owner.getornull(p_area);
+ Area3DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND(!area);
area->set_space_override_mode(p_mode);
}
PhysicsServer3D::AreaSpaceOverrideMode PhysicsServer3DSW::area_get_space_override_mode(RID p_area) const {
- const Area3DSW *area = area_owner.getornull(p_area);
+ const Area3DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND_V(!area, AREA_SPACE_OVERRIDE_DISABLED);
return area->get_space_override_mode();
}
void PhysicsServer3DSW::area_add_shape(RID p_area, RID p_shape, const Transform3D &p_transform, bool p_disabled) {
- Area3DSW *area = area_owner.getornull(p_area);
+ Area3DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND(!area);
- Shape3DSW *shape = shape_owner.getornull(p_shape);
+ Shape3DSW *shape = shape_owner.get_or_null(p_shape);
ERR_FAIL_COND(!shape);
area->add_shape(shape, p_transform, p_disabled);
}
void PhysicsServer3DSW::area_set_shape(RID p_area, int p_shape_idx, RID p_shape) {
- Area3DSW *area = area_owner.getornull(p_area);
+ Area3DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND(!area);
- Shape3DSW *shape = shape_owner.getornull(p_shape);
+ Shape3DSW *shape = shape_owner.get_or_null(p_shape);
ERR_FAIL_COND(!shape);
ERR_FAIL_COND(!shape->is_configured());
@@ -278,21 +285,21 @@ void PhysicsServer3DSW::area_set_shape(RID p_area, int p_shape_idx, RID p_shape)
}
void PhysicsServer3DSW::area_set_shape_transform(RID p_area, int p_shape_idx, const Transform3D &p_transform) {
- Area3DSW *area = area_owner.getornull(p_area);
+ Area3DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND(!area);
area->set_shape_transform(p_shape_idx, p_transform);
}
int PhysicsServer3DSW::area_get_shape_count(RID p_area) const {
- Area3DSW *area = area_owner.getornull(p_area);
+ Area3DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND_V(!area, -1);
return area->get_shape_count();
}
RID PhysicsServer3DSW::area_get_shape(RID p_area, int p_shape_idx) const {
- Area3DSW *area = area_owner.getornull(p_area);
+ Area3DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND_V(!area, RID());
Shape3DSW *shape = area->get_shape(p_shape_idx);
@@ -302,21 +309,21 @@ RID PhysicsServer3DSW::area_get_shape(RID p_area, int p_shape_idx) const {
}
Transform3D PhysicsServer3DSW::area_get_shape_transform(RID p_area, int p_shape_idx) const {
- Area3DSW *area = area_owner.getornull(p_area);
+ Area3DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND_V(!area, Transform3D());
return area->get_shape_transform(p_shape_idx);
}
void PhysicsServer3DSW::area_remove_shape(RID p_area, int p_shape_idx) {
- Area3DSW *area = area_owner.getornull(p_area);
+ Area3DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND(!area);
area->remove_shape(p_shape_idx);
}
void PhysicsServer3DSW::area_clear_shapes(RID p_area) {
- Area3DSW *area = area_owner.getornull(p_area);
+ Area3DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND(!area);
while (area->get_shape_count()) {
@@ -325,7 +332,7 @@ void PhysicsServer3DSW::area_clear_shapes(RID p_area) {
}
void PhysicsServer3DSW::area_set_shape_disabled(RID p_area, int p_shape_idx, bool p_disabled) {
- Area3DSW *area = area_owner.getornull(p_area);
+ Area3DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND(!area);
ERR_FAIL_INDEX(p_shape_idx, area->get_shape_count());
FLUSH_QUERY_CHECK(area);
@@ -334,74 +341,74 @@ void PhysicsServer3DSW::area_set_shape_disabled(RID p_area, int p_shape_idx, boo
void PhysicsServer3DSW::area_attach_object_instance_id(RID p_area, ObjectID p_id) {
if (space_owner.owns(p_area)) {
- Space3DSW *space = space_owner.getornull(p_area);
+ Space3DSW *space = space_owner.get_or_null(p_area);
p_area = space->get_default_area()->get_self();
}
- Area3DSW *area = area_owner.getornull(p_area);
+ Area3DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND(!area);
area->set_instance_id(p_id);
}
ObjectID PhysicsServer3DSW::area_get_object_instance_id(RID p_area) const {
if (space_owner.owns(p_area)) {
- Space3DSW *space = space_owner.getornull(p_area);
+ Space3DSW *space = space_owner.get_or_null(p_area);
p_area = space->get_default_area()->get_self();
}
- Area3DSW *area = area_owner.getornull(p_area);
+ Area3DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND_V(!area, ObjectID());
return area->get_instance_id();
}
void PhysicsServer3DSW::area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value) {
if (space_owner.owns(p_area)) {
- Space3DSW *space = space_owner.getornull(p_area);
+ Space3DSW *space = space_owner.get_or_null(p_area);
p_area = space->get_default_area()->get_self();
}
- Area3DSW *area = area_owner.getornull(p_area);
+ Area3DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND(!area);
area->set_param(p_param, p_value);
};
void PhysicsServer3DSW::area_set_transform(RID p_area, const Transform3D &p_transform) {
- Area3DSW *area = area_owner.getornull(p_area);
+ Area3DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND(!area);
area->set_transform(p_transform);
};
Variant PhysicsServer3DSW::area_get_param(RID p_area, AreaParameter p_param) const {
if (space_owner.owns(p_area)) {
- Space3DSW *space = space_owner.getornull(p_area);
+ Space3DSW *space = space_owner.get_or_null(p_area);
p_area = space->get_default_area()->get_self();
}
- Area3DSW *area = area_owner.getornull(p_area);
+ Area3DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND_V(!area, Variant());
return area->get_param(p_param);
};
Transform3D PhysicsServer3DSW::area_get_transform(RID p_area) const {
- Area3DSW *area = area_owner.getornull(p_area);
+ Area3DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND_V(!area, Transform3D());
return area->get_transform();
};
void PhysicsServer3DSW::area_set_collision_layer(RID p_area, uint32_t p_layer) {
- Area3DSW *area = area_owner.getornull(p_area);
+ Area3DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND(!area);
area->set_collision_layer(p_layer);
}
void PhysicsServer3DSW::area_set_collision_mask(RID p_area, uint32_t p_mask) {
- Area3DSW *area = area_owner.getornull(p_area);
+ Area3DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND(!area);
area->set_collision_mask(p_mask);
}
void PhysicsServer3DSW::area_set_monitorable(RID p_area, bool p_monitorable) {
- Area3DSW *area = area_owner.getornull(p_area);
+ Area3DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND(!area);
FLUSH_QUERY_CHECK(area);
@@ -409,21 +416,21 @@ void PhysicsServer3DSW::area_set_monitorable(RID p_area, bool p_monitorable) {
}
void PhysicsServer3DSW::area_set_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) {
- Area3DSW *area = area_owner.getornull(p_area);
+ Area3DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND(!area);
area->set_monitor_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method);
}
void PhysicsServer3DSW::area_set_ray_pickable(RID p_area, bool p_enable) {
- Area3DSW *area = area_owner.getornull(p_area);
+ Area3DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND(!area);
area->set_ray_pickable(p_enable);
}
void PhysicsServer3DSW::area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) {
- Area3DSW *area = area_owner.getornull(p_area);
+ Area3DSW *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND(!area);
area->set_area_monitor_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method);
@@ -439,12 +446,12 @@ RID PhysicsServer3DSW::body_create() {
};
void PhysicsServer3DSW::body_set_space(RID p_body, RID p_space) {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
Space3DSW *space = nullptr;
if (p_space.is_valid()) {
- space = space_owner.getornull(p_space);
+ space = space_owner.get_or_null(p_space);
ERR_FAIL_COND(!space);
}
@@ -457,7 +464,7 @@ void PhysicsServer3DSW::body_set_space(RID p_body, RID p_space) {
};
RID PhysicsServer3DSW::body_get_space(RID p_body) const {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!body, RID());
Space3DSW *space = body->get_space();
@@ -468,55 +475,55 @@ RID PhysicsServer3DSW::body_get_space(RID p_body) const {
};
void PhysicsServer3DSW::body_set_mode(RID p_body, BodyMode p_mode) {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
body->set_mode(p_mode);
};
PhysicsServer3D::BodyMode PhysicsServer3DSW::body_get_mode(RID p_body) const {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!body, BODY_MODE_STATIC);
return body->get_mode();
};
void PhysicsServer3DSW::body_add_shape(RID p_body, RID p_shape, const Transform3D &p_transform, bool p_disabled) {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
- Shape3DSW *shape = shape_owner.getornull(p_shape);
+ Shape3DSW *shape = shape_owner.get_or_null(p_shape);
ERR_FAIL_COND(!shape);
body->add_shape(shape, p_transform, p_disabled);
}
void PhysicsServer3DSW::body_set_shape(RID p_body, int p_shape_idx, RID p_shape) {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
- Shape3DSW *shape = shape_owner.getornull(p_shape);
+ Shape3DSW *shape = shape_owner.get_or_null(p_shape);
ERR_FAIL_COND(!shape);
ERR_FAIL_COND(!shape->is_configured());
body->set_shape(p_shape_idx, shape);
}
void PhysicsServer3DSW::body_set_shape_transform(RID p_body, int p_shape_idx, const Transform3D &p_transform) {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
body->set_shape_transform(p_shape_idx, p_transform);
}
int PhysicsServer3DSW::body_get_shape_count(RID p_body) const {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!body, -1);
return body->get_shape_count();
}
RID PhysicsServer3DSW::body_get_shape(RID p_body, int p_shape_idx) const {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!body, RID());
Shape3DSW *shape = body->get_shape(p_shape_idx);
@@ -526,7 +533,7 @@ RID PhysicsServer3DSW::body_get_shape(RID p_body, int p_shape_idx) const {
}
void PhysicsServer3DSW::body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled) {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
ERR_FAIL_INDEX(p_shape_idx, body->get_shape_count());
FLUSH_QUERY_CHECK(body);
@@ -535,21 +542,21 @@ void PhysicsServer3DSW::body_set_shape_disabled(RID p_body, int p_shape_idx, boo
}
Transform3D PhysicsServer3DSW::body_get_shape_transform(RID p_body, int p_shape_idx) const {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!body, Transform3D());
return body->get_shape_transform(p_shape_idx);
}
void PhysicsServer3DSW::body_remove_shape(RID p_body, int p_shape_idx) {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
body->remove_shape(p_shape_idx);
}
void PhysicsServer3DSW::body_clear_shapes(RID p_body) {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
while (body->get_shape_count()) {
@@ -558,21 +565,21 @@ void PhysicsServer3DSW::body_clear_shapes(RID p_body) {
}
void PhysicsServer3DSW::body_set_enable_continuous_collision_detection(RID p_body, bool p_enable) {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
body->set_continuous_collision_detection(p_enable);
}
bool PhysicsServer3DSW::body_is_continuous_collision_detection_enabled(RID p_body) const {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!body, false);
return body->is_continuous_collision_detection_enabled();
}
void PhysicsServer3DSW::body_set_collision_layer(RID p_body, uint32_t p_layer) {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
body->set_collision_layer(p_layer);
@@ -580,14 +587,14 @@ void PhysicsServer3DSW::body_set_collision_layer(RID p_body, uint32_t p_layer) {
}
uint32_t PhysicsServer3DSW::body_get_collision_layer(RID p_body) const {
- const Body3DSW *body = body_owner.getornull(p_body);
+ const Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!body, 0);
return body->get_collision_layer();
}
void PhysicsServer3DSW::body_set_collision_mask(RID p_body, uint32_t p_mask) {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
body->set_collision_mask(p_mask);
@@ -595,20 +602,20 @@ void PhysicsServer3DSW::body_set_collision_mask(RID p_body, uint32_t p_mask) {
}
uint32_t PhysicsServer3DSW::body_get_collision_mask(RID p_body) const {
- const Body3DSW *body = body_owner.getornull(p_body);
+ const Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!body, 0);
return body->get_collision_mask();
}
void PhysicsServer3DSW::body_attach_object_instance_id(RID p_body, ObjectID p_id) {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
if (body) {
body->set_instance_id(p_id);
return;
}
- SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
if (soft_body) {
soft_body->set_instance_id(p_id);
return;
@@ -618,54 +625,61 @@ void PhysicsServer3DSW::body_attach_object_instance_id(RID p_body, ObjectID p_id
};
ObjectID PhysicsServer3DSW::body_get_object_instance_id(RID p_body) const {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!body, ObjectID());
return body->get_instance_id();
};
void PhysicsServer3DSW::body_set_user_flags(RID p_body, uint32_t p_flags) {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
};
uint32_t PhysicsServer3DSW::body_get_user_flags(RID p_body) const {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!body, 0);
return 0;
};
-void PhysicsServer3DSW::body_set_param(RID p_body, BodyParameter p_param, real_t p_value) {
- Body3DSW *body = body_owner.getornull(p_body);
+void PhysicsServer3DSW::body_set_param(RID p_body, BodyParameter p_param, const Variant &p_value) {
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
body->set_param(p_param, p_value);
};
-real_t PhysicsServer3DSW::body_get_param(RID p_body, BodyParameter p_param) const {
- Body3DSW *body = body_owner.getornull(p_body);
+Variant PhysicsServer3DSW::body_get_param(RID p_body, BodyParameter p_param) const {
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!body, 0);
return body->get_param(p_param);
};
+void PhysicsServer3DSW::body_reset_mass_properties(RID p_body) {
+ Body3DSW *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ return body->reset_mass_properties();
+}
+
void PhysicsServer3DSW::body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
body->set_state(p_state, p_variant);
};
Variant PhysicsServer3DSW::body_get_state(RID p_body, BodyState p_state) const {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!body, Variant());
return body->get_state(p_state);
};
void PhysicsServer3DSW::body_set_applied_force(RID p_body, const Vector3 &p_force) {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
body->set_applied_force(p_force);
@@ -673,13 +687,13 @@ void PhysicsServer3DSW::body_set_applied_force(RID p_body, const Vector3 &p_forc
};
Vector3 PhysicsServer3DSW::body_get_applied_force(RID p_body) const {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!body, Vector3());
return body->get_applied_force();
};
void PhysicsServer3DSW::body_set_applied_torque(RID p_body, const Vector3 &p_torque) {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
body->set_applied_torque(p_torque);
@@ -687,14 +701,14 @@ void PhysicsServer3DSW::body_set_applied_torque(RID p_body, const Vector3 &p_tor
};
Vector3 PhysicsServer3DSW::body_get_applied_torque(RID p_body) const {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!body, Vector3());
return body->get_applied_torque();
};
void PhysicsServer3DSW::body_add_central_force(RID p_body, const Vector3 &p_force) {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
body->add_central_force(p_force);
@@ -702,7 +716,7 @@ void PhysicsServer3DSW::body_add_central_force(RID p_body, const Vector3 &p_forc
}
void PhysicsServer3DSW::body_add_force(RID p_body, const Vector3 &p_force, const Vector3 &p_position) {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
body->add_force(p_force, p_position);
@@ -710,7 +724,7 @@ void PhysicsServer3DSW::body_add_force(RID p_body, const Vector3 &p_force, const
};
void PhysicsServer3DSW::body_add_torque(RID p_body, const Vector3 &p_torque) {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
body->add_torque(p_torque);
@@ -718,7 +732,7 @@ void PhysicsServer3DSW::body_add_torque(RID p_body, const Vector3 &p_torque) {
};
void PhysicsServer3DSW::body_apply_central_impulse(RID p_body, const Vector3 &p_impulse) {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
_update_shapes();
@@ -728,7 +742,7 @@ void PhysicsServer3DSW::body_apply_central_impulse(RID p_body, const Vector3 &p_
}
void PhysicsServer3DSW::body_apply_impulse(RID p_body, const Vector3 &p_impulse, const Vector3 &p_position) {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
_update_shapes();
@@ -738,7 +752,7 @@ void PhysicsServer3DSW::body_apply_impulse(RID p_body, const Vector3 &p_impulse,
};
void PhysicsServer3DSW::body_apply_torque_impulse(RID p_body, const Vector3 &p_impulse) {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
_update_shapes();
@@ -748,7 +762,7 @@ void PhysicsServer3DSW::body_apply_torque_impulse(RID p_body, const Vector3 &p_i
};
void PhysicsServer3DSW::body_set_axis_velocity(RID p_body, const Vector3 &p_axis_velocity) {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
_update_shapes();
@@ -762,7 +776,7 @@ void PhysicsServer3DSW::body_set_axis_velocity(RID p_body, const Vector3 &p_axis
};
void PhysicsServer3DSW::body_set_axis_lock(RID p_body, BodyAxis p_axis, bool p_lock) {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
body->set_axis_lock(p_axis, p_lock);
@@ -770,13 +784,13 @@ void PhysicsServer3DSW::body_set_axis_lock(RID p_body, BodyAxis p_axis, bool p_l
}
bool PhysicsServer3DSW::body_is_axis_locked(RID p_body, BodyAxis p_axis) const {
- const Body3DSW *body = body_owner.getornull(p_body);
+ const Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!body, 0);
return body->is_axis_locked(p_axis);
}
void PhysicsServer3DSW::body_add_collision_exception(RID p_body, RID p_body_b) {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
body->add_exception(p_body_b);
@@ -784,7 +798,7 @@ void PhysicsServer3DSW::body_add_collision_exception(RID p_body, RID p_body_b) {
};
void PhysicsServer3DSW::body_remove_collision_exception(RID p_body, RID p_body_b) {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
body->remove_exception(p_body_b);
@@ -792,7 +806,7 @@ void PhysicsServer3DSW::body_remove_collision_exception(RID p_body, RID p_body_b
};
void PhysicsServer3DSW::body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions) {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
for (int i = 0; i < body->get_exceptions().size(); i++) {
@@ -801,73 +815,80 @@ void PhysicsServer3DSW::body_get_collision_exceptions(RID p_body, List<RID> *p_e
};
void PhysicsServer3DSW::body_set_contacts_reported_depth_threshold(RID p_body, real_t p_threshold) {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
};
real_t PhysicsServer3DSW::body_get_contacts_reported_depth_threshold(RID p_body) const {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!body, 0);
return 0;
};
void PhysicsServer3DSW::body_set_omit_force_integration(RID p_body, bool p_omit) {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
body->set_omit_force_integration(p_omit);
};
bool PhysicsServer3DSW::body_is_omitting_force_integration(RID p_body) const {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!body, false);
return body->get_omit_force_integration();
};
void PhysicsServer3DSW::body_set_max_contacts_reported(RID p_body, int p_contacts) {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
body->set_max_contacts_reported(p_contacts);
}
int PhysicsServer3DSW::body_get_max_contacts_reported(RID p_body) const {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!body, -1);
return body->get_max_contacts_reported();
}
+void PhysicsServer3DSW::body_set_state_sync_callback(RID p_body, void *p_instance, BodyStateCallback p_callback) {
+ Body3DSW *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+ body->set_state_sync_callback(p_instance, p_callback);
+}
+
void PhysicsServer3DSW::body_set_force_integration_callback(RID p_body, const Callable &p_callable, const Variant &p_udata) {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
body->set_force_integration_callback(p_callable, p_udata);
}
void PhysicsServer3DSW::body_set_ray_pickable(RID p_body, bool p_enable) {
- Body3DSW *body = body_owner.getornull(p_body);
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
body->set_ray_pickable(p_enable);
}
-bool PhysicsServer3DSW::body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin, MotionResult *r_result, const Set<RID> &p_exclude) {
- Body3DSW *body = body_owner.getornull(p_body);
+bool PhysicsServer3DSW::body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result) {
+ Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!body, false);
ERR_FAIL_COND_V(!body->get_space(), false);
ERR_FAIL_COND_V(body->get_space()->is_locked(), false);
_update_shapes();
- return body->get_space()->test_body_motion(body, p_from, p_motion, p_margin, r_result, p_exclude);
+ return body->get_space()->test_body_motion(body, p_parameters, r_result);
}
PhysicsDirectBodyState3D *PhysicsServer3DSW::body_get_direct_state(RID p_body) {
ERR_FAIL_COND_V_MSG((using_threads && !doing_sync), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification.");
- Body3DSW *body = body_owner.getornull(p_body);
- ERR_FAIL_COND_V(!body, nullptr);
+ Body3DSW *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_NULL_V(body, nullptr);
+
+ ERR_FAIL_NULL_V(body->get_space(), nullptr);
ERR_FAIL_COND_V_MSG(body->get_space()->is_locked(), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification.");
- direct_state->body = body;
- return direct_state;
+ return body->get_direct_state();
}
/* SOFT BODY */
@@ -880,19 +901,19 @@ RID PhysicsServer3DSW::soft_body_create() {
}
void PhysicsServer3DSW::soft_body_update_rendering_server(RID p_body, RenderingServerHandler *p_rendering_server_handler) {
- SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
ERR_FAIL_COND(!soft_body);
soft_body->update_rendering_server(p_rendering_server_handler);
}
void PhysicsServer3DSW::soft_body_set_space(RID p_body, RID p_space) {
- SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
ERR_FAIL_COND(!soft_body);
Space3DSW *space = nullptr;
if (p_space.is_valid()) {
- space = space_owner.getornull(p_space);
+ space = space_owner.get_or_null(p_space);
ERR_FAIL_COND(!space);
}
@@ -904,7 +925,7 @@ void PhysicsServer3DSW::soft_body_set_space(RID p_body, RID p_space) {
}
RID PhysicsServer3DSW::soft_body_get_space(RID p_body) const {
- SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!soft_body, RID());
Space3DSW *space = soft_body->get_space();
@@ -915,49 +936,49 @@ RID PhysicsServer3DSW::soft_body_get_space(RID p_body) const {
}
void PhysicsServer3DSW::soft_body_set_collision_layer(RID p_body, uint32_t p_layer) {
- SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
ERR_FAIL_COND(!soft_body);
soft_body->set_collision_layer(p_layer);
}
uint32_t PhysicsServer3DSW::soft_body_get_collision_layer(RID p_body) const {
- SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!soft_body, 0);
return soft_body->get_collision_layer();
}
void PhysicsServer3DSW::soft_body_set_collision_mask(RID p_body, uint32_t p_mask) {
- SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
ERR_FAIL_COND(!soft_body);
soft_body->set_collision_mask(p_mask);
}
uint32_t PhysicsServer3DSW::soft_body_get_collision_mask(RID p_body) const {
- SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!soft_body, 0);
return soft_body->get_collision_mask();
}
void PhysicsServer3DSW::soft_body_add_collision_exception(RID p_body, RID p_body_b) {
- SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
ERR_FAIL_COND(!soft_body);
soft_body->add_exception(p_body_b);
}
void PhysicsServer3DSW::soft_body_remove_collision_exception(RID p_body, RID p_body_b) {
- SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
ERR_FAIL_COND(!soft_body);
soft_body->remove_exception(p_body_b);
}
void PhysicsServer3DSW::soft_body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions) {
- SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
ERR_FAIL_COND(!soft_body);
for (int i = 0; i < soft_body->get_exceptions().size(); i++) {
@@ -966,154 +987,154 @@ void PhysicsServer3DSW::soft_body_get_collision_exceptions(RID p_body, List<RID>
}
void PhysicsServer3DSW::soft_body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) {
- SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
ERR_FAIL_COND(!soft_body);
soft_body->set_state(p_state, p_variant);
}
Variant PhysicsServer3DSW::soft_body_get_state(RID p_body, BodyState p_state) const {
- SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!soft_body, Variant());
return soft_body->get_state(p_state);
}
void PhysicsServer3DSW::soft_body_set_transform(RID p_body, const Transform3D &p_transform) {
- SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
ERR_FAIL_COND(!soft_body);
soft_body->set_state(BODY_STATE_TRANSFORM, p_transform);
}
void PhysicsServer3DSW::soft_body_set_ray_pickable(RID p_body, bool p_enable) {
- SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
ERR_FAIL_COND(!soft_body);
soft_body->set_ray_pickable(p_enable);
}
void PhysicsServer3DSW::soft_body_set_simulation_precision(RID p_body, int p_simulation_precision) {
- SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
ERR_FAIL_COND(!soft_body);
soft_body->set_iteration_count(p_simulation_precision);
}
int PhysicsServer3DSW::soft_body_get_simulation_precision(RID p_body) const {
- SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!soft_body, 0.f);
return soft_body->get_iteration_count();
}
void PhysicsServer3DSW::soft_body_set_total_mass(RID p_body, real_t p_total_mass) {
- SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
ERR_FAIL_COND(!soft_body);
soft_body->set_total_mass(p_total_mass);
}
real_t PhysicsServer3DSW::soft_body_get_total_mass(RID p_body) const {
- SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!soft_body, 0.f);
return soft_body->get_total_mass();
}
void PhysicsServer3DSW::soft_body_set_linear_stiffness(RID p_body, real_t p_stiffness) {
- SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
ERR_FAIL_COND(!soft_body);
soft_body->set_linear_stiffness(p_stiffness);
}
real_t PhysicsServer3DSW::soft_body_get_linear_stiffness(RID p_body) const {
- SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!soft_body, 0.f);
return soft_body->get_linear_stiffness();
}
void PhysicsServer3DSW::soft_body_set_pressure_coefficient(RID p_body, real_t p_pressure_coefficient) {
- SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
ERR_FAIL_COND(!soft_body);
soft_body->set_pressure_coefficient(p_pressure_coefficient);
}
real_t PhysicsServer3DSW::soft_body_get_pressure_coefficient(RID p_body) const {
- SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!soft_body, 0.f);
return soft_body->get_pressure_coefficient();
}
void PhysicsServer3DSW::soft_body_set_damping_coefficient(RID p_body, real_t p_damping_coefficient) {
- SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
ERR_FAIL_COND(!soft_body);
soft_body->set_damping_coefficient(p_damping_coefficient);
}
real_t PhysicsServer3DSW::soft_body_get_damping_coefficient(RID p_body) const {
- SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!soft_body, 0.f);
return soft_body->get_damping_coefficient();
}
void PhysicsServer3DSW::soft_body_set_drag_coefficient(RID p_body, real_t p_drag_coefficient) {
- SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
ERR_FAIL_COND(!soft_body);
soft_body->set_drag_coefficient(p_drag_coefficient);
}
real_t PhysicsServer3DSW::soft_body_get_drag_coefficient(RID p_body) const {
- SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!soft_body, 0.f);
return soft_body->get_drag_coefficient();
}
-void PhysicsServer3DSW::soft_body_set_mesh(RID p_body, const REF &p_mesh) {
- SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+void PhysicsServer3DSW::soft_body_set_mesh(RID p_body, RID p_mesh) {
+ SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
ERR_FAIL_COND(!soft_body);
soft_body->set_mesh(p_mesh);
}
AABB PhysicsServer3DSW::soft_body_get_bounds(RID p_body) const {
- SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!soft_body, AABB());
return soft_body->get_bounds();
}
void PhysicsServer3DSW::soft_body_move_point(RID p_body, int p_point_index, const Vector3 &p_global_position) {
- SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
ERR_FAIL_COND(!soft_body);
soft_body->set_vertex_position(p_point_index, p_global_position);
}
Vector3 PhysicsServer3DSW::soft_body_get_point_global_position(RID p_body, int p_point_index) const {
- SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!soft_body, Vector3());
return soft_body->get_vertex_position(p_point_index);
}
void PhysicsServer3DSW::soft_body_remove_all_pinned_points(RID p_body) {
- SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
ERR_FAIL_COND(!soft_body);
soft_body->unpin_all_vertices();
}
void PhysicsServer3DSW::soft_body_pin_point(RID p_body, int p_point_index, bool p_pin) {
- SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
ERR_FAIL_COND(!soft_body);
if (p_pin) {
@@ -1124,7 +1145,7 @@ void PhysicsServer3DSW::soft_body_pin_point(RID p_body, int p_point_index, bool
}
bool PhysicsServer3DSW::soft_body_is_point_pinned(RID p_body, int p_point_index) const {
- SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body);
+ SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!soft_body, false);
return soft_body->is_vertex_pinned(p_point_index);
@@ -1140,7 +1161,7 @@ RID PhysicsServer3DSW::joint_create() {
}
void PhysicsServer3DSW::joint_clear(RID p_joint) {
- Joint3DSW *joint = joint_owner.getornull(p_joint);
+ Joint3DSW *joint = joint_owner.get_or_null(p_joint);
if (joint->get_type() != JOINT_TYPE_MAX) {
Joint3DSW *empty_joint = memnew(Joint3DSW);
empty_joint->copy_settings_from(joint);
@@ -1151,7 +1172,7 @@ void PhysicsServer3DSW::joint_clear(RID p_joint) {
}
void PhysicsServer3DSW::joint_make_pin(RID p_joint, RID p_body_A, const Vector3 &p_local_A, RID p_body_B, const Vector3 &p_local_B) {
- Body3DSW *body_A = body_owner.getornull(p_body_A);
+ Body3DSW *body_A = body_owner.get_or_null(p_body_A);
ERR_FAIL_COND(!body_A);
if (!p_body_B.is_valid()) {
@@ -1159,12 +1180,12 @@ void PhysicsServer3DSW::joint_make_pin(RID p_joint, RID p_body_A, const Vector3
p_body_B = body_A->get_space()->get_static_global_body();
}
- Body3DSW *body_B = body_owner.getornull(p_body_B);
+ Body3DSW *body_B = body_owner.get_or_null(p_body_B);
ERR_FAIL_COND(!body_B);
ERR_FAIL_COND(body_A == body_B);
- Joint3DSW *prev_joint = joint_owner.getornull(p_joint);
+ Joint3DSW *prev_joint = joint_owner.get_or_null(p_joint);
ERR_FAIL_COND(prev_joint == nullptr);
Joint3DSW *joint = memnew(PinJoint3DSW(body_A, p_local_A, body_B, p_local_B));
@@ -1175,7 +1196,7 @@ void PhysicsServer3DSW::joint_make_pin(RID p_joint, RID p_body_A, const Vector3
}
void PhysicsServer3DSW::pin_joint_set_param(RID p_joint, PinJointParam p_param, real_t p_value) {
- Joint3DSW *joint = joint_owner.getornull(p_joint);
+ Joint3DSW *joint = joint_owner.get_or_null(p_joint);
ERR_FAIL_COND(!joint);
ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_PIN);
PinJoint3DSW *pin_joint = static_cast<PinJoint3DSW *>(joint);
@@ -1183,7 +1204,7 @@ void PhysicsServer3DSW::pin_joint_set_param(RID p_joint, PinJointParam p_param,
}
real_t PhysicsServer3DSW::pin_joint_get_param(RID p_joint, PinJointParam p_param) const {
- Joint3DSW *joint = joint_owner.getornull(p_joint);
+ Joint3DSW *joint = joint_owner.get_or_null(p_joint);
ERR_FAIL_COND_V(!joint, 0);
ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_PIN, 0);
PinJoint3DSW *pin_joint = static_cast<PinJoint3DSW *>(joint);
@@ -1191,7 +1212,7 @@ real_t PhysicsServer3DSW::pin_joint_get_param(RID p_joint, PinJointParam p_param
}
void PhysicsServer3DSW::pin_joint_set_local_a(RID p_joint, const Vector3 &p_A) {
- Joint3DSW *joint = joint_owner.getornull(p_joint);
+ Joint3DSW *joint = joint_owner.get_or_null(p_joint);
ERR_FAIL_COND(!joint);
ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_PIN);
PinJoint3DSW *pin_joint = static_cast<PinJoint3DSW *>(joint);
@@ -1199,7 +1220,7 @@ void PhysicsServer3DSW::pin_joint_set_local_a(RID p_joint, const Vector3 &p_A) {
}
Vector3 PhysicsServer3DSW::pin_joint_get_local_a(RID p_joint) const {
- Joint3DSW *joint = joint_owner.getornull(p_joint);
+ Joint3DSW *joint = joint_owner.get_or_null(p_joint);
ERR_FAIL_COND_V(!joint, Vector3());
ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_PIN, Vector3());
PinJoint3DSW *pin_joint = static_cast<PinJoint3DSW *>(joint);
@@ -1207,7 +1228,7 @@ Vector3 PhysicsServer3DSW::pin_joint_get_local_a(RID p_joint) const {
}
void PhysicsServer3DSW::pin_joint_set_local_b(RID p_joint, const Vector3 &p_B) {
- Joint3DSW *joint = joint_owner.getornull(p_joint);
+ Joint3DSW *joint = joint_owner.get_or_null(p_joint);
ERR_FAIL_COND(!joint);
ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_PIN);
PinJoint3DSW *pin_joint = static_cast<PinJoint3DSW *>(joint);
@@ -1215,7 +1236,7 @@ void PhysicsServer3DSW::pin_joint_set_local_b(RID p_joint, const Vector3 &p_B) {
}
Vector3 PhysicsServer3DSW::pin_joint_get_local_b(RID p_joint) const {
- Joint3DSW *joint = joint_owner.getornull(p_joint);
+ Joint3DSW *joint = joint_owner.get_or_null(p_joint);
ERR_FAIL_COND_V(!joint, Vector3());
ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_PIN, Vector3());
PinJoint3DSW *pin_joint = static_cast<PinJoint3DSW *>(joint);
@@ -1223,7 +1244,7 @@ Vector3 PhysicsServer3DSW::pin_joint_get_local_b(RID p_joint) const {
}
void PhysicsServer3DSW::joint_make_hinge(RID p_joint, RID p_body_A, const Transform3D &p_frame_A, RID p_body_B, const Transform3D &p_frame_B) {
- Body3DSW *body_A = body_owner.getornull(p_body_A);
+ Body3DSW *body_A = body_owner.get_or_null(p_body_A);
ERR_FAIL_COND(!body_A);
if (!p_body_B.is_valid()) {
@@ -1231,12 +1252,12 @@ void PhysicsServer3DSW::joint_make_hinge(RID p_joint, RID p_body_A, const Transf
p_body_B = body_A->get_space()->get_static_global_body();
}
- Body3DSW *body_B = body_owner.getornull(p_body_B);
+ Body3DSW *body_B = body_owner.get_or_null(p_body_B);
ERR_FAIL_COND(!body_B);
ERR_FAIL_COND(body_A == body_B);
- Joint3DSW *prev_joint = joint_owner.getornull(p_joint);
+ Joint3DSW *prev_joint = joint_owner.get_or_null(p_joint);
ERR_FAIL_COND(prev_joint == nullptr);
Joint3DSW *joint = memnew(HingeJoint3DSW(body_A, body_B, p_frame_A, p_frame_B));
@@ -1247,7 +1268,7 @@ void PhysicsServer3DSW::joint_make_hinge(RID p_joint, RID p_body_A, const Transf
}
void PhysicsServer3DSW::joint_make_hinge_simple(RID p_joint, RID p_body_A, const Vector3 &p_pivot_A, const Vector3 &p_axis_A, RID p_body_B, const Vector3 &p_pivot_B, const Vector3 &p_axis_B) {
- Body3DSW *body_A = body_owner.getornull(p_body_A);
+ Body3DSW *body_A = body_owner.get_or_null(p_body_A);
ERR_FAIL_COND(!body_A);
if (!p_body_B.is_valid()) {
@@ -1255,12 +1276,12 @@ void PhysicsServer3DSW::joint_make_hinge_simple(RID p_joint, RID p_body_A, const
p_body_B = body_A->get_space()->get_static_global_body();
}
- Body3DSW *body_B = body_owner.getornull(p_body_B);
+ Body3DSW *body_B = body_owner.get_or_null(p_body_B);
ERR_FAIL_COND(!body_B);
ERR_FAIL_COND(body_A == body_B);
- Joint3DSW *prev_joint = joint_owner.getornull(p_joint);
+ Joint3DSW *prev_joint = joint_owner.get_or_null(p_joint);
ERR_FAIL_COND(prev_joint == nullptr);
Joint3DSW *joint = memnew(HingeJoint3DSW(body_A, body_B, p_pivot_A, p_pivot_B, p_axis_A, p_axis_B));
@@ -1271,7 +1292,7 @@ void PhysicsServer3DSW::joint_make_hinge_simple(RID p_joint, RID p_body_A, const
}
void PhysicsServer3DSW::hinge_joint_set_param(RID p_joint, HingeJointParam p_param, real_t p_value) {
- Joint3DSW *joint = joint_owner.getornull(p_joint);
+ Joint3DSW *joint = joint_owner.get_or_null(p_joint);
ERR_FAIL_COND(!joint);
ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_HINGE);
HingeJoint3DSW *hinge_joint = static_cast<HingeJoint3DSW *>(joint);
@@ -1279,7 +1300,7 @@ void PhysicsServer3DSW::hinge_joint_set_param(RID p_joint, HingeJointParam p_par
}
real_t PhysicsServer3DSW::hinge_joint_get_param(RID p_joint, HingeJointParam p_param) const {
- Joint3DSW *joint = joint_owner.getornull(p_joint);
+ Joint3DSW *joint = joint_owner.get_or_null(p_joint);
ERR_FAIL_COND_V(!joint, 0);
ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_HINGE, 0);
HingeJoint3DSW *hinge_joint = static_cast<HingeJoint3DSW *>(joint);
@@ -1287,7 +1308,7 @@ real_t PhysicsServer3DSW::hinge_joint_get_param(RID p_joint, HingeJointParam p_p
}
void PhysicsServer3DSW::hinge_joint_set_flag(RID p_joint, HingeJointFlag p_flag, bool p_value) {
- Joint3DSW *joint = joint_owner.getornull(p_joint);
+ Joint3DSW *joint = joint_owner.get_or_null(p_joint);
ERR_FAIL_COND(!joint);
ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_HINGE);
HingeJoint3DSW *hinge_joint = static_cast<HingeJoint3DSW *>(joint);
@@ -1295,7 +1316,7 @@ void PhysicsServer3DSW::hinge_joint_set_flag(RID p_joint, HingeJointFlag p_flag,
}
bool PhysicsServer3DSW::hinge_joint_get_flag(RID p_joint, HingeJointFlag p_flag) const {
- Joint3DSW *joint = joint_owner.getornull(p_joint);
+ Joint3DSW *joint = joint_owner.get_or_null(p_joint);
ERR_FAIL_COND_V(!joint, false);
ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_HINGE, false);
HingeJoint3DSW *hinge_joint = static_cast<HingeJoint3DSW *>(joint);
@@ -1303,19 +1324,19 @@ bool PhysicsServer3DSW::hinge_joint_get_flag(RID p_joint, HingeJointFlag p_flag)
}
void PhysicsServer3DSW::joint_set_solver_priority(RID p_joint, int p_priority) {
- Joint3DSW *joint = joint_owner.getornull(p_joint);
+ Joint3DSW *joint = joint_owner.get_or_null(p_joint);
ERR_FAIL_COND(!joint);
joint->set_priority(p_priority);
}
int PhysicsServer3DSW::joint_get_solver_priority(RID p_joint) const {
- Joint3DSW *joint = joint_owner.getornull(p_joint);
+ Joint3DSW *joint = joint_owner.get_or_null(p_joint);
ERR_FAIL_COND_V(!joint, 0);
return joint->get_priority();
}
void PhysicsServer3DSW::joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable) {
- Joint3DSW *joint = joint_owner.getornull(p_joint);
+ Joint3DSW *joint = joint_owner.get_or_null(p_joint);
ERR_FAIL_COND(!joint);
joint->disable_collisions_between_bodies(p_disable);
@@ -1335,20 +1356,20 @@ void PhysicsServer3DSW::joint_disable_collisions_between_bodies(RID p_joint, con
}
bool PhysicsServer3DSW::joint_is_disabled_collisions_between_bodies(RID p_joint) const {
- Joint3DSW *joint = joint_owner.getornull(p_joint);
+ Joint3DSW *joint = joint_owner.get_or_null(p_joint);
ERR_FAIL_COND_V(!joint, true);
return joint->is_disabled_collisions_between_bodies();
}
PhysicsServer3DSW::JointType PhysicsServer3DSW::joint_get_type(RID p_joint) const {
- Joint3DSW *joint = joint_owner.getornull(p_joint);
+ Joint3DSW *joint = joint_owner.get_or_null(p_joint);
ERR_FAIL_COND_V(!joint, JOINT_TYPE_PIN);
return joint->get_type();
}
void PhysicsServer3DSW::joint_make_slider(RID p_joint, RID p_body_A, const Transform3D &p_local_frame_A, RID p_body_B, const Transform3D &p_local_frame_B) {
- Body3DSW *body_A = body_owner.getornull(p_body_A);
+ Body3DSW *body_A = body_owner.get_or_null(p_body_A);
ERR_FAIL_COND(!body_A);
if (!p_body_B.is_valid()) {
@@ -1356,12 +1377,12 @@ void PhysicsServer3DSW::joint_make_slider(RID p_joint, RID p_body_A, const Trans
p_body_B = body_A->get_space()->get_static_global_body();
}
- Body3DSW *body_B = body_owner.getornull(p_body_B);
+ Body3DSW *body_B = body_owner.get_or_null(p_body_B);
ERR_FAIL_COND(!body_B);
ERR_FAIL_COND(body_A == body_B);
- Joint3DSW *prev_joint = joint_owner.getornull(p_joint);
+ Joint3DSW *prev_joint = joint_owner.get_or_null(p_joint);
ERR_FAIL_COND(prev_joint == nullptr);
Joint3DSW *joint = memnew(SliderJoint3DSW(body_A, body_B, p_local_frame_A, p_local_frame_B));
@@ -1372,7 +1393,7 @@ void PhysicsServer3DSW::joint_make_slider(RID p_joint, RID p_body_A, const Trans
}
void PhysicsServer3DSW::slider_joint_set_param(RID p_joint, SliderJointParam p_param, real_t p_value) {
- Joint3DSW *joint = joint_owner.getornull(p_joint);
+ Joint3DSW *joint = joint_owner.get_or_null(p_joint);
ERR_FAIL_COND(!joint);
ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_SLIDER);
SliderJoint3DSW *slider_joint = static_cast<SliderJoint3DSW *>(joint);
@@ -1380,7 +1401,7 @@ void PhysicsServer3DSW::slider_joint_set_param(RID p_joint, SliderJointParam p_p
}
real_t PhysicsServer3DSW::slider_joint_get_param(RID p_joint, SliderJointParam p_param) const {
- Joint3DSW *joint = joint_owner.getornull(p_joint);
+ Joint3DSW *joint = joint_owner.get_or_null(p_joint);
ERR_FAIL_COND_V(!joint, 0);
ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_CONE_TWIST, 0);
SliderJoint3DSW *slider_joint = static_cast<SliderJoint3DSW *>(joint);
@@ -1388,7 +1409,7 @@ real_t PhysicsServer3DSW::slider_joint_get_param(RID p_joint, SliderJointParam p
}
void PhysicsServer3DSW::joint_make_cone_twist(RID p_joint, RID p_body_A, const Transform3D &p_local_frame_A, RID p_body_B, const Transform3D &p_local_frame_B) {
- Body3DSW *body_A = body_owner.getornull(p_body_A);
+ Body3DSW *body_A = body_owner.get_or_null(p_body_A);
ERR_FAIL_COND(!body_A);
if (!p_body_B.is_valid()) {
@@ -1396,12 +1417,12 @@ void PhysicsServer3DSW::joint_make_cone_twist(RID p_joint, RID p_body_A, const T
p_body_B = body_A->get_space()->get_static_global_body();
}
- Body3DSW *body_B = body_owner.getornull(p_body_B);
+ Body3DSW *body_B = body_owner.get_or_null(p_body_B);
ERR_FAIL_COND(!body_B);
ERR_FAIL_COND(body_A == body_B);
- Joint3DSW *prev_joint = joint_owner.getornull(p_joint);
+ Joint3DSW *prev_joint = joint_owner.get_or_null(p_joint);
ERR_FAIL_COND(prev_joint == nullptr);
Joint3DSW *joint = memnew(ConeTwistJoint3DSW(body_A, body_B, p_local_frame_A, p_local_frame_B));
@@ -1412,7 +1433,7 @@ void PhysicsServer3DSW::joint_make_cone_twist(RID p_joint, RID p_body_A, const T
}
void PhysicsServer3DSW::cone_twist_joint_set_param(RID p_joint, ConeTwistJointParam p_param, real_t p_value) {
- Joint3DSW *joint = joint_owner.getornull(p_joint);
+ Joint3DSW *joint = joint_owner.get_or_null(p_joint);
ERR_FAIL_COND(!joint);
ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_CONE_TWIST);
ConeTwistJoint3DSW *cone_twist_joint = static_cast<ConeTwistJoint3DSW *>(joint);
@@ -1420,7 +1441,7 @@ void PhysicsServer3DSW::cone_twist_joint_set_param(RID p_joint, ConeTwistJointPa
}
real_t PhysicsServer3DSW::cone_twist_joint_get_param(RID p_joint, ConeTwistJointParam p_param) const {
- Joint3DSW *joint = joint_owner.getornull(p_joint);
+ Joint3DSW *joint = joint_owner.get_or_null(p_joint);
ERR_FAIL_COND_V(!joint, 0);
ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_CONE_TWIST, 0);
ConeTwistJoint3DSW *cone_twist_joint = static_cast<ConeTwistJoint3DSW *>(joint);
@@ -1428,7 +1449,7 @@ real_t PhysicsServer3DSW::cone_twist_joint_get_param(RID p_joint, ConeTwistJoint
}
void PhysicsServer3DSW::joint_make_generic_6dof(RID p_joint, RID p_body_A, const Transform3D &p_local_frame_A, RID p_body_B, const Transform3D &p_local_frame_B) {
- Body3DSW *body_A = body_owner.getornull(p_body_A);
+ Body3DSW *body_A = body_owner.get_or_null(p_body_A);
ERR_FAIL_COND(!body_A);
if (!p_body_B.is_valid()) {
@@ -1436,12 +1457,12 @@ void PhysicsServer3DSW::joint_make_generic_6dof(RID p_joint, RID p_body_A, const
p_body_B = body_A->get_space()->get_static_global_body();
}
- Body3DSW *body_B = body_owner.getornull(p_body_B);
+ Body3DSW *body_B = body_owner.get_or_null(p_body_B);
ERR_FAIL_COND(!body_B);
ERR_FAIL_COND(body_A == body_B);
- Joint3DSW *prev_joint = joint_owner.getornull(p_joint);
+ Joint3DSW *prev_joint = joint_owner.get_or_null(p_joint);
ERR_FAIL_COND(prev_joint == nullptr);
Joint3DSW *joint = memnew(Generic6DOFJoint3DSW(body_A, body_B, p_local_frame_A, p_local_frame_B, true));
@@ -1452,7 +1473,7 @@ void PhysicsServer3DSW::joint_make_generic_6dof(RID p_joint, RID p_body_A, const
}
void PhysicsServer3DSW::generic_6dof_joint_set_param(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisParam p_param, real_t p_value) {
- Joint3DSW *joint = joint_owner.getornull(p_joint);
+ Joint3DSW *joint = joint_owner.get_or_null(p_joint);
ERR_FAIL_COND(!joint);
ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_6DOF);
Generic6DOFJoint3DSW *generic_6dof_joint = static_cast<Generic6DOFJoint3DSW *>(joint);
@@ -1460,7 +1481,7 @@ void PhysicsServer3DSW::generic_6dof_joint_set_param(RID p_joint, Vector3::Axis
}
real_t PhysicsServer3DSW::generic_6dof_joint_get_param(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisParam p_param) const {
- Joint3DSW *joint = joint_owner.getornull(p_joint);
+ Joint3DSW *joint = joint_owner.get_or_null(p_joint);
ERR_FAIL_COND_V(!joint, 0);
ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_6DOF, 0);
Generic6DOFJoint3DSW *generic_6dof_joint = static_cast<Generic6DOFJoint3DSW *>(joint);
@@ -1468,7 +1489,7 @@ real_t PhysicsServer3DSW::generic_6dof_joint_get_param(RID p_joint, Vector3::Axi
}
void PhysicsServer3DSW::generic_6dof_joint_set_flag(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisFlag p_flag, bool p_enable) {
- Joint3DSW *joint = joint_owner.getornull(p_joint);
+ Joint3DSW *joint = joint_owner.get_or_null(p_joint);
ERR_FAIL_COND(!joint);
ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_6DOF);
Generic6DOFJoint3DSW *generic_6dof_joint = static_cast<Generic6DOFJoint3DSW *>(joint);
@@ -1476,7 +1497,7 @@ void PhysicsServer3DSW::generic_6dof_joint_set_flag(RID p_joint, Vector3::Axis p
}
bool PhysicsServer3DSW::generic_6dof_joint_get_flag(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisFlag p_flag) const {
- Joint3DSW *joint = joint_owner.getornull(p_joint);
+ Joint3DSW *joint = joint_owner.get_or_null(p_joint);
ERR_FAIL_COND_V(!joint, false);
ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_6DOF, false);
Generic6DOFJoint3DSW *generic_6dof_joint = static_cast<Generic6DOFJoint3DSW *>(joint);
@@ -1487,7 +1508,7 @@ void PhysicsServer3DSW::free(RID p_rid) {
_update_shapes(); //just in case
if (shape_owner.owns(p_rid)) {
- Shape3DSW *shape = shape_owner.getornull(p_rid);
+ Shape3DSW *shape = shape_owner.get_or_null(p_rid);
while (shape->get_owners().size()) {
ShapeOwner3DSW *so = shape->get_owners().front()->key();
@@ -1497,7 +1518,7 @@ void PhysicsServer3DSW::free(RID p_rid) {
shape_owner.free(p_rid);
memdelete(shape);
} else if (body_owner.owns(p_rid)) {
- Body3DSW *body = body_owner.getornull(p_rid);
+ Body3DSW *body = body_owner.get_or_null(p_rid);
/*
if (body->get_state_query())
@@ -1516,14 +1537,14 @@ void PhysicsServer3DSW::free(RID p_rid) {
body_owner.free(p_rid);
memdelete(body);
} else if (soft_body_owner.owns(p_rid)) {
- SoftBody3DSW *soft_body = soft_body_owner.getornull(p_rid);
+ SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_rid);
soft_body->set_space(nullptr);
soft_body_owner.free(p_rid);
memdelete(soft_body);
} else if (area_owner.owns(p_rid)) {
- Area3DSW *area = area_owner.getornull(p_rid);
+ Area3DSW *area = area_owner.get_or_null(p_rid);
/*
if (area->get_monitor_query())
@@ -1539,7 +1560,7 @@ void PhysicsServer3DSW::free(RID p_rid) {
area_owner.free(p_rid);
memdelete(area);
} else if (space_owner.owns(p_rid)) {
- Space3DSW *space = space_owner.getornull(p_rid);
+ Space3DSW *space = space_owner.get_or_null(p_rid);
while (space->get_objects().size()) {
CollisionObject3DSW *co = (CollisionObject3DSW *)space->get_objects().front()->get();
@@ -1553,7 +1574,7 @@ void PhysicsServer3DSW::free(RID p_rid) {
space_owner.free(p_rid);
memdelete(space);
} else if (joint_owner.owns(p_rid)) {
- Joint3DSW *joint = joint_owner.getornull(p_rid);
+ Joint3DSW *joint = joint_owner.get_or_null(p_rid);
joint_owner.free(p_rid);
memdelete(joint);
@@ -1572,10 +1593,8 @@ void PhysicsServer3DSW::set_collision_iterations(int p_iterations) {
};
void PhysicsServer3DSW::init() {
- last_step = 0.001;
iterations = 8; // 8?
stepper = memnew(Step3DSW);
- direct_state = memnew(PhysicsDirectBodyState3DSW);
};
void PhysicsServer3DSW::step(real_t p_step) {
@@ -1587,9 +1606,6 @@ void PhysicsServer3DSW::step(real_t p_step) {
_update_shapes();
- last_step = p_step;
- PhysicsDirectBodyState3DSW::singleton->step = p_step;
-
island_count = 0;
active_objects = 0;
collision_pairs = 0;
@@ -1665,7 +1681,6 @@ void PhysicsServer3DSW::end_sync() {
void PhysicsServer3DSW::finish() {
memdelete(stepper);
- memdelete(direct_state);
};
int PhysicsServer3DSW::get_process_info(ProcessInfo p_info) {
@@ -1729,11 +1744,5 @@ PhysicsServer3DSW::PhysicsServer3DSW(bool p_using_threads) {
singletonsw = this;
BroadPhase3DSW::create_func = BroadPhase3DBVH::_create;
- island_count = 0;
- active_objects = 0;
- collision_pairs = 0;
using_threads = p_using_threads;
- active = true;
- flushing_queries = false;
- doing_sync = false;
};
diff --git a/servers/physics_3d/physics_server_3d_sw.h b/servers/physics_3d/physics_server_3d_sw.h
index 6e59a77e89..54a787198d 100644
--- a/servers/physics_3d/physics_server_3d_sw.h
+++ b/servers/physics_3d/physics_server_3d_sw.h
@@ -42,23 +42,20 @@ class PhysicsServer3DSW : public PhysicsServer3D {
GDCLASS(PhysicsServer3DSW, PhysicsServer3D);
friend class PhysicsDirectSpaceState3DSW;
- bool active;
- int iterations;
- real_t last_step;
+ bool active = true;
+ int iterations = 0;
- int island_count;
- int active_objects;
- int collision_pairs;
+ int island_count = 0;
+ int active_objects = 0;
+ int collision_pairs = 0;
- bool using_threads;
- bool doing_sync;
- bool flushing_queries;
+ bool using_threads = false;
+ bool doing_sync = false;
+ bool flushing_queries = false;
- Step3DSW *stepper;
+ Step3DSW *stepper = nullptr;
Set<const Space3DSW *> active_spaces;
- PhysicsDirectBodyState3DSW *direct_state;
-
mutable RID_PtrOwner<Shape3DSW, true> shape_owner;
mutable RID_PtrOwner<Space3DSW, true> space_owner;
mutable RID_PtrOwner<Area3DSW, true> area_owner;
@@ -82,7 +79,8 @@ public:
static void _shape_col_cbk(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata);
- virtual RID plane_shape_create() override;
+ virtual RID world_boundary_shape_create() override;
+ virtual RID separation_ray_shape_create() override;
virtual RID sphere_shape_create() override;
virtual RID box_shape_create() override;
virtual RID capsule_shape_create() override;
@@ -200,8 +198,10 @@ public:
virtual void body_set_user_flags(RID p_body, uint32_t p_flags) override;
virtual uint32_t body_get_user_flags(RID p_body) const override;
- virtual void body_set_param(RID p_body, BodyParameter p_param, real_t p_value) override;
- virtual real_t body_get_param(RID p_body, BodyParameter p_param) const override;
+ virtual void body_set_param(RID p_body, BodyParameter p_param, const Variant &p_value) override;
+ virtual Variant body_get_param(RID p_body, BodyParameter p_param) const override;
+
+ virtual void body_reset_mass_properties(RID p_body) override;
virtual void body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) override;
virtual Variant body_get_state(RID p_body, BodyState p_state) const override;
@@ -237,11 +237,12 @@ public:
virtual void body_set_max_contacts_reported(RID p_body, int p_contacts) override;
virtual int body_get_max_contacts_reported(RID p_body) const override;
+ virtual void body_set_state_sync_callback(RID p_body, void *p_instance, BodyStateCallback p_callback) override;
virtual void body_set_force_integration_callback(RID p_body, const Callable &p_callable, const Variant &p_udata = Variant()) override;
virtual void body_set_ray_pickable(RID p_body, bool p_enable) override;
- virtual bool body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin = 0.001, MotionResult *r_result = nullptr, const Set<RID> &p_exclude = Set<RID>()) override;
+ virtual bool body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result = nullptr) override;
// this function only works on physics process, errors and returns null otherwise
virtual PhysicsDirectBodyState3D *body_get_direct_state(RID p_body) override;
@@ -290,7 +291,7 @@ public:
virtual void soft_body_set_drag_coefficient(RID p_body, real_t p_drag_coefficient) override;
virtual real_t soft_body_get_drag_coefficient(RID p_body) const override;
- virtual void soft_body_set_mesh(RID p_body, const REF &p_mesh) override;
+ virtual void soft_body_set_mesh(RID p_body, RID p_mesh) override;
virtual AABB soft_body_get_bounds(RID p_body) const override;
diff --git a/servers/physics_3d/physics_server_3d_wrap_mt.cpp b/servers/physics_3d/physics_server_3d_wrap_mt.cpp
index 0a89c1a9c9..c424100bba 100644
--- a/servers/physics_3d/physics_server_3d_wrap_mt.cpp
+++ b/servers/physics_3d/physics_server_3d_wrap_mt.cpp
@@ -119,8 +119,6 @@ PhysicsServer3DWrapMT::PhysicsServer3DWrapMT(PhysicsServer3D *p_contained, bool
command_queue(p_create_thread) {
physics_3d_server = p_contained;
create_thread = p_create_thread;
- step_pending = 0;
- step_thread_up = false;
pool_max_size = GLOBAL_GET("memory/limits/multithreaded_server/rid_pool_prealloc");
@@ -131,7 +129,6 @@ PhysicsServer3DWrapMT::PhysicsServer3DWrapMT(PhysicsServer3D *p_contained, bool
}
main_thread = Thread::get_caller_id();
- first_frame = true;
}
PhysicsServer3DWrapMT::~PhysicsServer3DWrapMT() {
diff --git a/servers/physics_3d/physics_server_3d_wrap_mt.h b/servers/physics_3d/physics_server_3d_wrap_mt.h
index 75174628bf..17d02addda 100644
--- a/servers/physics_3d/physics_server_3d_wrap_mt.h
+++ b/servers/physics_3d/physics_server_3d_wrap_mt.h
@@ -58,7 +58,7 @@ class PhysicsServer3DWrapMT : public PhysicsServer3D {
bool create_thread = false;
Semaphore step_sem;
- int step_pending;
+ int step_pending = 0;
void thread_step(real_t p_delta);
void thread_flush();
@@ -78,7 +78,8 @@ public:
#include "servers/server_wrap_mt_common.h"
//FUNC1RID(shape,ShapeType); todo fix
- FUNCRID(plane_shape)
+ FUNCRID(world_boundary_shape)
+ FUNCRID(separation_ray_shape)
FUNCRID(sphere_shape)
FUNCRID(box_shape)
FUNCRID(capsule_shape)
@@ -209,8 +210,10 @@ public:
FUNC2(body_set_user_flags, RID, uint32_t);
FUNC1RC(uint32_t, body_get_user_flags, RID);
- FUNC3(body_set_param, RID, BodyParameter, real_t);
- FUNC2RC(real_t, body_get_param, RID, BodyParameter);
+ FUNC3(body_set_param, RID, BodyParameter, const Variant &);
+ FUNC2RC(Variant, body_get_param, RID, BodyParameter);
+
+ FUNC1(body_reset_mass_properties, RID);
FUNC3(body_set_state, RID, BodyState, const Variant &);
FUNC2RC(Variant, body_get_state, RID, BodyState);
@@ -245,13 +248,14 @@ public:
FUNC2(body_set_omit_force_integration, RID, bool);
FUNC1RC(bool, body_is_omitting_force_integration, RID);
+ FUNC3(body_set_state_sync_callback, RID, void *, BodyStateCallback);
FUNC3(body_set_force_integration_callback, RID, const Callable &, const Variant &);
FUNC2(body_set_ray_pickable, RID, bool);
- bool body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin = 0.001, MotionResult *r_result = nullptr, const Set<RID> &p_exclude = Set<RID>()) override {
+ bool body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result = nullptr) override {
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false);
- return physics_3d_server->body_test_motion(p_body, p_from, p_motion, p_margin, r_result, p_exclude);
+ return physics_3d_server->body_test_motion(p_body, p_parameters, r_result);
}
// this function only works on physics process, errors and returns null otherwise
@@ -304,7 +308,7 @@ public:
FUNC2(soft_body_set_drag_coefficient, RID, real_t);
FUNC1RC(real_t, soft_body_get_drag_coefficient, RID);
- FUNC2(soft_body_set_mesh, RID, const REF &);
+ FUNC2(soft_body_set_mesh, RID, RID);
FUNC1RC(AABB, soft_body_get_bounds, RID);
diff --git a/servers/physics_3d/shape_3d_sw.cpp b/servers/physics_3d/shape_3d_sw.cpp
index a84405de81..789fc6ab33 100644
--- a/servers/physics_3d/shape_3d_sw.cpp
+++ b/servers/physics_3d/shape_3d_sw.cpp
@@ -61,8 +61,8 @@ subject to the following restrictions:
void Shape3DSW::configure(const AABB &p_aabb) {
aabb = p_aabb;
configured = true;
- for (Map<ShapeOwner3DSW *, int>::Element *E = owners.front(); E; E = E->next()) {
- ShapeOwner3DSW *co = (ShapeOwner3DSW *)E->key();
+ for (const KeyValue<ShapeOwner3DSW *, int> &E : owners) {
+ ShapeOwner3DSW *co = (ShapeOwner3DSW *)E.key;
co->_shape_changed();
}
}
@@ -101,30 +101,25 @@ const Map<ShapeOwner3DSW *, int> &Shape3DSW::get_owners() const {
return owners;
}
-Shape3DSW::Shape3DSW() {
- custom_bias = 0;
- configured = false;
-}
-
Shape3DSW::~Shape3DSW() {
ERR_FAIL_COND(owners.size());
}
-Plane PlaneShape3DSW::get_plane() const {
+Plane WorldBoundaryShape3DSW::get_plane() const {
return plane;
}
-void PlaneShape3DSW::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const {
+void WorldBoundaryShape3DSW::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const {
// gibberish, a plane is infinity
r_min = -1e7;
r_max = 1e7;
}
-Vector3 PlaneShape3DSW::get_support(const Vector3 &p_normal) const {
+Vector3 WorldBoundaryShape3DSW::get_support(const Vector3 &p_normal) const {
return p_normal * 1e15;
}
-bool PlaneShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const {
+bool WorldBoundaryShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const {
bool inters = plane.intersects_segment(p_begin, p_end, &r_result);
if (inters) {
r_normal = plane.normal;
@@ -132,11 +127,11 @@ bool PlaneShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_
return inters;
}
-bool PlaneShape3DSW::intersect_point(const Vector3 &p_point) const {
+bool WorldBoundaryShape3DSW::intersect_point(const Vector3 &p_point) const {
return plane.distance_to(p_point) < 0;
}
-Vector3 PlaneShape3DSW::get_closest_point_to(const Vector3 &p_point) const {
+Vector3 WorldBoundaryShape3DSW::get_closest_point_to(const Vector3 &p_point) const {
if (plane.is_point_over(p_point)) {
return plane.project(p_point);
} else {
@@ -144,26 +139,108 @@ Vector3 PlaneShape3DSW::get_closest_point_to(const Vector3 &p_point) const {
}
}
-Vector3 PlaneShape3DSW::get_moment_of_inertia(real_t p_mass) const {
- return Vector3(); //wtf
+Vector3 WorldBoundaryShape3DSW::get_moment_of_inertia(real_t p_mass) const {
+ return Vector3(); // not applicable.
}
-void PlaneShape3DSW::_setup(const Plane &p_plane) {
+void WorldBoundaryShape3DSW::_setup(const Plane &p_plane) {
plane = p_plane;
configure(AABB(Vector3(-1e4, -1e4, -1e4), Vector3(1e4 * 2, 1e4 * 2, 1e4 * 2)));
}
-void PlaneShape3DSW::set_data(const Variant &p_data) {
+void WorldBoundaryShape3DSW::set_data(const Variant &p_data) {
_setup(p_data);
}
-Variant PlaneShape3DSW::get_data() const {
+Variant WorldBoundaryShape3DSW::get_data() const {
return plane;
}
-PlaneShape3DSW::PlaneShape3DSW() {
+WorldBoundaryShape3DSW::WorldBoundaryShape3DSW() {
+}
+
+//
+
+real_t SeparationRayShape3DSW::get_length() const {
+ return length;
+}
+
+bool SeparationRayShape3DSW::get_slide_on_slope() const {
+ return slide_on_slope;
+}
+
+void SeparationRayShape3DSW::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const {
+ // don't think this will be even used
+ r_min = 0;
+ r_max = 1;
+}
+
+Vector3 SeparationRayShape3DSW::get_support(const Vector3 &p_normal) const {
+ if (p_normal.z > 0) {
+ return Vector3(0, 0, length);
+ } else {
+ return Vector3(0, 0, 0);
+ }
+}
+
+void SeparationRayShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const {
+ if (Math::abs(p_normal.z) < _EDGE_IS_VALID_SUPPORT_THRESHOLD) {
+ r_amount = 2;
+ r_type = FEATURE_EDGE;
+ r_supports[0] = Vector3(0, 0, 0);
+ r_supports[1] = Vector3(0, 0, length);
+ } else if (p_normal.z > 0) {
+ r_amount = 1;
+ r_type = FEATURE_POINT;
+ *r_supports = Vector3(0, 0, length);
+ } else {
+ r_amount = 1;
+ r_type = FEATURE_POINT;
+ *r_supports = Vector3(0, 0, 0);
+ }
}
+bool SeparationRayShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const {
+ return false; //simply not possible
+}
+
+bool SeparationRayShape3DSW::intersect_point(const Vector3 &p_point) const {
+ return false; //simply not possible
+}
+
+Vector3 SeparationRayShape3DSW::get_closest_point_to(const Vector3 &p_point) const {
+ Vector3 s[2] = {
+ Vector3(0, 0, 0),
+ Vector3(0, 0, length)
+ };
+
+ return Geometry3D::get_closest_point_to_segment(p_point, s);
+}
+
+Vector3 SeparationRayShape3DSW::get_moment_of_inertia(real_t p_mass) const {
+ return Vector3();
+}
+
+void SeparationRayShape3DSW::_setup(real_t p_length, bool p_slide_on_slope) {
+ length = p_length;
+ slide_on_slope = p_slide_on_slope;
+ configure(AABB(Vector3(0, 0, 0), Vector3(0.1, 0.1, length)));
+}
+
+void SeparationRayShape3DSW::set_data(const Variant &p_data) {
+ Dictionary d = p_data;
+ _setup(d["length"], d["slide_on_slope"]);
+}
+
+Variant SeparationRayShape3DSW::get_data() const {
+ Dictionary d;
+ d["length"] = length;
+ d["slide_on_slope"] = slide_on_slope;
+ return d;
+}
+
+SeparationRayShape3DSW::SeparationRayShape3DSW() {}
+
/********** SPHERE *************/
real_t SphereShape3DSW::get_radius() const {
@@ -226,9 +303,7 @@ Variant SphereShape3DSW::get_data() const {
return radius;
}
-SphereShape3DSW::SphereShape3DSW() {
- radius = 0;
-}
+SphereShape3DSW::SphereShape3DSW() {}
/********** BOX *************/
@@ -417,8 +492,7 @@ Variant BoxShape3DSW::get_data() const {
return half_extents;
}
-BoxShape3DSW::BoxShape3DSW() {
-}
+BoxShape3DSW::BoxShape3DSW() {}
/********** CAPSULE *************/
@@ -583,9 +657,7 @@ Variant CapsuleShape3DSW::get_data() const {
return d;
}
-CapsuleShape3DSW::CapsuleShape3DSW() {
- height = radius = 0;
-}
+CapsuleShape3DSW::CapsuleShape3DSW() {}
/********** CYLINDER *************/
@@ -705,7 +777,7 @@ Vector3 CylinderShape3DSW::get_closest_point_to(const Vector3 &p_point) const {
// Project point to top disk.
real_t dir = p_point.y > 0.0 ? 1.0 : -1.0;
Vector3 circle_pos(0.0, dir * height * 0.5, 0.0);
- Plane circle_plane(circle_pos, Vector3(0.0, dir, 0.0));
+ Plane circle_plane(Vector3(0.0, dir, 0.0), circle_pos);
Vector3 proj_point = circle_plane.project(p_point);
// Clip position.
@@ -763,9 +835,7 @@ Variant CylinderShape3DSW::get_data() const {
return d;
}
-CylinderShape3DSW::CylinderShape3DSW() {
- height = radius = 0;
-}
+CylinderShape3DSW::CylinderShape3DSW() {}
/********** CONVEX POLYGON *************/
@@ -955,7 +1025,7 @@ Vector3 ConvexPolygonShape3DSW::get_closest_point_to(const Vector3 &p_point) con
Vector3 a = vertices[indices[j]];
Vector3 b = vertices[indices[(j + 1) % ic]];
Vector3 n = (a - b).cross(faces[i].plane.normal).normalized();
- if (Plane(a, n).is_point_over(p_point)) {
+ if (Plane(n, a).is_point_over(p_point)) {
is_inside = false;
break;
}
@@ -1297,11 +1367,11 @@ Vector3 ConcavePolygonShape3DSW::get_closest_point_to(const Vector3 &p_point) co
return Vector3();
}
-void ConcavePolygonShape3DSW::_cull(int p_idx, _CullParams *p_params) const {
+bool ConcavePolygonShape3DSW::_cull(int p_idx, _CullParams *p_params) const {
const BVH *bvh = &p_params->bvh[p_idx];
if (!p_params->aabb.intersects(bvh->aabb)) {
- return;
+ return false;
}
if (bvh->face_index >= 0) {
@@ -1311,20 +1381,27 @@ void ConcavePolygonShape3DSW::_cull(int p_idx, _CullParams *p_params) const {
face->vertex[0] = p_params->vertices[f->indices[0]];
face->vertex[1] = p_params->vertices[f->indices[1]];
face->vertex[2] = p_params->vertices[f->indices[2]];
- p_params->callback(p_params->userdata, face);
-
+ if (p_params->callback(p_params->userdata, face)) {
+ return true;
+ }
} else {
if (bvh->left >= 0) {
- _cull(bvh->left, p_params);
+ if (_cull(bvh->left, p_params)) {
+ return true;
+ }
}
if (bvh->right >= 0) {
- _cull(bvh->right, p_params);
+ if (_cull(bvh->right, p_params)) {
+ return true;
+ }
}
}
+
+ return false;
}
-void ConcavePolygonShape3DSW::cull(const AABB &p_local_aabb, Callback p_callback, void *p_userdata) const {
+void ConcavePolygonShape3DSW::cull(const AABB &p_local_aabb, QueryCallback p_callback, void *p_userdata) const {
// make matrix local to concave
if (faces.size() == 0) {
return;
@@ -1499,7 +1576,7 @@ void ConcavePolygonShape3DSW::_setup(const Vector<Vector3> &p_faces, bool p_back
Face3 face(facesr[i * 3 + 0], facesr[i * 3 + 1], facesr[i * 3 + 2]);
bvh_arrayw[i].aabb = face.get_aabb();
- bvh_arrayw[i].center = bvh_arrayw[i].aabb.position + bvh_arrayw[i].aabb.size * 0.5;
+ bvh_arrayw[i].center = bvh_arrayw[i].aabb.get_center();
bvh_arrayw[i].face_index = i;
facesw[i].indices[0] = i * 3 + 0;
facesw[i].indices[1] = i * 3 + 1;
@@ -1564,7 +1641,7 @@ int HeightMapShape3DSW::get_depth() const {
void HeightMapShape3DSW::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const {
//not very useful, but not very used either
- p_transform.xform(get_aabb()).project_range_in_plane(Plane(p_normal, 0), r_min, r_max);
+ p_transform.xform(get_aabb()).project_range_in_plane(Plane(p_normal), r_min, r_max);
}
Vector3 HeightMapShape3DSW::get_support(const Vector3 &p_normal) const {
@@ -1584,6 +1661,17 @@ struct _HeightmapSegmentCullParams {
FaceShape3DSW *face = nullptr;
};
+struct _HeightmapGridCullState {
+ real_t length = 0.0;
+ real_t length_flat = 0.0;
+
+ real_t dist = 0.0;
+ real_t prev_dist = 0.0;
+
+ int x = 0;
+ int z = 0;
+};
+
_FORCE_INLINE_ bool _heightmap_face_cull_segment(_HeightmapSegmentCullParams &p_params) {
Vector3 res;
Vector3 normal;
@@ -1596,11 +1684,11 @@ _FORCE_INLINE_ bool _heightmap_face_cull_segment(_HeightmapSegmentCullParams &p_
return false;
}
-_FORCE_INLINE_ bool _heightmap_cell_cull_segment(_HeightmapSegmentCullParams &p_params, int p_x, int p_z) {
+_FORCE_INLINE_ bool _heightmap_cell_cull_segment(_HeightmapSegmentCullParams &p_params, const _HeightmapGridCullState &p_state) {
// First triangle.
- p_params.heightmap->_get_point(p_x, p_z, p_params.face->vertex[0]);
- p_params.heightmap->_get_point(p_x + 1, p_z, p_params.face->vertex[1]);
- p_params.heightmap->_get_point(p_x, p_z + 1, p_params.face->vertex[2]);
+ p_params.heightmap->_get_point(p_state.x, p_state.z, p_params.face->vertex[0]);
+ p_params.heightmap->_get_point(p_state.x + 1, p_state.z, p_params.face->vertex[1]);
+ p_params.heightmap->_get_point(p_state.x, p_state.z + 1, p_params.face->vertex[2]);
p_params.face->normal = Plane(p_params.face->vertex[0], p_params.face->vertex[1], p_params.face->vertex[2]).normal;
if (_heightmap_face_cull_segment(p_params)) {
return true;
@@ -1608,7 +1696,7 @@ _FORCE_INLINE_ bool _heightmap_cell_cull_segment(_HeightmapSegmentCullParams &p_
// Second triangle.
p_params.face->vertex[0] = p_params.face->vertex[1];
- p_params.heightmap->_get_point(p_x + 1, p_z + 1, p_params.face->vertex[1]);
+ p_params.heightmap->_get_point(p_state.x + 1, p_state.z + 1, p_params.face->vertex[1]);
p_params.face->normal = Plane(p_params.face->vertex[0], p_params.face->vertex[1], p_params.face->vertex[2]).normal;
if (_heightmap_face_cull_segment(p_params)) {
return true;
@@ -1617,13 +1705,51 @@ _FORCE_INLINE_ bool _heightmap_cell_cull_segment(_HeightmapSegmentCullParams &p_
return false;
}
-bool HeightMapShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_point, Vector3 &r_normal) const {
- if (heights.is_empty()) {
+_FORCE_INLINE_ bool _heightmap_chunk_cull_segment(_HeightmapSegmentCullParams &p_params, const _HeightmapGridCullState &p_state) {
+ const HeightMapShape3DSW::Range &chunk = p_params.heightmap->_get_bounds_chunk(p_state.x, p_state.z);
+
+ Vector3 enter_pos;
+ Vector3 exit_pos;
+
+ if (p_state.length_flat > CMP_EPSILON) {
+ real_t flat_to_3d = p_state.length / p_state.length_flat;
+ real_t enter_param = p_state.prev_dist * flat_to_3d;
+ real_t exit_param = p_state.dist * flat_to_3d;
+ enter_pos = p_params.from + p_params.dir * enter_param;
+ exit_pos = p_params.from + p_params.dir * exit_param;
+ } else {
+ // Consider the ray vertical.
+ // (though we shouldn't reach this often because there is an early check up-front)
+ enter_pos = p_params.from;
+ exit_pos = p_params.to;
+ }
+
+ // Transform positions to heightmap space.
+ enter_pos *= HeightMapShape3DSW::BOUNDS_CHUNK_SIZE;
+ exit_pos *= HeightMapShape3DSW::BOUNDS_CHUNK_SIZE;
+
+ // We did enter the flat projection of the AABB,
+ // but we have to check if we intersect it on the vertical axis.
+ if ((enter_pos.y > chunk.max) && (exit_pos.y > chunk.max)) {
+ return false;
+ }
+ if ((enter_pos.y < chunk.min) && (exit_pos.y < chunk.min)) {
return false;
}
- Vector3 local_begin = p_begin + local_origin;
- Vector3 local_end = p_end + local_origin;
+ return p_params.heightmap->_intersect_grid_segment(_heightmap_cell_cull_segment, enter_pos, exit_pos, p_params.heightmap->width, p_params.heightmap->depth, p_params.heightmap->local_origin, p_params.result, p_params.normal);
+}
+
+template <typename ProcessFunction>
+bool HeightMapShape3DSW::_intersect_grid_segment(ProcessFunction &p_process, const Vector3 &p_begin, const Vector3 &p_end, int p_width, int p_depth, const Vector3 &offset, Vector3 &r_point, Vector3 &r_normal) const {
+ Vector3 delta = (p_end - p_begin);
+ real_t length = delta.length();
+
+ if (length < CMP_EPSILON) {
+ return false;
+ }
+
+ Vector3 local_begin = p_begin + offset;
FaceShape3DSW face;
face.backface_collision = false;
@@ -1631,136 +1757,181 @@ bool HeightMapShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3
_HeightmapSegmentCullParams params;
params.from = p_begin;
params.to = p_end;
- params.dir = (p_end - p_begin).normalized();
+ params.dir = delta / length;
params.heightmap = this;
params.face = &face;
- // Quantize the ray begin/end.
- int begin_x = floor(local_begin.x);
- int begin_z = floor(local_begin.z);
- int end_x = floor(local_end.x);
- int end_z = floor(local_end.z);
+ _HeightmapGridCullState state;
- if ((begin_x == end_x) && (begin_z == end_z)) {
- // Simple case for rays that don't traverse the grid horizontally.
- // Just perform a test on the given cell.
- int x = CLAMP(begin_x, 0, width - 2);
- int z = CLAMP(begin_z, 0, depth - 2);
- if (_heightmap_cell_cull_segment(params, x, z)) {
- r_point = params.result;
- r_normal = params.normal;
- return true;
- }
- } else {
- // Perform grid query from projected ray.
- Vector2 ray_dir_proj(local_end.x - local_begin.x, local_end.z - local_begin.z);
- real_t ray_dist_proj = ray_dir_proj.length();
+ // Perform grid query from projected ray.
+ Vector2 ray_dir_flat(delta.x, delta.z);
+ state.length = length;
+ state.length_flat = ray_dir_flat.length();
- if (ray_dist_proj < CMP_EPSILON) {
- ray_dir_proj = Vector2();
- } else {
- ray_dir_proj /= ray_dist_proj;
- }
+ if (state.length_flat < CMP_EPSILON) {
+ ray_dir_flat = Vector2();
+ } else {
+ ray_dir_flat /= state.length_flat;
+ }
- const int x_step = (ray_dir_proj.x > CMP_EPSILON) ? 1 : ((ray_dir_proj.x < -CMP_EPSILON) ? -1 : 0);
- const int z_step = (ray_dir_proj.y > CMP_EPSILON) ? 1 : ((ray_dir_proj.y < -CMP_EPSILON) ? -1 : 0);
+ const int x_step = (ray_dir_flat.x > CMP_EPSILON) ? 1 : ((ray_dir_flat.x < -CMP_EPSILON) ? -1 : 0);
+ const int z_step = (ray_dir_flat.y > CMP_EPSILON) ? 1 : ((ray_dir_flat.y < -CMP_EPSILON) ? -1 : 0);
- const real_t infinite = 1e20;
- const real_t delta_x = (x_step != 0) ? 1.f / Math::abs(ray_dir_proj.x) : infinite;
- const real_t delta_z = (z_step != 0) ? 1.f / Math::abs(ray_dir_proj.y) : infinite;
+ const real_t infinite = 1e20;
+ const real_t delta_x = (x_step != 0) ? 1.f / Math::abs(ray_dir_flat.x) : infinite;
+ const real_t delta_z = (z_step != 0) ? 1.f / Math::abs(ray_dir_flat.y) : infinite;
- real_t cross_x; // At which value of `param` we will cross a x-axis lane?
- real_t cross_z; // At which value of `param` we will cross a z-axis lane?
+ real_t cross_x; // At which value of `param` we will cross a x-axis lane?
+ real_t cross_z; // At which value of `param` we will cross a z-axis lane?
- // X initialization.
- if (x_step != 0) {
- if (x_step == 1) {
- cross_x = (ceil(local_begin.x) - local_begin.x) * delta_x;
- } else {
- cross_x = (local_begin.x - floor(local_begin.x)) * delta_x;
- }
+ // X initialization.
+ if (x_step != 0) {
+ if (x_step == 1) {
+ cross_x = (Math::ceil(local_begin.x) - local_begin.x) * delta_x;
} else {
- cross_x = infinite; // Will never cross on X.
+ cross_x = (local_begin.x - Math::floor(local_begin.x)) * delta_x;
}
+ } else {
+ cross_x = infinite; // Will never cross on X.
+ }
- // Z initialization.
- if (z_step != 0) {
- if (z_step == 1) {
- cross_z = (ceil(local_begin.z) - local_begin.z) * delta_z;
- } else {
- cross_z = (local_begin.z - floor(local_begin.z)) * delta_z;
- }
+ // Z initialization.
+ if (z_step != 0) {
+ if (z_step == 1) {
+ cross_z = (Math::ceil(local_begin.z) - local_begin.z) * delta_z;
} else {
- cross_z = infinite; // Will never cross on Z.
+ cross_z = (local_begin.z - Math::floor(local_begin.z)) * delta_z;
}
+ } else {
+ cross_z = infinite; // Will never cross on Z.
+ }
- int x = floor(local_begin.x);
- int z = floor(local_begin.z);
+ int x = Math::floor(local_begin.x);
+ int z = Math::floor(local_begin.z);
- // Workaround cases where the ray starts at an integer position.
- if (Math::is_zero_approx(cross_x)) {
- cross_x += delta_x;
- // If going backwards, we should ignore the position we would get by the above flooring,
- // because the ray is not heading in that direction.
- if (x_step == -1) {
- x -= 1;
- }
+ // Workaround cases where the ray starts at an integer position.
+ if (Math::is_zero_approx(cross_x)) {
+ cross_x += delta_x;
+ // If going backwards, we should ignore the position we would get by the above flooring,
+ // because the ray is not heading in that direction.
+ if (x_step == -1) {
+ x -= 1;
}
+ }
- if (Math::is_zero_approx(cross_z)) {
- cross_z += delta_z;
- if (z_step == -1) {
- z -= 1;
- }
+ if (Math::is_zero_approx(cross_z)) {
+ cross_z += delta_z;
+ if (z_step == -1) {
+ z -= 1;
}
+ }
+
+ // Start inside the grid.
+ int x_start = MAX(MIN(x, p_width - 2), 0);
+ int z_start = MAX(MIN(z, p_depth - 2), 0);
- // Start inside the grid.
- int x_start = CLAMP(x, 0, width - 2);
- int z_start = CLAMP(z, 0, depth - 2);
+ // Adjust initial cross values.
+ cross_x += delta_x * x_step * (x_start - x);
+ cross_z += delta_z * z_step * (z_start - z);
- // Adjust initial cross values.
- cross_x += delta_x * x_step * (x_start - x);
- cross_z += delta_z * z_step * (z_start - z);
+ x = x_start;
+ z = z_start;
- x = x_start;
- z = z_start;
+ while (true) {
+ state.prev_dist = state.dist;
+ state.x = x;
+ state.z = z;
- if (_heightmap_cell_cull_segment(params, x, z)) {
+ if (cross_x < cross_z) {
+ // X lane.
+ x += x_step;
+ // Assign before advancing the param,
+ // to be in sync with the initialization step.
+ state.dist = cross_x;
+ cross_x += delta_x;
+ } else {
+ // Z lane.
+ z += z_step;
+ state.dist = cross_z;
+ cross_z += delta_z;
+ }
+
+ if (state.dist > state.length_flat) {
+ state.dist = state.length_flat;
+ if (p_process(params, state)) {
+ r_point = params.result;
+ r_normal = params.normal;
+ return true;
+ }
+ break;
+ }
+
+ if (p_process(params, state)) {
r_point = params.result;
r_normal = params.normal;
return true;
}
- real_t dist = 0.0;
- while (true) {
- if (cross_x < cross_z) {
- // X lane.
- x += x_step;
- // Assign before advancing the param,
- // to be in sync with the initialization step.
- dist = cross_x;
- cross_x += delta_x;
- } else {
- // Z lane.
- z += z_step;
- dist = cross_z;
- cross_z += delta_z;
- }
+ // Stop when outside the grid.
+ if ((x < 0) || (z < 0) || (x >= p_width - 1) || (z >= p_depth - 1)) {
+ break;
+ }
+ }
- // Stop when outside the grid.
- if ((x < 0) || (z < 0) || (x >= width - 1) || (z >= depth - 1)) {
- break;
- }
+ return false;
+}
- if (_heightmap_cell_cull_segment(params, x, z)) {
- r_point = params.result;
- r_normal = params.normal;
- return true;
- }
+bool HeightMapShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_point, Vector3 &r_normal) const {
+ if (heights.is_empty()) {
+ return false;
+ }
- if (dist > ray_dist_proj) {
- break;
- }
+ Vector3 local_begin = p_begin + local_origin;
+ Vector3 local_end = p_end + local_origin;
+
+ // Quantize the ray begin/end.
+ int begin_x = Math::floor(local_begin.x);
+ int begin_z = Math::floor(local_begin.z);
+ int end_x = Math::floor(local_end.x);
+ int end_z = Math::floor(local_end.z);
+
+ if ((begin_x == end_x) && (begin_z == end_z)) {
+ // Simple case for rays that don't traverse the grid horizontally.
+ // Just perform a test on the given cell.
+ FaceShape3DSW face;
+ face.backface_collision = false;
+
+ _HeightmapSegmentCullParams params;
+ params.from = p_begin;
+ params.to = p_end;
+ params.dir = (p_end - p_begin).normalized();
+
+ params.heightmap = this;
+ params.face = &face;
+
+ _HeightmapGridCullState state;
+ state.x = MAX(MIN(begin_x, width - 2), 0);
+ state.z = MAX(MIN(begin_z, depth - 2), 0);
+ if (_heightmap_cell_cull_segment(params, state)) {
+ r_point = params.result;
+ r_normal = params.normal;
+ return true;
+ }
+ } else if (bounds_grid.is_empty()) {
+ // Process all cells intersecting the flat projection of the ray.
+ return _intersect_grid_segment(_heightmap_cell_cull_segment, p_begin, p_end, width, depth, local_origin, r_point, r_normal);
+ } else {
+ Vector3 ray_diff = (p_end - p_begin);
+ real_t length_flat_sqr = ray_diff.x * ray_diff.x + ray_diff.z * ray_diff.z;
+ if (length_flat_sqr < BOUNDS_CHUNK_SIZE * BOUNDS_CHUNK_SIZE) {
+ // Don't use chunks, the ray is too short in the plane.
+ return _intersect_grid_segment(_heightmap_cell_cull_segment, p_begin, p_end, width, depth, local_origin, r_point, r_normal);
+ } else {
+ // The ray is long, run raycast on a higher-level grid.
+ Vector3 bounds_from = p_begin / BOUNDS_CHUNK_SIZE;
+ Vector3 bounds_to = p_end / BOUNDS_CHUNK_SIZE;
+ Vector3 bounds_offset = local_origin / BOUNDS_CHUNK_SIZE;
+ return _intersect_grid_segment(_heightmap_chunk_cull_segment, bounds_from, bounds_to, bounds_grid_width, bounds_grid_depth, bounds_offset, r_point, r_normal);
}
}
@@ -1790,7 +1961,7 @@ void HeightMapShape3DSW::_get_cell(const Vector3 &p_point, int &r_x, int &r_y, i
r_z = (clamped_point.z < 0.0) ? (clamped_point.z - 0.5) : (clamped_point.z + 0.5);
}
-void HeightMapShape3DSW::cull(const AABB &p_local_aabb, Callback p_callback, void *p_userdata) const {
+void HeightMapShape3DSW::cull(const AABB &p_local_aabb, QueryCallback p_callback, void *p_userdata) const {
if (heights.is_empty()) {
return;
}
@@ -1825,14 +1996,18 @@ void HeightMapShape3DSW::cull(const AABB &p_local_aabb, Callback p_callback, voi
_get_point(x, z, face.vertex[0]);
_get_point(x + 1, z, face.vertex[1]);
_get_point(x, z + 1, face.vertex[2]);
- face.normal = Plane(face.vertex[0], face.vertex[2], face.vertex[1]).normal;
- p_callback(p_userdata, &face);
+ face.normal = Plane(face.vertex[0], face.vertex[1], face.vertex[2]).normal;
+ if (p_callback(p_userdata, &face)) {
+ return;
+ }
// Second triangle.
face.vertex[0] = face.vertex[1];
_get_point(x + 1, z + 1, face.vertex[1]);
- face.normal = Plane(face.vertex[0], face.vertex[2], face.vertex[1]).normal;
- p_callback(p_userdata, &face);
+ face.normal = Plane(face.vertex[0], face.vertex[1], face.vertex[2]).normal;
+ if (p_callback(p_userdata, &face)) {
+ return;
+ }
}
}
}
@@ -1847,6 +2022,75 @@ Vector3 HeightMapShape3DSW::get_moment_of_inertia(real_t p_mass) const {
(p_mass / 3.0) * (extents.x * extents.x + extents.y * extents.y));
}
+void HeightMapShape3DSW::_build_accelerator() {
+ bounds_grid.clear();
+
+ bounds_grid_width = width / BOUNDS_CHUNK_SIZE;
+ bounds_grid_depth = depth / BOUNDS_CHUNK_SIZE;
+
+ if (width % BOUNDS_CHUNK_SIZE > 0) {
+ ++bounds_grid_width; // In case terrain size isn't dividable by chunk size.
+ }
+
+ if (depth % BOUNDS_CHUNK_SIZE > 0) {
+ ++bounds_grid_depth;
+ }
+
+ uint32_t bound_grid_size = (uint32_t)(bounds_grid_width * bounds_grid_depth);
+
+ if (bound_grid_size < 2) {
+ // Grid is empty or just one chunk.
+ return;
+ }
+
+ bounds_grid.resize(bound_grid_size);
+
+ // Compute min and max height for all chunks.
+ for (int cz = 0; cz < bounds_grid_depth; ++cz) {
+ int z0 = cz * BOUNDS_CHUNK_SIZE;
+
+ for (int cx = 0; cx < bounds_grid_width; ++cx) {
+ int x0 = cx * BOUNDS_CHUNK_SIZE;
+
+ Range r;
+
+ r.min = _get_height(x0, z0);
+ r.max = r.min;
+
+ // Compute min and max height for this chunk.
+ // We have to include one extra cell to account for neighbors.
+ // Here is why:
+ // Say we have a flat terrain, and a plateau that fits a chunk perfectly.
+ //
+ // Left Right
+ // 0---0---0---1---1---1
+ // | | | | | |
+ // 0---0---0---1---1---1
+ // | | | | | |
+ // 0---0---0---1---1---1
+ // x
+ //
+ // If the AABB for the Left chunk did not share vertices with the Right,
+ // then we would fail collision tests at x due to a gap.
+ //
+ int z_max = MIN(z0 + BOUNDS_CHUNK_SIZE + 1, depth);
+ int x_max = MIN(x0 + BOUNDS_CHUNK_SIZE + 1, width);
+ for (int z = z0; z < z_max; ++z) {
+ for (int x = x0; x < x_max; ++x) {
+ real_t height = _get_height(x, z);
+ if (height < r.min) {
+ r.min = height;
+ } else if (height > r.max) {
+ r.max = height;
+ }
+ }
+ }
+
+ bounds_grid[cx + cz * bounds_grid_width] = r;
+ }
+ }
+}
+
void HeightMapShape3DSW::_setup(const Vector<real_t> &p_heights, int p_width, int p_depth, real_t p_min_height, real_t p_max_height) {
heights = p_heights;
width = p_width;
@@ -1863,6 +2107,8 @@ void HeightMapShape3DSW::_setup(const Vector<real_t> &p_heights, int p_width, in
aabb.position -= local_origin;
+ _build_accelerator();
+
configure(aabb);
}
@@ -1921,7 +2167,7 @@ void HeightMapShape3DSW::set_data(const Variant &p_data) {
} else {
int heights_size = heights.size();
for (int i = 0; i < heights_size; ++i) {
- float h = heights[i];
+ real_t h = heights[i];
if (h < min_height) {
min_height = h;
} else if (h > max_height) {
diff --git a/servers/physics_3d/shape_3d_sw.h b/servers/physics_3d/shape_3d_sw.h
index ca58900111..061d66a085 100644
--- a/servers/physics_3d/shape_3d_sw.h
+++ b/servers/physics_3d/shape_3d_sw.h
@@ -32,6 +32,7 @@
#define SHAPE_SW_H
#include "core/math/geometry_3d.h"
+#include "core/templates/local_vector.h"
#include "servers/physics_server_3d.h"
class Shape3DSW;
@@ -47,8 +48,8 @@ public:
class Shape3DSW {
RID self;
AABB aabb;
- bool configured;
- real_t custom_bias;
+ bool configured = false;
+ real_t custom_bias = 0.0;
Map<ShapeOwner3DSW *, int> owners;
@@ -94,22 +95,24 @@ public:
bool is_owner(ShapeOwner3DSW *p_owner) const;
const Map<ShapeOwner3DSW *, int> &get_owners() const;
- Shape3DSW();
+ Shape3DSW() {}
virtual ~Shape3DSW();
};
class ConcaveShape3DSW : public Shape3DSW {
public:
virtual bool is_concave() const override { return true; }
- typedef void (*Callback)(void *p_userdata, Shape3DSW *p_convex);
virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const override { r_amount = 0; }
- virtual void cull(const AABB &p_local_aabb, Callback p_callback, void *p_userdata) const = 0;
+ // Returns true to stop the query.
+ typedef bool (*QueryCallback)(void *p_userdata, Shape3DSW *p_convex);
+
+ virtual void cull(const AABB &p_local_aabb, QueryCallback p_callback, void *p_userdata) const = 0;
ConcaveShape3DSW() {}
};
-class PlaneShape3DSW : public Shape3DSW {
+class WorldBoundaryShape3DSW : public Shape3DSW {
Plane plane;
void _setup(const Plane &p_plane);
@@ -117,25 +120,53 @@ class PlaneShape3DSW : public Shape3DSW {
public:
Plane get_plane() const;
- virtual real_t get_area() const { return INFINITY; }
- virtual PhysicsServer3D::ShapeType get_type() const { return PhysicsServer3D::SHAPE_PLANE; }
- virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const;
- virtual Vector3 get_support(const Vector3 &p_normal) const;
- virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const { r_amount = 0; }
+ virtual real_t get_area() const override { return INFINITY; }
+ virtual PhysicsServer3D::ShapeType get_type() const override { return PhysicsServer3D::SHAPE_WORLD_BOUNDARY; }
+ virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const override;
+ virtual Vector3 get_support(const Vector3 &p_normal) const override;
+ virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const override { r_amount = 0; }
- virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const;
- virtual bool intersect_point(const Vector3 &p_point) const;
- virtual Vector3 get_closest_point_to(const Vector3 &p_point) const;
- virtual Vector3 get_moment_of_inertia(real_t p_mass) const;
+ virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const override;
+ virtual bool intersect_point(const Vector3 &p_point) const override;
+ virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override;
+ virtual Vector3 get_moment_of_inertia(real_t p_mass) const override;
- virtual void set_data(const Variant &p_data);
- virtual Variant get_data() const;
+ virtual void set_data(const Variant &p_data) override;
+ virtual Variant get_data() const override;
- PlaneShape3DSW();
+ WorldBoundaryShape3DSW();
+};
+
+class SeparationRayShape3DSW : public Shape3DSW {
+ real_t length = 1.0;
+ bool slide_on_slope = false;
+
+ void _setup(real_t p_length, bool p_slide_on_slope);
+
+public:
+ real_t get_length() const;
+ bool get_slide_on_slope() const;
+
+ virtual real_t get_area() const override { return 0.0; }
+ virtual PhysicsServer3D::ShapeType get_type() const override { return PhysicsServer3D::SHAPE_SEPARATION_RAY; }
+ virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const override;
+ virtual Vector3 get_support(const Vector3 &p_normal) const override;
+ virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const override;
+
+ virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const override;
+ virtual bool intersect_point(const Vector3 &p_point) const override;
+ virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override;
+
+ virtual Vector3 get_moment_of_inertia(real_t p_mass) const override;
+
+ virtual void set_data(const Variant &p_data) override;
+ virtual Variant get_data() const override;
+
+ SeparationRayShape3DSW();
};
class SphereShape3DSW : public Shape3DSW {
- real_t radius;
+ real_t radius = 0.0;
void _setup(real_t p_radius);
@@ -187,8 +218,8 @@ public:
};
class CapsuleShape3DSW : public Shape3DSW {
- real_t height;
- real_t radius;
+ real_t height = 0.0;
+ real_t radius = 0.0;
void _setup(real_t p_height, real_t p_radius);
@@ -216,8 +247,8 @@ public:
};
class CylinderShape3DSW : public Shape3DSW {
- real_t height;
- real_t radius;
+ real_t height = 0.0;
+ real_t radius = 0.0;
void _setup(real_t p_height, real_t p_radius);
@@ -277,7 +308,7 @@ struct ConcavePolygonShape3DSW : public ConcaveShape3DSW {
struct Face {
Vector3 normal;
- int indices[3];
+ int indices[3] = {};
};
Vector<Face> faces;
@@ -285,17 +316,17 @@ struct ConcavePolygonShape3DSW : public ConcaveShape3DSW {
struct BVH {
AABB aabb;
- int left;
- int right;
+ int left = 0;
+ int right = 0;
- int face_index;
+ int face_index = 0;
};
Vector<BVH> bvh;
struct _CullParams {
AABB aabb;
- Callback callback = nullptr;
+ QueryCallback callback = nullptr;
void *userdata = nullptr;
const Face *faces = nullptr;
const Vector3 *vertices = nullptr;
@@ -321,7 +352,7 @@ struct ConcavePolygonShape3DSW : public ConcaveShape3DSW {
bool backface_collision = false;
void _cull_segment(int p_idx, _SegmentCullParams *p_params) const;
- void _cull(int p_idx, _CullParams *p_params) const;
+ bool _cull(int p_idx, _CullParams *p_params) const;
void _fill_bvh(_VolumeSW_BVH *p_bvh_tree, BVH *p_bvh_array, int &p_idx);
@@ -339,7 +370,7 @@ public:
virtual bool intersect_point(const Vector3 &p_point) const override;
virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override;
- virtual void cull(const AABB &p_local_aabb, Callback p_callback, void *p_userdata) const override;
+ virtual void cull(const AABB &p_local_aabb, QueryCallback p_callback, void *p_userdata) const override;
virtual Vector3 get_moment_of_inertia(real_t p_mass) const override;
@@ -355,6 +386,21 @@ struct HeightMapShape3DSW : public ConcaveShape3DSW {
int depth = 0;
Vector3 local_origin;
+ // Accelerator.
+ struct Range {
+ real_t min = 0.0;
+ real_t max = 0.0;
+ };
+ LocalVector<Range> bounds_grid;
+ int bounds_grid_width = 0;
+ int bounds_grid_depth = 0;
+
+ static const int BOUNDS_CHUNK_SIZE = 16;
+
+ _FORCE_INLINE_ const Range &_get_bounds_chunk(int p_x, int p_z) const {
+ return bounds_grid[(p_z * bounds_grid_width) + p_x];
+ }
+
_FORCE_INLINE_ real_t _get_height(int p_x, int p_z) const {
return heights[(p_z * width) + p_x];
}
@@ -367,6 +413,11 @@ struct HeightMapShape3DSW : public ConcaveShape3DSW {
void _get_cell(const Vector3 &p_point, int &r_x, int &r_y, int &r_z) const;
+ void _build_accelerator();
+
+ template <typename ProcessFunction>
+ bool _intersect_grid_segment(ProcessFunction &p_process, const Vector3 &p_begin, const Vector3 &p_end, int p_width, int p_depth, const Vector3 &offset, Vector3 &r_point, Vector3 &r_normal) const;
+
void _setup(const Vector<real_t> &p_heights, int p_width, int p_depth, real_t p_min_height, real_t p_max_height);
public:
@@ -382,7 +433,7 @@ public:
virtual bool intersect_point(const Vector3 &p_point) const override;
virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override;
- virtual void cull(const AABB &p_local_aabb, Callback p_callback, void *p_userdata) const override;
+ virtual void cull(const AABB &p_local_aabb, QueryCallback p_callback, void *p_userdata) const override;
virtual Vector3 get_moment_of_inertia(real_t p_mass) const override;
@@ -418,7 +469,7 @@ struct FaceShape3DSW : public Shape3DSW {
};
struct MotionShape3DSW : public Shape3DSW {
- Shape3DSW *shape;
+ Shape3DSW *shape = nullptr;
Vector3 motion;
virtual PhysicsServer3D::ShapeType get_type() const override { return PhysicsServer3D::SHAPE_CONVEX_POLYGON; }
diff --git a/servers/physics_3d/soft_body_3d_sw.cpp b/servers/physics_3d/soft_body_3d_sw.cpp
index 73b81444e1..c9166810fe 100644
--- a/servers/physics_3d/soft_body_3d_sw.cpp
+++ b/servers/physics_3d/soft_body_3d_sw.cpp
@@ -33,6 +33,7 @@
#include "core/math/geometry_3d.h"
#include "core/templates/map.h"
+#include "servers/rendering_server.h"
// Based on Bullet soft body.
@@ -127,7 +128,7 @@ void SoftBody3DSW::set_space(Space3DSW *p_space) {
}
}
-void SoftBody3DSW::set_mesh(const Ref<Mesh> &p_mesh) {
+void SoftBody3DSW::set_mesh(RID p_mesh) {
destroy();
soft_mesh = p_mesh;
@@ -136,13 +137,11 @@ void SoftBody3DSW::set_mesh(const Ref<Mesh> &p_mesh) {
return;
}
- Array arrays = soft_mesh->surface_get_arrays(0);
- ERR_FAIL_COND(!(soft_mesh->surface_get_format(0) & RS::ARRAY_FORMAT_INDEX));
+ Array arrays = RenderingServer::get_singleton()->mesh_surface_get_arrays(soft_mesh, 0);
- bool success = create_from_trimesh(arrays[RS::ARRAY_INDEX], arrays[RS::ARRAY_VERTEX]);
+ bool success = create_from_trimesh(arrays[RenderingServer::ARRAY_INDEX], arrays[RenderingServer::ARRAY_VERTEX]);
if (!success) {
destroy();
- soft_mesh = Ref<Mesh>();
}
}
@@ -165,7 +164,7 @@ void SoftBody3DSW::update_rendering_server(RenderingServerHandler *p_rendering_s
p_rendering_server_handler->set_aabb(bounds);
}
-void SoftBody3DSW::update_normals() {
+void SoftBody3DSW::update_normals_and_centroids() {
uint32_t i, ni;
for (i = 0, ni = nodes.size(); i < ni; ++i) {
@@ -180,6 +179,7 @@ void SoftBody3DSW::update_normals() {
face.n[2]->n += n;
face.normal = n;
face.normal.normalize();
+ face.centroid = 0.33333333333 * (face.n[0]->x + face.n[1]->x + face.n[2]->x);
}
for (i = 0, ni = nodes.size(); i < ni; ++i) {
@@ -248,8 +248,10 @@ void SoftBody3DSW::update_area() {
// Node area.
LocalVector<int> counts;
- counts.resize(nodes.size());
- memset(counts.ptr(), 0, counts.size() * sizeof(int));
+ if (nodes.size() > 0) {
+ counts.resize(nodes.size());
+ memset(counts.ptr(), 0, counts.size() * sizeof(int));
+ }
for (i = 0, ni = nodes.size(); i < ni; ++i) {
nodes[i].area = 0.0;
@@ -310,17 +312,19 @@ void SoftBody3DSW::apply_nodes_transform(const Transform3D &p_transform) {
face_tree.clear();
- update_normals();
+ update_normals_and_centroids();
update_bounds();
update_constants();
}
Vector3 SoftBody3DSW::get_vertex_position(int p_index) const {
+ ERR_FAIL_COND_V(p_index < 0, Vector3());
+
if (soft_mesh.is_null()) {
return Vector3();
}
- ERR_FAIL_INDEX_V(p_index, (int)map_visual_to_physics.size(), Vector3());
+ ERR_FAIL_COND_V(p_index >= (int)map_visual_to_physics.size(), Vector3());
uint32_t node_index = map_visual_to_physics[p_index];
ERR_FAIL_COND_V(node_index >= nodes.size(), Vector3());
@@ -328,11 +332,13 @@ Vector3 SoftBody3DSW::get_vertex_position(int p_index) const {
}
void SoftBody3DSW::set_vertex_position(int p_index, const Vector3 &p_position) {
+ ERR_FAIL_COND(p_index < 0);
+
if (soft_mesh.is_null()) {
return;
}
- ERR_FAIL_INDEX(p_index, (int)map_visual_to_physics.size());
+ ERR_FAIL_COND(p_index >= (int)map_visual_to_physics.size());
uint32_t node_index = map_visual_to_physics[p_index];
ERR_FAIL_COND(node_index >= nodes.size());
@@ -342,6 +348,8 @@ void SoftBody3DSW::set_vertex_position(int p_index, const Vector3 &p_position) {
}
void SoftBody3DSW::pin_vertex(int p_index) {
+ ERR_FAIL_COND(p_index < 0);
+
if (is_vertex_pinned(p_index)) {
return;
}
@@ -349,7 +357,7 @@ void SoftBody3DSW::pin_vertex(int p_index) {
pinned_vertices.push_back(p_index);
if (!soft_mesh.is_null()) {
- ERR_FAIL_INDEX(p_index, (int)map_visual_to_physics.size());
+ ERR_FAIL_COND(p_index >= (int)map_visual_to_physics.size());
uint32_t node_index = map_visual_to_physics[p_index];
ERR_FAIL_COND(node_index >= nodes.size());
@@ -359,13 +367,15 @@ void SoftBody3DSW::pin_vertex(int p_index) {
}
void SoftBody3DSW::unpin_vertex(int p_index) {
+ ERR_FAIL_COND(p_index < 0);
+
uint32_t pinned_count = pinned_vertices.size();
for (uint32_t i = 0; i < pinned_count; ++i) {
if (p_index == pinned_vertices[i]) {
pinned_vertices.remove(i);
if (!soft_mesh.is_null()) {
- ERR_FAIL_INDEX(p_index, (int)map_visual_to_physics.size());
+ ERR_FAIL_COND(p_index >= (int)map_visual_to_physics.size());
uint32_t node_index = map_visual_to_physics[p_index];
ERR_FAIL_COND(node_index >= nodes.size());
@@ -385,10 +395,10 @@ void SoftBody3DSW::unpin_all_vertices() {
real_t inv_node_mass = nodes.size() * inv_total_mass;
uint32_t pinned_count = pinned_vertices.size();
for (uint32_t i = 0; i < pinned_count; ++i) {
- uint32_t vertex_index = pinned_vertices[i];
+ int pinned_vertex = pinned_vertices[i];
- ERR_CONTINUE(vertex_index >= map_visual_to_physics.size());
- uint32_t node_index = map_visual_to_physics[vertex_index];
+ ERR_CONTINUE(pinned_vertex >= (int)map_visual_to_physics.size());
+ uint32_t node_index = map_visual_to_physics[pinned_vertex];
ERR_CONTINUE(node_index >= nodes.size());
Node &node = nodes[node_index];
@@ -400,6 +410,8 @@ void SoftBody3DSW::unpin_all_vertices() {
}
bool SoftBody3DSW::is_vertex_pinned(int p_index) const {
+ ERR_FAIL_COND_V(p_index < 0, false);
+
uint32_t pinned_count = pinned_vertices.size();
for (uint32_t i = 0; i < pinned_count; ++i) {
if (p_index == pinned_vertices[i]) {
@@ -464,6 +476,9 @@ Vector3 SoftBody3DSW::get_face_normal(uint32_t p_face_index) const {
}
bool SoftBody3DSW::create_from_trimesh(const Vector<int> &p_indices, const Vector<Vector3> &p_vertices) {
+ ERR_FAIL_COND_V(p_indices.is_empty(), false);
+ ERR_FAIL_COND_V(p_vertices.is_empty(), false);
+
uint32_t node_count = 0;
LocalVector<Vector3> vertices;
const int visual_vertex_count(p_vertices.size());
@@ -574,7 +589,7 @@ bool SoftBody3DSW::create_from_trimesh(const Vector<int> &p_indices, const Vecto
reoptimize_link_order();
update_constants();
- update_normals();
+ update_normals_and_centroids();
update_bounds();
return true;
@@ -898,47 +913,86 @@ void SoftBody3DSW::add_velocity(const Vector3 &p_velocity) {
}
}
-void SoftBody3DSW::apply_forces() {
- if (pressure_coefficient < CMP_EPSILON) {
- return;
- }
+void SoftBody3DSW::apply_forces(bool p_has_wind_forces) {
+ int ac = areas.size();
if (nodes.is_empty()) {
return;
}
uint32_t i, ni;
+ int32_t j;
- // Calculate volume.
real_t volume = 0.0;
const Vector3 &org = nodes[0].x;
+
+ // Iterate over faces (try not to iterate elsewhere if possible).
for (i = 0, ni = faces.size(); i < ni; ++i) {
+ bool stopped = false;
const Face &face = faces[i];
+
+ Vector3 wind_force(0, 0, 0);
+
+ // Compute volume.
volume += vec3_dot(face.n[0]->x - org, vec3_cross(face.n[1]->x - org, face.n[2]->x - org));
+
+ // Compute nodal forces from area winds.
+ if (ac && p_has_wind_forces) {
+ const AreaCMP *aa = &areas[0];
+ for (j = ac - 1; j >= 0 && !stopped; j--) {
+ PhysicsServer3D::AreaSpaceOverrideMode mode = aa[j].area->get_space_override_mode();
+ switch (mode) {
+ case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE:
+ case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: {
+ wind_force += _compute_area_windforce(aa[j].area, &face);
+ stopped = mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE;
+ } break;
+ case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE:
+ case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: {
+ wind_force = _compute_area_windforce(aa[j].area, &face);
+ stopped = mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE;
+ } break;
+ default: {
+ }
+ }
+ }
+
+ for (j = 0; j < 3; j++) {
+ Node *current_node = face.n[j];
+ current_node->f += wind_force;
+ }
+ }
}
volume /= 6.0;
- // Apply per node forces.
- real_t ivolumetp = 1.0 / Math::abs(volume) * pressure_coefficient;
- for (i = 0, ni = nodes.size(); i < ni; ++i) {
- Node &node = nodes[i];
- if (node.im > 0) {
- node.f += node.n * (node.area * ivolumetp);
+ // Apply nodal pressure forces.
+ if (pressure_coefficient > CMP_EPSILON) {
+ real_t ivolumetp = 1.0 / Math::abs(volume) * pressure_coefficient;
+ for (i = 0, ni = nodes.size(); i < ni; ++i) {
+ Node &node = nodes[i];
+ if (node.im > 0) {
+ node.f += node.n * (node.area * ivolumetp);
+ }
}
}
}
void SoftBody3DSW::_compute_area_gravity(const Area3DSW *p_area) {
- if (p_area->is_gravity_point()) {
- if (p_area->get_gravity_distance_scale() > 0) {
- Vector3 v = p_area->get_transform().xform(p_area->get_gravity_vector()) - get_transform().get_origin();
- gravity += v.normalized() * (p_area->get_gravity() / Math::pow(v.length() * p_area->get_gravity_distance_scale() + 1, 2));
- } else {
- gravity += (p_area->get_transform().xform(p_area->get_gravity_vector()) - get_transform().get_origin()).normalized() * p_area->get_gravity();
- }
- } else {
- gravity += p_area->get_gravity_vector() * p_area->get_gravity();
- }
+ Vector3 area_gravity;
+ p_area->compute_gravity(get_transform().get_origin(), area_gravity);
+ gravity += area_gravity;
+}
+
+Vector3 SoftBody3DSW::_compute_area_windforce(const Area3DSW *p_area, const Face *p_face) {
+ real_t wfm = p_area->get_wind_force_magnitude();
+ real_t waf = p_area->get_wind_attenuation_factor();
+ const Vector3 &wd = p_area->get_wind_direction();
+ const Vector3 &ws = p_area->get_wind_source();
+ real_t projection_on_tri_normal = vec3_dot(p_face->normal, wd);
+ real_t projection_toward_centroid = vec3_dot(p_face->centroid - ws, wd);
+ real_t attenuation_over_distance = pow(projection_toward_centroid, -waf);
+ real_t nodal_force_magnitude = wfm * 0.33333333333 * p_face->ra * projection_on_tri_normal * attenuation_over_distance;
+ return nodal_force_magnitude * p_face->normal;
}
void SoftBody3DSW::predict_motion(real_t p_delta) {
@@ -952,11 +1006,15 @@ void SoftBody3DSW::predict_motion(real_t p_delta) {
int ac = areas.size();
bool stopped = false;
+ bool has_wind_forces = false;
if (ac) {
areas.sort();
const AreaCMP *aa = &areas[0];
for (int i = ac - 1; i >= 0 && !stopped; i--) {
+ // Avoids unnecessary loop in apply_forces().
+ has_wind_forces = has_wind_forces || aa[i].area->get_wind_force_magnitude() > CMP_EPSILON;
+
PhysicsServer3D::AreaSpaceOverrideMode mode = aa[i].area->get_space_override_mode();
switch (mode) {
case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE:
@@ -978,7 +1036,9 @@ void SoftBody3DSW::predict_motion(real_t p_delta) {
// Apply forces.
add_velocity(gravity * p_delta);
- apply_forces();
+ if (pressure_coefficient > CMP_EPSILON || has_wind_forces) {
+ apply_forces(has_wind_forces);
+ }
// Avoid soft body from 'exploding' so use some upper threshold of maximum motion
// that a node can travel per frame.
@@ -1057,7 +1117,7 @@ void SoftBody3DSW::solve_constraints(real_t p_delta) {
node.q = node.x;
}
- update_normals();
+ update_normals_and_centroids();
}
void SoftBody3DSW::solve_links(real_t kst, real_t ti) {
@@ -1179,6 +1239,8 @@ void SoftBody3DSW::deinitialize_shape() {
}
void SoftBody3DSW::destroy() {
+ soft_mesh = RID();
+
map_visual_to_physics.clear();
node_tree.clear();
diff --git a/servers/physics_3d/soft_body_3d_sw.h b/servers/physics_3d/soft_body_3d_sw.h
index be0620c506..7d4b83d0ee 100644
--- a/servers/physics_3d/soft_body_3d_sw.h
+++ b/servers/physics_3d/soft_body_3d_sw.h
@@ -40,12 +40,11 @@
#include "core/templates/local_vector.h"
#include "core/templates/set.h"
#include "core/templates/vset.h"
-#include "scene/resources/mesh.h"
class Constraint3DSW;
class SoftBody3DSW : public CollisionObject3DSW {
- Ref<Mesh> soft_mesh;
+ RID soft_mesh;
struct Node {
Vector3 s; // Source position
@@ -71,6 +70,7 @@ class SoftBody3DSW : public CollisionObject3DSW {
};
struct Face {
+ Vector3 centroid;
Node *n[3] = { nullptr, nullptr, nullptr }; // Node pointers
Vector3 normal; // Normal
real_t ra = 0.0; // Rest area
@@ -114,6 +114,7 @@ class SoftBody3DSW : public CollisionObject3DSW {
uint64_t island_step = 0;
_FORCE_INLINE_ void _compute_area_gravity(const Area3DSW *p_area);
+ _FORCE_INLINE_ Vector3 _compute_area_windforce(const Area3DSW *p_area, const Face *p_face);
public:
SoftBody3DSW();
@@ -157,7 +158,7 @@ public:
virtual void set_space(Space3DSW *p_space);
- void set_mesh(const Ref<Mesh> &p_mesh);
+ void set_mesh(RID p_mesh);
void update_rendering_server(RenderingServerHandler *p_rendering_server_handler);
@@ -220,7 +221,7 @@ protected:
virtual void _shapes_changed();
private:
- void update_normals();
+ void update_normals_and_centroids();
void update_bounds();
void update_constants();
void update_area();
@@ -231,7 +232,7 @@ private:
void add_velocity(const Vector3 &p_velocity);
- void apply_forces();
+ void apply_forces(bool p_has_wind_forces);
bool create_from_trimesh(const Vector<int> &p_indices, const Vector<Vector3> &p_vertices);
void generate_bending_constraints(int p_distance);
diff --git a/servers/physics_3d/space_3d_sw.cpp b/servers/physics_3d/space_3d_sw.cpp
index f9e55ad525..c88747c017 100644
--- a/servers/physics_3d/space_3d_sw.cpp
+++ b/servers/physics_3d/space_3d_sw.cpp
@@ -34,6 +34,8 @@
#include "core/config/project_settings.h"
#include "physics_server_3d_sw.h"
+#define TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR 0.05
+
_FORCE_INLINE_ static bool _can_collide_with(CollisionObject3DSW *p_object, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
if (!(p_object->get_collision_layer() & p_collision_mask)) {
return false;
@@ -185,7 +187,7 @@ int PhysicsDirectSpaceState3DSW::intersect_shape(const RID &p_shape, const Trans
return 0;
}
- Shape3DSW *shape = PhysicsServer3DSW::singletonsw->shape_owner.getornull(p_shape);
+ Shape3DSW *shape = PhysicsServer3DSW::singletonsw->shape_owner.get_or_null(p_shape);
ERR_FAIL_COND_V(!shape, 0);
AABB aabb = p_xform.xform(shape->get_aabb());
@@ -236,7 +238,7 @@ int PhysicsDirectSpaceState3DSW::intersect_shape(const RID &p_shape, const Trans
}
bool PhysicsDirectSpaceState3DSW::cast_motion(const RID &p_shape, const Transform3D &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, ShapeRestInfo *r_info) {
- Shape3DSW *shape = PhysicsServer3DSW::singletonsw->shape_owner.getornull(p_shape);
+ Shape3DSW *shape = PhysicsServer3DSW::singletonsw->shape_owner.get_or_null(p_shape);
ERR_FAIL_COND_V(!shape, false);
AABB aabb = p_xform.xform(shape->get_aabb());
@@ -359,7 +361,7 @@ bool PhysicsDirectSpaceState3DSW::collide_shape(RID p_shape, const Transform3D &
return false;
}
- Shape3DSW *shape = PhysicsServer3DSW::singletonsw->shape_owner.getornull(p_shape);
+ Shape3DSW *shape = PhysicsServer3DSW::singletonsw->shape_owner.get_or_null(p_shape);
ERR_FAIL_COND_V(!shape, 0);
AABB aabb = p_shape_xform.xform(shape->get_aabb());
@@ -401,17 +403,27 @@ bool PhysicsDirectSpaceState3DSW::collide_shape(RID p_shape, const Transform3D &
return collided;
}
+struct _RestResultData {
+ const CollisionObject3DSW *object = nullptr;
+ int local_shape = 0;
+ int shape = 0;
+ Vector3 contact;
+ Vector3 normal;
+ real_t len = 0.0;
+};
+
struct _RestCallbackData {
- const CollisionObject3DSW *object;
- const CollisionObject3DSW *best_object;
- int local_shape;
- int best_local_shape;
- int shape;
- int best_shape;
- Vector3 best_contact;
- Vector3 best_normal;
- real_t best_len;
- real_t min_allowed_depth;
+ const CollisionObject3DSW *object = nullptr;
+ int local_shape = 0;
+ int shape = 0;
+
+ real_t min_allowed_depth = 0.0;
+
+ _RestResultData best_result;
+
+ int max_results = 0;
+ int result_count = 0;
+ _RestResultData *other_results = nullptr;
};
static void _rest_cbk_result(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) {
@@ -422,32 +434,71 @@ static void _rest_cbk_result(const Vector3 &p_point_A, int p_index_A, const Vect
if (len < rd->min_allowed_depth) {
return;
}
- if (len <= rd->best_len) {
+
+ bool is_best_result = (len > rd->best_result.len);
+
+ if (rd->other_results && rd->result_count > 0) {
+ // Consider as new result by default.
+ int prev_result_count = rd->result_count++;
+
+ int result_index = 0;
+ real_t tested_len = is_best_result ? rd->best_result.len : len;
+ for (; result_index < prev_result_count - 1; ++result_index) {
+ if (tested_len > rd->other_results[result_index].len) {
+ // Re-using a previous result.
+ rd->result_count--;
+ break;
+ }
+ }
+
+ if (result_index < rd->max_results - 1) {
+ _RestResultData &result = rd->other_results[result_index];
+
+ if (is_best_result) {
+ // Keep the previous best result as separate result.
+ result = rd->best_result;
+ } else {
+ // Keep this result as separate result.
+ result.len = len;
+ result.contact = p_point_B;
+ result.normal = contact_rel / len;
+ result.object = rd->object;
+ result.shape = rd->shape;
+ result.local_shape = rd->local_shape;
+ }
+ } else {
+ // Discarding this result.
+ rd->result_count--;
+ }
+ } else if (is_best_result) {
+ rd->result_count = 1;
+ }
+
+ if (!is_best_result) {
return;
}
- rd->best_len = len;
- rd->best_contact = p_point_B;
- rd->best_normal = contact_rel / len;
- rd->best_object = rd->object;
- rd->best_shape = rd->shape;
- rd->best_local_shape = rd->local_shape;
+ rd->best_result.len = len;
+ rd->best_result.contact = p_point_B;
+ rd->best_result.normal = contact_rel / len;
+ rd->best_result.object = rd->object;
+ rd->best_result.shape = rd->shape;
+ rd->best_result.local_shape = rd->local_shape;
}
bool PhysicsDirectSpaceState3DSW::rest_info(RID p_shape, const Transform3D &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
- Shape3DSW *shape = PhysicsServer3DSW::singletonsw->shape_owner.getornull(p_shape);
+ Shape3DSW *shape = PhysicsServer3DSW::singletonsw->shape_owner.get_or_null(p_shape);
ERR_FAIL_COND_V(!shape, 0);
+ real_t min_contact_depth = p_margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR;
+
AABB aabb = p_shape_xform.xform(shape->get_aabb());
aabb = aabb.grow(p_margin);
int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, Space3DSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results);
_RestCallbackData rcd;
- rcd.best_len = 0;
- rcd.best_object = nullptr;
- rcd.best_shape = 0;
- rcd.min_allowed_depth = space->test_motion_min_contact_depth;
+ rcd.min_allowed_depth = min_contact_depth;
for (int i = 0; i < amount; i++) {
if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) {
@@ -470,18 +521,18 @@ bool PhysicsDirectSpaceState3DSW::rest_info(RID p_shape, const Transform3D &p_sh
}
}
- if (rcd.best_len == 0 || !rcd.best_object) {
+ if (rcd.best_result.len == 0 || !rcd.best_result.object) {
return false;
}
- r_info->collider_id = rcd.best_object->get_instance_id();
- r_info->shape = rcd.best_shape;
- r_info->normal = rcd.best_normal;
- r_info->point = rcd.best_contact;
- r_info->rid = rcd.best_object->get_self();
- if (rcd.best_object->get_type() == CollisionObject3DSW::TYPE_BODY) {
- const Body3DSW *body = static_cast<const Body3DSW *>(rcd.best_object);
- Vector3 rel_vec = rcd.best_contact - (body->get_transform().origin + body->get_center_of_mass());
+ r_info->collider_id = rcd.best_result.object->get_instance_id();
+ r_info->shape = rcd.best_result.shape;
+ r_info->normal = rcd.best_result.normal;
+ r_info->point = rcd.best_result.contact;
+ r_info->rid = rcd.best_result.object->get_self();
+ if (rcd.best_result.object->get_type() == CollisionObject3DSW::TYPE_BODY) {
+ const Body3DSW *body = static_cast<const Body3DSW *>(rcd.best_result.object);
+ Vector3 rel_vec = rcd.best_result.contact - (body->get_transform().origin + body->get_center_of_mass());
r_info->linear_velocity = body->get_linear_velocity() + (body->get_angular_velocity()).cross(rel_vec);
} else {
@@ -492,9 +543,9 @@ bool PhysicsDirectSpaceState3DSW::rest_info(RID p_shape, const Transform3D &p_sh
}
Vector3 PhysicsDirectSpaceState3DSW::get_closest_point_to_object_volume(RID p_object, const Vector3 p_point) const {
- CollisionObject3DSW *obj = PhysicsServer3DSW::singletonsw->area_owner.getornull(p_object);
+ CollisionObject3DSW *obj = PhysicsServer3DSW::singletonsw->area_owner.get_or_null(p_object);
if (!obj) {
- obj = PhysicsServer3DSW::singletonsw->body_owner.getornull(p_object);
+ obj = PhysicsServer3DSW::singletonsw->body_owner.get_or_null(p_object);
}
ERR_FAIL_COND_V(!obj, Vector3());
@@ -569,7 +620,7 @@ int Space3DSW::_cull_aabb_for_body(Body3DSW *p_body, const AABB &p_aabb) {
return amount;
}
-bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin, PhysicsServer3D::MotionResult *r_result, const Set<RID> &p_exclude) {
+bool Space3DSW::test_body_motion(Body3DSW *p_body, const PhysicsServer3D::MotionParameters &p_parameters, PhysicsServer3D::MotionResult *r_result) {
//give me back regular physics engine logic
//this is madness
//and most people using this function will think
@@ -577,10 +628,12 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co
//this took about a week to get right..
//but is it right? who knows at this point..
+ ERR_FAIL_INDEX_V(p_parameters.max_collisions, PhysicsServer3D::MotionResult::MAX_COLLISIONS, false);
+
if (r_result) {
- r_result->collider_id = ObjectID();
- r_result->collider_shape = 0;
+ *r_result = PhysicsServer3D::MotionResult();
}
+
AABB body_aabb;
bool shapes_found = false;
@@ -599,21 +652,22 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co
if (!shapes_found) {
if (r_result) {
- *r_result = PhysicsServer3D::MotionResult();
- r_result->travel = p_motion;
+ r_result->travel = p_parameters.motion;
}
return false;
}
// Undo the currently transform the physics server is aware of and apply the provided one
- body_aabb = p_from.xform(p_body->get_inv_transform().xform(body_aabb));
- body_aabb = body_aabb.grow(p_margin);
+ body_aabb = p_parameters.from.xform(p_body->get_inv_transform().xform(body_aabb));
+ body_aabb = body_aabb.grow(p_parameters.margin);
- real_t motion_length = p_motion.length();
- Vector3 motion_normal = p_motion / motion_length;
+ real_t min_contact_depth = p_parameters.margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR;
- Transform3D body_transform = p_from;
+ real_t motion_length = p_parameters.motion.length();
+ Vector3 motion_normal = p_parameters.motion / motion_length;
+
+ Transform3D body_transform = p_parameters.from;
bool recovered = false;
@@ -647,13 +701,16 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co
for (int i = 0; i < amount; i++) {
const CollisionObject3DSW *col_obj = intersection_query_results[i];
- if (p_exclude.has(col_obj->get_self())) {
+ if (p_parameters.exclude_bodies.has(col_obj->get_self())) {
+ continue;
+ }
+ if (p_parameters.exclude_objects.has(col_obj->get_instance_id())) {
continue;
}
int shape_idx = intersection_query_subindex_results[i];
- if (CollisionSolver3DSW::solve_static(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), cbkres, cbkptr, nullptr, p_margin)) {
+ if (CollisionSolver3DSW::solve_static(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), cbkres, cbkptr, nullptr, p_parameters.margin)) {
collided = cbk.amount > 0;
}
}
@@ -663,8 +720,9 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co
break;
}
- Vector3 recover_motion;
+ recovered = true;
+ Vector3 recover_motion;
for (int i = 0; i < cbk.amount; i++) {
Vector3 a = sr[i * 2 + 0];
Vector3 b = sr[i * 2 + 1];
@@ -675,9 +733,9 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co
// Compute depth on recovered motion.
real_t depth = n.dot(a + recover_motion) - d;
- if (depth > 0.0) {
+ if (depth > min_contact_depth + CMP_EPSILON) {
// Only recover if there is penetration.
- recover_motion -= n * depth * 0.4;
+ recover_motion -= n * (depth - min_contact_depth) * 0.4;
}
}
@@ -686,8 +744,6 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co
break;
}
- recovered = true;
-
body_transform.origin += recover_motion;
body_aabb.position += recover_motion;
@@ -704,7 +760,7 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co
// STEP 2 ATTEMPT MOTION
AABB motion_aabb = body_aabb;
- motion_aabb.position += p_motion;
+ motion_aabb.position += p_parameters.motion;
motion_aabb = motion_aabb.merge(body_aabb);
int amount = _cull_aabb_for_body(p_body, motion_aabb);
@@ -714,13 +770,23 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co
continue;
}
- Transform3D body_shape_xform = body_transform * p_body->get_shape_transform(j);
Shape3DSW *body_shape = p_body->get_shape(j);
+ // Colliding separation rays allows to properly snap to the ground,
+ // otherwise it's not needed in regular motion.
+ if (!p_parameters.collide_separation_ray && (body_shape->get_type() == PhysicsServer3D::SHAPE_SEPARATION_RAY)) {
+ // When slide on slope is on, separation ray shape acts like a regular shape.
+ if (!static_cast<SeparationRayShape3DSW *>(body_shape)->get_slide_on_slope()) {
+ continue;
+ }
+ }
+
+ Transform3D body_shape_xform = body_transform * p_body->get_shape_transform(j);
+
Transform3D body_shape_xform_inv = body_shape_xform.affine_inverse();
MotionShape3DSW mshape;
mshape.shape = body_shape;
- mshape.motion = body_shape_xform_inv.basis.xform(p_motion);
+ mshape.motion = body_shape_xform_inv.basis.xform(p_parameters.motion);
bool stuck = false;
@@ -729,7 +795,10 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co
for (int i = 0; i < amount; i++) {
const CollisionObject3DSW *col_obj = intersection_query_results[i];
- if (p_exclude.has(col_obj->get_self())) {
+ if (p_parameters.exclude_bodies.has(col_obj->get_self())) {
+ continue;
+ }
+ if (p_parameters.exclude_objects.has(col_obj->get_instance_id())) {
continue;
}
@@ -758,7 +827,7 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co
for (int k = 0; k < 8; k++) { //steps should be customizable..
real_t fraction = low + (hi - low) * fraction_coeff;
- mshape.motion = body_shape_xform_inv.basis.xform(p_motion * fraction);
+ mshape.motion = body_shape_xform_inv.basis.xform(p_parameters.motion * fraction);
Vector3 lA, lB;
Vector3 sep = motion_normal; //important optimization for this to work fast enough
@@ -820,15 +889,18 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co
//it collided, let's get the rest info in unsafe advance
Transform3D ugt = body_transform;
- ugt.origin += p_motion * unsafe;
+ ugt.origin += p_parameters.motion * unsafe;
+
+ _RestResultData results[PhysicsServer3D::MotionResult::MAX_COLLISIONS];
_RestCallbackData rcd;
- rcd.best_len = 0;
- rcd.best_object = nullptr;
- rcd.best_shape = 0;
+ if (p_parameters.max_collisions > 1) {
+ rcd.max_results = p_parameters.max_collisions;
+ rcd.other_results = results;
+ }
// Allowed depth can't be lower than motion length, in order to handle contacts at low speed.
- rcd.min_allowed_depth = MIN(motion_length, test_motion_min_contact_depth);
+ rcd.min_allowed_depth = MIN(motion_length, min_contact_depth);
int from_shape = best_shape != -1 ? best_shape : 0;
int to_shape = best_shape != -1 ? best_shape + 1 : p_body->get_shape_count();
@@ -841,47 +913,59 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co
Transform3D body_shape_xform = ugt * p_body->get_shape_transform(j);
Shape3DSW *body_shape = p_body->get_shape(j);
- body_aabb.position += p_motion * unsafe;
+ body_aabb.position += p_parameters.motion * unsafe;
int amount = _cull_aabb_for_body(p_body, body_aabb);
for (int i = 0; i < amount; i++) {
const CollisionObject3DSW *col_obj = intersection_query_results[i];
- if (p_exclude.has(col_obj->get_self())) {
+ if (p_parameters.exclude_bodies.has(col_obj->get_self())) {
+ continue;
+ }
+ if (p_parameters.exclude_objects.has(col_obj->get_instance_id())) {
continue;
}
+
int shape_idx = intersection_query_subindex_results[i];
rcd.object = col_obj;
rcd.shape = shape_idx;
- bool sc = CollisionSolver3DSW::solve_static(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), _rest_cbk_result, &rcd, nullptr, p_margin);
+ bool sc = CollisionSolver3DSW::solve_static(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), _rest_cbk_result, &rcd, nullptr, p_parameters.margin);
if (!sc) {
continue;
}
}
}
- if (rcd.best_len != 0) {
+ if (rcd.result_count > 0) {
if (r_result) {
- r_result->collider = rcd.best_object->get_self();
- r_result->collider_id = rcd.best_object->get_instance_id();
- r_result->collider_shape = rcd.best_shape;
- r_result->collision_local_shape = rcd.best_local_shape;
- r_result->collision_normal = rcd.best_normal;
- r_result->collision_point = rcd.best_contact;
- r_result->collision_depth = rcd.best_len;
- r_result->collision_safe_fraction = safe;
- r_result->collision_unsafe_fraction = unsafe;
- //r_result->collider_metadata = rcd.best_object->get_shape_metadata(rcd.best_shape);
+ for (int collision_index = 0; collision_index < rcd.result_count; ++collision_index) {
+ const _RestResultData &result = (collision_index > 0) ? rcd.other_results[collision_index - 1] : rcd.best_result;
- const Body3DSW *body = static_cast<const Body3DSW *>(rcd.best_object);
+ PhysicsServer3D::MotionCollision &collision = r_result->collisions[collision_index];
- Vector3 rel_vec = rcd.best_contact - (body->get_transform().origin + body->get_center_of_mass());
- r_result->collider_velocity = body->get_linear_velocity() + (body->get_angular_velocity()).cross(rel_vec);
+ collision.collider = result.object->get_self();
+ collision.collider_id = result.object->get_instance_id();
+ collision.collider_shape = result.shape;
+ collision.local_shape = result.local_shape;
+ collision.normal = result.normal;
+ collision.position = result.contact;
+ collision.depth = result.len;
- r_result->travel = safe * p_motion;
- r_result->remainder = p_motion - safe * p_motion;
- r_result->travel += (body_transform.get_origin() - p_from.get_origin());
+ const Body3DSW *body = static_cast<const Body3DSW *>(result.object);
+
+ Vector3 rel_vec = result.contact - (body->get_transform().origin + body->get_center_of_mass());
+ collision.collider_velocity = body->get_linear_velocity() + (body->get_angular_velocity()).cross(rel_vec);
+ }
+
+ r_result->travel = safe * p_parameters.motion;
+ r_result->remainder = p_parameters.motion - safe * p_parameters.motion;
+ r_result->travel += (body_transform.get_origin() - p_parameters.from.get_origin());
+
+ r_result->collision_safe_fraction = safe;
+ r_result->collision_unsafe_fraction = unsafe;
+
+ r_result->collision_count = rcd.result_count;
}
collided = true;
@@ -889,9 +973,12 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co
}
if (!collided && r_result) {
- r_result->travel = p_motion;
+ r_result->travel = p_parameters.motion;
r_result->remainder = Vector3();
- r_result->travel += (body_transform.get_origin() - p_from.get_origin());
+ r_result->travel += (body_transform.get_origin() - p_parameters.from.get_origin());
+
+ r_result->collision_safe_fraction = 1.0;
+ r_result->collision_unsafe_fraction = 1.0;
}
return collided;
@@ -967,12 +1054,12 @@ void Space3DSW::body_remove_from_active_list(SelfList<Body3DSW> *p_body) {
active_list.remove(p_body);
}
-void Space3DSW::body_add_to_inertia_update_list(SelfList<Body3DSW> *p_body) {
- inertia_update_list.add(p_body);
+void Space3DSW::body_add_to_mass_properties_update_list(SelfList<Body3DSW> *p_body) {
+ mass_properties_update_list.add(p_body);
}
-void Space3DSW::body_remove_from_inertia_update_list(SelfList<Body3DSW> *p_body) {
- inertia_update_list.remove(p_body);
+void Space3DSW::body_remove_from_mass_properties_update_list(SelfList<Body3DSW> *p_body) {
+ mass_properties_update_list.remove(p_body);
}
BroadPhase3DSW *Space3DSW::get_broadphase() {
@@ -1049,9 +1136,9 @@ void Space3DSW::call_queries() {
void Space3DSW::setup() {
contact_debug_count = 0;
- while (inertia_update_list.first()) {
- inertia_update_list.first()->self()->update_inertias();
- inertia_update_list.remove(inertia_update_list.first());
+ while (mass_properties_update_list.first()) {
+ mass_properties_update_list.first()->self()->update_mass_properties();
+ mass_properties_update_list.remove(mass_properties_update_list.first());
}
}
@@ -1085,9 +1172,6 @@ void Space3DSW::set_param(PhysicsServer3D::SpaceParameter p_param, real_t p_valu
case PhysicsServer3D::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS:
constraint_bias = p_value;
break;
- case PhysicsServer3D::SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH:
- test_motion_min_contact_depth = p_value;
- break;
}
}
@@ -1109,8 +1193,6 @@ real_t Space3DSW::get_param(PhysicsServer3D::SpaceParameter p_param) const {
return body_angular_velocity_damp_ratio;
case PhysicsServer3D::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS:
return constraint_bias;
- case PhysicsServer3D::SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH:
- return test_motion_min_contact_depth;
}
return 0;
}
@@ -1132,18 +1214,6 @@ PhysicsDirectSpaceState3DSW *Space3DSW::get_direct_state() {
}
Space3DSW::Space3DSW() {
- collision_pairs = 0;
- active_objects = 0;
- island_count = 0;
- contact_debug_count = 0;
-
- locked = false;
- contact_recycle_radius = 0.01;
- contact_max_separation = 0.05;
- contact_max_allowed_penetration = 0.01;
- test_motion_min_contact_depth = 0.00001;
-
- constraint_bias = 0.01;
body_linear_velocity_sleep_threshold = GLOBAL_DEF("physics/3d/sleep_threshold_linear", 0.1);
body_angular_velocity_sleep_threshold = GLOBAL_DEF("physics/3d/sleep_threshold_angular", Math::deg2rad(8.0));
body_time_to_sleep = GLOBAL_DEF("physics/3d/time_before_sleep", 0.5);
@@ -1153,14 +1223,9 @@ Space3DSW::Space3DSW() {
broadphase = BroadPhase3DSW::create_func();
broadphase->set_pair_callback(_broadphase_pair, this);
broadphase->set_unpair_callback(_broadphase_unpair, this);
- area = nullptr;
direct_access = memnew(PhysicsDirectSpaceState3DSW);
direct_access->space = this;
-
- for (int i = 0; i < ELAPSED_TIME_MAX; i++) {
- elapsed_time[i] = 0;
- }
}
Space3DSW::~Space3DSW() {
diff --git a/servers/physics_3d/space_3d_sw.h b/servers/physics_3d/space_3d_sw.h
index 9b5b4de069..69cc3c4bbd 100644
--- a/servers/physics_3d/space_3d_sw.h
+++ b/servers/physics_3d/space_3d_sw.h
@@ -48,12 +48,12 @@ class PhysicsDirectSpaceState3DSW : public PhysicsDirectSpaceState3D {
public:
Space3DSW *space;
- virtual int intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
- virtual bool intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_ray = false) override;
- virtual int intersect_shape(const RID &p_shape, const Transform3D &p_xform, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
- virtual bool cast_motion(const RID &p_shape, const Transform3D &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, ShapeRestInfo *r_info = nullptr) override;
- virtual bool collide_shape(RID p_shape, const Transform3D &p_shape_xform, real_t p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
- virtual bool rest_info(RID p_shape, const Transform3D &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
+ virtual int intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
+ virtual bool intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_ray = false) override;
+ virtual int intersect_shape(const RID &p_shape, const Transform3D &p_xform, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
+ virtual bool cast_motion(const RID &p_shape, const Transform3D &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, ShapeRestInfo *r_info = nullptr) override;
+ virtual bool collide_shape(RID p_shape, const Transform3D &p_shape_xform, real_t p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
+ virtual bool rest_info(RID p_shape, const Transform3D &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
virtual Vector3 get_closest_point_to_object_volume(RID p_object, const Vector3 p_point) const override;
PhysicsDirectSpaceState3DSW();
@@ -72,14 +72,14 @@ public:
};
private:
- uint64_t elapsed_time[ELAPSED_TIME_MAX];
+ uint64_t elapsed_time[ELAPSED_TIME_MAX] = {};
PhysicsDirectSpaceState3DSW *direct_access;
RID self;
BroadPhase3DSW *broadphase;
SelfList<Body3DSW>::List active_list;
- SelfList<Body3DSW>::List inertia_update_list;
+ SelfList<Body3DSW>::List mass_properties_update_list;
SelfList<Body3DSW>::List state_query_list;
SelfList<Area3DSW>::List monitor_query_list;
SelfList<Area3DSW>::List area_moved_list;
@@ -90,13 +90,12 @@ private:
Set<CollisionObject3DSW *> objects;
- Area3DSW *area;
+ Area3DSW *area = nullptr;
- real_t contact_recycle_radius;
- real_t contact_max_separation;
- real_t contact_max_allowed_penetration;
- real_t constraint_bias;
- real_t test_motion_min_contact_depth;
+ real_t contact_recycle_radius = 0.01;
+ real_t contact_max_separation = 0.05;
+ real_t contact_max_allowed_penetration = 0.01;
+ real_t constraint_bias = 0.01;
enum {
INTERSECTION_QUERY_MAX = 2048
@@ -110,16 +109,18 @@ private:
real_t body_time_to_sleep;
real_t body_angular_velocity_damp_ratio;
- bool locked;
+ bool locked = false;
- int island_count;
- int active_objects;
- int collision_pairs;
+ real_t last_step = 0.001;
+
+ int island_count = 0;
+ int active_objects = 0;
+ int collision_pairs = 0;
RID static_global_body;
Vector<Vector3> contact_debug;
- int contact_debug_count;
+ int contact_debug_count = 0;
friend class PhysicsDirectSpaceState3DSW;
@@ -135,8 +136,8 @@ public:
const SelfList<Body3DSW>::List &get_active_body_list() const;
void body_add_to_active_list(SelfList<Body3DSW> *p_body);
void body_remove_from_active_list(SelfList<Body3DSW> *p_body);
- void body_add_to_inertia_update_list(SelfList<Body3DSW> *p_body);
- void body_remove_from_inertia_update_list(SelfList<Body3DSW> *p_body);
+ void body_add_to_mass_properties_update_list(SelfList<Body3DSW> *p_body);
+ void body_remove_from_mass_properties_update_list(SelfList<Body3DSW> *p_body);
void body_add_to_state_query_list(SelfList<Body3DSW> *p_body);
void body_remove_from_state_query_list(SelfList<Body3DSW> *p_body);
@@ -174,6 +175,9 @@ public:
void lock();
void unlock();
+ real_t get_last_step() const { return last_step; }
+ void set_last_step(real_t p_step) { last_step = p_step; }
+
void set_param(PhysicsServer3D::SpaceParameter p_param, real_t p_value);
real_t get_param(PhysicsServer3D::SpaceParameter p_param) const;
@@ -203,7 +207,7 @@ public:
void set_elapsed_time(ElapsedTime p_time, uint64_t p_msec) { elapsed_time[p_time] = p_msec; }
uint64_t get_elapsed_time(ElapsedTime p_time) const { return elapsed_time[p_time]; }
- bool test_body_motion(Body3DSW *p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin, PhysicsServer3D::MotionResult *r_result, const Set<RID> &p_exclude = Set<RID>());
+ bool test_body_motion(Body3DSW *p_body, const PhysicsServer3D::MotionParameters &p_parameters, PhysicsServer3D::MotionResult *r_result);
Space3DSW();
~Space3DSW();
diff --git a/servers/physics_3d/step_3d_sw.cpp b/servers/physics_3d/step_3d_sw.cpp
index ba18bac611..6572d58c91 100644
--- a/servers/physics_3d/step_3d_sw.cpp
+++ b/servers/physics_3d/step_3d_sw.cpp
@@ -47,8 +47,8 @@ void Step3DSW::_populate_island(Body3DSW *p_body, LocalVector<Body3DSW *> &p_bod
p_body_island.push_back(p_body);
}
- for (Map<Constraint3DSW *, int>::Element *E = p_body->get_constraint_map().front(); E; E = E->next()) {
- Constraint3DSW *constraint = (Constraint3DSW *)E->key();
+ for (const KeyValue<Constraint3DSW *, int> &E : p_body->get_constraint_map()) {
+ Constraint3DSW *constraint = (Constraint3DSW *)E.key;
if (constraint->get_island_step() == _step) {
continue; // Already processed.
}
@@ -59,7 +59,7 @@ void Step3DSW::_populate_island(Body3DSW *p_body, LocalVector<Body3DSW *> &p_bod
// Find connected rigid bodies.
for (int i = 0; i < constraint->get_body_count(); i++) {
- if (i == E->get()) {
+ if (i == E.value) {
continue;
}
Body3DSW *other_body = constraint->get_body_ptr()[i];
@@ -185,6 +185,8 @@ void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) {
p_space->setup(); //update inertias, etc
+ p_space->set_last_step(p_delta);
+
iterations = p_iterations;
delta = p_delta;
@@ -405,8 +407,6 @@ void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) {
}
Step3DSW::Step3DSW() {
- _step = 1;
-
body_islands.reserve(BODY_ISLAND_COUNT_RESERVE);
constraint_islands.reserve(ISLAND_COUNT_RESERVE);
all_constraints.reserve(CONSTRAINT_COUNT_RESERVE);
diff --git a/servers/physics_3d/step_3d_sw.h b/servers/physics_3d/step_3d_sw.h
index 9c60004b24..f2f879104a 100644
--- a/servers/physics_3d/step_3d_sw.h
+++ b/servers/physics_3d/step_3d_sw.h
@@ -37,7 +37,7 @@
#include "core/templates/thread_work_pool.h"
class Step3DSW {
- uint64_t _step;
+ uint64_t _step = 1;
int iterations = 0;
real_t delta = 0.0;
diff --git a/servers/physics_server_2d.cpp b/servers/physics_server_2d.cpp
index c96f85446c..a6cb7dbdd9 100644
--- a/servers/physics_server_2d.cpp
+++ b/servers/physics_server_2d.cpp
@@ -77,6 +77,7 @@ void PhysicsDirectBodyState2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_total_linear_damp"), &PhysicsDirectBodyState2D::get_total_linear_damp);
ClassDB::bind_method(D_METHOD("get_total_angular_damp"), &PhysicsDirectBodyState2D::get_total_angular_damp);
+ ClassDB::bind_method(D_METHOD("get_center_of_mass"), &PhysicsDirectBodyState2D::get_center_of_mass);
ClassDB::bind_method(D_METHOD("get_inverse_mass"), &PhysicsDirectBodyState2D::get_inverse_mass);
ClassDB::bind_method(D_METHOD("get_inverse_inertia"), &PhysicsDirectBodyState2D::get_inverse_inertia);
@@ -111,7 +112,6 @@ void PhysicsDirectBodyState2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_contact_collider_id", "contact_idx"), &PhysicsDirectBodyState2D::get_contact_collider_id);
ClassDB::bind_method(D_METHOD("get_contact_collider_object", "contact_idx"), &PhysicsDirectBodyState2D::get_contact_collider_object);
ClassDB::bind_method(D_METHOD("get_contact_collider_shape", "contact_idx"), &PhysicsDirectBodyState2D::get_contact_collider_shape);
- ClassDB::bind_method(D_METHOD("get_contact_collider_shape_metadata", "contact_idx"), &PhysicsDirectBodyState2D::get_contact_collider_shape_metadata);
ClassDB::bind_method(D_METHOD("get_contact_collider_velocity_at_position", "contact_idx"), &PhysicsDirectBodyState2D::get_contact_collider_velocity_at_position);
ClassDB::bind_method(D_METHOD("get_step"), &PhysicsDirectBodyState2D::get_step);
ClassDB::bind_method(D_METHOD("integrate_forces"), &PhysicsDirectBodyState2D::integrate_forces);
@@ -123,6 +123,7 @@ void PhysicsDirectBodyState2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "total_angular_damp"), "", "get_total_angular_damp");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "total_linear_damp"), "", "get_total_linear_damp");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "total_gravity"), "", "get_total_gravity");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "center_of_mass"), "", "get_center_of_mass");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_velocity"), "set_angular_velocity", "get_angular_velocity");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "linear_velocity"), "set_linear_velocity", "get_linear_velocity");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sleeping"), "set_sleep_state", "is_sleeping");
@@ -198,7 +199,7 @@ Vector<RID> PhysicsShapeQueryParameters2D::get_exclude() const {
ret.resize(exclude.size());
int idx = 0;
for (Set<RID>::Element *E = exclude.front(); E; E = E->next()) {
- ret.write[idx] = E->get();
+ ret.write[idx++] = E->get();
}
return ret;
}
@@ -257,13 +258,6 @@ void PhysicsShapeQueryParameters2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas"), "set_collide_with_areas", "is_collide_with_areas_enabled");
}
-PhysicsShapeQueryParameters2D::PhysicsShapeQueryParameters2D() {
- margin = 0;
- collision_mask = 0x7FFFFFFF;
- collide_with_bodies = true;
- collide_with_areas = false;
-}
-
Dictionary PhysicsDirectSpaceState2D::_intersect_ray(const Vector2 &p_from, const Vector2 &p_to, const Vector<RID> &p_exclude, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas) {
RayResult inters;
Set<RID> exclude;
@@ -284,7 +278,6 @@ Dictionary PhysicsDirectSpaceState2D::_intersect_ray(const Vector2 &p_from, cons
d["collider"] = inters.collider;
d["shape"] = inters.shape;
d["rid"] = inters.rid;
- d["metadata"] = inters.metadata;
return d;
}
@@ -303,7 +296,6 @@ Array PhysicsDirectSpaceState2D::_intersect_shape(const Ref<PhysicsShapeQueryPar
d["collider_id"] = sr[i].collider_id;
d["collider"] = sr[i].collider;
d["shape"] = sr[i].shape;
- d["metadata"] = sr[i].metadata;
ret[i] = d;
}
@@ -353,7 +345,6 @@ Array PhysicsDirectSpaceState2D::_intersect_point_impl(const Vector2 &p_point, i
d["collider_id"] = ret[i].collider_id;
d["collider"] = ret[i].collider;
d["shape"] = ret[i].shape;
- d["metadata"] = ret[i].metadata;
r[i] = d;
}
return r;
@@ -402,7 +393,6 @@ Dictionary PhysicsDirectSpaceState2D::_get_rest_info(const Ref<PhysicsShapeQuery
r["collider_id"] = sri.collider_id;
r["shape"] = sri.shape;
r["linear_velocity"] = sri.linear_velocity;
- r["metadata"] = sri.metadata;
return r;
}
@@ -411,9 +401,9 @@ PhysicsDirectSpaceState2D::PhysicsDirectSpaceState2D() {
}
void PhysicsDirectSpaceState2D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("intersect_point", "point", "max_results", "exclude", "collision_mask", "collide_with_bodies", "collide_with_areas"), &PhysicsDirectSpaceState2D::_intersect_point, DEFVAL(32), DEFVAL(Array()), DEFVAL(0x7FFFFFFF), DEFVAL(true), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("intersect_point_on_canvas", "point", "canvas_instance_id", "max_results", "exclude", "collision_mask", "collide_with_bodies", "collide_with_areas"), &PhysicsDirectSpaceState2D::_intersect_point_on_canvas, DEFVAL(32), DEFVAL(Array()), DEFVAL(0x7FFFFFFF), DEFVAL(true), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("intersect_ray", "from", "to", "exclude", "collision_mask", "collide_with_bodies", "collide_with_areas"), &PhysicsDirectSpaceState2D::_intersect_ray, DEFVAL(Array()), DEFVAL(0x7FFFFFFF), DEFVAL(true), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("intersect_point", "point", "max_results", "exclude", "collision_mask", "collide_with_bodies", "collide_with_areas"), &PhysicsDirectSpaceState2D::_intersect_point, DEFVAL(32), DEFVAL(Array()), DEFVAL(UINT32_MAX), DEFVAL(true), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("intersect_point_on_canvas", "point", "canvas_instance_id", "max_results", "exclude", "collision_mask", "collide_with_bodies", "collide_with_areas"), &PhysicsDirectSpaceState2D::_intersect_point_on_canvas, DEFVAL(32), DEFVAL(Array()), DEFVAL(UINT32_MAX), DEFVAL(true), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("intersect_ray", "from", "to", "exclude", "collision_mask", "collide_with_bodies", "collide_with_areas"), &PhysicsDirectSpaceState2D::_intersect_ray, DEFVAL(Array()), DEFVAL(UINT32_MAX), DEFVAL(true), DEFVAL(false));
ClassDB::bind_method(D_METHOD("intersect_shape", "shape", "max_results"), &PhysicsDirectSpaceState2D::_intersect_shape, DEFVAL(32));
ClassDB::bind_method(D_METHOD("cast_motion", "shape"), &PhysicsDirectSpaceState2D::_cast_motion);
ClassDB::bind_method(D_METHOD("collide_shape", "shape", "max_results"), &PhysicsDirectSpaceState2D::_collide_shape, DEFVAL(32));
@@ -422,6 +412,73 @@ void PhysicsDirectSpaceState2D::_bind_methods() {
///////////////////////////////
+Vector<RID> PhysicsTestMotionParameters2D::get_exclude_bodies() const {
+ Vector<RID> exclude;
+ exclude.resize(parameters.exclude_bodies.size());
+
+ int body_index = 0;
+ for (RID body : parameters.exclude_bodies) {
+ exclude.write[body_index++] = body;
+ }
+
+ return exclude;
+}
+
+void PhysicsTestMotionParameters2D::set_exclude_bodies(const Vector<RID> &p_exclude) {
+ for (RID body : p_exclude) {
+ parameters.exclude_bodies.insert(body);
+ }
+}
+
+Array PhysicsTestMotionParameters2D::get_exclude_objects() const {
+ Array exclude;
+ exclude.resize(parameters.exclude_objects.size());
+
+ int object_index = 0;
+ for (ObjectID object_id : parameters.exclude_objects) {
+ exclude[object_index++] = object_id;
+ }
+
+ return exclude;
+}
+
+void PhysicsTestMotionParameters2D::set_exclude_objects(const Array &p_exclude) {
+ for (int i = 0; i < p_exclude.size(); ++i) {
+ ObjectID object_id = p_exclude[i];
+ ERR_CONTINUE(object_id.is_null());
+ parameters.exclude_objects.insert(object_id);
+ }
+}
+
+void PhysicsTestMotionParameters2D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("get_from"), &PhysicsTestMotionParameters2D::get_from);
+ ClassDB::bind_method(D_METHOD("set_from", "from"), &PhysicsTestMotionParameters2D::set_from);
+
+ ClassDB::bind_method(D_METHOD("get_motion"), &PhysicsTestMotionParameters2D::get_motion);
+ ClassDB::bind_method(D_METHOD("set_motion", "motion"), &PhysicsTestMotionParameters2D::set_motion);
+
+ ClassDB::bind_method(D_METHOD("get_margin"), &PhysicsTestMotionParameters2D::get_margin);
+ ClassDB::bind_method(D_METHOD("set_margin", "margin"), &PhysicsTestMotionParameters2D::set_margin);
+
+ ClassDB::bind_method(D_METHOD("is_collide_separation_ray_enabled"), &PhysicsTestMotionParameters2D::is_collide_separation_ray_enabled);
+ ClassDB::bind_method(D_METHOD("set_collide_separation_ray_enabled", "enabled"), &PhysicsTestMotionParameters2D::set_collide_separation_ray_enabled);
+
+ ClassDB::bind_method(D_METHOD("get_exclude_bodies"), &PhysicsTestMotionParameters2D::get_exclude_bodies);
+ ClassDB::bind_method(D_METHOD("set_exclude_bodies", "exclude_list"), &PhysicsTestMotionParameters2D::set_exclude_bodies);
+
+ ClassDB::bind_method(D_METHOD("get_exclude_objects"), &PhysicsTestMotionParameters2D::get_exclude_objects);
+ ClassDB::bind_method(D_METHOD("set_exclude_objects", "exclude_list"), &PhysicsTestMotionParameters2D::set_exclude_objects);
+
+ ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "from"), "set_from", "get_from");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion"), "set_motion", "get_motion");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin"), "set_margin", "get_margin");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_separation_ray"), "set_collide_separation_ray_enabled", "is_collide_separation_ray_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude_bodies"), "set_exclude_bodies", "get_exclude_bodies");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude_objects"), "set_exclude_objects", "get_exclude_objects");
+}
+
+///////////////////////////////
+
Vector2 PhysicsTestMotionResult2D::get_travel() const {
return result.travel;
}
@@ -458,6 +515,10 @@ int PhysicsTestMotionResult2D::get_collider_shape() const {
return result.collider_shape;
}
+int PhysicsTestMotionResult2D::get_collision_local_shape() const {
+ return result.collision_local_shape;
+}
+
real_t PhysicsTestMotionResult2D::get_collision_depth() const {
return result.collision_depth;
}
@@ -480,40 +541,28 @@ void PhysicsTestMotionResult2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_collider_rid"), &PhysicsTestMotionResult2D::get_collider_rid);
ClassDB::bind_method(D_METHOD("get_collider"), &PhysicsTestMotionResult2D::get_collider);
ClassDB::bind_method(D_METHOD("get_collider_shape"), &PhysicsTestMotionResult2D::get_collider_shape);
+ ClassDB::bind_method(D_METHOD("get_collision_local_shape"), &PhysicsTestMotionResult2D::get_collision_local_shape);
ClassDB::bind_method(D_METHOD("get_collision_depth"), &PhysicsTestMotionResult2D::get_collision_depth);
ClassDB::bind_method(D_METHOD("get_collision_safe_fraction"), &PhysicsTestMotionResult2D::get_collision_safe_fraction);
ClassDB::bind_method(D_METHOD("get_collision_unsafe_fraction"), &PhysicsTestMotionResult2D::get_collision_unsafe_fraction);
-
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "travel"), "", "get_travel");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "remainder"), "", "get_remainder");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "collision_point"), "", "get_collision_point");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "collision_normal"), "", "get_collision_normal");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "collider_velocity"), "", "get_collider_velocity");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "collider_id", PROPERTY_HINT_OBJECT_ID), "", "get_collider_id");
- ADD_PROPERTY(PropertyInfo(Variant::RID, "collider_rid"), "", "get_collider_rid");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "collider"), "", "get_collider");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "collider_shape"), "", "get_collider_shape");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision_depth"), "", "get_collision_depth");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision_safe_fraction"), "", "get_collision_safe_fraction");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision_unsafe_fraction"), "", "get_collision_unsafe_fraction");
}
///////////////////////////////////////
-bool PhysicsServer2D::_body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin, const Ref<PhysicsTestMotionResult2D> &p_result, const Vector<RID> &p_exclude) {
- MotionResult *r = nullptr;
+bool PhysicsServer2D::_body_test_motion(RID p_body, const Ref<PhysicsTestMotionParameters2D> &p_parameters, const Ref<PhysicsTestMotionResult2D> &p_result) {
+ ERR_FAIL_COND_V(!p_parameters.is_valid(), false);
+
+ MotionResult *result_ptr = nullptr;
if (p_result.is_valid()) {
- r = p_result->get_result_ptr();
+ result_ptr = p_result->get_result_ptr();
}
- Set<RID> exclude;
- for (int i = 0; i < p_exclude.size(); i++) {
- exclude.insert(p_exclude[i]);
- }
- return body_test_motion(p_body, p_from, p_motion, p_margin, r, exclude);
+
+ return body_test_motion(p_body, p_parameters->get_parameters(), result_ptr);
}
void PhysicsServer2D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("world_margin_shape_create"), &PhysicsServer2D::world_margin_shape_create);
+ ClassDB::bind_method(D_METHOD("world_boundary_shape_create"), &PhysicsServer2D::world_boundary_shape_create);
+ ClassDB::bind_method(D_METHOD("separation_ray_shape_create"), &PhysicsServer2D::separation_ray_shape_create);
ClassDB::bind_method(D_METHOD("segment_shape_create"), &PhysicsServer2D::segment_shape_create);
ClassDB::bind_method(D_METHOD("circle_shape_create"), &PhysicsServer2D::circle_shape_create);
ClassDB::bind_method(D_METHOD("rectangle_shape_create"), &PhysicsServer2D::rectangle_shape_create);
@@ -582,12 +631,10 @@ void PhysicsServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("body_add_shape", "body", "shape", "transform", "disabled"), &PhysicsServer2D::body_add_shape, DEFVAL(Transform2D()), DEFVAL(false));
ClassDB::bind_method(D_METHOD("body_set_shape", "body", "shape_idx", "shape"), &PhysicsServer2D::body_set_shape);
ClassDB::bind_method(D_METHOD("body_set_shape_transform", "body", "shape_idx", "transform"), &PhysicsServer2D::body_set_shape_transform);
- ClassDB::bind_method(D_METHOD("body_set_shape_metadata", "body", "shape_idx", "metadata"), &PhysicsServer2D::body_set_shape_metadata);
ClassDB::bind_method(D_METHOD("body_get_shape_count", "body"), &PhysicsServer2D::body_get_shape_count);
ClassDB::bind_method(D_METHOD("body_get_shape", "body", "shape_idx"), &PhysicsServer2D::body_get_shape);
ClassDB::bind_method(D_METHOD("body_get_shape_transform", "body", "shape_idx"), &PhysicsServer2D::body_get_shape_transform);
- ClassDB::bind_method(D_METHOD("body_get_shape_metadata", "body", "shape_idx"), &PhysicsServer2D::body_get_shape_metadata);
ClassDB::bind_method(D_METHOD("body_remove_shape", "body", "shape_idx"), &PhysicsServer2D::body_remove_shape);
ClassDB::bind_method(D_METHOD("body_clear_shapes", "body"), &PhysicsServer2D::body_clear_shapes);
@@ -613,6 +660,8 @@ void PhysicsServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("body_set_param", "body", "param", "value"), &PhysicsServer2D::body_set_param);
ClassDB::bind_method(D_METHOD("body_get_param", "body", "param"), &PhysicsServer2D::body_get_param);
+ ClassDB::bind_method(D_METHOD("body_reset_mass_properties", "body"), &PhysicsServer2D::body_reset_mass_properties);
+
ClassDB::bind_method(D_METHOD("body_set_state", "body", "state", "value"), &PhysicsServer2D::body_set_state);
ClassDB::bind_method(D_METHOD("body_get_state", "body", "state"), &PhysicsServer2D::body_get_state);
@@ -635,7 +684,7 @@ void PhysicsServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("body_set_force_integration_callback", "body", "callable", "userdata"), &PhysicsServer2D::body_set_force_integration_callback, DEFVAL(Variant()));
- ClassDB::bind_method(D_METHOD("body_test_motion", "body", "from", "motion", "margin", "result", "exclude"), &PhysicsServer2D::_body_test_motion, DEFVAL(0.08), DEFVAL(Variant()), DEFVAL(Array()));
+ ClassDB::bind_method(D_METHOD("body_test_motion", "body", "parameters", "result"), &PhysicsServer2D::_body_test_motion, DEFVAL(Variant()));
ClassDB::bind_method(D_METHOD("body_get_direct_state", "body"), &PhysicsServer2D::body_get_direct_state);
@@ -672,9 +721,9 @@ void PhysicsServer2D::_bind_methods() {
BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD);
BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_TIME_TO_SLEEP);
BIND_ENUM_CONSTANT(SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS);
- BIND_ENUM_CONSTANT(SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH);
- BIND_ENUM_CONSTANT(SHAPE_WORLD_MARGIN);
+ BIND_ENUM_CONSTANT(SHAPE_WORLD_BOUNDARY);
+ BIND_ENUM_CONSTANT(SHAPE_SEPARATION_RAY);
BIND_ENUM_CONSTANT(SHAPE_SEGMENT);
BIND_ENUM_CONSTANT(SHAPE_CIRCLE);
BIND_ENUM_CONSTANT(SHAPE_RECTANGLE);
@@ -701,12 +750,13 @@ void PhysicsServer2D::_bind_methods() {
BIND_ENUM_CONSTANT(BODY_MODE_STATIC);
BIND_ENUM_CONSTANT(BODY_MODE_KINEMATIC);
BIND_ENUM_CONSTANT(BODY_MODE_DYNAMIC);
- BIND_ENUM_CONSTANT(BODY_MODE_DYNAMIC_LOCKED);
+ BIND_ENUM_CONSTANT(BODY_MODE_DYNAMIC_LINEAR);
BIND_ENUM_CONSTANT(BODY_PARAM_BOUNCE);
BIND_ENUM_CONSTANT(BODY_PARAM_FRICTION);
BIND_ENUM_CONSTANT(BODY_PARAM_MASS);
BIND_ENUM_CONSTANT(BODY_PARAM_INERTIA);
+ BIND_ENUM_CONSTANT(BODY_PARAM_CENTER_OF_MASS);
BIND_ENUM_CONSTANT(BODY_PARAM_GRAVITY_SCALE);
BIND_ENUM_CONSTANT(BODY_PARAM_LINEAR_DAMP);
BIND_ENUM_CONSTANT(BODY_PARAM_ANGULAR_DAMP);
diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h
index 4c559dd7bd..26e1411111 100644
--- a/servers/physics_server_2d.h
+++ b/servers/physics_server_2d.h
@@ -48,6 +48,7 @@ public:
virtual real_t get_total_linear_damp() const = 0; // get density of this body space/area
virtual real_t get_total_angular_damp() const = 0; // get density of this body space/area
+ virtual Vector2 get_center_of_mass() const = 0;
virtual real_t get_inverse_mass() const = 0; // get the mass
virtual real_t get_inverse_inertia() const = 0; // get density of this body space
@@ -83,7 +84,6 @@ public:
virtual ObjectID get_contact_collider_id(int p_contact_idx) const = 0;
virtual Object *get_contact_collider_object(int p_contact_idx) const;
virtual int get_contact_collider_shape(int p_contact_idx) const = 0;
- virtual Variant get_contact_collider_shape_metadata(int p_contact_idx) const = 0;
virtual Vector2 get_contact_collider_velocity_at_position(int p_contact_idx) const = 0;
virtual real_t get_step() const = 0;
@@ -103,12 +103,12 @@ class PhysicsShapeQueryParameters2D : public RefCounted {
RID shape;
Transform2D transform;
Vector2 motion;
- real_t margin;
+ real_t margin = 0.0;
Set<RID> exclude;
- uint32_t collision_mask;
+ uint32_t collision_mask = UINT32_MAX;
- bool collide_with_bodies;
- bool collide_with_areas;
+ bool collide_with_bodies = true;
+ bool collide_with_areas = false;
protected:
static void _bind_methods();
@@ -139,8 +139,6 @@ public:
void set_exclude(const Vector<RID> &p_exclude);
Vector<RID> get_exclude() const;
-
- PhysicsShapeQueryParameters2D();
};
class PhysicsDirectSpaceState2D : public Object {
@@ -166,27 +164,25 @@ public:
ObjectID collider_id;
Object *collider = nullptr;
int shape = 0;
- Variant metadata;
};
- virtual bool intersect_ray(const Vector2 &p_from, const Vector2 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
+ virtual bool intersect_ray(const Vector2 &p_from, const Vector2 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
struct ShapeResult {
RID rid;
ObjectID collider_id;
Object *collider = nullptr;
int shape = 0;
- Variant metadata;
};
- virtual int intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_point = false) = 0;
- virtual int intersect_point_on_canvas(const Vector2 &p_point, ObjectID p_canvas_instance_id, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_point = false) = 0;
+ virtual int intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_point = false) = 0;
+ virtual int intersect_point_on_canvas(const Vector2 &p_point, ObjectID p_canvas_instance_id, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_point = false) = 0;
- virtual int intersect_shape(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
+ virtual int intersect_shape(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
- virtual bool cast_motion(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
+ virtual bool cast_motion(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
- virtual bool collide_shape(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, Vector2 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
+ virtual bool collide_shape(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, Vector2 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
struct ShapeRestInfo {
Vector2 point;
@@ -195,14 +191,14 @@ public:
ObjectID collider_id;
int shape = 0;
Vector2 linear_velocity; //velocity at contact point
- Variant metadata;
};
- virtual bool rest_info(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
+ virtual bool rest_info(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
PhysicsDirectSpaceState2D();
};
+class PhysicsTestMotionParameters2D;
class PhysicsTestMotionResult2D;
class PhysicsServer2D : public Object {
@@ -210,7 +206,7 @@ class PhysicsServer2D : public Object {
static PhysicsServer2D *singleton;
- virtual bool _body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin = 0.08, const Ref<PhysicsTestMotionResult2D> &p_result = Ref<PhysicsTestMotionResult2D>(), const Vector<RID> &p_exclude = Vector<RID>());
+ virtual bool _body_test_motion(RID p_body, const Ref<PhysicsTestMotionParameters2D> &p_parameters, const Ref<PhysicsTestMotionResult2D> &p_result = Ref<PhysicsTestMotionResult2D>());
protected:
static void _bind_methods();
@@ -219,7 +215,8 @@ public:
static PhysicsServer2D *get_singleton();
enum ShapeType {
- SHAPE_WORLD_MARGIN, ///< plane:"plane"
+ SHAPE_WORLD_BOUNDARY, ///< plane:"plane"
+ SHAPE_SEPARATION_RAY, ///< float:"length"
SHAPE_SEGMENT, ///< float:"length"
SHAPE_CIRCLE, ///< float:"radius"
SHAPE_RECTANGLE, ///< vec3:"extents"
@@ -229,7 +226,8 @@ public:
SHAPE_CUSTOM, ///< Server-Implementation based custom shape, calling shape_create() with this value will result in an error
};
- virtual RID world_margin_shape_create() = 0;
+ virtual RID world_boundary_shape_create() = 0;
+ virtual RID separation_ray_shape_create() = 0;
virtual RID segment_shape_create() = 0;
virtual RID circle_shape_create() = 0;
virtual RID rectangle_shape_create() = 0;
@@ -261,7 +259,6 @@ public:
SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD,
SPACE_PARAM_BODY_TIME_TO_SLEEP,
SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS,
- SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH,
};
virtual void space_set_param(RID p_space, SpaceParameter p_param, real_t p_value) = 0;
@@ -349,7 +346,7 @@ public:
BODY_MODE_STATIC,
BODY_MODE_KINEMATIC,
BODY_MODE_DYNAMIC,
- BODY_MODE_DYNAMIC_LOCKED,
+ BODY_MODE_DYNAMIC_LINEAR,
};
virtual RID body_create() = 0;
@@ -363,12 +360,10 @@ public:
virtual void body_add_shape(RID p_body, RID p_shape, const Transform2D &p_transform = Transform2D(), bool p_disabled = false) = 0;
virtual void body_set_shape(RID p_body, int p_shape_idx, RID p_shape) = 0;
virtual void body_set_shape_transform(RID p_body, int p_shape_idx, const Transform2D &p_transform) = 0;
- virtual void body_set_shape_metadata(RID p_body, int p_shape_idx, const Variant &p_metadata) = 0;
virtual int body_get_shape_count(RID p_body) const = 0;
virtual RID body_get_shape(RID p_body, int p_shape_idx) const = 0;
virtual Transform2D body_get_shape_transform(RID p_body, int p_shape_idx) const = 0;
- virtual Variant body_get_shape_metadata(RID p_body, int p_shape_idx) const = 0;
virtual void body_set_shape_disabled(RID p_body, int p_shape, bool p_disabled) = 0;
virtual void body_set_shape_as_one_way_collision(RID p_body, int p_shape, bool p_enabled, real_t p_margin = 0) = 0;
@@ -402,15 +397,18 @@ public:
BODY_PARAM_BOUNCE,
BODY_PARAM_FRICTION,
BODY_PARAM_MASS, ///< unused for static, always infinite
- BODY_PARAM_INERTIA, // read-only: computed from mass & shapes
+ BODY_PARAM_INERTIA,
+ BODY_PARAM_CENTER_OF_MASS,
BODY_PARAM_GRAVITY_SCALE,
BODY_PARAM_LINEAR_DAMP,
BODY_PARAM_ANGULAR_DAMP,
BODY_PARAM_MAX,
};
- virtual void body_set_param(RID p_body, BodyParameter p_param, real_t p_value) = 0;
- virtual real_t body_get_param(RID p_body, BodyParameter p_param) const = 0;
+ virtual void body_set_param(RID p_body, BodyParameter p_param, const Variant &p_value) = 0;
+ virtual Variant body_get_param(RID p_body, BodyParameter p_param) const = 0;
+
+ virtual void body_reset_mass_properties(RID p_body) = 0;
//state
enum BodyState {
@@ -455,6 +453,10 @@ public:
virtual void body_set_omit_force_integration(RID p_body, bool p_omit) = 0;
virtual bool body_is_omitting_force_integration(RID p_body) const = 0;
+ // Callback for C++ use only.
+ typedef void (*BodyStateCallback)(void *p_instance, PhysicsDirectBodyState2D *p_state);
+ virtual void body_set_state_sync_callback(RID p_body, void *p_instance, BodyStateCallback p_callback) = 0;
+
virtual void body_set_force_integration_callback(RID p_body, const Callable &p_callable, const Variant &p_udata = Variant()) = 0;
virtual bool body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, Vector2 *r_results, int p_result_max, int &r_result_count) = 0;
@@ -464,6 +466,22 @@ public:
// this function only works on physics process, errors and returns null otherwise
virtual PhysicsDirectBodyState2D *body_get_direct_state(RID p_body) = 0;
+ struct MotionParameters {
+ Transform2D from;
+ Vector2 motion;
+ real_t margin = 0.08;
+ bool collide_separation_ray = false;
+ Set<RID> exclude_bodies;
+ Set<ObjectID> exclude_objects;
+
+ MotionParameters() {}
+
+ MotionParameters(const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin = 0.08) :
+ from(p_from),
+ motion(p_motion),
+ margin(p_margin) {}
+ };
+
struct MotionResult {
Vector2 travel;
Vector2 remainder;
@@ -478,26 +496,13 @@ public:
ObjectID collider_id;
RID collider;
int collider_shape = 0;
- Variant collider_metadata;
real_t get_angle(Vector2 p_up_direction) const {
return Math::acos(collision_normal.dot(p_up_direction));
}
};
- virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin = 0.08, MotionResult *r_result = nullptr, const Set<RID> &p_exclude = Set<RID>()) = 0;
-
- struct SeparationResult {
- real_t collision_depth;
- Vector2 collision_point;
- Vector2 collision_normal;
- Vector2 collider_velocity;
- int collision_local_shape;
- ObjectID collider_id;
- RID collider;
- int collider_shape;
- Variant collider_metadata;
- };
+ virtual bool body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result = nullptr) = 0;
/* JOINT API */
@@ -580,11 +585,40 @@ public:
~PhysicsServer2D();
};
+class PhysicsTestMotionParameters2D : public RefCounted {
+ GDCLASS(PhysicsTestMotionParameters2D, RefCounted);
+
+ PhysicsServer2D::MotionParameters parameters;
+
+protected:
+ static void _bind_methods();
+
+public:
+ const PhysicsServer2D::MotionParameters &get_parameters() const { return parameters; }
+
+ const Transform2D &get_from() const { return parameters.from; }
+ void set_from(const Transform2D &p_from) { parameters.from = p_from; }
+
+ const Vector2 &get_motion() const { return parameters.motion; }
+ void set_motion(const Vector2 &p_motion) { parameters.motion = p_motion; }
+
+ real_t get_margin() const { return parameters.margin; }
+ void set_margin(real_t p_margin) { parameters.margin = p_margin; }
+
+ bool is_collide_separation_ray_enabled() const { return parameters.collide_separation_ray; }
+ void set_collide_separation_ray_enabled(bool p_enabled) { parameters.collide_separation_ray = p_enabled; }
+
+ Vector<RID> get_exclude_bodies() const;
+ void set_exclude_bodies(const Vector<RID> &p_exclude);
+
+ Array get_exclude_objects() const;
+ void set_exclude_objects(const Array &p_exclude);
+};
+
class PhysicsTestMotionResult2D : public RefCounted {
GDCLASS(PhysicsTestMotionResult2D, RefCounted);
PhysicsServer2D::MotionResult result;
- friend class PhysicsServer2D;
protected:
static void _bind_methods();
@@ -602,6 +636,7 @@ public:
RID get_collider_rid() const;
Object *get_collider() const;
int get_collider_shape() const;
+ int get_collision_local_shape() const;
real_t get_collision_depth() const;
real_t get_collision_safe_fraction() const;
real_t get_collision_unsafe_fraction() const;
diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp
index 53863cea72..90922cc250 100644
--- a/servers/physics_server_3d.cpp
+++ b/servers/physics_server_3d.cpp
@@ -194,7 +194,7 @@ Vector<RID> PhysicsShapeQueryParameters3D::get_exclude() const {
ret.resize(exclude.size());
int idx = 0;
for (Set<RID>::Element *E = exclude.front(); E; E = E->next()) {
- ret.write[idx] = E->get();
+ ret.write[idx++] = E->get();
}
return ret;
}
@@ -249,13 +249,6 @@ void PhysicsShapeQueryParameters3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas"), "set_collide_with_areas", "is_collide_with_areas_enabled");
}
-PhysicsShapeQueryParameters3D::PhysicsShapeQueryParameters3D() {
- margin = 0;
- collision_mask = 0x7FFFFFFF;
- collide_with_bodies = true;
- collide_with_areas = false;
-}
-
/////////////////////////////////////
Dictionary PhysicsDirectSpaceState3D::_intersect_ray(const Vector3 &p_from, const Vector3 &p_to, const Vector<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
@@ -360,7 +353,7 @@ PhysicsDirectSpaceState3D::PhysicsDirectSpaceState3D() {
}
void PhysicsDirectSpaceState3D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("intersect_ray", "from", "to", "exclude", "collision_mask", "collide_with_bodies", "collide_with_areas"), &PhysicsDirectSpaceState3D::_intersect_ray, DEFVAL(Array()), DEFVAL(0x7FFFFFFF), DEFVAL(true), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("intersect_ray", "from", "to", "exclude", "collision_mask", "collide_with_bodies", "collide_with_areas"), &PhysicsDirectSpaceState3D::_intersect_ray, DEFVAL(Array()), DEFVAL(UINT32_MAX), DEFVAL(true), DEFVAL(false));
ClassDB::bind_method(D_METHOD("intersect_shape", "shape", "max_results"), &PhysicsDirectSpaceState3D::_intersect_shape, DEFVAL(32));
ClassDB::bind_method(D_METHOD("cast_motion", "shape", "motion"), &PhysicsDirectSpaceState3D::_cast_motion);
ClassDB::bind_method(D_METHOD("collide_shape", "shape", "max_results"), &PhysicsDirectSpaceState3D::_collide_shape, DEFVAL(32));
@@ -369,6 +362,77 @@ void PhysicsDirectSpaceState3D::_bind_methods() {
///////////////////////////////
+Vector<RID> PhysicsTestMotionParameters3D::get_exclude_bodies() const {
+ Vector<RID> exclude;
+ exclude.resize(parameters.exclude_bodies.size());
+
+ int body_index = 0;
+ for (RID body : parameters.exclude_bodies) {
+ exclude.write[body_index++] = body;
+ }
+
+ return exclude;
+}
+
+void PhysicsTestMotionParameters3D::set_exclude_bodies(const Vector<RID> &p_exclude) {
+ for (RID body : p_exclude) {
+ parameters.exclude_bodies.insert(body);
+ }
+}
+
+Array PhysicsTestMotionParameters3D::get_exclude_objects() const {
+ Array exclude;
+ exclude.resize(parameters.exclude_objects.size());
+
+ int object_index = 0;
+ for (ObjectID object_id : parameters.exclude_objects) {
+ exclude[object_index++] = object_id;
+ }
+
+ return exclude;
+}
+
+void PhysicsTestMotionParameters3D::set_exclude_objects(const Array &p_exclude) {
+ for (int i = 0; i < p_exclude.size(); ++i) {
+ ObjectID object_id = p_exclude[i];
+ ERR_CONTINUE(object_id.is_null());
+ parameters.exclude_objects.insert(object_id);
+ }
+}
+
+void PhysicsTestMotionParameters3D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("get_from"), &PhysicsTestMotionParameters3D::get_from);
+ ClassDB::bind_method(D_METHOD("set_from", "from"), &PhysicsTestMotionParameters3D::set_from);
+
+ ClassDB::bind_method(D_METHOD("get_motion"), &PhysicsTestMotionParameters3D::get_motion);
+ ClassDB::bind_method(D_METHOD("set_motion", "motion"), &PhysicsTestMotionParameters3D::set_motion);
+
+ ClassDB::bind_method(D_METHOD("get_margin"), &PhysicsTestMotionParameters3D::get_margin);
+ ClassDB::bind_method(D_METHOD("set_margin", "margin"), &PhysicsTestMotionParameters3D::set_margin);
+
+ ClassDB::bind_method(D_METHOD("get_max_collisions"), &PhysicsTestMotionParameters3D::get_max_collisions);
+ ClassDB::bind_method(D_METHOD("set_max_collisions", "max_collisions"), &PhysicsTestMotionParameters3D::set_max_collisions);
+
+ ClassDB::bind_method(D_METHOD("is_collide_separation_ray_enabled"), &PhysicsTestMotionParameters3D::is_collide_separation_ray_enabled);
+ ClassDB::bind_method(D_METHOD("set_collide_separation_ray_enabled", "enabled"), &PhysicsTestMotionParameters3D::set_collide_separation_ray_enabled);
+
+ ClassDB::bind_method(D_METHOD("get_exclude_bodies"), &PhysicsTestMotionParameters3D::get_exclude_bodies);
+ ClassDB::bind_method(D_METHOD("set_exclude_bodies", "exclude_list"), &PhysicsTestMotionParameters3D::set_exclude_bodies);
+
+ ClassDB::bind_method(D_METHOD("get_exclude_objects"), &PhysicsTestMotionParameters3D::get_exclude_objects);
+ ClassDB::bind_method(D_METHOD("set_exclude_objects", "exclude_list"), &PhysicsTestMotionParameters3D::set_exclude_objects);
+
+ ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "from"), "set_from", "get_from");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "motion"), "set_motion", "get_motion");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin"), "set_margin", "get_margin");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "max_collisions"), "set_max_collisions", "get_max_collisions");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_separation_ray"), "set_collide_separation_ray_enabled", "is_collide_separation_ray_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude_bodies"), "set_exclude_bodies", "get_exclude_bodies");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude_objects"), "set_exclude_objects", "get_exclude_objects");
+}
+
+///////////////////////////////
+
Vector3 PhysicsTestMotionResult3D::get_travel() const {
return result.travel;
}
@@ -377,92 +441,99 @@ Vector3 PhysicsTestMotionResult3D::get_remainder() const {
return result.remainder;
}
-Vector3 PhysicsTestMotionResult3D::get_collision_point() const {
- return result.collision_point;
+real_t PhysicsTestMotionResult3D::get_collision_safe_fraction() const {
+ return result.collision_safe_fraction;
}
-Vector3 PhysicsTestMotionResult3D::get_collision_normal() const {
- return result.collision_normal;
+real_t PhysicsTestMotionResult3D::get_collision_unsafe_fraction() const {
+ return result.collision_unsafe_fraction;
}
-Vector3 PhysicsTestMotionResult3D::get_collider_velocity() const {
- return result.collider_velocity;
+int PhysicsTestMotionResult3D::get_collision_count() const {
+ return result.collision_count;
}
-ObjectID PhysicsTestMotionResult3D::get_collider_id() const {
- return result.collider_id;
+Vector3 PhysicsTestMotionResult3D::get_collision_point(int p_collision_index) const {
+ ERR_FAIL_INDEX_V(p_collision_index, result.collision_count, Vector3());
+ return result.collisions[p_collision_index].position;
}
-RID PhysicsTestMotionResult3D::get_collider_rid() const {
- return result.collider;
+Vector3 PhysicsTestMotionResult3D::get_collision_normal(int p_collision_index) const {
+ ERR_FAIL_INDEX_V(p_collision_index, result.collision_count, Vector3());
+ return result.collisions[p_collision_index].normal;
}
-Object *PhysicsTestMotionResult3D::get_collider() const {
- return ObjectDB::get_instance(result.collider_id);
+Vector3 PhysicsTestMotionResult3D::get_collider_velocity(int p_collision_index) const {
+ ERR_FAIL_INDEX_V(p_collision_index, result.collision_count, Vector3());
+ return result.collisions[p_collision_index].collider_velocity;
}
-int PhysicsTestMotionResult3D::get_collider_shape() const {
- return result.collider_shape;
+ObjectID PhysicsTestMotionResult3D::get_collider_id(int p_collision_index) const {
+ ERR_FAIL_INDEX_V(p_collision_index, result.collision_count, ObjectID());
+ return result.collisions[p_collision_index].collider_id;
}
-real_t PhysicsTestMotionResult3D::get_collision_depth() const {
- return result.collision_depth;
+RID PhysicsTestMotionResult3D::get_collider_rid(int p_collision_index) const {
+ ERR_FAIL_INDEX_V(p_collision_index, result.collision_count, RID());
+ return result.collisions[p_collision_index].collider;
}
-real_t PhysicsTestMotionResult3D::get_collision_safe_fraction() const {
- return result.collision_safe_fraction;
+Object *PhysicsTestMotionResult3D::get_collider(int p_collision_index) const {
+ ERR_FAIL_INDEX_V(p_collision_index, result.collision_count, nullptr);
+ return ObjectDB::get_instance(result.collisions[p_collision_index].collider_id);
}
-real_t PhysicsTestMotionResult3D::get_collision_unsafe_fraction() const {
- return result.collision_unsafe_fraction;
+int PhysicsTestMotionResult3D::get_collider_shape(int p_collision_index) const {
+ ERR_FAIL_INDEX_V(p_collision_index, result.collision_count, 0);
+ return result.collisions[p_collision_index].collider_shape;
+}
+
+int PhysicsTestMotionResult3D::get_collision_local_shape(int p_collision_index) const {
+ ERR_FAIL_INDEX_V(p_collision_index, result.collision_count, 0);
+ return result.collisions[p_collision_index].local_shape;
+}
+
+real_t PhysicsTestMotionResult3D::get_collision_depth(int p_collision_index) const {
+ ERR_FAIL_INDEX_V(p_collision_index, result.collision_count, 0.0);
+ return result.collisions[p_collision_index].depth;
}
void PhysicsTestMotionResult3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_travel"), &PhysicsTestMotionResult3D::get_travel);
ClassDB::bind_method(D_METHOD("get_remainder"), &PhysicsTestMotionResult3D::get_remainder);
- ClassDB::bind_method(D_METHOD("get_collision_point"), &PhysicsTestMotionResult3D::get_collision_point);
- ClassDB::bind_method(D_METHOD("get_collision_normal"), &PhysicsTestMotionResult3D::get_collision_normal);
- ClassDB::bind_method(D_METHOD("get_collider_velocity"), &PhysicsTestMotionResult3D::get_collider_velocity);
- ClassDB::bind_method(D_METHOD("get_collider_id"), &PhysicsTestMotionResult3D::get_collider_id);
- ClassDB::bind_method(D_METHOD("get_collider_rid"), &PhysicsTestMotionResult3D::get_collider_rid);
- ClassDB::bind_method(D_METHOD("get_collider"), &PhysicsTestMotionResult3D::get_collider);
- ClassDB::bind_method(D_METHOD("get_collider_shape"), &PhysicsTestMotionResult3D::get_collider_shape);
- ClassDB::bind_method(D_METHOD("get_collision_depth"), &PhysicsTestMotionResult3D::get_collision_depth);
ClassDB::bind_method(D_METHOD("get_collision_safe_fraction"), &PhysicsTestMotionResult3D::get_collision_safe_fraction);
ClassDB::bind_method(D_METHOD("get_collision_unsafe_fraction"), &PhysicsTestMotionResult3D::get_collision_unsafe_fraction);
-
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "travel"), "", "get_travel");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "remainder"), "", "get_remainder");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "collision_point"), "", "get_collision_point");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "collision_normal"), "", "get_collision_normal");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "collider_velocity"), "", "get_collider_velocity");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "collider_id", PROPERTY_HINT_OBJECT_ID), "", "get_collider_id");
- ADD_PROPERTY(PropertyInfo(Variant::RID, "collider_rid"), "", "get_collider_rid");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "collider"), "", "get_collider");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "collider_shape"), "", "get_collider_shape");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision_depth"), "", "get_collision_depth");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision_safe_fraction"), "", "get_collision_safe_fraction");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision_unsafe_fraction"), "", "get_collision_unsafe_fraction");
+ ClassDB::bind_method(D_METHOD("get_collision_count"), &PhysicsTestMotionResult3D::get_collision_count);
+ ClassDB::bind_method(D_METHOD("get_collision_point", "collision_index"), &PhysicsTestMotionResult3D::get_collision_point, DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("get_collision_normal", "collision_index"), &PhysicsTestMotionResult3D::get_collision_normal, DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("get_collider_velocity", "collision_index"), &PhysicsTestMotionResult3D::get_collider_velocity, DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("get_collider_id", "collision_index"), &PhysicsTestMotionResult3D::get_collider_id, DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("get_collider_rid", "collision_index"), &PhysicsTestMotionResult3D::get_collider_rid, DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("get_collider", "collision_index"), &PhysicsTestMotionResult3D::get_collider, DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("get_collider_shape", "collision_index"), &PhysicsTestMotionResult3D::get_collider_shape, DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("get_collision_local_shape", "collision_index"), &PhysicsTestMotionResult3D::get_collision_local_shape, DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("get_collision_depth", "collision_index"), &PhysicsTestMotionResult3D::get_collision_depth, DEFVAL(0));
}
///////////////////////////////////////
-bool PhysicsServer3D::_body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin, const Ref<PhysicsTestMotionResult3D> &p_result, const Vector<RID> &p_exclude) {
- MotionResult *r = nullptr;
+bool PhysicsServer3D::_body_test_motion(RID p_body, const Ref<PhysicsTestMotionParameters3D> &p_parameters, const Ref<PhysicsTestMotionResult3D> &p_result) {
+ ERR_FAIL_COND_V(!p_parameters.is_valid(), false);
+
+ MotionResult *result_ptr = nullptr;
if (p_result.is_valid()) {
- r = p_result->get_result_ptr();
+ result_ptr = p_result->get_result_ptr();
}
- Set<RID> exclude;
- for (int i = 0; i < p_exclude.size(); i++) {
- exclude.insert(p_exclude[i]);
- }
- return body_test_motion(p_body, p_from, p_motion, p_margin, r, exclude);
+
+ return body_test_motion(p_body, p_parameters->get_parameters(), result_ptr);
}
RID PhysicsServer3D::shape_create(ShapeType p_shape) {
switch (p_shape) {
- case SHAPE_PLANE:
- return plane_shape_create();
+ case SHAPE_WORLD_BOUNDARY:
+ return world_boundary_shape_create();
+ case SHAPE_SEPARATION_RAY:
+ return separation_ray_shape_create();
case SHAPE_SPHERE:
return sphere_shape_create();
case SHAPE_BOX:
@@ -487,7 +558,8 @@ RID PhysicsServer3D::shape_create(ShapeType p_shape) {
void PhysicsServer3D::_bind_methods() {
#ifndef _3D_DISABLED
- ClassDB::bind_method(D_METHOD("plane_shape_create"), &PhysicsServer3D::plane_shape_create);
+ ClassDB::bind_method(D_METHOD("world_boundary_shape_create"), &PhysicsServer3D::world_boundary_shape_create);
+ ClassDB::bind_method(D_METHOD("separation_ray_shape_create"), &PhysicsServer3D::separation_ray_shape_create);
ClassDB::bind_method(D_METHOD("sphere_shape_create"), &PhysicsServer3D::sphere_shape_create);
ClassDB::bind_method(D_METHOD("box_shape_create"), &PhysicsServer3D::box_shape_create);
ClassDB::bind_method(D_METHOD("capsule_shape_create"), &PhysicsServer3D::capsule_shape_create);
@@ -581,6 +653,8 @@ void PhysicsServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("body_set_param", "body", "param", "value"), &PhysicsServer3D::body_set_param);
ClassDB::bind_method(D_METHOD("body_get_param", "body", "param"), &PhysicsServer3D::body_get_param);
+ ClassDB::bind_method(D_METHOD("body_reset_mass_properties", "body"), &PhysicsServer3D::body_reset_mass_properties);
+
ClassDB::bind_method(D_METHOD("body_set_state", "body", "state", "value"), &PhysicsServer3D::body_set_state);
ClassDB::bind_method(D_METHOD("body_get_state", "body", "state"), &PhysicsServer3D::body_get_state);
@@ -609,7 +683,7 @@ void PhysicsServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("body_set_ray_pickable", "body", "enable"), &PhysicsServer3D::body_set_ray_pickable);
- ClassDB::bind_method(D_METHOD("body_test_motion", "body", "from", "motion", "margin", "result", "exclude"), &PhysicsServer3D::_body_test_motion, DEFVAL(0.001), DEFVAL(Variant()), DEFVAL(Array()));
+ ClassDB::bind_method(D_METHOD("body_test_motion", "body", "parameters", "result"), &PhysicsServer3D::_body_test_motion, DEFVAL(Variant()));
ClassDB::bind_method(D_METHOD("body_get_direct_state", "body"), &PhysicsServer3D::body_get_direct_state);
@@ -747,7 +821,8 @@ void PhysicsServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_process_info", "process_info"), &PhysicsServer3D::get_process_info);
- BIND_ENUM_CONSTANT(SHAPE_PLANE);
+ BIND_ENUM_CONSTANT(SHAPE_WORLD_BOUNDARY);
+ BIND_ENUM_CONSTANT(SHAPE_SEPARATION_RAY);
BIND_ENUM_CONSTANT(SHAPE_SPHERE);
BIND_ENUM_CONSTANT(SHAPE_BOX);
BIND_ENUM_CONSTANT(SHAPE_CAPSULE);
@@ -766,6 +841,10 @@ void PhysicsServer3D::_bind_methods() {
BIND_ENUM_CONSTANT(AREA_PARAM_LINEAR_DAMP);
BIND_ENUM_CONSTANT(AREA_PARAM_ANGULAR_DAMP);
BIND_ENUM_CONSTANT(AREA_PARAM_PRIORITY);
+ BIND_ENUM_CONSTANT(AREA_PARAM_WIND_FORCE_MAGNITUDE);
+ BIND_ENUM_CONSTANT(AREA_PARAM_WIND_SOURCE);
+ BIND_ENUM_CONSTANT(AREA_PARAM_WIND_DIRECTION);
+ BIND_ENUM_CONSTANT(AREA_PARAM_WIND_ATTENUATION_FACTOR);
BIND_ENUM_CONSTANT(AREA_SPACE_OVERRIDE_DISABLED);
BIND_ENUM_CONSTANT(AREA_SPACE_OVERRIDE_COMBINE);
@@ -776,11 +855,13 @@ void PhysicsServer3D::_bind_methods() {
BIND_ENUM_CONSTANT(BODY_MODE_STATIC);
BIND_ENUM_CONSTANT(BODY_MODE_KINEMATIC);
BIND_ENUM_CONSTANT(BODY_MODE_DYNAMIC);
- BIND_ENUM_CONSTANT(BODY_MODE_DYNAMIC_LOCKED);
+ BIND_ENUM_CONSTANT(BODY_MODE_DYNAMIC_LINEAR);
BIND_ENUM_CONSTANT(BODY_PARAM_BOUNCE);
BIND_ENUM_CONSTANT(BODY_PARAM_FRICTION);
BIND_ENUM_CONSTANT(BODY_PARAM_MASS);
+ BIND_ENUM_CONSTANT(BODY_PARAM_INERTIA);
+ BIND_ENUM_CONSTANT(BODY_PARAM_CENTER_OF_MASS);
BIND_ENUM_CONSTANT(BODY_PARAM_GRAVITY_SCALE);
BIND_ENUM_CONSTANT(BODY_PARAM_LINEAR_DAMP);
BIND_ENUM_CONSTANT(BODY_PARAM_ANGULAR_DAMP);
@@ -807,7 +888,6 @@ void PhysicsServer3D::_bind_methods() {
BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_TIME_TO_SLEEP);
BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO);
BIND_ENUM_CONSTANT(SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS);
- BIND_ENUM_CONSTANT(SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH);
BIND_ENUM_CONSTANT(BODY_AXIS_LINEAR_X);
BIND_ENUM_CONSTANT(BODY_AXIS_LINEAR_Y);
diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h
index f806fd55be..c609afc11e 100644
--- a/servers/physics_server_3d.h
+++ b/servers/physics_server_3d.h
@@ -103,12 +103,12 @@ class PhysicsShapeQueryParameters3D : public RefCounted {
RES shape_ref;
RID shape;
Transform3D transform;
- real_t margin;
+ real_t margin = 0.0;
Set<RID> exclude;
- uint32_t collision_mask;
+ uint32_t collision_mask = UINT32_MAX;
- bool collide_with_bodies;
- bool collide_with_areas;
+ bool collide_with_bodies = true;
+ bool collide_with_areas = false;
protected:
static void _bind_methods();
@@ -136,15 +136,13 @@ public:
void set_collide_with_areas(bool p_enable);
bool is_collide_with_areas_enabled() const;
-
- PhysicsShapeQueryParameters3D();
};
class PhysicsDirectSpaceState3D : public Object {
GDCLASS(PhysicsDirectSpaceState3D, Object);
private:
- Dictionary _intersect_ray(const Vector3 &p_from, const Vector3 &p_to, const Vector<RID> &p_exclude = Vector<RID>(), uint32_t p_collision_mask = 0, bool p_collide_with_bodies = true, bool p_collide_with_areas = false);
+ Dictionary _intersect_ray(const Vector3 &p_from, const Vector3 &p_to, const Vector<RID> &p_exclude = Vector<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false);
Array _intersect_shape(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, int p_max_results = 32);
Array _cast_motion(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, const Vector3 &p_motion);
Array _collide_shape(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, int p_max_results = 32);
@@ -161,7 +159,7 @@ public:
int shape = 0;
};
- virtual int intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
+ virtual int intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
struct RayResult {
Vector3 position;
@@ -172,9 +170,9 @@ public:
int shape = 0;
};
- virtual bool intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_ray = false) = 0;
+ virtual bool intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_ray = false) = 0;
- virtual int intersect_shape(const RID &p_shape, const Transform3D &p_xform, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
+ virtual int intersect_shape(const RID &p_shape, const Transform3D &p_xform, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
struct ShapeRestInfo {
Vector3 point;
@@ -185,11 +183,11 @@ public:
Vector3 linear_velocity; //velocity at contact point
};
- virtual bool cast_motion(const RID &p_shape, const Transform3D &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, ShapeRestInfo *r_info = nullptr) = 0;
+ virtual bool cast_motion(const RID &p_shape, const Transform3D &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, ShapeRestInfo *r_info = nullptr) = 0;
- virtual bool collide_shape(RID p_shape, const Transform3D &p_shape_xform, real_t p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
+ virtual bool collide_shape(RID p_shape, const Transform3D &p_shape_xform, real_t p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
- virtual bool rest_info(RID p_shape, const Transform3D &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
+ virtual bool rest_info(RID p_shape, const Transform3D &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
virtual Vector3 get_closest_point_to_object_volume(RID p_object, const Vector3 p_point) const = 0;
@@ -205,6 +203,7 @@ public:
virtual ~RenderingServerHandler() {}
};
+class PhysicsTestMotionParameters3D;
class PhysicsTestMotionResult3D;
class PhysicsServer3D : public Object {
@@ -212,7 +211,7 @@ class PhysicsServer3D : public Object {
static PhysicsServer3D *singleton;
- virtual bool _body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin = 0.001, const Ref<PhysicsTestMotionResult3D> &p_result = Ref<PhysicsTestMotionResult3D>(), const Vector<RID> &p_exclude = Vector<RID>());
+ virtual bool _body_test_motion(RID p_body, const Ref<PhysicsTestMotionParameters3D> &p_parameters, const Ref<PhysicsTestMotionResult3D> &p_result = Ref<PhysicsTestMotionResult3D>());
protected:
static void _bind_methods();
@@ -221,7 +220,8 @@ public:
static PhysicsServer3D *get_singleton();
enum ShapeType {
- SHAPE_PLANE, ///< plane:"plane"
+ SHAPE_WORLD_BOUNDARY, ///< plane:"plane"
+ SHAPE_SEPARATION_RAY, ///< float:"length"
SHAPE_SPHERE, ///< float:"radius"
SHAPE_BOX, ///< vec3:"extents"
SHAPE_CAPSULE, ///< dict( float:"radius", float:"height"):capsule
@@ -235,7 +235,8 @@ public:
RID shape_create(ShapeType p_shape);
- virtual RID plane_shape_create() = 0;
+ virtual RID world_boundary_shape_create() = 0;
+ virtual RID separation_ray_shape_create() = 0;
virtual RID sphere_shape_create() = 0;
virtual RID box_shape_create() = 0;
virtual RID capsule_shape_create() = 0;
@@ -271,7 +272,6 @@ public:
SPACE_PARAM_BODY_TIME_TO_SLEEP,
SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO,
SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS,
- SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH
};
virtual void space_set_param(RID p_space, SpaceParameter p_param, real_t p_value) = 0;
@@ -298,7 +298,11 @@ public:
AREA_PARAM_GRAVITY_POINT_ATTENUATION,
AREA_PARAM_LINEAR_DAMP,
AREA_PARAM_ANGULAR_DAMP,
- AREA_PARAM_PRIORITY
+ AREA_PARAM_PRIORITY,
+ AREA_PARAM_WIND_FORCE_MAGNITUDE,
+ AREA_PARAM_WIND_SOURCE,
+ AREA_PARAM_WIND_DIRECTION,
+ AREA_PARAM_WIND_ATTENUATION_FACTOR,
};
virtual RID area_create() = 0;
@@ -357,7 +361,7 @@ public:
BODY_MODE_STATIC,
BODY_MODE_KINEMATIC,
BODY_MODE_DYNAMIC,
- BODY_MODE_DYNAMIC_LOCKED,
+ BODY_MODE_DYNAMIC_LINEAR,
};
virtual RID body_create() = 0;
@@ -401,14 +405,18 @@ public:
BODY_PARAM_BOUNCE,
BODY_PARAM_FRICTION,
BODY_PARAM_MASS, ///< unused for static, always infinite
+ BODY_PARAM_INERTIA,
+ BODY_PARAM_CENTER_OF_MASS,
BODY_PARAM_GRAVITY_SCALE,
BODY_PARAM_LINEAR_DAMP,
BODY_PARAM_ANGULAR_DAMP,
BODY_PARAM_MAX,
};
- virtual void body_set_param(RID p_body, BodyParameter p_param, real_t p_value) = 0;
- virtual real_t body_get_param(RID p_body, BodyParameter p_param) const = 0;
+ virtual void body_set_param(RID p_body, BodyParameter p_param, const Variant &p_value) = 0;
+ virtual Variant body_get_param(RID p_body, BodyParameter p_param) const = 0;
+
+ virtual void body_reset_mass_properties(RID p_body) = 0;
//state
enum BodyState {
@@ -465,6 +473,10 @@ public:
virtual void body_set_omit_force_integration(RID p_body, bool p_omit) = 0;
virtual bool body_is_omitting_force_integration(RID p_body) const = 0;
+ // Callback for C++ use only.
+ typedef void (*BodyStateCallback)(void *p_instance, PhysicsDirectBodyState3D *p_state);
+ virtual void body_set_state_sync_callback(RID p_body, void *p_instance, BodyStateCallback p_callback) = 0;
+
virtual void body_set_force_integration_callback(RID p_body, const Callable &p_callable, const Variant &p_udata = Variant()) = 0;
virtual void body_set_ray_pickable(RID p_body, bool p_enable) = 0;
@@ -472,28 +484,50 @@ public:
// this function only works on physics process, errors and returns null otherwise
virtual PhysicsDirectBodyState3D *body_get_direct_state(RID p_body) = 0;
- struct MotionResult {
- Vector3 travel;
- Vector3 remainder;
+ struct MotionParameters {
+ Transform3D from;
+ Vector3 motion;
+ real_t margin = 0.001;
+ int max_collisions = 1;
+ bool collide_separation_ray = false;
+ Set<RID> exclude_bodies;
+ Set<ObjectID> exclude_objects;
+
+ MotionParameters() {}
+
+ MotionParameters(const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin = 0.001) :
+ from(p_from),
+ motion(p_motion),
+ margin(p_margin) {}
+ };
- Vector3 collision_point;
- Vector3 collision_normal;
+ struct MotionCollision {
+ Vector3 position;
+ Vector3 normal;
Vector3 collider_velocity;
- real_t collision_depth = 0.0;
- real_t collision_safe_fraction = 0.0;
- real_t collision_unsafe_fraction = 0.0;
- int collision_local_shape = 0;
+ real_t depth = 0.0;
+ int local_shape = 0;
ObjectID collider_id;
RID collider;
int collider_shape = 0;
- Variant collider_metadata;
real_t get_angle(Vector3 p_up_direction) const {
- return Math::acos(collision_normal.dot(p_up_direction));
+ return Math::acos(normal.dot(p_up_direction));
}
};
- virtual bool body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin = 0.001, MotionResult *r_result = nullptr, const Set<RID> &p_exclude = Set<RID>()) = 0;
+ struct MotionResult {
+ Vector3 travel;
+ Vector3 remainder;
+ real_t collision_safe_fraction = 0.0;
+ real_t collision_unsafe_fraction = 0.0;
+
+ static const int MAX_COLLISIONS = 32;
+ MotionCollision collisions[MAX_COLLISIONS];
+ int collision_count = 0;
+ };
+
+ virtual bool body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result = nullptr) = 0;
/* SOFT BODY */
@@ -504,7 +538,7 @@ public:
virtual void soft_body_set_space(RID p_body, RID p_space) = 0;
virtual RID soft_body_get_space(RID p_body) const = 0;
- virtual void soft_body_set_mesh(RID p_body, const REF &p_mesh) = 0;
+ virtual void soft_body_set_mesh(RID p_body, RID p_mesh) = 0;
virtual AABB soft_body_get_bounds(RID p_body) const = 0;
@@ -744,11 +778,43 @@ public:
~PhysicsServer3D();
};
+class PhysicsTestMotionParameters3D : public RefCounted {
+ GDCLASS(PhysicsTestMotionParameters3D, RefCounted);
+
+ PhysicsServer3D::MotionParameters parameters;
+
+protected:
+ static void _bind_methods();
+
+public:
+ const PhysicsServer3D::MotionParameters &get_parameters() const { return parameters; }
+
+ const Transform3D &get_from() const { return parameters.from; }
+ void set_from(const Transform3D &p_from) { parameters.from = p_from; }
+
+ const Vector3 &get_motion() const { return parameters.motion; }
+ void set_motion(const Vector3 &p_motion) { parameters.motion = p_motion; }
+
+ real_t get_margin() const { return parameters.margin; }
+ void set_margin(real_t p_margin) { parameters.margin = p_margin; }
+
+ int get_max_collisions() const { return parameters.max_collisions; }
+ void set_max_collisions(int p_max_collisions) { parameters.max_collisions = p_max_collisions; }
+
+ bool is_collide_separation_ray_enabled() const { return parameters.collide_separation_ray; }
+ void set_collide_separation_ray_enabled(bool p_enabled) { parameters.collide_separation_ray = p_enabled; }
+
+ Vector<RID> get_exclude_bodies() const;
+ void set_exclude_bodies(const Vector<RID> &p_exclude);
+
+ Array get_exclude_objects() const;
+ void set_exclude_objects(const Array &p_exclude);
+};
+
class PhysicsTestMotionResult3D : public RefCounted {
GDCLASS(PhysicsTestMotionResult3D, RefCounted);
PhysicsServer3D::MotionResult result;
- friend class PhysicsServer3D;
protected:
static void _bind_methods();
@@ -758,17 +824,20 @@ public:
Vector3 get_travel() const;
Vector3 get_remainder() const;
-
- Vector3 get_collision_point() const;
- Vector3 get_collision_normal() const;
- Vector3 get_collider_velocity() const;
- ObjectID get_collider_id() const;
- RID get_collider_rid() const;
- Object *get_collider() const;
- int get_collider_shape() const;
- real_t get_collision_depth() const;
real_t get_collision_safe_fraction() const;
real_t get_collision_unsafe_fraction() const;
+
+ int get_collision_count() const;
+
+ Vector3 get_collision_point(int p_collision_index = 0) const;
+ Vector3 get_collision_normal(int p_collision_index = 0) const;
+ Vector3 get_collider_velocity(int p_collision_index = 0) const;
+ ObjectID get_collider_id(int p_collision_index = 0) const;
+ RID get_collider_rid(int p_collision_index = 0) const;
+ Object *get_collider(int p_collision_index = 0) const;
+ int get_collider_shape(int p_collision_index = 0) const;
+ int get_collision_local_shape(int p_collision_index = 0) const;
+ real_t get_collision_depth(int p_collision_index = 0) const;
};
typedef PhysicsServer3D *(*CreatePhysicsServer3DCallback)();
diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp
index 857f112102..28cd8374c0 100644
--- a/servers/register_server_types.cpp
+++ b/servers/register_server_types.cpp
@@ -70,8 +70,10 @@
#include "rendering/rendering_device_binds.h"
#include "rendering_server.h"
#include "servers/rendering/shader_types.h"
+#include "text/text_server_extension.h"
#include "text_server.h"
#include "xr/xr_interface.h"
+#include "xr/xr_interface_extension.h"
#include "xr/xr_positional_tracker.h"
#include "xr_server.h"
@@ -106,15 +108,11 @@ static bool has_server_feature_callback(const String &p_feature) {
void preregister_server_types() {
shader_types = memnew(ShaderTypes);
- GLOBAL_DEF("internationalization/rendering/text_driver", "");
- String text_driver_options;
- for (int i = 0; i < TextServerManager::get_interface_count(); i++) {
- if (i > 0) {
- text_driver_options += ",";
- }
- text_driver_options += TextServerManager::get_interface_name(i);
- }
- ProjectSettings::get_singleton()->set_custom_property_info("internationalization/rendering/text_driver", PropertyInfo(Variant::STRING, "internationalization/rendering/text_driver", PROPERTY_HINT_ENUM, text_driver_options));
+ GDREGISTER_CLASS(TextServerManager);
+ GDREGISTER_VIRTUAL_CLASS(TextServer);
+ GDREGISTER_CLASS(TextServerExtension);
+
+ Engine::get_singleton()->add_singleton(Engine::Singleton("TextServerManager", TextServerManager::get_singleton(), "TextServerManager"));
}
void register_server_types() {
@@ -124,10 +122,6 @@ void register_server_types() {
GDREGISTER_VIRTUAL_CLASS(RenderingServer);
GDREGISTER_CLASS(AudioServer);
- GDREGISTER_CLASS(TextServerManager);
- GDREGISTER_VIRTUAL_CLASS(TextServer);
- TextServer::initialize_hex_code_box_fonts();
-
GDREGISTER_VIRTUAL_CLASS(PhysicsServer2D);
GDREGISTER_VIRTUAL_CLASS(PhysicsServer3D);
GDREGISTER_VIRTUAL_CLASS(NavigationServer2D);
@@ -138,10 +132,11 @@ void register_server_types() {
GDREGISTER_VIRTUAL_CLASS(RenderingDevice);
GDREGISTER_VIRTUAL_CLASS(XRInterface);
+ GDREGISTER_CLASS(XRInterfaceExtension); // can't register this as virtual because we need a creation function for our extensions.
GDREGISTER_CLASS(XRPositionalTracker);
- GDREGISTER_VIRTUAL_CLASS(AudioStream);
- GDREGISTER_VIRTUAL_CLASS(AudioStreamPlayback);
+ GDREGISTER_CLASS(AudioStream);
+ GDREGISTER_CLASS(AudioStreamPlayback);
GDREGISTER_VIRTUAL_CLASS(AudioStreamPlaybackResampled);
GDREGISTER_CLASS(AudioStreamMicrophone);
GDREGISTER_CLASS(AudioStreamRandomPitch);
@@ -213,12 +208,14 @@ void register_server_types() {
GDREGISTER_VIRTUAL_CLASS(PhysicsDirectBodyState2D);
GDREGISTER_VIRTUAL_CLASS(PhysicsDirectSpaceState2D);
+ GDREGISTER_CLASS(PhysicsTestMotionParameters2D);
GDREGISTER_CLASS(PhysicsTestMotionResult2D);
GDREGISTER_CLASS(PhysicsShapeQueryParameters2D);
GDREGISTER_CLASS(PhysicsShapeQueryParameters3D);
GDREGISTER_VIRTUAL_CLASS(PhysicsDirectBodyState3D);
GDREGISTER_VIRTUAL_CLASS(PhysicsDirectSpaceState3D);
+ GDREGISTER_CLASS(PhysicsTestMotionParameters3D);
GDREGISTER_CLASS(PhysicsTestMotionResult3D);
// Physics 2D
@@ -242,7 +239,6 @@ void unregister_server_types() {
NativeExtensionManager::get_singleton()->deinitialize_extensions(NativeExtension::INITIALIZATION_LEVEL_SERVERS);
memdelete(shader_types);
- TextServer::finish_hex_code_box_fonts();
}
void register_server_singletons() {
@@ -253,7 +249,6 @@ void register_server_singletons() {
Engine::get_singleton()->add_singleton(Engine::Singleton("PhysicsServer3D", PhysicsServer3D::get_singleton(), "PhysicsServer3D"));
Engine::get_singleton()->add_singleton(Engine::Singleton("NavigationServer2D", NavigationServer2D::get_singleton_mut(), "NavigationServer2D"));
Engine::get_singleton()->add_singleton(Engine::Singleton("NavigationServer3D", NavigationServer3D::get_singleton_mut(), "NavigationServer3D"));
- Engine::get_singleton()->add_singleton(Engine::Singleton("TextServerManager", TextServerManager::get_singleton(), "TextServerManager"));
Engine::get_singleton()->add_singleton(Engine::Singleton("XRServer", XRServer::get_singleton(), "XRServer"));
Engine::get_singleton()->add_singleton(Engine::Singleton("CameraServer", CameraServer::get_singleton(), "CameraServer"));
}
diff --git a/servers/rendering/rasterizer_dummy.h b/servers/rendering/rasterizer_dummy.h
index f58d124140..7821210284 100644
--- a/servers/rendering/rasterizer_dummy.h
+++ b/servers/rendering/rasterizer_dummy.h
@@ -103,7 +103,7 @@ public:
void environment_set_bg_color(RID p_env, const Color &p_color) override {}
void environment_set_bg_energy(RID p_env, float p_energy) override {}
void environment_set_canvas_max_layer(RID p_env, int p_max_layer) override {}
- void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG, const Color &p_ao_color = Color()) override {}
+ void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG) override {}
void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap) override {}
void environment_glow_set_use_bicubic_upscale(bool p_enable) override {}
@@ -197,7 +197,7 @@ public:
TypedArray<Image> bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) override { return TypedArray<Image>(); }
- bool free(RID p_rid) override { return true; }
+ bool free(RID p_rid) override { return false; }
void update() override {}
void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) override {}
@@ -224,7 +224,7 @@ public:
return texture_owner.make_rid(texture);
}
void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) override {
- DummyTexture *t = texture_owner.getornull(p_texture);
+ DummyTexture *t = texture_owner.get_or_null(p_texture);
ERR_FAIL_COND(!t);
t->image = p_image->duplicate();
}
@@ -241,7 +241,7 @@ public:
void texture_3d_placeholder_initialize(RID p_texture) override {}
Ref<Image> texture_2d_get(RID p_texture) const override {
- DummyTexture *t = texture_owner.getornull(p_texture);
+ DummyTexture *t = texture_owner.get_or_null(p_texture);
ERR_FAIL_COND_V(!t, Ref<Image>());
return t->image;
}
@@ -661,11 +661,12 @@ public:
bool free(RID p_rid) override {
if (texture_owner.owns(p_rid)) {
// delete the texture
- DummyTexture *texture = texture_owner.getornull(p_rid);
+ DummyTexture *texture = texture_owner.get_or_null(p_rid);
texture_owner.free(p_rid);
memdelete(texture);
+ return true;
}
- return true;
+ return false;
}
virtual void update_memory_info() override {}
diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp
index fd7d5b91fa..46683e8e68 100644
--- a/servers/rendering/renderer_canvas_cull.cpp
+++ b/servers/rendering/renderer_canvas_cull.cpp
@@ -100,7 +100,7 @@ void _collect_ysort_children(RendererCanvasCull::Item *p_canvas_item, Transform2
void _mark_ysort_dirty(RendererCanvasCull::Item *ysort_owner, RID_Owner<RendererCanvasCull::Item, true> &canvas_item_owner) {
do {
ysort_owner->ysort_children_count = -1;
- ysort_owner = canvas_item_owner.owns(ysort_owner->parent) ? canvas_item_owner.getornull(ysort_owner->parent) : nullptr;
+ ysort_owner = canvas_item_owner.owns(ysort_owner->parent) ? canvas_item_owner.get_or_null(ysort_owner->parent) : nullptr;
} while (ysort_owner && ysort_owner->sort_y);
}
@@ -182,7 +182,7 @@ void RendererCanvasCull::_attach_canvas_item_for_draw(RendererCanvasCull::Item *
if (ci->commands != nullptr) {
ci->final_transform = xform;
- ci->final_modulate = Color(modulate.r * ci->self_modulate.r, modulate.g * ci->self_modulate.g, modulate.b * ci->self_modulate.b, modulate.a * ci->self_modulate.a);
+ ci->final_modulate = modulate * ci->self_modulate;
ci->global_rect_cache = global_rect;
ci->global_rect_cache.position -= p_clip_rect.position;
ci->light_masked = false;
@@ -396,9 +396,9 @@ void RendererCanvasCull::canvas_initialize(RID p_rid) {
}
void RendererCanvasCull::canvas_set_item_mirroring(RID p_canvas, RID p_item, const Point2 &p_mirroring) {
- Canvas *canvas = canvas_owner.getornull(p_canvas);
+ Canvas *canvas = canvas_owner.get_or_null(p_canvas);
ERR_FAIL_COND(!canvas);
- Item *canvas_item = canvas_item_owner.getornull(p_item);
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
int idx = canvas->find_item(canvas_item);
@@ -407,7 +407,7 @@ void RendererCanvasCull::canvas_set_item_mirroring(RID p_canvas, RID p_item, con
}
void RendererCanvasCull::canvas_set_modulate(RID p_canvas, const Color &p_color) {
- Canvas *canvas = canvas_owner.getornull(p_canvas);
+ Canvas *canvas = canvas_owner.get_or_null(p_canvas);
ERR_FAIL_COND(!canvas);
canvas->modulate = p_color;
}
@@ -417,7 +417,7 @@ void RendererCanvasCull::canvas_set_disable_scale(bool p_disable) {
}
void RendererCanvasCull::canvas_set_parent(RID p_canvas, RID p_parent, float p_scale) {
- Canvas *canvas = canvas_owner.getornull(p_canvas);
+ Canvas *canvas = canvas_owner.get_or_null(p_canvas);
ERR_FAIL_COND(!canvas);
canvas->parent = p_parent;
@@ -432,15 +432,15 @@ void RendererCanvasCull::canvas_item_initialize(RID p_rid) {
}
void RendererCanvasCull::canvas_item_set_parent(RID p_item, RID p_parent) {
- Item *canvas_item = canvas_item_owner.getornull(p_item);
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
if (canvas_item->parent.is_valid()) {
if (canvas_owner.owns(canvas_item->parent)) {
- Canvas *canvas = canvas_owner.getornull(canvas_item->parent);
+ Canvas *canvas = canvas_owner.get_or_null(canvas_item->parent);
canvas->erase_item(canvas_item);
} else if (canvas_item_owner.owns(canvas_item->parent)) {
- Item *item_owner = canvas_item_owner.getornull(canvas_item->parent);
+ Item *item_owner = canvas_item_owner.get_or_null(canvas_item->parent);
item_owner->child_items.erase(canvas_item);
if (item_owner->sort_y) {
@@ -453,13 +453,13 @@ void RendererCanvasCull::canvas_item_set_parent(RID p_item, RID p_parent) {
if (p_parent.is_valid()) {
if (canvas_owner.owns(p_parent)) {
- Canvas *canvas = canvas_owner.getornull(p_parent);
+ Canvas *canvas = canvas_owner.get_or_null(p_parent);
Canvas::ChildItem ci;
ci.item = canvas_item;
canvas->child_items.push_back(ci);
canvas->children_order_dirty = true;
} else if (canvas_item_owner.owns(p_parent)) {
- Item *item_owner = canvas_item_owner.getornull(p_parent);
+ Item *item_owner = canvas_item_owner.get_or_null(p_parent);
item_owner->child_items.push_back(canvas_item);
item_owner->children_order_dirty = true;
@@ -476,7 +476,7 @@ void RendererCanvasCull::canvas_item_set_parent(RID p_item, RID p_parent) {
}
void RendererCanvasCull::canvas_item_set_visible(RID p_item, bool p_visible) {
- Item *canvas_item = canvas_item_owner.getornull(p_item);
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
canvas_item->visible = p_visible;
@@ -485,35 +485,35 @@ void RendererCanvasCull::canvas_item_set_visible(RID p_item, bool p_visible) {
}
void RendererCanvasCull::canvas_item_set_light_mask(RID p_item, int p_mask) {
- Item *canvas_item = canvas_item_owner.getornull(p_item);
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
canvas_item->light_mask = p_mask;
}
void RendererCanvasCull::canvas_item_set_transform(RID p_item, const Transform2D &p_transform) {
- Item *canvas_item = canvas_item_owner.getornull(p_item);
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
canvas_item->xform = p_transform;
}
void RendererCanvasCull::canvas_item_set_clip(RID p_item, bool p_clip) {
- Item *canvas_item = canvas_item_owner.getornull(p_item);
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
canvas_item->clip = p_clip;
}
void RendererCanvasCull::canvas_item_set_distance_field_mode(RID p_item, bool p_enable) {
- Item *canvas_item = canvas_item_owner.getornull(p_item);
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
canvas_item->distance_field = p_enable;
}
void RendererCanvasCull::canvas_item_set_custom_rect(RID p_item, bool p_custom_rect, const Rect2 &p_rect) {
- Item *canvas_item = canvas_item_owner.getornull(p_item);
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
canvas_item->custom_rect = p_custom_rect;
@@ -521,35 +521,35 @@ void RendererCanvasCull::canvas_item_set_custom_rect(RID p_item, bool p_custom_r
}
void RendererCanvasCull::canvas_item_set_modulate(RID p_item, const Color &p_color) {
- Item *canvas_item = canvas_item_owner.getornull(p_item);
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
canvas_item->modulate = p_color;
}
void RendererCanvasCull::canvas_item_set_self_modulate(RID p_item, const Color &p_color) {
- Item *canvas_item = canvas_item_owner.getornull(p_item);
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
canvas_item->self_modulate = p_color;
}
void RendererCanvasCull::canvas_item_set_draw_behind_parent(RID p_item, bool p_enable) {
- Item *canvas_item = canvas_item_owner.getornull(p_item);
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
canvas_item->behind = p_enable;
}
void RendererCanvasCull::canvas_item_set_update_when_visible(RID p_item, bool p_update) {
- Item *canvas_item = canvas_item_owner.getornull(p_item);
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
canvas_item->update_when_visible = p_update;
}
void RendererCanvasCull::canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width) {
- Item *canvas_item = canvas_item_owner.getornull(p_item);
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
Item::CommandPrimitive *line = canvas_item->alloc_command<Item::CommandPrimitive>();
@@ -573,7 +573,7 @@ void RendererCanvasCull::canvas_item_add_line(RID p_item, const Point2 &p_from,
void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width, bool p_antialiased) {
ERR_FAIL_COND(p_points.size() < 2);
- Item *canvas_item = canvas_item_owner.getornull(p_item);
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
Color color = Color(1, 1, 1, 1);
@@ -714,7 +714,7 @@ void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point
void RendererCanvasCull::canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width) {
ERR_FAIL_COND(p_points.size() < 2);
- Item *canvas_item = canvas_item_owner.getornull(p_item);
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
Item::CommandPolygon *pline = canvas_item->alloc_command<Item::CommandPolygon>();
@@ -730,7 +730,7 @@ void RendererCanvasCull::canvas_item_add_multiline(RID p_item, const Vector<Poin
}
void RendererCanvasCull::canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color) {
- Item *canvas_item = canvas_item_owner.getornull(p_item);
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
Item::CommandRect *rect = canvas_item->alloc_command<Item::CommandRect>();
@@ -740,7 +740,7 @@ void RendererCanvasCull::canvas_item_add_rect(RID p_item, const Rect2 &p_rect, c
}
void RendererCanvasCull::canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color) {
- Item *canvas_item = canvas_item_owner.getornull(p_item);
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
Item::CommandPolygon *circle = canvas_item->alloc_command<Item::CommandPolygon>();
@@ -776,7 +776,7 @@ void RendererCanvasCull::canvas_item_add_circle(RID p_item, const Point2 &p_pos,
}
void RendererCanvasCull::canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile, const Color &p_modulate, bool p_transpose) {
- Item *canvas_item = canvas_item_owner.getornull(p_item);
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
Item::CommandRect *rect = canvas_item->alloc_command<Item::CommandRect>();
@@ -806,8 +806,42 @@ void RendererCanvasCull::canvas_item_add_texture_rect(RID p_item, const Rect2 &p
rect->texture = p_texture;
}
+void RendererCanvasCull::canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate, int p_outline_size, float p_px_range) {
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
+ ERR_FAIL_COND(!canvas_item);
+
+ Item::CommandRect *rect = canvas_item->alloc_command<Item::CommandRect>();
+ ERR_FAIL_COND(!rect);
+ rect->modulate = p_modulate;
+ rect->rect = p_rect;
+
+ rect->texture = p_texture;
+
+ rect->source = p_src_rect;
+ rect->flags = RendererCanvasRender::CANVAS_RECT_REGION | RendererCanvasRender::CANVAS_RECT_MSDF;
+
+ if (p_rect.size.x < 0) {
+ rect->flags |= RendererCanvasRender::CANVAS_RECT_FLIP_H;
+ rect->rect.size.x = -rect->rect.size.x;
+ }
+ if (p_src_rect.size.x < 0) {
+ rect->flags ^= RendererCanvasRender::CANVAS_RECT_FLIP_H;
+ rect->source.size.x = -rect->source.size.x;
+ }
+ if (p_rect.size.y < 0) {
+ rect->flags |= RendererCanvasRender::CANVAS_RECT_FLIP_V;
+ rect->rect.size.y = -rect->rect.size.y;
+ }
+ if (p_src_rect.size.y < 0) {
+ rect->flags ^= RendererCanvasRender::CANVAS_RECT_FLIP_V;
+ rect->source.size.y = -rect->source.size.y;
+ }
+ rect->outline = p_outline_size;
+ rect->px_range = p_px_range;
+}
+
void RendererCanvasCull::canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, bool p_clip_uv) {
- Item *canvas_item = canvas_item_owner.getornull(p_item);
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
Item::CommandRect *rect = canvas_item->alloc_command<Item::CommandRect>();
@@ -848,7 +882,7 @@ void RendererCanvasCull::canvas_item_add_texture_rect_region(RID p_item, const R
}
void RendererCanvasCull::canvas_item_add_nine_patch(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector2 &p_topleft, const Vector2 &p_bottomright, RS::NinePatchAxisMode p_x_axis_mode, RS::NinePatchAxisMode p_y_axis_mode, bool p_draw_center, const Color &p_modulate) {
- Item *canvas_item = canvas_item_owner.getornull(p_item);
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
Item::CommandNinePatch *style = canvas_item->alloc_command<Item::CommandNinePatch>();
@@ -872,7 +906,7 @@ void RendererCanvasCull::canvas_item_add_primitive(RID p_item, const Vector<Poin
uint32_t pc = p_points.size();
ERR_FAIL_COND(pc == 0 || pc > 4);
- Item *canvas_item = canvas_item_owner.getornull(p_item);
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
Item::CommandPrimitive *prim = canvas_item->alloc_command<Item::CommandPrimitive>();
@@ -898,7 +932,7 @@ void RendererCanvasCull::canvas_item_add_primitive(RID p_item, const Vector<Poin
}
void RendererCanvasCull::canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture) {
- Item *canvas_item = canvas_item_owner.getornull(p_item);
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
#ifdef DEBUG_ENABLED
int pointcount = p_points.size();
@@ -919,7 +953,7 @@ void RendererCanvasCull::canvas_item_add_polygon(RID p_item, const Vector<Point2
}
void RendererCanvasCull::canvas_item_add_triangle_array(RID p_item, const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, const Vector<int> &p_bones, const Vector<float> &p_weights, RID p_texture, int p_count) {
- Item *canvas_item = canvas_item_owner.getornull(p_item);
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
int vertex_count = p_points.size();
@@ -942,7 +976,7 @@ void RendererCanvasCull::canvas_item_add_triangle_array(RID p_item, const Vector
}
void RendererCanvasCull::canvas_item_add_set_transform(RID p_item, const Transform2D &p_transform) {
- Item *canvas_item = canvas_item_owner.getornull(p_item);
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
Item::CommandTransform *tr = canvas_item->alloc_command<Item::CommandTransform>();
@@ -951,7 +985,7 @@ void RendererCanvasCull::canvas_item_add_set_transform(RID p_item, const Transfo
}
void RendererCanvasCull::canvas_item_add_mesh(RID p_item, const RID &p_mesh, const Transform2D &p_transform, const Color &p_modulate, RID p_texture) {
- Item *canvas_item = canvas_item_owner.getornull(p_item);
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
ERR_FAIL_COND(!p_mesh.is_valid());
@@ -970,7 +1004,7 @@ void RendererCanvasCull::canvas_item_add_mesh(RID p_item, const RID &p_mesh, con
}
void RendererCanvasCull::canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture) {
- Item *canvas_item = canvas_item_owner.getornull(p_item);
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
Item::CommandParticles *part = canvas_item->alloc_command<Item::CommandParticles>();
@@ -984,7 +1018,7 @@ void RendererCanvasCull::canvas_item_add_particles(RID p_item, RID p_particles,
}
void RendererCanvasCull::canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture) {
- Item *canvas_item = canvas_item_owner.getornull(p_item);
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
Item::CommandMultiMesh *mm = canvas_item->alloc_command<Item::CommandMultiMesh>();
@@ -995,7 +1029,7 @@ void RendererCanvasCull::canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p
}
void RendererCanvasCull::canvas_item_add_clip_ignore(RID p_item, bool p_ignore) {
- Item *canvas_item = canvas_item_owner.getornull(p_item);
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
Item::CommandClipIgnore *ci = canvas_item->alloc_command<Item::CommandClipIgnore>();
@@ -1004,7 +1038,7 @@ void RendererCanvasCull::canvas_item_add_clip_ignore(RID p_item, bool p_ignore)
}
void RendererCanvasCull::canvas_item_add_animation_slice(RID p_item, double p_animation_length, double p_slice_begin, double p_slice_end, double p_offset) {
- Item *canvas_item = canvas_item_owner.getornull(p_item);
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
Item::CommandAnimationSlice *as = canvas_item->alloc_command<Item::CommandAnimationSlice>();
@@ -1016,7 +1050,7 @@ void RendererCanvasCull::canvas_item_add_animation_slice(RID p_item, double p_an
}
void RendererCanvasCull::canvas_item_set_sort_children_by_y(RID p_item, bool p_enable) {
- Item *canvas_item = canvas_item_owner.getornull(p_item);
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
canvas_item->sort_y = p_enable;
@@ -1027,21 +1061,21 @@ void RendererCanvasCull::canvas_item_set_sort_children_by_y(RID p_item, bool p_e
void RendererCanvasCull::canvas_item_set_z_index(RID p_item, int p_z) {
ERR_FAIL_COND(p_z < RS::CANVAS_ITEM_Z_MIN || p_z > RS::CANVAS_ITEM_Z_MAX);
- Item *canvas_item = canvas_item_owner.getornull(p_item);
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
canvas_item->z_index = p_z;
}
void RendererCanvasCull::canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable) {
- Item *canvas_item = canvas_item_owner.getornull(p_item);
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
canvas_item->z_relative = p_enable;
}
void RendererCanvasCull::canvas_item_attach_skeleton(RID p_item, RID p_skeleton) {
- Item *canvas_item = canvas_item_owner.getornull(p_item);
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
if (canvas_item->skeleton == p_skeleton) {
return;
@@ -1070,7 +1104,7 @@ void RendererCanvasCull::canvas_item_attach_skeleton(RID p_item, RID p_skeleton)
}
void RendererCanvasCull::canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable, const Rect2 &p_rect) {
- Item *canvas_item = canvas_item_owner.getornull(p_item);
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
if (p_enable && (canvas_item->copy_back_buffer == nullptr)) {
canvas_item->copy_back_buffer = memnew(RendererCanvasRender::Item::CopyBackBuffer);
@@ -1087,25 +1121,25 @@ void RendererCanvasCull::canvas_item_set_copy_to_backbuffer(RID p_item, bool p_e
}
void RendererCanvasCull::canvas_item_clear(RID p_item) {
- Item *canvas_item = canvas_item_owner.getornull(p_item);
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
canvas_item->clear();
}
void RendererCanvasCull::canvas_item_set_draw_index(RID p_item, int p_index) {
- Item *canvas_item = canvas_item_owner.getornull(p_item);
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
canvas_item->index = p_index;
if (canvas_item_owner.owns(canvas_item->parent)) {
- Item *canvas_item_parent = canvas_item_owner.getornull(canvas_item->parent);
+ Item *canvas_item_parent = canvas_item_owner.get_or_null(canvas_item->parent);
canvas_item_parent->children_order_dirty = true;
return;
}
- Canvas *canvas = canvas_owner.getornull(canvas_item->parent);
+ Canvas *canvas = canvas_owner.get_or_null(canvas_item->parent);
if (canvas) {
canvas->children_order_dirty = true;
return;
@@ -1113,21 +1147,21 @@ void RendererCanvasCull::canvas_item_set_draw_index(RID p_item, int p_index) {
}
void RendererCanvasCull::canvas_item_set_material(RID p_item, RID p_material) {
- Item *canvas_item = canvas_item_owner.getornull(p_item);
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
canvas_item->material = p_material;
}
void RendererCanvasCull::canvas_item_set_use_parent_material(RID p_item, bool p_enable) {
- Item *canvas_item = canvas_item_owner.getornull(p_item);
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
canvas_item->use_parent_material = p_enable;
}
void RendererCanvasCull::canvas_item_set_visibility_notifier(RID p_item, bool p_enable, const Rect2 &p_area, const Callable &p_enter_callable, const Callable &p_exit_callable) {
- Item *canvas_item = canvas_item_owner.getornull(p_item);
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
if (p_enable) {
@@ -1147,7 +1181,7 @@ void RendererCanvasCull::canvas_item_set_visibility_notifier(RID p_item, bool p_
}
void RendererCanvasCull::canvas_item_set_canvas_group_mode(RID p_item, RS::CanvasGroupMode p_mode, float p_clear_margin, bool p_fit_empty, float p_fit_margin, bool p_blur_mipmaps) {
- Item *canvas_item = canvas_item_owner.getornull(p_item);
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
if (p_mode == RS::CANVAS_GROUP_MODE_DISABLED) {
@@ -1172,12 +1206,12 @@ RID RendererCanvasCull::canvas_light_allocate() {
}
void RendererCanvasCull::canvas_light_initialize(RID p_rid) {
canvas_light_owner.initialize_rid(p_rid);
- RendererCanvasRender::Light *clight = canvas_light_owner.getornull(p_rid);
+ RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_rid);
clight->light_internal = RSG::canvas_render->light_create();
}
void RendererCanvasCull::canvas_light_set_mode(RID p_light, RS::CanvasLightMode p_mode) {
- RendererCanvasRender::Light *clight = canvas_light_owner.getornull(p_light);
+ RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);
ERR_FAIL_COND(!clight);
if (clight->mode == p_mode) {
@@ -1198,11 +1232,11 @@ void RendererCanvasCull::canvas_light_set_mode(RID p_light, RS::CanvasLightMode
}
void RendererCanvasCull::canvas_light_attach_to_canvas(RID p_light, RID p_canvas) {
- RendererCanvasRender::Light *clight = canvas_light_owner.getornull(p_light);
+ RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);
ERR_FAIL_COND(!clight);
if (clight->canvas.is_valid()) {
- Canvas *canvas = canvas_owner.getornull(clight->canvas);
+ Canvas *canvas = canvas_owner.get_or_null(clight->canvas);
if (clight->mode == RS::CANVAS_LIGHT_MODE_POINT) {
canvas->lights.erase(clight);
} else {
@@ -1217,7 +1251,7 @@ void RendererCanvasCull::canvas_light_attach_to_canvas(RID p_light, RID p_canvas
clight->canvas = p_canvas;
if (clight->canvas.is_valid()) {
- Canvas *canvas = canvas_owner.getornull(clight->canvas);
+ Canvas *canvas = canvas_owner.get_or_null(clight->canvas);
if (clight->mode == RS::CANVAS_LIGHT_MODE_POINT) {
canvas->lights.insert(clight);
} else {
@@ -1227,28 +1261,28 @@ void RendererCanvasCull::canvas_light_attach_to_canvas(RID p_light, RID p_canvas
}
void RendererCanvasCull::canvas_light_set_enabled(RID p_light, bool p_enabled) {
- RendererCanvasRender::Light *clight = canvas_light_owner.getornull(p_light);
+ RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);
ERR_FAIL_COND(!clight);
clight->enabled = p_enabled;
}
void RendererCanvasCull::canvas_light_set_texture_scale(RID p_light, float p_scale) {
- RendererCanvasRender::Light *clight = canvas_light_owner.getornull(p_light);
+ RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);
ERR_FAIL_COND(!clight);
clight->scale = p_scale;
}
void RendererCanvasCull::canvas_light_set_transform(RID p_light, const Transform2D &p_transform) {
- RendererCanvasRender::Light *clight = canvas_light_owner.getornull(p_light);
+ RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);
ERR_FAIL_COND(!clight);
clight->xform = p_transform;
}
void RendererCanvasCull::canvas_light_set_texture(RID p_light, RID p_texture) {
- RendererCanvasRender::Light *clight = canvas_light_owner.getornull(p_light);
+ RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);
ERR_FAIL_COND(!clight);
if (clight->texture == p_texture) {
@@ -1260,35 +1294,35 @@ void RendererCanvasCull::canvas_light_set_texture(RID p_light, RID p_texture) {
}
void RendererCanvasCull::canvas_light_set_texture_offset(RID p_light, const Vector2 &p_offset) {
- RendererCanvasRender::Light *clight = canvas_light_owner.getornull(p_light);
+ RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);
ERR_FAIL_COND(!clight);
clight->texture_offset = p_offset;
}
void RendererCanvasCull::canvas_light_set_color(RID p_light, const Color &p_color) {
- RendererCanvasRender::Light *clight = canvas_light_owner.getornull(p_light);
+ RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);
ERR_FAIL_COND(!clight);
clight->color = p_color;
}
void RendererCanvasCull::canvas_light_set_height(RID p_light, float p_height) {
- RendererCanvasRender::Light *clight = canvas_light_owner.getornull(p_light);
+ RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);
ERR_FAIL_COND(!clight);
clight->height = p_height;
}
void RendererCanvasCull::canvas_light_set_energy(RID p_light, float p_energy) {
- RendererCanvasRender::Light *clight = canvas_light_owner.getornull(p_light);
+ RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);
ERR_FAIL_COND(!clight);
clight->energy = p_energy;
}
void RendererCanvasCull::canvas_light_set_z_range(RID p_light, int p_min_z, int p_max_z) {
- RendererCanvasRender::Light *clight = canvas_light_owner.getornull(p_light);
+ RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);
ERR_FAIL_COND(!clight);
clight->z_min = p_min_z;
@@ -1296,7 +1330,7 @@ void RendererCanvasCull::canvas_light_set_z_range(RID p_light, int p_min_z, int
}
void RendererCanvasCull::canvas_light_set_layer_range(RID p_light, int p_min_layer, int p_max_layer) {
- RendererCanvasRender::Light *clight = canvas_light_owner.getornull(p_light);
+ RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);
ERR_FAIL_COND(!clight);
clight->layer_max = p_max_layer;
@@ -1304,35 +1338,35 @@ void RendererCanvasCull::canvas_light_set_layer_range(RID p_light, int p_min_lay
}
void RendererCanvasCull::canvas_light_set_item_cull_mask(RID p_light, int p_mask) {
- RendererCanvasRender::Light *clight = canvas_light_owner.getornull(p_light);
+ RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);
ERR_FAIL_COND(!clight);
clight->item_mask = p_mask;
}
void RendererCanvasCull::canvas_light_set_item_shadow_cull_mask(RID p_light, int p_mask) {
- RendererCanvasRender::Light *clight = canvas_light_owner.getornull(p_light);
+ RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);
ERR_FAIL_COND(!clight);
clight->item_shadow_mask = p_mask;
}
void RendererCanvasCull::canvas_light_set_directional_distance(RID p_light, float p_distance) {
- RendererCanvasRender::Light *clight = canvas_light_owner.getornull(p_light);
+ RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);
ERR_FAIL_COND(!clight);
clight->directional_distance = p_distance;
}
void RendererCanvasCull::canvas_light_set_blend_mode(RID p_light, RS::CanvasLightBlendMode p_mode) {
- RendererCanvasRender::Light *clight = canvas_light_owner.getornull(p_light);
+ RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);
ERR_FAIL_COND(!clight);
clight->blend_mode = p_mode;
}
void RendererCanvasCull::canvas_light_set_shadow_enabled(RID p_light, bool p_enabled) {
- RendererCanvasRender::Light *clight = canvas_light_owner.getornull(p_light);
+ RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);
ERR_FAIL_COND(!clight);
if (clight->use_shadow == p_enabled) {
@@ -1344,21 +1378,21 @@ void RendererCanvasCull::canvas_light_set_shadow_enabled(RID p_light, bool p_ena
}
void RendererCanvasCull::canvas_light_set_shadow_filter(RID p_light, RS::CanvasLightShadowFilter p_filter) {
- RendererCanvasRender::Light *clight = canvas_light_owner.getornull(p_light);
+ RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);
ERR_FAIL_COND(!clight);
clight->shadow_filter = p_filter;
}
void RendererCanvasCull::canvas_light_set_shadow_color(RID p_light, const Color &p_color) {
- RendererCanvasRender::Light *clight = canvas_light_owner.getornull(p_light);
+ RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);
ERR_FAIL_COND(!clight);
clight->shadow_color = p_color;
}
void RendererCanvasCull::canvas_light_set_shadow_smooth(RID p_light, float p_smooth) {
- RendererCanvasRender::Light *clight = canvas_light_owner.getornull(p_light);
+ RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);
ERR_FAIL_COND(!clight);
clight->shadow_smooth = p_smooth;
}
@@ -1371,11 +1405,11 @@ void RendererCanvasCull::canvas_light_occluder_initialize(RID p_rid) {
}
void RendererCanvasCull::canvas_light_occluder_attach_to_canvas(RID p_occluder, RID p_canvas) {
- RendererCanvasRender::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_occluder);
+ RendererCanvasRender::LightOccluderInstance *occluder = canvas_light_occluder_owner.get_or_null(p_occluder);
ERR_FAIL_COND(!occluder);
if (occluder->canvas.is_valid()) {
- Canvas *canvas = canvas_owner.getornull(occluder->canvas);
+ Canvas *canvas = canvas_owner.get_or_null(occluder->canvas);
canvas->occluders.erase(occluder);
}
@@ -1386,24 +1420,24 @@ void RendererCanvasCull::canvas_light_occluder_attach_to_canvas(RID p_occluder,
occluder->canvas = p_canvas;
if (occluder->canvas.is_valid()) {
- Canvas *canvas = canvas_owner.getornull(occluder->canvas);
+ Canvas *canvas = canvas_owner.get_or_null(occluder->canvas);
canvas->occluders.insert(occluder);
}
}
void RendererCanvasCull::canvas_light_occluder_set_enabled(RID p_occluder, bool p_enabled) {
- RendererCanvasRender::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_occluder);
+ RendererCanvasRender::LightOccluderInstance *occluder = canvas_light_occluder_owner.get_or_null(p_occluder);
ERR_FAIL_COND(!occluder);
occluder->enabled = p_enabled;
}
void RendererCanvasCull::canvas_light_occluder_set_polygon(RID p_occluder, RID p_polygon) {
- RendererCanvasRender::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_occluder);
+ RendererCanvasRender::LightOccluderInstance *occluder = canvas_light_occluder_owner.get_or_null(p_occluder);
ERR_FAIL_COND(!occluder);
if (occluder->polygon.is_valid()) {
- LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.getornull(p_polygon);
+ LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get_or_null(p_polygon);
if (occluder_poly) {
occluder_poly->owners.erase(occluder);
}
@@ -1413,7 +1447,7 @@ void RendererCanvasCull::canvas_light_occluder_set_polygon(RID p_occluder, RID p
occluder->occluder = RID();
if (occluder->polygon.is_valid()) {
- LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.getornull(p_polygon);
+ LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get_or_null(p_polygon);
if (!occluder_poly) {
occluder->polygon = RID();
ERR_FAIL_COND(!occluder_poly);
@@ -1427,19 +1461,19 @@ void RendererCanvasCull::canvas_light_occluder_set_polygon(RID p_occluder, RID p
}
void RendererCanvasCull::canvas_light_occluder_set_as_sdf_collision(RID p_occluder, bool p_enable) {
- RendererCanvasRender::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_occluder);
+ RendererCanvasRender::LightOccluderInstance *occluder = canvas_light_occluder_owner.get_or_null(p_occluder);
ERR_FAIL_COND(!occluder);
}
void RendererCanvasCull::canvas_light_occluder_set_transform(RID p_occluder, const Transform2D &p_xform) {
- RendererCanvasRender::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_occluder);
+ RendererCanvasRender::LightOccluderInstance *occluder = canvas_light_occluder_owner.get_or_null(p_occluder);
ERR_FAIL_COND(!occluder);
occluder->xform = p_xform;
}
void RendererCanvasCull::canvas_light_occluder_set_light_mask(RID p_occluder, int p_mask) {
- RendererCanvasRender::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_occluder);
+ RendererCanvasRender::LightOccluderInstance *occluder = canvas_light_occluder_owner.get_or_null(p_occluder);
ERR_FAIL_COND(!occluder);
occluder->light_mask = p_mask;
@@ -1450,12 +1484,12 @@ RID RendererCanvasCull::canvas_occluder_polygon_allocate() {
}
void RendererCanvasCull::canvas_occluder_polygon_initialize(RID p_rid) {
canvas_light_occluder_polygon_owner.initialize_rid(p_rid);
- LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.getornull(p_rid);
+ LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get_or_null(p_rid);
occluder_poly->occluder = RSG::canvas_render->occluder_polygon_create();
}
void RendererCanvasCull::canvas_occluder_polygon_set_shape(RID p_occluder_polygon, const Vector<Vector2> &p_shape, bool p_closed) {
- LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.getornull(p_occluder_polygon);
+ LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get_or_null(p_occluder_polygon);
ERR_FAIL_COND(!occluder_poly);
uint32_t pc = p_shape.size();
@@ -1479,7 +1513,7 @@ void RendererCanvasCull::canvas_occluder_polygon_set_shape(RID p_occluder_polygo
}
void RendererCanvasCull::canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon, RS::CanvasOccluderPolygonCullMode p_mode) {
- LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.getornull(p_occluder_polygon);
+ LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get_or_null(p_occluder_polygon);
ERR_FAIL_COND(!occluder_poly);
occluder_poly->cull_mode = p_mode;
RSG::canvas_render->occluder_polygon_set_cull_mode(occluder_poly->occluder, p_mode);
@@ -1516,12 +1550,12 @@ void RendererCanvasCull::canvas_texture_set_texture_repeat(RID p_canvas_texture,
}
void RendererCanvasCull::canvas_item_set_default_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) {
- Item *ci = canvas_item_owner.getornull(p_item);
+ Item *ci = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!ci);
ci->texture_filter = p_filter;
}
void RendererCanvasCull::canvas_item_set_default_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) {
- Item *ci = canvas_item_owner.getornull(p_item);
+ Item *ci = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!ci);
ci->texture_repeat = p_repeat;
}
@@ -1566,11 +1600,11 @@ void RendererCanvasCull::update_visibility_notifiers() {
bool RendererCanvasCull::free(RID p_rid) {
if (canvas_owner.owns(p_rid)) {
- Canvas *canvas = canvas_owner.getornull(p_rid);
+ Canvas *canvas = canvas_owner.get_or_null(p_rid);
ERR_FAIL_COND_V(!canvas, false);
while (canvas->viewports.size()) {
- RendererViewport::Viewport *vp = RSG::viewport->viewport_owner.getornull(canvas->viewports.front()->get());
+ RendererViewport::Viewport *vp = RSG::viewport->viewport_owner.get_or_null(canvas->viewports.front()->get());
ERR_FAIL_COND_V(!vp, true);
Map<RID, RendererViewport::Viewport::CanvasData>::Element *E = vp->canvas_map.find(p_rid);
@@ -1595,15 +1629,15 @@ bool RendererCanvasCull::free(RID p_rid) {
canvas_owner.free(p_rid);
} else if (canvas_item_owner.owns(p_rid)) {
- Item *canvas_item = canvas_item_owner.getornull(p_rid);
+ Item *canvas_item = canvas_item_owner.get_or_null(p_rid);
ERR_FAIL_COND_V(!canvas_item, true);
if (canvas_item->parent.is_valid()) {
if (canvas_owner.owns(canvas_item->parent)) {
- Canvas *canvas = canvas_owner.getornull(canvas_item->parent);
+ Canvas *canvas = canvas_owner.get_or_null(canvas_item->parent);
canvas->erase_item(canvas_item);
} else if (canvas_item_owner.owns(canvas_item->parent)) {
- Item *item_owner = canvas_item_owner.getornull(canvas_item->parent);
+ Item *item_owner = canvas_item_owner.get_or_null(canvas_item->parent);
item_owner->child_items.erase(canvas_item);
if (item_owner->sort_y) {
@@ -1629,11 +1663,11 @@ bool RendererCanvasCull::free(RID p_rid) {
canvas_item_owner.free(p_rid);
} else if (canvas_light_owner.owns(p_rid)) {
- RendererCanvasRender::Light *canvas_light = canvas_light_owner.getornull(p_rid);
+ RendererCanvasRender::Light *canvas_light = canvas_light_owner.get_or_null(p_rid);
ERR_FAIL_COND_V(!canvas_light, true);
if (canvas_light->canvas.is_valid()) {
- Canvas *canvas = canvas_owner.getornull(canvas_light->canvas);
+ Canvas *canvas = canvas_owner.get_or_null(canvas_light->canvas);
if (canvas) {
canvas->lights.erase(canvas_light);
}
@@ -1644,25 +1678,25 @@ bool RendererCanvasCull::free(RID p_rid) {
canvas_light_owner.free(p_rid);
} else if (canvas_light_occluder_owner.owns(p_rid)) {
- RendererCanvasRender::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_rid);
+ RendererCanvasRender::LightOccluderInstance *occluder = canvas_light_occluder_owner.get_or_null(p_rid);
ERR_FAIL_COND_V(!occluder, true);
if (occluder->polygon.is_valid()) {
- LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.getornull(occluder->polygon);
+ LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get_or_null(occluder->polygon);
if (occluder_poly) {
occluder_poly->owners.erase(occluder);
}
}
if (occluder->canvas.is_valid() && canvas_owner.owns(occluder->canvas)) {
- Canvas *canvas = canvas_owner.getornull(occluder->canvas);
+ Canvas *canvas = canvas_owner.get_or_null(occluder->canvas);
canvas->occluders.erase(occluder);
}
canvas_light_occluder_owner.free(p_rid);
} else if (canvas_light_occluder_polygon_owner.owns(p_rid)) {
- LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.getornull(p_rid);
+ LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get_or_null(p_rid);
ERR_FAIL_COND_V(!occluder_poly, true);
RSG::canvas_render->free(occluder_poly->occluder);
diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h
index 79b5450d14..a2fdf95c76 100644
--- a/servers/rendering/renderer_canvas_cull.h
+++ b/servers/rendering/renderer_canvas_cull.h
@@ -222,6 +222,7 @@ public:
void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color);
void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false);
void canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, bool p_clip_uv = false);
+ void canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, float p_px_range = 1.0);
void canvas_item_add_nine_patch(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector2 &p_topleft, const Vector2 &p_bottomright, RS::NinePatchAxisMode p_x_axis_mode = RS::NINE_PATCH_STRETCH, RS::NinePatchAxisMode p_y_axis_mode = RS::NINE_PATCH_STRETCH, bool p_draw_center = true, const Color &p_modulate = Color(1, 1, 1));
void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width = 1.0);
void canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), RID p_texture = RID());
@@ -314,4 +315,4 @@ public:
~RendererCanvasCull();
};
-#endif // VISUALSERVERCANVAS_H
+#endif // RENDERING_SERVER_CANVAS_CULL_H
diff --git a/servers/rendering/renderer_canvas_render.h b/servers/rendering/renderer_canvas_render.h
index 8afe9ef410..04ddae4089 100644
--- a/servers/rendering/renderer_canvas_render.h
+++ b/servers/rendering/renderer_canvas_render.h
@@ -45,6 +45,7 @@ public:
CANVAS_RECT_TRANSPOSE = 16,
CANVAS_RECT_CLIP_UV = 32,
CANVAS_RECT_IS_GROUP = 64,
+ CANVAS_RECT_MSDF = 128,
};
struct Light {
@@ -193,11 +194,15 @@ public:
Color modulate;
Rect2 source;
uint8_t flags;
+ float outline;
+ float px_range;
RID texture;
CommandRect() {
flags = 0;
+ outline = 0;
+ px_range = 1;
type = TYPE_RECT;
}
};
diff --git a/servers/rendering/renderer_compositor.h b/servers/rendering/renderer_compositor.h
index 6206849b66..1971c3e781 100644
--- a/servers/rendering/renderer_compositor.h
+++ b/servers/rendering/renderer_compositor.h
@@ -41,7 +41,8 @@
class RendererSceneRender;
struct BlitToScreen {
RID render_target;
- Rect2i rect;
+ Rect2 src_rect = Rect2(0.0, 0.0, 1.0, 1.0);
+ Rect2i dst_rect;
struct {
bool use_layer = false;
diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.h b/servers/rendering/renderer_rd/cluster_builder_rd.h
index c0c03eb26a..feafd4c2db 100644
--- a/servers/rendering/renderer_rd/cluster_builder_rd.h
+++ b/servers/rendering/renderer_rd/cluster_builder_rd.h
@@ -289,7 +289,7 @@ public:
e.touches_near = min_d < z_near;
} else {
//contains camera inside light
- Plane base_plane(xform.origin, -xform.basis.get_axis(Vector3::AXIS_Z));
+ Plane base_plane(-xform.basis.get_axis(Vector3::AXIS_Z), xform.origin);
float dist = base_plane.distance_to(Vector3());
if (dist >= 0 && dist < radius) {
//inside, check angle
diff --git a/servers/rendering/renderer_rd/effects_rd.cpp b/servers/rendering/renderer_rd/effects_rd.cpp
index 3683622d3e..c69408a30b 100644
--- a/servers/rendering/renderer_rd/effects_rd.cpp
+++ b/servers/rendering/renderer_rd/effects_rd.cpp
@@ -812,6 +812,7 @@ void EffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer, const Tone
tonemap.push_constant.exposure = p_settings.exposure;
tonemap.push_constant.white = p_settings.white;
tonemap.push_constant.auto_exposure_grey = p_settings.auto_exposure_grey;
+ tonemap.push_constant.luminance_multiplier = p_settings.luminance_multiplier;
tonemap.push_constant.use_color_correction = p_settings.use_color_correction;
@@ -864,6 +865,7 @@ void EffectsRD::tonemapper(RD::DrawListID p_subpass_draw_list, RID p_source_colo
tonemap.push_constant.use_color_correction = p_settings.use_color_correction;
tonemap.push_constant.use_debanding = p_settings.use_debanding;
+ tonemap.push_constant.luminance_multiplier = p_settings.luminance_multiplier;
RD::get_singleton()->draw_list_bind_render_pipeline(p_subpass_draw_list, tonemap.pipelines[mode].get_render_pipeline(RD::INVALID_ID, p_dst_format_id, false, RD::get_singleton()->draw_list_get_current_pass()));
RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, _get_uniform_set_for_input(p_source_color), 0);
@@ -1398,6 +1400,7 @@ void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_dep
ssao.gather_push_constant.half_screen_pixel_size_x025[0] = ssao.gather_push_constant.half_screen_pixel_size[0] * 0.25;
ssao.gather_push_constant.half_screen_pixel_size_x025[1] = ssao.gather_push_constant.half_screen_pixel_size[1] * 0.25;
+ ssao.gather_push_constant.radius = p_settings.radius;
float radius_near_limit = (p_settings.radius * 1.2f);
if (p_settings.quality <= RS::ENV_SSAO_QUALITY_LOW) {
radius_near_limit *= 1.50f;
@@ -1405,12 +1408,8 @@ void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_dep
if (p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) {
ssao.gather_push_constant.radius *= 0.8f;
}
- if (p_settings.half_size) {
- ssao.gather_push_constant.radius *= 0.5f;
- }
}
radius_near_limit /= tan_half_fov_y;
- ssao.gather_push_constant.radius = p_settings.radius;
ssao.gather_push_constant.intensity = p_settings.intensity;
ssao.gather_push_constant.shadow_power = p_settings.power;
ssao.gather_push_constant.shadow_clamp = 0.98;
@@ -2171,10 +2170,8 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
for (int pass = 0; pass < 4; pass++) {
for (int subPass = 0; subPass < sub_pass_count; subPass++) {
int a = pass;
- int b = subPass;
-
int spmap[5]{ 0, 1, 4, 3, 2 };
- b = spmap[subPass];
+ int b = spmap[subPass];
float ca, sa;
float angle0 = (float(a) + float(b) / float(sub_pass_count)) * Math_PI * 0.5f;
diff --git a/servers/rendering/renderer_rd/effects_rd.h b/servers/rendering/renderer_rd/effects_rd.h
index c8d4cb7ad4..0db0919dbc 100644
--- a/servers/rendering/renderer_rd/effects_rd.h
+++ b/servers/rendering/renderer_rd/effects_rd.h
@@ -255,7 +255,7 @@ private:
float exposure; // 4 - 84
float white; // 4 - 88
float auto_exposure_grey; // 4 - 92
- uint32_t pad2; // 4 - 96
+ float luminance_multiplier; // 4 - 96
float pixel_size[2]; // 8 - 104
uint32_t use_fxaa; // 4 - 108
@@ -308,7 +308,7 @@ private:
float exposure_adjust;
float min_luminance;
float max_luminance;
- float pad[1];
+ uint32_t pad1;
};
struct LuminanceReduceFragment {
@@ -818,6 +818,7 @@ public:
bool use_auto_exposure = false;
float auto_exposure_grey = 0.5;
RID exposure_texture;
+ float luminance_multiplier = 1.0;
bool use_bcs = false;
float brightness = 1.0;
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 611f7c6494..6b84ab908d 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
@@ -223,7 +223,6 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_c
RD::TEXTURE_SAMPLES_2,
RD::TEXTURE_SAMPLES_4,
RD::TEXTURE_SAMPLES_8,
- RD::TEXTURE_SAMPLES_16
};
texture_samples = ts[p_msaa];
@@ -484,7 +483,7 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
if (material_uniform_set != prev_material_uniform_set) {
// Update uniform set.
- if (RD::get_singleton()->uniform_set_is_valid(material_uniform_set)) { // Material may not have a uniform set.
+ if (material_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(material_uniform_set)) { // Material may not have a uniform set.
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, material_uniform_set, MATERIAL_UNIFORM_SET);
}
@@ -754,19 +753,10 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat
scene_state.ubo.ssao_ao_affect = environment_get_ssao_ao_affect(p_render_data->environment);
scene_state.ubo.ssao_light_affect = environment_get_ssao_light_affect(p_render_data->environment);
- Color ao_color = environment_get_ao_color(p_render_data->environment).to_linear();
- scene_state.ubo.ao_color[0] = ao_color.r;
- scene_state.ubo.ao_color[1] = ao_color.g;
- scene_state.ubo.ao_color[2] = ao_color.b;
- scene_state.ubo.ao_color[3] = ao_color.a;
-
scene_state.ubo.fog_enabled = environment_is_fog_enabled(p_render_data->environment);
scene_state.ubo.fog_density = environment_get_fog_density(p_render_data->environment);
scene_state.ubo.fog_height = environment_get_fog_height(p_render_data->environment);
scene_state.ubo.fog_height_density = environment_get_fog_height_density(p_render_data->environment);
- if (scene_state.ubo.fog_height_density >= 0.0001) {
- scene_state.ubo.fog_height_density = 1.0 / scene_state.ubo.fog_height_density;
- }
scene_state.ubo.fog_aerial_perspective = environment_get_fog_aerial_perspective(p_render_data->environment);
Color fog_color = environment_get_fog_light_color(p_render_data->environment).to_linear();
@@ -914,7 +904,7 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
}
uint32_t lightmap_captures_used = 0;
- Plane near_plane(p_render_data->cam_transform.origin, -p_render_data->cam_transform.basis.get_axis(Vector3::AXIS_Z));
+ Plane near_plane = Plane(-p_render_data->cam_transform.basis.get_axis(Vector3::AXIS_Z), p_render_data->cam_transform.origin);
near_plane.d += p_render_data->cam_projection.get_z_near();
float z_max = p_render_data->cam_projection.get_z_far() - p_render_data->cam_projection.get_z_near();
@@ -1163,7 +1153,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
render_buffer = (RenderBufferDataForwardClustered *)render_buffers_get_data(p_render_data->render_buffers);
}
RendererSceneEnvironmentRD *env = get_environment(p_render_data->environment);
- static const int texture_multisamples[RS::VIEWPORT_MSAA_MAX] = { 1, 2, 4, 8, 16 };
+ static const int texture_multisamples[RS::VIEWPORT_MSAA_MAX] = { 1, 2, 4, 8 };
//first of all, make a new render pass
//fill up ubo
@@ -2552,7 +2542,7 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet
SceneShaderForwardClustered::MaterialData *material_shadow = nullptr;
void *surface_shadow = nullptr;
- if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass) {
+ if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_position && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass) {
flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SHARED_SHADOW_MATERIAL;
material_shadow = (SceneShaderForwardClustered::MaterialData *)storage->material_get_data(scene_shader.default_material, RendererStorageRD::SHADER_TYPE_3D);
@@ -2696,7 +2686,7 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome
} break;
#if 0
case RS::INSTANCE_IMMEDIATE: {
- RasterizerStorageGLES3::Immediate *immediate = storage->immediate_owner.getornull(inst->base);
+ RasterizerStorageGLES3::Immediate *immediate = storage->immediate_owner.get_or_null(inst->base);
ERR_CONTINUE(!immediate);
_add_geometry(immediate, inst, nullptr, -1, p_depth_pass, p_shadow_pass);
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
index 676f633d33..ff3d2fc6cb 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
@@ -257,8 +257,6 @@ class RenderForwardClustered : public RendererSceneRenderRD {
float roughness_limiter_limit;
uint32_t roughness_limiter_pad[2];
- float ao_color[4];
-
float sdf_to_bounds[16];
int32_t sdf_offset[3];
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 be18a73989..a1c3481ed6 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
@@ -66,6 +66,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
unshaded = false;
uses_vertex = false;
+ uses_position = false;
uses_sss = false;
uses_transmittance = false;
uses_screen_texture = false;
@@ -126,6 +127,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
actions.write_flag_pointers["MODELVIEW_MATRIX"] = &writes_modelview_or_projection;
actions.write_flag_pointers["PROJECTION_MATRIX"] = &writes_modelview_or_projection;
actions.write_flag_pointers["VERTEX"] = &uses_vertex;
+ actions.write_flag_pointers["POSITION"] = &uses_position;
actions.uniforms = &uniforms;
@@ -342,36 +344,36 @@ void SceneShaderForwardClustered::ShaderData::set_default_texture_param(const St
void SceneShaderForwardClustered::ShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
Map<int, StringName> order;
- for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) {
- if (E->get().scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) {
+ for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
+ if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) {
continue;
}
- if (E->get().texture_order >= 0) {
- order[E->get().texture_order + 100000] = E->key();
+ if (E.value.texture_order >= 0) {
+ order[E.value.texture_order + 100000] = E.key;
} else {
- order[E->get().order] = E->key();
+ order[E.value.order] = E.key;
}
}
- for (Map<int, StringName>::Element *E = order.front(); E; E = E->next()) {
- PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E->get()]);
- pi.name = E->get();
+ for (const KeyValue<int, StringName> &E : order) {
+ PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]);
+ pi.name = E.value;
p_param_list->push_back(pi);
}
}
void SceneShaderForwardClustered::ShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const {
- for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) {
- if (E->get().scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
+ for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
+ if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
continue;
}
RendererStorage::InstanceShaderParam p;
- p.info = ShaderLanguage::uniform_to_property_info(E->get());
- p.info.name = E->key(); //supply name
- p.index = E->get().instance_index;
- p.default_value = ShaderLanguage::constant_value_to_variant(E->get().default_value, E->get().type, E->get().hint);
+ p.info = ShaderLanguage::uniform_to_property_info(E.value);
+ p.info.name = E.key; //supply name
+ p.index = E.value.instance_index;
+ p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint);
p_param_list->push_back(p);
}
}
@@ -396,7 +398,7 @@ Variant SceneShaderForwardClustered::ShaderData::get_default_parameter(const Str
if (uniforms.has(p_parameter)) {
ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter];
Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value;
- return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.hint);
+ return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint);
}
return Variant();
}
@@ -601,10 +603,10 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
actions.usage_defines["UV2"] = "#define UV2_USED\n";
actions.usage_defines["BONE_INDICES"] = "#define BONES_USED\n";
actions.usage_defines["BONE_WEIGHTS"] = "#define WEIGHTS_USED\n";
- actions.usage_defines["CUSTOM0"] = "#define CUSTOM0\n";
- actions.usage_defines["CUSTOM1"] = "#define CUSTOM1\n";
- actions.usage_defines["CUSTOM2"] = "#define CUSTOM2\n";
- actions.usage_defines["CUSTOM3"] = "#define CUSTOM3\n";
+ actions.usage_defines["CUSTOM0"] = "#define CUSTOM0_USED\n";
+ actions.usage_defines["CUSTOM1"] = "#define CUSTOM1_USED\n";
+ actions.usage_defines["CUSTOM2"] = "#define CUSTOM2_USED\n";
+ actions.usage_defines["CUSTOM3"] = "#define CUSTOM3_USED\n";
actions.usage_defines["NORMAL_MAP"] = "#define NORMAL_MAP_USED\n";
actions.usage_defines["NORMAL_MAP_DEPTH"] = "@NORMAL_MAP";
actions.usage_defines["COLOR"] = "#define COLOR_USED\n";
@@ -683,6 +685,8 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
default_shader = storage->shader_allocate();
storage->shader_initialize(default_shader);
storage->shader_set_code(default_shader, R"(
+// Default 3D material shader (clustered).
+
shader_type spatial;
void vertex() {
@@ -712,6 +716,8 @@ void fragment() {
storage->shader_initialize(overdraw_material_shader);
// Use relatively low opacity so that more "layers" of overlapping objects can be distinguished.
storage->shader_set_code(overdraw_material_shader, R"(
+// 3D editor Overdraw debug draw mode shader (clustered).
+
shader_type spatial;
render_mode blend_add, unshaded;
diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
index 8d75f30a20..09ef425e2e 100644
--- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
@@ -137,6 +137,7 @@ public:
bool unshaded;
bool uses_vertex;
+ bool uses_position;
bool uses_sss;
bool uses_transmittance;
bool uses_screen_texture;
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 2064d9c5c5..1e5854a174 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
@@ -86,12 +86,13 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::clear() {
void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count) {
clear();
- bool is_half_resolution = false; // Set this once we support this feature.
-
msaa = p_msaa;
+ Size2i target_size = RD::get_singleton()->texture_size(p_target_buffer);
+
width = p_width;
height = p_height;
+ bool is_scaled = (target_size.width != p_width) || (target_size.height != p_height);
view_count = p_view_count;
color = p_color_buffer;
@@ -124,7 +125,7 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b
passes.push_back(pass);
color_fbs[FB_CONFIG_THREE_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count);
- if (!is_half_resolution) {
+ if (!is_scaled) {
// - add blit to 2D pass
fb.push_back(p_target_buffer); // 2 - target buffer
@@ -158,7 +159,6 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b
RD::TEXTURE_SAMPLES_2,
RD::TEXTURE_SAMPLES_4,
RD::TEXTURE_SAMPLES_8,
- RD::TEXTURE_SAMPLES_16
};
texture_samples = ts[p_msaa];
@@ -211,7 +211,7 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b
color_fbs[FB_CONFIG_ONE_PASS] = RD::get_singleton()->framebuffer_create_multipass(fb, one_pass_with_resolve, RenderingDevice::INVALID_ID, view_count);
}
- if (!is_half_resolution) {
+ if (!is_scaled) {
// - add blit to 2D pass
fb.push_back(p_target_buffer); // 3 - target buffer
RD::FramebufferPass blit_pass;
@@ -271,6 +271,12 @@ bool RenderForwardMobile::free(RID p_rid) {
/* Render functions */
+float RenderForwardMobile::_render_buffers_get_luminance_multiplier() {
+ // On mobile renderer we need to multiply source colors by 2 due to using a UNORM buffer
+ // and multiplying by the output color during 3D rendering by 0.5
+ return 2.0;
+}
+
RD::DataFormat RenderForwardMobile::_render_buffers_get_color_format() {
// Using 32bit buffers enables AFBC on mobile devices which should have a definite performance improvement (MALI G710 and newer support this on 64bit RTs)
return RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32;
@@ -491,7 +497,6 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
bool using_subpass_transparent = true;
bool using_subpass_post_process = true;
- bool is_half_resolution = false; // Set this once we support this feature.
bool using_ssr = false; // I don't think we support this in our mobile renderer so probably should phase it out
bool using_sss = false; // I don't think we support this in our mobile renderer so probably should phase it out
@@ -512,7 +517,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
screen_size.x = render_buffer->width;
screen_size.y = render_buffer->height;
- if (is_half_resolution) {
+ if (render_buffer->color_fbs[FB_CONFIG_FOUR_SUBPASSES].is_null()) {
// can't do blit subpass
using_subpass_post_process = false;
} else if (env && (env->glow_enabled || env->auto_exposure || camera_effects_uses_dof(p_render_data->camera_effects))) {
@@ -631,7 +636,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
RID sky_rid = env->sky;
if (sky_rid.is_valid()) {
- sky.update(env, projection, p_render_data->cam_transform, time);
+ sky.update(env, projection, p_render_data->cam_transform, time, _render_buffers_get_luminance_multiplier());
radiance_texture = sky.sky_get_radiance_texture_rd(sky_rid);
} else {
// do not try to draw sky if invalid
@@ -750,9 +755,9 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
CameraMatrix correction;
correction.set_depth_correction(true);
CameraMatrix projection = correction * p_render_data->cam_projection;
- sky.draw(draw_list, env, framebuffer, 1, &projection, p_render_data->cam_transform, time);
+ sky.draw(draw_list, env, framebuffer, 1, &projection, p_render_data->cam_transform, time, _render_buffers_get_luminance_multiplier());
} else {
- sky.draw(draw_list, env, framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time);
+ sky.draw(draw_list, env, framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time, _render_buffers_get_luminance_multiplier());
}
RD::get_singleton()->draw_command_end_label(); // Draw Sky Subpass
@@ -1317,7 +1322,7 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const
}
uint32_t lightmap_captures_used = 0;
- Plane near_plane(p_render_data->cam_transform.origin, -p_render_data->cam_transform.basis.get_axis(Vector3::AXIS_Z));
+ Plane near_plane(-p_render_data->cam_transform.basis.get_axis(Vector3::AXIS_Z), p_render_data->cam_transform.origin);
near_plane.d += p_render_data->cam_projection.get_z_near();
float z_max = p_render_data->cam_projection.get_z_far() - p_render_data->cam_projection.get_z_near();
@@ -1628,19 +1633,10 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data,
scene_state.ubo.ssao_ao_affect = environment_get_ssao_ao_affect(p_render_data->environment);
scene_state.ubo.ssao_light_affect = environment_get_ssao_light_affect(p_render_data->environment);
- Color ao_color = environment_get_ao_color(p_render_data->environment).to_linear();
- scene_state.ubo.ao_color[0] = ao_color.r;
- scene_state.ubo.ao_color[1] = ao_color.g;
- scene_state.ubo.ao_color[2] = ao_color.b;
- scene_state.ubo.ao_color[3] = ao_color.a;
-
scene_state.ubo.fog_enabled = environment_is_fog_enabled(p_render_data->environment);
scene_state.ubo.fog_density = environment_get_fog_density(p_render_data->environment);
scene_state.ubo.fog_height = environment_get_fog_height(p_render_data->environment);
scene_state.ubo.fog_height_density = environment_get_fog_height_density(p_render_data->environment);
- if (scene_state.ubo.fog_height_density >= 0.0001) {
- scene_state.ubo.fog_height_density = 1.0 / scene_state.ubo.fog_height_density;
- }
scene_state.ubo.fog_aerial_perspective = environment_get_fog_aerial_perspective(p_render_data->environment);
Color fog_color = environment_get_fog_light_color(p_render_data->environment).to_linear();
@@ -1976,7 +1972,7 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
if (material_uniform_set != prev_material_uniform_set) {
// Update uniform set.
- if (RD::get_singleton()->uniform_set_is_valid(material_uniform_set)) { // Material may not have a uniform set.
+ if (material_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(material_uniform_set)) { // Material may not have a uniform set.
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, material_uniform_set, MATERIAL_UNIFORM_SET);
}
@@ -2435,7 +2431,7 @@ void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry
} break;
#if 0
case RS::INSTANCE_IMMEDIATE: {
- RasterizerStorageGLES3::Immediate *immediate = storage->immediate_owner.getornull(inst->base);
+ RasterizerStorageGLES3::Immediate *immediate = storage->immediate_owner.get_or_null(inst->base);
ERR_CONTINUE(!immediate);
_add_geometry(immediate, inst, nullptr, -1, p_depth_pass, p_shadow_pass);
diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
index 764d8e80df..36a92e1464 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
@@ -202,6 +202,7 @@ protected:
}
};
+ virtual float _render_buffers_get_luminance_multiplier() override;
virtual RD::DataFormat _render_buffers_get_color_format() override;
virtual bool _render_buffers_can_be_storage() override;
@@ -293,8 +294,6 @@ protected:
float roughness_limiter_limit;
uint32_t roughness_limiter_pad[2];
- float ao_color[4];
-
// Fog
uint32_t fog_enabled;
float fog_density;
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 735014a2ec..16d650a540 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
@@ -336,36 +336,36 @@ void SceneShaderForwardMobile::ShaderData::set_default_texture_param(const Strin
void SceneShaderForwardMobile::ShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
Map<int, StringName> order;
- for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) {
- if (E->get().scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) {
+ for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
+ if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) {
continue;
}
- if (E->get().texture_order >= 0) {
- order[E->get().texture_order + 100000] = E->key();
+ if (E.value.texture_order >= 0) {
+ order[E.value.texture_order + 100000] = E.key;
} else {
- order[E->get().order] = E->key();
+ order[E.value.order] = E.key;
}
}
- for (Map<int, StringName>::Element *E = order.front(); E; E = E->next()) {
- PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E->get()]);
- pi.name = E->get();
+ for (const KeyValue<int, StringName> &E : order) {
+ PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]);
+ pi.name = E.value;
p_param_list->push_back(pi);
}
}
void SceneShaderForwardMobile::ShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const {
- for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) {
- if (E->get().scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
+ for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
+ if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
continue;
}
RendererStorage::InstanceShaderParam p;
- p.info = ShaderLanguage::uniform_to_property_info(E->get());
- p.info.name = E->key(); //supply name
- p.index = E->get().instance_index;
- p.default_value = ShaderLanguage::constant_value_to_variant(E->get().default_value, E->get().type, E->get().hint);
+ p.info = ShaderLanguage::uniform_to_property_info(E.value);
+ p.info.name = E.key; //supply name
+ p.index = E.value.instance_index;
+ p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint);
p_param_list->push_back(p);
}
}
@@ -390,7 +390,7 @@ Variant SceneShaderForwardMobile::ShaderData::get_default_parameter(const String
if (uniforms.has(p_parameter)) {
ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter];
Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value;
- return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.hint);
+ return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint);
}
return Variant();
}
@@ -593,10 +593,10 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
actions.usage_defines["UV2"] = "#define UV2_USED\n";
actions.usage_defines["BONE_INDICES"] = "#define BONES_USED\n";
actions.usage_defines["BONE_WEIGHTS"] = "#define WEIGHTS_USED\n";
- actions.usage_defines["CUSTOM0"] = "#define CUSTOM0\n";
- actions.usage_defines["CUSTOM1"] = "#define CUSTOM1\n";
- actions.usage_defines["CUSTOM2"] = "#define CUSTOM2\n";
- actions.usage_defines["CUSTOM3"] = "#define CUSTOM3\n";
+ actions.usage_defines["CUSTOM0"] = "#define CUSTOM0_USED\n";
+ actions.usage_defines["CUSTOM1"] = "#define CUSTOM1_USED\n";
+ actions.usage_defines["CUSTOM2"] = "#define CUSTOM2_USED\n";
+ actions.usage_defines["CUSTOM3"] = "#define CUSTOM3_USED\n";
actions.usage_defines["NORMAL_MAP"] = "#define NORMAL_MAP_USED\n";
actions.usage_defines["NORMAL_MAP_DEPTH"] = "@NORMAL_MAP";
actions.usage_defines["COLOR"] = "#define COLOR_USED\n";
@@ -665,6 +665,8 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
actions.global_buffer_array_variable = "global_variables.data";
actions.instance_uniform_index_variable = "draw_call.instance_uniforms_ofs";
+ actions.apply_luminance_multiplier = true; // apply luminance multiplier to screen texture
+
compiler.initialize(actions);
}
@@ -673,6 +675,8 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
default_shader = storage->shader_allocate();
storage->shader_initialize(default_shader);
storage->shader_set_code(default_shader, R"(
+// Default 3D material shader (mobile).
+
shader_type spatial;
void vertex() {
@@ -701,6 +705,8 @@ void fragment() {
storage->shader_initialize(overdraw_material_shader);
// Use relatively low opacity so that more "layers" of overlapping objects can be distinguished.
storage->shader_set_code(overdraw_material_shader, R"(
+// 3D editor Overdraw debug draw mode shader (mobile).
+
shader_type spatial;
render_mode blend_add, unshaded;
diff --git a/servers/rendering/renderer_rd/pipeline_cache_rd.cpp b/servers/rendering/renderer_rd/pipeline_cache_rd.cpp
index aefe926cb0..0d60052666 100644
--- a/servers/rendering/renderer_rd/pipeline_cache_rd.cpp
+++ b/servers/rendering/renderer_rd/pipeline_cache_rd.cpp
@@ -35,8 +35,10 @@ RID PipelineCacheRD::_generate_version(RD::VertexFormatID p_vertex_format_id, RD
RD::PipelineMultisampleState multisample_state_version = multisample_state;
multisample_state_version.sample_count = RD::get_singleton()->framebuffer_format_get_texture_samples(p_framebuffer_format_id, p_render_pass);
+ bool wireframe = p_wireframe || rasterization_state.wireframe;
+
RD::PipelineRasterizationState raster_state_version = rasterization_state;
- raster_state_version.wireframe = p_wireframe;
+ raster_state_version.wireframe = wireframe;
Vector<RD::PipelineSpecializationConstant> specialization_constants = base_specialization_constants;
@@ -59,7 +61,7 @@ RID PipelineCacheRD::_generate_version(RD::VertexFormatID p_vertex_format_id, RD
versions = (Version *)memrealloc(versions, sizeof(Version) * (version_count + 1));
versions[version_count].framebuffer_id = p_framebuffer_format_id;
versions[version_count].vertex_id = p_vertex_format_id;
- versions[version_count].wireframe = p_wireframe;
+ versions[version_count].wireframe = wireframe;
versions[version_count].pipeline = pipeline;
versions[version_count].render_pass = p_render_pass;
versions[version_count].bool_specializations = p_bool_specializations;
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
index f8aefdb29c..c69c9eeadf 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
@@ -541,6 +541,14 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
src_rect = Rect2(0, 0, 1, 1);
}
+ if (rect->flags & CANVAS_RECT_MSDF) {
+ push_constant.flags |= FLAGS_USE_MSDF;
+ push_constant.msdf[0] = rect->px_range; // Pixel range.
+ push_constant.msdf[1] = rect->outline; // Outline size.
+ push_constant.msdf[2] = 0.f; // Reserved.
+ push_constant.msdf[3] = 0.f; // Reserved.
+ }
+
push_constant.modulation[0] = rect->modulate.r * base_color.r;
push_constant.modulation[1] = rect->modulate.g * base_color.g;
push_constant.modulation[2] = rect->modulate.b * base_color.b;
@@ -1078,7 +1086,7 @@ void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_co
}
}
- RID material = ci->material;
+ RID material = ci->material_owner == nullptr ? ci->material : ci->material_owner->material;
if (material.is_null() && ci->canvas_group != nullptr) {
material = default_canvas_group_material;
@@ -1094,7 +1102,7 @@ void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_co
if (material_data->shader_data->version.is_valid() && material_data->shader_data->valid) {
pipeline_variants = &material_data->shader_data->pipeline_variants;
// Update uniform set.
- if (RD::get_singleton()->uniform_set_is_valid(material_data->uniform_set)) { // Material may not have a uniform set.
+ if (material_data->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(material_data->uniform_set)) { // Material may not have a uniform set.
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, material_data->uniform_set, MATERIAL_UNIFORM_SET);
}
} else {
@@ -1136,7 +1144,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
continue;
}
- CanvasLight *clight = canvas_light_owner.getornull(l->light_internal);
+ CanvasLight *clight = canvas_light_owner.get_or_null(l->light_internal);
if (!clight) { //unused or invalid texture
l->render_index_cache = -1;
l = l->next_ptr;
@@ -1199,7 +1207,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
continue;
}
- CanvasLight *clight = canvas_light_owner.getornull(l->light_internal);
+ CanvasLight *clight = canvas_light_owner.get_or_null(l->light_internal);
if (!clight) { //unused or invalid texture
l->render_index_cache = -1;
l = l->next_ptr;
@@ -1346,8 +1354,10 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
}
}
- if (ci->material.is_valid()) {
- MaterialData *md = (MaterialData *)storage->material_get_data(ci->material, RendererStorageRD::SHADER_TYPE_2D);
+ RID material = ci->material_owner == nullptr ? ci->material : ci->material_owner->material;
+
+ if (material.is_valid()) {
+ MaterialData *md = (MaterialData *)storage->material_get_data(material, RendererStorageRD::SHADER_TYPE_2D);
if (md && md->shader_data->valid) {
if (md->shader_data->uses_screen_texture && canvas_group_owner == nullptr) {
if (!material_screen_texture_found) {
@@ -1367,7 +1377,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
if (!RD::get_singleton()->uniform_set_is_valid(md->uniform_set)) {
// uniform set may be gone because a dependency was erased. In this case, it will happen
// if a texture is deleted, so just re-create it.
- storage->material_force_update_textures(ci->material, RendererStorageRD::SHADER_TYPE_2D);
+ storage->material_force_update_textures(material, RendererStorageRD::SHADER_TYPE_2D);
}
}
}
@@ -1384,6 +1394,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
update_skeletons = true;
}
}
+ c = c->next;
}
}
@@ -1470,7 +1481,7 @@ RID RendererCanvasRenderRD::light_create() {
}
void RendererCanvasRenderRD::light_set_texture(RID p_rid, RID p_texture) {
- CanvasLight *cl = canvas_light_owner.getornull(p_rid);
+ CanvasLight *cl = canvas_light_owner.get_or_null(p_rid);
ERR_FAIL_COND(!cl);
if (cl->texture == p_texture) {
return;
@@ -1486,7 +1497,7 @@ void RendererCanvasRenderRD::light_set_texture(RID p_rid, RID p_texture) {
}
void RendererCanvasRenderRD::light_set_use_shadow(RID p_rid, bool p_enable) {
- CanvasLight *cl = canvas_light_owner.getornull(p_rid);
+ CanvasLight *cl = canvas_light_owner.get_or_null(p_rid);
ERR_FAIL_COND(!cl);
cl->shadow.enabled = p_enable;
@@ -1526,7 +1537,7 @@ void RendererCanvasRenderRD::_update_shadow_atlas() {
}
}
void RendererCanvasRenderRD::light_update_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders) {
- CanvasLight *cl = canvas_light_owner.getornull(p_rid);
+ CanvasLight *cl = canvas_light_owner.get_or_null(p_rid);
ERR_FAIL_COND(!cl->shadow.enabled);
_update_shadow_atlas();
@@ -1580,7 +1591,7 @@ void RendererCanvasRenderRD::light_update_shadow(RID p_rid, int p_shadow_index,
LightOccluderInstance *instance = p_occluders;
while (instance) {
- OccluderPolygon *co = occluder_polygon_owner.getornull(instance->occluder);
+ OccluderPolygon *co = occluder_polygon_owner.get_or_null(instance->occluder);
if (!co || co->index_array.is_null() || !(p_light_mask & instance->light_mask)) {
instance = instance->next;
@@ -1604,14 +1615,14 @@ void RendererCanvasRenderRD::light_update_shadow(RID p_rid, int p_shadow_index,
}
void RendererCanvasRenderRD::light_update_directional_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_cull_distance, const Rect2 &p_clip_rect, LightOccluderInstance *p_occluders) {
- CanvasLight *cl = canvas_light_owner.getornull(p_rid);
+ CanvasLight *cl = canvas_light_owner.get_or_null(p_rid);
ERR_FAIL_COND(!cl->shadow.enabled);
_update_shadow_atlas();
Vector2 light_dir = p_light_xform.elements[1].normalized();
- Vector2 center = p_clip_rect.position + p_clip_rect.size * 0.5;
+ Vector2 center = p_clip_rect.get_center();
float to_edge_distance = ABS(light_dir.dot(p_clip_rect.get_support(light_dir)) - light_dir.dot(center));
@@ -1655,7 +1666,7 @@ void RendererCanvasRenderRD::light_update_directional_shadow(RID p_rid, int p_sh
LightOccluderInstance *instance = p_occluders;
while (instance) {
- OccluderPolygon *co = occluder_polygon_owner.getornull(instance->occluder);
+ OccluderPolygon *co = occluder_polygon_owner.get_or_null(instance->occluder);
if (!co || co->index_array.is_null() || !(p_light_mask & instance->light_mask)) {
instance = instance->next;
@@ -1721,7 +1732,7 @@ void RendererCanvasRenderRD::render_sdf(RID p_render_target, LightOccluderInstan
LightOccluderInstance *instance = p_occluders;
while (instance) {
- OccluderPolygon *co = occluder_polygon_owner.getornull(instance->occluder);
+ OccluderPolygon *co = occluder_polygon_owner.get_or_null(instance->occluder);
if (!co || co->sdf_index_array.is_null()) {
instance = instance->next;
@@ -1755,7 +1766,7 @@ RID RendererCanvasRenderRD::occluder_polygon_create() {
}
void RendererCanvasRenderRD::occluder_polygon_set_shape(RID p_occluder, const Vector<Vector2> &p_points, bool p_closed) {
- OccluderPolygon *oc = occluder_polygon_owner.getornull(p_occluder);
+ OccluderPolygon *oc = occluder_polygon_owner.get_or_null(p_occluder);
ERR_FAIL_COND(!oc);
Vector<Vector2> lines;
@@ -1924,7 +1935,7 @@ void RendererCanvasRenderRD::occluder_polygon_set_shape(RID p_occluder, const Ve
}
void RendererCanvasRenderRD::occluder_polygon_set_cull_mode(RID p_occluder, RS::CanvasOccluderPolygonCullMode p_mode) {
- OccluderPolygon *oc = occluder_polygon_owner.getornull(p_occluder);
+ OccluderPolygon *oc = occluder_polygon_owner.get_or_null(p_occluder);
ERR_FAIL_COND(!oc);
oc->cull_mode = p_mode;
}
@@ -2122,35 +2133,35 @@ void RendererCanvasRenderRD::ShaderData::set_default_texture_param(const StringN
void RendererCanvasRenderRD::ShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
Map<int, StringName> order;
- for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) {
- if (E->get().scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) {
+ for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
+ if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) {
continue;
}
- if (E->get().texture_order >= 0) {
- order[E->get().texture_order + 100000] = E->key();
+ if (E.value.texture_order >= 0) {
+ order[E.value.texture_order + 100000] = E.key;
} else {
- order[E->get().order] = E->key();
+ order[E.value.order] = E.key;
}
}
- for (Map<int, StringName>::Element *E = order.front(); E; E = E->next()) {
- PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E->get()]);
- pi.name = E->get();
+ for (const KeyValue<int, StringName> &E : order) {
+ PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]);
+ pi.name = E.value;
p_param_list->push_back(pi);
}
}
void RendererCanvasRenderRD::ShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const {
- for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) {
- if (E->get().scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
+ for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
+ if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
continue;
}
RendererStorage::InstanceShaderParam p;
- p.info = ShaderLanguage::uniform_to_property_info(E->get());
- p.info.name = E->key(); //supply name
- p.index = E->get().instance_index;
- p.default_value = ShaderLanguage::constant_value_to_variant(E->get().default_value, E->get().type, E->get().hint);
+ p.info = ShaderLanguage::uniform_to_property_info(E.value);
+ p.info.name = E.key; //supply name
+ p.index = E.value.instance_index;
+ p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint);
p_param_list->push_back(p);
}
}
@@ -2175,7 +2186,7 @@ Variant RendererCanvasRenderRD::ShaderData::get_default_parameter(const StringNa
if (uniforms.has(p_parameter)) {
ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter];
Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value;
- return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.hint);
+ return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint);
}
return Variant();
}
@@ -2575,6 +2586,8 @@ RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) {
storage->shader_initialize(default_canvas_group_shader);
storage->shader_set_code(default_canvas_group_shader, R"(
+// Default CanvasGroup shader.
+
shader_type canvas_item;
void fragment() {
@@ -2598,7 +2611,7 @@ void fragment() {
bool RendererCanvasRenderRD::free(RID p_rid) {
if (canvas_light_owner.owns(p_rid)) {
- CanvasLight *cl = canvas_light_owner.getornull(p_rid);
+ CanvasLight *cl = canvas_light_owner.get_or_null(p_rid);
ERR_FAIL_COND_V(!cl, false);
light_set_use_shadow(p_rid, false);
canvas_light_owner.free(p_rid);
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
index 7c4f62832c..ec7d7e2854 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
@@ -84,8 +84,9 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
FLAGS_LIGHT_COUNT_SHIFT = 20,
FLAGS_DEFAULT_NORMAL_MAP_USED = (1 << 26),
- FLAGS_DEFAULT_SPECULAR_MAP_USED = (1 << 27)
+ FLAGS_DEFAULT_SPECULAR_MAP_USED = (1 << 27),
+ FLAGS_USE_MSDF = (1 << 28),
};
enum {
@@ -388,7 +389,10 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
//rect
struct {
float modulation[4];
- float ninepatch_margins[4];
+ union {
+ float msdf[4];
+ float ninepatch_margins[4];
+ };
float dst_rect[4];
float src_rect[4];
float pad[2];
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
index 62e9386f95..559e6d5ad7 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
@@ -46,6 +46,8 @@ void RendererCompositorRD::blit_render_targets_to_screen(DisplayServer::WindowID
RID rd_texture = storage->texture_get_rd_texture(texture);
ERR_CONTINUE(rd_texture.is_null());
+ // TODO if keep_3d_linear was set when rendering to this render target we need to add a linear->sRGB conversion in.
+
if (!render_target_descriptors.has(rd_texture) || !RD::get_singleton()->uniform_set_is_valid(render_target_descriptors[rd_texture])) {
Vector<RD::Uniform> uniforms;
RD::Uniform u;
@@ -65,10 +67,14 @@ void RendererCompositorRD::blit_render_targets_to_screen(DisplayServer::WindowID
RD::get_singleton()->draw_list_bind_index_array(draw_list, blit.array);
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, render_target_descriptors[rd_texture], 0);
- blit.push_constant.rect[0] = p_render_targets[i].rect.position.x / screen_size.width;
- blit.push_constant.rect[1] = p_render_targets[i].rect.position.y / screen_size.height;
- blit.push_constant.rect[2] = p_render_targets[i].rect.size.width / screen_size.width;
- blit.push_constant.rect[3] = p_render_targets[i].rect.size.height / screen_size.height;
+ blit.push_constant.src_rect[0] = p_render_targets[i].src_rect.position.x;
+ blit.push_constant.src_rect[1] = p_render_targets[i].src_rect.position.y;
+ blit.push_constant.src_rect[2] = p_render_targets[i].src_rect.size.width;
+ blit.push_constant.src_rect[3] = p_render_targets[i].src_rect.size.height;
+ blit.push_constant.dst_rect[0] = p_render_targets[i].dst_rect.position.x / screen_size.width;
+ blit.push_constant.dst_rect[1] = p_render_targets[i].dst_rect.position.y / screen_size.height;
+ blit.push_constant.dst_rect[2] = p_render_targets[i].dst_rect.size.width / screen_size.width;
+ blit.push_constant.dst_rect[3] = p_render_targets[i].dst_rect.size.height / screen_size.height;
blit.push_constant.layer = p_render_targets[i].multi_view.layer;
blit.push_constant.eye_center[0] = p_render_targets[i].lens_distortion.eye_center.x;
blit.push_constant.eye_center[1] = p_render_targets[i].lens_distortion.eye_center.y;
@@ -191,7 +197,7 @@ void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color
}
} else {
screenrect = imgrect;
- screenrect.position += ((Size2(window_size.width, window_size.height) - screenrect.size) / 2.0).floor();
+ screenrect.position += ((window_size - screenrect.size) / 2.0).floor();
}
screenrect.position /= window_size;
@@ -203,10 +209,14 @@ void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color
RD::get_singleton()->draw_list_bind_index_array(draw_list, blit.array);
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uset, 0);
- blit.push_constant.rect[0] = screenrect.position.x;
- blit.push_constant.rect[1] = screenrect.position.y;
- blit.push_constant.rect[2] = screenrect.size.width;
- blit.push_constant.rect[3] = screenrect.size.height;
+ blit.push_constant.src_rect[0] = 0.0;
+ blit.push_constant.src_rect[1] = 0.0;
+ blit.push_constant.src_rect[2] = 1.0;
+ blit.push_constant.src_rect[3] = 1.0;
+ blit.push_constant.dst_rect[0] = screenrect.position.x;
+ blit.push_constant.dst_rect[1] = screenrect.position.y;
+ blit.push_constant.dst_rect[2] = screenrect.size.width;
+ blit.push_constant.dst_rect[3] = screenrect.size.height;
blit.push_constant.layer = 0;
blit.push_constant.eye_center[0] = 0;
blit.push_constant.eye_center[1] = 0;
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.h b/servers/rendering/renderer_rd/renderer_compositor_rd.h
index 8639362da9..0230c46800 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.h
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h
@@ -55,7 +55,8 @@ protected:
};
struct BlitPushConstant {
- float rect[4];
+ float src_rect[4];
+ float dst_rect[4];
float eye_center[2];
float k1;
diff --git a/servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp
index d631cb4bac..bb7fbbcdc2 100644
--- a/servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp
@@ -32,13 +32,12 @@
uint64_t RendererSceneEnvironmentRD::auto_exposure_counter = 2;
-void RendererSceneEnvironmentRD::set_ambient_light(const Color &p_color, RS::EnvironmentAmbientSource p_ambient, float p_energy, float p_sky_contribution, RS::EnvironmentReflectionSource p_reflection_source, const Color &p_ao_color) {
+void RendererSceneEnvironmentRD::set_ambient_light(const Color &p_color, RS::EnvironmentAmbientSource p_ambient, float p_energy, float p_sky_contribution, RS::EnvironmentReflectionSource p_reflection_source) {
ambient_light = p_color;
ambient_source = p_ambient;
ambient_light_energy = p_energy;
ambient_sky_contribution = p_sky_contribution;
reflection_source = p_reflection_source;
- ao_color = p_ao_color;
}
void RendererSceneEnvironmentRD::set_tonemap(RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) {
diff --git a/servers/rendering/renderer_rd/renderer_scene_environment_rd.h b/servers/rendering/renderer_rd/renderer_scene_environment_rd.h
index 992c4bf471..bc47abbff5 100644
--- a/servers/rendering/renderer_rd/renderer_scene_environment_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_environment_rd.h
@@ -52,7 +52,6 @@ public:
float ambient_light_energy = 1.0;
float ambient_sky_contribution = 1.0;
RS::EnvironmentReflectionSource reflection_source = RS::ENV_REFLECTION_SOURCE_BG;
- Color ao_color;
/// Tonemap
@@ -142,7 +141,7 @@ public:
bool use_1d_color_correction = false;
RID color_correction = RID();
- void set_ambient_light(const Color &p_color, RS::EnvironmentAmbientSource p_ambient, float p_energy, float p_sky_contribution, RS::EnvironmentReflectionSource p_reflection_source, const Color &p_ao_color);
+ void set_ambient_light(const Color &p_color, RS::EnvironmentAmbientSource p_ambient, float p_energy, float p_sky_contribution, RS::EnvironmentReflectionSource p_reflection_source);
void set_tonemap(RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale);
void set_glow(bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap);
void set_sdfgi(bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias);
diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp
index 098e2a5c87..ea73dbf26e 100644
--- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp
@@ -1450,7 +1450,7 @@ void RendererSceneGIRD::SDFGI::pre_process_gi(const Transform3D &p_transform, Re
break;
}
- RendererSceneRenderRD::LightInstance *li = p_scene_render->light_instance_owner.getornull(p_scene_render->render_state.sdfgi_update_data->directional_lights->get(j));
+ RendererSceneRenderRD::LightInstance *li = p_scene_render->light_instance_owner.get_or_null(p_scene_render->render_state.sdfgi_update_data->directional_lights->get(j));
ERR_CONTINUE(!li);
if (storage->light_directional_is_sky_only(li->light)) {
@@ -1469,7 +1469,7 @@ void RendererSceneGIRD::SDFGI::pre_process_gi(const Transform3D &p_transform, Re
lights[idx].color[1] = color.g;
lights[idx].color[2] = color.b;
lights[idx].type = RS::LIGHT_DIRECTIONAL;
- lights[idx].energy = storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY);
+ lights[idx].energy = storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY) * storage->light_get_param(li->light, RS::LIGHT_PARAM_INDIRECT_ENERGY);
lights[idx].has_shadow = storage->light_has_shadow(li->light);
idx++;
@@ -1484,7 +1484,7 @@ void RendererSceneGIRD::SDFGI::pre_process_gi(const Transform3D &p_transform, Re
break;
}
- RendererSceneRenderRD::LightInstance *li = p_scene_render->light_instance_owner.getornull(p_scene_render->render_state.sdfgi_update_data->positional_light_instances[j]);
+ RendererSceneRenderRD::LightInstance *li = p_scene_render->light_instance_owner.get_or_null(p_scene_render->render_state.sdfgi_update_data->positional_light_instances[j]);
ERR_CONTINUE(!li);
uint32_t max_sdfgi_cascade = storage->light_get_max_sdfgi_cascade(li->light);
@@ -1514,7 +1514,7 @@ void RendererSceneGIRD::SDFGI::pre_process_gi(const Transform3D &p_transform, Re
lights[idx].color[1] = color.g;
lights[idx].color[2] = color.b;
lights[idx].type = storage->light_get_type(li->light);
- lights[idx].energy = storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY);
+ lights[idx].energy = storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY) * storage->light_get_param(li->light, RS::LIGHT_PARAM_INDIRECT_ENERGY);
lights[idx].has_shadow = storage->light_has_shadow(li->light);
lights[idx].attenuation = storage->light_get_param(li->light, RS::LIGHT_PARAM_ATTENUATION);
lights[idx].radius = storage->light_get_param(li->light, RS::LIGHT_PARAM_RANGE);
@@ -1534,7 +1534,7 @@ void RendererSceneGIRD::SDFGI::pre_process_gi(const Transform3D &p_transform, Re
void RendererSceneGIRD::SDFGI::render_region(RID p_render_buffers, int p_region, const PagedArray<RendererSceneRender::GeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render) {
//print_line("rendering region " + itos(p_region));
- RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.getornull(p_render_buffers);
+ RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(!rb); // we wouldn't be here if this failed but...
AABB bounds;
Vector3i from;
@@ -1892,7 +1892,7 @@ void RendererSceneGIRD::SDFGI::render_region(RID p_render_buffers, int p_region,
}
void RendererSceneGIRD::SDFGI::render_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result, RendererSceneRenderRD *p_scene_render) {
- RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.getornull(p_render_buffers);
+ RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(!rb); // we wouldn't be here if this failed but...
RD::get_singleton()->draw_command_begin_label("SDFGI Render Static Lighs");
@@ -1921,7 +1921,7 @@ void RendererSceneGIRD::SDFGI::render_static_lights(RID p_render_buffers, uint32
break;
}
- RendererSceneRenderRD::LightInstance *li = p_scene_render->light_instance_owner.getornull(p_positional_light_cull_result[i][j]);
+ RendererSceneRenderRD::LightInstance *li = p_scene_render->light_instance_owner.get_or_null(p_positional_light_cull_result[i][j]);
ERR_CONTINUE(!li);
uint32_t max_sdfgi_cascade = storage->light_get_max_sdfgi_cascade(li->light);
@@ -1953,7 +1953,7 @@ void RendererSceneGIRD::SDFGI::render_static_lights(RID p_render_buffers, uint32
lights[idx].color[0] = color.r;
lights[idx].color[1] = color.g;
lights[idx].color[2] = color.b;
- lights[idx].energy = storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY);
+ lights[idx].energy = storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY) * storage->light_get_param(li->light, RS::LIGHT_PARAM_INDIRECT_ENERGY);
lights[idx].has_shadow = storage->light_has_shadow(li->light);
lights[idx].attenuation = storage->light_get_param(li->light, RS::LIGHT_PARAM_ATTENUATION);
lights[idx].radius = storage->light_get_param(li->light, RS::LIGHT_PARAM_RANGE);
@@ -2575,7 +2575,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
Vector3 render_dir = render_z[j];
Vector3 up_dir = render_up[j];
- Vector3 center = aabb.position + aabb.size * 0.5;
+ Vector3 center = aabb.get_center();
Transform3D xform;
xform.set_look_at(center - aabb.size * 0.5 * render_dir, center, up_dir);
@@ -3024,7 +3024,7 @@ void RendererSceneGIRD::setup_voxel_gi_instances(RID p_render_buffers, const Tra
r_voxel_gi_instances_used = 0;
// feels a little dirty to use our container this way but....
- RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.getornull(p_render_buffers);
+ RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(rb == nullptr);
RID voxel_gi_buffer = p_scene_render->render_buffers_get_voxel_gi_buffer(p_render_buffers);
@@ -3119,9 +3119,8 @@ void RendererSceneGIRD::setup_voxel_gi_instances(RID p_render_buffers, const Tra
void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_voxel_gi_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render) {
RD::get_singleton()->draw_command_begin_label("GI Render");
- RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.getornull(p_render_buffers);
+ RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(rb == nullptr);
- RendererSceneEnvironmentRD *env = p_scene_render->environment_owner.getornull(p_environment);
if (rb->ambient_buffer.is_null() || rb->gi.using_half_size_gi != half_resolution) {
if (rb->ambient_buffer.is_valid()) {
@@ -3160,16 +3159,6 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_
bool use_sdfgi = rb->sdfgi != nullptr;
bool use_voxel_gi_instances = push_constant.max_voxel_gi_instances > 0;
- if (env) {
- push_constant.ao_color[0] = env->ao_color.r;
- push_constant.ao_color[1] = env->ao_color.g;
- push_constant.ao_color[2] = env->ao_color.b;
- } else {
- push_constant.ao_color[0] = 0;
- push_constant.ao_color[1] = 0;
- push_constant.ao_color[2] = 0;
- }
-
push_constant.cam_rotation[0] = p_transform.basis[0][0];
push_constant.cam_rotation[1] = p_transform.basis[1][0];
push_constant.cam_rotation[2] = p_transform.basis[2][0];
@@ -3393,7 +3382,7 @@ void RendererSceneGIRD::voxel_gi_update(RID p_probe, bool p_update_light_instanc
}
void RendererSceneGIRD::debug_voxel_gi(RID p_voxel_gi, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) {
- VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.getornull(p_voxel_gi);
+ VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_voxel_gi);
ERR_FAIL_COND(!voxel_gi);
voxel_gi->debug(p_draw_list, p_framebuffer, p_camera_with_transform, p_lighting, p_emission, p_alpha);
diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.h b/servers/rendering/renderer_rd/renderer_scene_gi_rd.h
index 0b4622646f..9f6fc8a9b7 100644
--- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.h
@@ -383,7 +383,7 @@ public:
mutable RID_Owner<VoxelGIInstance> voxel_gi_instance_owner;
_FORCE_INLINE_ VoxelGIInstance *get_probe_instance(RID p_probe) const {
- return voxel_gi_instance_owner.getornull(p_probe);
+ return voxel_gi_instance_owner.get_or_null(p_probe);
};
_FORCE_INLINE_ RID voxel_gi_instance_get_texture(RID p_probe) {
@@ -623,12 +623,11 @@ public:
float z_far;
float proj_info[4];
- float ao_color[3];
- uint32_t max_voxel_gi_instances;
+ uint32_t max_voxel_gi_instances;
uint32_t high_quality_vct;
uint32_t orthogonal;
- uint32_t pad[2];
+ uint32_t pad;
float cam_rotation[12];
};
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index 8496ef631b..329deeb1ae 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -48,8 +48,8 @@ void get_vogel_disk(float *r_kernel, int p_sample_count) {
}
void RendererSceneRenderRD::sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) {
- RendererSceneEnvironmentRD *env = environment_owner.getornull(p_environment);
- RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+ RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_environment);
+ RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
bool needs_sdfgi = env && env->sdfgi_enabled;
if (!needs_sdfgi) {
@@ -83,7 +83,7 @@ void RendererSceneRenderRD::sdfgi_update(RID p_render_buffers, RID p_environment
}
int RendererSceneRenderRD::sdfgi_get_pending_region_count(RID p_render_buffers) const {
- RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+ RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND_V(rb == nullptr, 0);
@@ -113,7 +113,7 @@ AABB RendererSceneRenderRD::sdfgi_get_pending_region_bounds(RID p_render_buffers
AABB bounds;
Vector3i from;
Vector3i size;
- RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+ RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND_V(rb == nullptr, AABB());
ERR_FAIL_COND_V(rb->sdfgi == nullptr, AABB());
@@ -126,7 +126,7 @@ uint32_t RendererSceneRenderRD::sdfgi_get_pending_region_cascade(RID p_render_bu
AABB bounds;
Vector3i from;
Vector3i size;
- RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+ RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND_V(rb == nullptr, -1);
ERR_FAIL_COND_V(rb->sdfgi == nullptr, -1);
@@ -164,139 +164,133 @@ void RendererSceneRenderRD::environment_initialize(RID p_rid) {
}
void RendererSceneRenderRD::environment_set_background(RID p_env, RS::EnvironmentBG p_bg) {
- RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND(!env);
env->background = p_bg;
}
void RendererSceneRenderRD::environment_set_sky(RID p_env, RID p_sky) {
- RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND(!env);
env->sky = p_sky;
}
void RendererSceneRenderRD::environment_set_sky_custom_fov(RID p_env, float p_scale) {
- RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND(!env);
env->sky_custom_fov = p_scale;
}
void RendererSceneRenderRD::environment_set_sky_orientation(RID p_env, const Basis &p_orientation) {
- RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND(!env);
env->sky_orientation = p_orientation;
}
void RendererSceneRenderRD::environment_set_bg_color(RID p_env, const Color &p_color) {
- RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND(!env);
env->bg_color = p_color;
}
void RendererSceneRenderRD::environment_set_bg_energy(RID p_env, float p_energy) {
- RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND(!env);
env->bg_energy = p_energy;
}
void RendererSceneRenderRD::environment_set_canvas_max_layer(RID p_env, int p_max_layer) {
- RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND(!env);
env->canvas_max_layer = p_max_layer;
}
-void RendererSceneRenderRD::environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient, float p_energy, float p_sky_contribution, RS::EnvironmentReflectionSource p_reflection_source, const Color &p_ao_color) {
- RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
+void RendererSceneRenderRD::environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient, float p_energy, float p_sky_contribution, RS::EnvironmentReflectionSource p_reflection_source) {
+ RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND(!env);
- env->set_ambient_light(p_color, p_ambient, p_energy, p_sky_contribution, p_reflection_source, p_ao_color);
+ env->set_ambient_light(p_color, p_ambient, p_energy, p_sky_contribution, p_reflection_source);
}
RS::EnvironmentBG RendererSceneRenderRD::environment_get_background(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND_V(!env, RS::ENV_BG_MAX);
return env->background;
}
RID RendererSceneRenderRD::environment_get_sky(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND_V(!env, RID());
return env->sky;
}
float RendererSceneRenderRD::environment_get_sky_custom_fov(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND_V(!env, 0);
return env->sky_custom_fov;
}
Basis RendererSceneRenderRD::environment_get_sky_orientation(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND_V(!env, Basis());
return env->sky_orientation;
}
Color RendererSceneRenderRD::environment_get_bg_color(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND_V(!env, Color());
return env->bg_color;
}
float RendererSceneRenderRD::environment_get_bg_energy(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND_V(!env, 0);
return env->bg_energy;
}
int RendererSceneRenderRD::environment_get_canvas_max_layer(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND_V(!env, 0);
return env->canvas_max_layer;
}
Color RendererSceneRenderRD::environment_get_ambient_light_color(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND_V(!env, Color());
return env->ambient_light;
}
RS::EnvironmentAmbientSource RendererSceneRenderRD::environment_get_ambient_source(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND_V(!env, RS::ENV_AMBIENT_SOURCE_BG);
return env->ambient_source;
}
float RendererSceneRenderRD::environment_get_ambient_light_energy(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND_V(!env, 0);
return env->ambient_light_energy;
}
float RendererSceneRenderRD::environment_get_ambient_sky_contribution(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND_V(!env, 0);
return env->ambient_sky_contribution;
}
RS::EnvironmentReflectionSource RendererSceneRenderRD::environment_get_reflection_source(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND_V(!env, RS::ENV_REFLECTION_SOURCE_DISABLED);
return env->reflection_source;
}
-Color RendererSceneRenderRD::environment_get_ao_color(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
- ERR_FAIL_COND_V(!env, Color());
- return env->ao_color;
-}
-
void RendererSceneRenderRD::environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) {
- RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND(!env);
env->set_tonemap(p_tone_mapper, p_exposure, p_white, p_auto_exposure, p_min_luminance, p_max_luminance, p_auto_exp_speed, p_auto_exp_scale);
}
void RendererSceneRenderRD::environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap) {
- RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND(!env);
env->set_glow(p_enable, p_levels, p_intensity, p_strength, p_mix, p_bloom_threshold, p_blend_mode, p_hdr_bleed_threshold, p_hdr_bleed_scale, p_hdr_luminance_cap);
}
@@ -310,7 +304,7 @@ void RendererSceneRenderRD::environment_glow_set_use_high_quality(bool p_enable)
}
void RendererSceneRenderRD::environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) {
- RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND(!env);
if (!is_dynamic_gi_supported()) {
@@ -321,58 +315,58 @@ void RendererSceneRenderRD::environment_set_sdfgi(RID p_env, bool p_enable, RS::
}
void RendererSceneRenderRD::environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_fog_aerial_perspective) {
- RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND(!env);
env->set_fog(p_enable, p_light_color, p_light_energy, p_sun_scatter, p_density, p_height, p_height_density, p_fog_aerial_perspective);
}
bool RendererSceneRenderRD::environment_is_fog_enabled(RID p_env) const {
- const RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
+ const RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND_V(!env, false);
return env->fog_enabled;
}
Color RendererSceneRenderRD::environment_get_fog_light_color(RID p_env) const {
- const RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
+ const RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND_V(!env, Color());
return env->fog_light_color;
}
float RendererSceneRenderRD::environment_get_fog_light_energy(RID p_env) const {
- const RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
+ const RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND_V(!env, 0);
return env->fog_light_energy;
}
float RendererSceneRenderRD::environment_get_fog_sun_scatter(RID p_env) const {
- const RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
+ const RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND_V(!env, 0);
return env->fog_sun_scatter;
}
float RendererSceneRenderRD::environment_get_fog_density(RID p_env) const {
- const RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
+ const RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND_V(!env, 0);
return env->fog_density;
}
float RendererSceneRenderRD::environment_get_fog_height(RID p_env) const {
- const RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
+ const RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND_V(!env, 0);
return env->fog_height;
}
float RendererSceneRenderRD::environment_get_fog_height_density(RID p_env) const {
- const RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
+ const RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND_V(!env, 0);
return env->fog_height_density;
}
float RendererSceneRenderRD::environment_get_fog_aerial_perspective(RID p_env) const {
- const RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
+ const RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND_V(!env, 0);
return env->fog_aerial_perspective;
}
void RendererSceneRenderRD::environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount) {
- RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND(!env);
if (!is_volumetric_supported()) {
@@ -403,7 +397,7 @@ void RendererSceneRenderRD::environment_set_sdfgi_frames_to_update_light(RS::Env
}
void RendererSceneRenderRD::environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) {
- RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND(!env);
env->set_ssr(p_enable, p_max_steps, p_fade_int, p_fade_out, p_depth_tolerance);
@@ -418,7 +412,7 @@ RS::EnvironmentSSRRoughnessQuality RendererSceneRenderRD::environment_get_ssr_ro
}
void RendererSceneRenderRD::environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) {
- RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND(!env);
env->set_ssao(p_enable, p_radius, p_intensity, p_power, p_detail, p_horizon, p_sharpness, p_light_affect, p_ao_channel_affect);
@@ -434,30 +428,30 @@ void RendererSceneRenderRD::environment_set_ssao_quality(RS::EnvironmentSSAOQual
}
bool RendererSceneRenderRD::environment_is_ssao_enabled(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND_V(!env, false);
return env->ssao_enabled;
}
float RendererSceneRenderRD::environment_get_ssao_ao_affect(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND_V(!env, 0.0);
return env->ssao_ao_channel_affect;
}
float RendererSceneRenderRD::environment_get_ssao_light_affect(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND_V(!env, 0.0);
return env->ssao_direct_light_affect;
}
bool RendererSceneRenderRD::environment_is_ssr_enabled(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND_V(!env, false);
return env->ssr_enabled;
}
bool RendererSceneRenderRD::environment_is_sdfgi_enabled(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND_V(!env, false);
return env->sdfgi_enabled;
}
@@ -467,7 +461,7 @@ bool RendererSceneRenderRD::is_environment(RID p_env) const {
}
Ref<Image> RendererSceneRenderRD::environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) {
- RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND_V(!env, Ref<Image>());
if (env->background == RS::ENV_BG_CAMERA_FEED || env->background == RS::ENV_BG_CANVAS || env->background == RS::ENV_BG_KEEP) {
@@ -522,7 +516,7 @@ RID RendererSceneRenderRD::reflection_atlas_create() {
}
void RendererSceneRenderRD::reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) {
- ReflectionAtlas *ra = reflection_atlas_owner.getornull(p_ref_atlas);
+ ReflectionAtlas *ra = reflection_atlas_owner.get_or_null(p_ref_atlas);
ERR_FAIL_COND(!ra);
if (ra->size == p_reflection_size && ra->count == p_reflection_count) {
@@ -557,7 +551,7 @@ void RendererSceneRenderRD::reflection_atlas_set_size(RID p_ref_atlas, int p_ref
}
int RendererSceneRenderRD::reflection_atlas_get_size(RID p_ref_atlas) const {
- ReflectionAtlas *ra = reflection_atlas_owner.getornull(p_ref_atlas);
+ ReflectionAtlas *ra = reflection_atlas_owner.get_or_null(p_ref_atlas);
ERR_FAIL_COND_V(!ra, 0);
return ra->size;
@@ -573,7 +567,7 @@ RID RendererSceneRenderRD::reflection_probe_instance_create(RID p_probe) {
}
void RendererSceneRenderRD::reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) {
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
ERR_FAIL_COND(!rpi);
rpi->transform = p_transform;
@@ -581,13 +575,13 @@ void RendererSceneRenderRD::reflection_probe_instance_set_transform(RID p_instan
}
void RendererSceneRenderRD::reflection_probe_release_atlas_index(RID p_instance) {
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
ERR_FAIL_COND(!rpi);
if (rpi->atlas.is_null()) {
return; //nothing to release
}
- ReflectionAtlas *atlas = reflection_atlas_owner.getornull(rpi->atlas);
+ ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(rpi->atlas);
ERR_FAIL_COND(!atlas);
ERR_FAIL_INDEX(rpi->atlas_index, atlas->reflections.size());
atlas->reflections.write[rpi->atlas_index].owner = RID();
@@ -596,7 +590,7 @@ void RendererSceneRenderRD::reflection_probe_release_atlas_index(RID p_instance)
}
bool RendererSceneRenderRD::reflection_probe_instance_needs_redraw(RID p_instance) {
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
ERR_FAIL_COND_V(!rpi, false);
if (rpi->rendering) {
@@ -615,18 +609,18 @@ bool RendererSceneRenderRD::reflection_probe_instance_needs_redraw(RID p_instanc
}
bool RendererSceneRenderRD::reflection_probe_instance_has_reflection(RID p_instance) {
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
ERR_FAIL_COND_V(!rpi, false);
return rpi->atlas.is_valid();
}
bool RendererSceneRenderRD::reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) {
- ReflectionAtlas *atlas = reflection_atlas_owner.getornull(p_reflection_atlas);
+ ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(p_reflection_atlas);
ERR_FAIL_COND_V(!atlas, false);
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
ERR_FAIL_COND_V(!rpi, false);
RD::get_singleton()->draw_command_begin_label("Reflection probe render");
@@ -701,7 +695,7 @@ bool RendererSceneRenderRD::reflection_probe_instance_begin_render(RID p_instanc
uint64_t pass_min = 0;
for (int i = 0; i < atlas->reflections.size(); i++) {
- ReflectionProbeInstance *rpi2 = reflection_probe_instance_owner.getornull(atlas->reflections[i].owner);
+ ReflectionProbeInstance *rpi2 = reflection_probe_instance_owner.get_or_null(atlas->reflections[i].owner);
if (rpi2->last_pass < pass_min) {
pass_min = rpi2->last_pass;
rpi->atlas_index = i;
@@ -733,12 +727,12 @@ RID RendererSceneRenderRD::reflection_probe_create_framebuffer(RID p_color, RID
}
bool RendererSceneRenderRD::reflection_probe_instance_postprocess_step(RID p_instance) {
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
ERR_FAIL_COND_V(!rpi, false);
ERR_FAIL_COND_V(!rpi->rendering, false);
ERR_FAIL_COND_V(rpi->atlas.is_null(), false);
- ReflectionAtlas *atlas = reflection_atlas_owner.getornull(rpi->atlas);
+ ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(rpi->atlas);
if (!atlas || rpi->atlas_index == -1) {
//does not belong to an atlas anymore, cancel (was removed from atlas or atlas changed while rendering)
rpi->rendering = false;
@@ -779,30 +773,30 @@ bool RendererSceneRenderRD::reflection_probe_instance_postprocess_step(RID p_ins
}
uint32_t RendererSceneRenderRD::reflection_probe_instance_get_resolution(RID p_instance) {
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
ERR_FAIL_COND_V(!rpi, 0);
- ReflectionAtlas *atlas = reflection_atlas_owner.getornull(rpi->atlas);
+ ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(rpi->atlas);
ERR_FAIL_COND_V(!atlas, 0);
return atlas->size;
}
RID RendererSceneRenderRD::reflection_probe_instance_get_framebuffer(RID p_instance, int p_index) {
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
ERR_FAIL_COND_V(!rpi, RID());
ERR_FAIL_INDEX_V(p_index, 6, RID());
- ReflectionAtlas *atlas = reflection_atlas_owner.getornull(rpi->atlas);
+ ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(rpi->atlas);
ERR_FAIL_COND_V(!atlas, RID());
return atlas->reflections[rpi->atlas_index].fbs[p_index];
}
RID RendererSceneRenderRD::reflection_probe_instance_get_depth_framebuffer(RID p_instance, int p_index) {
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
ERR_FAIL_COND_V(!rpi, RID());
ERR_FAIL_INDEX_V(p_index, 6, RID());
- ReflectionAtlas *atlas = reflection_atlas_owner.getornull(rpi->atlas);
+ ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(rpi->atlas);
ERR_FAIL_COND_V(!atlas, RID());
return atlas->depth_fb;
}
@@ -829,7 +823,7 @@ void RendererSceneRenderRD::_update_shadow_atlas(ShadowAtlas *shadow_atlas) {
}
void RendererSceneRenderRD::shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits) {
- ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_atlas);
+ ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_atlas);
ERR_FAIL_COND(!shadow_atlas);
ERR_FAIL_COND(p_size < 0);
p_size = next_power_of_2(p_size);
@@ -850,8 +844,8 @@ void RendererSceneRenderRD::shadow_atlas_set_size(RID p_atlas, int p_size, bool
}
//erase shadow atlas reference from lights
- for (Map<RID, uint32_t>::Element *E = shadow_atlas->shadow_owners.front(); E; E = E->next()) {
- LightInstance *li = light_instance_owner.getornull(E->key());
+ for (const KeyValue<RID, uint32_t> &E : shadow_atlas->shadow_owners) {
+ LightInstance *li = light_instance_owner.get_or_null(E.key);
ERR_CONTINUE(!li);
li->shadow_atlases.erase(p_atlas);
}
@@ -864,7 +858,7 @@ void RendererSceneRenderRD::shadow_atlas_set_size(RID p_atlas, int p_size, bool
}
void RendererSceneRenderRD::shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) {
- ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_atlas);
+ ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_atlas);
ERR_FAIL_COND(!shadow_atlas);
ERR_FAIL_INDEX(p_quadrant, 4);
ERR_FAIL_INDEX(p_subdivision, 16384);
@@ -886,7 +880,7 @@ void RendererSceneRenderRD::shadow_atlas_set_quadrant_subdivision(RID p_atlas, i
for (int i = 0; i < shadow_atlas->quadrants[p_quadrant].shadows.size(); i++) {
if (shadow_atlas->quadrants[p_quadrant].shadows[i].owner.is_valid()) {
shadow_atlas->shadow_owners.erase(shadow_atlas->quadrants[p_quadrant].shadows[i].owner);
- LightInstance *li = light_instance_owner.getornull(shadow_atlas->quadrants[p_quadrant].shadows[i].owner);
+ LightInstance *li = light_instance_owner.get_or_null(shadow_atlas->quadrants[p_quadrant].shadows[i].owner);
ERR_CONTINUE(!li);
li->shadow_atlases.erase(p_atlas);
}
@@ -947,7 +941,7 @@ bool RendererSceneRenderRD::_shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas,
break;
}
- LightInstance *sli = light_instance_owner.getornull(sarr[j].owner);
+ LightInstance *sli = light_instance_owner.get_or_null(sarr[j].owner);
ERR_CONTINUE(!sli);
if (sli->last_scene_pass != scene_pass) {
@@ -999,7 +993,7 @@ bool RendererSceneRenderRD::_shadow_atlas_find_omni_shadows(ShadowAtlas *shadow_
uint64_t pass = 0;
if (sarr[j].owner.is_valid()) {
- LightInstance *sli = light_instance_owner.getornull(sarr[j].owner);
+ LightInstance *sli = light_instance_owner.get_or_null(sarr[j].owner);
ERR_CONTINUE(!sli);
if (sli->last_scene_pass == scene_pass) {
@@ -1014,7 +1008,7 @@ bool RendererSceneRenderRD::_shadow_atlas_find_omni_shadows(ShadowAtlas *shadow_
}
if (sarr[j + 1].owner.is_valid()) {
- LightInstance *sli = light_instance_owner.getornull(sarr[j + 1].owner);
+ LightInstance *sli = light_instance_owner.get_or_null(sarr[j + 1].owner);
ERR_CONTINUE(!sli);
if (sli->last_scene_pass == scene_pass) {
@@ -1053,10 +1047,10 @@ bool RendererSceneRenderRD::_shadow_atlas_find_omni_shadows(ShadowAtlas *shadow_
}
bool RendererSceneRenderRD::shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) {
- ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_atlas);
+ ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_atlas);
ERR_FAIL_COND_V(!shadow_atlas, false);
- LightInstance *li = light_instance_owner.getornull(p_light_intance);
+ LightInstance *li = light_instance_owner.get_or_null(p_light_intance);
ERR_FAIL_COND_V(!li, false);
if (shadow_atlas->size == 0 || shadow_atlas->smallest_subdiv == 0) {
@@ -1179,7 +1173,7 @@ bool RendererSceneRenderRD::shadow_atlas_update_light(RID p_atlas, RID p_light_i
void RendererSceneRenderRD::_shadow_atlas_invalidate_shadow(RendererSceneRenderRD::ShadowAtlas::Quadrant::Shadow *p_shadow, RID p_atlas, RendererSceneRenderRD::ShadowAtlas *p_shadow_atlas, uint32_t p_quadrant, uint32_t p_shadow_idx) {
if (p_shadow->owner.is_valid()) {
- LightInstance *sli = light_instance_owner.getornull(p_shadow->owner);
+ LightInstance *sli = light_instance_owner.get_or_null(p_shadow->owner);
uint32_t old_key = p_shadow_atlas->shadow_owners[p_shadow->owner];
if (old_key & ShadowAtlas::OMNI_LIGHT_FLAG) {
@@ -1260,7 +1254,7 @@ int RendererSceneRenderRD::get_directional_light_shadow_size(RID p_light_intance
Rect2i r = _get_directional_shadow_rect(directional_shadow.size, directional_shadow.light_count, 0);
- LightInstance *light_instance = light_instance_owner.getornull(p_light_intance);
+ LightInstance *light_instance = light_instance_owner.get_or_null(p_light_intance);
ERR_FAIL_COND_V(!light_instance, 0);
switch (storage->light_directional_get_shadow_mode(light_instance->light)) {
@@ -1296,7 +1290,7 @@ void RendererSceneRenderRD::camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokeh
}
void RendererSceneRenderRD::camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) {
- CameraEffects *camfx = camera_effects_owner.getornull(p_camera_effects);
+ CameraEffects *camfx = camera_effects_owner.get_or_null(p_camera_effects);
ERR_FAIL_COND(!camfx);
camfx->dof_blur_far_enabled = p_far_enable;
@@ -1311,7 +1305,7 @@ void RendererSceneRenderRD::camera_effects_set_dof_blur(RID p_camera_effects, bo
}
void RendererSceneRenderRD::camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) {
- CameraEffects *camfx = camera_effects_owner.getornull(p_camera_effects);
+ CameraEffects *camfx = camera_effects_owner.get_or_null(p_camera_effects);
ERR_FAIL_COND(!camfx);
camfx->override_exposure_enabled = p_enable;
@@ -1321,7 +1315,7 @@ void RendererSceneRenderRD::camera_effects_set_custom_exposure(RID p_camera_effe
RID RendererSceneRenderRD::light_instance_create(RID p_light) {
RID li = light_instance_owner.make_rid(LightInstance());
- LightInstance *light_instance = light_instance_owner.getornull(li);
+ LightInstance *light_instance = light_instance_owner.get_or_null(li);
light_instance->self = li;
light_instance->light = p_light;
@@ -1334,21 +1328,21 @@ RID RendererSceneRenderRD::light_instance_create(RID p_light) {
}
void RendererSceneRenderRD::light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) {
- LightInstance *light_instance = light_instance_owner.getornull(p_light_instance);
+ LightInstance *light_instance = light_instance_owner.get_or_null(p_light_instance);
ERR_FAIL_COND(!light_instance);
light_instance->transform = p_transform;
}
void RendererSceneRenderRD::light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) {
- LightInstance *light_instance = light_instance_owner.getornull(p_light_instance);
+ LightInstance *light_instance = light_instance_owner.get_or_null(p_light_instance);
ERR_FAIL_COND(!light_instance);
light_instance->aabb = p_aabb;
}
void RendererSceneRenderRD::light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale, float p_range_begin, const Vector2 &p_uv_scale) {
- LightInstance *light_instance = light_instance_owner.getornull(p_light_instance);
+ LightInstance *light_instance = light_instance_owner.get_or_null(p_light_instance);
ERR_FAIL_COND(!light_instance);
ERR_FAIL_INDEX(p_pass, 6);
@@ -1364,7 +1358,7 @@ void RendererSceneRenderRD::light_instance_set_shadow_transform(RID p_light_inst
}
void RendererSceneRenderRD::light_instance_mark_visible(RID p_light_instance) {
- LightInstance *light_instance = light_instance_owner.getornull(p_light_instance);
+ LightInstance *light_instance = light_instance_owner.get_or_null(p_light_instance);
ERR_FAIL_COND(!light_instance);
light_instance->last_scene_pass = scene_pass;
@@ -1407,7 +1401,7 @@ RID RendererSceneRenderRD::decal_instance_create(RID p_decal) {
}
void RendererSceneRenderRD::decal_instance_set_transform(RID p_decal, const Transform3D &p_transform) {
- DecalInstance *di = decal_instance_owner.getornull(p_decal);
+ DecalInstance *di = decal_instance_owner.get_or_null(p_decal);
ERR_FAIL_COND(!di);
di->transform = p_transform;
}
@@ -1420,7 +1414,7 @@ RID RendererSceneRenderRD::lightmap_instance_create(RID p_lightmap) {
return lightmap_instance_owner.make_rid(li);
}
void RendererSceneRenderRD::lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) {
- LightmapInstance *li = lightmap_instance_owner.getornull(p_lightmap);
+ LightmapInstance *li = lightmap_instance_owner.get_or_null(p_lightmap);
ERR_FAIL_COND(!li);
li->transform = p_transform;
}
@@ -1452,7 +1446,7 @@ void RendererSceneRenderRD::voxel_gi_update(RID p_probe, bool p_update_light_ins
}
void RendererSceneRenderRD::_debug_sdfgi_probes(RID p_render_buffers, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform) {
- RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+ RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(!rb);
if (!rb->sdfgi) {
@@ -1790,7 +1784,7 @@ void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) {
}
void RendererSceneRenderRD::_process_sss(RID p_render_buffers, const CameraMatrix &p_camera) {
- RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+ RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(!rb);
bool can_use_effects = rb->width >= 8 && rb->height >= 8;
@@ -1808,7 +1802,7 @@ void RendererSceneRenderRD::_process_sss(RID p_render_buffers, const CameraMatri
}
void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_framebuffer, RID p_normal_buffer, RID p_specular_buffer, RID p_metallic, const Color &p_metallic_mask, RID p_environment, const CameraMatrix &p_projection, bool p_use_additive) {
- RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+ RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(!rb);
bool can_use_effects = rb->width >= 8 && rb->height >= 8;
@@ -1819,7 +1813,7 @@ void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_frameb
return;
}
- RendererSceneEnvironmentRD *env = environment_owner.getornull(p_environment);
+ RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_environment);
ERR_FAIL_COND(!env);
ERR_FAIL_COND(!env->ssr_enabled);
@@ -1860,10 +1854,10 @@ void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_frameb
}
void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection) {
- RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+ RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(!rb);
- RendererSceneEnvironmentRD *env = environment_owner.getornull(p_environment);
+ RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_environment);
ERR_FAIL_COND(!env);
RENDER_TIMESTAMP("Process SSAO");
@@ -2005,7 +1999,7 @@ void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environmen
}
void RendererSceneRenderRD::_render_buffers_copy_screen_texture(const RenderDataRD *p_render_data) {
- RenderBuffers *rb = render_buffers_owner.getornull(p_render_data->render_buffers);
+ RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers);
ERR_FAIL_COND(!rb);
RD::get_singleton()->draw_command_begin_label("Copy screen texture");
@@ -2034,7 +2028,7 @@ void RendererSceneRenderRD::_render_buffers_copy_screen_texture(const RenderData
}
void RendererSceneRenderRD::_render_buffers_copy_depth_texture(const RenderDataRD *p_render_data) {
- RenderBuffers *rb = render_buffers_owner.getornull(p_render_data->render_buffers);
+ RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers);
ERR_FAIL_COND(!rb);
RD::get_singleton()->draw_command_begin_label("Copy depth texture");
@@ -2057,12 +2051,12 @@ void RendererSceneRenderRD::_render_buffers_copy_depth_texture(const RenderDataR
}
void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const RenderDataRD *p_render_data) {
- RenderBuffers *rb = render_buffers_owner.getornull(p_render_data->render_buffers);
+ RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers);
ERR_FAIL_COND(!rb);
- RendererSceneEnvironmentRD *env = environment_owner.getornull(p_render_data->environment);
+ RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_render_data->environment);
//glow (if enabled)
- CameraEffects *camfx = camera_effects_owner.getornull(p_render_data->camera_effects);
+ CameraEffects *camfx = camera_effects_owner.get_or_null(p_render_data->camera_effects);
bool can_use_effects = rb->width >= 8 && rb->height >= 8;
bool can_use_storage = _render_buffers_can_be_storage();
@@ -2237,6 +2231,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
}
}
+ tonemap.luminance_multiplier = _render_buffers_get_luminance_multiplier();
tonemap.view_count = p_render_data->view_count;
storage->get_effects()->tonemapper(rb->texture, storage->render_target_get_rd_framebuffer(rb->render_target), tonemap);
@@ -2250,10 +2245,10 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_framebuffer, const RenderDataRD *p_render_data) {
RD::get_singleton()->draw_command_begin_label("Post Process Subpass");
- RenderBuffers *rb = render_buffers_owner.getornull(p_render_data->render_buffers);
+ RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers);
ERR_FAIL_COND(!rb);
- RendererSceneEnvironmentRD *env = environment_owner.getornull(p_render_data->environment);
+ RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_render_data->environment);
bool can_use_effects = rb->width >= 8 && rb->height >= 8;
@@ -2301,6 +2296,7 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr
tonemap.use_debanding = rb->use_debanding;
tonemap.texture_size = Vector2i(rb->width, rb->height);
+ tonemap.luminance_multiplier = _render_buffers_get_luminance_multiplier();
tonemap.view_count = p_render_data->view_count;
storage->get_effects()->tonemapper(draw_list, p_source_texture, RD::get_singleton()->framebuffer_get_format(p_framebuffer), tonemap);
@@ -2309,7 +2305,7 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr
}
void RendererSceneRenderRD::_disable_clear_request(const RenderDataRD *p_render_data) {
- RenderBuffers *rb = render_buffers_owner.getornull(p_render_data->render_buffers);
+ RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers);
ERR_FAIL_COND(!rb);
storage->render_target_disable_clear_request(rb->render_target);
@@ -2318,7 +2314,7 @@ void RendererSceneRenderRD::_disable_clear_request(const RenderDataRD *p_render_
void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer) {
EffectsRD *effects = storage->get_effects();
- RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+ RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(!rb);
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SHADOW_ATLAS) {
@@ -2384,7 +2380,7 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID
}
void RendererSceneRenderRD::environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) {
- RendererSceneEnvironmentRD *env = environment_owner.getornull(p_env);
+ RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND(!env);
env->adjustments_enabled = p_enable;
@@ -2396,7 +2392,7 @@ void RendererSceneRenderRD::environment_set_adjustment(RID p_env, bool p_enable,
}
RID RendererSceneRenderRD::render_buffers_get_back_buffer_texture(RID p_render_buffers) {
- RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+ RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND_V(!rb, RID());
if (!rb->blur[0].texture.is_valid()) {
return RID(); //not valid at the moment
@@ -2405,7 +2401,7 @@ RID RendererSceneRenderRD::render_buffers_get_back_buffer_texture(RID p_render_b
}
RID RendererSceneRenderRD::render_buffers_get_back_depth_texture(RID p_render_buffers) {
- RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+ RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND_V(!rb, RID());
if (!rb->depth_back_texture.is_valid()) {
return RID(); //not valid at the moment
@@ -2413,15 +2409,22 @@ RID RendererSceneRenderRD::render_buffers_get_back_depth_texture(RID p_render_bu
return rb->depth_back_texture;
}
+RID RendererSceneRenderRD::render_buffers_get_depth_texture(RID p_render_buffers) {
+ RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
+ ERR_FAIL_COND_V(!rb, RID());
+
+ return rb->depth_texture;
+}
+
RID RendererSceneRenderRD::render_buffers_get_ao_texture(RID p_render_buffers) {
- RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+ RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND_V(!rb, RID());
return rb->ssao.ao_final;
}
RID RendererSceneRenderRD::render_buffers_get_voxel_gi_buffer(RID p_render_buffers) {
- RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+ RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND_V(!rb, RID());
if (rb->gi.voxel_gi_buffer.is_null()) {
rb->gi.voxel_gi_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(RendererSceneGIRD::VoxelGIData) * RendererSceneGIRD::MAX_VOXEL_GI_INSTANCES);
@@ -2434,31 +2437,31 @@ RID RendererSceneRenderRD::render_buffers_get_default_voxel_gi_buffer() {
}
RID RendererSceneRenderRD::render_buffers_get_gi_ambient_texture(RID p_render_buffers) {
- RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+ RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND_V(!rb, RID());
return rb->ambient_buffer;
}
RID RendererSceneRenderRD::render_buffers_get_gi_reflection_texture(RID p_render_buffers) {
- RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+ RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND_V(!rb, RID());
return rb->reflection_buffer;
}
uint32_t RendererSceneRenderRD::render_buffers_get_sdfgi_cascade_count(RID p_render_buffers) const {
- const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+ const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND_V(!rb, 0);
ERR_FAIL_COND_V(!rb->sdfgi, 0);
return rb->sdfgi->cascades.size();
}
bool RendererSceneRenderRD::render_buffers_is_sdfgi_enabled(RID p_render_buffers) const {
- const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+ const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND_V(!rb, false);
return rb->sdfgi != nullptr;
}
RID RendererSceneRenderRD::render_buffers_get_sdfgi_irradiance_probes(RID p_render_buffers) const {
- const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+ const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND_V(!rb, RID());
ERR_FAIL_COND_V(!rb->sdfgi, RID());
@@ -2466,7 +2469,7 @@ RID RendererSceneRenderRD::render_buffers_get_sdfgi_irradiance_probes(RID p_rend
}
Vector3 RendererSceneRenderRD::render_buffers_get_sdfgi_cascade_offset(RID p_render_buffers, uint32_t p_cascade) const {
- const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+ const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND_V(!rb, Vector3());
ERR_FAIL_COND_V(!rb->sdfgi, Vector3());
ERR_FAIL_UNSIGNED_INDEX_V(p_cascade, rb->sdfgi->cascades.size(), Vector3());
@@ -2475,7 +2478,7 @@ Vector3 RendererSceneRenderRD::render_buffers_get_sdfgi_cascade_offset(RID p_ren
}
Vector3i RendererSceneRenderRD::render_buffers_get_sdfgi_cascade_probe_offset(RID p_render_buffers, uint32_t p_cascade) const {
- const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+ const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND_V(!rb, Vector3i());
ERR_FAIL_COND_V(!rb->sdfgi, Vector3i());
ERR_FAIL_UNSIGNED_INDEX_V(p_cascade, rb->sdfgi->cascades.size(), Vector3i());
@@ -2485,14 +2488,14 @@ Vector3i RendererSceneRenderRD::render_buffers_get_sdfgi_cascade_probe_offset(RI
}
float RendererSceneRenderRD::render_buffers_get_sdfgi_normal_bias(RID p_render_buffers) const {
- const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+ const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND_V(!rb, 0);
ERR_FAIL_COND_V(!rb->sdfgi, 0);
return rb->sdfgi->normal_bias;
}
float RendererSceneRenderRD::render_buffers_get_sdfgi_cascade_probe_size(RID p_render_buffers, uint32_t p_cascade) const {
- const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+ const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND_V(!rb, 0);
ERR_FAIL_COND_V(!rb->sdfgi, 0);
ERR_FAIL_UNSIGNED_INDEX_V(p_cascade, rb->sdfgi->cascades.size(), 0);
@@ -2500,7 +2503,7 @@ float RendererSceneRenderRD::render_buffers_get_sdfgi_cascade_probe_size(RID p_r
return float(rb->sdfgi->cascade_size) * rb->sdfgi->cascades[p_cascade].cell_size / float(rb->sdfgi->probe_axis_count - 1);
}
uint32_t RendererSceneRenderRD::render_buffers_get_sdfgi_cascade_probe_count(RID p_render_buffers) const {
- const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+ const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND_V(!rb, 0);
ERR_FAIL_COND_V(!rb->sdfgi, 0);
@@ -2508,7 +2511,7 @@ uint32_t RendererSceneRenderRD::render_buffers_get_sdfgi_cascade_probe_count(RID
}
uint32_t RendererSceneRenderRD::render_buffers_get_sdfgi_cascade_size(RID p_render_buffers) const {
- const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+ const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND_V(!rb, 0);
ERR_FAIL_COND_V(!rb->sdfgi, 0);
@@ -2516,7 +2519,7 @@ uint32_t RendererSceneRenderRD::render_buffers_get_sdfgi_cascade_size(RID p_rend
}
bool RendererSceneRenderRD::render_buffers_is_sdfgi_using_occlusion(RID p_render_buffers) const {
- const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+ const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND_V(!rb, false);
ERR_FAIL_COND_V(!rb->sdfgi, false);
@@ -2524,14 +2527,14 @@ bool RendererSceneRenderRD::render_buffers_is_sdfgi_using_occlusion(RID p_render
}
float RendererSceneRenderRD::render_buffers_get_sdfgi_energy(RID p_render_buffers) const {
- const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+ const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND_V(!rb, 0.0);
ERR_FAIL_COND_V(!rb->sdfgi, 0.0);
return rb->sdfgi->energy;
}
RID RendererSceneRenderRD::render_buffers_get_sdfgi_occlusion_texture(RID p_render_buffers) const {
- const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+ const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND_V(!rb, RID());
ERR_FAIL_COND_V(!rb->sdfgi, RID());
@@ -2539,20 +2542,20 @@ RID RendererSceneRenderRD::render_buffers_get_sdfgi_occlusion_texture(RID p_rend
}
bool RendererSceneRenderRD::render_buffers_has_volumetric_fog(RID p_render_buffers) const {
- const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+ const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND_V(!rb, false);
return rb->volumetric_fog != nullptr;
}
RID RendererSceneRenderRD::render_buffers_get_volumetric_fog_texture(RID p_render_buffers) {
- const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+ const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND_V(!rb || !rb->volumetric_fog, RID());
return rb->volumetric_fog->fog_map;
}
RID RendererSceneRenderRD::render_buffers_get_volumetric_fog_sky_uniform_set(RID p_render_buffers) {
- const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+ const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND_V(!rb, RID());
if (!rb->volumetric_fog) {
@@ -2563,16 +2566,20 @@ RID RendererSceneRenderRD::render_buffers_get_volumetric_fog_sky_uniform_set(RID
}
float RendererSceneRenderRD::render_buffers_get_volumetric_fog_end(RID p_render_buffers) {
- const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+ const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND_V(!rb || !rb->volumetric_fog, 0);
return rb->volumetric_fog->length;
}
float RendererSceneRenderRD::render_buffers_get_volumetric_fog_detail_spread(RID p_render_buffers) {
- const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+ const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND_V(!rb || !rb->volumetric_fog, 0);
return rb->volumetric_fog->spread;
}
+float RendererSceneRenderRD::_render_buffers_get_luminance_multiplier() {
+ return 1.0;
+}
+
RD::DataFormat RendererSceneRenderRD::_render_buffers_get_color_format() {
return RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
}
@@ -2584,7 +2591,9 @@ bool RendererSceneRenderRD::_render_buffers_can_be_storage() {
void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) {
ERR_FAIL_COND_MSG(p_view_count == 0, "Must have at least 1 view");
- RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+ RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
+
+ // Should we add an overrule per viewport?
rb->width = p_width;
rb->height = p_height;
rb->render_target = p_render_target;
@@ -2631,8 +2640,8 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
tf.format = RD::DATA_FORMAT_R32_SFLOAT;
}
- tf.width = p_width;
- tf.height = p_height;
+ tf.width = rb->width;
+ tf.height = rb->height;
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT;
tf.array_layers = rb->view_count; // create a layer for every view
@@ -2654,10 +2663,10 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
}
RID target_texture = storage->render_target_get_rd_texture(rb->render_target);
- rb->data->configure(rb->texture, rb->depth_texture, target_texture, p_width, p_height, p_msaa, p_view_count);
+ rb->data->configure(rb->texture, rb->depth_texture, target_texture, rb->width, rb->height, p_msaa, p_view_count);
if (is_clustered_enabled()) {
- rb->cluster_builder->setup(Size2i(p_width, p_height), max_cluster_elements, rb->depth_texture, storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED), rb->texture);
+ rb->cluster_builder->setup(Size2i(rb->width, rb->height), max_cluster_elements, rb->depth_texture, storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED), rb->texture);
}
}
@@ -2786,7 +2795,7 @@ bool RendererSceneRenderRD::is_using_radiance_cubemap_array() const {
}
RendererSceneRenderRD::RenderBufferData *RendererSceneRenderRD::render_buffers_get_data(RID p_render_buffers) {
- RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+ RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND_V(!rb, nullptr);
return rb->data;
}
@@ -2799,7 +2808,7 @@ void RendererSceneRenderRD::_setup_reflections(const PagedArray<RID> &p_reflecti
break;
}
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_reflections[i]);
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_reflections[i]);
if (!rpi) {
continue;
}
@@ -2877,7 +2886,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
r_positional_light_count = 0;
sky.sky_scene_state.ubo.directional_light_count = 0;
- Plane camera_plane(p_camera_transform.origin, -p_camera_transform.basis.get_axis(Vector3::AXIS_Z).normalized());
+ Plane camera_plane(-p_camera_transform.basis.get_axis(Vector3::AXIS_Z).normalized(), p_camera_transform.origin);
cluster.omni_light_count = 0;
cluster.spot_light_count = 0;
@@ -2885,7 +2894,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
r_directional_light_soft_shadows = false;
for (int i = 0; i < (int)p_lights.size(); i++) {
- LightInstance *li = light_instance_owner.getornull(p_lights[i]);
+ LightInstance *li = light_instance_owner.get_or_null(p_lights[i]);
if (!li) {
continue;
}
@@ -3114,7 +3123,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
ShadowAtlas *shadow_atlas = nullptr;
if (p_shadow_atlas.is_valid() && p_using_shadows) {
- shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas);
+ shadow_atlas = shadow_atlas_owner.get_or_null(p_shadow_atlas);
}
bool using_forward_ids = _uses_forward_ids();
@@ -3297,7 +3306,7 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
break;
}
- DecalInstance *di = decal_instance_owner.getornull(p_decals[i]);
+ DecalInstance *di = decal_instance_owner.get_or_null(p_decals[i]);
if (!di) {
continue;
}
@@ -3357,7 +3366,7 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
Vector3 decal_extents = storage->decal_get_extents(decal);
Transform3D scale_xform;
- scale_xform.basis.scale(Vector3(decal_extents.x, decal_extents.y, decal_extents.z));
+ scale_xform.basis.scale(decal_extents);
Transform3D to_decal_xform = (p_camera_inverse_xform * di->transform * scale_xform * uv_xform).affine_inverse();
RendererStorageRD::store_transform(to_decal_xform, dd.xform);
@@ -3480,9 +3489,9 @@ void RendererSceneRenderRD::_volumetric_fog_erase(RenderBuffers *rb) {
void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform3D &p_cam_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count) {
ERR_FAIL_COND(!is_clustered_enabled()); // can't use volumetric fog without clustered
- RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+ RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(!rb);
- RendererSceneEnvironmentRD *env = environment_owner.getornull(p_environment);
+ RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_environment);
float ratio = float(rb->width) / float((rb->width + rb->height) / 2);
uint32_t target_width = uint32_t(float(volumetric_fog_size) * ratio);
@@ -3551,7 +3560,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 1;
- ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas);
+ ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_shadow_atlas);
if (shadow_atlas == nullptr || shadow_atlas->depth.is_null()) {
u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK));
} else {
@@ -3873,7 +3882,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
bool RendererSceneRenderRD::_needs_post_prepass_render(RenderDataRD *p_render_data, bool p_use_gi) {
if (p_render_data->render_buffers.is_valid()) {
- RenderBuffers *rb = render_buffers_owner.getornull(p_render_data->render_buffers);
+ RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers);
if (rb->sdfgi != nullptr) {
return true;
}
@@ -3884,14 +3893,14 @@ bool RendererSceneRenderRD::_needs_post_prepass_render(RenderDataRD *p_render_da
void RendererSceneRenderRD::_post_prepass_render(RenderDataRD *p_render_data, bool p_use_gi) {
if (p_render_data->render_buffers.is_valid()) {
if (p_use_gi) {
- RenderBuffers *rb = render_buffers_owner.getornull(p_render_data->render_buffers);
+ RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers);
ERR_FAIL_COND(rb == nullptr);
if (rb->sdfgi == nullptr) {
return;
}
- RendererSceneEnvironmentRD *env = environment_owner.getornull(p_render_data->environment);
- rb->sdfgi->update_probes(env, sky.sky_owner.getornull(env->sky));
+ RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_render_data->environment);
+ rb->sdfgi->update_probes(env, sky.sky_owner.get_or_null(env->sky));
}
}
}
@@ -3908,7 +3917,7 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool
// Render shadows while GI is rendering, due to how barriers are handled, this should happen at the same time
if (p_render_data->render_buffers.is_valid() && p_use_gi) {
- RenderBuffers *rb = render_buffers_owner.getornull(p_render_data->render_buffers);
+ RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers);
ERR_FAIL_COND(rb == nullptr);
if (rb->sdfgi != nullptr) {
rb->sdfgi->store_probes();
@@ -3919,11 +3928,11 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool
render_state.shadows.clear();
render_state.directional_shadows.clear();
- Plane camera_plane(p_render_data->cam_transform.origin, -p_render_data->cam_transform.basis.get_axis(Vector3::AXIS_Z));
+ Plane camera_plane(-p_render_data->cam_transform.basis.get_axis(Vector3::AXIS_Z), p_render_data->cam_transform.origin);
float lod_distance_multiplier = p_render_data->cam_projection.get_lod_multiplier();
{
for (int i = 0; i < render_state.render_shadow_count; i++) {
- LightInstance *li = light_instance_owner.getornull(render_state.render_shadows[i].light);
+ LightInstance *li = light_instance_owner.get_or_null(render_state.render_shadows[i].light);
if (storage->light_get_type(li->light) == RS::LIGHT_DIRECTIONAL) {
render_state.directional_shadows.push_back(i);
@@ -4043,7 +4052,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData
// getting this here now so we can direct call a bunch of things more easily
RenderBuffers *rb = nullptr;
if (p_render_buffers.is_valid()) {
- rb = render_buffers_owner.getornull(p_render_buffers);
+ rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(!rb);
}
@@ -4081,7 +4090,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData
// this should be the same for all cameras..
render_data.lod_distance_multiplier = p_camera_data->main_projection.get_lod_multiplier();
- render_data.lod_camera_plane = Plane(p_camera_data->main_transform.get_origin(), -p_camera_data->main_transform.basis.get_axis(Vector3::AXIS_Z));
+ render_data.lod_camera_plane = Plane(-p_camera_data->main_transform.basis.get_axis(Vector3::AXIS_Z), p_camera_data->main_transform.get_origin());
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_DISABLE_LOD) {
render_data.screen_lod_threshold = 0.0;
@@ -4125,7 +4134,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData
//assign render indices to voxel_gi_instances
if (is_dynamic_gi_supported()) {
for (uint32_t i = 0; i < (uint32_t)p_voxel_gi_instances.size(); i++) {
- RendererSceneGIRD::VoxelGIInstance *voxel_gi_inst = gi.voxel_gi_instance_owner.getornull(p_voxel_gi_instances[i]);
+ RendererSceneGIRD::VoxelGIInstance *voxel_gi_inst = gi.voxel_gi_instance_owner.get_or_null(p_voxel_gi_instances[i]);
if (voxel_gi_inst) {
voxel_gi_inst->render_index = i;
}
@@ -4136,8 +4145,8 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData
// render_data.render_buffers == p_render_buffers so we can use our already retrieved rb
current_cluster_builder = rb->cluster_builder;
} else if (reflection_probe_instance_owner.owns(render_data.reflection_probe)) {
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(render_data.reflection_probe);
- ReflectionAtlas *ra = reflection_atlas_owner.getornull(rpi->atlas);
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(render_data.reflection_probe);
+ ReflectionAtlas *ra = reflection_atlas_owner.get_or_null(rpi->atlas);
if (!ra) {
ERR_PRINT("reflection probe has no reflection atlas! Bug?");
current_cluster_builder = nullptr;
@@ -4215,7 +4224,7 @@ void RendererSceneRenderRD::_debug_draw_cluster(RID p_render_buffers) {
}
void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<GeometryInstance *> &p_instances, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold, bool p_open_pass, bool p_close_pass, bool p_clear_region, RendererScene::RenderInfo *p_render_info) {
- LightInstance *light_instance = light_instance_owner.getornull(p_light);
+ LightInstance *light_instance = light_instance_owner.get_or_null(p_light);
ERR_FAIL_COND(!light_instance);
Rect2i atlas_rect;
@@ -4250,10 +4259,7 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas,
light_projection = light_instance->shadow_transform[p_pass].camera;
light_transform = light_instance->shadow_transform[p_pass].transform;
- atlas_rect.position.x = light_instance->directional_rect.position.x;
- atlas_rect.position.y = light_instance->directional_rect.position.y;
- atlas_rect.size.width = light_instance->directional_rect.size.x;
- atlas_rect.size.height = light_instance->directional_rect.size.y;
+ atlas_rect = light_instance->directional_rect;
if (storage->light_directional_get_shadow_mode(light_instance->light) == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) {
atlas_rect.size.width /= 2;
@@ -4264,8 +4270,7 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas,
} else if (p_pass == 2) {
atlas_rect.position.y += atlas_rect.size.height;
} else if (p_pass == 3) {
- atlas_rect.position.x += atlas_rect.size.width;
- atlas_rect.position.y += atlas_rect.size.height;
+ atlas_rect.position += atlas_rect.size;
}
} else if (storage->light_directional_get_shadow_mode(light_instance->light) == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) {
atlas_rect.size.height /= 2;
@@ -4290,7 +4295,7 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas,
} else {
//set from shadow atlas
- ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas);
+ ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_shadow_atlas);
ERR_FAIL_COND(!shadow_atlas);
ERR_FAIL_COND(!shadow_atlas->shadow_owners.has(p_light));
@@ -4374,10 +4379,8 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas,
_render_shadow_end();
//reblit
Rect2 atlas_rect_norm = atlas_rect;
- atlas_rect_norm.position.x /= float(atlas_size);
- atlas_rect_norm.position.y /= float(atlas_size);
- atlas_rect_norm.size.x /= float(atlas_size);
- atlas_rect_norm.size.y /= float(atlas_size);
+ atlas_rect_norm.position /= float(atlas_size);
+ atlas_rect_norm.size /= float(atlas_size);
storage->get_effects()->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect_norm, atlas_rect.size, light_projection.get_z_near(), light_projection.get_z_far(), false);
atlas_rect_norm.position += Vector2(dual_paraboloid_offset) * atlas_rect_norm.size;
storage->get_effects()->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect_norm, atlas_rect.size, light_projection.get_z_near(), light_projection.get_z_far(), true);
@@ -4415,7 +4418,7 @@ void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider,
bool RendererSceneRenderRD::free(RID p_rid) {
if (render_buffers_owner.owns(p_rid)) {
- RenderBuffers *rb = render_buffers_owner.getornull(p_rid);
+ RenderBuffers *rb = render_buffers_owner.get_or_null(p_rid);
_free_render_buffer_data(rb);
memdelete(rb->data);
if (rb->sdfgi) {
@@ -4438,24 +4441,24 @@ bool RendererSceneRenderRD::free(RID p_rid) {
camera_effects_owner.free(p_rid);
} else if (reflection_atlas_owner.owns(p_rid)) {
reflection_atlas_set_size(p_rid, 0, 0);
- ReflectionAtlas *ra = reflection_atlas_owner.getornull(p_rid);
+ ReflectionAtlas *ra = reflection_atlas_owner.get_or_null(p_rid);
if (ra->cluster_builder) {
memdelete(ra->cluster_builder);
}
reflection_atlas_owner.free(p_rid);
} else if (reflection_probe_instance_owner.owns(p_rid)) {
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_rid);
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_rid);
_free_forward_id(FORWARD_ID_TYPE_REFLECTION_PROBE, rpi->forward_id);
reflection_probe_release_atlas_index(p_rid);
reflection_probe_instance_owner.free(p_rid);
} else if (decal_instance_owner.owns(p_rid)) {
- DecalInstance *di = decal_instance_owner.getornull(p_rid);
+ DecalInstance *di = decal_instance_owner.get_or_null(p_rid);
_free_forward_id(FORWARD_ID_TYPE_DECAL, di->forward_id);
decal_instance_owner.free(p_rid);
} else if (lightmap_instance_owner.owns(p_rid)) {
lightmap_instance_owner.free(p_rid);
} else if (gi.voxel_gi_instance_owner.owns(p_rid)) {
- RendererSceneGIRD::VoxelGIInstance *voxel_gi = gi.voxel_gi_instance_owner.getornull(p_rid);
+ RendererSceneGIRD::VoxelGIInstance *voxel_gi = gi.voxel_gi_instance_owner.get_or_null(p_rid);
if (voxel_gi->texture.is_valid()) {
RD::get_singleton()->free(voxel_gi->texture);
RD::get_singleton()->free(voxel_gi->write_buffer);
@@ -4471,11 +4474,11 @@ bool RendererSceneRenderRD::free(RID p_rid) {
sky.update_dirty_skys();
sky.free_sky(p_rid);
} else if (light_instance_owner.owns(p_rid)) {
- LightInstance *light_instance = light_instance_owner.getornull(p_rid);
+ LightInstance *light_instance = light_instance_owner.get_or_null(p_rid);
//remove from shadow atlases..
for (Set<RID>::Element *E = light_instance->shadow_atlases.front(); E; E = E->next()) {
- ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(E->get());
+ ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(E->get());
ERR_CONTINUE(!shadow_atlas->shadow_owners.has(p_rid));
uint32_t key = shadow_atlas->shadow_owners[p_rid];
uint32_t q = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3;
@@ -4792,8 +4795,8 @@ void RendererSceneRenderRD::init() {
}
RendererSceneRenderRD::~RendererSceneRenderRD() {
- for (Map<int, ShadowCubemap>::Element *E = shadow_cubemaps.front(); E; E = E->next()) {
- RD::get_singleton()->free(E->get().cubemap);
+ for (const KeyValue<int, ShadowCubemap> &E : shadow_cubemaps) {
+ RD::get_singleton()->free(E.value.cubemap);
}
if (sky.sky_scene_state.uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(sky.sky_scene_state.uniform_set)) {
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
index 37533baecf..d74848f0af 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
@@ -149,7 +149,7 @@ protected:
RendererSceneEnvironmentRD *get_environment(RID p_environment) {
if (p_environment.is_valid()) {
- return environment_owner.getornull(p_environment);
+ return environment_owner.get_or_null(p_environment);
} else {
return nullptr;
}
@@ -814,19 +814,19 @@ public:
virtual void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) override;
virtual bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) override;
_FORCE_INLINE_ bool shadow_atlas_owns_light_instance(RID p_atlas, RID p_light_intance) {
- ShadowAtlas *atlas = shadow_atlas_owner.getornull(p_atlas);
+ ShadowAtlas *atlas = shadow_atlas_owner.get_or_null(p_atlas);
ERR_FAIL_COND_V(!atlas, false);
return atlas->shadow_owners.has(p_light_intance);
}
_FORCE_INLINE_ RID shadow_atlas_get_texture(RID p_atlas) {
- ShadowAtlas *atlas = shadow_atlas_owner.getornull(p_atlas);
+ ShadowAtlas *atlas = shadow_atlas_owner.get_or_null(p_atlas);
ERR_FAIL_COND_V(!atlas, RID());
return atlas->depth;
}
_FORCE_INLINE_ Size2i shadow_atlas_get_size(RID p_atlas) {
- ShadowAtlas *atlas = shadow_atlas_owner.getornull(p_atlas);
+ ShadowAtlas *atlas = shadow_atlas_owner.get_or_null(p_atlas);
ERR_FAIL_COND_V(!atlas, Size2i());
return Size2(atlas->size, atlas->size);
}
@@ -873,7 +873,7 @@ public:
virtual void environment_set_bg_color(RID p_env, const Color &p_color) override;
virtual void environment_set_bg_energy(RID p_env, float p_energy) override;
virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer) override;
- virtual void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG, const Color &p_ao_color = Color()) override;
+ virtual void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG) override;
virtual RS::EnvironmentBG environment_get_background(RID p_env) const override;
RID environment_get_sky(RID p_env) const;
@@ -887,7 +887,6 @@ public:
float environment_get_ambient_light_energy(RID p_env) const;
float environment_get_ambient_sky_contribution(RID p_env) const;
RS::EnvironmentReflectionSource environment_get_reflection_source(RID p_env) const;
- Color environment_get_ao_color(RID p_env) const;
virtual bool is_environment(RID p_env) const override;
@@ -942,7 +941,7 @@ public:
virtual void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) override;
bool camera_effects_uses_dof(RID p_camera_effects) {
- CameraEffects *camfx = camera_effects_owner.getornull(p_camera_effects);
+ CameraEffects *camfx = camera_effects_owner.get_or_null(p_camera_effects);
return camfx && (camfx->dof_blur_near_enabled || camfx->dof_blur_far_enabled) && camfx->dof_blur_amount > 0.0;
}
@@ -954,18 +953,18 @@ public:
virtual void light_instance_mark_visible(RID p_light_instance) override;
_FORCE_INLINE_ RID light_instance_get_base_light(RID p_light_instance) {
- LightInstance *li = light_instance_owner.getornull(p_light_instance);
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
return li->light;
}
_FORCE_INLINE_ Transform3D light_instance_get_base_transform(RID p_light_instance) {
- LightInstance *li = light_instance_owner.getornull(p_light_instance);
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
return li->transform;
}
_FORCE_INLINE_ Rect2 light_instance_get_shadow_atlas_rect(RID p_light_instance, RID p_shadow_atlas, Vector2i &r_omni_offset) {
- ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas);
- LightInstance *li = light_instance_owner.getornull(p_light_instance);
+ ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_shadow_atlas);
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
uint32_t key = shadow_atlas->shadow_owners[li->self];
uint32_t quadrant = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3;
@@ -1000,16 +999,16 @@ public:
}
_FORCE_INLINE_ CameraMatrix light_instance_get_shadow_camera(RID p_light_instance, int p_index) {
- LightInstance *li = light_instance_owner.getornull(p_light_instance);
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
return li->shadow_transform[p_index].camera;
}
_FORCE_INLINE_ float light_instance_get_shadow_texel_size(RID p_light_instance, RID p_shadow_atlas) {
#ifdef DEBUG_ENABLED
- LightInstance *li = light_instance_owner.getornull(p_light_instance);
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
ERR_FAIL_COND_V(!li->shadow_atlases.has(p_shadow_atlas), 0);
#endif
- ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas);
+ ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_shadow_atlas);
ERR_FAIL_COND_V(!shadow_atlas, 0);
#ifdef DEBUG_ENABLED
ERR_FAIL_COND_V(!shadow_atlas->shadow_owners.has(p_light_instance), 0);
@@ -1027,59 +1026,59 @@ public:
_FORCE_INLINE_ Transform3D
light_instance_get_shadow_transform(RID p_light_instance, int p_index) {
- LightInstance *li = light_instance_owner.getornull(p_light_instance);
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
return li->shadow_transform[p_index].transform;
}
_FORCE_INLINE_ float light_instance_get_shadow_bias_scale(RID p_light_instance, int p_index) {
- LightInstance *li = light_instance_owner.getornull(p_light_instance);
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
return li->shadow_transform[p_index].bias_scale;
}
_FORCE_INLINE_ float light_instance_get_shadow_range(RID p_light_instance, int p_index) {
- LightInstance *li = light_instance_owner.getornull(p_light_instance);
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
return li->shadow_transform[p_index].farplane;
}
_FORCE_INLINE_ float light_instance_get_shadow_range_begin(RID p_light_instance, int p_index) {
- LightInstance *li = light_instance_owner.getornull(p_light_instance);
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
return li->shadow_transform[p_index].range_begin;
}
_FORCE_INLINE_ Vector2 light_instance_get_shadow_uv_scale(RID p_light_instance, int p_index) {
- LightInstance *li = light_instance_owner.getornull(p_light_instance);
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
return li->shadow_transform[p_index].uv_scale;
}
_FORCE_INLINE_ Rect2 light_instance_get_directional_shadow_atlas_rect(RID p_light_instance, int p_index) {
- LightInstance *li = light_instance_owner.getornull(p_light_instance);
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
return li->shadow_transform[p_index].atlas_rect;
}
_FORCE_INLINE_ float light_instance_get_directional_shadow_split(RID p_light_instance, int p_index) {
- LightInstance *li = light_instance_owner.getornull(p_light_instance);
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
return li->shadow_transform[p_index].split;
}
_FORCE_INLINE_ float light_instance_get_directional_shadow_texel_size(RID p_light_instance, int p_index) {
- LightInstance *li = light_instance_owner.getornull(p_light_instance);
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
return li->shadow_transform[p_index].shadow_texel_size;
}
_FORCE_INLINE_ void light_instance_set_render_pass(RID p_light_instance, uint64_t p_pass) {
- LightInstance *li = light_instance_owner.getornull(p_light_instance);
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
li->last_pass = p_pass;
}
_FORCE_INLINE_ uint64_t light_instance_get_render_pass(RID p_light_instance) {
- LightInstance *li = light_instance_owner.getornull(p_light_instance);
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
return li->last_pass;
}
_FORCE_INLINE_ ForwardID light_instance_get_forward_id(RID p_light_instance) {
- LightInstance *li = light_instance_owner.getornull(p_light_instance);
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
return li->forward_id;
}
_FORCE_INLINE_ RS::LightType light_instance_get_type(RID p_light_instance) {
- LightInstance *li = light_instance_owner.getornull(p_light_instance);
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
return li->light_type;
}
@@ -1088,7 +1087,7 @@ public:
virtual int reflection_atlas_get_size(RID p_ref_atlas) const override;
_FORCE_INLINE_ RID reflection_atlas_get_texture(RID p_ref_atlas) {
- ReflectionAtlas *atlas = reflection_atlas_owner.getornull(p_ref_atlas);
+ ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(p_ref_atlas);
ERR_FAIL_COND_V(!atlas, RID());
return atlas->reflection;
}
@@ -1107,41 +1106,41 @@ public:
RID reflection_probe_instance_get_depth_framebuffer(RID p_instance, int p_index);
_FORCE_INLINE_ RID reflection_probe_instance_get_probe(RID p_instance) {
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
ERR_FAIL_COND_V(!rpi, RID());
return rpi->probe;
}
_FORCE_INLINE_ ForwardID reflection_probe_instance_get_forward_id(RID p_instance) {
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
ERR_FAIL_COND_V(!rpi, 0);
return rpi->forward_id;
}
_FORCE_INLINE_ void reflection_probe_instance_set_render_pass(RID p_instance, uint32_t p_render_pass) {
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
ERR_FAIL_COND(!rpi);
rpi->last_pass = p_render_pass;
}
_FORCE_INLINE_ uint32_t reflection_probe_instance_get_render_pass(RID p_instance) {
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
ERR_FAIL_COND_V(!rpi, 0);
return rpi->last_pass;
}
_FORCE_INLINE_ Transform3D reflection_probe_instance_get_transform(RID p_instance) {
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
ERR_FAIL_COND_V(!rpi, Transform3D());
return rpi->transform;
}
_FORCE_INLINE_ int reflection_probe_instance_get_atlas_index(RID p_instance) {
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
ERR_FAIL_COND_V(!rpi, -1);
return rpi->atlas_index;
@@ -1151,32 +1150,32 @@ public:
virtual void decal_instance_set_transform(RID p_decal, const Transform3D &p_transform) override;
_FORCE_INLINE_ RID decal_instance_get_base(RID p_decal) const {
- DecalInstance *decal = decal_instance_owner.getornull(p_decal);
+ DecalInstance *decal = decal_instance_owner.get_or_null(p_decal);
return decal->decal;
}
_FORCE_INLINE_ ForwardID decal_instance_get_forward_id(RID p_decal) const {
- DecalInstance *decal = decal_instance_owner.getornull(p_decal);
+ DecalInstance *decal = decal_instance_owner.get_or_null(p_decal);
return decal->forward_id;
}
_FORCE_INLINE_ Transform3D decal_instance_get_transform(RID p_decal) const {
- DecalInstance *decal = decal_instance_owner.getornull(p_decal);
+ DecalInstance *decal = decal_instance_owner.get_or_null(p_decal);
return decal->transform;
}
virtual RID lightmap_instance_create(RID p_lightmap) override;
virtual void lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) override;
_FORCE_INLINE_ bool lightmap_instance_is_valid(RID p_lightmap_instance) {
- return lightmap_instance_owner.getornull(p_lightmap_instance) != nullptr;
+ return lightmap_instance_owner.get_or_null(p_lightmap_instance) != nullptr;
}
_FORCE_INLINE_ RID lightmap_instance_get_lightmap(RID p_lightmap_instance) {
- LightmapInstance *li = lightmap_instance_owner.getornull(p_lightmap_instance);
+ LightmapInstance *li = lightmap_instance_owner.get_or_null(p_lightmap_instance);
return li->lightmap;
}
_FORCE_INLINE_ Transform3D lightmap_instance_get_transform(RID p_lightmap_instance) {
- LightmapInstance *li = lightmap_instance_owner.getornull(p_lightmap_instance);
+ LightmapInstance *li = lightmap_instance_owner.get_or_null(p_lightmap_instance);
return li->transform;
}
@@ -1190,12 +1189,14 @@ public:
/* render buffers */
+ virtual float _render_buffers_get_luminance_multiplier();
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_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, 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);
RID render_buffers_get_ao_texture(RID p_render_buffers);
RID render_buffers_get_back_buffer_texture(RID p_render_buffers);
RID render_buffers_get_back_depth_texture(RID p_render_buffers);
diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
index 9e85608f1e..5814c164cc 100644
--- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
@@ -148,36 +148,36 @@ void RendererSceneSkyRD::SkyShaderData::set_default_texture_param(const StringNa
void RendererSceneSkyRD::SkyShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
Map<int, StringName> order;
- for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) {
- if (E->get().scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E->get().scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
+ for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
+ if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
continue;
}
- if (E->get().texture_order >= 0) {
- order[E->get().texture_order + 100000] = E->key();
+ if (E.value.texture_order >= 0) {
+ order[E.value.texture_order + 100000] = E.key;
} else {
- order[E->get().order] = E->key();
+ order[E.value.order] = E.key;
}
}
- for (Map<int, StringName>::Element *E = order.front(); E; E = E->next()) {
- PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E->get()]);
- pi.name = E->get();
+ for (const KeyValue<int, StringName> &E : order) {
+ PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]);
+ pi.name = E.value;
p_param_list->push_back(pi);
}
}
void RendererSceneSkyRD::SkyShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const {
- for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) {
- if (E->get().scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
+ for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
+ if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
continue;
}
RendererStorage::InstanceShaderParam p;
- p.info = ShaderLanguage::uniform_to_property_info(E->get());
- p.info.name = E->key(); //supply name
- p.index = E->get().instance_index;
- p.default_value = ShaderLanguage::constant_value_to_variant(E->get().default_value, E->get().type, E->get().hint);
+ p.info = ShaderLanguage::uniform_to_property_info(E.value);
+ p.info.name = E.key; //supply name
+ p.index = E.value.instance_index;
+ p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint);
p_param_list->push_back(p);
}
}
@@ -202,7 +202,7 @@ Variant RendererSceneSkyRD::SkyShaderData::get_default_parameter(const StringNam
if (uniforms.has(p_parameter)) {
ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter];
Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value;
- return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.hint);
+ return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint);
}
return Variant();
}
@@ -259,7 +259,7 @@ static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_basis, float *p_ar
p_array[11] = 0;
}
-void RendererSceneSkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const CameraMatrix *p_projections, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position) {
+void RendererSceneSkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const CameraMatrix *p_projections, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position, float p_luminance_multiplier) {
SkyPushConstant sky_push_constant;
memset(&sky_push_constant, 0, sizeof(SkyPushConstant));
@@ -276,6 +276,7 @@ void RendererSceneSkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_
sky_push_constant.position[2] = p_position.z;
sky_push_constant.multiplier = p_multiplier;
sky_push_constant.time = p_time;
+ sky_push_constant.luminance_multiplier = p_luminance_multiplier;
store_transform_3x3(p_orientation, sky_push_constant.orientation);
RenderingDevice::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(p_fb);
@@ -287,7 +288,7 @@ void RendererSceneSkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_
// Update uniform sets.
{
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, sky_scene_state.uniform_set, 0);
- if (RD::get_singleton()->uniform_set_is_valid(p_uniform_set)) { // Material may not have a uniform set.
+ if (p_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(p_uniform_set)) { // Material may not have a uniform set.
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_uniform_set, 1);
}
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_texture_set, 2);
@@ -855,6 +856,8 @@ void RendererSceneSkyRD::init(RendererStorageRD *p_storage) {
storage->shader_initialize(sky_shader.default_shader);
storage->shader_set_code(sky_shader.default_shader, R"(
+// Default sky shader.
+
shader_type sky;
void sky() {
@@ -942,6 +945,8 @@ void sky() {
storage->shader_initialize(sky_scene_state.fog_shader);
storage->shader_set_code(sky_scene_state.fog_shader, R"(
+// Default clear color sky shader.
+
shader_type sky;
uniform vec4 clear_color;
@@ -1031,11 +1036,7 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b
SkyShaderData *shader_data = nullptr;
- RS::EnvironmentBG background = p_env->background;
-
- if (!(background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) || sky) {
- // !BAS! Possibly silently fail here, we now get error spam when you select sky as the background but haven't setup the sky yet.
- ERR_FAIL_COND(!sky);
+ if (sky) {
sky_material = sky_get_material(p_env->sky);
if (sky_material.is_valid()) {
@@ -1055,9 +1056,7 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b
shader_data = material->shader_data;
ERR_FAIL_COND(!shader_data);
- }
- if (sky) {
// Invalidate supbass buffers if screen size changes
if (sky->screen_size != p_screen_size) {
sky->screen_size = p_screen_size;
@@ -1191,7 +1190,7 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b
RD::get_singleton()->buffer_update(sky_scene_state.uniform_buffer, 0, sizeof(SkySceneState::UBO), &sky_scene_state.ubo);
}
-void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform, double p_time) {
+void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) {
ERR_FAIL_COND(!p_env);
Sky *sky = get_sky(p_env->sky);
@@ -1283,7 +1282,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES, sky_shader.default_shader_rd);
cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[2].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[2].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, multiplier, p_transform.origin);
+ _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[2].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, multiplier, p_transform.origin, p_luminance_multiplier);
RD::get_singleton()->draw_list_end();
}
RD::get_singleton()->draw_command_end_label();
@@ -1302,7 +1301,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_CUBEMAP_HALF_RES, sky_shader.default_shader_rd);
cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[1].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[1].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, multiplier, p_transform.origin);
+ _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[1].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, multiplier, p_transform.origin, p_luminance_multiplier);
RD::get_singleton()->draw_list_end();
}
RD::get_singleton()->draw_command_end_label();
@@ -1317,7 +1316,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_CUBEMAP, sky_shader.default_shader_rd);
cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[0].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[0].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, multiplier, p_transform.origin);
+ _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[0].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, multiplier, p_transform.origin, p_luminance_multiplier);
RD::get_singleton()->draw_list_end();
}
RD::get_singleton()->draw_command_end_label();
@@ -1366,7 +1365,6 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont
ERR_FAIL_COND(p_view_count > RendererSceneRender::MAX_RENDER_VIEWS);
Sky *sky = get_sky(p_env->sky);
- ERR_FAIL_COND(!sky);
SkyMaterialData *material = nullptr;
RID sky_material;
@@ -1435,7 +1433,7 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont
clear_colors.push_back(Color(0.0, 0.0, 0.0));
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->quarter_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors);
- _render_sky(draw_list, p_time, sky->quarter_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin);
+ _render_sky(draw_list, p_time, sky->quarter_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, 1.0);
RD::get_singleton()->draw_list_end();
}
@@ -1448,7 +1446,7 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont
clear_colors.push_back(Color(0.0, 0.0, 0.0));
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->half_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors);
- _render_sky(draw_list, p_time, sky->half_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin);
+ _render_sky(draw_list, p_time, sky->half_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, 1.0);
RD::get_singleton()->draw_list_end();
}
@@ -1462,11 +1460,11 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont
}
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_fb, RD::INITIAL_ACTION_CONTINUE, p_can_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, p_can_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ);
- _render_sky(draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin);
+ _render_sky(draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, 1.0);
RD::get_singleton()->draw_list_end();
}
-void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time) {
+void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) {
ERR_FAIL_COND(!p_env);
ERR_FAIL_COND(p_view_count == 0);
@@ -1478,27 +1476,17 @@ void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, u
SkyMaterialData *material = nullptr;
RID sky_material;
- RS::EnvironmentBG background = p_env->background;
-
- if (!(background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) || sky) {
- ERR_FAIL_COND(!sky);
- sky_material = sky_get_material(p_env->sky);
-
- if (sky_material.is_valid()) {
- material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
- if (!material || !material->shader_data->valid) {
- material = nullptr;
- }
- }
+ sky_material = sky_get_material(p_env->sky);
- if (!material) {
- sky_material = sky_shader.default_material;
- material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ if (sky_material.is_valid()) {
+ material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ if (!material || !material->shader_data->valid) {
+ material = nullptr;
}
}
- if (background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) {
- sky_material = sky_scene_state.fog_material;
+ if (!material) {
+ sky_material = sky_shader.default_material;
material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
}
@@ -1542,7 +1530,7 @@ void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, u
clear_colors.push_back(Color(0.0, 0.0, 0.0));
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->quarter_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors);
- _render_sky(draw_list, p_time, sky->quarter_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin);
+ _render_sky(draw_list, p_time, sky->quarter_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, p_luminance_multiplier);
RD::get_singleton()->draw_list_end();
}
@@ -1555,19 +1543,18 @@ void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, u
clear_colors.push_back(Color(0.0, 0.0, 0.0));
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->half_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors);
- _render_sky(draw_list, p_time, sky->half_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin);
+ _render_sky(draw_list, p_time, sky->half_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, p_luminance_multiplier);
RD::get_singleton()->draw_list_end();
}
}
-void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironmentRD *p_env, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time) {
+void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironmentRD *p_env, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) {
ERR_FAIL_COND(!p_env);
ERR_FAIL_COND(p_view_count == 0);
ERR_FAIL_COND(p_view_count > RendererSceneRender::MAX_RENDER_VIEWS);
Sky *sky = get_sky(p_env->sky);
- ERR_FAIL_COND(!sky);
SkyMaterialData *material = nullptr;
RID sky_material;
@@ -1636,7 +1623,7 @@ void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironme
texture_uniform_set = sky_scene_state.fog_only_texture_uniform_set;
}
- _render_sky(p_draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin);
+ _render_sky(p_draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, p_luminance_multiplier);
}
void RendererSceneSkyRD::invalidate_sky(Sky *p_sky) {
@@ -1767,7 +1754,7 @@ void RendererSceneSkyRD::initialize_sky_rid(RID p_rid) {
}
RendererSceneSkyRD::Sky *RendererSceneSkyRD::get_sky(RID p_sky) const {
- return sky_owner.getornull(p_sky);
+ return sky_owner.get_or_null(p_sky);
}
void RendererSceneSkyRD::free_sky(RID p_sky) {
diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
index 7b670bddd5..7f563c9bc4 100644
--- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
@@ -100,7 +100,8 @@ private:
float position[3]; // 12 - 92
float multiplier; // 4 - 96
float time; // 4 - 100
- float pad[3]; // 12 - 112 // Using pad to align on 16 bytes
+ float luminance_multiplier; // 4 - 104
+ float pad[2]; // 8 - 112 // Using pad to align on 16 bytes
// 128 is the max size of a push constant. We can replace "pad" but we can't add any more.
};
@@ -138,7 +139,7 @@ private:
virtual ~SkyShaderData();
};
- void _render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const CameraMatrix *p_projections, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position);
+ void _render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const CameraMatrix *p_projections, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position, float p_luminance_multiplier);
public:
struct SkySceneState {
@@ -293,10 +294,10 @@ public:
~RendererSceneSkyRD();
void setup(RendererSceneEnvironmentRD *p_env, RID p_render_buffers, const CameraMatrix &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render);
- void update(RendererSceneEnvironmentRD *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform, double p_time);
- void draw(RendererSceneEnvironmentRD *p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time);
- void update_res_buffers(RendererSceneEnvironmentRD *p_env, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time);
- void draw(RD::DrawListID p_draw_list, RendererSceneEnvironmentRD *p_env, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time);
+ void update(RendererSceneEnvironmentRD *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0);
+ void draw(RendererSceneEnvironmentRD *p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time); // only called by clustered renderer
+ void update_res_buffers(RendererSceneEnvironmentRD *p_env, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0);
+ void draw(RD::DrawListID p_draw_list, RendererSceneEnvironmentRD *p_env, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0);
void invalidate_sky(Sky *p_sky);
void update_dirty_skys();
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
index 8cc20618fc..a7bfea455d 100644
--- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
@@ -842,7 +842,7 @@ void RendererStorageRD::texture_3d_initialize(RID p_texture, Image::Format p_for
}
void RendererStorageRD::texture_proxy_initialize(RID p_texture, RID p_base) {
- Texture *tex = texture_owner.getornull(p_base);
+ Texture *tex = texture_owner.get_or_null(p_base);
ERR_FAIL_COND(!tex);
Texture proxy_tex = *tex;
@@ -865,7 +865,7 @@ void RendererStorageRD::texture_proxy_initialize(RID p_texture, RID p_base) {
void RendererStorageRD::_texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer, bool p_immediate) {
ERR_FAIL_COND(p_image.is_null() || p_image->is_empty());
- Texture *tex = texture_owner.getornull(p_texture);
+ Texture *tex = texture_owner.get_or_null(p_texture);
ERR_FAIL_COND(!tex);
ERR_FAIL_COND(tex->is_render_target);
ERR_FAIL_COND(p_image->get_width() != tex->width || p_image->get_height() != tex->height);
@@ -889,7 +889,7 @@ void RendererStorageRD::texture_2d_update(RID p_texture, const Ref<Image> &p_ima
}
void RendererStorageRD::texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) {
- Texture *tex = texture_owner.getornull(p_texture);
+ Texture *tex = texture_owner.get_or_null(p_texture);
ERR_FAIL_COND(!tex);
ERR_FAIL_COND(tex->type != Texture::TYPE_3D);
Image::Image3DValidateError verr = Image::validate_3d_image(tex->format, tex->width, tex->height, tex->depth, tex->mipmaps > 1, p_data);
@@ -926,10 +926,10 @@ void RendererStorageRD::texture_3d_update(RID p_texture, const Vector<Ref<Image>
}
void RendererStorageRD::texture_proxy_update(RID p_texture, RID p_proxy_to) {
- Texture *tex = texture_owner.getornull(p_texture);
+ Texture *tex = texture_owner.get_or_null(p_texture);
ERR_FAIL_COND(!tex);
ERR_FAIL_COND(!tex->is_proxy);
- Texture *proxy_to = texture_owner.getornull(p_proxy_to);
+ Texture *proxy_to = texture_owner.get_or_null(p_proxy_to);
ERR_FAIL_COND(!proxy_to);
ERR_FAIL_COND(proxy_to->is_proxy);
@@ -943,7 +943,7 @@ void RendererStorageRD::texture_proxy_update(RID p_texture, RID p_proxy_to) {
RD::get_singleton()->free(tex->rd_texture_srgb);
tex->rd_texture_srgb = RID();
}
- Texture *prev_tex = texture_owner.getornull(tex->proxy_to);
+ Texture *prev_tex = texture_owner.get_or_null(tex->proxy_to);
ERR_FAIL_COND(!prev_tex);
prev_tex->proxies.erase(p_texture);
}
@@ -1030,7 +1030,7 @@ void RendererStorageRD::texture_3d_placeholder_initialize(RID p_texture) {
}
Ref<Image> RendererStorageRD::texture_2d_get(RID p_texture) const {
- Texture *tex = texture_owner.getornull(p_texture);
+ Texture *tex = texture_owner.get_or_null(p_texture);
ERR_FAIL_COND_V(!tex, Ref<Image>());
#ifdef TOOLS_ENABLED
@@ -1058,7 +1058,7 @@ Ref<Image> RendererStorageRD::texture_2d_get(RID p_texture) const {
}
Ref<Image> RendererStorageRD::texture_2d_layer_get(RID p_texture, int p_layer) const {
- Texture *tex = texture_owner.getornull(p_texture);
+ Texture *tex = texture_owner.get_or_null(p_texture);
ERR_FAIL_COND_V(!tex, Ref<Image>());
Vector<uint8_t> data = RD::get_singleton()->texture_get_data(tex->rd_texture, p_layer);
@@ -1075,7 +1075,7 @@ Ref<Image> RendererStorageRD::texture_2d_layer_get(RID p_texture, int p_layer) c
}
Vector<Ref<Image>> RendererStorageRD::texture_3d_get(RID p_texture) const {
- Texture *tex = texture_owner.getornull(p_texture);
+ Texture *tex = texture_owner.get_or_null(p_texture);
ERR_FAIL_COND_V(!tex, Vector<Ref<Image>>());
ERR_FAIL_COND_V(tex->type != Texture::TYPE_3D, Vector<Ref<Image>>());
@@ -1106,10 +1106,10 @@ Vector<Ref<Image>> RendererStorageRD::texture_3d_get(RID p_texture) const {
}
void RendererStorageRD::texture_replace(RID p_texture, RID p_by_texture) {
- Texture *tex = texture_owner.getornull(p_texture);
+ Texture *tex = texture_owner.get_or_null(p_texture);
ERR_FAIL_COND(!tex);
ERR_FAIL_COND(tex->proxy_to.is_valid()); //can't replace proxy
- Texture *by_tex = texture_owner.getornull(p_by_texture);
+ Texture *by_tex = texture_owner.get_or_null(p_by_texture);
ERR_FAIL_COND(!by_tex);
ERR_FAIL_COND(by_tex->proxy_to.is_valid()); //can't replace proxy
@@ -1155,7 +1155,7 @@ void RendererStorageRD::texture_replace(RID p_texture, RID p_by_texture) {
}
void RendererStorageRD::texture_set_size_override(RID p_texture, int p_width, int p_height) {
- Texture *tex = texture_owner.getornull(p_texture);
+ Texture *tex = texture_owner.get_or_null(p_texture);
ERR_FAIL_COND(!tex);
ERR_FAIL_COND(tex->type != Texture::TYPE_2D);
tex->width_2d = p_width;
@@ -1163,7 +1163,7 @@ void RendererStorageRD::texture_set_size_override(RID p_texture, int p_width, in
}
void RendererStorageRD::texture_set_path(RID p_texture, const String &p_path) {
- Texture *tex = texture_owner.getornull(p_texture);
+ Texture *tex = texture_owner.get_or_null(p_texture);
ERR_FAIL_COND(!tex);
tex->path = p_path;
}
@@ -1173,21 +1173,21 @@ String RendererStorageRD::texture_get_path(RID p_texture) const {
}
void RendererStorageRD::texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) {
- Texture *tex = texture_owner.getornull(p_texture);
+ Texture *tex = texture_owner.get_or_null(p_texture);
ERR_FAIL_COND(!tex);
tex->detect_3d_callback_ud = p_userdata;
tex->detect_3d_callback = p_callback;
}
void RendererStorageRD::texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) {
- Texture *tex = texture_owner.getornull(p_texture);
+ Texture *tex = texture_owner.get_or_null(p_texture);
ERR_FAIL_COND(!tex);
tex->detect_normal_callback_ud = p_userdata;
tex->detect_normal_callback = p_callback;
}
void RendererStorageRD::texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) {
- Texture *tex = texture_owner.getornull(p_texture);
+ Texture *tex = texture_owner.get_or_null(p_texture);
ERR_FAIL_COND(!tex);
tex->detect_roughness_callback_ud = p_userdata;
tex->detect_roughness_callback = p_callback;
@@ -1235,7 +1235,7 @@ void RendererStorageRD::canvas_texture_initialize(RID p_rid) {
}
void RendererStorageRD::canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) {
- CanvasTexture *ct = canvas_texture_owner.getornull(p_canvas_texture);
+ CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
switch (p_channel) {
case RS::CANVAS_TEXTURE_CHANNEL_DIFFUSE: {
ct->diffuse = p_texture;
@@ -1252,7 +1252,7 @@ void RendererStorageRD::canvas_texture_set_channel(RID p_canvas_texture, RS::Can
}
void RendererStorageRD::canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_specular_color, float p_shininess) {
- CanvasTexture *ct = canvas_texture_owner.getornull(p_canvas_texture);
+ CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
ct->specular_color.r = p_specular_color.r;
ct->specular_color.g = p_specular_color.g;
ct->specular_color.b = p_specular_color.b;
@@ -1261,13 +1261,13 @@ void RendererStorageRD::canvas_texture_set_shading_parameters(RID p_canvas_textu
}
void RendererStorageRD::canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter) {
- CanvasTexture *ct = canvas_texture_owner.getornull(p_canvas_texture);
+ CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
ct->texture_filter = p_filter;
ct->clear_sets();
}
void RendererStorageRD::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) {
- CanvasTexture *ct = canvas_texture_owner.getornull(p_canvas_texture);
+ CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
ct->texture_repeat = p_repeat;
ct->clear_sets();
}
@@ -1275,7 +1275,7 @@ void RendererStorageRD::canvas_texture_set_texture_repeat(RID p_canvas_texture,
bool RendererStorageRD::canvas_texture_get_uniform_set(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID p_base_shader, int p_base_set, RID &r_uniform_set, Size2i &r_size, Color &r_specular_shininess, bool &r_use_normal, bool &r_use_specular) {
CanvasTexture *ct = nullptr;
- Texture *t = texture_owner.getornull(p_texture);
+ Texture *t = texture_owner.get_or_null(p_texture);
if (t) {
//regular texture
@@ -1286,7 +1286,7 @@ bool RendererStorageRD::canvas_texture_get_uniform_set(RID p_texture, RS::Canvas
ct = t->canvas_texture;
} else {
- ct = canvas_texture_owner.getornull(p_texture);
+ ct = canvas_texture_owner.get_or_null(p_texture);
}
if (!ct) {
@@ -1308,7 +1308,7 @@ bool RendererStorageRD::canvas_texture_get_uniform_set(RID p_texture, RS::Canvas
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 0;
- t = texture_owner.getornull(ct->diffuse);
+ t = texture_owner.get_or_null(ct->diffuse);
if (!t) {
u.ids.push_back(texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE));
ct->size_cache = Size2i(1, 1);
@@ -1323,7 +1323,7 @@ bool RendererStorageRD::canvas_texture_get_uniform_set(RID p_texture, RS::Canvas
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 1;
- t = texture_owner.getornull(ct->normal_map);
+ t = texture_owner.get_or_null(ct->normal_map);
if (!t) {
u.ids.push_back(texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL));
ct->use_normal_cache = false;
@@ -1338,7 +1338,7 @@ bool RendererStorageRD::canvas_texture_get_uniform_set(RID p_texture, RS::Canvas
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 2;
- t = texture_owner.getornull(ct->specular);
+ t = texture_owner.get_or_null(ct->specular);
if (!t) {
u.ids.push_back(texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE));
ct->use_specular_cache = false;
@@ -1384,7 +1384,7 @@ void RendererStorageRD::shader_initialize(RID p_rid) {
}
void RendererStorageRD::shader_set_code(RID p_shader, const String &p_code) {
- Shader *shader = shader_owner.getornull(p_shader);
+ Shader *shader = shader_owner.get_or_null(p_shader);
ERR_FAIL_COND(!shader);
shader->code = p_code;
@@ -1438,8 +1438,8 @@ void RendererStorageRD::shader_set_code(RID p_shader, const String &p_code) {
}
if (shader->data) {
- for (Map<StringName, RID>::Element *E = shader->default_texture_parameter.front(); E; E = E->next()) {
- shader->data->set_default_texture_param(E->key(), E->get());
+ for (const KeyValue<StringName, RID> &E : shader->default_texture_parameter) {
+ shader->data->set_default_texture_param(E.key, E.value);
}
}
}
@@ -1456,13 +1456,13 @@ void RendererStorageRD::shader_set_code(RID p_shader, const String &p_code) {
}
String RendererStorageRD::shader_get_code(RID p_shader) const {
- Shader *shader = shader_owner.getornull(p_shader);
+ Shader *shader = shader_owner.get_or_null(p_shader);
ERR_FAIL_COND_V(!shader, String());
return shader->code;
}
void RendererStorageRD::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const {
- Shader *shader = shader_owner.getornull(p_shader);
+ Shader *shader = shader_owner.get_or_null(p_shader);
ERR_FAIL_COND(!shader);
if (shader->data) {
return shader->data->get_param_list(p_param_list);
@@ -1470,7 +1470,7 @@ void RendererStorageRD::shader_get_param_list(RID p_shader, List<PropertyInfo> *
}
void RendererStorageRD::shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) {
- Shader *shader = shader_owner.getornull(p_shader);
+ Shader *shader = shader_owner.get_or_null(p_shader);
ERR_FAIL_COND(!shader);
if (p_texture.is_valid() && texture_owner.owns(p_texture)) {
@@ -1488,7 +1488,7 @@ void RendererStorageRD::shader_set_default_texture_param(RID p_shader, const Str
}
RID RendererStorageRD::shader_get_default_texture_param(RID p_shader, const StringName &p_name) const {
- Shader *shader = shader_owner.getornull(p_shader);
+ Shader *shader = shader_owner.get_or_null(p_shader);
ERR_FAIL_COND_V(!shader, RID());
if (shader->default_texture_parameter.has(p_name)) {
return shader->default_texture_parameter[p_name];
@@ -1498,7 +1498,7 @@ RID RendererStorageRD::shader_get_default_texture_param(RID p_shader, const Stri
}
Variant RendererStorageRD::shader_get_param_default(RID p_shader, const StringName &p_param) const {
- Shader *shader = shader_owner.getornull(p_shader);
+ Shader *shader = shader_owner.get_or_null(p_shader);
ERR_FAIL_COND_V(!shader, Variant());
if (shader->data) {
return shader->data->get_default_parameter(p_param);
@@ -1512,7 +1512,7 @@ void RendererStorageRD::shader_set_data_request_function(ShaderType p_shader_typ
}
RS::ShaderNativeSourceCode RendererStorageRD::shader_get_native_source_code(RID p_shader) const {
- Shader *shader = shader_owner.getornull(p_shader);
+ Shader *shader = shader_owner.get_or_null(p_shader);
ERR_FAIL_COND_V(!shader, RS::ShaderNativeSourceCode());
if (shader->data) {
return shader->data->get_native_source_code();
@@ -1527,7 +1527,7 @@ RID RendererStorageRD::material_allocate() {
}
void RendererStorageRD::material_initialize(RID p_rid) {
material_owner.initialize_rid(p_rid);
- Material *material = material_owner.getornull(p_rid);
+ Material *material = material_owner.get_or_null(p_rid);
material->self = p_rid;
}
@@ -1543,7 +1543,7 @@ void RendererStorageRD::_material_queue_update(Material *material, bool p_unifor
}
void RendererStorageRD::material_set_shader(RID p_material, RID p_shader) {
- Material *material = material_owner.getornull(p_material);
+ Material *material = material_owner.get_or_null(p_material);
ERR_FAIL_COND(!material);
if (material->data) {
@@ -1563,7 +1563,7 @@ void RendererStorageRD::material_set_shader(RID p_material, RID p_shader) {
return;
}
- Shader *shader = shader_owner.getornull(p_shader);
+ Shader *shader = shader_owner.get_or_null(p_shader);
ERR_FAIL_COND(!shader);
material->shader = shader;
material->shader_type = shader->type;
@@ -1586,7 +1586,7 @@ void RendererStorageRD::material_set_shader(RID p_material, RID p_shader) {
}
void RendererStorageRD::material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) {
- Material *material = material_owner.getornull(p_material);
+ Material *material = material_owner.get_or_null(p_material);
ERR_FAIL_COND(!material);
if (p_value.get_type() == Variant::NIL) {
@@ -1605,7 +1605,7 @@ void RendererStorageRD::material_set_param(RID p_material, const StringName &p_p
}
Variant RendererStorageRD::material_get_param(RID p_material, const StringName &p_param) const {
- Material *material = material_owner.getornull(p_material);
+ Material *material = material_owner.get_or_null(p_material);
ERR_FAIL_COND_V(!material, Variant());
if (material->params.has(p_param)) {
return material->params[p_param];
@@ -1615,7 +1615,7 @@ Variant RendererStorageRD::material_get_param(RID p_material, const StringName &
}
void RendererStorageRD::material_set_next_pass(RID p_material, RID p_next_material) {
- Material *material = material_owner.getornull(p_material);
+ Material *material = material_owner.get_or_null(p_material);
ERR_FAIL_COND(!material);
if (material->next_pass == p_next_material) {
@@ -1631,7 +1631,7 @@ void RendererStorageRD::material_set_next_pass(RID p_material, RID p_next_materi
}
void RendererStorageRD::material_set_render_priority(RID p_material, int priority) {
- Material *material = material_owner.getornull(p_material);
+ Material *material = material_owner.get_or_null(p_material);
ERR_FAIL_COND(!material);
material->priority = priority;
if (material->data) {
@@ -1640,7 +1640,7 @@ void RendererStorageRD::material_set_render_priority(RID p_material, int priorit
}
bool RendererStorageRD::material_is_animated(RID p_material) {
- Material *material = material_owner.getornull(p_material);
+ Material *material = material_owner.get_or_null(p_material);
ERR_FAIL_COND_V(!material, false);
if (material->shader && material->shader->data) {
if (material->shader->data->is_animated()) {
@@ -1653,7 +1653,7 @@ bool RendererStorageRD::material_is_animated(RID p_material) {
}
bool RendererStorageRD::material_casts_shadows(RID p_material) {
- Material *material = material_owner.getornull(p_material);
+ Material *material = material_owner.get_or_null(p_material);
ERR_FAIL_COND_V(!material, true);
if (material->shader && material->shader->data) {
if (material->shader->data->casts_shadows()) {
@@ -1666,7 +1666,7 @@ bool RendererStorageRD::material_casts_shadows(RID p_material) {
}
void RendererStorageRD::material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) {
- Material *material = material_owner.getornull(p_material);
+ Material *material = material_owner.get_or_null(p_material);
ERR_FAIL_COND(!material);
if (material->shader && material->shader->data) {
material->shader->data->get_instance_param_list(r_parameters);
@@ -1678,7 +1678,7 @@ void RendererStorageRD::material_get_instance_shader_parameters(RID p_material,
}
void RendererStorageRD::material_update_dependency(RID p_material, DependencyTracker *p_instance) {
- Material *material = material_owner.getornull(p_material);
+ Material *material = material_owner.get_or_null(p_material);
ERR_FAIL_COND(!material);
p_instance->update_dependency(&material->dependency);
if (material->next_pass.is_valid()) {
@@ -1691,73 +1691,183 @@ void RendererStorageRD::material_set_data_request_function(ShaderType p_shader_t
material_data_request_func[p_shader_type] = p_function;
}
-_FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataType type, const Variant &value, uint8_t *data, bool p_linear_color) {
+_FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataType type, int p_array_size, const Variant &value, uint8_t *data, bool p_linear_color) {
switch (type) {
case ShaderLanguage::TYPE_BOOL: {
- bool v = value;
-
uint32_t *gui = (uint32_t *)data;
- *gui = v ? 1 : 0;
+
+ if (p_array_size > 0) {
+ const PackedInt32Array &ba = value;
+ int s = ba.size();
+ const int *r = ba.ptr();
+
+ for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
+ if (i < s) {
+ gui[j] = (r[i] != 0) ? 1 : 0;
+ } else {
+ gui[j] = 0;
+ }
+ gui[j + 1] = 0; // ignored
+ gui[j + 2] = 0; // ignored
+ gui[j + 3] = 0; // ignored
+ }
+ } else {
+ bool v = value;
+ gui[0] = v ? 1 : 0;
+ }
} break;
case ShaderLanguage::TYPE_BVEC2: {
- int v = value;
uint32_t *gui = (uint32_t *)data;
- gui[0] = v & 1 ? 1 : 0;
- gui[1] = v & 2 ? 1 : 0;
+ if (p_array_size > 0) {
+ const PackedInt32Array &ba = value;
+ int s = ba.size();
+ const int *r = ba.ptr();
+ int count = 2 * p_array_size;
+
+ for (int i = 0, j = 0; i < count; i += 2, j += 4) {
+ if (i < s) {
+ gui[j] = r[i] ? 1 : 0;
+ gui[j + 1] = r[i + 1] ? 1 : 0;
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ }
+ gui[j + 2] = 0; // ignored
+ gui[j + 3] = 0; // ignored
+ }
+ } else {
+ int v = value;
+ gui[0] = v & 1 ? 1 : 0;
+ gui[1] = v & 2 ? 1 : 0;
+ }
} break;
case ShaderLanguage::TYPE_BVEC3: {
- int v = value;
uint32_t *gui = (uint32_t *)data;
- gui[0] = (v & 1) ? 1 : 0;
- gui[1] = (v & 2) ? 1 : 0;
- gui[2] = (v & 4) ? 1 : 0;
+ if (p_array_size > 0) {
+ const PackedInt32Array &ba = value;
+ int s = ba.size();
+ const int *r = ba.ptr();
+ int count = 3 * p_array_size;
+
+ for (int i = 0, j = 0; i < count; i += 3, j += 4) {
+ if (i < s) {
+ gui[j] = r[i] ? 1 : 0;
+ gui[j + 1] = r[i + 1] ? 1 : 0;
+ gui[j + 2] = r[i + 2] ? 1 : 0;
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ gui[j + 2] = 0;
+ }
+ gui[j + 3] = 0; // ignored
+ }
+ } else {
+ int v = value;
+ gui[0] = (v & 1) ? 1 : 0;
+ gui[1] = (v & 2) ? 1 : 0;
+ gui[2] = (v & 4) ? 1 : 0;
+ }
} break;
case ShaderLanguage::TYPE_BVEC4: {
- int v = value;
uint32_t *gui = (uint32_t *)data;
- gui[0] = (v & 1) ? 1 : 0;
- gui[1] = (v & 2) ? 1 : 0;
- gui[2] = (v & 4) ? 1 : 0;
- gui[3] = (v & 8) ? 1 : 0;
+ if (p_array_size > 0) {
+ const PackedInt32Array &ba = value;
+ int s = ba.size();
+ const int *r = ba.ptr();
+ int count = 4 * p_array_size;
+
+ for (int i = 0; i < count; i += 4) {
+ if (i < s) {
+ gui[i] = r[i] ? 1 : 0;
+ gui[i + 1] = r[i + 1] ? 1 : 0;
+ gui[i + 2] = r[i + 2] ? 1 : 0;
+ gui[i + 3] = r[i + 3] ? 1 : 0;
+ } else {
+ gui[i] = 0;
+ gui[i + 1] = 0;
+ gui[i + 2] = 0;
+ gui[i + 3] = 0;
+ }
+ }
+ } else {
+ int v = value;
+ gui[0] = (v & 1) ? 1 : 0;
+ gui[1] = (v & 2) ? 1 : 0;
+ gui[2] = (v & 4) ? 1 : 0;
+ gui[3] = (v & 8) ? 1 : 0;
+ }
} break;
case ShaderLanguage::TYPE_INT: {
- int v = value;
int32_t *gui = (int32_t *)data;
- gui[0] = v;
+ if (p_array_size > 0) {
+ Vector<int> iv = value;
+ int s = iv.size();
+ const int *r = iv.ptr();
+
+ for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
+ if (i < s) {
+ gui[j] = r[i];
+ } else {
+ gui[j] = 0;
+ }
+ gui[j + 1] = 0; // ignored
+ gui[j + 2] = 0; // ignored
+ gui[j + 3] = 0; // ignored
+ }
+ } else {
+ int v = value;
+ gui[0] = v;
+ }
} break;
case ShaderLanguage::TYPE_IVEC2: {
Vector<int> iv = value;
int s = iv.size();
int32_t *gui = (int32_t *)data;
- const int *r = iv.ptr();
+ if (p_array_size <= 0) {
+ p_array_size = 1;
+ }
+ int count = 2 * p_array_size;
- for (int i = 0; i < 2; i++) {
+ const int *r = iv.ptr();
+ for (int i = 0, j = 0; i < count; i += 2, j += 4) {
if (i < s) {
- gui[i] = r[i];
+ gui[j] = r[i];
+ gui[j + 1] = r[i + 1];
} else {
- gui[i] = 0;
+ gui[j] = 0;
+ gui[j + 1] = 0;
}
+ gui[j + 2] = 0; // ignored
+ gui[j + 3] = 0; // ignored
}
-
} break;
case ShaderLanguage::TYPE_IVEC3: {
Vector<int> iv = value;
int s = iv.size();
int32_t *gui = (int32_t *)data;
- const int *r = iv.ptr();
+ if (p_array_size <= 0) {
+ p_array_size = 1;
+ }
+ int count = 3 * p_array_size;
- for (int i = 0; i < 3; i++) {
+ const int *r = iv.ptr();
+ for (int i = 0, j = 0; i < count; i += 3, j += 4) {
if (i < s) {
- gui[i] = r[i];
+ gui[j] = r[i];
+ gui[j + 1] = r[i + 1];
+ gui[j + 2] = r[i + 2];
} else {
- gui[i] = 0;
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ gui[j + 2] = 0;
}
+ gui[j + 3] = 0; // ignored
}
} break;
case ShaderLanguage::TYPE_IVEC4: {
@@ -1765,35 +1875,70 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
int s = iv.size();
int32_t *gui = (int32_t *)data;
- const int *r = iv.ptr();
+ if (p_array_size <= 0) {
+ p_array_size = 1;
+ }
+ int count = 4 * p_array_size;
- for (int i = 0; i < 4; i++) {
+ const int *r = iv.ptr();
+ for (int i = 0; i < count; i += 4) {
if (i < s) {
gui[i] = r[i];
+ gui[i + 1] = r[i + 1];
+ gui[i + 2] = r[i + 2];
+ gui[i + 3] = r[i + 3];
} else {
gui[i] = 0;
+ gui[i + 1] = 0;
+ gui[i + 2] = 0;
+ gui[i + 3] = 0;
}
}
} break;
case ShaderLanguage::TYPE_UINT: {
- int v = value;
uint32_t *gui = (uint32_t *)data;
- gui[0] = v;
+ if (p_array_size > 0) {
+ Vector<int> iv = value;
+ int s = iv.size();
+ const int *r = iv.ptr();
+
+ for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
+ if (i < s) {
+ gui[j] = r[i];
+ } else {
+ gui[j] = 0;
+ }
+ gui[j + 1] = 0; // ignored
+ gui[j + 2] = 0; // ignored
+ gui[j + 3] = 0; // ignored
+ }
+ } else {
+ int v = value;
+ gui[0] = v;
+ }
} break;
case ShaderLanguage::TYPE_UVEC2: {
Vector<int> iv = value;
int s = iv.size();
uint32_t *gui = (uint32_t *)data;
- const int *r = iv.ptr();
+ if (p_array_size <= 0) {
+ p_array_size = 1;
+ }
+ int count = 2 * p_array_size;
- for (int i = 0; i < 2; i++) {
+ const int *r = iv.ptr();
+ for (int i = 0, j = 0; i < count; i += 2, j += 4) {
if (i < s) {
- gui[i] = r[i];
+ gui[j] = r[i];
+ gui[j + 1] = r[i + 1];
} else {
- gui[i] = 0;
+ gui[j] = 0;
+ gui[j + 1] = 0;
}
+ gui[j + 2] = 0; // ignored
+ gui[j + 3] = 0; // ignored
}
} break;
case ShaderLanguage::TYPE_UVEC3: {
@@ -1801,141 +1946,370 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
int s = iv.size();
uint32_t *gui = (uint32_t *)data;
- const int *r = iv.ptr();
+ if (p_array_size <= 0) {
+ p_array_size = 1;
+ }
+ int count = 3 * p_array_size;
- for (int i = 0; i < 3; i++) {
+ const int *r = iv.ptr();
+ for (int i = 0, j = 0; i < count; i += 3, j += 4) {
if (i < s) {
- gui[i] = r[i];
+ gui[j] = r[i];
+ gui[j + 1] = r[i + 1];
+ gui[j + 2] = r[i + 2];
} else {
- gui[i] = 0;
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ gui[j + 2] = 0;
}
+ gui[j + 3] = 0; // ignored
}
-
} break;
case ShaderLanguage::TYPE_UVEC4: {
Vector<int> iv = value;
int s = iv.size();
uint32_t *gui = (uint32_t *)data;
- const int *r = iv.ptr();
+ if (p_array_size <= 0) {
+ p_array_size = 1;
+ }
+ int count = 4 * p_array_size;
- for (int i = 0; i < 4; i++) {
+ const int *r = iv.ptr();
+ for (int i = 0; i < count; i++) {
if (i < s) {
gui[i] = r[i];
+ gui[i + 1] = r[i + 1];
+ gui[i + 2] = r[i + 2];
+ gui[i + 3] = r[i + 3];
} else {
gui[i] = 0;
+ gui[i + 1] = 0;
+ gui[i + 2] = 0;
+ gui[i + 3] = 0;
}
}
} break;
case ShaderLanguage::TYPE_FLOAT: {
- float v = value;
float *gui = (float *)data;
- gui[0] = v;
+ if (p_array_size > 0) {
+ const PackedFloat32Array &a = value;
+ int s = a.size();
+
+ for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
+ if (i < s) {
+ gui[j] = a[i];
+ } else {
+ gui[j] = 0;
+ }
+ gui[j + 1] = 0; // ignored
+ gui[j + 2] = 0; // ignored
+ gui[j + 3] = 0; // ignored
+ }
+ } else {
+ float v = value;
+ gui[0] = v;
+ }
} break;
case ShaderLanguage::TYPE_VEC2: {
- Vector2 v = value;
float *gui = (float *)data;
- gui[0] = v.x;
- gui[1] = v.y;
+ if (p_array_size > 0) {
+ const PackedVector2Array &a = value;
+ int s = a.size();
+
+ for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
+ if (i < s) {
+ gui[j] = a[i].x;
+ gui[j + 1] = a[i].y;
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ }
+ gui[j + 2] = 0; // ignored
+ gui[j + 3] = 0; // ignored
+ }
+ } else {
+ Vector2 v = value;
+ gui[0] = v.x;
+ gui[1] = v.y;
+ }
} break;
case ShaderLanguage::TYPE_VEC3: {
- Vector3 v = value;
float *gui = (float *)data;
- gui[0] = v.x;
- gui[1] = v.y;
- gui[2] = v.z;
+ if (p_array_size > 0) {
+ const PackedVector3Array &a = value;
+ int s = a.size();
+
+ for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
+ if (i < s) {
+ gui[j] = a[i].x;
+ gui[j + 1] = a[i].y;
+ gui[j + 2] = a[i].z;
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ gui[j + 2] = 0;
+ }
+ gui[j + 3] = 0; // ignored
+ }
+ } else {
+ Vector3 v = value;
+ gui[0] = v.x;
+ gui[1] = v.y;
+ gui[2] = v.z;
+ }
} break;
case ShaderLanguage::TYPE_VEC4: {
float *gui = (float *)data;
- if (value.get_type() == Variant::COLOR) {
- Color v = value;
+ if (p_array_size > 0) {
+ if (value.get_type() == Variant::PACKED_COLOR_ARRAY) {
+ const PackedColorArray &a = value;
+ int s = a.size();
- if (p_linear_color) {
- v = v.to_linear();
+ for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
+ if (i < s) {
+ Color color = a[i];
+ if (p_linear_color) {
+ color = color.to_linear();
+ }
+ gui[j] = color.r;
+ gui[j + 1] = color.g;
+ gui[j + 2] = color.b;
+ gui[j + 3] = color.a;
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ gui[j + 2] = 0;
+ gui[j + 3] = 0;
+ }
+ }
+ } else {
+ const PackedFloat32Array &a = value;
+ int s = a.size();
+ int count = 4 * p_array_size;
+
+ for (int i = 0; i < count; i += 4) {
+ if (i + 3 < s) {
+ gui[i] = a[i];
+ gui[i + 1] = a[i + 1];
+ gui[i + 2] = a[i + 2];
+ gui[i + 3] = a[i + 3];
+ } else {
+ gui[i] = 0;
+ gui[i + 1] = 0;
+ gui[i + 2] = 0;
+ gui[i + 3] = 0;
+ }
+ }
}
+ } else {
+ if (value.get_type() == Variant::COLOR) {
+ Color v = value;
- gui[0] = v.r;
- gui[1] = v.g;
- gui[2] = v.b;
- gui[3] = v.a;
- } else if (value.get_type() == Variant::RECT2) {
- Rect2 v = value;
-
- gui[0] = v.position.x;
- gui[1] = v.position.y;
- gui[2] = v.size.x;
- gui[3] = v.size.y;
- } else if (value.get_type() == Variant::QUATERNION) {
- Quaternion v = value;
+ if (p_linear_color) {
+ v = v.to_linear();
+ }
- gui[0] = v.x;
- gui[1] = v.y;
- gui[2] = v.z;
- gui[3] = v.w;
- } else {
- Plane v = value;
+ gui[0] = v.r;
+ gui[1] = v.g;
+ gui[2] = v.b;
+ gui[3] = v.a;
+ } else if (value.get_type() == Variant::RECT2) {
+ Rect2 v = value;
+
+ gui[0] = v.position.x;
+ gui[1] = v.position.y;
+ gui[2] = v.size.x;
+ gui[3] = v.size.y;
+ } else if (value.get_type() == Variant::QUATERNION) {
+ Quaternion v = value;
+
+ gui[0] = v.x;
+ gui[1] = v.y;
+ gui[2] = v.z;
+ gui[3] = v.w;
+ } else {
+ Plane v = value;
- gui[0] = v.normal.x;
- gui[1] = v.normal.y;
- gui[2] = v.normal.z;
- gui[3] = v.d;
+ gui[0] = v.normal.x;
+ gui[1] = v.normal.y;
+ gui[2] = v.normal.z;
+ gui[3] = v.d;
+ }
}
} break;
case ShaderLanguage::TYPE_MAT2: {
- Transform2D v = value;
float *gui = (float *)data;
- //in std140 members of mat2 are treated as vec4s
- gui[0] = v.elements[0][0];
- gui[1] = v.elements[0][1];
- gui[2] = 0;
- gui[3] = 0;
- gui[4] = v.elements[1][0];
- gui[5] = v.elements[1][1];
- gui[6] = 0;
- gui[7] = 0;
+ if (p_array_size > 0) {
+ const PackedFloat32Array &a = value;
+ int s = a.size();
+
+ for (int i = 0, j = 0; i < p_array_size * 4; i += 4, j += 8) {
+ if (i + 3 < s) {
+ gui[j] = a[i];
+ gui[j + 1] = a[i + 1];
+
+ gui[j + 4] = a[i + 2];
+ gui[j + 5] = a[i + 3];
+ } else {
+ gui[j] = 1;
+ gui[j + 1] = 0;
+
+ gui[j + 4] = 0;
+ gui[j + 5] = 1;
+ }
+ gui[j + 2] = 0; // ignored
+ gui[j + 3] = 0; // ignored
+ gui[j + 6] = 0; // ignored
+ gui[j + 7] = 0; // ignored
+ }
+ } else {
+ Transform2D v = value;
+
+ //in std140 members of mat2 are treated as vec4s
+ gui[0] = v.elements[0][0];
+ gui[1] = v.elements[0][1];
+ gui[2] = 0; // ignored
+ gui[3] = 0; // ignored
+
+ gui[4] = v.elements[1][0];
+ gui[5] = v.elements[1][1];
+ gui[6] = 0; // ignored
+ gui[7] = 0; // ignored
+ }
} break;
case ShaderLanguage::TYPE_MAT3: {
- Basis v = value;
float *gui = (float *)data;
- gui[0] = v.elements[0][0];
- gui[1] = v.elements[1][0];
- gui[2] = v.elements[2][0];
- gui[3] = 0;
- gui[4] = v.elements[0][1];
- gui[5] = v.elements[1][1];
- gui[6] = v.elements[2][1];
- gui[7] = 0;
- gui[8] = v.elements[0][2];
- gui[9] = v.elements[1][2];
- gui[10] = v.elements[2][2];
- gui[11] = 0;
+ if (p_array_size > 0) {
+ const PackedFloat32Array &a = value;
+ int s = a.size();
+
+ for (int i = 0, j = 0; i < p_array_size * 9; i += 9, j += 12) {
+ if (i + 8 < s) {
+ gui[j] = a[i];
+ gui[j + 1] = a[i + 1];
+ gui[j + 2] = a[i + 2];
+
+ gui[j + 4] = a[i + 3];
+ gui[j + 5] = a[i + 4];
+ gui[j + 6] = a[i + 5];
+
+ gui[j + 8] = a[i + 6];
+ gui[j + 9] = a[i + 7];
+ gui[j + 10] = a[i + 8];
+ } else {
+ gui[j] = 1;
+ gui[j + 1] = 0;
+ gui[j + 2] = 0;
+
+ gui[j + 4] = 0;
+ gui[j + 5] = 1;
+ gui[j + 6] = 0;
+
+ gui[j + 8] = 0;
+ gui[j + 9] = 0;
+ gui[j + 10] = 1;
+ }
+ gui[j + 3] = 0; // ignored
+ gui[j + 7] = 0; // ignored
+ gui[j + 11] = 0; // ignored
+ }
+ } else {
+ Basis v = value;
+ gui[0] = v.elements[0][0];
+ gui[1] = v.elements[1][0];
+ gui[2] = v.elements[2][0];
+ gui[3] = 0; // ignored
+
+ gui[4] = v.elements[0][1];
+ gui[5] = v.elements[1][1];
+ gui[6] = v.elements[2][1];
+ gui[7] = 0; // ignored
+
+ gui[8] = v.elements[0][2];
+ gui[9] = v.elements[1][2];
+ gui[10] = v.elements[2][2];
+ gui[11] = 0; // ignored
+ }
} break;
case ShaderLanguage::TYPE_MAT4: {
- Transform3D v = value;
float *gui = (float *)data;
- gui[0] = v.basis.elements[0][0];
- gui[1] = v.basis.elements[1][0];
- gui[2] = v.basis.elements[2][0];
- gui[3] = 0;
- gui[4] = v.basis.elements[0][1];
- gui[5] = v.basis.elements[1][1];
- gui[6] = v.basis.elements[2][1];
- gui[7] = 0;
- gui[8] = v.basis.elements[0][2];
- gui[9] = v.basis.elements[1][2];
- gui[10] = v.basis.elements[2][2];
- gui[11] = 0;
- gui[12] = v.origin.x;
- gui[13] = v.origin.y;
- gui[14] = v.origin.z;
- gui[15] = 1;
+ if (p_array_size > 0) {
+ const PackedFloat32Array &a = value;
+ int s = a.size();
+
+ for (int i = 0; i < p_array_size * 16; i += 16) {
+ if (i + 15 < s) {
+ gui[i] = a[i];
+ gui[i + 1] = a[i + 1];
+ gui[i + 2] = a[i + 2];
+ gui[i + 3] = a[i + 3];
+
+ gui[i + 4] = a[i + 4];
+ gui[i + 5] = a[i + 5];
+ gui[i + 6] = a[i + 6];
+ gui[i + 7] = a[i + 7];
+
+ gui[i + 8] = a[i + 8];
+ gui[i + 9] = a[i + 9];
+ gui[i + 10] = a[i + 10];
+ gui[i + 11] = a[i + 11];
+
+ gui[i + 12] = a[i + 12];
+ gui[i + 13] = a[i + 13];
+ gui[i + 14] = a[i + 14];
+ gui[i + 15] = a[i + 15];
+ } else {
+ gui[i] = 1;
+ gui[i + 1] = 0;
+ gui[i + 2] = 0;
+ gui[i + 3] = 0;
+
+ gui[i + 4] = 0;
+ gui[i + 5] = 1;
+ gui[i + 6] = 0;
+ gui[i + 7] = 0;
+
+ gui[i + 8] = 0;
+ gui[i + 9] = 0;
+ gui[i + 10] = 1;
+ gui[i + 11] = 0;
+
+ gui[i + 12] = 0;
+ gui[i + 13] = 0;
+ gui[i + 14] = 0;
+ gui[i + 15] = 1;
+ }
+ }
+ } else {
+ Transform3D v = value;
+ gui[0] = v.basis.elements[0][0];
+ gui[1] = v.basis.elements[1][0];
+ gui[2] = v.basis.elements[2][0];
+ gui[3] = 0;
+
+ gui[4] = v.basis.elements[0][1];
+ gui[5] = v.basis.elements[1][1];
+ gui[6] = v.basis.elements[2][1];
+ gui[7] = 0;
+
+ gui[8] = v.basis.elements[0][2];
+ gui[9] = v.basis.elements[1][2];
+ gui[10] = v.basis.elements[2][2];
+ gui[11] = 0;
+
+ gui[12] = v.origin.x;
+ gui[13] = v.origin.y;
+ gui[14] = v.origin.z;
+ gui[15] = 1;
+ }
} break;
default: {
}
@@ -2094,19 +2468,23 @@ _FORCE_INLINE_ static void _fill_std140_ubo_value(ShaderLanguage::DataType type,
}
}
-_FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type, uint8_t *data) {
+_FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type, int p_array_size, uint8_t *data) {
+ if (p_array_size <= 0) {
+ p_array_size = 1;
+ }
+
switch (type) {
case ShaderLanguage::TYPE_BOOL:
case ShaderLanguage::TYPE_INT:
case ShaderLanguage::TYPE_UINT:
case ShaderLanguage::TYPE_FLOAT: {
- memset(data, 0, 4);
+ memset(data, 0, 4 * p_array_size);
} break;
case ShaderLanguage::TYPE_BVEC2:
case ShaderLanguage::TYPE_IVEC2:
case ShaderLanguage::TYPE_UVEC2:
case ShaderLanguage::TYPE_VEC2: {
- memset(data, 0, 8);
+ memset(data, 0, 8 * p_array_size);
} break;
case ShaderLanguage::TYPE_BVEC3:
case ShaderLanguage::TYPE_IVEC3:
@@ -2116,16 +2494,16 @@ _FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type,
case ShaderLanguage::TYPE_IVEC4:
case ShaderLanguage::TYPE_UVEC4:
case ShaderLanguage::TYPE_VEC4: {
- memset(data, 0, 16);
+ memset(data, 0, 16 * p_array_size);
} break;
case ShaderLanguage::TYPE_MAT2: {
- memset(data, 0, 32);
+ memset(data, 0, 32 * p_array_size);
} break;
case ShaderLanguage::TYPE_MAT3: {
- memset(data, 0, 48);
+ memset(data, 0, 48 * p_array_size);
} break;
case ShaderLanguage::TYPE_MAT4: {
- memset(data, 0, 64);
+ memset(data, 0, 64 * p_array_size);
} break;
default: {
@@ -2136,28 +2514,28 @@ _FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type,
void RendererStorageRD::MaterialData::update_uniform_buffer(const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Map<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color) {
bool uses_global_buffer = false;
- for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = p_uniforms.front(); E; E = E->next()) {
- if (E->get().order < 0) {
+ for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : p_uniforms) {
+ if (E.value.order < 0) {
continue; // texture, does not go here
}
- if (E->get().scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
+ if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
continue; //instance uniforms don't appear in the bufferr
}
- if (E->get().scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) {
+ if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) {
//this is a global variable, get the index to it
RendererStorageRD *rs = base_singleton;
- GlobalVariables::Variable *gv = rs->global_variables.variables.getptr(E->key());
+ GlobalVariables::Variable *gv = rs->global_variables.variables.getptr(E.key);
uint32_t index = 0;
if (gv) {
index = gv->buffer_index;
} else {
- WARN_PRINT("Shader uses global uniform '" + E->key() + "', but it was removed at some point. Material will not display correctly.");
+ WARN_PRINT("Shader uses global uniform '" + E.key + "', but it was removed at some point. Material will not display correctly.");
}
- uint32_t offset = p_uniform_offsets[E->get().order];
+ uint32_t offset = p_uniform_offsets[E.value.order];
uint32_t *intptr = (uint32_t *)&p_buffer[offset];
*intptr = index;
uses_global_buffer = true;
@@ -2165,30 +2543,30 @@ void RendererStorageRD::MaterialData::update_uniform_buffer(const Map<StringName
}
//regular uniform
- uint32_t offset = p_uniform_offsets[E->get().order];
+ uint32_t offset = p_uniform_offsets[E.value.order];
#ifdef DEBUG_ENABLED
- uint32_t size = ShaderLanguage::get_type_size(E->get().type);
+ uint32_t size = ShaderLanguage::get_type_size(E.value.type);
ERR_CONTINUE(offset + size > p_buffer_size);
#endif
uint8_t *data = &p_buffer[offset];
- const Map<StringName, Variant>::Element *V = p_parameters.find(E->key());
+ const Map<StringName, Variant>::Element *V = p_parameters.find(E.key);
if (V) {
//user provided
- _fill_std140_variant_ubo_value(E->get().type, V->get(), data, p_use_linear_color);
+ _fill_std140_variant_ubo_value(E.value.type, E.value.array_size, V->get(), data, p_use_linear_color);
- } else if (E->get().default_value.size()) {
+ } else if (E.value.default_value.size()) {
//default value
- _fill_std140_ubo_value(E->get().type, E->get().default_value, data);
- //value=E->get().default_value;
+ _fill_std140_ubo_value(E.value.type, E.value.default_value, data);
+ //value=E.value.default_value;
} else {
//zero because it was not provided
- if (E->get().type == ShaderLanguage::TYPE_VEC4 && E->get().hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) {
+ if (E.value.type == ShaderLanguage::TYPE_VEC4 && E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) {
//colors must be set as black, with alpha as 1.0
- _fill_std140_variant_ubo_value(E->get().type, Color(0, 0, 0, 1), data, p_use_linear_color);
+ _fill_std140_variant_ubo_value(E.value.type, E.value.array_size, Color(0, 0, 0, 1), data, p_use_linear_color);
} else {
//else just zero it out
- _fill_std140_ubo_empty(E->get().type, data);
+ _fill_std140_ubo_empty(E.value.type, E.value.array_size, data);
}
}
}
@@ -2215,8 +2593,8 @@ RendererStorageRD::MaterialData::~MaterialData() {
//unregister global textures
RendererStorageRD *rs = base_singleton;
- for (Map<StringName, uint64_t>::Element *E = used_global_textures.front(); E; E = E->next()) {
- GlobalVariables::Variable *v = rs->global_variables.variables.getptr(E->key());
+ for (const KeyValue<StringName, uint64_t> &E : used_global_textures) {
+ GlobalVariables::Variable *v = rs->global_variables.variables.getptr(E.key);
if (v) {
v->texture_materials.erase(self);
}
@@ -2241,10 +2619,11 @@ void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Vari
bool uses_global_textures = false;
global_textures_pass++;
- for (int i = 0; i < p_texture_uniforms.size(); i++) {
+ for (int i = 0, k = 0; i < p_texture_uniforms.size(); i++) {
const StringName &uniform_name = p_texture_uniforms[i].name;
+ int uniform_array_size = p_texture_uniforms[i].array_size;
- RID texture;
+ Vector<RID> textures;
if (p_texture_uniforms[i].global) {
RendererStorageRD *rs = base_singleton;
@@ -2265,31 +2644,51 @@ void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Vari
E->get() = global_textures_pass;
}
- texture = v->override.get_type() != Variant::NIL ? v->override : v->value;
+ textures.push_back(v->override.get_type() != Variant::NIL ? v->override : v->value);
}
} else {
WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it was removed at some point. Material will not display correctly.");
}
} else {
- if (!texture.is_valid()) {
- const Map<StringName, Variant>::Element *V = p_parameters.find(uniform_name);
- if (V) {
- texture = V->get();
+ const Map<StringName, Variant>::Element *V = p_parameters.find(uniform_name);
+ if (V) {
+ if (V->get().is_array()) {
+ Array array = (Array)V->get();
+ if (uniform_array_size > 0) {
+ for (int j = 0; j < array.size(); j++) {
+ textures.push_back(array[j]);
+ }
+ } else {
+ if (array.size() > 0) {
+ textures.push_back(array[0]);
+ }
+ }
+ } else {
+ textures.push_back(V->get());
}
}
- if (!texture.is_valid()) {
+ if (uniform_array_size > 0) {
+ if (textures.size() < uniform_array_size) {
+ const Map<StringName, RID>::Element *W = p_default_textures.find(uniform_name);
+ if (W) {
+ for (int j = textures.size(); j < uniform_array_size; j++) {
+ textures.push_back(W->get());
+ }
+ }
+ }
+ } else if (textures.is_empty()) {
const Map<StringName, RID>::Element *W = p_default_textures.find(uniform_name);
if (W) {
- texture = W->get();
+ textures.push_back(W->get());
}
}
}
RID rd_texture;
- if (texture.is_null()) {
+ if (textures.is_empty()) {
//check default usage
switch (p_texture_uniforms[i].hint) {
case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK:
@@ -2306,45 +2705,55 @@ void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Vari
rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE);
} break;
}
+#ifdef TOOLS_ENABLED
+ if (roughness_detect_texture && normal_detect_texture && normal_detect_texture->path != String()) {
+ roughness_detect_texture->detect_roughness_callback(roughness_detect_texture->detect_roughness_callback_ud, normal_detect_texture->path, roughness_channel);
+ }
+#endif
+ if (uniform_array_size > 0) {
+ for (int j = 0; j < uniform_array_size; j++) {
+ p_textures[k++] = rd_texture;
+ }
+ } else {
+ p_textures[k++] = rd_texture;
+ }
} else {
bool srgb = p_use_linear_color && (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ALBEDO || p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO);
- Texture *tex = singleton->texture_owner.getornull(texture);
+ for (int j = 0; j < textures.size(); j++) {
+ Texture *tex = singleton->texture_owner.get_or_null(textures[j]);
- if (tex) {
- rd_texture = (srgb && tex->rd_texture_srgb.is_valid()) ? tex->rd_texture_srgb : tex->rd_texture;
+ if (tex) {
+ rd_texture = (srgb && tex->rd_texture_srgb.is_valid()) ? tex->rd_texture_srgb : tex->rd_texture;
#ifdef TOOLS_ENABLED
- if (tex->detect_3d_callback && p_use_linear_color) {
- tex->detect_3d_callback(tex->detect_3d_callback_ud);
- }
- if (tex->detect_normal_callback && (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL || p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL)) {
- if (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL) {
- normal_detect_texture = tex;
+ if (tex->detect_3d_callback && p_use_linear_color) {
+ tex->detect_3d_callback(tex->detect_3d_callback_ud);
}
- tex->detect_normal_callback(tex->detect_normal_callback_ud);
+ if (tex->detect_normal_callback && (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL || p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL)) {
+ if (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL) {
+ normal_detect_texture = tex;
+ }
+ tex->detect_normal_callback(tex->detect_normal_callback_ud);
+ }
+ if (tex->detect_roughness_callback && (p_texture_uniforms[i].hint >= ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_R || p_texture_uniforms[i].hint <= ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_GRAY)) {
+ //find the normal texture
+ roughness_detect_texture = tex;
+ roughness_channel = RS::TextureDetectRoughnessChannel(p_texture_uniforms[i].hint - ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_R);
+ }
+#endif
}
- if (tex->detect_roughness_callback && (p_texture_uniforms[i].hint >= ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_R || p_texture_uniforms[i].hint <= ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_GRAY)) {
- //find the normal texture
- roughness_detect_texture = tex;
- roughness_channel = RS::TextureDetectRoughnessChannel(p_texture_uniforms[i].hint - ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_R);
+ if (rd_texture.is_null()) {
+ rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE);
+ }
+#ifdef TOOLS_ENABLED
+ if (roughness_detect_texture && normal_detect_texture && normal_detect_texture->path != String()) {
+ roughness_detect_texture->detect_roughness_callback(roughness_detect_texture->detect_roughness_callback_ud, normal_detect_texture->path, roughness_channel);
}
-
#endif
- }
-
- if (rd_texture.is_null()) {
- //wtf
- rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE);
+ p_textures[k++] = rd_texture;
}
}
-
- p_textures[i] = rd_texture;
}
-#ifdef TOOLS_ENABLED
- if (roughness_detect_texture && normal_detect_texture && normal_detect_texture->path != String()) {
- roughness_detect_texture->detect_roughness_callback(roughness_detect_texture->detect_roughness_callback_ud, normal_detect_texture->path, roughness_channel);
- }
-#endif
{
//for textures no longer used, unregister them
List<Map<StringName, uint64_t>::Element *> to_delete;
@@ -2412,7 +2821,10 @@ bool RendererStorageRD::MaterialData::update_parameters_uniform_set(const Map<St
RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw(), p_barrier);
}
- uint32_t tex_uniform_count = p_texture_uniforms.size();
+ uint32_t tex_uniform_count = 0U;
+ for (int i = 0; i < p_texture_uniforms.size(); i++) {
+ tex_uniform_count += uint32_t(p_texture_uniforms[i].array_size > 0 ? p_texture_uniforms[i].array_size : 1);
+ }
if ((uint32_t)texture_cache.size() != tex_uniform_count || p_textures_dirty) {
texture_cache.resize(tex_uniform_count);
@@ -2452,11 +2864,19 @@ bool RendererStorageRD::MaterialData::update_parameters_uniform_set(const Map<St
}
const RID *textures = texture_cache.ptrw();
- for (uint32_t i = 0; i < tex_uniform_count; i++) {
+ for (int i = 0, k = 0; i < p_texture_uniforms.size(); i++) {
+ const int array_size = p_texture_uniforms[i].array_size;
+
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 1 + i;
- u.ids.push_back(textures[i]);
+ u.binding = 1 + k;
+ if (array_size > 0) {
+ for (int j = 0; j < array_size; j++) {
+ u.ids.push_back(textures[k++]);
+ }
+ } else {
+ u.ids.push_back(textures[k++]);
+ }
uniforms.push_back(u);
}
}
@@ -2470,14 +2890,14 @@ bool RendererStorageRD::MaterialData::update_parameters_uniform_set(const Map<St
void RendererStorageRD::_material_uniform_set_erased(const RID &p_set, void *p_material) {
RID rid = *(RID *)p_material;
- Material *material = base_singleton->material_owner.getornull(rid);
+ Material *material = base_singleton->material_owner.get_or_null(rid);
if (material) {
material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL);
}
}
void RendererStorageRD::material_force_update_textures(RID p_material, ShaderType p_shader_type) {
- Material *material = material_owner.getornull(p_material);
+ Material *material = material_owner.get_or_null(p_material);
if (material->shader_type != p_shader_type) {
return;
}
@@ -2518,7 +2938,7 @@ void RendererStorageRD::mesh_initialize(RID p_rid) {
void RendererStorageRD::mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) {
ERR_FAIL_COND(p_blend_shape_count < 0);
- Mesh *mesh = mesh_owner.getornull(p_mesh);
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
ERR_FAIL_COND(!mesh);
ERR_FAIL_COND(mesh->surface_count > 0); //surfaces already exist
@@ -2528,7 +2948,7 @@ void RendererStorageRD::mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape
/// Returns stride
void RendererStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) {
- Mesh *mesh = mesh_owner.getornull(p_mesh);
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
ERR_FAIL_COND(!mesh);
ERR_FAIL_COND(mesh->surface_count == RS::MAX_MESH_SURFACES);
@@ -2732,13 +3152,13 @@ void RendererStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_su
}
int RendererStorageRD::mesh_get_blend_shape_count(RID p_mesh) const {
- const Mesh *mesh = mesh_owner.getornull(p_mesh);
+ const Mesh *mesh = mesh_owner.get_or_null(p_mesh);
ERR_FAIL_COND_V(!mesh, -1);
return mesh->blend_shape_count;
}
void RendererStorageRD::mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) {
- Mesh *mesh = mesh_owner.getornull(p_mesh);
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
ERR_FAIL_COND(!mesh);
ERR_FAIL_INDEX((int)p_mode, 2);
@@ -2746,13 +3166,13 @@ void RendererStorageRD::mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode
}
RS::BlendShapeMode RendererStorageRD::mesh_get_blend_shape_mode(RID p_mesh) const {
- Mesh *mesh = mesh_owner.getornull(p_mesh);
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
ERR_FAIL_COND_V(!mesh, RS::BLEND_SHAPE_MODE_NORMALIZED);
return mesh->blend_shape_mode;
}
void RendererStorageRD::mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
- Mesh *mesh = mesh_owner.getornull(p_mesh);
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
ERR_FAIL_COND(!mesh);
ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
ERR_FAIL_COND(p_data.size() == 0);
@@ -2763,7 +3183,7 @@ void RendererStorageRD::mesh_surface_update_vertex_region(RID p_mesh, int p_surf
}
void RendererStorageRD::mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
- Mesh *mesh = mesh_owner.getornull(p_mesh);
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
ERR_FAIL_COND(!mesh);
ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
ERR_FAIL_COND(p_data.size() == 0);
@@ -2775,7 +3195,7 @@ void RendererStorageRD::mesh_surface_update_attribute_region(RID p_mesh, int p_s
}
void RendererStorageRD::mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
- Mesh *mesh = mesh_owner.getornull(p_mesh);
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
ERR_FAIL_COND(!mesh);
ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
ERR_FAIL_COND(p_data.size() == 0);
@@ -2787,7 +3207,7 @@ void RendererStorageRD::mesh_surface_update_skin_region(RID p_mesh, int p_surfac
}
void RendererStorageRD::mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) {
- Mesh *mesh = mesh_owner.getornull(p_mesh);
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
ERR_FAIL_COND(!mesh);
ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
mesh->surfaces[p_surface]->material = p_material;
@@ -2797,7 +3217,7 @@ void RendererStorageRD::mesh_surface_set_material(RID p_mesh, int p_surface, RID
}
RID RendererStorageRD::mesh_surface_get_material(RID p_mesh, int p_surface) const {
- Mesh *mesh = mesh_owner.getornull(p_mesh);
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
ERR_FAIL_COND_V(!mesh, RID());
ERR_FAIL_UNSIGNED_INDEX_V((uint32_t)p_surface, mesh->surface_count, RID());
@@ -2805,7 +3225,7 @@ RID RendererStorageRD::mesh_surface_get_material(RID p_mesh, int p_surface) cons
}
RS::SurfaceData RendererStorageRD::mesh_get_surface(RID p_mesh, int p_surface) const {
- Mesh *mesh = mesh_owner.getornull(p_mesh);
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
ERR_FAIL_COND_V(!mesh, RS::SurfaceData());
ERR_FAIL_UNSIGNED_INDEX_V((uint32_t)p_surface, mesh->surface_count, RS::SurfaceData());
@@ -2845,32 +3265,32 @@ RS::SurfaceData RendererStorageRD::mesh_get_surface(RID p_mesh, int p_surface) c
}
int RendererStorageRD::mesh_get_surface_count(RID p_mesh) const {
- Mesh *mesh = mesh_owner.getornull(p_mesh);
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
ERR_FAIL_COND_V(!mesh, 0);
return mesh->surface_count;
}
void RendererStorageRD::mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) {
- Mesh *mesh = mesh_owner.getornull(p_mesh);
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
ERR_FAIL_COND(!mesh);
mesh->custom_aabb = p_aabb;
}
AABB RendererStorageRD::mesh_get_custom_aabb(RID p_mesh) const {
- Mesh *mesh = mesh_owner.getornull(p_mesh);
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
ERR_FAIL_COND_V(!mesh, AABB());
return mesh->custom_aabb;
}
AABB RendererStorageRD::mesh_get_aabb(RID p_mesh, RID p_skeleton) {
- Mesh *mesh = mesh_owner.getornull(p_mesh);
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
ERR_FAIL_COND_V(!mesh, AABB());
if (mesh->custom_aabb != AABB()) {
return mesh->custom_aabb;
}
- Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
if (!skeleton || skeleton->size == 0) {
return mesh->aabb;
@@ -2968,16 +3388,16 @@ AABB RendererStorageRD::mesh_get_aabb(RID p_mesh, RID p_skeleton) {
}
void RendererStorageRD::mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) {
- Mesh *mesh = mesh_owner.getornull(p_mesh);
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
ERR_FAIL_COND(!mesh);
- Mesh *shadow_mesh = mesh_owner.getornull(mesh->shadow_mesh);
+ Mesh *shadow_mesh = mesh_owner.get_or_null(mesh->shadow_mesh);
if (shadow_mesh) {
shadow_mesh->shadow_owners.erase(mesh);
}
mesh->shadow_mesh = p_shadow_mesh;
- shadow_mesh = mesh_owner.getornull(mesh->shadow_mesh);
+ shadow_mesh = mesh_owner.get_or_null(mesh->shadow_mesh);
if (shadow_mesh) {
shadow_mesh->shadow_owners.insert(mesh);
@@ -2987,7 +3407,7 @@ void RendererStorageRD::mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) {
}
void RendererStorageRD::mesh_clear(RID p_mesh) {
- Mesh *mesh = mesh_owner.getornull(p_mesh);
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
ERR_FAIL_COND(!mesh);
for (uint32_t i = 0; i < mesh->surface_count; i++) {
Mesh::Surface &s = *mesh->surfaces[i];
@@ -3041,7 +3461,7 @@ void RendererStorageRD::mesh_clear(RID p_mesh) {
}
bool RendererStorageRD::mesh_needs_instance(RID p_mesh, bool p_has_skeleton) {
- Mesh *mesh = mesh_owner.getornull(p_mesh);
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
ERR_FAIL_COND_V(!mesh, false);
return mesh->blend_shape_count > 0 || (mesh->has_bone_weights && p_has_skeleton);
@@ -3050,11 +3470,11 @@ bool RendererStorageRD::mesh_needs_instance(RID p_mesh, bool p_has_skeleton) {
/* MESH INSTANCE */
RID RendererStorageRD::mesh_instance_create(RID p_base) {
- Mesh *mesh = mesh_owner.getornull(p_base);
+ Mesh *mesh = mesh_owner.get_or_null(p_base);
ERR_FAIL_COND_V(!mesh, RID());
RID rid = mesh_instance_owner.make_rid();
- MeshInstance *mi = mesh_instance_owner.getornull(rid);
+ MeshInstance *mi = mesh_instance_owner.get_or_null(rid);
mi->mesh = mesh;
@@ -3069,7 +3489,7 @@ RID RendererStorageRD::mesh_instance_create(RID p_base) {
return rid;
}
void RendererStorageRD::mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) {
- MeshInstance *mi = mesh_instance_owner.getornull(p_mesh_instance);
+ MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance);
if (mi->skeleton == p_skeleton) {
return;
}
@@ -3079,7 +3499,7 @@ void RendererStorageRD::mesh_instance_set_skeleton(RID p_mesh_instance, RID p_sk
}
void RendererStorageRD::mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) {
- MeshInstance *mi = mesh_instance_owner.getornull(p_mesh_instance);
+ MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance);
ERR_FAIL_COND(!mi);
ERR_FAIL_INDEX(p_shape, (int)mi->blend_weights.size());
mi->blend_weights[p_shape] = p_weight;
@@ -3151,7 +3571,7 @@ void RendererStorageRD::_mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh,
}
void RendererStorageRD::mesh_instance_check_for_update(RID p_mesh_instance) {
- MeshInstance *mi = mesh_instance_owner.getornull(p_mesh_instance);
+ MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance);
bool needs_update = mi->dirty;
@@ -3165,7 +3585,7 @@ void RendererStorageRD::mesh_instance_check_for_update(RID p_mesh_instance) {
}
if (!needs_update && mi->skeleton.is_valid()) {
- Skeleton *sk = skeleton_owner.getornull(mi->skeleton);
+ Skeleton *sk = skeleton_owner.get_or_null(mi->skeleton);
if (sk && sk->version != mi->skeleton_version) {
needs_update = true;
}
@@ -3196,7 +3616,7 @@ void RendererStorageRD::update_mesh_instances() {
while (dirty_mesh_instance_arrays.first()) {
MeshInstance *mi = dirty_mesh_instance_arrays.first()->self();
- Skeleton *sk = skeleton_owner.getornull(mi->skeleton);
+ Skeleton *sk = skeleton_owner.get_or_null(mi->skeleton);
for (uint32_t i = 0; i < mi->surfaces.size(); i++) {
if (mi->surfaces[i].uniform_set == RID() || mi->mesh->surfaces[i]->uniform_set == RID()) {
@@ -3443,7 +3863,7 @@ void RendererStorageRD::multimesh_initialize(RID p_rid) {
}
void RendererStorageRD::multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors, bool p_use_custom_data) {
- MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_COND(!multimesh);
if (multimesh->instances == p_instances && multimesh->xform_format == p_transform_format && multimesh->uses_colors == p_use_colors && multimesh->uses_custom_data == p_use_custom_data) {
@@ -3486,13 +3906,13 @@ void RendererStorageRD::multimesh_allocate_data(RID p_multimesh, int p_instances
}
int RendererStorageRD::multimesh_get_instance_count(RID p_multimesh) const {
- MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_COND_V(!multimesh, 0);
return multimesh->instances;
}
void RendererStorageRD::multimesh_set_mesh(RID p_multimesh, RID p_mesh) {
- MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_COND(!multimesh);
if (multimesh->mesh == p_mesh) {
return;
@@ -3539,7 +3959,7 @@ void RendererStorageRD::_multimesh_make_local(MultiMesh *multimesh) const {
memcpy(w, r, buffer.size());
}
} else {
- memset(w, 0, multimesh->instances * multimesh->stride_cache * sizeof(float));
+ memset(w, 0, (size_t)multimesh->instances * multimesh->stride_cache * sizeof(float));
}
}
uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
@@ -3638,7 +4058,7 @@ void RendererStorageRD::_multimesh_re_create_aabb(MultiMesh *multimesh, const fl
}
void RendererStorageRD::multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) {
- MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_COND(!multimesh);
ERR_FAIL_INDEX(p_index, multimesh->instances);
ERR_FAIL_COND(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_3D);
@@ -3668,7 +4088,7 @@ void RendererStorageRD::multimesh_instance_set_transform(RID p_multimesh, int p_
}
void RendererStorageRD::multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) {
- MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_COND(!multimesh);
ERR_FAIL_INDEX(p_index, multimesh->instances);
ERR_FAIL_COND(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_2D);
@@ -3694,7 +4114,7 @@ void RendererStorageRD::multimesh_instance_set_transform_2d(RID p_multimesh, int
}
void RendererStorageRD::multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) {
- MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_COND(!multimesh);
ERR_FAIL_INDEX(p_index, multimesh->instances);
ERR_FAIL_COND(!multimesh->uses_colors);
@@ -3716,7 +4136,7 @@ void RendererStorageRD::multimesh_instance_set_color(RID p_multimesh, int p_inde
}
void RendererStorageRD::multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) {
- MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_COND(!multimesh);
ERR_FAIL_INDEX(p_index, multimesh->instances);
ERR_FAIL_COND(!multimesh->uses_custom_data);
@@ -3738,14 +4158,14 @@ void RendererStorageRD::multimesh_instance_set_custom_data(RID p_multimesh, int
}
RID RendererStorageRD::multimesh_get_mesh(RID p_multimesh) const {
- MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_COND_V(!multimesh, RID());
return multimesh->mesh;
}
Transform3D RendererStorageRD::multimesh_instance_get_transform(RID p_multimesh, int p_index) const {
- MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_COND_V(!multimesh, Transform3D());
ERR_FAIL_INDEX_V(p_index, multimesh->instances, Transform3D());
ERR_FAIL_COND_V(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_3D, Transform3D());
@@ -3776,7 +4196,7 @@ Transform3D RendererStorageRD::multimesh_instance_get_transform(RID p_multimesh,
}
Transform2D RendererStorageRD::multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const {
- MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_COND_V(!multimesh, Transform2D());
ERR_FAIL_INDEX_V(p_index, multimesh->instances, Transform2D());
ERR_FAIL_COND_V(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_2D, Transform2D());
@@ -3801,7 +4221,7 @@ Transform2D RendererStorageRD::multimesh_instance_get_transform_2d(RID p_multime
}
Color RendererStorageRD::multimesh_instance_get_color(RID p_multimesh, int p_index) const {
- MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_COND_V(!multimesh, Color());
ERR_FAIL_INDEX_V(p_index, multimesh->instances, Color());
ERR_FAIL_COND_V(!multimesh->uses_colors, Color());
@@ -3824,7 +4244,7 @@ Color RendererStorageRD::multimesh_instance_get_color(RID p_multimesh, int p_ind
}
Color RendererStorageRD::multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const {
- MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_COND_V(!multimesh, Color());
ERR_FAIL_INDEX_V(p_index, multimesh->instances, Color());
ERR_FAIL_COND_V(!multimesh->uses_custom_data, Color());
@@ -3847,7 +4267,7 @@ Color RendererStorageRD::multimesh_instance_get_custom_data(RID p_multimesh, int
}
void RendererStorageRD::multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) {
- MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_COND(!multimesh);
ERR_FAIL_COND(p_buffer.size() != (multimesh->instances * (int)multimesh->stride_cache));
@@ -3880,7 +4300,7 @@ void RendererStorageRD::multimesh_set_buffer(RID p_multimesh, const Vector<float
}
Vector<float> RendererStorageRD::multimesh_get_buffer(RID p_multimesh) const {
- MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_COND_V(!multimesh, Vector<float>());
if (multimesh->buffer.is_null()) {
return Vector<float>();
@@ -3903,7 +4323,7 @@ Vector<float> RendererStorageRD::multimesh_get_buffer(RID p_multimesh) const {
}
void RendererStorageRD::multimesh_set_visible_instances(RID p_multimesh, int p_visible) {
- MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_COND(!multimesh);
ERR_FAIL_COND(p_visible < -1 || p_visible > multimesh->instances);
if (multimesh->visible_instances == p_visible) {
@@ -3921,13 +4341,13 @@ void RendererStorageRD::multimesh_set_visible_instances(RID p_multimesh, int p_v
}
int RendererStorageRD::multimesh_get_visible_instances(RID p_multimesh) const {
- MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_COND_V(!multimesh, 0);
return multimesh->visible_instances;
}
AABB RendererStorageRD::multimesh_get_aabb(RID p_multimesh) const {
- MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_COND_V(!multimesh, AABB());
if (multimesh->aabb_dirty) {
const_cast<RendererStorageRD *>(this)->_update_dirty_multimeshes();
@@ -3952,13 +4372,13 @@ void RendererStorageRD::_update_dirty_multimeshes() {
if (multimesh->data_cache_used_dirty_regions > 32 || multimesh->data_cache_used_dirty_regions > visible_region_count / 2) {
//if there too many dirty regions, or represent the majority of regions, just copy all, else transfer cost piles up too much
- RD::get_singleton()->buffer_update(multimesh->buffer, 0, MIN(visible_region_count * region_size, multimesh->instances * multimesh->stride_cache * sizeof(float)), data);
+ RD::get_singleton()->buffer_update(multimesh->buffer, 0, MIN(visible_region_count * region_size, multimesh->instances * (uint32_t)multimesh->stride_cache * (uint32_t)sizeof(float)), data);
} else {
//not that many regions? update them all
for (uint32_t i = 0; i < visible_region_count; i++) {
if (multimesh->data_cache_dirty_regions[i]) {
- uint64_t offset = i * region_size;
- uint64_t size = multimesh->stride_cache * multimesh->instances * sizeof(float);
+ uint32_t offset = i * region_size;
+ uint32_t size = multimesh->stride_cache * (uint32_t)multimesh->instances * (uint32_t)sizeof(float);
RD::get_singleton()->buffer_update(multimesh->buffer, offset, MIN(region_size, size - offset), &data[i * region_size]);
}
}
@@ -3998,7 +4418,7 @@ void RendererStorageRD::particles_initialize(RID p_rid) {
}
void RendererStorageRD::particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) {
- Particles *particles = particles_owner.getornull(p_particles);
+ Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND(!particles);
if (particles->mode == p_mode) {
return;
@@ -4010,7 +4430,7 @@ void RendererStorageRD::particles_set_mode(RID p_particles, RS::ParticlesMode p_
}
void RendererStorageRD::particles_set_emitting(RID p_particles, bool p_emitting) {
- Particles *particles = particles_owner.getornull(p_particles);
+ Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND(!particles);
particles->emitting = p_emitting;
@@ -4018,7 +4438,7 @@ void RendererStorageRD::particles_set_emitting(RID p_particles, bool p_emitting)
bool RendererStorageRD::particles_get_emitting(RID p_particles) {
ERR_FAIL_COND_V_MSG(RSG::threaded, false, "This function should never be used with threaded rendering, as it stalls the renderer.");
- Particles *particles = particles_owner.getornull(p_particles);
+ Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND_V(!particles, false);
return particles->emitting;
@@ -4073,7 +4493,7 @@ void RendererStorageRD::_particles_free_data(Particles *particles) {
}
void RendererStorageRD::particles_set_amount(RID p_particles, int p_amount) {
- Particles *particles = particles_owner.getornull(p_particles);
+ Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND(!particles);
if (particles->amount == p_amount) {
@@ -4093,55 +4513,56 @@ void RendererStorageRD::particles_set_amount(RID p_particles, int p_amount) {
}
void RendererStorageRD::particles_set_lifetime(RID p_particles, double p_lifetime) {
- Particles *particles = particles_owner.getornull(p_particles);
+ Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND(!particles);
particles->lifetime = p_lifetime;
}
void RendererStorageRD::particles_set_one_shot(RID p_particles, bool p_one_shot) {
- Particles *particles = particles_owner.getornull(p_particles);
+ Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND(!particles);
particles->one_shot = p_one_shot;
}
void RendererStorageRD::particles_set_pre_process_time(RID p_particles, double p_time) {
- Particles *particles = particles_owner.getornull(p_particles);
+ Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND(!particles);
particles->pre_process_time = p_time;
}
void RendererStorageRD::particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) {
- Particles *particles = particles_owner.getornull(p_particles);
+ Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND(!particles);
particles->explosiveness = p_ratio;
}
void RendererStorageRD::particles_set_randomness_ratio(RID p_particles, real_t p_ratio) {
- Particles *particles = particles_owner.getornull(p_particles);
+ Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND(!particles);
particles->randomness = p_ratio;
}
void RendererStorageRD::particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) {
- Particles *particles = particles_owner.getornull(p_particles);
+ Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND(!particles);
particles->custom_aabb = p_aabb;
particles->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
}
void RendererStorageRD::particles_set_speed_scale(RID p_particles, double p_scale) {
- Particles *particles = particles_owner.getornull(p_particles);
+ Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND(!particles);
particles->speed_scale = p_scale;
}
void RendererStorageRD::particles_set_use_local_coordinates(RID p_particles, bool p_enable) {
- Particles *particles = particles_owner.getornull(p_particles);
+ Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND(!particles);
particles->use_local_coords = p_enable;
+ particles->dependency.changed_notify(DEPENDENCY_CHANGED_PARTICLES);
}
void RendererStorageRD::particles_set_fixed_fps(RID p_particles, int p_fps) {
- Particles *particles = particles_owner.getornull(p_particles);
+ Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND(!particles);
particles->fixed_fps = p_fps;
@@ -4157,21 +4578,21 @@ void RendererStorageRD::particles_set_fixed_fps(RID p_particles, int p_fps) {
}
void RendererStorageRD::particles_set_interpolate(RID p_particles, bool p_enable) {
- Particles *particles = particles_owner.getornull(p_particles);
+ Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND(!particles);
particles->interpolate = p_enable;
}
void RendererStorageRD::particles_set_fractional_delta(RID p_particles, bool p_enable) {
- Particles *particles = particles_owner.getornull(p_particles);
+ Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND(!particles);
particles->fractional_delta = p_enable;
}
void RendererStorageRD::particles_set_trails(RID p_particles, bool p_enable, double p_length) {
- Particles *particles = particles_owner.getornull(p_particles);
+ Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND(!particles);
ERR_FAIL_COND(p_length < 0.1);
p_length = MIN(10.0, p_length);
@@ -4190,7 +4611,7 @@ void RendererStorageRD::particles_set_trails(RID p_particles, bool p_enable, dou
}
void RendererStorageRD::particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) {
- Particles *particles = particles_owner.getornull(p_particles);
+ Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND(!particles);
if (particles->trail_bind_pose_buffer.is_valid() && particles->trail_bind_poses.size() != p_bind_poses.size()) {
_particles_free_data(particles);
@@ -4207,49 +4628,49 @@ void RendererStorageRD::particles_set_trail_bind_poses(RID p_particles, const Ve
}
void RendererStorageRD::particles_set_collision_base_size(RID p_particles, real_t p_size) {
- Particles *particles = particles_owner.getornull(p_particles);
+ Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND(!particles);
particles->collision_base_size = p_size;
}
void RendererStorageRD::particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) {
- Particles *particles = particles_owner.getornull(p_particles);
+ Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND(!particles);
particles->transform_align = p_transform_align;
}
void RendererStorageRD::particles_set_process_material(RID p_particles, RID p_material) {
- Particles *particles = particles_owner.getornull(p_particles);
+ Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND(!particles);
particles->process_material = p_material;
}
void RendererStorageRD::particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) {
- Particles *particles = particles_owner.getornull(p_particles);
+ Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND(!particles);
particles->draw_order = p_order;
}
void RendererStorageRD::particles_set_draw_passes(RID p_particles, int p_passes) {
- Particles *particles = particles_owner.getornull(p_particles);
+ Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND(!particles);
particles->draw_passes.resize(p_passes);
}
void RendererStorageRD::particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) {
- Particles *particles = particles_owner.getornull(p_particles);
+ Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND(!particles);
ERR_FAIL_INDEX(p_pass, particles->draw_passes.size());
particles->draw_passes.write[p_pass] = p_mesh;
}
void RendererStorageRD::particles_restart(RID p_particles) {
- Particles *particles = particles_owner.getornull(p_particles);
+ Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND(!particles);
particles->restart_request = true;
@@ -4273,7 +4694,7 @@ void RendererStorageRD::_particles_allocate_emission_buffer(Particles *particles
}
void RendererStorageRD::particles_set_subemitter(RID p_particles, RID p_subemitter_particles) {
- Particles *particles = particles_owner.getornull(p_particles);
+ Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND(!particles);
ERR_FAIL_COND(p_particles == p_subemitter_particles);
@@ -4286,7 +4707,7 @@ void RendererStorageRD::particles_set_subemitter(RID p_particles, RID p_subemitt
}
void RendererStorageRD::particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) {
- Particles *particles = particles_owner.getornull(p_particles);
+ Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND(!particles);
ERR_FAIL_COND(particles->amount == 0);
@@ -4329,7 +4750,7 @@ void RendererStorageRD::particles_emit(RID p_particles, const Transform3D &p_tra
}
void RendererStorageRD::particles_request_process(RID p_particles) {
- Particles *particles = particles_owner.getornull(p_particles);
+ Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND(!particles);
if (!particles->dirty) {
@@ -4344,7 +4765,7 @@ AABB RendererStorageRD::particles_get_current_aabb(RID p_particles) {
WARN_PRINT_ONCE("Calling this function with threaded rendering enabled stalls the renderer, use with care.");
}
- const Particles *particles = particles_owner.getornull(p_particles);
+ const Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND_V(!particles, AABB());
int total_amount = particles->amount;
@@ -4352,10 +4773,8 @@ AABB RendererStorageRD::particles_get_current_aabb(RID p_particles) {
total_amount *= particles->trail_bind_poses.size();
}
- Vector<ParticleData> data;
- data.resize(total_amount);
-
Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(particles->particle_buffer);
+ ERR_FAIL_COND_V(buffer.size() != (int)(total_amount * sizeof(ParticleData)), AABB());
Transform3D inv = particles->emission_transform.affine_inverse();
@@ -4363,7 +4782,7 @@ AABB RendererStorageRD::particles_get_current_aabb(RID p_particles) {
if (buffer.size()) {
bool first = true;
- const ParticleData *particle_data = (const ParticleData *)data.ptr();
+ const ParticleData *particle_data = reinterpret_cast<const ParticleData *>(buffer.ptr());
for (int i = 0; i < total_amount; i++) {
if (particle_data[i].active) {
Vector3 pos = Vector3(particle_data[i].xform[12], particle_data[i].xform[13], particle_data[i].xform[14]);
@@ -4394,28 +4813,28 @@ AABB RendererStorageRD::particles_get_current_aabb(RID p_particles) {
}
AABB RendererStorageRD::particles_get_aabb(RID p_particles) const {
- const Particles *particles = particles_owner.getornull(p_particles);
+ const Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND_V(!particles, AABB());
return particles->custom_aabb;
}
void RendererStorageRD::particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) {
- Particles *particles = particles_owner.getornull(p_particles);
+ Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND(!particles);
particles->emission_transform = p_transform;
}
int RendererStorageRD::particles_get_draw_passes(RID p_particles) const {
- const Particles *particles = particles_owner.getornull(p_particles);
+ const Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND_V(!particles, 0);
return particles->draw_passes.size();
}
RID RendererStorageRD::particles_get_draw_pass_mesh(RID p_particles, int p_pass) const {
- const Particles *particles = particles_owner.getornull(p_particles);
+ const Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND_V(!particles, RID());
ERR_FAIL_INDEX_V(p_pass, particles->draw_passes.size(), RID());
@@ -4423,19 +4842,19 @@ RID RendererStorageRD::particles_get_draw_pass_mesh(RID p_particles, int p_pass)
}
void RendererStorageRD::particles_add_collision(RID p_particles, RID p_particles_collision_instance) {
- Particles *particles = particles_owner.getornull(p_particles);
+ Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND(!particles);
particles->collisions.insert(p_particles_collision_instance);
}
void RendererStorageRD::particles_remove_collision(RID p_particles, RID p_particles_collision_instance) {
- Particles *particles = particles_owner.getornull(p_particles);
+ Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND(!particles);
particles->collisions.erase(p_particles_collision_instance);
}
void RendererStorageRD::particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) {
- Particles *particles = particles_owner.getornull(p_particles);
+ Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND(!particles);
particles->has_sdf_collision = p_enable;
particles->sdf_collision_transform = p_xform;
@@ -4477,7 +4896,7 @@ void RendererStorageRD::_particles_process(Particles *p_particles, double p_delt
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 3;
- Particles *sub_emitter = particles_owner.getornull(p_particles->sub_emitter);
+ Particles *sub_emitter = particles_owner.get_or_null(p_particles->sub_emitter);
if (sub_emitter) {
if (sub_emitter->emission_buffer == nullptr) { //no emission buffer, allocate emission buffer
_particles_allocate_emission_buffer(sub_emitter);
@@ -4594,11 +5013,11 @@ void RendererStorageRD::_particles_process(Particles *p_particles, double p_delt
uint32_t collision_3d_textures_used = 0;
for (const Set<RID>::Element *E = p_particles->collisions.front(); E; E = E->next()) {
- ParticlesCollisionInstance *pci = particles_collision_instance_owner.getornull(E->get());
+ ParticlesCollisionInstance *pci = particles_collision_instance_owner.get_or_null(E->get());
if (!pci || !pci->active) {
continue;
}
- ParticlesCollision *pc = particles_collision_owner.getornull(pci->collision);
+ ParticlesCollision *pc = particles_collision_owner.get_or_null(pci->collision);
ERR_CONTINUE(!pc);
Transform3D to_collider = pci->transform;
@@ -4746,7 +5165,7 @@ void RendererStorageRD::_particles_process(Particles *p_particles, double p_delt
for (uint32_t i = 0; i < ParticlesFrameParams::MAX_3D_TEXTURES; i++) {
RID rd_tex;
if (i < collision_3d_textures_used) {
- Texture *t = texture_owner.getornull(collision_3d_textures[i]);
+ Texture *t = texture_owner.get_or_null(collision_3d_textures[i]);
if (t && t->type == Texture::TYPE_3D) {
rd_tex = t->rd_texture;
}
@@ -4791,7 +5210,7 @@ void RendererStorageRD::_particles_process(Particles *p_particles, double p_delt
p_particles->force_sub_emit = false; //reset
- Particles *sub_emitter = particles_owner.getornull(p_particles->sub_emitter);
+ Particles *sub_emitter = particles_owner.get_or_null(p_particles->sub_emitter);
if (sub_emitter && sub_emitter->emission_storage_buffer.is_valid()) {
// print_line("updating subemitter buffer");
@@ -4848,7 +5267,7 @@ void RendererStorageRD::_particles_process(Particles *p_particles, double p_delt
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_particles->particles_material_uniform_set, 1);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_particles->collision_textures_uniform_set, 2);
- if (m->uniform_set.is_valid()) {
+ if (m->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(m->uniform_set)) {
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, m->uniform_set, 3);
}
@@ -4871,7 +5290,7 @@ void RendererStorageRD::_particles_process(Particles *p_particles, double p_delt
}
void RendererStorageRD::particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) {
- Particles *particles = particles_owner.getornull(p_particles);
+ Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND(!particles);
if (particles->draw_order != RS::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY) {
@@ -5229,7 +5648,7 @@ void RendererStorageRD::update_particles() {
bool RendererStorageRD::particles_is_inactive(RID p_particles) const {
ERR_FAIL_COND_V_MSG(RSG::threaded, false, "This function should never be used with threaded rendering, as it stalls the renderer.");
- const Particles *particles = particles_owner.getornull(p_particles);
+ const Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND_V(!particles, false);
return !particles->emitting && particles->inactive;
}
@@ -5299,36 +5718,36 @@ void RendererStorageRD::ParticlesShaderData::set_default_texture_param(const Str
void RendererStorageRD::ParticlesShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
Map<int, StringName> order;
- for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) {
- if (E->get().scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E->get().scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
+ for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
+ if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
continue;
}
- if (E->get().texture_order >= 0) {
- order[E->get().texture_order + 100000] = E->key();
+ if (E.value.texture_order >= 0) {
+ order[E.value.texture_order + 100000] = E.key;
} else {
- order[E->get().order] = E->key();
+ order[E.value.order] = E.key;
}
}
- for (Map<int, StringName>::Element *E = order.front(); E; E = E->next()) {
- PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E->get()]);
- pi.name = E->get();
+ for (const KeyValue<int, StringName> &E : order) {
+ PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]);
+ pi.name = E.value;
p_param_list->push_back(pi);
}
}
void RendererStorageRD::ParticlesShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const {
- for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) {
- if (E->get().scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
+ for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
+ if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
continue;
}
RendererStorage::InstanceShaderParam p;
- p.info = ShaderLanguage::uniform_to_property_info(E->get());
- p.info.name = E->key(); //supply name
- p.index = E->get().instance_index;
- p.default_value = ShaderLanguage::constant_value_to_variant(E->get().default_value, E->get().type, E->get().hint);
+ p.info = ShaderLanguage::uniform_to_property_info(E.value);
+ p.info.name = E.key; //supply name
+ p.index = E.value.instance_index;
+ p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint);
p_param_list->push_back(p);
}
}
@@ -5353,7 +5772,7 @@ Variant RendererStorageRD::ParticlesShaderData::get_default_parameter(const Stri
if (uniforms.has(p_parameter)) {
ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter];
Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value;
- return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.hint);
+ return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint);
}
return Variant();
}
@@ -5407,7 +5826,7 @@ void RendererStorageRD::particles_collision_initialize(RID p_rid) {
}
RID RendererStorageRD::particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const {
- ParticlesCollision *particles_collision = particles_collision_owner.getornull(p_particles_collision);
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
ERR_FAIL_COND_V(!particles_collision, RID());
ERR_FAIL_COND_V(particles_collision->type != RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE, RID());
@@ -5442,7 +5861,7 @@ RID RendererStorageRD::particles_collision_get_heightfield_framebuffer(RID p_par
}
void RendererStorageRD::particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) {
- ParticlesCollision *particles_collision = particles_collision_owner.getornull(p_particles_collision);
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
ERR_FAIL_COND(!particles_collision);
if (p_type == particles_collision->type) {
@@ -5458,13 +5877,13 @@ void RendererStorageRD::particles_collision_set_collision_type(RID p_particles_c
}
void RendererStorageRD::particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) {
- ParticlesCollision *particles_collision = particles_collision_owner.getornull(p_particles_collision);
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
ERR_FAIL_COND(!particles_collision);
particles_collision->cull_mask = p_cull_mask;
}
void RendererStorageRD::particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) {
- ParticlesCollision *particles_collision = particles_collision_owner.getornull(p_particles_collision);
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
ERR_FAIL_COND(!particles_collision);
particles_collision->radius = p_radius;
@@ -5472,7 +5891,7 @@ void RendererStorageRD::particles_collision_set_sphere_radius(RID p_particles_co
}
void RendererStorageRD::particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) {
- ParticlesCollision *particles_collision = particles_collision_owner.getornull(p_particles_collision);
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
ERR_FAIL_COND(!particles_collision);
particles_collision->extents = p_extents;
@@ -5480,41 +5899,41 @@ void RendererStorageRD::particles_collision_set_box_extents(RID p_particles_coll
}
void RendererStorageRD::particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) {
- ParticlesCollision *particles_collision = particles_collision_owner.getornull(p_particles_collision);
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
ERR_FAIL_COND(!particles_collision);
particles_collision->attractor_strength = p_strength;
}
void RendererStorageRD::particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) {
- ParticlesCollision *particles_collision = particles_collision_owner.getornull(p_particles_collision);
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
ERR_FAIL_COND(!particles_collision);
particles_collision->attractor_directionality = p_directionality;
}
void RendererStorageRD::particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) {
- ParticlesCollision *particles_collision = particles_collision_owner.getornull(p_particles_collision);
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
ERR_FAIL_COND(!particles_collision);
particles_collision->attractor_attenuation = p_curve;
}
void RendererStorageRD::particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) {
- ParticlesCollision *particles_collision = particles_collision_owner.getornull(p_particles_collision);
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
ERR_FAIL_COND(!particles_collision);
particles_collision->field_texture = p_texture;
}
void RendererStorageRD::particles_collision_height_field_update(RID p_particles_collision) {
- ParticlesCollision *particles_collision = particles_collision_owner.getornull(p_particles_collision);
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
ERR_FAIL_COND(!particles_collision);
particles_collision->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
}
void RendererStorageRD::particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) {
- ParticlesCollision *particles_collision = particles_collision_owner.getornull(p_particles_collision);
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
ERR_FAIL_COND(!particles_collision);
ERR_FAIL_INDEX(p_resolution, RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_MAX);
@@ -5531,7 +5950,7 @@ void RendererStorageRD::particles_collision_set_height_field_resolution(RID p_pa
}
AABB RendererStorageRD::particles_collision_get_aabb(RID p_particles_collision) const {
- ParticlesCollision *particles_collision = particles_collision_owner.getornull(p_particles_collision);
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
ERR_FAIL_COND_V(!particles_collision, AABB());
switch (particles_collision->type) {
@@ -5554,13 +5973,13 @@ AABB RendererStorageRD::particles_collision_get_aabb(RID p_particles_collision)
}
Vector3 RendererStorageRD::particles_collision_get_extents(RID p_particles_collision) const {
- const ParticlesCollision *particles_collision = particles_collision_owner.getornull(p_particles_collision);
+ const ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
ERR_FAIL_COND_V(!particles_collision, Vector3());
return particles_collision->extents;
}
bool RendererStorageRD::particles_collision_is_heightfield(RID p_particles_collision) const {
- const ParticlesCollision *particles_collision = particles_collision_owner.getornull(p_particles_collision);
+ const ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
ERR_FAIL_COND_V(!particles_collision, false);
return particles_collision->type == RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE;
}
@@ -5571,12 +5990,12 @@ RID RendererStorageRD::particles_collision_instance_create(RID p_collision) {
return particles_collision_instance_owner.make_rid(pci);
}
void RendererStorageRD::particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) {
- ParticlesCollisionInstance *pci = particles_collision_instance_owner.getornull(p_collision_instance);
+ ParticlesCollisionInstance *pci = particles_collision_instance_owner.get_or_null(p_collision_instance);
ERR_FAIL_COND(!pci);
pci->transform = p_transform;
}
void RendererStorageRD::particles_collision_instance_set_active(RID p_collision_instance, bool p_active) {
- ParticlesCollisionInstance *pci = particles_collision_instance_owner.getornull(p_collision_instance);
+ ParticlesCollisionInstance *pci = particles_collision_instance_owner.get_or_null(p_collision_instance);
ERR_FAIL_COND(!pci);
pci->active = p_active;
}
@@ -5590,25 +6009,25 @@ void RendererStorageRD::visibility_notifier_initialize(RID p_notifier) {
visibility_notifier_owner.initialize_rid(p_notifier, VisibilityNotifier());
}
void RendererStorageRD::visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) {
- VisibilityNotifier *vn = visibility_notifier_owner.getornull(p_notifier);
+ VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_notifier);
ERR_FAIL_COND(!vn);
vn->aabb = p_aabb;
vn->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
}
void RendererStorageRD::visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable) {
- VisibilityNotifier *vn = visibility_notifier_owner.getornull(p_notifier);
+ VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_notifier);
ERR_FAIL_COND(!vn);
vn->enter_callback = p_enter_callbable;
vn->exit_callback = p_exit_callable;
}
AABB RendererStorageRD::visibility_notifier_get_aabb(RID p_notifier) const {
- const VisibilityNotifier *vn = visibility_notifier_owner.getornull(p_notifier);
+ const VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_notifier);
ERR_FAIL_COND_V(!vn, AABB());
return vn->aabb;
}
void RendererStorageRD::visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) {
- VisibilityNotifier *vn = visibility_notifier_owner.getornull(p_notifier);
+ VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_notifier);
ERR_FAIL_COND(!vn);
if (p_enter) {
@@ -5652,7 +6071,7 @@ void RendererStorageRD::_skeleton_make_dirty(Skeleton *skeleton) {
}
void RendererStorageRD::skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton) {
- Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
ERR_FAIL_COND(!skeleton);
ERR_FAIL_COND(p_bones < 0);
@@ -5695,14 +6114,14 @@ void RendererStorageRD::skeleton_allocate_data(RID p_skeleton, int p_bones, bool
}
int RendererStorageRD::skeleton_get_bone_count(RID p_skeleton) const {
- Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
ERR_FAIL_COND_V(!skeleton, 0);
return skeleton->size;
}
void RendererStorageRD::skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) {
- Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
ERR_FAIL_COND(!skeleton);
ERR_FAIL_INDEX(p_bone, skeleton->size);
@@ -5727,7 +6146,7 @@ void RendererStorageRD::skeleton_bone_set_transform(RID p_skeleton, int p_bone,
}
Transform3D RendererStorageRD::skeleton_bone_get_transform(RID p_skeleton, int p_bone) const {
- Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
ERR_FAIL_COND_V(!skeleton, Transform3D());
ERR_FAIL_INDEX_V(p_bone, skeleton->size, Transform3D());
@@ -5754,7 +6173,7 @@ Transform3D RendererStorageRD::skeleton_bone_get_transform(RID p_skeleton, int p
}
void RendererStorageRD::skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) {
- Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
ERR_FAIL_COND(!skeleton);
ERR_FAIL_INDEX(p_bone, skeleton->size);
@@ -5775,7 +6194,7 @@ void RendererStorageRD::skeleton_bone_set_transform_2d(RID p_skeleton, int p_bon
}
Transform2D RendererStorageRD::skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const {
- Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
ERR_FAIL_COND_V(!skeleton, Transform2D());
ERR_FAIL_INDEX_V(p_bone, skeleton->size, Transform2D());
@@ -5795,7 +6214,7 @@ Transform2D RendererStorageRD::skeleton_bone_get_transform_2d(RID p_skeleton, in
}
void RendererStorageRD::skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) {
- Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
ERR_FAIL_COND(!skeleton->use_2d);
@@ -5874,14 +6293,14 @@ void RendererStorageRD::spot_light_initialize(RID p_light) {
}
void RendererStorageRD::light_set_color(RID p_light, const Color &p_color) {
- Light *light = light_owner.getornull(p_light);
+ Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_COND(!light);
light->color = p_color;
}
void RendererStorageRD::light_set_param(RID p_light, RS::LightParam p_param, float p_value) {
- Light *light = light_owner.getornull(p_light);
+ Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_COND(!light);
ERR_FAIL_INDEX(p_param, RS::LIGHT_PARAM_MAX);
@@ -5916,7 +6335,7 @@ void RendererStorageRD::light_set_param(RID p_light, RS::LightParam p_param, flo
}
void RendererStorageRD::light_set_shadow(RID p_light, bool p_enabled) {
- Light *light = light_owner.getornull(p_light);
+ Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_COND(!light);
light->shadow = p_enabled;
@@ -5925,13 +6344,13 @@ void RendererStorageRD::light_set_shadow(RID p_light, bool p_enabled) {
}
void RendererStorageRD::light_set_shadow_color(RID p_light, const Color &p_color) {
- Light *light = light_owner.getornull(p_light);
+ Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_COND(!light);
light->shadow_color = p_color;
}
void RendererStorageRD::light_set_projector(RID p_light, RID p_texture) {
- Light *light = light_owner.getornull(p_light);
+ Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_COND(!light);
if (light->projector == p_texture) {
@@ -5953,14 +6372,14 @@ void RendererStorageRD::light_set_projector(RID p_light, RID p_texture) {
}
void RendererStorageRD::light_set_negative(RID p_light, bool p_enable) {
- Light *light = light_owner.getornull(p_light);
+ Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_COND(!light);
light->negative = p_enable;
}
void RendererStorageRD::light_set_cull_mask(RID p_light, uint32_t p_mask) {
- Light *light = light_owner.getornull(p_light);
+ Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_COND(!light);
light->cull_mask = p_mask;
@@ -5970,7 +6389,7 @@ void RendererStorageRD::light_set_cull_mask(RID p_light, uint32_t p_mask) {
}
void RendererStorageRD::light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) {
- Light *light = light_owner.getornull(p_light);
+ Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_COND(!light);
light->reverse_cull = p_enabled;
@@ -5980,7 +6399,7 @@ void RendererStorageRD::light_set_reverse_cull_face_mode(RID p_light, bool p_ena
}
void RendererStorageRD::light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) {
- Light *light = light_owner.getornull(p_light);
+ Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_COND(!light);
light->bake_mode = p_bake_mode;
@@ -5990,7 +6409,7 @@ void RendererStorageRD::light_set_bake_mode(RID p_light, RS::LightBakeMode p_bak
}
void RendererStorageRD::light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) {
- Light *light = light_owner.getornull(p_light);
+ Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_COND(!light);
light->max_sdfgi_cascade = p_cascade;
@@ -6000,7 +6419,7 @@ void RendererStorageRD::light_set_max_sdfgi_cascade(RID p_light, uint32_t p_casc
}
void RendererStorageRD::light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) {
- Light *light = light_owner.getornull(p_light);
+ Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_COND(!light);
light->omni_shadow_mode = p_mode;
@@ -6010,14 +6429,14 @@ void RendererStorageRD::light_omni_set_shadow_mode(RID p_light, RS::LightOmniSha
}
RS::LightOmniShadowMode RendererStorageRD::light_omni_get_shadow_mode(RID p_light) {
- const Light *light = light_owner.getornull(p_light);
+ const Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_COND_V(!light, RS::LIGHT_OMNI_SHADOW_CUBE);
return light->omni_shadow_mode;
}
void RendererStorageRD::light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) {
- Light *light = light_owner.getornull(p_light);
+ Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_COND(!light);
light->directional_shadow_mode = p_mode;
@@ -6026,7 +6445,7 @@ void RendererStorageRD::light_directional_set_shadow_mode(RID p_light, RS::Light
}
void RendererStorageRD::light_directional_set_blend_splits(RID p_light, bool p_enable) {
- Light *light = light_owner.getornull(p_light);
+ Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_COND(!light);
light->directional_blend_splits = p_enable;
@@ -6035,56 +6454,56 @@ void RendererStorageRD::light_directional_set_blend_splits(RID p_light, bool p_e
}
bool RendererStorageRD::light_directional_get_blend_splits(RID p_light) const {
- const Light *light = light_owner.getornull(p_light);
+ const Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_COND_V(!light, false);
return light->directional_blend_splits;
}
void RendererStorageRD::light_directional_set_sky_only(RID p_light, bool p_sky_only) {
- Light *light = light_owner.getornull(p_light);
+ Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_COND(!light);
light->directional_sky_only = p_sky_only;
}
bool RendererStorageRD::light_directional_is_sky_only(RID p_light) const {
- const Light *light = light_owner.getornull(p_light);
+ const Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_COND_V(!light, false);
return light->directional_sky_only;
}
RS::LightDirectionalShadowMode RendererStorageRD::light_directional_get_shadow_mode(RID p_light) {
- const Light *light = light_owner.getornull(p_light);
+ const Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL);
return light->directional_shadow_mode;
}
uint32_t RendererStorageRD::light_get_max_sdfgi_cascade(RID p_light) {
- const Light *light = light_owner.getornull(p_light);
+ const Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_COND_V(!light, 0);
return light->max_sdfgi_cascade;
}
RS::LightBakeMode RendererStorageRD::light_get_bake_mode(RID p_light) {
- const Light *light = light_owner.getornull(p_light);
+ const Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_COND_V(!light, RS::LIGHT_BAKE_DISABLED);
return light->bake_mode;
}
uint64_t RendererStorageRD::light_get_version(RID p_light) const {
- const Light *light = light_owner.getornull(p_light);
+ const Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_COND_V(!light, 0);
return light->version;
}
AABB RendererStorageRD::light_get_aabb(RID p_light) const {
- const Light *light = light_owner.getornull(p_light);
+ const Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_COND_V(!light, AABB());
switch (light->type) {
@@ -6115,7 +6534,7 @@ void RendererStorageRD::reflection_probe_initialize(RID p_reflection_probe) {
}
void RendererStorageRD::reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) {
- ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
ERR_FAIL_COND(!reflection_probe);
reflection_probe->update_mode = p_mode;
@@ -6123,35 +6542,35 @@ void RendererStorageRD::reflection_probe_set_update_mode(RID p_probe, RS::Reflec
}
void RendererStorageRD::reflection_probe_set_intensity(RID p_probe, float p_intensity) {
- ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
ERR_FAIL_COND(!reflection_probe);
reflection_probe->intensity = p_intensity;
}
void RendererStorageRD::reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) {
- ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
ERR_FAIL_COND(!reflection_probe);
reflection_probe->ambient_mode = p_mode;
}
void RendererStorageRD::reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) {
- ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
ERR_FAIL_COND(!reflection_probe);
reflection_probe->ambient_color = p_color;
}
void RendererStorageRD::reflection_probe_set_ambient_energy(RID p_probe, float p_energy) {
- ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
ERR_FAIL_COND(!reflection_probe);
reflection_probe->ambient_color_energy = p_energy;
}
void RendererStorageRD::reflection_probe_set_max_distance(RID p_probe, float p_distance) {
- ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
ERR_FAIL_COND(!reflection_probe);
reflection_probe->max_distance = p_distance;
@@ -6160,7 +6579,7 @@ void RendererStorageRD::reflection_probe_set_max_distance(RID p_probe, float p_d
}
void RendererStorageRD::reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) {
- ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
ERR_FAIL_COND(!reflection_probe);
if (reflection_probe->extents == p_extents) {
@@ -6171,7 +6590,7 @@ void RendererStorageRD::reflection_probe_set_extents(RID p_probe, const Vector3
}
void RendererStorageRD::reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) {
- ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
ERR_FAIL_COND(!reflection_probe);
reflection_probe->origin_offset = p_offset;
@@ -6179,7 +6598,7 @@ void RendererStorageRD::reflection_probe_set_origin_offset(RID p_probe, const Ve
}
void RendererStorageRD::reflection_probe_set_as_interior(RID p_probe, bool p_enable) {
- ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
ERR_FAIL_COND(!reflection_probe);
reflection_probe->interior = p_enable;
@@ -6187,14 +6606,14 @@ void RendererStorageRD::reflection_probe_set_as_interior(RID p_probe, bool p_ena
}
void RendererStorageRD::reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) {
- ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
ERR_FAIL_COND(!reflection_probe);
reflection_probe->box_projection = p_enable;
}
void RendererStorageRD::reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) {
- ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
ERR_FAIL_COND(!reflection_probe);
reflection_probe->enable_shadows = p_enable;
@@ -6202,7 +6621,7 @@ void RendererStorageRD::reflection_probe_set_enable_shadows(RID p_probe, bool p_
}
void RendererStorageRD::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) {
- ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
ERR_FAIL_COND(!reflection_probe);
reflection_probe->cull_mask = p_layers;
@@ -6210,7 +6629,7 @@ void RendererStorageRD::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_l
}
void RendererStorageRD::reflection_probe_set_resolution(RID p_probe, int p_resolution) {
- ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
ERR_FAIL_COND(!reflection_probe);
ERR_FAIL_COND(p_resolution < 32);
@@ -6218,7 +6637,7 @@ void RendererStorageRD::reflection_probe_set_resolution(RID p_probe, int p_resol
}
void RendererStorageRD::reflection_probe_set_lod_threshold(RID p_probe, float p_ratio) {
- ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
ERR_FAIL_COND(!reflection_probe);
reflection_probe->lod_threshold = p_ratio;
@@ -6227,7 +6646,7 @@ void RendererStorageRD::reflection_probe_set_lod_threshold(RID p_probe, float p_
}
AABB RendererStorageRD::reflection_probe_get_aabb(RID p_probe) const {
- const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
ERR_FAIL_COND_V(!reflection_probe, AABB());
AABB aabb;
@@ -6238,96 +6657,96 @@ AABB RendererStorageRD::reflection_probe_get_aabb(RID p_probe) const {
}
RS::ReflectionProbeUpdateMode RendererStorageRD::reflection_probe_get_update_mode(RID p_probe) const {
- const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
ERR_FAIL_COND_V(!reflection_probe, RS::REFLECTION_PROBE_UPDATE_ALWAYS);
return reflection_probe->update_mode;
}
uint32_t RendererStorageRD::reflection_probe_get_cull_mask(RID p_probe) const {
- const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
ERR_FAIL_COND_V(!reflection_probe, 0);
return reflection_probe->cull_mask;
}
Vector3 RendererStorageRD::reflection_probe_get_extents(RID p_probe) const {
- const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
ERR_FAIL_COND_V(!reflection_probe, Vector3());
return reflection_probe->extents;
}
Vector3 RendererStorageRD::reflection_probe_get_origin_offset(RID p_probe) const {
- const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
ERR_FAIL_COND_V(!reflection_probe, Vector3());
return reflection_probe->origin_offset;
}
bool RendererStorageRD::reflection_probe_renders_shadows(RID p_probe) const {
- const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
ERR_FAIL_COND_V(!reflection_probe, false);
return reflection_probe->enable_shadows;
}
float RendererStorageRD::reflection_probe_get_origin_max_distance(RID p_probe) const {
- const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
ERR_FAIL_COND_V(!reflection_probe, 0);
return reflection_probe->max_distance;
}
float RendererStorageRD::reflection_probe_get_lod_threshold(RID p_probe) const {
- const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
ERR_FAIL_COND_V(!reflection_probe, 0);
return reflection_probe->lod_threshold;
}
int RendererStorageRD::reflection_probe_get_resolution(RID p_probe) const {
- const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
ERR_FAIL_COND_V(!reflection_probe, 0);
return reflection_probe->resolution;
}
float RendererStorageRD::reflection_probe_get_intensity(RID p_probe) const {
- const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
ERR_FAIL_COND_V(!reflection_probe, 0);
return reflection_probe->intensity;
}
bool RendererStorageRD::reflection_probe_is_interior(RID p_probe) const {
- const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
ERR_FAIL_COND_V(!reflection_probe, false);
return reflection_probe->interior;
}
bool RendererStorageRD::reflection_probe_is_box_projection(RID p_probe) const {
- const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
ERR_FAIL_COND_V(!reflection_probe, false);
return reflection_probe->box_projection;
}
RS::ReflectionProbeAmbientMode RendererStorageRD::reflection_probe_get_ambient_mode(RID p_probe) const {
- const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
ERR_FAIL_COND_V(!reflection_probe, RS::REFLECTION_PROBE_AMBIENT_DISABLED);
return reflection_probe->ambient_mode;
}
Color RendererStorageRD::reflection_probe_get_ambient_color(RID p_probe) const {
- const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
ERR_FAIL_COND_V(!reflection_probe, Color());
return reflection_probe->ambient_color;
}
float RendererStorageRD::reflection_probe_get_ambient_color_energy(RID p_probe) const {
- const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
ERR_FAIL_COND_V(!reflection_probe, 0);
return reflection_probe->ambient_color_energy;
@@ -6341,14 +6760,14 @@ void RendererStorageRD::decal_initialize(RID p_decal) {
}
void RendererStorageRD::decal_set_extents(RID p_decal, const Vector3 &p_extents) {
- Decal *decal = decal_owner.getornull(p_decal);
+ Decal *decal = decal_owner.get_or_null(p_decal);
ERR_FAIL_COND(!decal);
decal->extents = p_extents;
decal->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
}
void RendererStorageRD::decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) {
- Decal *decal = decal_owner.getornull(p_decal);
+ Decal *decal = decal_owner.get_or_null(p_decal);
ERR_FAIL_COND(!decal);
ERR_FAIL_INDEX(p_type, RS::DECAL_TEXTURE_MAX);
@@ -6372,32 +6791,32 @@ void RendererStorageRD::decal_set_texture(RID p_decal, RS::DecalTexture p_type,
}
void RendererStorageRD::decal_set_emission_energy(RID p_decal, float p_energy) {
- Decal *decal = decal_owner.getornull(p_decal);
+ Decal *decal = decal_owner.get_or_null(p_decal);
ERR_FAIL_COND(!decal);
decal->emission_energy = p_energy;
}
void RendererStorageRD::decal_set_albedo_mix(RID p_decal, float p_mix) {
- Decal *decal = decal_owner.getornull(p_decal);
+ Decal *decal = decal_owner.get_or_null(p_decal);
ERR_FAIL_COND(!decal);
decal->albedo_mix = p_mix;
}
void RendererStorageRD::decal_set_modulate(RID p_decal, const Color &p_modulate) {
- Decal *decal = decal_owner.getornull(p_decal);
+ Decal *decal = decal_owner.get_or_null(p_decal);
ERR_FAIL_COND(!decal);
decal->modulate = p_modulate;
}
void RendererStorageRD::decal_set_cull_mask(RID p_decal, uint32_t p_layers) {
- Decal *decal = decal_owner.getornull(p_decal);
+ Decal *decal = decal_owner.get_or_null(p_decal);
ERR_FAIL_COND(!decal);
decal->cull_mask = p_layers;
decal->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
}
void RendererStorageRD::decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) {
- Decal *decal = decal_owner.getornull(p_decal);
+ Decal *decal = decal_owner.get_or_null(p_decal);
ERR_FAIL_COND(!decal);
decal->distance_fade = p_enabled;
decal->distance_fade_begin = p_begin;
@@ -6405,20 +6824,20 @@ void RendererStorageRD::decal_set_distance_fade(RID p_decal, bool p_enabled, flo
}
void RendererStorageRD::decal_set_fade(RID p_decal, float p_above, float p_below) {
- Decal *decal = decal_owner.getornull(p_decal);
+ Decal *decal = decal_owner.get_or_null(p_decal);
ERR_FAIL_COND(!decal);
decal->upper_fade = p_above;
decal->lower_fade = p_below;
}
void RendererStorageRD::decal_set_normal_fade(RID p_decal, float p_fade) {
- Decal *decal = decal_owner.getornull(p_decal);
+ Decal *decal = decal_owner.get_or_null(p_decal);
ERR_FAIL_COND(!decal);
decal->normal_fade = p_fade;
}
AABB RendererStorageRD::decal_get_aabb(RID p_decal) const {
- Decal *decal = decal_owner.getornull(p_decal);
+ Decal *decal = decal_owner.get_or_null(p_decal);
ERR_FAIL_COND_V(!decal, AABB());
return AABB(-decal->extents, decal->extents * 2.0);
@@ -6432,7 +6851,7 @@ void RendererStorageRD::voxel_gi_initialize(RID p_voxel_gi) {
}
void RendererStorageRD::voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) {
- VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
ERR_FAIL_COND(!voxel_gi);
if (voxel_gi->octree_buffer.is_valid()) {
@@ -6557,20 +6976,20 @@ void RendererStorageRD::voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D
}
AABB RendererStorageRD::voxel_gi_get_bounds(RID p_voxel_gi) const {
- VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
ERR_FAIL_COND_V(!voxel_gi, AABB());
return voxel_gi->bounds;
}
Vector3i RendererStorageRD::voxel_gi_get_octree_size(RID p_voxel_gi) const {
- VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
ERR_FAIL_COND_V(!voxel_gi, Vector3i());
return voxel_gi->octree_size;
}
Vector<uint8_t> RendererStorageRD::voxel_gi_get_octree_cells(RID p_voxel_gi) const {
- VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
ERR_FAIL_COND_V(!voxel_gi, Vector<uint8_t>());
if (voxel_gi->octree_buffer.is_valid()) {
@@ -6580,7 +6999,7 @@ Vector<uint8_t> RendererStorageRD::voxel_gi_get_octree_cells(RID p_voxel_gi) con
}
Vector<uint8_t> RendererStorageRD::voxel_gi_get_data_cells(RID p_voxel_gi) const {
- VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
ERR_FAIL_COND_V(!voxel_gi, Vector<uint8_t>());
if (voxel_gi->data_buffer.is_valid()) {
@@ -6590,7 +7009,7 @@ Vector<uint8_t> RendererStorageRD::voxel_gi_get_data_cells(RID p_voxel_gi) const
}
Vector<uint8_t> RendererStorageRD::voxel_gi_get_distance_field(RID p_voxel_gi) const {
- VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
ERR_FAIL_COND_V(!voxel_gi, Vector<uint8_t>());
if (voxel_gi->data_buffer.is_valid()) {
@@ -6600,21 +7019,21 @@ Vector<uint8_t> RendererStorageRD::voxel_gi_get_distance_field(RID p_voxel_gi) c
}
Vector<int> RendererStorageRD::voxel_gi_get_level_counts(RID p_voxel_gi) const {
- VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
ERR_FAIL_COND_V(!voxel_gi, Vector<int>());
return voxel_gi->level_counts;
}
Transform3D RendererStorageRD::voxel_gi_get_to_cell_xform(RID p_voxel_gi) const {
- VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
ERR_FAIL_COND_V(!voxel_gi, Transform3D());
return voxel_gi->to_cell_xform;
}
void RendererStorageRD::voxel_gi_set_dynamic_range(RID p_voxel_gi, float p_range) {
- VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
ERR_FAIL_COND(!voxel_gi);
voxel_gi->dynamic_range = p_range;
@@ -6622,14 +7041,14 @@ void RendererStorageRD::voxel_gi_set_dynamic_range(RID p_voxel_gi, float p_range
}
float RendererStorageRD::voxel_gi_get_dynamic_range(RID p_voxel_gi) const {
- VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
ERR_FAIL_COND_V(!voxel_gi, 0);
return voxel_gi->dynamic_range;
}
void RendererStorageRD::voxel_gi_set_propagation(RID p_voxel_gi, float p_range) {
- VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
ERR_FAIL_COND(!voxel_gi);
voxel_gi->propagation = p_range;
@@ -6637,72 +7056,72 @@ void RendererStorageRD::voxel_gi_set_propagation(RID p_voxel_gi, float p_range)
}
float RendererStorageRD::voxel_gi_get_propagation(RID p_voxel_gi) const {
- VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
ERR_FAIL_COND_V(!voxel_gi, 0);
return voxel_gi->propagation;
}
void RendererStorageRD::voxel_gi_set_energy(RID p_voxel_gi, float p_energy) {
- VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
ERR_FAIL_COND(!voxel_gi);
voxel_gi->energy = p_energy;
}
float RendererStorageRD::voxel_gi_get_energy(RID p_voxel_gi) const {
- VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
ERR_FAIL_COND_V(!voxel_gi, 0);
return voxel_gi->energy;
}
void RendererStorageRD::voxel_gi_set_bias(RID p_voxel_gi, float p_bias) {
- VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
ERR_FAIL_COND(!voxel_gi);
voxel_gi->bias = p_bias;
}
float RendererStorageRD::voxel_gi_get_bias(RID p_voxel_gi) const {
- VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
ERR_FAIL_COND_V(!voxel_gi, 0);
return voxel_gi->bias;
}
void RendererStorageRD::voxel_gi_set_normal_bias(RID p_voxel_gi, float p_normal_bias) {
- VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
ERR_FAIL_COND(!voxel_gi);
voxel_gi->normal_bias = p_normal_bias;
}
float RendererStorageRD::voxel_gi_get_normal_bias(RID p_voxel_gi) const {
- VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
ERR_FAIL_COND_V(!voxel_gi, 0);
return voxel_gi->normal_bias;
}
void RendererStorageRD::voxel_gi_set_anisotropy_strength(RID p_voxel_gi, float p_strength) {
- VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
ERR_FAIL_COND(!voxel_gi);
voxel_gi->anisotropy_strength = p_strength;
}
float RendererStorageRD::voxel_gi_get_anisotropy_strength(RID p_voxel_gi) const {
- VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
ERR_FAIL_COND_V(!voxel_gi, 0);
return voxel_gi->anisotropy_strength;
}
void RendererStorageRD::voxel_gi_set_interior(RID p_voxel_gi, bool p_enable) {
- VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
ERR_FAIL_COND(!voxel_gi);
voxel_gi->interior = p_enable;
}
void RendererStorageRD::voxel_gi_set_use_two_bounces(RID p_voxel_gi, bool p_enable) {
- VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
ERR_FAIL_COND(!voxel_gi);
voxel_gi->use_two_bounces = p_enable;
@@ -6710,43 +7129,43 @@ void RendererStorageRD::voxel_gi_set_use_two_bounces(RID p_voxel_gi, bool p_enab
}
bool RendererStorageRD::voxel_gi_is_using_two_bounces(RID p_voxel_gi) const {
- VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
ERR_FAIL_COND_V(!voxel_gi, false);
return voxel_gi->use_two_bounces;
}
bool RendererStorageRD::voxel_gi_is_interior(RID p_voxel_gi) const {
- VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
ERR_FAIL_COND_V(!voxel_gi, 0);
return voxel_gi->interior;
}
uint32_t RendererStorageRD::voxel_gi_get_version(RID p_voxel_gi) {
- VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
ERR_FAIL_COND_V(!voxel_gi, 0);
return voxel_gi->version;
}
uint32_t RendererStorageRD::voxel_gi_get_data_version(RID p_voxel_gi) {
- VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
ERR_FAIL_COND_V(!voxel_gi, 0);
return voxel_gi->data_version;
}
RID RendererStorageRD::voxel_gi_get_octree_buffer(RID p_voxel_gi) const {
- VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
ERR_FAIL_COND_V(!voxel_gi, RID());
return voxel_gi->octree_buffer;
}
RID RendererStorageRD::voxel_gi_get_data_buffer(RID p_voxel_gi) const {
- VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
ERR_FAIL_COND_V(!voxel_gi, RID());
return voxel_gi->data_buffer;
}
RID RendererStorageRD::voxel_gi_get_sdf_texture(RID p_voxel_gi) {
- VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
ERR_FAIL_COND_V(!voxel_gi, RID());
return voxel_gi->sdf_texture;
@@ -6763,20 +7182,20 @@ void RendererStorageRD::lightmap_initialize(RID p_lightmap) {
}
void RendererStorageRD::lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) {
- Lightmap *lm = lightmap_owner.getornull(p_lightmap);
+ Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
ERR_FAIL_COND(!lm);
lightmap_array_version++;
//erase lightmap users
if (lm->light_texture.is_valid()) {
- Texture *t = texture_owner.getornull(lm->light_texture);
+ Texture *t = texture_owner.get_or_null(lm->light_texture);
if (t) {
t->lightmap_users.erase(p_lightmap);
}
}
- Texture *t = texture_owner.getornull(p_light);
+ Texture *t = texture_owner.get_or_null(p_light);
lm->light_texture = p_light;
lm->uses_spherical_harmonics = p_uses_spherical_haromics;
@@ -6811,19 +7230,19 @@ void RendererStorageRD::lightmap_set_textures(RID p_lightmap, RID p_light, bool
}
void RendererStorageRD::lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) {
- Lightmap *lm = lightmap_owner.getornull(p_lightmap);
+ Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
ERR_FAIL_COND(!lm);
lm->bounds = p_bounds;
}
void RendererStorageRD::lightmap_set_probe_interior(RID p_lightmap, bool p_interior) {
- Lightmap *lm = lightmap_owner.getornull(p_lightmap);
+ Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
ERR_FAIL_COND(!lm);
lm->interior = p_interior;
}
void RendererStorageRD::lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) {
- Lightmap *lm = lightmap_owner.getornull(p_lightmap);
+ Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
ERR_FAIL_COND(!lm);
if (p_points.size()) {
@@ -6839,26 +7258,26 @@ void RendererStorageRD::lightmap_set_probe_capture_data(RID p_lightmap, const Pa
}
PackedVector3Array RendererStorageRD::lightmap_get_probe_capture_points(RID p_lightmap) const {
- Lightmap *lm = lightmap_owner.getornull(p_lightmap);
+ Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
ERR_FAIL_COND_V(!lm, PackedVector3Array());
return lm->points;
}
PackedColorArray RendererStorageRD::lightmap_get_probe_capture_sh(RID p_lightmap) const {
- Lightmap *lm = lightmap_owner.getornull(p_lightmap);
+ Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
ERR_FAIL_COND_V(!lm, PackedColorArray());
return lm->point_sh;
}
PackedInt32Array RendererStorageRD::lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const {
- Lightmap *lm = lightmap_owner.getornull(p_lightmap);
+ Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
ERR_FAIL_COND_V(!lm, PackedInt32Array());
return lm->tetrahedra;
}
PackedInt32Array RendererStorageRD::lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const {
- Lightmap *lm = lightmap_owner.getornull(p_lightmap);
+ Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
ERR_FAIL_COND_V(!lm, PackedInt32Array());
return lm->bsp_tree;
}
@@ -6868,7 +7287,7 @@ void RendererStorageRD::lightmap_set_probe_capture_update_speed(float p_speed) {
}
void RendererStorageRD::lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) {
- Lightmap *lm = lightmap_owner.getornull(p_lightmap);
+ Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
ERR_FAIL_COND(!lm);
for (int i = 0; i < 9; i++) {
@@ -6918,13 +7337,13 @@ void RendererStorageRD::lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_p
}
bool RendererStorageRD::lightmap_is_interior(RID p_lightmap) const {
- const Lightmap *lm = lightmap_owner.getornull(p_lightmap);
+ const Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
ERR_FAIL_COND_V(!lm, false);
return lm->interior;
}
AABB RendererStorageRD::lightmap_get_aabb(RID p_lightmap) const {
- const Lightmap *lm = lightmap_owner.getornull(p_lightmap);
+ const Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
ERR_FAIL_COND_V(!lm, AABB());
return lm->bounds;
}
@@ -6964,7 +7383,7 @@ void RendererStorageRD::_update_render_target(RenderTarget *rt) {
//create a placeholder until updated
rt->texture = texture_allocate();
texture_2d_placeholder_initialize(rt->texture);
- Texture *tex = texture_owner.getornull(rt->texture);
+ Texture *tex = texture_owner.get_or_null(rt->texture);
tex->is_render_target = true;
}
@@ -7011,7 +7430,7 @@ void RendererStorageRD::_update_render_target(RenderTarget *rt) {
{ //update texture
- Texture *tex = texture_owner.getornull(rt->texture);
+ Texture *tex = texture_owner.get_or_null(rt->texture);
//free existing textures
if (RD::get_singleton()->texture_is_valid(tex->rd_texture)) {
@@ -7118,7 +7537,7 @@ void RendererStorageRD::render_target_set_position(RID p_render_target, int p_x,
}
void RendererStorageRD::render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) {
- RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND(!rt);
if (rt->size.x != p_width || rt->size.y != p_height || rt->view_count != p_view_count) {
rt->size.x = p_width;
@@ -7129,7 +7548,7 @@ void RendererStorageRD::render_target_set_size(RID p_render_target, int p_width,
}
RID RendererStorageRD::render_target_get_texture(RID p_render_target) {
- RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND_V(!rt, RID());
return rt->texture;
@@ -7139,53 +7558,53 @@ void RendererStorageRD::render_target_set_external_texture(RID p_render_target,
}
void RendererStorageRD::render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) {
- RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND(!rt);
rt->flags[p_flag] = p_value;
_update_render_target(rt);
}
bool RendererStorageRD::render_target_was_used(RID p_render_target) {
- RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND_V(!rt, false);
return rt->was_used;
}
void RendererStorageRD::render_target_set_as_unused(RID p_render_target) {
- RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND(!rt);
rt->was_used = false;
}
Size2 RendererStorageRD::render_target_get_size(RID p_render_target) {
- RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND_V(!rt, Size2());
return rt->size;
}
RID RendererStorageRD::render_target_get_rd_framebuffer(RID p_render_target) {
- RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND_V(!rt, RID());
return rt->framebuffer;
}
RID RendererStorageRD::render_target_get_rd_texture(RID p_render_target) {
- RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND_V(!rt, RID());
return rt->color;
}
RID RendererStorageRD::render_target_get_rd_backbuffer(RID p_render_target) {
- RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND_V(!rt, RID());
return rt->backbuffer;
}
RID RendererStorageRD::render_target_get_rd_backbuffer_framebuffer(RID p_render_target) {
- RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND_V(!rt, RID());
if (!rt->backbuffer.is_valid()) {
@@ -7196,32 +7615,32 @@ RID RendererStorageRD::render_target_get_rd_backbuffer_framebuffer(RID p_render_
}
void RendererStorageRD::render_target_request_clear(RID p_render_target, const Color &p_clear_color) {
- RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND(!rt);
rt->clear_requested = true;
rt->clear_color = p_clear_color;
}
bool RendererStorageRD::render_target_is_clear_requested(RID p_render_target) {
- RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND_V(!rt, false);
return rt->clear_requested;
}
Color RendererStorageRD::render_target_get_clear_request_color(RID p_render_target) {
- RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND_V(!rt, Color());
return rt->clear_color;
}
void RendererStorageRD::render_target_disable_clear_request(RID p_render_target) {
- RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND(!rt);
rt->clear_requested = false;
}
void RendererStorageRD::render_target_do_clear_request(RID p_render_target) {
- RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND(!rt);
if (!rt->clear_requested) {
return;
@@ -7234,7 +7653,7 @@ void RendererStorageRD::render_target_do_clear_request(RID p_render_target) {
}
void RendererStorageRD::render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) {
- RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND(!rt);
if (rt->sdf_oversize == p_size && rt->sdf_scale == p_scale) {
return;
@@ -7276,28 +7695,28 @@ Rect2i RendererStorageRD::_render_target_get_sdf_rect(const RenderTarget *rt) co
}
Rect2i RendererStorageRD::render_target_get_sdf_rect(RID p_render_target) const {
- const RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ const RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND_V(!rt, Rect2i());
return _render_target_get_sdf_rect(rt);
}
void RendererStorageRD::render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) {
- RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND(!rt);
rt->sdf_enabled = p_enabled;
}
bool RendererStorageRD::render_target_is_sdf_enabled(RID p_render_target) const {
- const RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ const RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND_V(!rt, false);
return rt->sdf_enabled;
}
RID RendererStorageRD::render_target_get_sdf_texture(RID p_render_target) {
- RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND_V(!rt, RID());
if (rt->sdf_buffer_read.is_null()) {
// no texture, create a dummy one for the 2D uniform set
@@ -7432,7 +7851,7 @@ void RendererStorageRD::_render_target_clear_sdf(RenderTarget *rt) {
}
RID RendererStorageRD::render_target_get_sdf_framebuffer(RID p_render_target) {
- RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND_V(!rt, RID());
if (rt->sdf_buffer_write_fb.is_null()) {
@@ -7442,7 +7861,7 @@ RID RendererStorageRD::render_target_get_sdf_framebuffer(RID p_render_target) {
return rt->sdf_buffer_write_fb;
}
void RendererStorageRD::render_target_sdf_process(RID p_render_target) {
- RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND(!rt);
ERR_FAIL_COND(rt->sdf_buffer_write_fb.is_null());
@@ -7517,7 +7936,7 @@ void RendererStorageRD::render_target_sdf_process(RID p_render_target) {
}
void RendererStorageRD::render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region, bool p_gen_mipmaps) {
- RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND(!rt);
if (!rt->backbuffer.is_valid()) {
_create_render_target_backbuffer(rt);
@@ -7557,7 +7976,7 @@ void RendererStorageRD::render_target_copy_to_back_buffer(RID p_render_target, c
}
void RendererStorageRD::render_target_clear_back_buffer(RID p_render_target, const Rect2i &p_region, const Color &p_color) {
- RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND(!rt);
if (!rt->backbuffer.is_valid()) {
_create_render_target_backbuffer(rt);
@@ -7578,7 +7997,7 @@ void RendererStorageRD::render_target_clear_back_buffer(RID p_render_target, con
}
void RendererStorageRD::render_target_gen_back_buffer_mipmaps(RID p_render_target, const Rect2i &p_region) {
- RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND(!rt);
if (!rt->backbuffer.is_valid()) {
_create_render_target_backbuffer(rt);
@@ -7610,66 +8029,66 @@ void RendererStorageRD::render_target_gen_back_buffer_mipmaps(RID p_render_targe
}
RID RendererStorageRD::render_target_get_framebuffer_uniform_set(RID p_render_target) {
- RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND_V(!rt, RID());
return rt->framebuffer_uniform_set;
}
RID RendererStorageRD::render_target_get_backbuffer_uniform_set(RID p_render_target) {
- RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND_V(!rt, RID());
return rt->backbuffer_uniform_set;
}
void RendererStorageRD::render_target_set_framebuffer_uniform_set(RID p_render_target, RID p_uniform_set) {
- RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND(!rt);
rt->framebuffer_uniform_set = p_uniform_set;
}
void RendererStorageRD::render_target_set_backbuffer_uniform_set(RID p_render_target, RID p_uniform_set) {
- RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND(!rt);
rt->backbuffer_uniform_set = p_uniform_set;
}
void RendererStorageRD::base_update_dependency(RID p_base, DependencyTracker *p_instance) {
if (mesh_owner.owns(p_base)) {
- Mesh *mesh = mesh_owner.getornull(p_base);
+ Mesh *mesh = mesh_owner.get_or_null(p_base);
p_instance->update_dependency(&mesh->dependency);
} else if (multimesh_owner.owns(p_base)) {
- MultiMesh *multimesh = multimesh_owner.getornull(p_base);
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_base);
p_instance->update_dependency(&multimesh->dependency);
if (multimesh->mesh.is_valid()) {
base_update_dependency(multimesh->mesh, p_instance);
}
} else if (reflection_probe_owner.owns(p_base)) {
- ReflectionProbe *rp = reflection_probe_owner.getornull(p_base);
+ ReflectionProbe *rp = reflection_probe_owner.get_or_null(p_base);
p_instance->update_dependency(&rp->dependency);
} else if (decal_owner.owns(p_base)) {
- Decal *decal = decal_owner.getornull(p_base);
+ Decal *decal = decal_owner.get_or_null(p_base);
p_instance->update_dependency(&decal->dependency);
} else if (voxel_gi_owner.owns(p_base)) {
- VoxelGI *gip = voxel_gi_owner.getornull(p_base);
+ VoxelGI *gip = voxel_gi_owner.get_or_null(p_base);
p_instance->update_dependency(&gip->dependency);
} else if (lightmap_owner.owns(p_base)) {
- Lightmap *lm = lightmap_owner.getornull(p_base);
+ Lightmap *lm = lightmap_owner.get_or_null(p_base);
p_instance->update_dependency(&lm->dependency);
} else if (light_owner.owns(p_base)) {
- Light *l = light_owner.getornull(p_base);
+ Light *l = light_owner.get_or_null(p_base);
p_instance->update_dependency(&l->dependency);
} else if (particles_owner.owns(p_base)) {
- Particles *p = particles_owner.getornull(p_base);
+ Particles *p = particles_owner.get_or_null(p_base);
p_instance->update_dependency(&p->dependency);
} else if (particles_collision_owner.owns(p_base)) {
- ParticlesCollision *pc = particles_collision_owner.getornull(p_base);
+ ParticlesCollision *pc = particles_collision_owner.get_or_null(p_base);
p_instance->update_dependency(&pc->dependency);
} else if (visibility_notifier_owner.owns(p_base)) {
- VisibilityNotifier *vn = visibility_notifier_owner.getornull(p_base);
+ VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_base);
p_instance->update_dependency(&vn->dependency);
}
}
void RendererStorageRD::skeleton_update_dependency(RID p_skeleton, DependencyTracker *p_instance) {
- Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
ERR_FAIL_COND(!skeleton);
p_instance->update_dependency(&skeleton->dependency);
@@ -7775,7 +8194,7 @@ void RendererStorageRD::_update_decal_atlas() {
while ((K = decal_atlas.textures.next(K))) {
DecalAtlas::SortItem &si = itemsv.write[idx];
- Texture *src_tex = texture_owner.getornull(*K);
+ Texture *src_tex = texture_owner.get_or_null(*K);
si.size.width = (src_tex->width / border) + 1;
si.size.height = (src_tex->height / border) + 1;
@@ -7924,7 +8343,7 @@ void RendererStorageRD::_update_decal_atlas() {
const RID *K = nullptr;
while ((K = decal_atlas.textures.next(K))) {
DecalAtlas::Texture *t = decal_atlas.textures.getptr(*K);
- Texture *src_tex = texture_owner.getornull(*K);
+ Texture *src_tex = texture_owner.get_or_null(*K);
effects->copy_to_atlas_fb(src_tex->rd_texture, mm.fb, t->uv_rect, draw_list, false, t->panorama_to_dp_users > 0);
}
@@ -8340,7 +8759,7 @@ void RendererStorageRD::global_variable_set(const StringName &p_name, const Vari
} else {
//texture
for (Set<RID>::Element *E = gv.texture_materials.front(); E; E = E->next()) {
- Material *material = material_owner.getornull(E->get());
+ Material *material = material_owner.get_or_null(E->get());
ERR_CONTINUE(!material);
_material_queue_update(material, false, true);
}
@@ -8371,7 +8790,7 @@ void RendererStorageRD::global_variable_set_override(const StringName &p_name, c
} else {
//texture
for (Set<RID>::Element *E = gv.texture_materials.front(); E; E = E->next()) {
- Material *material = material_owner.getornull(E->get());
+ Material *material = material_owner.get_or_null(E->get());
ERR_CONTINUE(!material);
_material_queue_update(material, false, true);
}
@@ -8552,7 +8971,7 @@ void RendererStorageRD::global_variables_instance_update(RID p_instance, int p_i
pos += p_index;
- _fill_std140_variant_ubo_value(datatype, p_value, (uint8_t *)&global_variables.buffer_values[pos], true); //instances always use linear color in this renderer
+ _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);
}
@@ -8582,7 +9001,7 @@ void RendererStorageRD::_update_global_variables() {
// only happens in the case of a buffer variable added or removed,
// so not often.
for (const RID &E : global_variables.materials_using_buffer) {
- Material *material = material_owner.getornull(E);
+ Material *material = material_owner.get_or_null(E);
ERR_CONTINUE(!material); //wtf
_material_queue_update(material, true, false);
@@ -8595,7 +9014,7 @@ void RendererStorageRD::_update_global_variables() {
// only happens in the case of a buffer variable added or removed,
// so not often.
for (const RID &E : global_variables.materials_using_texture) {
- Material *material = material_owner.getornull(E);
+ Material *material = material_owner.get_or_null(E);
ERR_CONTINUE(!material); //wtf
_material_queue_update(material, false, true);
@@ -8640,7 +9059,7 @@ bool RendererStorageRD::has_os_feature(const String &p_feature) const {
bool RendererStorageRD::free(RID p_rid) {
if (texture_owner.owns(p_rid)) {
- Texture *t = texture_owner.getornull(p_rid);
+ Texture *t = texture_owner.get_or_null(p_rid);
ERR_FAIL_COND_V(!t, false);
ERR_FAIL_COND_V(t->is_render_target, false);
@@ -8654,7 +9073,7 @@ bool RendererStorageRD::free(RID p_rid) {
}
if (t->is_proxy && t->proxy_to.is_valid()) {
- Texture *proxy_to = texture_owner.getornull(t->proxy_to);
+ Texture *proxy_to = texture_owner.get_or_null(t->proxy_to);
if (proxy_to) {
proxy_to->proxies.erase(p_rid);
}
@@ -8666,7 +9085,7 @@ bool RendererStorageRD::free(RID p_rid) {
}
for (int i = 0; i < t->proxies.size(); i++) {
- Texture *p = texture_owner.getornull(t->proxies[i]);
+ Texture *p = texture_owner.get_or_null(t->proxies[i]);
ERR_CONTINUE(!p);
p->proxy_to = RID();
p->rd_texture = RID();
@@ -8681,7 +9100,7 @@ bool RendererStorageRD::free(RID p_rid) {
} else if (canvas_texture_owner.owns(p_rid)) {
canvas_texture_owner.free(p_rid);
} else if (shader_owner.owns(p_rid)) {
- Shader *shader = shader_owner.getornull(p_rid);
+ Shader *shader = shader_owner.get_or_null(p_rid);
//make material unreference this
while (shader->owners.size()) {
material_set_shader(shader->owners.front()->get()->self, RID());
@@ -8693,7 +9112,7 @@ bool RendererStorageRD::free(RID p_rid) {
shader_owner.free(p_rid);
} else if (material_owner.owns(p_rid)) {
- Material *material = material_owner.getornull(p_rid);
+ Material *material = material_owner.get_or_null(p_rid);
material_set_shader(p_rid, RID()); //clean up shader
material->dependency.deleted_notify(p_rid);
@@ -8701,7 +9120,7 @@ bool RendererStorageRD::free(RID p_rid) {
} else if (mesh_owner.owns(p_rid)) {
mesh_clear(p_rid);
mesh_set_shadow_mesh(p_rid, RID());
- Mesh *mesh = mesh_owner.getornull(p_rid);
+ Mesh *mesh = mesh_owner.get_or_null(p_rid);
mesh->dependency.deleted_notify(p_rid);
if (mesh->instances.size()) {
ERR_PRINT("deleting mesh with active instances");
@@ -8715,7 +9134,7 @@ bool RendererStorageRD::free(RID p_rid) {
}
mesh_owner.free(p_rid);
} else if (mesh_instance_owner.owns(p_rid)) {
- MeshInstance *mi = mesh_instance_owner.getornull(p_rid);
+ MeshInstance *mi = mesh_instance_owner.get_or_null(p_rid);
_mesh_instance_clear(mi);
mi->mesh->instances.erase(mi->I);
mi->I = nullptr;
@@ -8725,21 +9144,21 @@ bool RendererStorageRD::free(RID p_rid) {
} else if (multimesh_owner.owns(p_rid)) {
_update_dirty_multimeshes();
multimesh_allocate_data(p_rid, 0, RS::MULTIMESH_TRANSFORM_2D);
- MultiMesh *multimesh = multimesh_owner.getornull(p_rid);
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_rid);
multimesh->dependency.deleted_notify(p_rid);
multimesh_owner.free(p_rid);
} else if (skeleton_owner.owns(p_rid)) {
_update_dirty_skeletons();
skeleton_allocate_data(p_rid, 0);
- Skeleton *skeleton = skeleton_owner.getornull(p_rid);
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_rid);
skeleton->dependency.deleted_notify(p_rid);
skeleton_owner.free(p_rid);
} else if (reflection_probe_owner.owns(p_rid)) {
- ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_rid);
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_rid);
reflection_probe->dependency.deleted_notify(p_rid);
reflection_probe_owner.free(p_rid);
} else if (decal_owner.owns(p_rid)) {
- Decal *decal = decal_owner.getornull(p_rid);
+ Decal *decal = decal_owner.get_or_null(p_rid);
for (int i = 0; i < RS::DECAL_TEXTURE_MAX; i++) {
if (decal->textures[i].is_valid() && texture_owner.owns(decal->textures[i])) {
texture_remove_from_decal_atlas(decal->textures[i]);
@@ -8749,30 +9168,30 @@ bool RendererStorageRD::free(RID p_rid) {
decal_owner.free(p_rid);
} else if (voxel_gi_owner.owns(p_rid)) {
voxel_gi_allocate_data(p_rid, Transform3D(), AABB(), Vector3i(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<int>()); //deallocate
- VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_rid);
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_rid);
voxel_gi->dependency.deleted_notify(p_rid);
voxel_gi_owner.free(p_rid);
} else if (lightmap_owner.owns(p_rid)) {
lightmap_set_textures(p_rid, RID(), false);
- Lightmap *lightmap = lightmap_owner.getornull(p_rid);
+ Lightmap *lightmap = lightmap_owner.get_or_null(p_rid);
lightmap->dependency.deleted_notify(p_rid);
lightmap_owner.free(p_rid);
} else if (light_owner.owns(p_rid)) {
light_set_projector(p_rid, RID()); //clear projector
// delete the texture
- Light *light = light_owner.getornull(p_rid);
+ Light *light = light_owner.get_or_null(p_rid);
light->dependency.deleted_notify(p_rid);
light_owner.free(p_rid);
} else if (particles_owner.owns(p_rid)) {
update_particles();
- Particles *particles = particles_owner.getornull(p_rid);
+ Particles *particles = particles_owner.get_or_null(p_rid);
particles->dependency.deleted_notify(p_rid);
_particles_free_data(particles);
particles_owner.free(p_rid);
} else if (particles_collision_owner.owns(p_rid)) {
- ParticlesCollision *particles_collision = particles_collision_owner.getornull(p_rid);
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_rid);
if (particles_collision->heightfield_texture.is_valid()) {
RD::get_singleton()->free(particles_collision->heightfield_texture);
@@ -8780,18 +9199,18 @@ bool RendererStorageRD::free(RID p_rid) {
particles_collision->dependency.deleted_notify(p_rid);
particles_collision_owner.free(p_rid);
} else if (visibility_notifier_owner.owns(p_rid)) {
- VisibilityNotifier *vn = visibility_notifier_owner.getornull(p_rid);
+ VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_rid);
vn->dependency.deleted_notify(p_rid);
visibility_notifier_owner.free(p_rid);
} else if (particles_collision_instance_owner.owns(p_rid)) {
particles_collision_instance_owner.free(p_rid);
} else if (render_target_owner.owns(p_rid)) {
- RenderTarget *rt = render_target_owner.getornull(p_rid);
+ RenderTarget *rt = render_target_owner.get_or_null(p_rid);
_clear_render_target(rt);
if (rt->texture.is_valid()) {
- Texture *tex = texture_owner.getornull(rt->texture);
+ Texture *tex = texture_owner.get_or_null(rt->texture);
tex->is_render_target = false;
free(rt->texture);
}
@@ -9398,6 +9817,8 @@ RendererStorageRD::RendererStorageRD() {
particles_shader.default_shader = shader_allocate();
shader_initialize(particles_shader.default_shader);
shader_set_code(particles_shader.default_shader, R"(
+// Default particles shader.
+
shader_type particles;
void process() {
@@ -9549,6 +9970,6 @@ RendererStorageRD::~RendererStorageRD() {
if (effects) {
memdelete(effects);
- effects = NULL;
+ effects = nullptr;
}
}
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.h b/servers/rendering/renderer_rd/renderer_storage_rd.h
index 02395a884f..d6129bb57b 100644
--- a/servers/rendering/renderer_rd/renderer_storage_rd.h
+++ b/servers/rendering/renderer_rd/renderer_storage_rd.h
@@ -621,7 +621,6 @@ private:
float color[4];
float custom[3];
float lifetime;
- uint32_t pad[3];
};
struct ParticlesFrameParams {
@@ -1285,7 +1284,7 @@ private:
void _update_global_variables();
/* EFFECTS */
- EffectsRD *effects = NULL;
+ EffectsRD *effects = nullptr;
public:
virtual bool can_create_resources_async() const;
@@ -1351,7 +1350,7 @@ public:
if (p_texture.is_null()) {
return RID();
}
- Texture *tex = texture_owner.getornull(p_texture);
+ Texture *tex = texture_owner.get_or_null(p_texture);
if (!tex) {
return RID();
@@ -1363,7 +1362,7 @@ public:
if (p_texture.is_null()) {
return Size2i();
}
- Texture *tex = texture_owner.getornull(p_texture);
+ Texture *tex = texture_owner.get_or_null(p_texture);
if (!tex) {
return Size2i();
@@ -1431,12 +1430,12 @@ public:
void material_set_data_request_function(ShaderType p_shader_type, MaterialDataRequestFunction p_function);
_FORCE_INLINE_ uint32_t material_get_shader_id(RID p_material) {
- Material *material = material_owner.getornull(p_material);
+ Material *material = material_owner.get_or_null(p_material);
return material->shader_id;
}
_FORCE_INLINE_ MaterialData *material_get_data(RID p_material, ShaderType p_shader_type) {
- Material *material = material_owner.getornull(p_material);
+ Material *material = material_owner.get_or_null(p_material);
if (!material || material->shader_type != p_shader_type) {
return nullptr;
} else {
@@ -1489,7 +1488,7 @@ public:
virtual void update_mesh_instances();
_FORCE_INLINE_ const RID *mesh_get_surface_count_and_materials(RID p_mesh, uint32_t &r_surface_count) {
- Mesh *mesh = mesh_owner.getornull(p_mesh);
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
ERR_FAIL_COND_V(!mesh, nullptr);
r_surface_count = mesh->surface_count;
if (r_surface_count == 0) {
@@ -1506,7 +1505,7 @@ public:
}
_FORCE_INLINE_ void *mesh_get_surface(RID p_mesh, uint32_t p_surface_index) {
- Mesh *mesh = mesh_owner.getornull(p_mesh);
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
ERR_FAIL_COND_V(!mesh, nullptr);
ERR_FAIL_UNSIGNED_INDEX_V(p_surface_index, mesh->surface_count, nullptr);
@@ -1514,7 +1513,7 @@ public:
}
_FORCE_INLINE_ RID mesh_get_shadow_mesh(RID p_mesh) {
- Mesh *mesh = mesh_owner.getornull(p_mesh);
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
ERR_FAIL_COND_V(!mesh, RID());
return mesh->shadow_mesh;
@@ -1600,7 +1599,7 @@ public:
}
_FORCE_INLINE_ void mesh_instance_surface_get_vertex_arrays_and_format(RID p_mesh_instance, uint32_t p_surface_index, uint32_t p_input_mask, RID &r_vertex_array_rd, RD::VertexFormatID &r_vertex_format) {
- MeshInstance *mi = mesh_instance_owner.getornull(p_mesh_instance);
+ MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance);
ERR_FAIL_COND(!mi);
Mesh *mesh = mi->mesh;
ERR_FAIL_UNSIGNED_INDEX(p_surface_index, mesh->surface_count);
@@ -1641,7 +1640,7 @@ public:
}
_FORCE_INLINE_ uint32_t mesh_surface_get_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) {
- Mesh *mesh = mesh_owner.getornull(p_mesh);
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
Mesh::Surface *s = mesh->surfaces[p_surface_index];
if (s->render_pass != p_render_pass) {
@@ -1654,7 +1653,7 @@ public:
}
_FORCE_INLINE_ uint32_t mesh_surface_get_multimesh_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) {
- Mesh *mesh = mesh_owner.getornull(p_mesh);
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
Mesh::Surface *s = mesh->surfaces[p_surface_index];
if (s->multimesh_render_pass != p_render_pass) {
@@ -1667,7 +1666,7 @@ public:
}
_FORCE_INLINE_ uint32_t mesh_surface_get_particles_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) {
- Mesh *mesh = mesh_owner.getornull(p_mesh);
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
Mesh::Surface *s = mesh->surfaces[p_surface_index];
if (s->particles_render_pass != p_render_pass) {
@@ -1709,22 +1708,22 @@ public:
AABB multimesh_get_aabb(RID p_multimesh) const;
_FORCE_INLINE_ RS::MultimeshTransformFormat multimesh_get_transform_format(RID p_multimesh) const {
- MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
return multimesh->xform_format;
}
_FORCE_INLINE_ bool multimesh_uses_colors(RID p_multimesh) const {
- MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
return multimesh->uses_colors;
}
_FORCE_INLINE_ bool multimesh_uses_custom_data(RID p_multimesh) const {
- MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
return multimesh->uses_custom_data;
}
_FORCE_INLINE_ uint32_t multimesh_get_instances_to_draw(RID p_multimesh) const {
- MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
if (multimesh->visible_instances >= 0) {
return multimesh->visible_instances;
}
@@ -1732,7 +1731,7 @@ public:
}
_FORCE_INLINE_ RID multimesh_get_3d_uniform_set(RID p_multimesh, RID p_shader, uint32_t p_set) const {
- MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
if (!multimesh->uniform_set_3d.is_valid()) {
Vector<RD::Uniform> uniforms;
RD::Uniform u;
@@ -1747,7 +1746,7 @@ public:
}
_FORCE_INLINE_ RID multimesh_get_2d_uniform_set(RID p_multimesh, RID p_shader, uint32_t p_set) const {
- MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
if (!multimesh->uniform_set_2d.is_valid()) {
Vector<RD::Uniform> uniforms;
RD::Uniform u;
@@ -1776,11 +1775,11 @@ public:
Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const;
_FORCE_INLINE_ bool skeleton_is_valid(RID p_skeleton) {
- return skeleton_owner.getornull(p_skeleton) != nullptr;
+ return skeleton_owner.get_or_null(p_skeleton) != nullptr;
}
_FORCE_INLINE_ RID skeleton_get_3d_uniform_set(RID p_skeleton, RID p_shader, uint32_t p_set) const {
- Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
ERR_FAIL_COND_V(!skeleton, RID());
ERR_FAIL_COND_V(skeleton->size == 0, RID());
if (skeleton->use_2d) {
@@ -1834,7 +1833,7 @@ public:
RS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light);
_FORCE_INLINE_ RS::LightType light_get_type(RID p_light) const {
- const Light *light = light_owner.getornull(p_light);
+ const Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL);
return light->type;
@@ -1842,70 +1841,70 @@ public:
AABB light_get_aabb(RID p_light) const;
_FORCE_INLINE_ float light_get_param(RID p_light, RS::LightParam p_param) {
- const Light *light = light_owner.getornull(p_light);
+ const Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_COND_V(!light, 0);
return light->param[p_param];
}
_FORCE_INLINE_ RID light_get_projector(RID p_light) {
- const Light *light = light_owner.getornull(p_light);
+ const Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_COND_V(!light, RID());
return light->projector;
}
_FORCE_INLINE_ Color light_get_color(RID p_light) {
- const Light *light = light_owner.getornull(p_light);
+ const Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_COND_V(!light, Color());
return light->color;
}
_FORCE_INLINE_ Color light_get_shadow_color(RID p_light) {
- const Light *light = light_owner.getornull(p_light);
+ const Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_COND_V(!light, Color());
return light->shadow_color;
}
_FORCE_INLINE_ uint32_t light_get_cull_mask(RID p_light) {
- const Light *light = light_owner.getornull(p_light);
+ const Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_COND_V(!light, 0);
return light->cull_mask;
}
_FORCE_INLINE_ bool light_has_shadow(RID p_light) const {
- const Light *light = light_owner.getornull(p_light);
+ const Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL);
return light->shadow;
}
_FORCE_INLINE_ bool light_has_projector(RID p_light) const {
- const Light *light = light_owner.getornull(p_light);
+ const Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL);
return texture_owner.owns(light->projector);
}
_FORCE_INLINE_ bool light_is_negative(RID p_light) const {
- const Light *light = light_owner.getornull(p_light);
+ const Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL);
return light->negative;
}
_FORCE_INLINE_ float light_get_transmittance_bias(RID p_light) const {
- const Light *light = light_owner.getornull(p_light);
+ const Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_COND_V(!light, 0.0);
return light->param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS];
}
_FORCE_INLINE_ float light_get_shadow_volumetric_fog_fade(RID p_light) const {
- const Light *light = light_owner.getornull(p_light);
+ const Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_COND_V(!light, 0.0);
return light->param[RS::LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE];
@@ -1972,62 +1971,62 @@ public:
virtual void decal_set_normal_fade(RID p_decal, float p_fade);
_FORCE_INLINE_ Vector3 decal_get_extents(RID p_decal) {
- const Decal *decal = decal_owner.getornull(p_decal);
+ const Decal *decal = decal_owner.get_or_null(p_decal);
return decal->extents;
}
_FORCE_INLINE_ RID decal_get_texture(RID p_decal, RS::DecalTexture p_texture) {
- const Decal *decal = decal_owner.getornull(p_decal);
+ const Decal *decal = decal_owner.get_or_null(p_decal);
return decal->textures[p_texture];
}
_FORCE_INLINE_ Color decal_get_modulate(RID p_decal) {
- const Decal *decal = decal_owner.getornull(p_decal);
+ const Decal *decal = decal_owner.get_or_null(p_decal);
return decal->modulate;
}
_FORCE_INLINE_ float decal_get_emission_energy(RID p_decal) {
- const Decal *decal = decal_owner.getornull(p_decal);
+ const Decal *decal = decal_owner.get_or_null(p_decal);
return decal->emission_energy;
}
_FORCE_INLINE_ float decal_get_albedo_mix(RID p_decal) {
- const Decal *decal = decal_owner.getornull(p_decal);
+ const Decal *decal = decal_owner.get_or_null(p_decal);
return decal->albedo_mix;
}
_FORCE_INLINE_ uint32_t decal_get_cull_mask(RID p_decal) {
- const Decal *decal = decal_owner.getornull(p_decal);
+ const Decal *decal = decal_owner.get_or_null(p_decal);
return decal->cull_mask;
}
_FORCE_INLINE_ float decal_get_upper_fade(RID p_decal) {
- const Decal *decal = decal_owner.getornull(p_decal);
+ const Decal *decal = decal_owner.get_or_null(p_decal);
return decal->upper_fade;
}
_FORCE_INLINE_ float decal_get_lower_fade(RID p_decal) {
- const Decal *decal = decal_owner.getornull(p_decal);
+ const Decal *decal = decal_owner.get_or_null(p_decal);
return decal->lower_fade;
}
_FORCE_INLINE_ float decal_get_normal_fade(RID p_decal) {
- const Decal *decal = decal_owner.getornull(p_decal);
+ const Decal *decal = decal_owner.get_or_null(p_decal);
return decal->normal_fade;
}
_FORCE_INLINE_ bool decal_is_distance_fade_enabled(RID p_decal) {
- const Decal *decal = decal_owner.getornull(p_decal);
+ const Decal *decal = decal_owner.get_or_null(p_decal);
return decal->distance_fade;
}
_FORCE_INLINE_ float decal_get_distance_fade_begin(RID p_decal) {
- const Decal *decal = decal_owner.getornull(p_decal);
+ const Decal *decal = decal_owner.get_or_null(p_decal);
return decal->distance_fade_begin;
}
_FORCE_INLINE_ float decal_get_distance_fade_length(RID p_decal) {
- const Decal *decal = decal_owner.getornull(p_decal);
+ const Decal *decal = decal_owner.get_or_null(p_decal);
return decal->distance_fade_length;
}
@@ -2102,18 +2101,18 @@ public:
return lightmap_probe_capture_update_speed;
}
_FORCE_INLINE_ RID lightmap_get_texture(RID p_lightmap) const {
- const Lightmap *lm = lightmap_owner.getornull(p_lightmap);
+ const Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
ERR_FAIL_COND_V(!lm, RID());
return lm->light_texture;
}
_FORCE_INLINE_ int32_t lightmap_get_array_index(RID p_lightmap) const {
ERR_FAIL_COND_V(!using_lightmap_array, -1); //only for arrays
- const Lightmap *lm = lightmap_owner.getornull(p_lightmap);
+ const Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
return lm->array_index;
}
_FORCE_INLINE_ bool lightmap_uses_spherical_harmonics(RID p_lightmap) const {
ERR_FAIL_COND_V(!using_lightmap_array, false); //only for arrays
- const Lightmap *lm = lightmap_owner.getornull(p_lightmap);
+ const Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
return lm->uses_spherical_harmonics;
}
_FORCE_INLINE_ uint64_t lightmap_array_get_version() const {
@@ -2182,13 +2181,13 @@ public:
virtual bool particles_is_inactive(RID p_particles) const;
_FORCE_INLINE_ RS::ParticlesMode particles_get_mode(RID p_particles) {
- Particles *particles = particles_owner.getornull(p_particles);
+ Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND_V(!particles, RS::PARTICLES_MODE_2D);
return particles->mode;
}
_FORCE_INLINE_ uint32_t particles_get_amount(RID p_particles, uint32_t &r_trail_divisor) {
- Particles *particles = particles_owner.getornull(p_particles);
+ Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND_V(!particles, 0);
if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
@@ -2201,21 +2200,21 @@ public:
}
_FORCE_INLINE_ bool particles_has_collision(RID p_particles) {
- Particles *particles = particles_owner.getornull(p_particles);
+ Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND_V(!particles, 0);
return particles->has_collision_cache;
}
_FORCE_INLINE_ uint32_t particles_is_using_local_coords(RID p_particles) {
- Particles *particles = particles_owner.getornull(p_particles);
+ Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND_V(!particles, false);
return particles->use_local_coords;
}
_FORCE_INLINE_ RID particles_get_instance_buffer_uniform_set(RID p_particles, RID p_shader, uint32_t p_set) {
- Particles *particles = particles_owner.getornull(p_particles);
+ Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND_V(!particles, RID());
if (particles->particles_transforms_buffer_uniform_set.is_null()) {
_particles_update_buffers(particles);
diff --git a/servers/rendering/renderer_rd/shader_compiler_rd.cpp b/servers/rendering/renderer_rd/shader_compiler_rd.cpp
index bad37f5c25..42d11d8bc1 100644
--- a/servers/rendering/renderer_rd/shader_compiler_rd.cpp
+++ b/servers/rendering/renderer_rd/shader_compiler_rd.cpp
@@ -91,7 +91,7 @@ static int _get_datatype_size(SL::DataType p_type) {
case SL::TYPE_VEC4:
return 16;
case SL::TYPE_MAT2:
- return 32; //4 * 4 + 4 * 4
+ return 32; // 4 * 4 + 4 * 4
case SL::TYPE_MAT3:
return 48; // 4 * 4 + 4 * 4 + 4 * 4
case SL::TYPE_MAT4:
@@ -566,11 +566,11 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
int max_texture_uniforms = 0;
int max_uniforms = 0;
- for (Map<StringName, SL::ShaderNode::Uniform>::Element *E = pnode->uniforms.front(); E; E = E->next()) {
- if (SL::is_sampler_type(E->get().type)) {
+ for (const KeyValue<StringName, SL::ShaderNode::Uniform> &E : pnode->uniforms) {
+ if (SL::is_sampler_type(E.value.type)) {
max_texture_uniforms++;
} else {
- if (E->get().scope == SL::ShaderNode::Uniform::SCOPE_INSTANCE) {
+ if (E.value.scope == SL::ShaderNode::Uniform::SCOPE_INSTANCE) {
continue; // Instances are indexed directly, don't need index uniforms.
}
@@ -590,8 +590,8 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
Vector<StringName> uniform_names;
- for (Map<StringName, SL::ShaderNode::Uniform>::Element *E = pnode->uniforms.front(); E; E = E->next()) {
- uniform_names.push_back(E->key());
+ for (const KeyValue<StringName, SL::ShaderNode::Uniform> &E : pnode->uniforms) {
+ uniform_names.push_back(E.key);
}
uniform_names.sort_custom<StringName::AlphCompare>(); //ensure order is deterministic so the same shader is always produced
@@ -608,7 +608,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
continue; // Instances are indexed directly, don't need index uniforms.
}
if (SL::is_sampler_type(uniform.type)) {
- ucode = "layout(set = " + itos(actions.texture_layout_set) + ", binding = " + itos(actions.base_texture_binding_index + uniform.texture_order) + ") uniform ";
+ ucode = "layout(set = " + itos(actions.texture_layout_set) + ", binding = " + itos(actions.base_texture_binding_index + uniform.texture_binding) + ") uniform ";
}
bool is_buffer_global = !SL::is_sampler_type(uniform.type) && uniform.scope == SL::ShaderNode::Uniform::SCOPE_GLOBAL;
@@ -622,6 +622,11 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
}
ucode += " " + _mkid(uniform_name);
+ if (uniform.array_size > 0) {
+ ucode += "[";
+ ucode += itos(uniform.array_size);
+ ucode += "]";
+ }
ucode += ";\n";
if (SL::is_sampler_type(uniform.type)) {
for (int j = 0; j < STAGE_MAX; j++) {
@@ -635,6 +640,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
texture.filter = uniform.filter;
texture.repeat = uniform.repeat;
texture.global = uniform.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL;
+ texture.array_size = uniform.array_size;
if (texture.global) {
r_gen_code.uses_global_textures = true;
}
@@ -650,7 +656,16 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
uniform_sizes.write[uniform.order] = _get_datatype_size(ShaderLanguage::TYPE_UINT);
uniform_alignments.write[uniform.order] = _get_datatype_alignment(ShaderLanguage::TYPE_UINT);
} else {
- uniform_sizes.write[uniform.order] = _get_datatype_size(uniform.type);
+ if (uniform.array_size > 0) {
+ int size = _get_datatype_size(uniform.type) * uniform.array_size;
+ int m = (16 * uniform.array_size);
+ if ((size % m) != 0) {
+ size += m - (size % m);
+ }
+ uniform_sizes.write[uniform.order] = size;
+ } else {
+ uniform_sizes.write[uniform.order] = _get_datatype_size(uniform.type);
+ }
uniform_alignments.write[uniform.order] = _get_datatype_alignment(uniform.type);
}
}
@@ -724,8 +739,8 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
Vector<StringName> varying_names;
- for (Map<StringName, SL::ShaderNode::Varying>::Element *E = pnode->varyings.front(); E; E = E->next()) {
- varying_names.push_back(E->key());
+ for (const KeyValue<StringName, SL::ShaderNode::Varying> &E : pnode->varyings) {
+ varying_names.push_back(E.key);
}
varying_names.sort_custom<StringName::AlphCompare>(); //ensure order is deterministic so the same shader is always produced
@@ -1074,10 +1089,32 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
if (p_default_actions.renames.has(anode->name)) {
code = p_default_actions.renames[anode->name];
} else {
- if (use_fragment_varying) {
- code = "frag_to_light.";
+ if (shader->uniforms.has(anode->name)) {
+ //its a uniform!
+ const ShaderLanguage::ShaderNode::Uniform &u = shader->uniforms[anode->name];
+ if (u.texture_order >= 0) {
+ code = _mkid(anode->name); //texture, use as is
+ } else {
+ //a scalar or vector
+ 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);
+ } 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);
+ } else {
+ //regular uniform, index from UBO
+ code = actions.base_uniform_string + _mkid(anode->name);
+ }
+ }
+ } else {
+ if (use_fragment_varying) {
+ code = "frag_to_light.";
+ }
+ code += _mkid(anode->name);
}
- code += _mkid(anode->name);
}
if (anode->call_expression != nullptr) {
@@ -1165,6 +1202,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
SL::VariableNode *vnode = (SL::VariableNode *)onode->arguments[0];
bool is_texture_func = false;
+ bool is_screen_texture = false;
if (onode->op == SL::OP_STRUCT) {
code += _mkid(vnode->name);
} else if (onode->op == SL::OP_CONSTRUCT) {
@@ -1192,50 +1230,73 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
code += ", ";
}
String node_code = _dump_node_code(onode->arguments[i], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
- if (is_texture_func && i == 1 && onode->arguments[i]->type == SL::Node::TYPE_VARIABLE) {
+ if (is_texture_func && i == 1) {
//need to map from texture to sampler in order to sample
- const SL::VariableNode *varnode = static_cast<const SL::VariableNode *>(onode->arguments[i]);
+ StringName texture_uniform;
+ bool correct_texture_uniform = false;
+
+ switch (onode->arguments[i]->type) {
+ case SL::Node::TYPE_VARIABLE: {
+ const SL::VariableNode *varnode = static_cast<const SL::VariableNode *>(onode->arguments[i]);
+ texture_uniform = varnode->name;
+ correct_texture_uniform = true;
+ } break;
+ case SL::Node::TYPE_ARRAY: {
+ const SL::ArrayNode *anode = static_cast<const SL::ArrayNode *>(onode->arguments[i]);
+ texture_uniform = anode->name;
+ correct_texture_uniform = true;
+ } break;
+ default:
+ break;
+ }
- StringName texture_uniform = varnode->name;
+ if (correct_texture_uniform) {
+ is_screen_texture = (texture_uniform == "SCREEN_TEXTURE");
- String sampler_name;
+ String sampler_name;
- if (actions.custom_samplers.has(texture_uniform)) {
- sampler_name = actions.custom_samplers[texture_uniform];
- } else {
- if (shader->uniforms.has(texture_uniform)) {
- sampler_name = _get_sampler_name(shader->uniforms[texture_uniform].filter, shader->uniforms[texture_uniform].repeat);
+ if (actions.custom_samplers.has(texture_uniform)) {
+ sampler_name = actions.custom_samplers[texture_uniform];
} else {
- bool found = false;
-
- for (int j = 0; j < function->arguments.size(); j++) {
- if (function->arguments[j].name == texture_uniform) {
- if (function->arguments[j].tex_builtin_check) {
- ERR_CONTINUE(!actions.custom_samplers.has(function->arguments[j].tex_builtin));
- sampler_name = actions.custom_samplers[function->arguments[j].tex_builtin];
- found = true;
- break;
- }
- if (function->arguments[j].tex_argument_check) {
- sampler_name = _get_sampler_name(function->arguments[j].tex_argument_filter, function->arguments[j].tex_argument_repeat);
- found = true;
- break;
+ if (shader->uniforms.has(texture_uniform)) {
+ sampler_name = _get_sampler_name(shader->uniforms[texture_uniform].filter, shader->uniforms[texture_uniform].repeat);
+ } else {
+ bool found = false;
+
+ for (int j = 0; j < function->arguments.size(); j++) {
+ if (function->arguments[j].name == texture_uniform) {
+ if (function->arguments[j].tex_builtin_check) {
+ ERR_CONTINUE(!actions.custom_samplers.has(function->arguments[j].tex_builtin));
+ sampler_name = actions.custom_samplers[function->arguments[j].tex_builtin];
+ found = true;
+ break;
+ }
+ if (function->arguments[j].tex_argument_check) {
+ sampler_name = _get_sampler_name(function->arguments[j].tex_argument_filter, function->arguments[j].tex_argument_repeat);
+ found = true;
+ break;
+ }
}
}
- }
- if (!found) {
- //function was most likely unused, so use anything (compiler will remove it anyway)
- sampler_name = _get_sampler_name(ShaderLanguage::FILTER_DEFAULT, ShaderLanguage::REPEAT_DEFAULT);
+ if (!found) {
+ //function was most likely unused, so use anything (compiler will remove it anyway)
+ sampler_name = _get_sampler_name(ShaderLanguage::FILTER_DEFAULT, ShaderLanguage::REPEAT_DEFAULT);
+ }
}
}
- }
- code += ShaderLanguage::get_datatype_name(onode->arguments[i]->get_datatype()) + "(" + node_code + ", " + sampler_name + ")";
+ code += ShaderLanguage::get_datatype_name(onode->arguments[i]->get_datatype()) + "(" + node_code + ", " + sampler_name + ")";
+ } else {
+ code += node_code;
+ }
} else {
code += node_code;
}
}
code += ")";
+ if (is_screen_texture && actions.apply_luminance_multiplier) {
+ code = "(" + code + " * vec4(vec3(sc_luminance_multiplier), 1.0))";
+ }
} break;
case SL::OP_INDEX: {
code += _dump_node_code(onode->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
@@ -1402,6 +1463,7 @@ void ShaderCompilerRD::initialize(DefaultIdentifierActions p_actions) {
texture_functions.insert("textureLod");
texture_functions.insert("textureProjLod");
texture_functions.insert("textureGrad");
+ texture_functions.insert("textureGather");
texture_functions.insert("textureSize");
texture_functions.insert("texelFetch");
}
diff --git a/servers/rendering/renderer_rd/shader_compiler_rd.h b/servers/rendering/renderer_rd/shader_compiler_rd.h
index 2da127ffa3..2ab689c27c 100644
--- a/servers/rendering/renderer_rd/shader_compiler_rd.h
+++ b/servers/rendering/renderer_rd/shader_compiler_rd.h
@@ -65,6 +65,7 @@ public:
ShaderLanguage::TextureFilter filter;
ShaderLanguage::TextureRepeat repeat;
bool global;
+ int array_size;
};
Vector<Texture> texture_uniforms;
@@ -95,6 +96,7 @@ public:
String global_buffer_array_variable;
String instance_uniform_index_variable;
uint32_t base_varying_index = 0;
+ bool apply_luminance_multiplier = false;
};
private:
diff --git a/servers/rendering/renderer_rd/shader_rd.cpp b/servers/rendering/renderer_rd/shader_rd.cpp
index 82efa1318c..b9a8947fa2 100644
--- a/servers/rendering/renderer_rd/shader_rd.cpp
+++ b/servers/rendering/renderer_rd/shader_rd.cpp
@@ -174,8 +174,8 @@ void ShaderRD::_build_variant_code(StringBuilder &builder, uint32_t p_variant, c
if (p_version->uniforms.size()) {
builder.append("#define MATERIAL_UNIFORMS_USED\n");
}
- for (Map<StringName, CharString>::Element *E = p_version->code_sections.front(); E; E = E->next()) {
- builder.append(String("#define ") + String(E->key()) + "_CODE_USED\n");
+ for (const KeyValue<StringName, CharString> &E : p_version->code_sections) {
+ builder.append(String("#define ") + String(E.key) + "_CODE_USED\n");
}
} break;
case StageTemplate::Chunk::TYPE_MATERIAL_UNIFORMS: {
@@ -292,7 +292,7 @@ void ShaderRD::_compile_variant(uint32_t p_variant, Version *p_version) {
}
RS::ShaderNativeSourceCode ShaderRD::version_get_native_source_code(RID p_version) {
- Version *version = version_owner.getornull(p_version);
+ Version *version = version_owner.get_or_null(p_version);
RS::ShaderNativeSourceCode source_code;
ERR_FAIL_COND_V(!version, source_code);
@@ -355,8 +355,8 @@ String ShaderRD::_version_get_sha1(Version *p_version) const {
hash_build.append(p_version->compute_globals.get_data());
Vector<StringName> code_sections;
- for (Map<StringName, CharString>::Element *E = p_version->code_sections.front(); E; E = E->next()) {
- code_sections.push_back(E->key());
+ for (const KeyValue<StringName, CharString> &E : p_version->code_sections) {
+ code_sections.push_back(E.key);
}
code_sections.sort_custom<StringName::AlphCompare>();
@@ -524,14 +524,14 @@ void ShaderRD::_compile_version(Version *p_version) {
void ShaderRD::version_set_code(RID p_version, const Map<String, String> &p_code, const String &p_uniforms, const String &p_vertex_globals, const String &p_fragment_globals, const Vector<String> &p_custom_defines) {
ERR_FAIL_COND(is_compute);
- Version *version = version_owner.getornull(p_version);
+ Version *version = version_owner.get_or_null(p_version);
ERR_FAIL_COND(!version);
version->vertex_globals = p_vertex_globals.utf8();
version->fragment_globals = p_fragment_globals.utf8();
version->uniforms = p_uniforms.utf8();
version->code_sections.clear();
- for (Map<String, String>::Element *E = p_code.front(); E; E = E->next()) {
- version->code_sections[StringName(E->key().to_upper())] = E->get().utf8();
+ for (const KeyValue<String, String> &E : p_code) {
+ version->code_sections[StringName(E.key.to_upper())] = E.value.utf8();
}
version->custom_defines.clear();
@@ -549,15 +549,15 @@ void ShaderRD::version_set_code(RID p_version, const Map<String, String> &p_code
void ShaderRD::version_set_compute_code(RID p_version, const Map<String, String> &p_code, const String &p_uniforms, const String &p_compute_globals, const Vector<String> &p_custom_defines) {
ERR_FAIL_COND(!is_compute);
- Version *version = version_owner.getornull(p_version);
+ Version *version = version_owner.get_or_null(p_version);
ERR_FAIL_COND(!version);
version->compute_globals = p_compute_globals.utf8();
version->uniforms = p_uniforms.utf8();
version->code_sections.clear();
- for (Map<String, String>::Element *E = p_code.front(); E; E = E->next()) {
- version->code_sections[StringName(E->key().to_upper())] = E->get().utf8();
+ for (const KeyValue<String, String> &E : p_code) {
+ version->code_sections[StringName(E.key.to_upper())] = E.value.utf8();
}
version->custom_defines.clear();
@@ -573,7 +573,7 @@ void ShaderRD::version_set_compute_code(RID p_version, const Map<String, String>
}
bool ShaderRD::version_is_valid(RID p_version) {
- Version *version = version_owner.getornull(p_version);
+ Version *version = version_owner.get_or_null(p_version);
ERR_FAIL_COND_V(!version, false);
if (version->dirty) {
@@ -585,7 +585,7 @@ bool ShaderRD::version_is_valid(RID p_version) {
bool ShaderRD::version_free(RID p_version) {
if (version_owner.owns(p_version)) {
- Version *version = version_owner.getornull(p_version);
+ Version *version = version_owner.get_or_null(p_version);
_clear_version(version);
version_owner.free(p_version);
} else {
diff --git a/servers/rendering/renderer_rd/shader_rd.h b/servers/rendering/renderer_rd/shader_rd.h
index 529328f0ed..984b168659 100644
--- a/servers/rendering/renderer_rd/shader_rd.h
+++ b/servers/rendering/renderer_rd/shader_rd.h
@@ -141,7 +141,7 @@ public:
ERR_FAIL_INDEX_V(p_variant, variant_defines.size(), RID());
ERR_FAIL_COND_V(!variants_enabled[p_variant], RID());
- Version *version = version_owner.getornull(p_version);
+ Version *version = version_owner.get_or_null(p_version);
ERR_FAIL_COND_V(!version, RID());
if (version->dirty) {
diff --git a/servers/rendering/renderer_rd/shaders/blit.glsl b/servers/rendering/renderer_rd/shaders/blit.glsl
index 967da1e6e4..8051f96738 100644
--- a/servers/rendering/renderer_rd/shaders/blit.glsl
+++ b/servers/rendering/renderer_rd/shaders/blit.glsl
@@ -5,6 +5,7 @@
#VERSION_DEFINES
layout(push_constant, binding = 0, std140) uniform Pos {
+ vec4 src_rect;
vec4 dst_rect;
vec2 eye_center;
@@ -22,8 +23,8 @@ layout(location = 0) out vec2 uv;
void main() {
vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
- uv = base_arr[gl_VertexIndex];
- vec2 vtx = data.dst_rect.xy + uv * data.dst_rect.zw;
+ uv = data.src_rect.xy + base_arr[gl_VertexIndex] * data.src_rect.zw;
+ vec2 vtx = data.dst_rect.xy + base_arr[gl_VertexIndex] * data.dst_rect.zw;
gl_Position = vec4(vtx * 2.0 - 1.0, 0.0, 1.0);
}
@@ -34,6 +35,7 @@ void main() {
#VERSION_DEFINES
layout(push_constant, binding = 0, std140) uniform Pos {
+ vec4 src_rect;
vec4 dst_rect;
vec2 eye_center;
diff --git a/servers/rendering/renderer_rd/shaders/blur_raster.glsl b/servers/rendering/renderer_rd/shaders/blur_raster.glsl
index 0789a4b396..f8b4e3f610 100644
--- a/servers/rendering/renderer_rd/shaders/blur_raster.glsl
+++ b/servers/rendering/renderer_rd/shaders/blur_raster.glsl
@@ -38,6 +38,8 @@ layout(set = 1, binding = 0) uniform sampler2D source_auto_exposure;
layout(location = 0) out vec4 frag_color;
void main() {
+ // We do not apply our color scale for our mobile renderer here, we'll leave our colors at half brightness and apply scale in the tonemap raster.
+
#ifdef MODE_MIPMAP
vec2 pix_size = blur.pixel_size;
diff --git a/servers/rendering/renderer_rd/shaders/bokeh_dof_raster.glsl b/servers/rendering/renderer_rd/shaders/bokeh_dof_raster.glsl
index 43a2a29616..a3b3938ee9 100644
--- a/servers/rendering/renderer_rd/shaders/bokeh_dof_raster.glsl
+++ b/servers/rendering/renderer_rd/shaders/bokeh_dof_raster.glsl
@@ -47,7 +47,7 @@ layout(set = 2, binding = 0) uniform sampler2D original_weight;
#endif
//DOF
-// Bokeh single pass implementation based on http://tuxedolabs.blogspot.com/2018/05/bokeh-depth-of-field-in-single-pass.html
+// Bokeh single pass implementation based on https://tuxedolabs.blogspot.com/2018/05/bokeh-depth-of-field-in-single-pass.html
#ifdef MODE_GEN_BLUR_SIZE
diff --git a/servers/rendering/renderer_rd/shaders/canvas.glsl b/servers/rendering/renderer_rd/shaders/canvas.glsl
index a443bcdcb8..2911e8b731 100644
--- a/servers/rendering/renderer_rd/shaders/canvas.glsl
+++ b/servers/rendering/renderer_rd/shaders/canvas.glsl
@@ -458,6 +458,14 @@ void light_blend_compute(uint light_base, vec4 light_color, inout vec3 color) {
#endif
+float msdf_median(float r, float g, float b, float a) {
+ return min(max(min(r, g), min(max(r, g), b)), a);
+}
+
+vec2 msdf_map(vec2 value, vec2 in_min, vec2 in_max, vec2 out_min, vec2 out_max) {
+ return out_min + (out_max - out_min) * (value - in_min) / (in_max - in_min);
+}
+
void main() {
vec4 color = color_interp;
vec2 uv = uv_interp;
@@ -485,7 +493,34 @@ void main() {
#endif
- color *= texture(sampler2D(color_texture, texture_sampler), uv);
+#ifndef USE_PRIMITIVE
+ if (bool(draw_data.flags & FLAGS_USE_MSDF)) {
+ float px_range = draw_data.ninepatch_margins.x;
+ float outline_thickness = draw_data.ninepatch_margins.y;
+ //float reserved1 = draw_data.ninepatch_margins.z;
+ //float reserved2 = draw_data.ninepatch_margins.w;
+
+ vec4 msdf_sample = texture(sampler2D(color_texture, texture_sampler), uv);
+ vec2 msdf_size = vec2(textureSize(sampler2D(color_texture, texture_sampler), 0));
+ vec2 dest_size = vec2(1.0) / fwidth(uv);
+ float px_size = max(0.5 * dot((vec2(px_range) / msdf_size), dest_size), 1.0);
+ float d = msdf_median(msdf_sample.r, msdf_sample.g, msdf_sample.b, msdf_sample.a) - 0.5;
+
+ if (outline_thickness > 0) {
+ float cr = clamp(outline_thickness, 0.0, px_range / 2) / px_range;
+ float a = clamp((d + cr) * px_size, 0.0, 1.0);
+ color.a = a * color.a;
+ } else {
+ float a = clamp(d * px_size + 0.5, 0.0, 1.0);
+ color.a = a * color.a;
+ }
+
+ } else {
+#else
+ {
+#endif
+ color *= texture(sampler2D(color_texture, texture_sampler), uv);
+ }
uint light_count = (draw_data.flags >> FLAGS_LIGHT_COUNT_SHIFT) & 0xF; //max 16 lights
bool using_light = light_count > 0 || canvas_data.directional_light_count > 0;
diff --git a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl
index 451f9b0089..0cff505cae 100644
--- a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl
@@ -24,6 +24,8 @@
#define FLAGS_DEFAULT_NORMAL_MAP_USED (1 << 26)
#define FLAGS_DEFAULT_SPECULAR_MAP_USED (1 << 27)
+#define FLAGS_USE_MSDF (1 << 28)
+
#define SAMPLER_NEAREST_CLAMP 0
#define SAMPLER_LINEAR_CLAMP 1
#define SAMPLER_NEAREST_WITH_MIPMAPS_CLAMP 2
diff --git a/servers/rendering/renderer_rd/shaders/cluster_render.glsl b/servers/rendering/renderer_rd/shaders/cluster_render.glsl
index da7d189281..6d95722a57 100644
--- a/servers/rendering/renderer_rd/shaders/cluster_render.glsl
+++ b/servers/rendering/renderer_rd/shaders/cluster_render.glsl
@@ -117,7 +117,7 @@ void main() {
uint cluster_thread_group_index;
if (!gl_HelperInvocation) {
- //http://advances.realtimerendering.com/s2017/2017_Sig_Improved_Culling_final.pdf
+ //https://advances.realtimerendering.com/s2017/2017_Sig_Improved_Culling_final.pdf
uvec4 mask;
diff --git a/servers/rendering/renderer_rd/shaders/cubemap_roughness_inc.glsl b/servers/rendering/renderer_rd/shaders/cubemap_roughness_inc.glsl
index 80c0ac4fb4..be12be5dec 100644
--- a/servers/rendering/renderer_rd/shaders/cubemap_roughness_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/cubemap_roughness_inc.glsl
@@ -69,13 +69,13 @@ vec3 ImportanceSampleGGX(vec2 Xi, float Roughness, vec3 N) {
return TangentX * H.x + TangentY * H.y + N * H.z;
}
-// http://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html
+// https://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html
float GGX(float NdotV, float a) {
float k = a / 2.0;
return NdotV / (NdotV * (1.0 - k) + k);
}
-// http://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html
+// https://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html
float G_Smith(float a, float nDotV, float nDotL) {
return GGX(nDotL, a * a) * GGX(nDotV, a * a);
}
diff --git a/servers/rendering/renderer_rd/shaders/gi.glsl b/servers/rendering/renderer_rd/shaders/gi.glsl
index 60c881881d..5528ea3659 100644
--- a/servers/rendering/renderer_rd/shaders/gi.glsl
+++ b/servers/rendering/renderer_rd/shaders/gi.glsl
@@ -97,12 +97,10 @@ layout(push_constant, binding = 0, std430) uniform Params {
vec4 proj_info;
- vec3 ao_color;
uint max_voxel_gi_instances;
-
bool high_quality_vct;
bool orthogonal;
- uint pad[2];
+ uint pad;
mat3x4 cam_rotation;
}
diff --git a/servers/rendering/renderer_rd/shaders/giprobe_write.glsl b/servers/rendering/renderer_rd/shaders/giprobe_write.glsl
index 5dc2d08a3b..25d87ca45d 100644
--- a/servers/rendering/renderer_rd/shaders/giprobe_write.glsl
+++ b/servers/rendering/renderer_rd/shaders/giprobe_write.glsl
@@ -202,12 +202,7 @@ void main() {
vec3 emission = vec3(ivec3(cell_data.data[cell_index].emission & 0x3FF, (cell_data.data[cell_index].emission >> 10) & 0x7FF, cell_data.data[cell_index].emission >> 21)) * params.emission_scale;
vec4 normal = unpackSnorm4x8(cell_data.data[cell_index].normal);
-#ifdef MODE_ANISOTROPIC
- vec3 accum[6] = vec3[](vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0));
- const vec3 accum_dirs[6] = vec3[](vec3(1.0, 0.0, 0.0), vec3(-1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(0.0, -1.0, 0.0), vec3(0.0, 0.0, 1.0), vec3(0.0, 0.0, -1.0));
-#else
vec3 accum = vec3(0.0);
-#endif
for (uint i = 0; i < params.light_count; i++) {
float attenuation;
@@ -242,77 +237,35 @@ void main() {
vec3 light = lights.data[i].color * albedo.rgb * attenuation * lights.data[i].energy;
-#ifdef MODE_ANISOTROPIC
- for (uint j = 0; j < 6; j++) {
- accum[j] += max(0.0, dot(accum_dir, -light_dir)) * light + emission;
- }
-#else
if (length(normal.xyz) > 0.2) {
accum += max(0.0, dot(normal.xyz, -light_dir)) * light + emission;
} else {
//all directions
accum += light + emission;
}
-#endif
}
-#ifdef MODE_ANISOTROPIC
-
- output.data[cell_index * 6 + 0] = vec4(accum[0], 0.0);
- output.data[cell_index * 6 + 1] = vec4(accum[1], 0.0);
- output.data[cell_index * 6 + 2] = vec4(accum[2], 0.0);
- output.data[cell_index * 6 + 3] = vec4(accum[3], 0.0);
- output.data[cell_index * 6 + 4] = vec4(accum[4], 0.0);
- output.data[cell_index * 6 + 5] = vec4(accum[5], 0.0);
-#else
output.data[cell_index] = vec4(accum, 0.0);
-#endif
-
#endif //MODE_COMPUTE_LIGHT
#ifdef MODE_UPDATE_MIPMAPS
{
-#ifdef MODE_ANISOTROPIC
- vec3 light_accum[6] = vec3[](vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0));
-#else
vec3 light_accum = vec3(0.0);
-#endif
float count = 0.0;
for (uint i = 0; i < 8; i++) {
uint child_index = cell_children.data[cell_index].children[i];
if (child_index == NO_CHILDREN) {
continue;
}
-#ifdef MODE_ANISOTROPIC
- light_accum[1] += output.data[child_index * 6 + 0].rgb;
- light_accum[2] += output.data[child_index * 6 + 1].rgb;
- light_accum[3] += output.data[child_index * 6 + 2].rgb;
- light_accum[4] += output.data[child_index * 6 + 3].rgb;
- light_accum[5] += output.data[child_index * 6 + 4].rgb;
- light_accum[6] += output.data[child_index * 6 + 5].rgb;
-
-#else
light_accum += output.data[child_index].rgb;
-#endif
-
count += 1.0;
}
float divisor = mix(8.0, count, params.propagation);
-#ifdef MODE_ANISOTROPIC
- output.data[cell_index * 6 + 0] = vec4(light_accum[0] / divisor, 0.0);
- output.data[cell_index * 6 + 1] = vec4(light_accum[1] / divisor, 0.0);
- output.data[cell_index * 6 + 2] = vec4(light_accum[2] / divisor, 0.0);
- output.data[cell_index * 6 + 3] = vec4(light_accum[3] / divisor, 0.0);
- output.data[cell_index * 6 + 4] = vec4(light_accum[4] / divisor, 0.0);
- output.data[cell_index * 6 + 5] = vec4(light_accum[5] / divisor, 0.0);
-
-#else
output.data[cell_index] = vec4(light_accum / divisor, 0.0);
-#endif
}
#endif
diff --git a/servers/rendering/renderer_rd/shaders/luminance_reduce_raster_inc.glsl b/servers/rendering/renderer_rd/shaders/luminance_reduce_raster_inc.glsl
index ed389ffe56..3cde9923fa 100644
--- a/servers/rendering/renderer_rd/shaders/luminance_reduce_raster_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/luminance_reduce_raster_inc.glsl
@@ -6,6 +6,6 @@ layout(push_constant, binding = 1, std430) uniform PushConstant {
float exposure_adjust;
float min_luminance;
float max_luminance;
- float pad;
+ uint pad1;
}
settings;
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
index adf9f20618..5261868155 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
@@ -118,7 +118,7 @@ void main() {
mat3 world_normal_matrix;
if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_NON_UNIFORM_SCALE)) {
- world_normal_matrix = inverse(mat3(world_matrix));
+ world_normal_matrix = transpose(inverse(mat3(world_matrix)));
} else {
world_normal_matrix = mat3(world_matrix);
}
@@ -374,6 +374,9 @@ layout(constant_id = 9) const uint sc_directional_penumbra_shadow_samples = 4;
layout(constant_id = 10) const bool sc_decal_use_mipmaps = true;
layout(constant_id = 11) const bool sc_projector_use_mipmaps = true;
+// not used in clustered renderer but we share some code with the mobile renderer that requires this.
+const float sc_luminance_multiplier = 1.0;
+
#include "scene_forward_clustered_inc.glsl"
/* Varyings */
@@ -521,14 +524,14 @@ vec4 fog_process(vec3 vertex) {
}
}
- float fog_amount = 1.0 - exp(min(0.0, vertex.z * scene_data.fog_density));
+ float fog_amount = 1.0 - exp(min(0.0, -length(vertex) * scene_data.fog_density));
- if (abs(scene_data.fog_height_density) > 0.001) {
+ if (abs(scene_data.fog_height_density) >= 0.0001) {
float y = (scene_data.camera_matrix * vec4(vertex, 1.0)).y;
- float y_dist = scene_data.fog_height - y;
+ float y_dist = y - scene_data.fog_height;
- float vfog_amount = clamp(exp(y_dist * scene_data.fog_height_density), 0.0, 1.0);
+ float vfog_amount = 1.0 - exp(min(0.0, y_dist * scene_data.fog_height_density));
fog_amount = max(vfog_amount, fog_amount);
}
@@ -881,7 +884,7 @@ void main() {
#ifdef NORMAL_USED
if (scene_data.roughness_limiter_enabled) {
- //http://www.jp.square-enix.com/tech/library/pdf/ImprovedGeometricSpecularAA.pdf
+ //https://www.jp.square-enix.com/tech/library/pdf/ImprovedGeometricSpecularAA.pdf
float roughness2 = roughness * roughness;
vec3 dndu = dFdx(normal), dndv = dFdy(normal);
float variance = scene_data.roughness_limiter_amount * (dot(dndu, dndu) + dot(dndv, dndv));
@@ -900,6 +903,7 @@ void main() {
if (scene_data.use_reflection_cubemap) {
vec3 ref_vec = reflect(-view, normal);
+ float horizon = min(1.0 + dot(ref_vec, normal), 1.0);
ref_vec = scene_data.radiance_inverse_xform * ref_vec;
#ifdef USE_RADIANCE_CUBEMAP_ARRAY
@@ -912,7 +916,6 @@ void main() {
specular_light = textureLod(samplerCube(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), ref_vec, roughness * MAX_ROUGHNESS_LOD).rgb;
#endif //USE_RADIANCE_CUBEMAP_ARRAY
- float horizon = min(1.0 + dot(ref_vec, normal), 1.0);
specular_light *= horizon * horizon;
specular_light *= scene_data.ambient_light_color_energy.a;
}
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 b53bf6a6d4..b943d81784 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl
@@ -209,8 +209,6 @@ layout(set = 1, binding = 0, std140) uniform SceneData {
float roughness_limiter_limit;
uvec2 roughness_limiter_pad;
- vec4 ao_color;
-
mat4 sdf_to_bounds;
ivec3 sdf_offset;
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
index ef2fde7516..4d466342f8 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
@@ -97,6 +97,11 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte
#endif
inout vec3 diffuse_light, inout vec3 specular_light) {
+ vec4 orms_unpacked = unpackUnorm4x8(orms);
+
+ float roughness = orms_unpacked.y;
+ float metallic = orms_unpacked.z;
+
#if defined(LIGHT_CODE_USED)
// light is written by the light shader
@@ -125,9 +130,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte
float cLdotH = clamp(A + dot(L, H), 0.0, 1.0);
#endif
- float metallic = unpackUnorm4x8(orms).z;
if (metallic < 1.0) {
- float roughness = unpackUnorm4x8(orms).y;
float diffuse_brdf_NL; // BRDF times N.L for calculating diffuse radiance
#if defined(DIFFUSE_LAMBERT_WRAP)
@@ -199,7 +202,6 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte
#endif //LIGHT_TRANSMITTANCE_USED
}
- float roughness = unpackUnorm4x8(orms).y;
if (roughness > 0.0) { // FIXME: roughness == 0 should not disable specular light entirely
// D
@@ -211,7 +213,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte
float blinn = pow(cNdotH, shininess);
blinn *= (shininess + 2.0) * (1.0 / (8.0 * M_PI));
- specular_light += light_color * attenuation * specular_amount * blinn * f0 * unpackUnorm4x8(orms).w;
+ specular_light += light_color * attenuation * specular_amount * blinn * f0 * orms_unpacked.w;
#elif defined(SPECULAR_PHONG)
@@ -221,7 +223,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte
float phong = pow(cRdotV, shininess);
phong *= (shininess + 1.0) * (1.0 / (8.0 * M_PI));
- specular_light += light_color * attenuation * specular_amount * phong * f0 * unpackUnorm4x8(orms).w;
+ specular_light += light_color * attenuation * specular_amount * phong * f0 * orms_unpacked.w;
#elif defined(SPECULAR_TOON)
@@ -288,7 +290,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte
#ifndef USE_NO_SHADOWS
// Interleaved Gradient Noise
-// http://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare
+// https://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare
float quick_hash(vec2 pos) {
const vec3 magic = vec3(0.06711056f, 0.00583715f, 52.9829189f);
return fract(magic.z * fract(dot(pos, magic.xy)));
@@ -969,7 +971,7 @@ void reflection_process(uint ref_index, vec3 vertex, vec3 normal, float roughnes
vec4 reflection;
- reflection.rgb = textureLod(samplerCubeArray(reflection_atlas, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(local_ref_vec, reflections.data[ref_index].index), roughness * MAX_ROUGHNESS_LOD).rgb;
+ reflection.rgb = textureLod(samplerCubeArray(reflection_atlas, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(local_ref_vec, reflections.data[ref_index].index), roughness * MAX_ROUGHNESS_LOD).rgb * sc_luminance_multiplier;
if (reflections.data[ref_index].exterior) {
reflection.rgb = mix(specular_light, reflection.rgb, blend);
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
index a2a54a0511..0ee68d5e10 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
@@ -124,7 +124,7 @@ void main() {
mat3 world_normal_matrix;
if (bool(draw_call.flags & INSTANCE_FLAGS_NON_UNIFORM_SCALE)) {
- world_normal_matrix = inverse(mat3(world_matrix));
+ world_normal_matrix = transpose(inverse(mat3(world_matrix)));
} else {
world_normal_matrix = mat3(world_matrix);
}
@@ -401,6 +401,8 @@ layout(constant_id = 14) const bool sc_disable_fog = false;
#endif //!MODE_RENDER_DEPTH
+layout(constant_id = 15) const float sc_luminance_multiplier = 2.0;
+
/* Include our forward mobile UBOs definitions etc. */
#include "scene_forward_mobile_inc.glsl"
@@ -548,14 +550,14 @@ vec4 fog_process(vec3 vertex) {
}
}
- float fog_amount = 1.0 - exp(min(0.0, vertex.z * scene_data.fog_density));
+ float fog_amount = 1.0 - exp(min(0.0, -length(vertex) * scene_data.fog_density));
- if (abs(scene_data.fog_height_density) > 0.001) {
+ if (abs(scene_data.fog_height_density) >= 0.0001) {
float y = (scene_data.camera_matrix * vec4(vertex, 1.0)).y;
- float y_dist = scene_data.fog_height - y;
+ float y_dist = y - scene_data.fog_height;
- float vfog_amount = clamp(exp(y_dist * scene_data.fog_height_density), 0.0, 1.0);
+ float vfog_amount = 1.0 - exp(min(0.0, y_dist * scene_data.fog_height_density));
fog_amount = max(vfog_amount, fog_amount);
}
@@ -847,7 +849,7 @@ void main() {
#ifdef NORMAL_USED
if (scene_data.roughness_limiter_enabled) {
- //http://www.jp.square-enix.com/tech/library/pdf/ImprovedGeometricSpecularAA.pdf
+ //https://www.jp.square-enix.com/tech/library/pdf/ImprovedGeometricSpecularAA.pdf
float roughness2 = roughness * roughness;
vec3 dndu = dFdx(normal), dndv = dFdy(normal);
float variance = scene_data.roughness_limiter_amount * (dot(dndu, dndu) + dot(dndv, dndv));
@@ -866,6 +868,7 @@ void main() {
if (scene_data.use_reflection_cubemap) {
vec3 ref_vec = reflect(-view, normal);
+ float horizon = min(1.0 + dot(ref_vec, normal), 1.0);
ref_vec = scene_data.radiance_inverse_xform * ref_vec;
#ifdef USE_RADIANCE_CUBEMAP_ARRAY
@@ -878,7 +881,6 @@ void main() {
specular_light = textureLod(samplerCube(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), ref_vec, roughness * MAX_ROUGHNESS_LOD).rgb;
#endif //USE_RADIANCE_CUBEMAP_ARRAY
- float horizon = min(1.0 + dot(ref_vec, normal), 1.0);
specular_light *= horizon * horizon;
specular_light *= scene_data.ambient_light_color_energy.a;
}
@@ -1551,12 +1553,15 @@ void main() {
frag_color = vec4(albedo, alpha);
#else // MODE_UNSHADED
frag_color = vec4(emission + ambient_light + diffuse_light + specular_light, alpha);
- //frag_color = vec4(1.0);
#endif // MODE_UNSHADED
// Draw "fixed" fog before volumetric fog to ensure volumetric fog can appear in front of the sky.
frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a);
+ // On mobile we use a UNORM buffer with 10bpp which results in a range from 0.0 - 1.0 resulting in HDR breaking
+ // We divide by sc_luminance_multiplier to support a range from 0.0 - 2.0 both increasing precision on bright and darker images
+ frag_color.rgb = frag_color.rgb / sc_luminance_multiplier;
+
#endif //MODE_MULTIPLE_RENDER_TARGETS
#endif //MODE_RENDER_DEPTH
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 dd8879acb4..eb8fb49598 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl
@@ -170,8 +170,6 @@ layout(set = 1, binding = 0, std140) uniform SceneData {
mediump float roughness_limiter_limit;
uvec2 roughness_limiter_pad;
- mediump vec4 ao_color;
-
bool fog_enabled;
highp float fog_density;
highp float fog_height;
diff --git a/servers/rendering/renderer_rd/shaders/sdfgi_debug_probes.glsl b/servers/rendering/renderer_rd/shaders/sdfgi_debug_probes.glsl
index 0eacbc5363..4290d5b869 100644
--- a/servers/rendering/renderer_rd/shaders/sdfgi_debug_probes.glsl
+++ b/servers/rendering/renderer_rd/shaders/sdfgi_debug_probes.glsl
@@ -24,7 +24,7 @@ layout(push_constant, binding = 0, std430) uniform Params {
}
params;
-// http://in4k.untergrund.net/html_articles/hugi_27_-_coding_corner_polaris_sphere_tessellation_101.htm
+// https://in4k.untergrund.net/html_articles/hugi_27_-_coding_corner_polaris_sphere_tessellation_101.htm
vec3 get_sphere_vertex(uint p_vertex_id) {
float x_angle = float(p_vertex_id & 1u) + (p_vertex_id >> params.band_power);
diff --git a/servers/rendering/renderer_rd/shaders/sky.glsl b/servers/rendering/renderer_rd/shaders/sky.glsl
index 41c6325bc5..d07a454ade 100644
--- a/servers/rendering/renderer_rd/shaders/sky.glsl
+++ b/servers/rendering/renderer_rd/shaders/sky.glsl
@@ -17,6 +17,8 @@ layout(push_constant, binding = 1, std430) uniform Params {
vec4 projections[MAX_VIEWS];
vec4 position_multiplier;
float time;
+ float luminance_multiplier;
+ float pad[2];
}
params;
@@ -55,6 +57,8 @@ layout(push_constant, binding = 1, std430) uniform Params {
vec4 projections[MAX_VIEWS];
vec4 position_multiplier;
float time;
+ float luminance_multiplier;
+ float pad[2];
}
params;
@@ -199,17 +203,17 @@ void main() {
vec3 inverted_cube_normal = cube_normal;
inverted_cube_normal.z *= -1.0;
#ifdef USES_HALF_RES_COLOR
- half_res_color = texture(samplerCube(half_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), inverted_cube_normal);
+ half_res_color = texture(samplerCube(half_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), inverted_cube_normal) * params.luminance_multiplier;
#endif
#ifdef USES_QUARTER_RES_COLOR
- quarter_res_color = texture(samplerCube(quarter_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), inverted_cube_normal);
+ quarter_res_color = texture(samplerCube(quarter_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), inverted_cube_normal) * params.luminance_multiplier;
#endif
#else
#ifdef USES_HALF_RES_COLOR
- half_res_color = textureLod(sampler2D(half_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0);
+ half_res_color = textureLod(sampler2D(half_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0) * params.luminance_multiplier;
#endif
#ifdef USES_QUARTER_RES_COLOR
- quarter_res_color = textureLod(sampler2D(quarter_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0);
+ quarter_res_color = textureLod(sampler2D(quarter_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0) * params.luminance_multiplier;
#endif
#endif
@@ -246,4 +250,7 @@ void main() {
if (!AT_CUBEMAP_PASS && !AT_HALF_RES_PASS && !AT_QUARTER_RES_PASS) {
frag_color.a = 0.0;
}
+
+ // For mobile renderer we're dividing by 2.0 as we're using a UNORM buffer
+ frag_color.rgb = frag_color.rgb / params.luminance_multiplier;
}
diff --git a/servers/rendering/renderer_rd/shaders/tonemap.glsl b/servers/rendering/renderer_rd/shaders/tonemap.glsl
index 3c685c25b9..1ce3e04421 100644
--- a/servers/rendering/renderer_rd/shaders/tonemap.glsl
+++ b/servers/rendering/renderer_rd/shaders/tonemap.glsl
@@ -37,15 +37,15 @@ layout(location = 0) in vec2 uv_interp;
#ifdef SUBPASS
layout(input_attachment_index = 0, set = 0, binding = 0) uniform subpassInput input_color;
-#else
-#if MULTIVIEW
+#elif defined(MULTIVIEW)
layout(set = 0, binding = 0) uniform sampler2DArray source_color;
#else
layout(set = 0, binding = 0) uniform sampler2D source_color;
#endif
-#endif
+
layout(set = 1, binding = 0) uniform sampler2D source_auto_exposure;
layout(set = 2, binding = 0) uniform sampler2D source_glow;
+
#ifdef USE_1D_LUT
layout(set = 3, binding = 0) uniform sampler2D source_color_correction;
#else
@@ -71,7 +71,7 @@ layout(push_constant, binding = 1, std430) uniform Params {
float exposure;
float white;
float auto_exposure_grey;
- uint pad2;
+ float luminance_multiplier;
vec2 pixel_size;
bool use_fxaa;
@@ -169,16 +169,33 @@ vec3 tonemap_filmic(vec3 color, float white) {
return color_tonemapped / white_tonemapped;
}
+// Adapted from https://github.com/TheRealMJP/BakingLab/blob/master/BakingLab/ACES.hlsl
+// (MIT License).
vec3 tonemap_aces(vec3 color, float white) {
- const float exposure_bias = 0.85f;
- const float A = 2.51f * exposure_bias * exposure_bias;
- const float B = 0.03f * exposure_bias;
- const float C = 2.43f * exposure_bias * exposure_bias;
- const float D = 0.59f * exposure_bias;
- const float E = 0.14f;
-
- vec3 color_tonemapped = (color * (A * color + B)) / (color * (C * color + D) + E);
- float white_tonemapped = (white * (A * white + B)) / (white * (C * white + D) + E);
+ const float exposure_bias = 1.8f;
+ const float A = 0.0245786f;
+ const float B = 0.000090537f;
+ const float C = 0.983729f;
+ const float D = 0.432951f;
+ const float E = 0.238081f;
+
+ // Exposure bias baked into transform to save shader instructions. Equivalent to `color *= exposure_bias`
+ const mat3 rgb_to_rrt = mat3(
+ vec3(0.59719f * exposure_bias, 0.35458f * exposure_bias, 0.04823f * exposure_bias),
+ vec3(0.07600f * exposure_bias, 0.90834f * exposure_bias, 0.01566f * exposure_bias),
+ vec3(0.02840f * exposure_bias, 0.13383f * exposure_bias, 0.83777f * exposure_bias));
+
+ const mat3 odt_to_rgb = mat3(
+ vec3(1.60475f, -0.53108f, -0.07367f),
+ vec3(-0.10208f, 1.10813f, -0.00605f),
+ vec3(-0.00327f, -0.07276f, 1.07602f));
+
+ color *= rgb_to_rrt;
+ vec3 color_tonemapped = (color * (color + A) - B) / (color * (C * color + D) + E);
+ color_tonemapped *= odt_to_rgb;
+
+ white *= exposure_bias;
+ float white_tonemapped = (white * (white + A) - B) / (white * (C * white + D) + E);
return color_tonemapped / white_tonemapped;
}
@@ -200,15 +217,16 @@ vec3 linear_to_srgb(vec3 color) {
#define TONEMAPPER_ACES 3
vec3 apply_tonemapping(vec3 color, float white) { // inputs are LINEAR, always outputs clamped [0;1] color
-
+ // Ensure color values passed to tonemappers are positive.
+ // They can be negative in the case of negative lights, which leads to undesired behavior.
if (params.tonemapper == TONEMAPPER_LINEAR) {
return color;
} else if (params.tonemapper == TONEMAPPER_REINHARD) {
- return tonemap_reinhard(color, white);
+ return tonemap_reinhard(max(vec3(0.0f), color), white);
} else if (params.tonemapper == TONEMAPPER_FILMIC) {
- return tonemap_filmic(color, white);
+ return tonemap_filmic(max(vec3(0.0f), color), white);
} else { // TONEMAPPER_ACES
- return tonemap_aces(color, white);
+ return tonemap_aces(max(vec3(0.0f), color), white);
}
}
@@ -298,15 +316,15 @@ vec3 do_fxaa(vec3 color, float exposure, vec2 uv_interp) {
const float FXAA_SPAN_MAX = 8.0;
#ifdef MULTIVIEW
- vec3 rgbNW = textureLod(source_color, vec3(uv_interp + vec2(-1.0, -1.0) * params.pixel_size, ViewIndex), 0.0).xyz * exposure;
- vec3 rgbNE = textureLod(source_color, vec3(uv_interp + vec2(1.0, -1.0) * params.pixel_size, ViewIndex), 0.0).xyz * exposure;
- vec3 rgbSW = textureLod(source_color, vec3(uv_interp + vec2(-1.0, 1.0) * params.pixel_size, ViewIndex), 0.0).xyz * exposure;
- vec3 rgbSE = textureLod(source_color, vec3(uv_interp + vec2(1.0, 1.0) * params.pixel_size, ViewIndex), 0.0).xyz * exposure;
+ vec3 rgbNW = textureLod(source_color, vec3(uv_interp + vec2(-1.0, -1.0) * params.pixel_size, ViewIndex), 0.0).xyz * exposure * params.luminance_multiplier;
+ vec3 rgbNE = textureLod(source_color, vec3(uv_interp + vec2(1.0, -1.0) * params.pixel_size, ViewIndex), 0.0).xyz * exposure * params.luminance_multiplier;
+ vec3 rgbSW = textureLod(source_color, vec3(uv_interp + vec2(-1.0, 1.0) * params.pixel_size, ViewIndex), 0.0).xyz * exposure * params.luminance_multiplier;
+ vec3 rgbSE = textureLod(source_color, vec3(uv_interp + vec2(1.0, 1.0) * params.pixel_size, ViewIndex), 0.0).xyz * exposure * params.luminance_multiplier;
#else
- vec3 rgbNW = textureLod(source_color, uv_interp + vec2(-1.0, -1.0) * params.pixel_size, 0.0).xyz * exposure;
- vec3 rgbNE = textureLod(source_color, uv_interp + vec2(1.0, -1.0) * params.pixel_size, 0.0).xyz * exposure;
- vec3 rgbSW = textureLod(source_color, uv_interp + vec2(-1.0, 1.0) * params.pixel_size, 0.0).xyz * exposure;
- vec3 rgbSE = textureLod(source_color, uv_interp + vec2(1.0, 1.0) * params.pixel_size, 0.0).xyz * exposure;
+ vec3 rgbNW = textureLod(source_color, uv_interp + vec2(-1.0, -1.0) * params.pixel_size, 0.0).xyz * exposure * params.luminance_multiplier;
+ vec3 rgbNE = textureLod(source_color, uv_interp + vec2(1.0, -1.0) * params.pixel_size, 0.0).xyz * exposure * params.luminance_multiplier;
+ vec3 rgbSW = textureLod(source_color, uv_interp + vec2(-1.0, 1.0) * params.pixel_size, 0.0).xyz * exposure * params.luminance_multiplier;
+ vec3 rgbSE = textureLod(source_color, uv_interp + vec2(1.0, 1.0) * params.pixel_size, 0.0).xyz * exposure * params.luminance_multiplier;
#endif
vec3 rgbM = color;
vec3 luma = vec3(0.299, 0.587, 0.114);
@@ -333,11 +351,11 @@ vec3 do_fxaa(vec3 color, float exposure, vec2 uv_interp) {
params.pixel_size;
#ifdef MULTIVIEW
- vec3 rgbA = 0.5 * exposure * (textureLod(source_color, vec3(uv_interp + dir * (1.0 / 3.0 - 0.5), ViewIndex), 0.0).xyz + textureLod(source_color, vec3(uv_interp + dir * (2.0 / 3.0 - 0.5), ViewIndex), 0.0).xyz);
- vec3 rgbB = rgbA * 0.5 + 0.25 * exposure * (textureLod(source_color, vec3(uv_interp + dir * -0.5, ViewIndex), 0.0).xyz + textureLod(source_color, vec3(uv_interp + dir * 0.5, ViewIndex), 0.0).xyz);
+ vec3 rgbA = 0.5 * exposure * (textureLod(source_color, vec3(uv_interp + dir * (1.0 / 3.0 - 0.5), ViewIndex), 0.0).xyz + textureLod(source_color, vec3(uv_interp + dir * (2.0 / 3.0 - 0.5), ViewIndex), 0.0).xyz) * params.luminance_multiplier;
+ vec3 rgbB = rgbA * 0.5 + 0.25 * exposure * (textureLod(source_color, vec3(uv_interp + dir * -0.5, ViewIndex), 0.0).xyz + textureLod(source_color, vec3(uv_interp + dir * 0.5, ViewIndex), 0.0).xyz) * params.luminance_multiplier;
#else
- vec3 rgbA = 0.5 * exposure * (textureLod(source_color, uv_interp + dir * (1.0 / 3.0 - 0.5), 0.0).xyz + textureLod(source_color, uv_interp + dir * (2.0 / 3.0 - 0.5), 0.0).xyz);
- vec3 rgbB = rgbA * 0.5 + 0.25 * exposure * (textureLod(source_color, uv_interp + dir * -0.5, 0.0).xyz + textureLod(source_color, uv_interp + dir * 0.5, 0.0).xyz);
+ vec3 rgbA = 0.5 * exposure * (textureLod(source_color, uv_interp + dir * (1.0 / 3.0 - 0.5), 0.0).xyz + textureLod(source_color, uv_interp + dir * (2.0 / 3.0 - 0.5), 0.0).xyz) * params.luminance_multiplier;
+ vec3 rgbB = rgbA * 0.5 + 0.25 * exposure * (textureLod(source_color, uv_interp + dir * -0.5, 0.0).xyz + textureLod(source_color, uv_interp + dir * 0.5, 0.0).xyz) * params.luminance_multiplier;
#endif
float lumaB = dot(rgbB, luma);
@@ -349,7 +367,7 @@ vec3 do_fxaa(vec3 color, float exposure, vec2 uv_interp) {
}
#endif // !SUBPASS
-// From http://alex.vlachos.com/graphics/Alex_Vlachos_Advanced_VR_Rendering_GDC2015.pdf
+// From https://alex.vlachos.com/graphics/Alex_Vlachos_Advanced_VR_Rendering_GDC2015.pdf
// and https://www.shadertoy.com/view/MslGR8 (5th one starting from the bottom)
// NOTE: `frag_coord` is in pixels (i.e. not normalized UV).
vec3 screen_space_dither(vec2 frag_coord) {
@@ -364,11 +382,11 @@ vec3 screen_space_dither(vec2 frag_coord) {
void main() {
#ifdef SUBPASS
// SUBPASS and MULTIVIEW can be combined but in that case we're already reading from the correct layer
- vec3 color = subpassLoad(input_color).rgb;
-#elif MULTIVIEW
- vec3 color = textureLod(source_color, vec3(uv_interp, ViewIndex), 0.0f).rgb;
+ vec3 color = subpassLoad(input_color).rgb * params.luminance_multiplier;
+#elif defined(MULTIVIEW)
+ vec3 color = textureLod(source_color, vec3(uv_interp, ViewIndex), 0.0f).rgb * params.luminance_multiplier;
#else
- vec3 color = textureLod(source_color, uv_interp, 0.0f).rgb;
+ vec3 color = textureLod(source_color, uv_interp, 0.0f).rgb * params.luminance_multiplier;
#endif
// Exposure
@@ -377,7 +395,7 @@ void main() {
#ifndef SUBPASS
if (params.use_auto_exposure) {
- exposure *= 1.0 / (texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / params.auto_exposure_grey);
+ exposure *= 1.0 / (texelFetch(source_auto_exposure, ivec2(0, 0), 0).r * params.luminance_multiplier / params.auto_exposure_grey);
}
#endif
@@ -386,7 +404,7 @@ void main() {
// Early Tonemap & SRGB Conversion
#ifndef SUBPASS
if (params.use_glow && params.glow_mode == GLOW_MODE_MIX) {
- vec3 glow = gather_glow(source_glow, uv_interp);
+ vec3 glow = gather_glow(source_glow, uv_interp) * params.luminance_multiplier;
color.rgb = mix(color.rgb, glow, params.glow_intensity);
}
@@ -401,9 +419,7 @@ void main() {
color += screen_space_dither(gl_FragCoord.xy);
}
- // Ensure color values passed to tonemappers are positive.
- // They can be negative in the case of negative lights, which leads to undesired behavior.
- color = apply_tonemapping(max(vec3(0.0), color), params.white);
+ color = apply_tonemapping(color, params.white);
color = linear_to_srgb(color); // regular linear -> SRGB conversion
@@ -411,7 +427,7 @@ void main() {
// Glow
if (params.use_glow && params.glow_mode != GLOW_MODE_MIX) {
- vec3 glow = gather_glow(source_glow, uv_interp) * params.glow_intensity;
+ vec3 glow = gather_glow(source_glow, uv_interp) * params.glow_intensity * params.luminance_multiplier;
// high dynamic range -> SRGB
glow = apply_tonemapping(glow, params.white);
diff --git a/servers/rendering/renderer_rd/shaders/voxel_gi.glsl b/servers/rendering/renderer_rd/shaders/voxel_gi.glsl
index 49a493cdc7..779f04ed35 100644
--- a/servers/rendering/renderer_rd/shaders/voxel_gi.glsl
+++ b/servers/rendering/renderer_rd/shaders/voxel_gi.glsl
@@ -71,11 +71,6 @@ lights;
layout(set = 0, binding = 5) uniform texture3D color_texture;
-#ifdef MODE_ANISOTROPIC
-layout(set = 0, binding = 7) uniform texture3D aniso_pos_texture;
-layout(set = 0, binding = 8) uniform texture3D aniso_neg_texture;
-#endif // MODE ANISOTROPIC
-
#endif // MODE_SECOND_BOUNCE
#ifndef MODE_DYNAMIC
@@ -110,13 +105,6 @@ layout(set = 0, binding = 10) uniform sampler texture_sampler;
layout(rgba8, set = 0, binding = 5) uniform restrict writeonly image3D color_tex;
-#ifdef MODE_ANISOTROPIC
-
-layout(r16ui, set = 0, binding = 6) uniform restrict writeonly uimage3D aniso_pos_tex;
-layout(r16ui, set = 0, binding = 7) uniform restrict writeonly uimage3D aniso_neg_tex;
-
-#endif
-
#endif
#ifdef MODE_DYNAMIC
@@ -170,13 +158,6 @@ layout(r32f, set = 0, binding = 8) uniform restrict writeonly image2D depth;
layout(rgba8, set = 0, binding = 11) uniform restrict image3D color_texture;
-#ifdef MODE_ANISOTROPIC
-
-layout(r16ui, set = 0, binding = 12) uniform restrict writeonly uimage3D aniso_pos_texture;
-layout(r16ui, set = 0, binding = 13) uniform restrict writeonly uimage3D aniso_neg_texture;
-
-#endif // MODE ANISOTROPIC
-
#endif //MODE_DYNAMIC_SHRINK_PLOT
#endif // MODE_DYNAMIC_SHRINK
@@ -374,12 +355,7 @@ void main() {
vec3 emission = vec3(uvec3(cell_data.data[cell_index].emission & 0x1ff, (cell_data.data[cell_index].emission >> 9) & 0x1ff, (cell_data.data[cell_index].emission >> 18) & 0x1ff)) * pow(2.0, float(cell_data.data[cell_index].emission >> 27) - 15.0 - 9.0);
vec3 normal = unpackSnorm4x8(cell_data.data[cell_index].normal).xyz;
-#ifdef MODE_ANISOTROPIC
- vec3 accum[6] = vec3[](vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0));
- const vec3 accum_dirs[6] = vec3[](vec3(1.0, 0.0, 0.0), vec3(-1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(0.0, -1.0, 0.0), vec3(0.0, 0.0, 1.0), vec3(0.0, 0.0, -1.0));
-#else
vec3 accum = vec3(0.0);
-#endif
for (uint i = 0; i < params.light_count; i++) {
vec3 light;
@@ -390,38 +366,16 @@ void main() {
light *= albedo.rgb;
-#ifdef MODE_ANISOTROPIC
- for (uint j = 0; j < 6; j++) {
- accum[j] += max(0.0, dot(accum_dirs[j], -light_dir)) * light;
- }
-#else
if (length(normal) > 0.2) {
accum += max(0.0, dot(normal, -light_dir)) * light;
} else {
//all directions
accum += light;
}
-#endif
}
-#ifdef MODE_ANISOTROPIC
-
- for (uint i = 0; i < 6; i++) {
- vec3 light = accum[i];
- if (length(normal) > 0.2) {
- light += max(0.0, dot(accum_dirs[i], -normal)) * emission;
- } else {
- light += emission;
- }
-
- outputs.data[cell_index * 6 + i] = vec4(light, 0.0);
- }
-
-#else
outputs.data[cell_index] = vec4(accum + emission, 0.0);
-#endif
-
#endif //MODE_COMPUTE_LIGHT
/////////////////SECOND BOUNCE///////////////////////////////
@@ -431,32 +385,8 @@ void main() {
ivec3 ipos = ivec3(posu);
vec4 normal = unpackSnorm4x8(cell_data.data[cell_index].normal);
-#ifdef MODE_ANISOTROPIC
- vec3 accum[6];
- const vec3 accum_dirs[6] = vec3[](vec3(1.0, 0.0, 0.0), vec3(-1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(0.0, -1.0, 0.0), vec3(0.0, 0.0, 1.0), vec3(0.0, 0.0, -1.0));
-
- /*vec3 src_color = texelFetch(sampler3D(color_texture,texture_sampler),ipos,0).rgb * params.dynamic_range;
- vec3 src_aniso_pos = texelFetch(sampler3D(aniso_pos_texture,texture_sampler),ipos,0).rgb;
- vec3 src_anisp_neg = texelFetch(sampler3D(anisp_neg_texture,texture_sampler),ipos,0).rgb;
- accum[0]=src_col * src_aniso_pos.x;
- accum[1]=src_col * src_aniso_neg.x;
- accum[2]=src_col * src_aniso_pos.y;
- accum[3]=src_col * src_aniso_neg.y;
- accum[4]=src_col * src_aniso_pos.z;
- accum[5]=src_col * src_aniso_neg.z;*/
-
- accum[0] = outputs.data[cell_index * 6 + 0].rgb;
- accum[1] = outputs.data[cell_index * 6 + 1].rgb;
- accum[2] = outputs.data[cell_index * 6 + 2].rgb;
- accum[3] = outputs.data[cell_index * 6 + 3].rgb;
- accum[4] = outputs.data[cell_index * 6 + 4].rgb;
- accum[5] = outputs.data[cell_index * 6 + 5].rgb;
-
-#else
vec3 accum = outputs.data[cell_index].rgb;
-#endif
-
if (length(normal.xyz) > 0.2) {
vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0);
vec3 tangent = normalize(cross(v0, normal.xyz));
@@ -484,9 +414,6 @@ void main() {
float max_distance = length(vec3(params.limits));
vec3 cell_size = 1.0 / vec3(params.limits);
-#ifdef MODE_ANISOTROPIC
- vec3 aniso_normal = mix(direction, normal.xyz, params.aniso_strength);
-#endif
while (dist < max_distance && color.a < 0.95) {
float diameter = max(1.0, 2.0 * tan_half_angle * dist);
vec3 uvw_pos = (pos + dist * direction) * cell_size;
@@ -498,42 +425,18 @@ void main() {
float log2_diameter = log2(diameter);
vec4 scolor = textureLod(sampler3D(color_texture, texture_sampler), uvw_pos, log2_diameter);
-#ifdef MODE_ANISOTROPIC
-
- vec3 aniso_neg = textureLod(sampler3D(aniso_neg_texture, texture_sampler), uvw_pos, log2_diameter).rgb;
- vec3 aniso_pos = textureLod(sampler3D(aniso_pos_texture, texture_sampler), uvw_pos, log2_diameter).rgb;
-
- scolor.rgb *= dot(max(vec3(0.0), (aniso_normal * aniso_pos)), vec3(1.0)) + dot(max(vec3(0.0), (-aniso_normal * aniso_neg)), vec3(1.0));
-#endif
float a = (1.0 - color.a);
color += a * scolor;
dist += half_diameter;
}
}
color *= cone_weights[i] * vec4(albedo.rgb, 1.0) * params.dynamic_range; //restore range
-#ifdef MODE_ANISOTROPIC
- for (uint j = 0; j < 6; j++) {
- accum[j] += max(0.0, dot(accum_dirs[j], direction)) * color.rgb;
- }
-#else
accum += color.rgb;
-#endif
}
}
-#ifdef MODE_ANISOTROPIC
-
- outputs.data[cell_index * 6 + 0] = vec4(accum[0], 0.0);
- outputs.data[cell_index * 6 + 1] = vec4(accum[1], 0.0);
- outputs.data[cell_index * 6 + 2] = vec4(accum[2], 0.0);
- outputs.data[cell_index * 6 + 3] = vec4(accum[3], 0.0);
- outputs.data[cell_index * 6 + 4] = vec4(accum[4], 0.0);
- outputs.data[cell_index * 6 + 5] = vec4(accum[5], 0.0);
-#else
outputs.data[cell_index] = vec4(accum, 0.0);
-#endif
-
#endif // MODE_SECOND_BOUNCE
/////////////////UPDATE MIPMAPS///////////////////////////////
@@ -541,45 +444,20 @@ void main() {
#ifdef MODE_UPDATE_MIPMAPS
{
-#ifdef MODE_ANISOTROPIC
- vec3 light_accum[6] = vec3[](vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0));
-#else
vec3 light_accum = vec3(0.0);
-#endif
float count = 0.0;
for (uint i = 0; i < 8; i++) {
uint child_index = cell_children.data[cell_index].children[i];
if (child_index == NO_CHILDREN) {
continue;
}
-#ifdef MODE_ANISOTROPIC
- light_accum[0] += outputs.data[child_index * 6 + 0].rgb;
- light_accum[1] += outputs.data[child_index * 6 + 1].rgb;
- light_accum[2] += outputs.data[child_index * 6 + 2].rgb;
- light_accum[3] += outputs.data[child_index * 6 + 3].rgb;
- light_accum[4] += outputs.data[child_index * 6 + 4].rgb;
- light_accum[5] += outputs.data[child_index * 6 + 5].rgb;
-
-#else
light_accum += outputs.data[child_index].rgb;
-#endif
-
count += 1.0;
}
float divisor = mix(8.0, count, params.propagation);
-#ifdef MODE_ANISOTROPIC
- outputs.data[cell_index * 6 + 0] = vec4(light_accum[0] / divisor, 0.0);
- outputs.data[cell_index * 6 + 1] = vec4(light_accum[1] / divisor, 0.0);
- outputs.data[cell_index * 6 + 2] = vec4(light_accum[2] / divisor, 0.0);
- outputs.data[cell_index * 6 + 3] = vec4(light_accum[3] / divisor, 0.0);
- outputs.data[cell_index * 6 + 4] = vec4(light_accum[4] / divisor, 0.0);
- outputs.data[cell_index * 6 + 5] = vec4(light_accum[5] / divisor, 0.0);
-
-#else
outputs.data[cell_index] = vec4(light_accum / divisor, 0.0);
-#endif
}
#endif
@@ -587,40 +465,7 @@ void main() {
#ifdef MODE_WRITE_TEXTURE
{
-#ifdef MODE_ANISOTROPIC
- vec3 accum_total = vec3(0.0);
- accum_total += outputs.data[cell_index * 6 + 0].rgb;
- accum_total += outputs.data[cell_index * 6 + 1].rgb;
- accum_total += outputs.data[cell_index * 6 + 2].rgb;
- accum_total += outputs.data[cell_index * 6 + 3].rgb;
- accum_total += outputs.data[cell_index * 6 + 4].rgb;
- accum_total += outputs.data[cell_index * 6 + 5].rgb;
-
- float accum_total_energy = max(dot(accum_total, GREY_VEC), 0.00001);
- vec3 iso_positive = vec3(dot(outputs.data[cell_index * 6 + 0].rgb, GREY_VEC), dot(outputs.data[cell_index * 6 + 2].rgb, GREY_VEC), dot(outputs.data[cell_index * 6 + 4].rgb, GREY_VEC)) / vec3(accum_total_energy);
- vec3 iso_negative = vec3(dot(outputs.data[cell_index * 6 + 1].rgb, GREY_VEC), dot(outputs.data[cell_index * 6 + 3].rgb, GREY_VEC), dot(outputs.data[cell_index * 6 + 5].rgb, GREY_VEC)) / vec3(accum_total_energy);
-
- {
- uint aniso_pos = uint(clamp(iso_positive.b * 31.0, 0.0, 31.0));
- aniso_pos |= uint(clamp(iso_positive.g * 63.0, 0.0, 63.0)) << 5;
- aniso_pos |= uint(clamp(iso_positive.r * 31.0, 0.0, 31.0)) << 11;
- imageStore(aniso_pos_tex, ivec3(posu), uvec4(aniso_pos));
- }
-
- {
- uint aniso_neg = uint(clamp(iso_negative.b * 31.0, 0.0, 31.0));
- aniso_neg |= uint(clamp(iso_negative.g * 63.0, 0.0, 63.0)) << 5;
- aniso_neg |= uint(clamp(iso_negative.r * 31.0, 0.0, 31.0)) << 11;
- imageStore(aniso_neg_tex, ivec3(posu), uvec4(aniso_neg));
- }
-
- imageStore(color_tex, ivec3(posu), vec4(accum_total / params.dynamic_range, albedo.a));
-
-#else
-
imageStore(color_tex, ivec3(posu), vec4(outputs.data[cell_index].rgb / params.dynamic_range, albedo.a));
-
-#endif
}
#endif
@@ -763,13 +608,6 @@ void main() {
color.rgb /= params.dynamic_range;
imageStore(color_texture, pos3d, color);
//imageStore(color_texture,pos3d,vec4(1,1,1,1));
-
-#ifdef MODE_ANISOTROPIC
- //do not care about anisotropy for dynamic objects, just store full lit in all directions
- imageStore(aniso_pos_texture, pos3d, uvec4(0xFFFF));
- imageStore(aniso_neg_texture, pos3d, uvec4(0xFFFF));
-
-#endif // ANISOTROPIC
}
#endif // MODE_DYNAMIC_SHRINK_PLOT
}
diff --git a/servers/rendering/renderer_rd/shaders/voxel_gi_debug.glsl b/servers/rendering/renderer_rd/shaders/voxel_gi_debug.glsl
index 7d4d72967a..281c496df3 100644
--- a/servers/rendering/renderer_rd/shaders/voxel_gi_debug.glsl
+++ b/servers/rendering/renderer_rd/shaders/voxel_gi_debug.glsl
@@ -20,11 +20,6 @@ layout(set = 0, binding = 2) uniform texture3D color_tex;
layout(set = 0, binding = 3) uniform sampler tex_sampler;
-#ifdef USE_ANISOTROPY
-layout(set = 0, binding = 4) uniform texture3D aniso_pos_tex;
-layout(set = 0, binding = 5) uniform texture3D aniso_neg_tex;
-#endif
-
layout(push_constant, binding = 0, std430) uniform Params {
mat4 projection;
uint cell_offset;
diff --git a/servers/rendering/renderer_scene.h b/servers/rendering/renderer_scene.h
index 972637d183..5961f59b6f 100644
--- a/servers/rendering/renderer_scene.h
+++ b/servers/rendering/renderer_scene.h
@@ -126,7 +126,7 @@ public:
virtual void environment_set_bg_color(RID p_env, const Color &p_color) = 0;
virtual void environment_set_bg_energy(RID p_env, float p_energy) = 0;
virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer) = 0;
- virtual void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG, const Color &p_ao_color = Color()) = 0;
+ virtual void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG) = 0;
virtual void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap) = 0;
virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) = 0;
diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp
index cd8014632d..bae98f8884 100644
--- a/servers/rendering/renderer_scene_cull.cpp
+++ b/servers/rendering/renderer_scene_cull.cpp
@@ -47,7 +47,7 @@ void RendererSceneCull::camera_initialize(RID p_rid) {
}
void RendererSceneCull::camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far) {
- Camera *camera = camera_owner.getornull(p_camera);
+ Camera *camera = camera_owner.get_or_null(p_camera);
ERR_FAIL_COND(!camera);
camera->type = Camera::PERSPECTIVE;
camera->fov = p_fovy_degrees;
@@ -56,7 +56,7 @@ void RendererSceneCull::camera_set_perspective(RID p_camera, float p_fovy_degree
}
void RendererSceneCull::camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far) {
- Camera *camera = camera_owner.getornull(p_camera);
+ Camera *camera = camera_owner.get_or_null(p_camera);
ERR_FAIL_COND(!camera);
camera->type = Camera::ORTHOGONAL;
camera->size = p_size;
@@ -65,7 +65,7 @@ void RendererSceneCull::camera_set_orthogonal(RID p_camera, float p_size, float
}
void RendererSceneCull::camera_set_frustum(RID p_camera, float p_size, Vector2 p_offset, float p_z_near, float p_z_far) {
- Camera *camera = camera_owner.getornull(p_camera);
+ Camera *camera = camera_owner.get_or_null(p_camera);
ERR_FAIL_COND(!camera);
camera->type = Camera::FRUSTUM;
camera->size = p_size;
@@ -75,32 +75,32 @@ void RendererSceneCull::camera_set_frustum(RID p_camera, float p_size, Vector2 p
}
void RendererSceneCull::camera_set_transform(RID p_camera, const Transform3D &p_transform) {
- Camera *camera = camera_owner.getornull(p_camera);
+ Camera *camera = camera_owner.get_or_null(p_camera);
ERR_FAIL_COND(!camera);
camera->transform = p_transform.orthonormalized();
}
void RendererSceneCull::camera_set_cull_mask(RID p_camera, uint32_t p_layers) {
- Camera *camera = camera_owner.getornull(p_camera);
+ Camera *camera = camera_owner.get_or_null(p_camera);
ERR_FAIL_COND(!camera);
camera->visible_layers = p_layers;
}
void RendererSceneCull::camera_set_environment(RID p_camera, RID p_env) {
- Camera *camera = camera_owner.getornull(p_camera);
+ Camera *camera = camera_owner.get_or_null(p_camera);
ERR_FAIL_COND(!camera);
camera->env = p_env;
}
void RendererSceneCull::camera_set_camera_effects(RID p_camera, RID p_fx) {
- Camera *camera = camera_owner.getornull(p_camera);
+ Camera *camera = camera_owner.get_or_null(p_camera);
ERR_FAIL_COND(!camera);
camera->effects = p_fx;
}
void RendererSceneCull::camera_set_use_vertical_aspect(RID p_camera, bool p_enable) {
- Camera *camera = camera_owner.getornull(p_camera);
+ Camera *camera = camera_owner.get_or_null(p_camera);
ERR_FAIL_COND(!camera);
camera->vaspect = p_enable;
}
@@ -354,7 +354,7 @@ RID RendererSceneCull::scenario_allocate() {
void RendererSceneCull::scenario_initialize(RID p_rid) {
scenario_owner.initialize_rid(p_rid);
- Scenario *scenario = scenario_owner.getornull(p_rid);
+ Scenario *scenario = scenario_owner.get_or_null(p_rid);
scenario->self = p_rid;
scenario->reflection_probe_shadow_atlas = scene_render->shadow_atlas_create();
@@ -373,25 +373,25 @@ void RendererSceneCull::scenario_initialize(RID p_rid) {
}
void RendererSceneCull::scenario_set_environment(RID p_scenario, RID p_environment) {
- Scenario *scenario = scenario_owner.getornull(p_scenario);
+ Scenario *scenario = scenario_owner.get_or_null(p_scenario);
ERR_FAIL_COND(!scenario);
scenario->environment = p_environment;
}
void RendererSceneCull::scenario_set_camera_effects(RID p_scenario, RID p_camera_effects) {
- Scenario *scenario = scenario_owner.getornull(p_scenario);
+ Scenario *scenario = scenario_owner.get_or_null(p_scenario);
ERR_FAIL_COND(!scenario);
scenario->camera_effects = p_camera_effects;
}
void RendererSceneCull::scenario_set_fallback_environment(RID p_scenario, RID p_environment) {
- Scenario *scenario = scenario_owner.getornull(p_scenario);
+ Scenario *scenario = scenario_owner.get_or_null(p_scenario);
ERR_FAIL_COND(!scenario);
scenario->fallback_environment = p_environment;
}
void RendererSceneCull::scenario_set_reflection_atlas_size(RID p_scenario, int p_reflection_size, int p_reflection_count) {
- Scenario *scenario = scenario_owner.getornull(p_scenario);
+ Scenario *scenario = scenario_owner.get_or_null(p_scenario);
ERR_FAIL_COND(!scenario);
scene_render->reflection_atlas_set_size(scenario->reflection_atlas, p_reflection_size, p_reflection_count);
}
@@ -401,13 +401,13 @@ bool RendererSceneCull::is_scenario(RID p_scenario) const {
}
RID RendererSceneCull::scenario_get_environment(RID p_scenario) {
- Scenario *scenario = scenario_owner.getornull(p_scenario);
+ Scenario *scenario = scenario_owner.get_or_null(p_scenario);
ERR_FAIL_COND_V(!scenario, RID());
return scenario->environment;
}
void RendererSceneCull::scenario_remove_viewport_visibility_mask(RID p_scenario, RID p_viewport) {
- Scenario *scenario = scenario_owner.getornull(p_scenario);
+ Scenario *scenario = scenario_owner.get_or_null(p_scenario);
ERR_FAIL_COND(!scenario);
if (!scenario->viewport_visibility_masks.has(p_viewport)) {
return;
@@ -419,7 +419,7 @@ void RendererSceneCull::scenario_remove_viewport_visibility_mask(RID p_scenario,
}
void RendererSceneCull::scenario_add_viewport_visibility_mask(RID p_scenario, RID p_viewport) {
- Scenario *scenario = scenario_owner.getornull(p_scenario);
+ Scenario *scenario = scenario_owner.get_or_null(p_scenario);
ERR_FAIL_COND(!scenario);
ERR_FAIL_COND(scenario->viewport_visibility_masks.has(p_viewport));
@@ -459,7 +459,7 @@ RID RendererSceneCull::instance_allocate() {
}
void RendererSceneCull::instance_initialize(RID p_rid) {
instance_owner.initialize_rid(p_rid);
- Instance *instance = instance_owner.getornull(p_rid);
+ Instance *instance = instance_owner.get_or_null(p_rid);
instance->self = p_rid;
}
@@ -493,7 +493,7 @@ void RendererSceneCull::_instance_update_mesh_instance(Instance *p_instance) {
}
void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
- Instance *instance = instance_owner.getornull(p_instance);
+ Instance *instance = instance_owner.get_or_null(p_instance);
ERR_FAIL_COND(!instance);
Scenario *scenario = instance->scenario;
@@ -710,7 +710,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
}
void RendererSceneCull::instance_set_scenario(RID p_instance, RID p_scenario) {
- Instance *instance = instance_owner.getornull(p_instance);
+ Instance *instance = instance_owner.get_or_null(p_instance);
ERR_FAIL_COND(!instance);
if (instance->scenario) {
@@ -772,7 +772,7 @@ void RendererSceneCull::instance_set_scenario(RID p_instance, RID p_scenario) {
}
if (p_scenario.is_valid()) {
- Scenario *scenario = scenario_owner.getornull(p_scenario);
+ Scenario *scenario = scenario_owner.get_or_null(p_scenario);
ERR_FAIL_COND(!scenario);
instance->scenario = scenario;
@@ -805,7 +805,7 @@ void RendererSceneCull::instance_set_scenario(RID p_instance, RID p_scenario) {
}
void RendererSceneCull::instance_set_layer_mask(RID p_instance, uint32_t p_mask) {
- Instance *instance = instance_owner.getornull(p_instance);
+ Instance *instance = instance_owner.get_or_null(p_instance);
ERR_FAIL_COND(!instance);
instance->layer_mask = p_mask;
@@ -820,7 +820,7 @@ void RendererSceneCull::instance_set_layer_mask(RID p_instance, uint32_t p_mask)
}
void RendererSceneCull::instance_set_transform(RID p_instance, const Transform3D &p_transform) {
- Instance *instance = instance_owner.getornull(p_instance);
+ Instance *instance = instance_owner.get_or_null(p_instance);
ERR_FAIL_COND(!instance);
if (instance->transform == p_transform) {
@@ -845,14 +845,14 @@ void RendererSceneCull::instance_set_transform(RID p_instance, const Transform3D
}
void RendererSceneCull::instance_attach_object_instance_id(RID p_instance, ObjectID p_id) {
- Instance *instance = instance_owner.getornull(p_instance);
+ Instance *instance = instance_owner.get_or_null(p_instance);
ERR_FAIL_COND(!instance);
instance->object_id = p_id;
}
void RendererSceneCull::instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight) {
- Instance *instance = instance_owner.getornull(p_instance);
+ Instance *instance = instance_owner.get_or_null(p_instance);
ERR_FAIL_COND(!instance);
if (instance->update_item.in_list()) {
@@ -865,7 +865,7 @@ void RendererSceneCull::instance_set_blend_shape_weight(RID p_instance, int p_sh
}
void RendererSceneCull::instance_set_surface_override_material(RID p_instance, int p_surface, RID p_material) {
- Instance *instance = instance_owner.getornull(p_instance);
+ Instance *instance = instance_owner.get_or_null(p_instance);
ERR_FAIL_COND(!instance);
if (instance->base_type == RS::INSTANCE_MESH) {
@@ -881,7 +881,7 @@ void RendererSceneCull::instance_set_surface_override_material(RID p_instance, i
}
void RendererSceneCull::instance_set_visible(RID p_instance, bool p_visible) {
- Instance *instance = instance_owner.getornull(p_instance);
+ Instance *instance = instance_owner.get_or_null(p_instance);
ERR_FAIL_COND(!instance);
if (instance->visible == p_visible) {
@@ -926,7 +926,7 @@ inline bool is_geometry_instance(RenderingServer::InstanceType p_type) {
}
void RendererSceneCull::instance_set_custom_aabb(RID p_instance, AABB p_aabb) {
- Instance *instance = instance_owner.getornull(p_instance);
+ Instance *instance = instance_owner.get_or_null(p_instance);
ERR_FAIL_COND(!instance);
ERR_FAIL_COND(!is_geometry_instance(instance->base_type));
@@ -951,7 +951,7 @@ void RendererSceneCull::instance_set_custom_aabb(RID p_instance, AABB p_aabb) {
}
void RendererSceneCull::instance_attach_skeleton(RID p_instance, RID p_skeleton) {
- Instance *instance = instance_owner.getornull(p_instance);
+ Instance *instance = instance_owner.get_or_null(p_instance);
ERR_FAIL_COND(!instance);
if (instance->skeleton == p_skeleton) {
@@ -976,7 +976,7 @@ void RendererSceneCull::instance_attach_skeleton(RID p_instance, RID p_skeleton)
}
void RendererSceneCull::instance_set_extra_visibility_margin(RID p_instance, real_t p_margin) {
- Instance *instance = instance_owner.getornull(p_instance);
+ Instance *instance = instance_owner.get_or_null(p_instance);
ERR_FAIL_COND(!instance);
instance->extra_margin = p_margin;
@@ -985,7 +985,7 @@ void RendererSceneCull::instance_set_extra_visibility_margin(RID p_instance, rea
Vector<ObjectID> RendererSceneCull::instances_cull_aabb(const AABB &p_aabb, RID p_scenario) const {
Vector<ObjectID> instances;
- Scenario *scenario = scenario_owner.getornull(p_scenario);
+ Scenario *scenario = scenario_owner.get_or_null(p_scenario);
ERR_FAIL_COND_V(!scenario, instances);
const_cast<RendererSceneCull *>(this)->update_dirty_instances(); // check dirty instances before culling
@@ -1009,7 +1009,7 @@ Vector<ObjectID> RendererSceneCull::instances_cull_aabb(const AABB &p_aabb, RID
Vector<ObjectID> RendererSceneCull::instances_cull_ray(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario) const {
Vector<ObjectID> instances;
- Scenario *scenario = scenario_owner.getornull(p_scenario);
+ Scenario *scenario = scenario_owner.get_or_null(p_scenario);
ERR_FAIL_COND_V(!scenario, instances);
const_cast<RendererSceneCull *>(this)->update_dirty_instances(); // check dirty instances before culling
@@ -1032,7 +1032,7 @@ Vector<ObjectID> RendererSceneCull::instances_cull_ray(const Vector3 &p_from, co
Vector<ObjectID> RendererSceneCull::instances_cull_convex(const Vector<Plane> &p_convex, RID p_scenario) const {
Vector<ObjectID> instances;
- Scenario *scenario = scenario_owner.getornull(p_scenario);
+ Scenario *scenario = scenario_owner.get_or_null(p_scenario);
ERR_FAIL_COND_V(!scenario, instances);
const_cast<RendererSceneCull *>(this)->update_dirty_instances(); // check dirty instances before culling
@@ -1056,7 +1056,7 @@ Vector<ObjectID> RendererSceneCull::instances_cull_convex(const Vector<Plane> &p
}
void RendererSceneCull::instance_geometry_set_flag(RID p_instance, RS::InstanceFlags p_flags, bool p_enabled) {
- Instance *instance = instance_owner.getornull(p_instance);
+ Instance *instance = instance_owner.get_or_null(p_instance);
ERR_FAIL_COND(!instance);
//ERR_FAIL_COND(((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK));
@@ -1131,7 +1131,7 @@ void RendererSceneCull::instance_geometry_set_flag(RID p_instance, RS::InstanceF
}
void RendererSceneCull::instance_geometry_set_cast_shadows_setting(RID p_instance, RS::ShadowCastingSetting p_shadow_casting_setting) {
- Instance *instance = instance_owner.getornull(p_instance);
+ Instance *instance = instance_owner.get_or_null(p_instance);
ERR_FAIL_COND(!instance);
instance->cast_shadows = p_shadow_casting_setting;
@@ -1161,7 +1161,7 @@ void RendererSceneCull::instance_geometry_set_cast_shadows_setting(RID p_instanc
}
void RendererSceneCull::instance_geometry_set_material_override(RID p_instance, RID p_material) {
- Instance *instance = instance_owner.getornull(p_instance);
+ Instance *instance = instance_owner.get_or_null(p_instance);
ERR_FAIL_COND(!instance);
instance->material_override = p_material;
@@ -1174,7 +1174,7 @@ void RendererSceneCull::instance_geometry_set_material_override(RID p_instance,
}
void RendererSceneCull::instance_geometry_set_visibility_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin) {
- Instance *instance = instance_owner.getornull(p_instance);
+ Instance *instance = instance_owner.get_or_null(p_instance);
ERR_FAIL_COND(!instance);
instance->visibility_range_begin = p_min;
@@ -1194,7 +1194,7 @@ void RendererSceneCull::instance_geometry_set_visibility_range(RID p_instance, f
}
void RendererSceneCull::instance_set_visibility_parent(RID p_instance, RID p_parent_instance) {
- Instance *instance = instance_owner.getornull(p_instance);
+ Instance *instance = instance_owner.get_or_null(p_instance);
ERR_FAIL_COND(!instance);
Instance *old_parent = instance->visibility_parent;
@@ -1207,7 +1207,7 @@ void RendererSceneCull::instance_set_visibility_parent(RID p_instance, RID p_par
instance->visibility_parent = nullptr;
}
- Instance *parent = instance_owner.getornull(p_parent_instance);
+ Instance *parent = instance_owner.get_or_null(p_parent_instance);
ERR_FAIL_COND(p_parent_instance.is_valid() && !parent);
if (parent) {
@@ -1286,7 +1286,7 @@ void RendererSceneCull::_update_instance_visibility_dependencies(Instance *p_ins
vd.range_end = p_instance->visibility_range_end;
vd.range_begin_margin = p_instance->visibility_range_begin_margin;
vd.range_end_margin = p_instance->visibility_range_end_margin;
- vd.position = p_instance->transformed_aabb.get_position() + p_instance->transformed_aabb.get_size() / 2.0f;
+ vd.position = p_instance->transformed_aabb.get_center();
vd.array_index = p_instance->array_index;
InstanceGeometryData *geom_data = static_cast<InstanceGeometryData *>(p_instance->base_data);
@@ -1312,7 +1312,7 @@ void RendererSceneCull::_update_instance_visibility_dependencies(Instance *p_ins
}
void RendererSceneCull::instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_slice_index) {
- Instance *instance = instance_owner.getornull(p_instance);
+ Instance *instance = instance_owner.get_or_null(p_instance);
ERR_FAIL_COND(!instance);
if (instance->lightmap) {
@@ -1321,7 +1321,7 @@ void RendererSceneCull::instance_geometry_set_lightmap(RID p_instance, RID p_lig
instance->lightmap = nullptr;
}
- Instance *lightmap_instance = instance_owner.getornull(p_lightmap);
+ Instance *lightmap_instance = instance_owner.get_or_null(p_lightmap);
instance->lightmap = lightmap_instance;
instance->lightmap_uv_scale = p_lightmap_uv_scale;
@@ -1342,7 +1342,7 @@ void RendererSceneCull::instance_geometry_set_lightmap(RID p_instance, RID p_lig
}
void RendererSceneCull::instance_geometry_set_lod_bias(RID p_instance, float p_lod_bias) {
- Instance *instance = instance_owner.getornull(p_instance);
+ Instance *instance = instance_owner.get_or_null(p_instance);
ERR_FAIL_COND(!instance);
instance->lod_bias = p_lod_bias;
@@ -1354,7 +1354,7 @@ void RendererSceneCull::instance_geometry_set_lod_bias(RID p_instance, float p_l
}
void RendererSceneCull::instance_geometry_set_shader_parameter(RID p_instance, const StringName &p_parameter, const Variant &p_value) {
- Instance *instance = instance_owner.getornull(p_instance);
+ Instance *instance = instance_owner.get_or_null(p_instance);
ERR_FAIL_COND(!instance);
ERR_FAIL_COND(p_value.get_type() == Variant::OBJECT);
@@ -1377,7 +1377,7 @@ void RendererSceneCull::instance_geometry_set_shader_parameter(RID p_instance, c
}
Variant RendererSceneCull::instance_geometry_get_shader_parameter(RID p_instance, const StringName &p_parameter) const {
- const Instance *instance = const_cast<RendererSceneCull *>(this)->instance_owner.getornull(p_instance);
+ const Instance *instance = const_cast<RendererSceneCull *>(this)->instance_owner.get_or_null(p_instance);
ERR_FAIL_COND_V(!instance, Variant());
if (instance->instance_shader_parameters.has(p_parameter)) {
@@ -1387,7 +1387,7 @@ Variant RendererSceneCull::instance_geometry_get_shader_parameter(RID p_instance
}
Variant RendererSceneCull::instance_geometry_get_shader_parameter_default_value(RID p_instance, const StringName &p_parameter) const {
- const Instance *instance = const_cast<RendererSceneCull *>(this)->instance_owner.getornull(p_instance);
+ const Instance *instance = const_cast<RendererSceneCull *>(this)->instance_owner.get_or_null(p_instance);
ERR_FAIL_COND_V(!instance, Variant());
if (instance->instance_shader_parameters.has(p_parameter)) {
@@ -1397,14 +1397,14 @@ Variant RendererSceneCull::instance_geometry_get_shader_parameter_default_value(
}
void RendererSceneCull::instance_geometry_get_shader_parameter_list(RID p_instance, List<PropertyInfo> *p_parameters) const {
- const Instance *instance = const_cast<RendererSceneCull *>(this)->instance_owner.getornull(p_instance);
+ const Instance *instance = const_cast<RendererSceneCull *>(this)->instance_owner.get_or_null(p_instance);
ERR_FAIL_COND(!instance);
const_cast<RendererSceneCull *>(this)->update_dirty_instances();
Vector<StringName> names;
- for (Map<StringName, Instance::InstanceShaderParameter>::Element *E = instance->instance_shader_parameters.front(); E; E = E->next()) {
- names.push_back(E->key());
+ for (const KeyValue<StringName, Instance::InstanceShaderParameter> &E : instance->instance_shader_parameters) {
+ names.push_back(E.key);
}
names.sort_custom<StringName::AlphCompare>();
for (int i = 0; i < names.size(); i++) {
@@ -1636,7 +1636,7 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
}
if (p_instance->visibility_index != -1) {
- p_instance->scenario->instance_visibility[p_instance->visibility_index].position = p_instance->transformed_aabb.get_position() + p_instance->transformed_aabb.get_size() / 2.0f;
+ p_instance->scenario->instance_visibility[p_instance->visibility_index].position = p_instance->transformed_aabb.get_center();
}
//move instance and repair
@@ -1851,7 +1851,7 @@ void RendererSceneCull::_update_instance_lightmap_captures(Instance *p_instance)
}
Transform3D to_bounds = lightmap->transform.affine_inverse();
- Vector3 center = p_instance->transform.xform(p_instance->aabb.position + p_instance->aabb.size * 0.5); //use aabb center
+ Vector3 center = p_instance->transform.xform(p_instance->aabb.get_center()); //use aabb center
Vector3 lm_pos = to_bounds.xform(center);
@@ -2354,7 +2354,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, float p_screen_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RenderInfo *r_render_info) {
#ifndef _3D_DISABLED
- Camera *camera = camera_owner.getornull(p_camera);
+ Camera *camera = camera_owner.get_or_null(p_camera);
ERR_FAIL_COND(!camera);
RendererSceneRender::CameraData camera_data;
@@ -2747,9 +2747,9 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
}
void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_camera_data, RID p_render_buffers, RID p_environment, RID p_force_camera_effects, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, bool p_using_shadows, RendererScene::RenderInfo *r_render_info) {
- Instance *render_reflection_probe = instance_owner.getornull(p_reflection_probe); //if null, not rendering to it
+ Instance *render_reflection_probe = instance_owner.get_or_null(p_reflection_probe); //if null, not rendering to it
- Scenario *scenario = scenario_owner.getornull(p_scenario);
+ Scenario *scenario = scenario_owner.get_or_null(p_scenario);
render_pass++;
@@ -2952,7 +2952,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
Transform3D cam_xf = p_camera_data->main_transform;
float zn = p_camera_data->main_projection.get_z_near();
- Plane p(cam_xf.origin + cam_xf.basis.get_axis(2) * -zn, -cam_xf.basis.get_axis(2)); //camera near plane
+ Plane p(-cam_xf.basis.get_axis(2), cam_xf.origin + cam_xf.basis.get_axis(2) * -zn); //camera near plane
// near plane half width and height
Vector2 vp_half_extents = p_camera_data->main_projection.get_viewport_half_extents();
@@ -3103,12 +3103,12 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
}
RID RendererSceneCull::_render_get_environment(RID p_camera, RID p_scenario) {
- Camera *camera = camera_owner.getornull(p_camera);
+ Camera *camera = camera_owner.get_or_null(p_camera);
if (camera && scene_render->is_environment(camera->env)) {
return camera->env;
}
- Scenario *scenario = scenario_owner.getornull(p_scenario);
+ Scenario *scenario = scenario_owner.get_or_null(p_scenario);
if (!scenario) {
return RID();
}
@@ -3125,7 +3125,7 @@ RID RendererSceneCull::_render_get_environment(RID p_camera, RID p_scenario) {
void RendererSceneCull::render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas) {
#ifndef _3D_DISABLED
- Scenario *scenario = scenario_owner.getornull(p_scenario);
+ Scenario *scenario = scenario_owner.get_or_null(p_scenario);
RID environment;
if (scenario->environment.is_valid()) {
@@ -3688,9 +3688,9 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
p_instance->instance_allocated_shader_parameters_offset = RSG::storage->global_variables_instance_allocate(p_instance->self);
scene_render->geometry_instance_set_instance_shader_parameters_offset(geom->geometry_instance, p_instance->instance_allocated_shader_parameters_offset);
- for (Map<StringName, Instance::InstanceShaderParameter>::Element *E = p_instance->instance_shader_parameters.front(); E; E = E->next()) {
- if (E->get().value.get_type() != Variant::NIL) {
- RSG::storage->global_variables_instance_update(p_instance->self, E->get().index, E->get().value);
+ for (const KeyValue<StringName, Instance::InstanceShaderParameter> &E : p_instance->instance_shader_parameters) {
+ if (E.value.value.get_type() != Variant::NIL) {
+ RSG::storage->global_variables_instance_update(p_instance->self, E.value.index, E.value.value);
}
}
} else {
@@ -3750,7 +3750,7 @@ bool RendererSceneCull::free(RID p_rid) {
camera_owner.free(p_rid);
} else if (scenario_owner.owns(p_rid)) {
- Scenario *scenario = scenario_owner.getornull(p_rid);
+ Scenario *scenario = scenario_owner.get_or_null(p_rid);
while (scenario->instances.first()) {
instance_set_scenario(scenario->instances.first()->self()->self, RID());
@@ -3771,7 +3771,7 @@ bool RendererSceneCull::free(RID p_rid) {
update_dirty_instances();
- Instance *instance = instance_owner.getornull(p_rid);
+ Instance *instance = instance_owner.get_or_null(p_rid);
instance_geometry_set_lightmap(p_rid, RID(), Rect2(), 0);
instance_set_scenario(p_rid, RID());
diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h
index 96fe6ce25c..905d0eb558 100644
--- a/servers/rendering/renderer_scene_cull.h
+++ b/servers/rendering/renderer_scene_cull.h
@@ -1078,7 +1078,7 @@ public:
PASS2(environment_set_bg_color, RID, const Color &)
PASS2(environment_set_bg_energy, RID, float)
PASS2(environment_set_canvas_max_layer, RID, int)
- PASS7(environment_set_ambient_light, RID, const Color &, RS::EnvironmentAmbientSource, float, float, RS::EnvironmentReflectionSource, const Color &)
+ PASS6(environment_set_ambient_light, RID, const Color &, RS::EnvironmentAmbientSource, float, float, RS::EnvironmentReflectionSource)
PASS6(environment_set_ssr, RID, bool, int, float, float, float)
PASS1(environment_set_ssr_roughness_quality, RS::EnvironmentSSRRoughnessQuality)
@@ -1158,4 +1158,4 @@ public:
virtual ~RendererSceneCull();
};
-#endif // VISUALSERVERSCENE_H
+#endif // RENDERING_SERVER_SCENE_CULL_H
diff --git a/servers/rendering/renderer_scene_occlusion_cull.h b/servers/rendering/renderer_scene_occlusion_cull.h
index e06b3ba153..4e4b1b94db 100644
--- a/servers/rendering/renderer_scene_occlusion_cull.h
+++ b/servers/rendering/renderer_scene_occlusion_cull.h
@@ -76,26 +76,28 @@ public:
return false;
}
- float min_depth;
- if (p_cam_projection.is_orthogonal()) {
- min_depth = (-closest_point_view.z) - p_near;
- } else {
- float r = -p_near / closest_point_view.z;
- Vector3 closest_point_proj = Vector3(closest_point_view.x * r, closest_point_view.y * r, -p_near);
- min_depth = closest_point_proj.distance_to(closest_point_view);
- }
+ float min_depth = -closest_point_view.z * 0.95f;
Vector2 rect_min = Vector2(FLT_MAX, FLT_MAX);
Vector2 rect_max = Vector2(FLT_MIN, FLT_MIN);
for (int j = 0; j < 8; j++) {
- Vector3 c = RendererSceneOcclusionCull::HZBuffer::corners[j];
+ const Vector3 &c = RendererSceneOcclusionCull::HZBuffer::corners[j];
Vector3 nc = Vector3(1, 1, 1) - c;
Vector3 corner = Vector3(p_bounds[0] * c.x + p_bounds[3] * nc.x, p_bounds[1] * c.y + p_bounds[4] * nc.y, p_bounds[2] * c.z + p_bounds[5] * nc.z);
Vector3 view = p_cam_inv_transform.xform(corner);
- Vector3 projected = p_cam_projection.xform(view);
- Vector2 normalized = Vector2(projected.x * 0.5f + 0.5f, projected.y * 0.5f + 0.5f);
+ Plane vp = Plane(view, 1.0);
+ Plane projected = p_cam_projection.xform4(vp);
+
+ float w = projected.d;
+ if (w < 1.0) {
+ rect_min = Vector2(0.0f, 0.0f);
+ rect_max = Vector2(1.0f, 1.0f);
+ break;
+ }
+
+ Vector2 normalized = Vector2(projected.normal.x / w * 0.5f + 0.5f, projected.normal.y / w * 0.5f + 0.5f);
rect_min = rect_min.min(normalized);
rect_max = rect_max.max(normalized);
}
diff --git a/servers/rendering/renderer_scene_render.cpp b/servers/rendering/renderer_scene_render.cpp
index 3a230ac89d..38d1218dee 100644
--- a/servers/rendering/renderer_scene_render.cpp
+++ b/servers/rendering/renderer_scene_render.cpp
@@ -68,7 +68,7 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count
main_transform.basis.set(x, y, z);
// 3. create a horizon plane with one of the eyes and the up vector as normal.
- Plane horizon(p_transforms[0].origin, y);
+ Plane horizon(y, p_transforms[0].origin);
// 4. Intersect horizon, left and right to obtain the combined camera origin.
ERR_FAIL_COND_MSG(
@@ -79,7 +79,7 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count
// 5. figure out far plane, this could use some improvement, we may have our far plane too close like this, not sure if this matters
Vector3 far_center = (planes[0][CameraMatrix::PLANE_FAR].center() + planes[1][CameraMatrix::PLANE_FAR].center()) * 0.5;
- Plane far(far_center, -z);
+ Plane far(-z, far_center);
/////////////////////////////////////////////////////////////////////////////
// Figure out our top/bottom planes
@@ -137,9 +137,9 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count
Plane near;
Vector3 neg_z = -z;
if (neg_z.dot(p_transforms[1].origin) < neg_z.dot(p_transforms[0].origin)) {
- near = Plane(p_transforms[0].origin, neg_z);
+ near = Plane(neg_z, p_transforms[0].origin);
} else {
- near = Plane(p_transforms[1].origin, neg_z);
+ near = Plane(neg_z, p_transforms[1].origin);
}
// 13. Intersect near plane with bottm/left planes, to obtain min_vec then top/right to obtain max_vec
diff --git a/servers/rendering/renderer_scene_render.h b/servers/rendering/renderer_scene_render.h
index 2000afa0d3..60ba355c03 100644
--- a/servers/rendering/renderer_scene_render.h
+++ b/servers/rendering/renderer_scene_render.h
@@ -113,7 +113,7 @@ public:
virtual void environment_set_bg_color(RID p_env, const Color &p_color) = 0;
virtual void environment_set_bg_energy(RID p_env, float p_energy) = 0;
virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer) = 0;
- virtual void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG, const Color &p_ao_color = Color()) = 0;
+ virtual void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG) = 0;
// FIXME: Disabled during Vulkan refactoring, should be ported.
#if 0
virtual void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id) = 0;
diff --git a/servers/rendering/renderer_storage.cpp b/servers/rendering/renderer_storage.cpp
index a402ecc668..aa005fac0a 100644
--- a/servers/rendering/renderer_storage.cpp
+++ b/servers/rendering/renderer_storage.cpp
@@ -33,21 +33,21 @@
RendererStorage *RendererStorage::base_singleton = nullptr;
void RendererStorage::Dependency::changed_notify(DependencyChangedNotification p_notification) {
- for (Map<DependencyTracker *, uint32_t>::Element *E = instances.front(); E; E = E->next()) {
- if (E->key()->changed_callback) {
- E->key()->changed_callback(p_notification, E->key());
+ for (const KeyValue<DependencyTracker *, uint32_t> &E : instances) {
+ if (E.key->changed_callback) {
+ E.key->changed_callback(p_notification, E.key);
}
}
}
void RendererStorage::Dependency::deleted_notify(const RID &p_rid) {
- for (Map<DependencyTracker *, uint32_t>::Element *E = instances.front(); E; E = E->next()) {
- if (E->key()->deleted_callback) {
- E->key()->deleted_callback(p_rid, E->key());
+ for (const KeyValue<DependencyTracker *, uint32_t> &E : instances) {
+ if (E.key->deleted_callback) {
+ E.key->deleted_callback(p_rid, E.key);
}
}
- for (Map<DependencyTracker *, uint32_t>::Element *E = instances.front(); E; E = E->next()) {
- E->key()->dependencies.erase(this);
+ for (const KeyValue<DependencyTracker *, uint32_t> &E : instances) {
+ E.key->dependencies.erase(this);
}
instances.clear();
}
@@ -56,8 +56,8 @@ RendererStorage::Dependency::~Dependency() {
#ifdef DEBUG_ENABLED
if (instances.size()) {
WARN_PRINT("Leaked instance dependency: Bug - did not call instance_notify_deleted when freeing.");
- for (Map<DependencyTracker *, uint32_t>::Element *E = instances.front(); E; E = E->next()) {
- E->key()->dependencies.erase(this);
+ for (const KeyValue<DependencyTracker *, uint32_t> &E : instances) {
+ E.key->dependencies.erase(this);
}
}
#endif
diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp
index 15ce1dbe63..b67b1cd806 100644
--- a/servers/rendering/renderer_viewport.cpp
+++ b/servers/rendering/renderer_viewport.cpp
@@ -71,6 +71,28 @@ static Transform2D _canvas_get_transform(RendererViewport::Viewport *p_viewport,
return xf;
}
+void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) {
+ if (p_viewport->render_buffers.is_valid()) {
+ if (p_viewport->size.width == 0 || p_viewport->size.height == 0) {
+ RSG::scene->free(p_viewport->render_buffers);
+ p_viewport->render_buffers = RID();
+ } else {
+ float scale_3d = p_viewport->scale_3d;
+ if (Engine::get_singleton()->is_editor_hint()) {
+ // Ignore the 3D viewport render scaling inside of the editor.
+ // The Half Resolution 3D editor viewport option should be used instead.
+ scale_3d = 1.0;
+ }
+
+ // Clamp 3D rendering resolution to reasonable values supported on most hardware.
+ // This prevents freezing the engine or outright crashing on lower-end GPUs.
+ const int width = CLAMP(p_viewport->size.width * scale_3d, 1, 16384);
+ const int height = CLAMP(p_viewport->size.height * scale_3d, 1, 16384);
+ RSG::scene->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, width, height, p_viewport->msaa, p_viewport->screen_space_aa, p_viewport->use_debanding, p_viewport->get_view_count());
+ }
+ }
+}
+
void RendererViewport::_draw_3d(Viewport *p_viewport) {
RENDER_TIMESTAMP(">Begin Rendering 3D Scene");
@@ -100,7 +122,7 @@ void RendererViewport::_draw_3d(Viewport *p_viewport) {
RENDER_TIMESTAMP("<End Rendering 3D Scene");
}
-void RendererViewport::_draw_viewport(Viewport *p_viewport, uint32_t p_view_count) {
+void RendererViewport::_draw_viewport(Viewport *p_viewport) {
if (p_viewport->measure_render_time) {
String rt_id = "vp_begin_" + itos(p_viewport->self.get_id());
RSG::storage->capture_timestamp(rt_id);
@@ -142,7 +164,8 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport, uint32_t p_view_coun
if ((scenario_draw_canvas_bg || can_draw_3d) && !p_viewport->render_buffers.is_valid()) {
//wants to draw 3D but there is no render buffer, create
p_viewport->render_buffers = RSG::scene->render_buffers_create();
- RSG::scene->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, p_viewport->size.width, p_viewport->size.height, p_viewport->msaa, p_viewport->screen_space_aa, p_viewport->use_debanding, p_view_count);
+
+ _configure_3d_render_buffers(p_viewport);
}
RSG::storage->render_target_request_clear(p_viewport->render_target, bgcolor);
@@ -171,9 +194,9 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport, uint32_t p_view_coun
RendererCanvasRender::LightOccluderInstance *occluders = nullptr;
//make list of occluders
- for (Map<RID, Viewport::CanvasData>::Element *E = p_viewport->canvas_map.front(); E; E = E->next()) {
- RendererCanvasCull::Canvas *canvas = static_cast<RendererCanvasCull::Canvas *>(E->get().canvas);
- Transform2D xf = _canvas_get_transform(p_viewport, canvas, &E->get(), clip_rect.size);
+ for (KeyValue<RID, Viewport::CanvasData> &E : p_viewport->canvas_map) {
+ RendererCanvasCull::Canvas *canvas = static_cast<RendererCanvasCull::Canvas *>(E.value.canvas);
+ Transform2D xf = _canvas_get_transform(p_viewport, canvas, &E.value, clip_rect.size);
for (Set<RendererCanvasRender::LightOccluderInstance *>::Element *F = canvas->occluders.front(); F; F = F->next()) {
if (!F->get()->enabled) {
@@ -203,10 +226,10 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport, uint32_t p_view_coun
int directional_light_count = 0;
RENDER_TIMESTAMP("Cull Canvas Lights");
- for (Map<RID, Viewport::CanvasData>::Element *E = p_viewport->canvas_map.front(); E; E = E->next()) {
- RendererCanvasCull::Canvas *canvas = static_cast<RendererCanvasCull::Canvas *>(E->get().canvas);
+ for (KeyValue<RID, Viewport::CanvasData> &E : p_viewport->canvas_map) {
+ RendererCanvasCull::Canvas *canvas = static_cast<RendererCanvasCull::Canvas *>(E.value.canvas);
- Transform2D xf = _canvas_get_transform(p_viewport, canvas, &E->get(), clip_rect.size);
+ Transform2D xf = _canvas_get_transform(p_viewport, canvas, &E.value, clip_rect.size);
//find lights in canvas
@@ -268,7 +291,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport, uint32_t p_view_coun
}
}
- canvas_map[Viewport::CanvasKey(E->key(), E->get().layer, E->get().sublayer)] = &E->get();
+ canvas_map[Viewport::CanvasKey(E.key, E.value.layer, E.value.sublayer)] = &E.value;
}
if (lights_with_shadow) {
@@ -280,9 +303,9 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport, uint32_t p_view_coun
RENDER_TIMESTAMP("Cull Occluders");
//make list of occluders
- for (Map<RID, Viewport::CanvasData>::Element *E = p_viewport->canvas_map.front(); E; E = E->next()) {
- RendererCanvasCull::Canvas *canvas = static_cast<RendererCanvasCull::Canvas *>(E->get().canvas);
- Transform2D xf = _canvas_get_transform(p_viewport, canvas, &E->get(), clip_rect.size);
+ for (KeyValue<RID, Viewport::CanvasData> &E : p_viewport->canvas_map) {
+ RendererCanvasCull::Canvas *canvas = static_cast<RendererCanvasCull::Canvas *>(E.value.canvas);
+ Transform2D xf = _canvas_get_transform(p_viewport, canvas, &E.value, clip_rect.size);
for (Set<RendererCanvasRender::LightOccluderInstance *>::Element *F = canvas->occluders.front(); F; F = F->next()) {
if (!F->get()->enabled) {
@@ -361,9 +384,9 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport, uint32_t p_view_coun
//make list of occluders
int occ_cullded = 0;
- for (Map<RID, Viewport::CanvasData>::Element *E = p_viewport->canvas_map.front(); E; E = E->next()) {
- RendererCanvasCull::Canvas *canvas = static_cast<RendererCanvasCull::Canvas *>(E->get().canvas);
- Transform2D xf = _canvas_get_transform(p_viewport, canvas, &E->get(), clip_rect.size);
+ for (KeyValue<RID, Viewport::CanvasData> &E : p_viewport->canvas_map) {
+ RendererCanvasCull::Canvas *canvas = static_cast<RendererCanvasCull::Canvas *>(E.value.canvas);
+ Transform2D xf = _canvas_get_transform(p_viewport, canvas, &E.value, clip_rect.size);
for (Set<RendererCanvasRender::LightOccluderInstance *>::Element *F = canvas->occluders.front(); F; F = F->next()) {
if (!F->get()->enabled) {
@@ -400,17 +423,17 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport, uint32_t p_view_coun
scenario_draw_canvas_bg = false;
}
- for (Map<Viewport::CanvasKey, Viewport::CanvasData *>::Element *E = canvas_map.front(); E; E = E->next()) {
- RendererCanvasCull::Canvas *canvas = static_cast<RendererCanvasCull::Canvas *>(E->get()->canvas);
+ for (const KeyValue<Viewport::CanvasKey, Viewport::CanvasData *> &E : canvas_map) {
+ RendererCanvasCull::Canvas *canvas = static_cast<RendererCanvasCull::Canvas *>(E.value->canvas);
- Transform2D xform = _canvas_get_transform(p_viewport, canvas, E->get(), clip_rect.size);
+ Transform2D xform = _canvas_get_transform(p_viewport, canvas, E.value, clip_rect.size);
RendererCanvasRender::Light *canvas_lights = nullptr;
RendererCanvasRender::Light *canvas_directional_lights = nullptr;
RendererCanvasRender::Light *ptr = lights;
while (ptr) {
- if (E->get()->layer >= ptr->layer_min && E->get()->layer <= ptr->layer_max) {
+ if (E.value->layer >= ptr->layer_min && E.value->layer <= ptr->layer_max) {
ptr->next_ptr = canvas_lights;
canvas_lights = ptr;
}
@@ -419,7 +442,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport, uint32_t p_view_coun
ptr = directional_lights;
while (ptr) {
- if (E->get()->layer >= ptr->layer_min && E->get()->layer <= ptr->layer_max) {
+ if (E.value->layer >= ptr->layer_min && E.value->layer <= ptr->layer_max) {
ptr->next_ptr = canvas_directional_lights;
canvas_directional_lights = ptr;
}
@@ -432,7 +455,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport, uint32_t p_view_coun
}
i++;
- if (scenario_draw_canvas_bg && E->key().get_layer() >= scenario_canvas_max_layer) {
+ if (scenario_draw_canvas_bg && E.key.get_layer() >= scenario_canvas_max_layer) {
if (!can_draw_3d) {
RSG::scene->render_empty_scene(p_viewport->render_buffers, p_viewport->scenario, p_viewport->shadow_atlas);
} else {
@@ -515,7 +538,7 @@ void RendererViewport::draw_viewports() {
}
if (vp->update_mode == RS::VIEWPORT_UPDATE_WHEN_PARENT_VISIBLE) {
- Viewport *parent = viewport_owner.getornull(vp->parent);
+ Viewport *parent = viewport_owner.get_or_null(vp->parent);
if (parent && parent->last_pass == draw_viewports_pass) {
visible = true;
}
@@ -544,7 +567,7 @@ void RendererViewport::draw_viewports() {
RSG::storage->render_target_set_as_unused(vp->render_target);
if (vp->use_xr && xr_interface.is_valid()) {
// override our size, make sure it matches our required size and is created as a stereo target
- vp->size = xr_interface->get_render_targetsize();
+ vp->size = xr_interface->get_render_target_size();
uint32_t view_count = xr_interface->get_view_count();
RSG::storage->render_target_set_size(vp->render_target, vp->size.x, vp->size.y, view_count);
@@ -556,7 +579,7 @@ void RendererViewport::draw_viewports() {
RSG::scene->set_debug_draw_mode(vp->debug_draw);
// and draw viewport
- _draw_viewport(vp, view_count);
+ _draw_viewport(vp);
// measure
@@ -580,17 +603,17 @@ void RendererViewport::draw_viewports() {
RSG::scene->set_debug_draw_mode(vp->debug_draw);
// render standard mono camera
- _draw_viewport(vp, 1);
+ _draw_viewport(vp);
if (vp->viewport_to_screen != DisplayServer::INVALID_WINDOW_ID && (!vp->viewport_render_direct_to_screen || !RSG::rasterizer->is_low_end())) {
//copy to screen if set as such
BlitToScreen blit;
blit.render_target = vp->render_target;
if (vp->viewport_to_screen_rect != Rect2()) {
- blit.rect = vp->viewport_to_screen_rect;
+ blit.dst_rect = vp->viewport_to_screen_rect;
} else {
- blit.rect.position = Vector2();
- blit.rect.size = vp->size;
+ blit.dst_rect.position = Vector2();
+ blit.dst_rect.size = vp->size;
}
if (!blit_to_screen_list.has(vp->viewport_to_screen)) {
@@ -621,8 +644,8 @@ void RendererViewport::draw_viewports() {
//this needs to be called to make screen swapping more efficient
RSG::rasterizer->prepare_for_blitting_render_targets();
- for (Map<int, Vector<BlitToScreen>>::Element *E = blit_to_screen_list.front(); E; E = E->next()) {
- RSG::rasterizer->blit_render_targets_to_screen(E->key(), E->get().ptr(), E->get().size());
+ for (const KeyValue<int, Vector<BlitToScreen>> &E : blit_to_screen_list) {
+ RSG::rasterizer->blit_render_targets_to_screen(E.key, E.value.ptr(), E.value.size());
}
}
@@ -632,7 +655,7 @@ RID RendererViewport::viewport_allocate() {
void RendererViewport::viewport_initialize(RID p_rid) {
viewport_owner.initialize_rid(p_rid);
- Viewport *viewport = viewport_owner.getornull(p_rid);
+ Viewport *viewport = viewport_owner.get_or_null(p_rid);
viewport->self = p_rid;
viewport->render_target = RSG::storage->render_target_create();
viewport->shadow_atlas = RSG::scene->shadow_atlas_create();
@@ -640,7 +663,7 @@ void RendererViewport::viewport_initialize(RID p_rid) {
}
void RendererViewport::viewport_set_use_xr(RID p_viewport, bool p_use_xr) {
- Viewport *viewport = viewport_owner.getornull(p_viewport);
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
if (viewport->use_xr == p_use_xr) {
@@ -648,9 +671,22 @@ void RendererViewport::viewport_set_use_xr(RID p_viewport, bool p_use_xr) {
}
viewport->use_xr = p_use_xr;
- if (viewport->render_buffers.is_valid()) {
- RSG::scene->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa, viewport->screen_space_aa, viewport->use_debanding, viewport->get_view_count());
+ _configure_3d_render_buffers(viewport);
+}
+
+void RendererViewport::viewport_set_scale_3d(RID p_viewport, float p_scale_3d) {
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
+ ERR_FAIL_COND(!viewport);
+
+ // Clamp to reasonable values that are actually useful.
+ // Values above 2.0 don't serve a practical purpose since the viewport
+ // isn't displayed with mipmaps.
+ if (viewport->scale_3d == CLAMP(p_scale_3d, 0.1, 2.0)) {
+ return;
}
+
+ viewport->scale_3d = CLAMP(p_scale_3d, 0.1, 2.0);
+ _configure_3d_render_buffers(viewport);
}
uint32_t RendererViewport::Viewport::get_view_count() {
@@ -671,26 +707,19 @@ uint32_t RendererViewport::Viewport::get_view_count() {
void RendererViewport::viewport_set_size(RID p_viewport, int p_width, int p_height) {
ERR_FAIL_COND(p_width < 0 && p_height < 0);
- Viewport *viewport = viewport_owner.getornull(p_viewport);
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
viewport->size = Size2(p_width, p_height);
uint32_t view_count = viewport->get_view_count();
RSG::storage->render_target_set_size(viewport->render_target, p_width, p_height, view_count);
- if (viewport->render_buffers.is_valid()) {
- if (p_width == 0 || p_height == 0) {
- RSG::scene->free(viewport->render_buffers);
- viewport->render_buffers = RID();
- } else {
- RSG::scene->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa, viewport->screen_space_aa, viewport->use_debanding, view_count);
- }
- }
+ _configure_3d_render_buffers(viewport);
viewport->occlusion_buffer_dirty = true;
}
void RendererViewport::viewport_set_active(RID p_viewport, bool p_active) {
- Viewport *viewport = viewport_owner.getornull(p_viewport);
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
if (p_active) {
@@ -703,21 +732,21 @@ void RendererViewport::viewport_set_active(RID p_viewport, bool p_active) {
}
void RendererViewport::viewport_set_parent_viewport(RID p_viewport, RID p_parent_viewport) {
- Viewport *viewport = viewport_owner.getornull(p_viewport);
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
viewport->parent = p_parent_viewport;
}
void RendererViewport::viewport_set_clear_mode(RID p_viewport, RS::ViewportClearMode p_clear_mode) {
- Viewport *viewport = viewport_owner.getornull(p_viewport);
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
viewport->clear_mode = p_clear_mode;
}
void RendererViewport::viewport_attach_to_screen(RID p_viewport, const Rect2 &p_rect, DisplayServer::WindowID p_screen) {
- Viewport *viewport = viewport_owner.getornull(p_viewport);
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
if (p_screen != DisplayServer::INVALID_WINDOW_ID) {
@@ -743,7 +772,7 @@ void RendererViewport::viewport_attach_to_screen(RID p_viewport, const Rect2 &p_
}
void RendererViewport::viewport_set_render_direct_to_screen(RID p_viewport, bool p_enable) {
- Viewport *viewport = viewport_owner.getornull(p_viewport);
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
if (p_enable == viewport->viewport_render_direct_to_screen) {
@@ -767,21 +796,21 @@ void RendererViewport::viewport_set_render_direct_to_screen(RID p_viewport, bool
}
void RendererViewport::viewport_set_update_mode(RID p_viewport, RS::ViewportUpdateMode p_mode) {
- Viewport *viewport = viewport_owner.getornull(p_viewport);
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
viewport->update_mode = p_mode;
}
RID RendererViewport::viewport_get_texture(RID p_viewport) const {
- const Viewport *viewport = viewport_owner.getornull(p_viewport);
+ const Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND_V(!viewport, RID());
return RSG::storage->render_target_get_texture(viewport->render_target);
}
RID RendererViewport::viewport_get_occluder_debug_texture(RID p_viewport) const {
- const Viewport *viewport = viewport_owner.getornull(p_viewport);
+ const Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND_V(!viewport, RID());
if (viewport->use_occlusion_culling && viewport->debug_draw == RenderingServer::VIEWPORT_DEBUG_DRAW_OCCLUDERS) {
@@ -791,35 +820,35 @@ RID RendererViewport::viewport_get_occluder_debug_texture(RID p_viewport) const
}
void RendererViewport::viewport_set_disable_2d(RID p_viewport, bool p_disable) {
- Viewport *viewport = viewport_owner.getornull(p_viewport);
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
viewport->disable_2d = p_disable;
}
void RendererViewport::viewport_set_disable_environment(RID p_viewport, bool p_disable) {
- Viewport *viewport = viewport_owner.getornull(p_viewport);
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
viewport->disable_environment = p_disable;
}
void RendererViewport::viewport_set_disable_3d(RID p_viewport, bool p_disable) {
- Viewport *viewport = viewport_owner.getornull(p_viewport);
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
viewport->disable_3d = p_disable;
}
void RendererViewport::viewport_attach_camera(RID p_viewport, RID p_camera) {
- Viewport *viewport = viewport_owner.getornull(p_viewport);
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
viewport->camera = p_camera;
}
void RendererViewport::viewport_set_scenario(RID p_viewport, RID p_scenario) {
- Viewport *viewport = viewport_owner.getornull(p_viewport);
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
if (viewport->scenario.is_valid()) {
@@ -833,11 +862,11 @@ void RendererViewport::viewport_set_scenario(RID p_viewport, RID p_scenario) {
}
void RendererViewport::viewport_attach_canvas(RID p_viewport, RID p_canvas) {
- Viewport *viewport = viewport_owner.getornull(p_viewport);
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
ERR_FAIL_COND(viewport->canvas_map.has(p_canvas));
- RendererCanvasCull::Canvas *canvas = RSG::canvas->canvas_owner.getornull(p_canvas);
+ RendererCanvasCull::Canvas *canvas = RSG::canvas->canvas_owner.get_or_null(p_canvas);
ERR_FAIL_COND(!canvas);
canvas->viewports.insert(p_viewport);
@@ -848,10 +877,10 @@ void RendererViewport::viewport_attach_canvas(RID p_viewport, RID p_canvas) {
}
void RendererViewport::viewport_remove_canvas(RID p_viewport, RID p_canvas) {
- Viewport *viewport = viewport_owner.getornull(p_viewport);
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
- RendererCanvasCull::Canvas *canvas = RSG::canvas->canvas_owner.getornull(p_canvas);
+ RendererCanvasCull::Canvas *canvas = RSG::canvas->canvas_owner.get_or_null(p_canvas);
ERR_FAIL_COND(!canvas);
viewport->canvas_map.erase(p_canvas);
@@ -859,7 +888,7 @@ void RendererViewport::viewport_remove_canvas(RID p_viewport, RID p_canvas) {
}
void RendererViewport::viewport_set_canvas_transform(RID p_viewport, RID p_canvas, const Transform2D &p_offset) {
- Viewport *viewport = viewport_owner.getornull(p_viewport);
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
ERR_FAIL_COND(!viewport->canvas_map.has(p_canvas));
@@ -867,7 +896,7 @@ void RendererViewport::viewport_set_canvas_transform(RID p_viewport, RID p_canva
}
void RendererViewport::viewport_set_transparent_background(RID p_viewport, bool p_enabled) {
- Viewport *viewport = viewport_owner.getornull(p_viewport);
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
RSG::storage->render_target_set_flag(viewport->render_target, RendererStorage::RENDER_TARGET_TRANSPARENT, p_enabled);
@@ -875,14 +904,14 @@ void RendererViewport::viewport_set_transparent_background(RID p_viewport, bool
}
void RendererViewport::viewport_set_global_canvas_transform(RID p_viewport, const Transform2D &p_transform) {
- Viewport *viewport = viewport_owner.getornull(p_viewport);
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
viewport->global_transform = p_transform;
}
void RendererViewport::viewport_set_canvas_stacking(RID p_viewport, RID p_canvas, int p_layer, int p_sublayer) {
- Viewport *viewport = viewport_owner.getornull(p_viewport);
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
ERR_FAIL_COND(!viewport->canvas_map.has(p_canvas));
@@ -891,7 +920,7 @@ void RendererViewport::viewport_set_canvas_stacking(RID p_viewport, RID p_canvas
}
void RendererViewport::viewport_set_shadow_atlas_size(RID p_viewport, int p_size, bool p_16_bits) {
- Viewport *viewport = viewport_owner.getornull(p_viewport);
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
viewport->shadow_atlas_size = p_size;
@@ -901,53 +930,47 @@ void RendererViewport::viewport_set_shadow_atlas_size(RID p_viewport, int p_size
}
void RendererViewport::viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv) {
- Viewport *viewport = viewport_owner.getornull(p_viewport);
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
RSG::scene->shadow_atlas_set_quadrant_subdivision(viewport->shadow_atlas, p_quadrant, p_subdiv);
}
void RendererViewport::viewport_set_msaa(RID p_viewport, RS::ViewportMSAA p_msaa) {
- Viewport *viewport = viewport_owner.getornull(p_viewport);
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
if (viewport->msaa == p_msaa) {
return;
}
viewport->msaa = p_msaa;
- if (viewport->render_buffers.is_valid()) {
- RSG::scene->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, p_msaa, viewport->screen_space_aa, viewport->use_debanding, viewport->get_view_count());
- }
+ _configure_3d_render_buffers(viewport);
}
void RendererViewport::viewport_set_screen_space_aa(RID p_viewport, RS::ViewportScreenSpaceAA p_mode) {
- Viewport *viewport = viewport_owner.getornull(p_viewport);
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
if (viewport->screen_space_aa == p_mode) {
return;
}
viewport->screen_space_aa = p_mode;
- if (viewport->render_buffers.is_valid()) {
- RSG::scene->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa, p_mode, viewport->use_debanding, viewport->get_view_count());
- }
+ _configure_3d_render_buffers(viewport);
}
void RendererViewport::viewport_set_use_debanding(RID p_viewport, bool p_use_debanding) {
- Viewport *viewport = viewport_owner.getornull(p_viewport);
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
if (viewport->use_debanding == p_use_debanding) {
return;
}
viewport->use_debanding = p_use_debanding;
- if (viewport->render_buffers.is_valid()) {
- RSG::scene->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa, viewport->screen_space_aa, p_use_debanding, viewport->get_view_count());
- }
+ _configure_3d_render_buffers(viewport);
}
void RendererViewport::viewport_set_use_occlusion_culling(RID p_viewport, bool p_use_occlusion_culling) {
- Viewport *viewport = viewport_owner.getornull(p_viewport);
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
if (viewport->use_occlusion_culling == p_use_occlusion_culling) {
@@ -982,7 +1005,7 @@ void RendererViewport::viewport_set_occlusion_culling_build_quality(RS::Viewport
}
void RendererViewport::viewport_set_lod_threshold(RID p_viewport, float p_pixels) {
- Viewport *viewport = viewport_owner.getornull(p_viewport);
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
viewport->lod_threshold = p_pixels;
@@ -991,7 +1014,7 @@ void RendererViewport::viewport_set_lod_threshold(RID p_viewport, float p_pixels
int RendererViewport::viewport_get_render_info(RID p_viewport, RS::ViewportRenderInfoType p_type, RS::ViewportRenderInfo p_info) {
ERR_FAIL_INDEX_V(p_info, RS::VIEWPORT_RENDER_INFO_MAX, -1);
- Viewport *viewport = viewport_owner.getornull(p_viewport);
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
if (!viewport) {
return 0; //there should be a lock here..
}
@@ -1000,62 +1023,62 @@ int RendererViewport::viewport_get_render_info(RID p_viewport, RS::ViewportRende
}
void RendererViewport::viewport_set_debug_draw(RID p_viewport, RS::ViewportDebugDraw p_draw) {
- Viewport *viewport = viewport_owner.getornull(p_viewport);
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
viewport->debug_draw = p_draw;
}
void RendererViewport::viewport_set_measure_render_time(RID p_viewport, bool p_enable) {
- Viewport *viewport = viewport_owner.getornull(p_viewport);
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
viewport->measure_render_time = p_enable;
}
float RendererViewport::viewport_get_measured_render_time_cpu(RID p_viewport) const {
- Viewport *viewport = viewport_owner.getornull(p_viewport);
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND_V(!viewport, 0);
return double(viewport->time_cpu_end - viewport->time_cpu_begin) / 1000.0;
}
float RendererViewport::viewport_get_measured_render_time_gpu(RID p_viewport) const {
- Viewport *viewport = viewport_owner.getornull(p_viewport);
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND_V(!viewport, 0);
return double((viewport->time_gpu_end - viewport->time_gpu_begin) / 1000) / 1000.0;
}
void RendererViewport::viewport_set_snap_2d_transforms_to_pixel(RID p_viewport, bool p_enabled) {
- Viewport *viewport = viewport_owner.getornull(p_viewport);
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
viewport->snap_2d_transforms_to_pixel = p_enabled;
}
void RendererViewport::viewport_set_snap_2d_vertices_to_pixel(RID p_viewport, bool p_enabled) {
- Viewport *viewport = viewport_owner.getornull(p_viewport);
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
viewport->snap_2d_vertices_to_pixel = p_enabled;
}
void RendererViewport::viewport_set_default_canvas_item_texture_filter(RID p_viewport, RS::CanvasItemTextureFilter p_filter) {
ERR_FAIL_COND_MSG(p_filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, "Viewport does not accept DEFAULT as texture filter (it's the topmost choice already).)");
- Viewport *viewport = viewport_owner.getornull(p_viewport);
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
viewport->texture_filter = p_filter;
}
void RendererViewport::viewport_set_default_canvas_item_texture_repeat(RID p_viewport, RS::CanvasItemTextureRepeat p_repeat) {
ERR_FAIL_COND_MSG(p_repeat == RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, "Viewport does not accept DEFAULT as texture repeat (it's the topmost choice already).)");
- Viewport *viewport = viewport_owner.getornull(p_viewport);
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
viewport->texture_repeat = p_repeat;
}
void RendererViewport::viewport_set_sdf_oversize_and_scale(RID p_viewport, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) {
- Viewport *viewport = viewport_owner.getornull(p_viewport);
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
RSG::storage->render_target_set_sdf_size_and_scale(viewport->render_target, p_size, p_scale);
@@ -1063,7 +1086,7 @@ void RendererViewport::viewport_set_sdf_oversize_and_scale(RID p_viewport, RS::V
bool RendererViewport::free(RID p_rid) {
if (viewport_owner.owns(p_rid)) {
- Viewport *viewport = viewport_owner.getornull(p_rid);
+ Viewport *viewport = viewport_owner.get_or_null(p_rid);
RSG::storage->free(viewport->render_target);
RSG::scene->free(viewport->shadow_atlas);
@@ -1096,7 +1119,7 @@ void RendererViewport::handle_timestamp(String p_timestamp, uint64_t p_cpu_time,
return;
}
- Viewport *viewport = viewport_owner.getornull(*vp);
+ Viewport *viewport = viewport_owner.get_or_null(*vp);
if (!viewport) {
return;
}
diff --git a/servers/rendering/renderer_viewport.h b/servers/rendering/renderer_viewport.h
index ac7a35f97d..f6e6cc8e84 100644
--- a/servers/rendering/renderer_viewport.h
+++ b/servers/rendering/renderer_viewport.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef VISUALSERVERVIEWPORT_H
-#define VISUALSERVERVIEWPORT_H
+#ifndef RENDERER_VIEWPORT_H
+#define RENDERER_VIEWPORT_H
#include "core/templates/local_vector.h"
#include "core/templates/rid_owner.h"
@@ -49,6 +49,8 @@ public:
bool use_xr; /* use xr interface to override camera positioning and projection matrices and control output */
+ float scale_3d = 1.0;
+
Size2i size;
RID camera;
RID scenario;
@@ -192,8 +194,9 @@ public:
int total_draw_calls_used = 0;
private:
+ void _configure_3d_render_buffers(Viewport *p_viewport);
void _draw_3d(Viewport *p_viewport);
- void _draw_viewport(Viewport *p_viewport, uint32_t p_view_count = 1);
+ void _draw_viewport(Viewport *p_viewport);
int occlusion_rays_per_thread = 512;
@@ -204,6 +207,7 @@ public:
void viewport_initialize(RID p_rid);
void viewport_set_use_xr(RID p_viewport, bool p_use_xr);
+ void viewport_set_scale_3d(RID p_viewport, float p_scale_3d);
void viewport_set_size(RID p_viewport, int p_width, int p_height);
@@ -278,4 +282,4 @@ public:
virtual ~RendererViewport() {}
};
-#endif // VISUALSERVERVIEWPORT_H
+#endif // RENDERER_VIEWPORT_H
diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp
index b302c6b793..dcbc5f5c8e 100644
--- a/servers/rendering/rendering_device.cpp
+++ b/servers/rendering/rendering_device.cpp
@@ -476,7 +476,9 @@ void RenderingDevice::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_device_name"), &RenderingDevice::get_device_name);
ClassDB::bind_method(D_METHOD("get_device_pipeline_cache_uuid"), &RenderingDevice::get_device_pipeline_cache_uuid);
- ClassDB::bind_method(D_METHOD("get_memory_usage"), &RenderingDevice::get_memory_usage);
+ ClassDB::bind_method(D_METHOD("get_memory_usage", "type"), &RenderingDevice::get_memory_usage);
+
+ ClassDB::bind_method(D_METHOD("get_driver_resource", "resource", "rid", "index"), &RenderingDevice::get_driver_resource);
BIND_CONSTANT(BARRIER_MASK_RASTER);
BIND_CONSTANT(BARRIER_MASK_COMPUTE);
@@ -484,6 +486,20 @@ void RenderingDevice::_bind_methods() {
BIND_CONSTANT(BARRIER_MASK_ALL);
BIND_CONSTANT(BARRIER_MASK_NO_BARRIER);
+ BIND_ENUM_CONSTANT(DRIVER_RESOURCE_VULKAN_DEVICE);
+ BIND_ENUM_CONSTANT(DRIVER_RESOURCE_VULKAN_PHYSICAL_DEVICE);
+ BIND_ENUM_CONSTANT(DRIVER_RESOURCE_VULKAN_INSTANCE);
+ BIND_ENUM_CONSTANT(DRIVER_RESOURCE_VULKAN_QUEUE);
+ BIND_ENUM_CONSTANT(DRIVER_RESOURCE_VULKAN_QUEUE_FAMILY_INDEX);
+ BIND_ENUM_CONSTANT(DRIVER_RESOURCE_VULKAN_IMAGE);
+ BIND_ENUM_CONSTANT(DRIVER_RESOURCE_VULKAN_IMAGE_VIEW);
+ BIND_ENUM_CONSTANT(DRIVER_RESOURCE_VULKAN_IMAGE_NATIVE_TEXTURE_FORMAT);
+ BIND_ENUM_CONSTANT(DRIVER_RESOURCE_VULKAN_SAMPLER);
+ BIND_ENUM_CONSTANT(DRIVER_RESOURCE_VULKAN_DESCRIPTOR_SET);
+ BIND_ENUM_CONSTANT(DRIVER_RESOURCE_VULKAN_BUFFER);
+ BIND_ENUM_CONSTANT(DRIVER_RESOURCE_VULKAN_COMPUTE_PIPELINE);
+ BIND_ENUM_CONSTANT(DRIVER_RESOURCE_VULKAN_RENDER_PIPELINE);
+
BIND_ENUM_CONSTANT(DATA_FORMAT_R4G4_UNORM_PACK8);
BIND_ENUM_CONSTANT(DATA_FORMAT_R4G4B4A4_UNORM_PACK16);
BIND_ENUM_CONSTANT(DATA_FORMAT_B4G4R4A4_UNORM_PACK16);
diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h
index e2d207dab2..5eb8f1cead 100644
--- a/servers/rendering/rendering_device.h
+++ b/servers/rendering/rendering_device.h
@@ -60,6 +60,23 @@ public:
DEVICE_DIRECTX
};
+ enum DriverResource {
+ DRIVER_RESOURCE_VULKAN_DEVICE = 0,
+ DRIVER_RESOURCE_VULKAN_PHYSICAL_DEVICE,
+ DRIVER_RESOURCE_VULKAN_INSTANCE,
+ DRIVER_RESOURCE_VULKAN_QUEUE,
+ DRIVER_RESOURCE_VULKAN_QUEUE_FAMILY_INDEX,
+ DRIVER_RESOURCE_VULKAN_IMAGE,
+ DRIVER_RESOURCE_VULKAN_IMAGE_VIEW,
+ DRIVER_RESOURCE_VULKAN_IMAGE_NATIVE_TEXTURE_FORMAT,
+ DRIVER_RESOURCE_VULKAN_SAMPLER,
+ DRIVER_RESOURCE_VULKAN_DESCRIPTOR_SET,
+ DRIVER_RESOURCE_VULKAN_BUFFER,
+ DRIVER_RESOURCE_VULKAN_COMPUTE_PIPELINE,
+ DRIVER_RESOURCE_VULKAN_RENDER_PIPELINE,
+ //next driver continue enum from 1000 to keep order
+ };
+
enum ShaderStage {
SHADER_STAGE_VERTEX,
SHADER_STAGE_FRAGMENT,
@@ -495,6 +512,7 @@ public:
virtual bool texture_is_format_supported_for_usage(DataFormat p_format, uint32_t p_usage) const = 0;
virtual bool texture_is_shared(RID p_texture) = 0;
virtual bool texture_is_valid(RID p_texture) = 0;
+ virtual Size2i texture_size(RID p_texture) = 0;
virtual Error texture_copy(RID p_from_texture, RID p_to_texture, const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_size, uint32_t p_src_mipmap, uint32_t p_dst_mipmap, uint32_t p_src_layer, uint32_t p_dst_layer, uint32_t p_post_barrier = BARRIER_MASK_ALL) = 0;
virtual Error texture_clear(RID p_texture, const Color &p_color, uint32_t p_base_mipmap, uint32_t p_mipmaps, uint32_t p_base_layer, uint32_t p_layers, uint32_t p_post_barrier = BARRIER_MASK_ALL) = 0;
@@ -1182,6 +1200,8 @@ public:
virtual String get_device_name() const = 0;
virtual String get_device_pipeline_cache_uuid() const = 0;
+ virtual uint64_t get_driver_resource(DriverResource p_resource, RID p_rid = RID(), uint64_t p_index = 0) = 0;
+
static RenderingDevice *get_singleton();
RenderingDevice();
@@ -1216,6 +1236,7 @@ protected:
Vector<int64_t> _draw_list_switch_to_next_pass_split(uint32_t p_splits);
};
+VARIANT_ENUM_CAST(RenderingDevice::DriverResource)
VARIANT_ENUM_CAST(RenderingDevice::ShaderStage)
VARIANT_ENUM_CAST(RenderingDevice::ShaderLanguage)
VARIANT_ENUM_CAST(RenderingDevice::CompareOperator)
diff --git a/servers/rendering/rendering_device_binds.cpp b/servers/rendering/rendering_device_binds.cpp
index fa3f2f3895..a21f28989b 100644
--- a/servers/rendering/rendering_device_binds.cpp
+++ b/servers/rendering/rendering_device_binds.cpp
@@ -171,7 +171,7 @@ Error RDShaderFile::parse_versions_from_text(const String &p_text, const String
/* STEP 2, Compile the versions, add to shader file */
- for (Map<StringName, String>::Element *E = version_texts.front(); E; E = E->next()) {
+ for (const KeyValue<StringName, String> &E : version_texts) {
Ref<RDShaderSPIRV> bytecode;
bytecode.instantiate();
@@ -180,7 +180,7 @@ Error RDShaderFile::parse_versions_from_text(const String &p_text, const String
if (code == String()) {
continue;
}
- code = code.replace("VERSION_DEFINES", E->get());
+ code = code.replace("VERSION_DEFINES", E.value);
String error;
Vector<uint8_t> spirv = RenderingDevice::get_singleton()->shader_compile_spirv_from_source(RD::ShaderStage(i), code, RD::SHADER_LANGUAGE_GLSL, &error, false);
bytecode->set_stage_bytecode(RD::ShaderStage(i), spirv);
@@ -195,7 +195,7 @@ Error RDShaderFile::parse_versions_from_text(const String &p_text, const String
bytecode->set_stage_compile_error(RD::ShaderStage(i), error);
}
- set_bytecode(bytecode, E->key());
+ set_bytecode(bytecode, E.key);
}
return errors_found ? ERR_PARSE_ERROR : OK;
diff --git a/servers/rendering/rendering_device_binds.h b/servers/rendering/rendering_device_binds.h
index ccc3e2fb39..da614877c4 100644
--- a/servers/rendering/rendering_device_binds.h
+++ b/servers/rendering/rendering_device_binds.h
@@ -351,8 +351,8 @@ public:
Vector<StringName> get_version_list() const {
Vector<StringName> vnames;
- for (Map<StringName, Ref<RDShaderSPIRV>>::Element *E = versions.front(); E; E = E->next()) {
- vnames.push_back(E->key());
+ for (const KeyValue<StringName, Ref<RDShaderSPIRV>> &E : versions) {
+ vnames.push_back(E.key);
}
vnames.sort_custom<StringName::AlphCompare>();
return vnames;
@@ -371,9 +371,9 @@ public:
if (base_error != "") {
ERR_PRINT("Error parsing shader '" + p_file + "':\n\n" + base_error);
} else {
- for (Map<StringName, Ref<RDShaderSPIRV>>::Element *E = versions.front(); E; E = E->next()) {
+ for (KeyValue<StringName, Ref<RDShaderSPIRV>> &E : versions) {
for (int i = 0; i < RD::SHADER_STAGE_MAX; i++) {
- String error = E->get()->get_stage_compile_error(RD::ShaderStage(i));
+ String error = E.value->get_stage_compile_error(RD::ShaderStage(i));
if (error != String()) {
static const char *stage_str[RD::SHADER_STAGE_MAX] = {
"vertex",
@@ -383,7 +383,7 @@ public:
"compute"
};
- ERR_PRINT("Error parsing shader '" + p_file + "', version '" + String(E->key()) + "', stage '" + stage_str[i] + "':\n\n" + error);
+ ERR_PRINT("Error parsing shader '" + p_file + "', version '" + String(E.key) + "', stage '" + stage_str[i] + "':\n\n" + error);
}
}
}
diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp
index bed6ade1f6..107c9f8040 100644
--- a/servers/rendering/rendering_server_default.cpp
+++ b/servers/rendering/rendering_server_default.cpp
@@ -38,13 +38,16 @@
#include "renderer_scene_cull.h"
#include "rendering_server_globals.h"
-// careful, these may run in different threads than the visual server
+// careful, these may run in different threads than the rendering server
int RenderingServerDefault::changes = 0;
/* FREE */
void RenderingServerDefault::_free(RID p_rid) {
+ if (unlikely(p_rid.is_null())) {
+ return;
+ }
if (RSG::storage->free(p_rid)) {
return;
}
diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h
index c1336ee42d..911d4c463b 100644
--- a/servers/rendering/rendering_server_default.h
+++ b/servers/rendering/rendering_server_default.h
@@ -526,6 +526,7 @@ public:
FUNCRIDSPLIT(viewport)
FUNC2(viewport_set_use_xr, RID, bool)
+ FUNC2(viewport_set_scale_3d, RID, float)
FUNC3(viewport_set_size, RID, int, int)
FUNC2(viewport_set_active, RID, bool)
@@ -607,7 +608,7 @@ public:
FUNC2(environment_set_bg_color, RID, const Color &)
FUNC2(environment_set_bg_energy, RID, float)
FUNC2(environment_set_canvas_max_layer, RID, int)
- FUNC7(environment_set_ambient_light, RID, const Color &, EnvironmentAmbientSource, float, float, EnvironmentReflectionSource, const Color &)
+ FUNC6(environment_set_ambient_light, RID, const Color &, EnvironmentAmbientSource, float, float, EnvironmentReflectionSource)
// FIXME: Disabled during Vulkan refactoring, should be ported.
#if 0
@@ -762,6 +763,7 @@ public:
FUNC4(canvas_item_add_circle, RID, const Point2 &, float, const Color &)
FUNC6(canvas_item_add_texture_rect, RID, const Rect2 &, RID, bool, const Color &, bool)
FUNC7(canvas_item_add_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, bool, bool)
+ FUNC7(canvas_item_add_msdf_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, int, float)
FUNC10(canvas_item_add_nine_patch, RID, const Rect2 &, const Rect2 &, RID, const Vector2 &, const Vector2 &, NinePatchAxisMode, NinePatchAxisMode, bool, const Color &)
FUNC6(canvas_item_add_primitive, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, float)
FUNC5(canvas_item_add_polygon, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID)
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index 4218214fda..9c38bf7606 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -930,7 +930,6 @@ void ShaderLanguage::clear() {
error_set = false;
error_str = "";
last_const = false;
- pass_array = false;
while (nodes) {
Node *n = nodes;
nodes = nodes->next;
@@ -1078,6 +1077,9 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea
if (r_data_type) {
*r_data_type = shader->uniforms[p_identifier].type;
}
+ if (r_array_size) {
+ *r_array_size = shader->uniforms[p_identifier].array_size;
+ }
if (r_type) {
*r_type = IDENTIFIER_UNIFORM;
}
@@ -1597,7 +1599,8 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
}
const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
- //constructors
+ // Constructors.
+
{ "bool", TYPE_BOOL, { TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "bvec2", TYPE_BVEC2, { TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "bvec2", TYPE_BVEC2, { TYPE_BOOL, TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
@@ -1670,7 +1673,7 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "mat3", TYPE_MAT3, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "mat4", TYPE_MAT4, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- //conversion scalars
+ // Conversion scalars.
{ "int", TYPE_INT, { TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "int", TYPE_INT, { TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
@@ -1692,7 +1695,7 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "bool", TYPE_BOOL, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
{ "bool", TYPE_BOOL, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- //conversion vectors
+ // Conversion vectors.
{ "ivec2", TYPE_IVEC2, { TYPE_BVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "ivec2", TYPE_IVEC2, { TYPE_IVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
@@ -1754,7 +1757,7 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "bvec4", TYPE_BVEC4, { TYPE_UVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
{ "bvec4", TYPE_BVEC4, { TYPE_VEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- //conversion between matrixes
+ // Conversion between matrixes.
{ "mat2", TYPE_MAT2, { TYPE_MAT3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "mat2", TYPE_MAT2, { TYPE_MAT4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
@@ -1763,43 +1766,58 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "mat4", TYPE_MAT4, { TYPE_MAT2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "mat4", TYPE_MAT4, { TYPE_MAT3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- //builtins - trigonometry
+ // Built-ins - trigonometric functions.
+ // radians
{ "radians", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "degrees" }, TAG_GLOBAL, false },
{ "radians", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "degrees" }, TAG_GLOBAL, false },
{ "radians", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "degrees" }, TAG_GLOBAL, false },
{ "radians", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "degrees" }, TAG_GLOBAL, false },
+ // degrees
+
{ "degrees", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "radians" }, TAG_GLOBAL, false },
{ "degrees", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "radians" }, TAG_GLOBAL, false },
{ "degrees", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "radians" }, TAG_GLOBAL, false },
{ "degrees", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "radians" }, TAG_GLOBAL, false },
+ // sin
+
{ "sin", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false },
{ "sin", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false },
{ "sin", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false },
{ "sin", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false },
+ // cos
+
{ "cos", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false },
{ "cos", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false },
{ "cos", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false },
{ "cos", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false },
+ // tan
+
{ "tan", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false },
{ "tan", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false },
{ "tan", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false },
{ "tan", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false },
+ // asin
+
{ "asin", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "asin", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "asin", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "asin", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ // acos
+
{ "acos", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "acos", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "acos", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "acos", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ // atan
+
{ "atan", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "y_over_x" }, TAG_GLOBAL, false },
{ "atan", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "y_over_x" }, TAG_GLOBAL, false },
{ "atan", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "y_over_x" }, TAG_GLOBAL, false },
@@ -1809,66 +1827,101 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "atan", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "y", "x" }, TAG_GLOBAL, false },
{ "atan", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "y", "x" }, TAG_GLOBAL, false },
+ // sinh
+
{ "sinh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "sinh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "sinh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "sinh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ // cosh
+
{ "cosh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "cosh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "cosh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "cosh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ // tanh
+
{ "tanh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "tanh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "tanh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "tanh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ // asinh
+
{ "asinh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "asinh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "asinh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "asinh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ // acosh
+
{ "acosh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "acosh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "acosh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "acosh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ // atanh
+
{ "atanh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "atanh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "atanh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "atanh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
- //builtins - exponential
+ // Builtins - exponential functions.
+ // pow
+
{ "pow", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false },
{ "pow", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false },
{ "pow", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false },
{ "pow", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false },
+
+ // exp
+
{ "exp", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "exp", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "exp", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "exp", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ // log
+
{ "log", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "log", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "log", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "log", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ // exp2
+
{ "exp2", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "exp2", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "exp2", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "exp2", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ // log2
+
{ "log2", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "log2", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "log2", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "log2", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ // sqrt
+
{ "sqrt", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "sqrt", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "sqrt", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "sqrt", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ // inversesqrt
+
{ "inversesqrt", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "inversesqrt", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "inversesqrt", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "inversesqrt", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
- //builtins - common
+
+ // Built-ins - common functions.
+ // abs
+
{ "abs", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "abs", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "abs", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
@@ -1879,6 +1932,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "abs", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "abs", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ // sign
+
{ "sign", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "sign", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "sign", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
@@ -1889,31 +1944,50 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "sign", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "sign", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ // floor
+
{ "floor", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "floor", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "floor", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "floor", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ // trunc
+
{ "trunc", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "trunc", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "trunc", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "trunc", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ // round
+
{ "round", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "round", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "round", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "round", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ // roundEven
+
{ "roundEven", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "roundEven", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "roundEven", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "roundEven", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ // ceil
+
{ "ceil", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "ceil", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "ceil", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "ceil", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ // fract
+
{ "fract", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "fract", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "fract", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "fract", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ // mod
+
{ "mod", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false },
{ "mod", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false },
{ "mod", TYPE_VEC2, { TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false },
@@ -1922,11 +1996,15 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "mod", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false },
{ "mod", TYPE_VEC4, { TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false },
+ // modf
+
{ "modf", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "x", "i" }, TAG_GLOBAL, true },
{ "modf", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "x", "i" }, TAG_GLOBAL, true },
{ "modf", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "x", "i" }, TAG_GLOBAL, true },
{ "modf", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "x", "i" }, TAG_GLOBAL, true },
+ // min
+
{ "min", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "min", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "min", TYPE_VEC2, { TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
@@ -1951,6 +2029,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "min", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
{ "min", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ // max
+
{ "max", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "max", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "max", TYPE_VEC2, { TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
@@ -1975,6 +2055,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "max", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
{ "max", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ // clamp
+
{ "clamp", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
{ "clamp", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
{ "clamp", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
@@ -1999,6 +2081,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "clamp", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, true },
{ "clamp", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, true },
+ // mix
+
{ "mix", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "a", "b", "value" }, TAG_GLOBAL, false },
{ "mix", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "a", "b", "value" }, TAG_GLOBAL, false },
{ "mix", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_BVEC2, TYPE_VOID }, { "a", "b", "value" }, TAG_GLOBAL, false },
@@ -2010,6 +2094,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "mix", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_BVEC4, TYPE_VOID }, { "a", "b", "value" }, TAG_GLOBAL, false },
{ "mix", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b", "value" }, TAG_GLOBAL, false },
+ // step
+
{ "step", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "edge", "x" }, TAG_GLOBAL, false },
{ "step", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "edge", "x" }, TAG_GLOBAL, false },
{ "step", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "edge", "x" }, TAG_GLOBAL, false },
@@ -2017,6 +2103,9 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "step", TYPE_VEC2, { TYPE_FLOAT, TYPE_VEC2, TYPE_VOID }, { "edge", "x" }, TAG_GLOBAL, false },
{ "step", TYPE_VEC3, { TYPE_FLOAT, TYPE_VEC3, TYPE_VOID }, { "edge", "x" }, TAG_GLOBAL, false },
{ "step", TYPE_VEC4, { TYPE_FLOAT, TYPE_VEC4, TYPE_VOID }, { "edge", "x" }, TAG_GLOBAL, false },
+
+ // smoothstep
+
{ "smoothstep", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "edge0", "edge1", "value" }, TAG_GLOBAL, false },
{ "smoothstep", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "edge0", "edge1", "value" }, TAG_GLOBAL, false },
{ "smoothstep", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "edge0", "edge1", "value" }, TAG_GLOBAL, false },
@@ -2025,77 +2114,127 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "smoothstep", TYPE_VEC3, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VEC3, TYPE_VOID }, { "edge0", "edge1", "value" }, TAG_GLOBAL, false },
{ "smoothstep", TYPE_VEC4, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VEC4, TYPE_VOID }, { "edge0", "edge1", "value" }, TAG_GLOBAL, false },
+ // isnan
+
{ "isnan", TYPE_BOOL, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "isnan", TYPE_BVEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "isnan", TYPE_BVEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "isnan", TYPE_BVEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ // isinf
+
{ "isinf", TYPE_BOOL, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "isinf", TYPE_BVEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "isinf", TYPE_BVEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "isinf", TYPE_BVEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ // floatBitsToInt
+
{ "floatBitsToInt", TYPE_INT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
{ "floatBitsToInt", TYPE_IVEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
{ "floatBitsToInt", TYPE_IVEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
{ "floatBitsToInt", TYPE_IVEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+ // floatBitsToUint
+
{ "floatBitsToUint", TYPE_UINT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
{ "floatBitsToUint", TYPE_UVEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
{ "floatBitsToUint", TYPE_UVEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
{ "floatBitsToUint", TYPE_UVEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+ // intBitsToFloat
+
{ "intBitsToFloat", TYPE_FLOAT, { TYPE_INT, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
{ "intBitsToFloat", TYPE_VEC2, { TYPE_IVEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
{ "intBitsToFloat", TYPE_VEC3, { TYPE_IVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
{ "intBitsToFloat", TYPE_VEC4, { TYPE_IVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+ // uintBitsToFloat
+
{ "uintBitsToFloat", TYPE_FLOAT, { TYPE_UINT, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
{ "uintBitsToFloat", TYPE_VEC2, { TYPE_UVEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
{ "uintBitsToFloat", TYPE_VEC3, { TYPE_UVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
{ "uintBitsToFloat", TYPE_VEC4, { TYPE_UVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
- //builtins - geometric
+ // Built-ins - geometric functions.
+ // length
+
+ { "length", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "length", TYPE_FLOAT, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "length", TYPE_FLOAT, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "length", TYPE_FLOAT, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ // distance
+
+ { "distance", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "distance", TYPE_FLOAT, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "distance", TYPE_FLOAT, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "distance", TYPE_FLOAT, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+
+ // dot
+
+ { "dot", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "dot", TYPE_FLOAT, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "dot", TYPE_FLOAT, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "dot", TYPE_FLOAT, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+
+ // cross
+
{ "cross", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+
+ // normalize
+
+ { "normalize", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "v" }, TAG_GLOBAL, false },
{ "normalize", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "v" }, TAG_GLOBAL, false },
{ "normalize", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "v" }, TAG_GLOBAL, false },
{ "normalize", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "v" }, TAG_GLOBAL, false },
+
+ // reflect
+
{ "reflect", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "I", "N" }, TAG_GLOBAL, false },
+
+ // refract
+
{ "refract", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "I", "N", "eta" }, TAG_GLOBAL, false },
+ // faceforward
+
{ "faceforward", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "N", "I", "Nref" }, TAG_GLOBAL, false },
{ "faceforward", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "N", "I", "Nref" }, TAG_GLOBAL, false },
{ "faceforward", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "N", "I", "Nref" }, TAG_GLOBAL, false },
+ // matrixCompMult
+
{ "matrixCompMult", TYPE_MAT2, { TYPE_MAT2, TYPE_MAT2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "matrixCompMult", TYPE_MAT3, { TYPE_MAT3, TYPE_MAT3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "matrixCompMult", TYPE_MAT4, { TYPE_MAT4, TYPE_MAT4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ // outerProduct
+
{ "outerProduct", TYPE_MAT2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "c", "r" }, TAG_GLOBAL, false },
{ "outerProduct", TYPE_MAT3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "c", "r" }, TAG_GLOBAL, false },
{ "outerProduct", TYPE_MAT4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "c", "r" }, TAG_GLOBAL, false },
+ // transpose
+
{ "transpose", TYPE_MAT2, { TYPE_MAT2, TYPE_VOID }, { "m" }, TAG_GLOBAL, false },
{ "transpose", TYPE_MAT3, { TYPE_MAT3, TYPE_VOID }, { "m" }, TAG_GLOBAL, false },
{ "transpose", TYPE_MAT4, { TYPE_MAT4, TYPE_VOID }, { "m" }, TAG_GLOBAL, false },
+ // determinant
+
{ "determinant", TYPE_FLOAT, { TYPE_MAT2, TYPE_VOID }, { "m" }, TAG_GLOBAL, false },
{ "determinant", TYPE_FLOAT, { TYPE_MAT3, TYPE_VOID }, { "m" }, TAG_GLOBAL, false },
{ "determinant", TYPE_FLOAT, { TYPE_MAT4, TYPE_VOID }, { "m" }, TAG_GLOBAL, false },
+ // inverse
+
{ "inverse", TYPE_MAT2, { TYPE_MAT2, TYPE_VOID }, { "m" }, TAG_GLOBAL, false },
{ "inverse", TYPE_MAT3, { TYPE_MAT3, TYPE_VOID }, { "m" }, TAG_GLOBAL, false },
{ "inverse", TYPE_MAT4, { TYPE_MAT4, TYPE_VOID }, { "m" }, TAG_GLOBAL, false },
+ // lessThan
+
{ "lessThan", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "lessThan", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "lessThan", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
@@ -2108,6 +2247,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "lessThan", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
{ "lessThan", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ // greaterThan
+
{ "greaterThan", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "greaterThan", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "greaterThan", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
@@ -2120,6 +2261,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "greaterThan", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
{ "greaterThan", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ // lessThanEqual
+
{ "lessThanEqual", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "lessThanEqual", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "lessThanEqual", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
@@ -2132,6 +2275,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "lessThanEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
{ "lessThanEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ // greaterThanEqual
+
{ "greaterThanEqual", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "greaterThanEqual", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "greaterThanEqual", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
@@ -2144,6 +2289,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "greaterThanEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
{ "greaterThanEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ // equal
+
{ "equal", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "equal", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "equal", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
@@ -2160,6 +2307,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "equal", TYPE_BVEC3, { TYPE_BVEC3, TYPE_BVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "equal", TYPE_BVEC4, { TYPE_BVEC4, TYPE_BVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ // notEqual
+
{ "notEqual", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "notEqual", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "notEqual", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
@@ -2176,19 +2325,27 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "notEqual", TYPE_BVEC3, { TYPE_BVEC3, TYPE_BVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "notEqual", TYPE_BVEC4, { TYPE_BVEC4, TYPE_BVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ // any
+
{ "any", TYPE_BOOL, { TYPE_BVEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "any", TYPE_BOOL, { TYPE_BVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "any", TYPE_BOOL, { TYPE_BVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ // all
+
{ "all", TYPE_BOOL, { TYPE_BVEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "all", TYPE_BOOL, { TYPE_BVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "all", TYPE_BOOL, { TYPE_BVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ // not
+
{ "not", TYPE_BVEC2, { TYPE_BVEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "not", TYPE_BVEC3, { TYPE_BVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
{ "not", TYPE_BVEC4, { TYPE_BVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
- //builtins - texture
+ // Built-ins: texture functions.
+ // textureSize
+
{ "textureSize", TYPE_IVEC2, { TYPE_SAMPLER2D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
{ "textureSize", TYPE_IVEC2, { TYPE_ISAMPLER2D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
{ "textureSize", TYPE_IVEC2, { TYPE_USAMPLER2D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
@@ -2201,6 +2358,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "textureSize", TYPE_IVEC2, { TYPE_SAMPLERCUBE, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
{ "textureSize", TYPE_IVEC2, { TYPE_SAMPLERCUBEARRAY, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
+ // texture
+
{ "texture", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
{ "texture", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
{ "texture", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
@@ -2224,6 +2383,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "texture", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
{ "texture", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
+ // textureProj
+
{ "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
{ "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
{ "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
@@ -2243,6 +2404,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "textureProj", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
{ "textureProj", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
+ // textureLod
+
{ "textureLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
{ "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
{ "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
@@ -2255,6 +2418,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "textureLod", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
{ "textureLod", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ // texelFetch
+
{ "texelFetch", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
{ "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
{ "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
@@ -2265,6 +2430,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
{ "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ // textureProjLod
+
{ "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
{ "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
{ "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
@@ -2275,6 +2442,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
{ "textureProjLod", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ // textureGrad
+
{ "textureGrad", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
{ "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
{ "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
@@ -2287,40 +2456,202 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "textureGrad", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
{ "textureGrad", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
+ // textureGather
+
+ { "textureGather", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureGather", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureGather", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureGather", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true },
+ { "textureGather", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true },
+ { "textureGather", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true },
+ { "textureGather", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureGather", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureGather", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureGather", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true },
+ { "textureGather", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true },
+ { "textureGather", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true },
+ { "textureGather", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureGather", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true },
+
+ // dFdx
+
{ "dFdx", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
{ "dFdx", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
{ "dFdx", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
{ "dFdx", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ // dFdy
+
{ "dFdy", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
{ "dFdy", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
{ "dFdy", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
{ "dFdy", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ // fwidth
+
{ "fwidth", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
{ "fwidth", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
{ "fwidth", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
{ "fwidth", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
- //sub-functions
+ // Sub-functions.
+ // array
- //array
{ "length", TYPE_INT, { TYPE_VOID }, { "" }, TAG_ARRAY, true },
- // modern functions
+ // Modern functions.
+ // fma
{ "fma", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "a", "b", "c" }, TAG_GLOBAL, false },
{ "fma", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b", "c" }, TAG_GLOBAL, false },
{ "fma", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b", "c" }, TAG_GLOBAL, false },
{ "fma", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b", "c" }, TAG_GLOBAL, false },
+ // Packing/Unpacking functions.
+
+ { "packHalf2x16", TYPE_UINT, { TYPE_VEC2, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
+ { "packUnorm2x16", TYPE_UINT, { TYPE_VEC2, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
+ { "packSnorm2x16", TYPE_UINT, { TYPE_VEC2, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
+ { "packUnorm4x8", TYPE_UINT, { TYPE_VEC4, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
+ { "packSnorm4x8", TYPE_UINT, { TYPE_VEC4, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
+
+ { "unpackHalf2x16", TYPE_VEC2, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
+ { "unpackUnorm2x16", TYPE_VEC2, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
+ { "unpackSnorm2x16", TYPE_VEC2, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
+ { "unpackUnorm4x8", TYPE_VEC4, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
+ { "unpackSnorm4x8", TYPE_VEC4, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
+
+ // bitfieldExtract
+
+ { "bitfieldExtract", TYPE_INT, { TYPE_INT, TYPE_INT, TYPE_INT, TYPE_VOID }, { "value", "offset", "bits" }, TAG_GLOBAL, true },
+ { "bitfieldExtract", TYPE_IVEC2, { TYPE_IVEC2, TYPE_INT, TYPE_INT, TYPE_VOID }, { "value", "offset", "bits" }, TAG_GLOBAL, true },
+ { "bitfieldExtract", TYPE_IVEC3, { TYPE_IVEC3, TYPE_INT, TYPE_INT, TYPE_VOID }, { "value", "offset", "bits" }, TAG_GLOBAL, true },
+ { "bitfieldExtract", TYPE_IVEC4, { TYPE_IVEC4, TYPE_INT, TYPE_INT, TYPE_VOID }, { "value", "offset", "bits" }, TAG_GLOBAL, true },
+
+ { "bitfieldExtract", TYPE_UINT, { TYPE_UINT, TYPE_INT, TYPE_INT, TYPE_VOID }, { "value", "offset", "bits" }, TAG_GLOBAL, true },
+ { "bitfieldExtract", TYPE_UVEC2, { TYPE_UVEC2, TYPE_INT, TYPE_INT, TYPE_VOID }, { "value", "offset", "bits" }, TAG_GLOBAL, true },
+ { "bitfieldExtract", TYPE_UVEC3, { TYPE_UVEC3, TYPE_INT, TYPE_INT, TYPE_VOID }, { "value", "offset", "bits" }, TAG_GLOBAL, true },
+ { "bitfieldExtract", TYPE_UVEC4, { TYPE_UVEC4, TYPE_INT, TYPE_INT, TYPE_VOID }, { "value", "offset", "bits" }, TAG_GLOBAL, true },
+
+ // bitfieldInsert
+
+ { "bitfieldInsert", TYPE_INT, { TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_VOID }, { "base", "insert", "offset", "bits" }, TAG_GLOBAL, true },
+ { "bitfieldInsert", TYPE_IVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_INT, TYPE_INT, TYPE_VOID }, { "base", "insert", "offset", "bits" }, TAG_GLOBAL, true },
+ { "bitfieldInsert", TYPE_IVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_INT, TYPE_INT, TYPE_VOID }, { "base", "insert", "offset", "bits" }, TAG_GLOBAL, true },
+ { "bitfieldInsert", TYPE_IVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_INT, TYPE_INT, TYPE_VOID }, { "base", "insert", "offset", "bits" }, TAG_GLOBAL, true },
+
+ { "bitfieldInsert", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_INT, TYPE_INT, TYPE_VOID }, { "base", "insert", "offset", "bits" }, TAG_GLOBAL, true },
+ { "bitfieldInsert", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_INT, TYPE_INT, TYPE_VOID }, { "base", "insert", "offset", "bits" }, TAG_GLOBAL, true },
+ { "bitfieldInsert", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_INT, TYPE_INT, TYPE_VOID }, { "base", "insert", "offset", "bits" }, TAG_GLOBAL, true },
+ { "bitfieldInsert", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_INT, TYPE_INT, TYPE_VOID }, { "base", "insert", "offset", "bits" }, TAG_GLOBAL, true },
+
+ // bitfieldReverse
+
+ { "bitfieldReverse", TYPE_INT, { TYPE_INT, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "bitfieldReverse", TYPE_IVEC2, { TYPE_IVEC2, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "bitfieldReverse", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "bitfieldReverse", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+
+ { "bitfieldReverse", TYPE_UINT, { TYPE_UINT, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "bitfieldReverse", TYPE_UVEC2, { TYPE_UVEC2, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "bitfieldReverse", TYPE_UVEC3, { TYPE_UVEC3, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "bitfieldReverse", TYPE_UVEC4, { TYPE_UVEC4, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+
+ // bitCount
+
+ { "bitCount", TYPE_INT, { TYPE_INT, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "bitCount", TYPE_IVEC2, { TYPE_IVEC2, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "bitCount", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "bitCount", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+
+ { "bitCount", TYPE_UINT, { TYPE_UINT, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "bitCount", TYPE_UVEC2, { TYPE_UVEC2, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "bitCount", TYPE_UVEC3, { TYPE_UVEC3, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "bitCount", TYPE_UVEC4, { TYPE_UVEC4, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+
+ // findLSB
+
+ { "findLSB", TYPE_INT, { TYPE_INT, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "findLSB", TYPE_IVEC2, { TYPE_IVEC2, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "findLSB", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "findLSB", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+
+ { "findLSB", TYPE_UINT, { TYPE_UINT, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "findLSB", TYPE_UVEC2, { TYPE_UVEC2, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "findLSB", TYPE_UVEC3, { TYPE_UVEC3, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "findLSB", TYPE_UVEC4, { TYPE_UVEC4, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+
+ // findMSB
+
+ { "findMSB", TYPE_INT, { TYPE_INT, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "findMSB", TYPE_IVEC2, { TYPE_IVEC2, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "findMSB", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "findMSB", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+
+ { "findMSB", TYPE_UINT, { TYPE_UINT, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "findMSB", TYPE_UVEC2, { TYPE_UVEC2, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "findMSB", TYPE_UVEC3, { TYPE_UVEC3, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "findMSB", TYPE_UVEC4, { TYPE_UVEC4, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+
+ // umulExtended
+
+ { "umulExtended", TYPE_VOID, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "y", "msb", "lsb" }, TAG_GLOBAL, true },
+ { "umulExtended", TYPE_VOID, { TYPE_UVEC2, TYPE_UVEC2, TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "x", "y", "msb", "lsb" }, TAG_GLOBAL, true },
+ { "umulExtended", TYPE_VOID, { TYPE_UVEC3, TYPE_UVEC3, TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "x", "y", "msb", "lsb" }, TAG_GLOBAL, true },
+ { "umulExtended", TYPE_VOID, { TYPE_UVEC4, TYPE_UVEC4, TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "x", "y", "msb", "lsb" }, TAG_GLOBAL, true },
+
+ // imulExtended
+
+ { "imulExtended", TYPE_VOID, { TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_VOID }, { "x", "y", "msb", "lsb" }, TAG_GLOBAL, true },
+ { "imulExtended", TYPE_VOID, { TYPE_IVEC2, TYPE_IVEC2, TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, { "x", "y", "msb", "lsb" }, TAG_GLOBAL, true },
+ { "imulExtended", TYPE_VOID, { TYPE_IVEC3, TYPE_IVEC3, TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, { "x", "y", "msb", "lsb" }, TAG_GLOBAL, true },
+ { "imulExtended", TYPE_VOID, { TYPE_IVEC4, TYPE_IVEC4, TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "x", "y", "msb", "lsb" }, TAG_GLOBAL, true },
+
+ // uaddCarry
+
+ { "uaddCarry", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "y", "carry" }, TAG_GLOBAL, true },
+ { "uaddCarry", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "x", "y", "carry" }, TAG_GLOBAL, true },
+ { "uaddCarry", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "x", "y", "carry" }, TAG_GLOBAL, true },
+ { "uaddCarry", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "x", "y", "carry" }, TAG_GLOBAL, true },
+
+ // usubBorrow
+
+ { "usubBorrow", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "y", "borrow" }, TAG_GLOBAL, true },
+ { "usubBorrow", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "x", "y", "borrow" }, TAG_GLOBAL, true },
+ { "usubBorrow", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "x", "y", "borrow" }, TAG_GLOBAL, true },
+ { "usubBorrow", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "x", "y", "borrow" }, TAG_GLOBAL, true },
+
+ // ldexp
+
+ { "ldexp", TYPE_FLOAT, { TYPE_FLOAT, TYPE_INT, TYPE_VOID }, { "x", "exp" }, TAG_GLOBAL, true },
+ { "ldexp", TYPE_VEC2, { TYPE_VEC2, TYPE_IVEC2, TYPE_VOID }, { "x", "exp" }, TAG_GLOBAL, true },
+ { "ldexp", TYPE_VEC3, { TYPE_VEC3, TYPE_IVEC3, TYPE_VOID }, { "x", "exp" }, TAG_GLOBAL, true },
+ { "ldexp", TYPE_VEC4, { TYPE_VEC4, TYPE_IVEC4, TYPE_VOID }, { "x", "exp" }, TAG_GLOBAL, true },
+
+ // frexp
+
+ { "frexp", TYPE_FLOAT, { TYPE_FLOAT, TYPE_INT, TYPE_VOID }, { "x", "exp" }, TAG_GLOBAL, true },
+ { "frexp", TYPE_VEC2, { TYPE_VEC2, TYPE_IVEC2, TYPE_VOID }, { "x", "exp" }, TAG_GLOBAL, true },
+ { "frexp", TYPE_VEC3, { TYPE_VEC3, TYPE_IVEC3, TYPE_VOID }, { "x", "exp" }, TAG_GLOBAL, true },
+ { "frexp", TYPE_VEC4, { TYPE_VEC4, TYPE_IVEC4, TYPE_VOID }, { "x", "exp" }, TAG_GLOBAL, true },
+
{ nullptr, TYPE_VOID, { TYPE_VOID }, { "" }, TAG_GLOBAL, false }
};
const ShaderLanguage::BuiltinFuncOutArgs ShaderLanguage::builtin_func_out_args[] = {
- //constructors
- { "modf", 1 },
- { nullptr, 0 }
+ { "modf", { 1, -1 } },
+ { "umulExtended", { 2, 3 } },
+ { "imulExtended", { 2, 3 } },
+ { "uaddCarry", { 2, -1 } },
+ { "usubBorrow", { 2, -1 } },
+ { "ldexp", { 1, -1 } },
+ { "frexp", { 1, -1 } },
+ { nullptr, { 0, -1 } }
+};
+
+const ShaderLanguage::BuiltinFuncConstArgs ShaderLanguage::builtin_func_const_args[] = {
+ { "textureGather", 2, 0, 3 },
+ { nullptr, 0, 0, 0 }
};
bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionInfo &p_function_info, OperatorNode *p_func, DataType *r_ret_type, StringName *r_ret_type_str) {
@@ -2384,6 +2715,13 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
failed_builtin = true;
bool fail = false;
for (int i = 0; i < argcount; i++) {
+ if (p_func->arguments[i + 1]->type == Node::TYPE_ARRAY) {
+ const ArrayNode *anode = static_cast<const ArrayNode *>(p_func->arguments[i + 1]);
+ if (anode->call_expression == nullptr && !anode->is_indexed()) {
+ fail = true;
+ break;
+ }
+ }
if (get_scalar_type(args[i]) == args[i] && p_func->arguments[i + 1]->type == Node::TYPE_CONSTANT && convert_constant(static_cast<ConstantNode *>(p_func->arguments[i + 1]), builtin_func_defs[idx].args[i])) {
//all good, but needs implicit conversion later
} else if (args[i] != builtin_func_defs[idx].args[i]) {
@@ -2407,100 +2745,152 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
}
if (!fail) {
- //make sure its not an out argument used in the wrong way
- int outarg_idx = 0;
- while (builtin_func_out_args[outarg_idx].name) {
- if (String(name) == builtin_func_out_args[outarg_idx].name) {
- int arg_idx = builtin_func_out_args[outarg_idx].argument;
-
- if (arg_idx < argcount) {
- if (p_func->arguments[arg_idx + 1]->type != Node::TYPE_VARIABLE && p_func->arguments[arg_idx + 1]->type != Node::TYPE_MEMBER && p_func->arguments[arg_idx + 1]->type != Node::TYPE_ARRAY) {
- _set_error("Argument " + itos(arg_idx + 1) + " of function '" + String(name) + "' is not a variable, array or member.");
- return false;
+ {
+ int constarg_idx = 0;
+ while (builtin_func_const_args[constarg_idx].name) {
+ if (String(name) == builtin_func_const_args[constarg_idx].name) {
+ int arg = builtin_func_const_args[constarg_idx].arg + 1;
+ if (p_func->arguments.size() <= arg) {
+ break;
}
- if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_ARRAY) {
- ArrayNode *mn = static_cast<ArrayNode *>(p_func->arguments[arg_idx + 1]);
- if (mn->is_const) {
- fail = true;
- }
- } else if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_MEMBER) {
- MemberNode *mn = static_cast<MemberNode *>(p_func->arguments[arg_idx + 1]);
- if (mn->basetype_const) {
- fail = true;
+ int min = builtin_func_const_args[constarg_idx].min;
+ int max = builtin_func_const_args[constarg_idx].max;
+
+ bool error = false;
+ if (p_func->arguments[arg]->type == Node::TYPE_VARIABLE) {
+ const VariableNode *vn = (VariableNode *)p_func->arguments[arg];
+
+ bool is_const = false;
+ ConstantNode::Value value;
+
+ _find_identifier(p_block, false, p_function_info, vn->name, nullptr, nullptr, &is_const, nullptr, nullptr, &value);
+ if (!is_const || value.sint < min || value.sint > max) {
+ error = true;
}
- } else { // TYPE_VARIABLE
- VariableNode *vn = static_cast<VariableNode *>(p_func->arguments[arg_idx + 1]);
- if (vn->is_const) {
- fail = true;
- } else {
- StringName varname = vn->name;
- if (shader->uniforms.has(varname)) {
- fail = true;
- } else {
- if (shader->varyings.has(varname)) {
- _set_error(vformat("Varyings cannot be passed for '%s' parameter!", "out"));
- return false;
- }
- if (p_function_info.built_ins.has(varname)) {
- BuiltInInfo info = p_function_info.built_ins[varname];
- if (info.constant) {
- fail = true;
- }
+ } else {
+ if (p_func->arguments[arg]->type == Node::TYPE_CONSTANT) {
+ ConstantNode *cn = (ConstantNode *)p_func->arguments[arg];
+
+ if (cn->get_datatype() == TYPE_INT && cn->values.size() == 1) {
+ int value = cn->values[0].sint;
+
+ if (value < min || value > max) {
+ error = true;
}
+ } else {
+ error = true;
}
+ } else {
+ error = true;
}
}
- if (fail) {
- _set_error(vformat("Constant value cannot be passed for '%s' parameter!", "out"));
+ if (error) {
+ _set_error(vformat("Expected integer constant within %s..%s range.", min, max));
return false;
}
+ }
+ constarg_idx++;
+ }
+ }
- StringName var_name;
- if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_ARRAY) {
- var_name = static_cast<const ArrayNode *>(p_func->arguments[arg_idx + 1])->name;
- } else if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_MEMBER) {
- Node *n = static_cast<const MemberNode *>(p_func->arguments[arg_idx + 1])->owner;
- while (n->type == Node::TYPE_MEMBER) {
- n = static_cast<const MemberNode *>(n)->owner;
- }
- if (n->type != Node::TYPE_VARIABLE && n->type != Node::TYPE_ARRAY) {
+ //make sure its not an out argument used in the wrong way
+ int outarg_idx = 0;
+ while (builtin_func_out_args[outarg_idx].name) {
+ if (String(name) == builtin_func_out_args[outarg_idx].name) {
+ for (int arg = 0; arg < BuiltinFuncOutArgs::MAX_ARGS; arg++) {
+ int arg_idx = builtin_func_out_args[outarg_idx].arguments[arg];
+ if (arg_idx == -1) {
+ break;
+ }
+ if (arg_idx < argcount) {
+ if (p_func->arguments[arg_idx + 1]->type != Node::TYPE_VARIABLE && p_func->arguments[arg_idx + 1]->type != Node::TYPE_MEMBER && p_func->arguments[arg_idx + 1]->type != Node::TYPE_ARRAY) {
_set_error("Argument " + itos(arg_idx + 1) + " of function '" + String(name) + "' is not a variable, array or member.");
return false;
}
- if (n->type == Node::TYPE_VARIABLE) {
- var_name = static_cast<const VariableNode *>(n)->name;
- } else { // TYPE_ARRAY
- var_name = static_cast<const ArrayNode *>(n)->name;
+
+ if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_ARRAY) {
+ ArrayNode *mn = static_cast<ArrayNode *>(p_func->arguments[arg_idx + 1]);
+ if (mn->is_const) {
+ fail = true;
+ }
+ } else if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_MEMBER) {
+ MemberNode *mn = static_cast<MemberNode *>(p_func->arguments[arg_idx + 1]);
+ if (mn->basetype_const) {
+ fail = true;
+ }
+ } else { // TYPE_VARIABLE
+ VariableNode *vn = static_cast<VariableNode *>(p_func->arguments[arg_idx + 1]);
+ if (vn->is_const) {
+ fail = true;
+ } else {
+ StringName varname = vn->name;
+ if (shader->uniforms.has(varname)) {
+ fail = true;
+ } else {
+ if (shader->varyings.has(varname)) {
+ _set_error(vformat("Varyings cannot be passed for '%s' parameter!", "out"));
+ return false;
+ }
+ if (p_function_info.built_ins.has(varname)) {
+ BuiltInInfo info = p_function_info.built_ins[varname];
+ if (info.constant) {
+ fail = true;
+ }
+ }
+ }
+ }
}
- } else { // TYPE_VARIABLE
- var_name = static_cast<const VariableNode *>(p_func->arguments[arg_idx + 1])->name;
- }
- const BlockNode *b = p_block;
- bool valid = false;
- while (b) {
- if (b->variables.has(var_name) || p_function_info.built_ins.has(var_name)) {
- valid = true;
- break;
+ if (fail) {
+ _set_error(vformat("Constant value cannot be passed for '%s' parameter!", "out"));
+ return false;
}
- if (b->parent_function) {
- for (int i = 0; i < b->parent_function->arguments.size(); i++) {
- if (b->parent_function->arguments[i].name == var_name) {
- valid = true;
- break;
+
+ StringName var_name;
+ if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_ARRAY) {
+ var_name = static_cast<const ArrayNode *>(p_func->arguments[arg_idx + 1])->name;
+ } else if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_MEMBER) {
+ Node *n = static_cast<const MemberNode *>(p_func->arguments[arg_idx + 1])->owner;
+ while (n->type == Node::TYPE_MEMBER) {
+ n = static_cast<const MemberNode *>(n)->owner;
+ }
+ if (n->type != Node::TYPE_VARIABLE && n->type != Node::TYPE_ARRAY) {
+ _set_error("Argument " + itos(arg_idx + 1) + " of function '" + String(name) + "' is not a variable, array or member.");
+ return false;
+ }
+ if (n->type == Node::TYPE_VARIABLE) {
+ var_name = static_cast<const VariableNode *>(n)->name;
+ } else { // TYPE_ARRAY
+ var_name = static_cast<const ArrayNode *>(n)->name;
+ }
+ } else { // TYPE_VARIABLE
+ var_name = static_cast<const VariableNode *>(p_func->arguments[arg_idx + 1])->name;
+ }
+ const BlockNode *b = p_block;
+ bool valid = false;
+ while (b) {
+ if (b->variables.has(var_name) || p_function_info.built_ins.has(var_name)) {
+ valid = true;
+ break;
+ }
+ if (b->parent_function) {
+ for (int i = 0; i < b->parent_function->arguments.size(); i++) {
+ if (b->parent_function->arguments[i].name == var_name) {
+ valid = true;
+ break;
+ }
}
}
+ b = b->parent_block;
}
- b = b->parent_block;
- }
- if (!valid) {
- _set_error("Argument " + itos(arg_idx + 1) + " of function '" + String(name) + "' can only take a local variable, array or member.");
- return false;
+ if (!valid) {
+ _set_error("Argument " + itos(arg_idx + 1) + " of function '" + String(name) + "' can only take a local variable, array or member.");
+ return false;
+ }
}
}
}
-
outarg_idx++;
}
//implicitly convert values if possible
@@ -2560,6 +2950,11 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
} else {
arg_name = get_datatype_name(args[i]);
}
+ if (args3[i] > 0) {
+ arg_name += "[";
+ arg_name += itos(args3[i]);
+ arg_name += "]";
+ }
err += arg_name;
}
err += ")";
@@ -2912,86 +3307,294 @@ bool ShaderLanguage::is_sampler_type(DataType p_type) {
p_type == TYPE_SAMPLERCUBEARRAY;
}
-Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::ConstantNode::Value> &p_value, DataType p_type, ShaderLanguage::ShaderNode::Uniform::Hint p_hint) {
+Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::ConstantNode::Value> &p_value, DataType p_type, int p_array_size, ShaderLanguage::ShaderNode::Uniform::Hint p_hint) {
+ int array_size = p_array_size;
+
if (p_value.size() > 0) {
Variant value;
switch (p_type) {
case ShaderLanguage::TYPE_BOOL:
- value = Variant(p_value[0].boolean);
+ if (array_size > 0) {
+ PackedInt32Array array = PackedInt32Array();
+ for (int i = 0; i < array_size; i++) {
+ array.push_back(p_value[i].boolean);
+ }
+ value = Variant(array);
+ } else {
+ value = Variant(p_value[0].boolean);
+ }
break;
case ShaderLanguage::TYPE_BVEC2:
+ array_size *= 2;
+
+ if (array_size > 0) {
+ PackedInt32Array array = PackedInt32Array();
+ for (int i = 0; i < array_size; i++) {
+ array.push_back(p_value[i].boolean);
+ }
+ value = Variant(array);
+ } else {
+ value = Variant(p_value[0].boolean);
+ }
+ break;
case ShaderLanguage::TYPE_BVEC3:
+ array_size *= 3;
+
+ if (array_size > 0) {
+ PackedInt32Array array = PackedInt32Array();
+ for (int i = 0; i < array_size; i++) {
+ array.push_back(p_value[i].boolean);
+ }
+ value = Variant(array);
+ } else {
+ value = Variant(p_value[0].boolean);
+ }
+ break;
case ShaderLanguage::TYPE_BVEC4:
+ array_size *= 4;
+
+ if (array_size > 0) {
+ PackedInt32Array array = PackedInt32Array();
+ for (int i = 0; i < array_size; i++) {
+ array.push_back(p_value[i].boolean);
+ }
+ value = Variant(array);
+ } else {
+ value = Variant(p_value[0].boolean);
+ }
+ break;
case ShaderLanguage::TYPE_INT:
- value = Variant(p_value[0].sint);
+ if (array_size > 0) {
+ PackedInt32Array array = PackedInt32Array();
+ for (int i = 0; i < array_size; i++) {
+ array.push_back(p_value[i].sint);
+ }
+ value = Variant(array);
+ } else {
+ value = Variant(p_value[0].sint);
+ }
break;
case ShaderLanguage::TYPE_IVEC2:
- value = Variant(Vector2(p_value[0].sint, p_value[1].sint));
+ if (array_size > 0) {
+ array_size *= 2;
+
+ PackedInt32Array array = PackedInt32Array();
+ for (int i = 0; i < array_size; i++) {
+ array.push_back(p_value[i].sint);
+ }
+ value = Variant(array);
+ } else {
+ value = Variant(Vector2(p_value[0].sint, p_value[1].sint));
+ }
break;
case ShaderLanguage::TYPE_IVEC3:
- value = Variant(Vector3(p_value[0].sint, p_value[1].sint, p_value[2].sint));
+ if (array_size > 0) {
+ array_size *= 3;
+
+ PackedInt32Array array = PackedInt32Array();
+ for (int i = 0; i < array_size; i++) {
+ array.push_back(p_value[i].sint);
+ }
+ value = Variant(array);
+ } else {
+ value = Variant(Vector3(p_value[0].sint, p_value[1].sint, p_value[2].sint));
+ }
break;
case ShaderLanguage::TYPE_IVEC4:
- value = Variant(Plane(p_value[0].sint, p_value[1].sint, p_value[2].sint, p_value[3].sint));
+ if (array_size > 0) {
+ array_size *= 4;
+
+ PackedInt32Array array = PackedInt32Array();
+ for (int i = 0; i < array_size; i++) {
+ array.push_back(p_value[i].sint);
+ }
+ value = Variant(array);
+ } else {
+ value = Variant(Plane(p_value[0].sint, p_value[1].sint, p_value[2].sint, p_value[3].sint));
+ }
break;
case ShaderLanguage::TYPE_UINT:
- value = Variant(p_value[0].uint);
+ if (array_size > 0) {
+ PackedInt32Array array = PackedInt32Array();
+ for (int i = 0; i < array_size; i++) {
+ array.push_back(p_value[i].uint);
+ }
+ value = Variant(array);
+ } else {
+ value = Variant(p_value[0].uint);
+ }
break;
case ShaderLanguage::TYPE_UVEC2:
- value = Variant(Vector2(p_value[0].uint, p_value[1].uint));
+ if (array_size > 0) {
+ array_size *= 2;
+
+ PackedInt32Array array = PackedInt32Array();
+ for (int i = 0; i < array_size; i++) {
+ array.push_back(p_value[i].uint);
+ }
+ value = Variant(array);
+ } else {
+ value = Variant(Vector2(p_value[0].uint, p_value[1].uint));
+ }
break;
case ShaderLanguage::TYPE_UVEC3:
- value = Variant(Vector3(p_value[0].uint, p_value[1].uint, p_value[2].uint));
+ if (array_size > 0) {
+ array_size *= 3;
+
+ PackedInt32Array array = PackedInt32Array();
+ for (int i = 0; i < array_size; i++) {
+ array.push_back(p_value[i].uint);
+ }
+ value = Variant(array);
+ } else {
+ value = Variant(Vector3(p_value[0].uint, p_value[1].uint, p_value[2].uint));
+ }
break;
case ShaderLanguage::TYPE_UVEC4:
- value = Variant(Plane(p_value[0].uint, p_value[1].uint, p_value[2].uint, p_value[3].uint));
+ if (array_size > 0) {
+ array_size *= 4;
+
+ PackedInt32Array array = PackedInt32Array();
+ for (int i = 0; i < array_size; i++) {
+ array.push_back(p_value[i].uint);
+ }
+ value = Variant(array);
+ } else {
+ value = Variant(Plane(p_value[0].uint, p_value[1].uint, p_value[2].uint, p_value[3].uint));
+ }
break;
case ShaderLanguage::TYPE_FLOAT:
- value = Variant(p_value[0].real);
+ if (array_size > 0) {
+ PackedFloat32Array array = PackedFloat32Array();
+ for (int i = 0; i < array_size; i++) {
+ array.push_back(p_value[i].real);
+ }
+ value = Variant(array);
+ } else {
+ value = Variant(p_value[0].real);
+ }
break;
case ShaderLanguage::TYPE_VEC2:
- value = Variant(Vector2(p_value[0].real, p_value[1].real));
+ if (array_size > 0) {
+ array_size *= 2;
+
+ PackedVector2Array array = PackedVector2Array();
+ for (int i = 0; i < array_size; i += 2) {
+ array.push_back(Vector2(p_value[i].real, p_value[i + 1].real));
+ }
+ value = Variant(array);
+ } else {
+ value = Variant(Vector2(p_value[0].real, p_value[1].real));
+ }
break;
case ShaderLanguage::TYPE_VEC3:
- value = Variant(Vector3(p_value[0].real, p_value[1].real, p_value[2].real));
+ if (array_size > 0) {
+ array_size *= 3;
+
+ PackedVector3Array array = PackedVector3Array();
+ for (int i = 0; i < array_size; i += 3) {
+ array.push_back(Vector3(p_value[i].real, p_value[i + 1].real, p_value[i + 2].real));
+ }
+ value = Variant(array);
+ } else {
+ value = Variant(Vector3(p_value[0].real, p_value[1].real, p_value[2].real));
+ }
break;
case ShaderLanguage::TYPE_VEC4:
- if (p_hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) {
- value = Variant(Color(p_value[0].real, p_value[1].real, p_value[2].real, p_value[3].real));
+ if (array_size > 0) {
+ array_size *= 4;
+
+ if (p_hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) {
+ PackedColorArray array = PackedColorArray();
+ for (int i = 0; i < array_size; i += 4) {
+ array.push_back(Color(p_value[i].real, p_value[i + 1].real, p_value[i + 2].real, p_value[i + 3].real));
+ }
+ value = Variant(array);
+ } else {
+ PackedFloat32Array array = PackedFloat32Array();
+ for (int i = 0; i < array_size; i += 4) {
+ array.push_back(p_value[i].real);
+ array.push_back(p_value[i + 1].real);
+ array.push_back(p_value[i + 2].real);
+ array.push_back(p_value[i + 3].real);
+ }
+ value = Variant(array);
+ }
} else {
- value = Variant(Plane(p_value[0].real, p_value[1].real, p_value[2].real, p_value[3].real));
+ if (p_hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) {
+ value = Variant(Color(p_value[0].real, p_value[1].real, p_value[2].real, p_value[3].real));
+ } else {
+ value = Variant(Plane(p_value[0].real, p_value[1].real, p_value[2].real, p_value[3].real));
+ }
}
break;
case ShaderLanguage::TYPE_MAT2:
- value = Variant(Transform2D(p_value[0].real, p_value[2].real, p_value[1].real, p_value[3].real, 0.0, 0.0));
+ if (array_size > 0) {
+ array_size *= 4;
+
+ PackedFloat32Array array = PackedFloat32Array();
+ for (int i = 0; i < array_size; i += 4) {
+ array.push_back(p_value[i].real);
+ array.push_back(p_value[i + 1].real);
+ array.push_back(p_value[i + 2].real);
+ array.push_back(p_value[i + 3].real);
+ }
+ value = Variant(array);
+ } else {
+ value = Variant(Transform2D(p_value[0].real, p_value[2].real, p_value[1].real, p_value[3].real, 0.0, 0.0));
+ }
break;
case ShaderLanguage::TYPE_MAT3: {
- Basis p;
- p[0][0] = p_value[0].real;
- p[0][1] = p_value[1].real;
- p[0][2] = p_value[2].real;
- p[1][0] = p_value[3].real;
- p[1][1] = p_value[4].real;
- p[1][2] = p_value[5].real;
- p[2][0] = p_value[6].real;
- p[2][1] = p_value[7].real;
- p[2][2] = p_value[8].real;
- value = Variant(p);
+ if (array_size > 0) {
+ array_size *= 9;
+
+ PackedFloat32Array array = PackedFloat32Array();
+ for (int i = 0; i < array_size; i += 9) {
+ for (int j = 0; j < 9; j++) {
+ array.push_back(p_value[i + j].real);
+ }
+ }
+ value = Variant(array);
+ } else {
+ Basis p;
+ p[0][0] = p_value[0].real;
+ p[0][1] = p_value[1].real;
+ p[0][2] = p_value[2].real;
+ p[1][0] = p_value[3].real;
+ p[1][1] = p_value[4].real;
+ p[1][2] = p_value[5].real;
+ p[2][0] = p_value[6].real;
+ p[2][1] = p_value[7].real;
+ p[2][2] = p_value[8].real;
+ value = Variant(p);
+ }
break;
}
case ShaderLanguage::TYPE_MAT4: {
- Basis p;
- p[0][0] = p_value[0].real;
- p[0][1] = p_value[1].real;
- p[0][2] = p_value[2].real;
- p[1][0] = p_value[4].real;
- p[1][1] = p_value[5].real;
- p[1][2] = p_value[6].real;
- p[2][0] = p_value[8].real;
- p[2][1] = p_value[9].real;
- p[2][2] = p_value[10].real;
- Transform3D t = Transform3D(p, Vector3(p_value[3].real, p_value[7].real, p_value[11].real));
- value = Variant(t);
+ if (array_size > 0) {
+ array_size *= 16;
+
+ PackedFloat32Array array = PackedFloat32Array();
+ for (int i = 0; i < array_size; i += 16) {
+ for (int j = 0; j < 16; j++) {
+ array.push_back(p_value[i + j].real);
+ }
+ }
+ value = Variant(array);
+ } else {
+ Basis p;
+ p[0][0] = p_value[0].real;
+ p[0][1] = p_value[1].real;
+ p[0][2] = p_value[2].real;
+ p[1][0] = p_value[4].real;
+ p[1][1] = p_value[5].real;
+ p[1][2] = p_value[6].real;
+ p[2][0] = p_value[8].real;
+ p[2][1] = p_value[9].real;
+ p[2][2] = p_value[10].real;
+ Transform3D t = Transform3D(p, Vector3(p_value[3].real, p_value[7].real, p_value[11].real));
+ value = Variant(t);
+ }
break;
}
case ShaderLanguage::TYPE_ISAMPLER2DARRAY:
@@ -3027,31 +3630,50 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform
pi.type = Variant::NIL;
break;
case ShaderLanguage::TYPE_BOOL:
- pi.type = Variant::BOOL;
+ if (p_uniform.array_size > 0) {
+ pi.type = Variant::PACKED_INT32_ARRAY;
+ } else {
+ pi.type = Variant::BOOL;
+ }
break;
case ShaderLanguage::TYPE_BVEC2:
- pi.type = Variant::INT;
- pi.hint = PROPERTY_HINT_FLAGS;
- pi.hint_string = "x,y";
+ if (p_uniform.array_size > 0) {
+ pi.type = Variant::PACKED_INT32_ARRAY;
+ } else {
+ pi.type = Variant::INT;
+ pi.hint = PROPERTY_HINT_FLAGS;
+ pi.hint_string = "x,y";
+ }
break;
case ShaderLanguage::TYPE_BVEC3:
- pi.type = Variant::INT;
- pi.hint = PROPERTY_HINT_FLAGS;
- pi.hint_string = "x,y,z";
+ if (p_uniform.array_size > 0) {
+ pi.type = Variant::PACKED_INT32_ARRAY;
+ } else {
+ pi.type = Variant::INT;
+ pi.hint = PROPERTY_HINT_FLAGS;
+ pi.hint_string = "x,y,z";
+ }
break;
case ShaderLanguage::TYPE_BVEC4:
- pi.type = Variant::INT;
- pi.hint = PROPERTY_HINT_FLAGS;
- pi.hint_string = "x,y,z,w";
+ if (p_uniform.array_size > 0) {
+ pi.type = Variant::PACKED_INT32_ARRAY;
+ } else {
+ pi.type = Variant::INT;
+ pi.hint = PROPERTY_HINT_FLAGS;
+ pi.hint_string = "x,y,z,w";
+ }
break;
case ShaderLanguage::TYPE_UINT:
case ShaderLanguage::TYPE_INT: {
- pi.type = Variant::INT;
- if (p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_RANGE) {
- pi.hint = PROPERTY_HINT_RANGE;
- pi.hint_string = rtos(p_uniform.hint_range[0]) + "," + rtos(p_uniform.hint_range[1]) + "," + rtos(p_uniform.hint_range[2]);
+ if (p_uniform.array_size > 0) {
+ pi.type = Variant::PACKED_INT32_ARRAY;
+ } else {
+ pi.type = Variant::INT;
+ if (p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_RANGE) {
+ pi.hint = PROPERTY_HINT_RANGE;
+ pi.hint_string = rtos(p_uniform.hint_range[0]) + "," + rtos(p_uniform.hint_range[1]) + "," + rtos(p_uniform.hint_range[2]);
+ }
}
-
} break;
case ShaderLanguage::TYPE_IVEC2:
case ShaderLanguage::TYPE_IVEC3:
@@ -3062,59 +3684,106 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform
pi.type = Variant::PACKED_INT32_ARRAY;
} break;
case ShaderLanguage::TYPE_FLOAT: {
- pi.type = Variant::FLOAT;
- if (p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_RANGE) {
- pi.hint = PROPERTY_HINT_RANGE;
- pi.hint_string = rtos(p_uniform.hint_range[0]) + "," + rtos(p_uniform.hint_range[1]) + "," + rtos(p_uniform.hint_range[2]);
+ if (p_uniform.array_size > 0) {
+ pi.type = Variant::PACKED_FLOAT32_ARRAY;
+ } else {
+ pi.type = Variant::FLOAT;
+ if (p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_RANGE) {
+ pi.hint = PROPERTY_HINT_RANGE;
+ pi.hint_string = rtos(p_uniform.hint_range[0]) + "," + rtos(p_uniform.hint_range[1]) + "," + rtos(p_uniform.hint_range[2]);
+ }
}
-
} break;
case ShaderLanguage::TYPE_VEC2:
- pi.type = Variant::VECTOR2;
+ if (p_uniform.array_size > 0) {
+ pi.type = Variant::PACKED_VECTOR2_ARRAY;
+ } else {
+ pi.type = Variant::VECTOR2;
+ }
break;
case ShaderLanguage::TYPE_VEC3:
- pi.type = Variant::VECTOR3;
+ if (p_uniform.array_size > 0) {
+ pi.type = Variant::PACKED_VECTOR3_ARRAY;
+ } else {
+ pi.type = Variant::VECTOR3;
+ }
break;
case ShaderLanguage::TYPE_VEC4: {
- if (p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) {
- pi.type = Variant::COLOR;
+ if (p_uniform.array_size > 0) {
+ if (p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) {
+ pi.type = Variant::PACKED_COLOR_ARRAY;
+ } else {
+ pi.type = Variant::PACKED_FLOAT32_ARRAY;
+ }
} else {
- pi.type = Variant::PLANE;
+ if (p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) {
+ pi.type = Variant::COLOR;
+ } else {
+ pi.type = Variant::PLANE;
+ }
}
} break;
case ShaderLanguage::TYPE_MAT2:
- pi.type = Variant::TRANSFORM2D;
+ if (p_uniform.array_size > 0) {
+ pi.type = Variant::PACKED_FLOAT32_ARRAY;
+ } else {
+ pi.type = Variant::TRANSFORM2D;
+ }
break;
case ShaderLanguage::TYPE_MAT3:
- pi.type = Variant::BASIS;
+ if (p_uniform.array_size > 0) {
+ pi.type = Variant::PACKED_FLOAT32_ARRAY;
+ } else {
+ pi.type = Variant::BASIS;
+ }
break;
case ShaderLanguage::TYPE_MAT4:
- pi.type = Variant::TRANSFORM3D;
+ if (p_uniform.array_size > 0) {
+ pi.type = Variant::PACKED_FLOAT32_ARRAY;
+ } else {
+ pi.type = Variant::TRANSFORM3D;
+ }
break;
case ShaderLanguage::TYPE_SAMPLER2D:
case ShaderLanguage::TYPE_ISAMPLER2D:
case ShaderLanguage::TYPE_USAMPLER2D: {
- pi.type = Variant::OBJECT;
+ if (p_uniform.array_size > 0) {
+ pi.type = Variant::ARRAY;
+ } else {
+ pi.type = Variant::OBJECT;
+ }
pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
pi.hint_string = "Texture2D";
} break;
case ShaderLanguage::TYPE_SAMPLER2DARRAY:
case ShaderLanguage::TYPE_ISAMPLER2DARRAY:
case ShaderLanguage::TYPE_USAMPLER2DARRAY: {
- pi.type = Variant::OBJECT;
+ if (p_uniform.array_size > 0) {
+ pi.type = Variant::ARRAY;
+ } else {
+ pi.type = Variant::OBJECT;
+ }
pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
pi.hint_string = "TextureLayered";
} break;
case ShaderLanguage::TYPE_SAMPLER3D:
case ShaderLanguage::TYPE_ISAMPLER3D:
case ShaderLanguage::TYPE_USAMPLER3D: {
- pi.type = Variant::OBJECT;
+ if (p_uniform.array_size > 0) {
+ pi.type = Variant::ARRAY;
+ } else {
+ pi.type = Variant::OBJECT;
+ }
pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
pi.hint_string = "Texture3D";
} break;
case ShaderLanguage::TYPE_SAMPLERCUBE:
case ShaderLanguage::TYPE_SAMPLERCUBEARRAY: {
- pi.type = Variant::OBJECT;
+ if (p_uniform.array_size > 0) {
+ pi.type = Variant::ARRAY;
+ } else {
+ pi.type = Variant::OBJECT;
+ }
pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
pi.hint_string = "TextureLayered";
} break;
@@ -3537,9 +4206,9 @@ bool ShaderLanguage::_propagate_function_call_sampler_uniform_settings(StringNam
arg->tex_argument_check = true;
arg->tex_argument_filter = p_filter;
arg->tex_argument_repeat = p_repeat;
- for (Map<StringName, Set<int>>::Element *E = arg->tex_argument_connect.front(); E; E = E->next()) {
- for (Set<int>::Element *F = E->get().front(); F; F = F->next()) {
- if (!_propagate_function_call_sampler_uniform_settings(E->key(), F->get(), p_filter, p_repeat)) {
+ for (KeyValue<StringName, Set<int>> &E : arg->tex_argument_connect) {
+ for (Set<int>::Element *F = E.value.front(); F; F = F->next()) {
+ if (!_propagate_function_call_sampler_uniform_settings(E.key, F->get(), p_filter, p_repeat)) {
return false;
}
}
@@ -3571,9 +4240,9 @@ bool ShaderLanguage::_propagate_function_call_sampler_builtin_reference(StringNa
arg->tex_builtin_check = true;
arg->tex_builtin = p_builtin;
- for (Map<StringName, Set<int>>::Element *E = arg->tex_argument_connect.front(); E; E = E->next()) {
- for (Set<int>::Element *F = E->get().front(); F; F = F->next()) {
- if (!_propagate_function_call_sampler_builtin_reference(E->key(), F->get(), p_builtin)) {
+ for (KeyValue<StringName, Set<int>> &E : arg->tex_argument_connect) {
+ for (Set<int>::Element *F = E.value.front(); F; F = F->next()) {
+ if (!_propagate_function_call_sampler_builtin_reference(E.key, F->get(), p_builtin)) {
return false;
}
}
@@ -3585,6 +4254,116 @@ bool ShaderLanguage::_propagate_function_call_sampler_builtin_reference(StringNa
ERR_FAIL_V(false); //bug? function not found
}
+ShaderLanguage::Node *ShaderLanguage::_parse_array_size(BlockNode *p_block, const FunctionInfo &p_function_info, int &r_array_size) {
+ int array_size = 0;
+
+ Node *n = _parse_and_reduce_expression(p_block, p_function_info);
+ if (n) {
+ if (n->type == Node::TYPE_VARIABLE) {
+ VariableNode *vn = static_cast<VariableNode *>(n);
+ if (vn) {
+ ConstantNode::Value v;
+ DataType data_type;
+ bool is_const = false;
+
+ _find_identifier(p_block, false, p_function_info, vn->name, &data_type, nullptr, &is_const, nullptr, nullptr, &v);
+
+ if (is_const) {
+ if (data_type == TYPE_INT) {
+ int32_t value = v.sint;
+ if (value > 0) {
+ array_size = value;
+ }
+ } else if (data_type == TYPE_UINT) {
+ uint32_t value = v.uint;
+ if (value > 0U) {
+ array_size = value;
+ }
+ }
+ }
+ }
+ } else if (n->type == Node::TYPE_OPERATOR) {
+ _set_error("Array size expressions are not yet implemented.");
+ return nullptr;
+ }
+ }
+
+ r_array_size = array_size;
+ return n;
+}
+
+Error ShaderLanguage::_parse_global_array_size(int &r_array_size) {
+ if (r_array_size > 0) {
+ _set_error("Array size is already defined!");
+ return ERR_PARSE_ERROR;
+ }
+ TkPos pos = _get_tkpos();
+ Token tk = _get_token();
+
+ int array_size = 0;
+
+ if (tk.type != TK_INT_CONSTANT || ((int)tk.constant) <= 0) {
+ _set_tkpos(pos);
+ Node *n = _parse_array_size(nullptr, FunctionInfo(), array_size);
+ if (!n) {
+ return ERR_PARSE_ERROR;
+ }
+ } else if (((int)tk.constant) > 0) {
+ array_size = (uint32_t)tk.constant;
+ }
+
+ if (array_size <= 0) {
+ _set_error("Expected single integer constant > 0");
+ return ERR_PARSE_ERROR;
+ }
+
+ tk = _get_token();
+ if (tk.type != TK_BRACKET_CLOSE) {
+ _set_error("Expected ']'");
+ return ERR_PARSE_ERROR;
+ }
+
+ r_array_size = array_size;
+ return OK;
+}
+
+Error ShaderLanguage::_parse_local_array_size(BlockNode *p_block, const FunctionInfo &p_function_info, ArrayDeclarationNode *p_node, ArrayDeclarationNode::Declaration *p_decl, int &r_array_size, bool &r_is_unknown_size) {
+ TkPos pos = _get_tkpos();
+ Token tk = _get_token();
+
+ if (tk.type == TK_BRACKET_CLOSE) {
+ r_is_unknown_size = true;
+ } else {
+ if (tk.type != TK_INT_CONSTANT || ((int)tk.constant) <= 0) {
+ _set_tkpos(pos);
+ int array_size = 0;
+ Node *n = _parse_array_size(p_block, p_function_info, array_size);
+ if (!n) {
+ return ERR_PARSE_ERROR;
+ }
+ p_decl->size = array_size;
+ p_node->size_expression = n;
+ } else if (((int)tk.constant) > 0) {
+ p_decl->size = (uint32_t)tk.constant;
+ }
+
+ if (p_decl->size <= 0) {
+ _set_error("Expected single integer constant > 0");
+ return ERR_PARSE_ERROR;
+ }
+
+ tk = _get_token();
+ if (tk.type != TK_BRACKET_CLOSE) {
+ _set_error("Expected ']'");
+ return ERR_PARSE_ERROR;
+ }
+
+ r_array_size = p_decl->size;
+ }
+
+ return OK;
+}
+
ShaderLanguage::Node *ShaderLanguage::_parse_array_constructor(BlockNode *p_block, const FunctionInfo &p_function_info) {
DataType type = TYPE_VOID;
String struct_name = "";
@@ -3721,9 +4500,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_array_constructor(BlockNode *p_bloc
if (!is_token_variable_datatype(tk.type)) {
_set_tkpos(prev_pos);
- pass_array = true;
Node *n = _parse_and_reduce_expression(p_block, p_function_info);
- pass_array = false;
if (!n) {
_set_error("Invalid data type for array");
@@ -3813,7 +4590,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_array_constructor(BlockNode *p_bloc
return nullptr;
}
- if (!_compare_datatypes(p_type, p_struct_name, 0, n->get_datatype(), n->get_datatype_name(), 0)) {
+ if (!_compare_datatypes(p_type, p_struct_name, 0, n->get_datatype(), n->get_datatype_name(), n->get_array_size())) {
return nullptr;
}
@@ -4061,9 +4838,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
int carg = -1;
- pass_array = true;
bool ok = _parse_function_arguments(p_block, p_function_info, func, &carg);
- pass_array = false;
// Check if block has a variable with the same name as function to prevent shader crash.
ShaderLanguage::BlockNode *bnode = p_block;
@@ -4315,62 +5090,58 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
Node *assign_expression = nullptr;
if (array_size > 0) {
- if (!pass_array) {
- tk = _get_token();
+ prepos = _get_tkpos();
+ tk = _get_token();
- if (tk.type != TK_BRACKET_OPEN && tk.type != TK_PERIOD && tk.type != TK_OP_ASSIGN) {
- _set_error("Expected '[','.' or '='");
+ if (tk.type == TK_OP_ASSIGN) {
+ if (is_const) {
+ _set_error("Constants cannot be modified.");
+ return nullptr;
+ }
+ assign_expression = _parse_array_constructor(p_block, p_function_info, data_type, struct_name, array_size);
+ if (!assign_expression) {
+ return nullptr;
+ }
+ } else if (tk.type == TK_PERIOD) {
+ completion_class = TAG_ARRAY;
+ p_block->block_tag = SubClassTag::TAG_ARRAY;
+ call_expression = _parse_and_reduce_expression(p_block, p_function_info);
+ p_block->block_tag = SubClassTag::TAG_GLOBAL;
+ if (!call_expression) {
+ return nullptr;
+ }
+ data_type = call_expression->get_datatype();
+ } else if (tk.type == TK_BRACKET_OPEN) { // indexing
+ index_expression = _parse_and_reduce_expression(p_block, p_function_info);
+ if (!index_expression) {
return nullptr;
}
- if (tk.type == TK_OP_ASSIGN) {
- if (is_const) {
- _set_error("Constants cannot be modified.");
- return nullptr;
- }
- assign_expression = _parse_array_constructor(p_block, p_function_info, data_type, struct_name, array_size);
- if (!assign_expression) {
- return nullptr;
- }
- } else if (tk.type == TK_PERIOD) {
- completion_class = TAG_ARRAY;
- p_block->block_tag = SubClassTag::TAG_ARRAY;
- call_expression = _parse_and_reduce_expression(p_block, p_function_info);
- p_block->block_tag = SubClassTag::TAG_GLOBAL;
- if (!call_expression) {
- return nullptr;
- }
- data_type = call_expression->get_datatype();
- } else { // indexing
- index_expression = _parse_and_reduce_expression(p_block, p_function_info);
- if (!index_expression) {
- return nullptr;
- }
-
- if (index_expression->get_datatype() != TYPE_INT && index_expression->get_datatype() != TYPE_UINT) {
- _set_error("Only integer expressions are allowed for indexing");
- return nullptr;
- }
+ if (index_expression->get_array_size() != 0 || (index_expression->get_datatype() != TYPE_INT && index_expression->get_datatype() != TYPE_UINT)) {
+ _set_error("Only integer expressions are allowed for indexing.");
+ return nullptr;
+ }
- if (index_expression->type == Node::TYPE_CONSTANT) {
- ConstantNode *cnode = (ConstantNode *)index_expression;
- if (cnode) {
- if (!cnode->values.is_empty()) {
- int value = cnode->values[0].sint;
- if (value < 0 || value >= array_size) {
- _set_error(vformat("Index [%s] out of range [%s..%s]", value, 0, array_size - 1));
- return nullptr;
- }
+ if (index_expression->type == Node::TYPE_CONSTANT) {
+ ConstantNode *cnode = (ConstantNode *)index_expression;
+ if (cnode) {
+ if (!cnode->values.is_empty()) {
+ int value = cnode->values[0].sint;
+ if (value < 0 || value >= array_size) {
+ _set_error(vformat("Index [%s] out of range [%s..%s]", value, 0, array_size - 1));
+ return nullptr;
}
}
}
+ }
- tk = _get_token();
- if (tk.type != TK_BRACKET_CLOSE) {
- _set_error("Expected ']'");
- return nullptr;
- }
+ tk = _get_token();
+ if (tk.type != TK_BRACKET_CLOSE) {
+ _set_error("Expected ']'");
+ return nullptr;
}
+ } else {
+ _set_tkpos(prepos);
}
ArrayNode *arrname = alloc_node<ArrayNode>();
@@ -4770,8 +5541,8 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
return nullptr;
}
- if (index_expression->get_datatype() != TYPE_INT && index_expression->get_datatype() != TYPE_UINT) {
- _set_error("Only integer expressions are allowed for indexing");
+ if (index_expression->get_array_size() != 0 || (index_expression->get_datatype() != TYPE_INT && index_expression->get_datatype() != TYPE_UINT)) {
+ _set_error("Only integer expressions are allowed for indexing.");
return nullptr;
}
@@ -4795,10 +5566,6 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
mn->index_expression = index_expression;
} else {
- if (!pass_array) {
- _set_error("Expected '[','.' or '='");
- return nullptr;
- }
_set_tkpos(prev_pos);
}
}
@@ -4820,8 +5587,8 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
return nullptr;
}
- if (index->get_datatype() != TYPE_INT && index->get_datatype() != TYPE_UINT) {
- _set_error("Only integer datatypes are allowed for indexing");
+ if (index->get_array_size() != 0 || (index->get_datatype() != TYPE_INT && index->get_datatype() != TYPE_UINT)) {
+ _set_error("Only integer expressions are allowed for indexing.");
return nullptr;
}
@@ -5243,7 +6010,9 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
#if DEBUG_ENABLED
- if (check_warnings && HAS_WARNING(ShaderWarning::FLOAT_COMPARISON_FLAG) && (op == OP_EQUAL || op == OP_NOT_EQUAL) && expression[i - 1].node->get_datatype() == TYPE_FLOAT && expression[i + 1].node->get_datatype() == TYPE_FLOAT) {
+ if (check_warnings && HAS_WARNING(ShaderWarning::FLOAT_COMPARISON_FLAG) && (op == OP_EQUAL || op == OP_NOT_EQUAL) &&
+ (!expression[i - 1].is_op && !expression[i + 1].is_op) &&
+ (expression[i - 1].node->get_datatype() == TYPE_FLOAT && expression[i + 1].node->get_datatype() == TYPE_FLOAT)) {
_add_line_warning(ShaderWarning::FLOAT_COMPARISON);
}
#endif // DEBUG_ENABLED
@@ -5607,11 +6376,46 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
Node *vardecl = nullptr;
while (true) {
- if (tk.type != TK_IDENTIFIER) {
- _set_error("Expected identifier after type");
+ bool unknown_size = false;
+ int array_size = 0;
+
+ ArrayDeclarationNode *anode = nullptr;
+ ArrayDeclarationNode::Declaration adecl;
+
+ if (tk.type != TK_IDENTIFIER && tk.type != TK_BRACKET_OPEN) {
+ _set_error("Expected identifier or '[' after type.");
return ERR_PARSE_ERROR;
}
+ if (tk.type == TK_BRACKET_OPEN) {
+ anode = alloc_node<ArrayDeclarationNode>();
+
+ if (is_struct) {
+ anode->struct_name = struct_name;
+ anode->datatype = TYPE_STRUCT;
+ } else {
+ anode->datatype = type;
+ }
+
+ anode->precision = precision;
+ anode->is_const = is_const;
+ vardecl = (Node *)anode;
+
+ adecl.size = 0U;
+ adecl.single_expression = false;
+
+ Error error = _parse_local_array_size(p_block, p_function_info, anode, &adecl, array_size, unknown_size);
+ if (error != OK) {
+ return error;
+ }
+ tk = _get_token();
+
+ if (tk.type != TK_IDENTIFIER) {
+ _set_error("Expected identifier!");
+ return ERR_PARSE_ERROR;
+ }
+ }
+
StringName name = tk.text;
ShaderLanguage::IdentifierType itype;
if (_find_identifier(p_block, true, p_function_info, name, (ShaderLanguage::DataType *)nullptr, &itype)) {
@@ -5621,6 +6425,8 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
}
}
+ adecl.name = name;
+
#ifdef DEBUG_ENABLED
if (check_warnings && HAS_WARNING(ShaderWarning::UNUSED_LOCAL_VARIABLE_FLAG)) {
if (p_block && p_block->parent_function) {
@@ -5639,95 +6445,47 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
var.type = type;
var.precision = precision;
var.line = tk_line;
- var.array_size = 0;
+ var.array_size = array_size;
var.is_const = is_const;
var.struct_name = struct_name;
tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) {
- bool unknown_size = false;
+ if (var.array_size > 0 || unknown_size) {
+ _set_error("Array size is already defined!");
+ return ERR_PARSE_ERROR;
+ }
if (RenderingServer::get_singleton()->is_low_end() && is_const) {
_set_error("Local const arrays are supported only on high-end platform!");
return ERR_PARSE_ERROR;
}
- ArrayDeclarationNode *node = alloc_node<ArrayDeclarationNode>();
+ anode = alloc_node<ArrayDeclarationNode>();
if (is_struct) {
- node->struct_name = struct_name;
- node->datatype = TYPE_STRUCT;
+ anode->struct_name = struct_name;
+ anode->datatype = TYPE_STRUCT;
} else {
- node->datatype = type;
+ anode->datatype = type;
}
- node->precision = precision;
- node->is_const = is_const;
- vardecl = (Node *)node;
-
- ArrayDeclarationNode::Declaration decl;
- decl.name = name;
- decl.size = 0U;
- decl.single_expression = false;
-
- pos = _get_tkpos();
- tk = _get_token();
-
- if (tk.type == TK_BRACKET_CLOSE) {
- unknown_size = true;
- } else {
- if (tk.type != TK_INT_CONSTANT || ((int)tk.constant) <= 0) {
- _set_tkpos(pos);
- Node *n = _parse_and_reduce_expression(p_block, p_function_info);
- if (n) {
- if (n->type == Node::TYPE_VARIABLE) {
- VariableNode *vn = static_cast<VariableNode *>(n);
- if (vn) {
- ConstantNode::Value v;
- DataType data_type;
-
- _find_identifier(p_block, false, p_function_info, vn->name, &data_type, nullptr, &is_const, nullptr, nullptr, &v);
-
- if (is_const) {
- if (data_type == TYPE_INT) {
- int32_t value = v.sint;
- if (value > 0) {
- node->size_expression = n;
- decl.size = (uint32_t)value;
- }
- } else if (data_type == TYPE_UINT) {
- uint32_t value = v.uint;
- if (value > 0U) {
- node->size_expression = n;
- decl.size = value;
- }
- }
- }
- }
- } else if (n->type == Node::TYPE_OPERATOR) {
- _set_error("Array size expressions are not yet implemented.");
- return ERR_PARSE_ERROR;
- }
- }
- } else if (((int)tk.constant) > 0) {
- decl.size = (uint32_t)tk.constant;
- }
+ anode->precision = precision;
+ anode->is_const = is_const;
+ vardecl = (Node *)anode;
- if (decl.size == 0U) {
- _set_error("Expected integer constant > 0 or ']'");
- return ERR_PARSE_ERROR;
- }
- tk = _get_token();
+ adecl.size = 0U;
+ adecl.single_expression = false;
- if (tk.type != TK_BRACKET_CLOSE) {
- _set_error("Expected ']'");
- return ERR_PARSE_ERROR;
- }
- var.array_size = decl.size;
+ Error error = _parse_local_array_size(p_block, p_function_info, anode, &adecl, var.array_size, unknown_size);
+ if (error != OK) {
+ return error;
}
+ tk = _get_token();
+ }
+ if (var.array_size > 0 || unknown_size) {
bool full_def = false;
- tk = _get_token();
if (tk.type == TK_OP_ASSIGN) {
if (RenderingServer::get_singleton()->is_low_end()) {
_set_error("Array initialization is supported only on high-end platform!");
@@ -5739,16 +6497,14 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
if (tk.type == TK_IDENTIFIER) { // a function call array initialization
_set_tkpos(prev_pos);
- pass_array = true;
Node *n = _parse_and_reduce_expression(p_block, p_function_info);
- pass_array = false;
if (!n) {
_set_error("Expected correct array initializer!");
return ERR_PARSE_ERROR;
} else {
if (unknown_size) {
- decl.size = n->get_array_size();
+ adecl.size = n->get_array_size();
var.array_size = n->get_array_size();
}
@@ -5756,8 +6512,8 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
return ERR_PARSE_ERROR;
}
- decl.single_expression = true;
- decl.initializer.push_back(n);
+ adecl.single_expression = true;
+ adecl.initializer.push_back(n);
}
tk = _get_token();
@@ -5896,7 +6652,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
return ERR_PARSE_ERROR;
}
- if (node->is_const && n->type == Node::TYPE_OPERATOR && ((OperatorNode *)n)->op == OP_CALL) {
+ if (anode->is_const && n->type == Node::TYPE_OPERATOR && ((OperatorNode *)n)->op == OP_CALL) {
_set_error("Expected constant expression");
return ERR_PARSE_ERROR;
}
@@ -5907,13 +6663,13 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
tk = _get_token();
if (tk.type == TK_COMMA) {
- decl.initializer.push_back(n);
+ adecl.initializer.push_back(n);
continue;
} else if (!curly && tk.type == TK_PARENTHESIS_CLOSE) {
- decl.initializer.push_back(n);
+ adecl.initializer.push_back(n);
break;
} else if (curly && tk.type == TK_CURLY_BRACKET_CLOSE) {
- decl.initializer.push_back(n);
+ adecl.initializer.push_back(n);
break;
} else {
if (curly) {
@@ -5925,9 +6681,9 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
}
}
if (unknown_size) {
- decl.size = decl.initializer.size();
- var.array_size = decl.initializer.size();
- } else if (decl.initializer.size() != var.array_size) {
+ adecl.size = adecl.initializer.size();
+ var.array_size = adecl.initializer.size();
+ } else if (adecl.initializer.size() != var.array_size) {
_set_error("Array size mismatch");
return ERR_PARSE_ERROR;
}
@@ -5939,13 +6695,13 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
_set_error("Expected array initialization");
return ERR_PARSE_ERROR;
}
- if (node->is_const) {
+ if (anode->is_const) {
_set_error("Expected initialization of constant");
return ERR_PARSE_ERROR;
}
}
- node->declarations.push_back(decl);
+ anode->declarations.push_back(adecl);
} else if (tk.type == TK_OP_ASSIGN) {
VariableDeclarationNode *node = alloc_node<VariableDeclarationNode>();
if (is_struct) {
@@ -6466,12 +7222,10 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
} else {
_set_tkpos(pos); //rollback, wants expression
- pass_array = true;
Node *expr = _parse_and_reduce_expression(p_block, p_function_info);
if (!expr) {
return ERR_PARSE_ERROR;
}
- pass_array = false;
if (b->parent_function->return_type != expr->get_datatype() || b->parent_function->return_array_size != expr->get_array_size() || return_struct_name != expr->get_datatype_name()) {
_set_error("Expected return with an expression of type '" + (return_struct_name != "" ? return_struct_name : get_datatype_name(b->parent_function->return_type)) + array_size_string + "'");
@@ -6683,6 +7437,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
int texture_uniforms = 0;
+ int texture_binding = 0;
int uniforms = 0;
int instance_index = 0;
ShaderNode::Uniform::Scope uniform_scope = ShaderNode::Uniform::SCOPE_LOCAL;
@@ -6793,8 +7548,23 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
_set_error("void datatype not allowed here");
return ERR_PARSE_ERROR;
}
-
tk = _get_token();
+
+ if (tk.type != TK_IDENTIFIER && tk.type != TK_BRACKET_OPEN) {
+ _set_error("Expected identifier or '['.");
+ return ERR_PARSE_ERROR;
+ }
+
+ int array_size = 0;
+
+ if (tk.type == TK_BRACKET_OPEN) {
+ Error error = _parse_global_array_size(array_size);
+ if (error != OK) {
+ return error;
+ }
+ tk = _get_token();
+ }
+
if (tk.type != TK_IDENTIFIER) {
_set_error("Expected identifier!");
return ERR_PARSE_ERROR;
@@ -6805,41 +7575,29 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
member->datatype = type;
member->struct_name = struct_name;
member->name = tk.text;
+ member->array_size = array_size;
if (member_names.has(member->name)) {
_set_error("Redefinition of '" + String(member->name) + "'");
return ERR_PARSE_ERROR;
}
member_names.insert(member->name);
-
tk = _get_token();
- if (tk.type == TK_BRACKET_OPEN) {
- tk = _get_token();
- if (tk.type == TK_INT_CONSTANT && tk.constant > 0) {
- member->array_size = (int)tk.constant;
- tk = _get_token();
- if (tk.type == TK_BRACKET_CLOSE) {
- tk = _get_token();
- if (tk.type != TK_SEMICOLON) {
- _set_error("Expected ';'");
- return ERR_PARSE_ERROR;
- }
- } else {
- _set_error("Expected ']'");
- return ERR_PARSE_ERROR;
- }
- } else {
- _set_error("Expected single integer constant > 0");
- return ERR_PARSE_ERROR;
+ if (tk.type == TK_BRACKET_OPEN) {
+ Error error = _parse_global_array_size(member->array_size);
+ if (error != OK) {
+ return error;
}
+ tk = _get_token();
}
- st_node->members.push_back(member);
if (tk.type != TK_SEMICOLON) {
- _set_error("Expected ']' or ';'");
+ _set_error("Expected ';'");
return ERR_PARSE_ERROR;
}
+
+ st_node->members.push_back(member);
member_count++;
}
}
@@ -6892,6 +7650,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
}
+ bool precision_defined = false;
DataPrecision precision = PRECISION_DEFAULT;
DataInterpolation interpolation = INTERPOLATION_SMOOTH;
DataType type;
@@ -6900,15 +7659,34 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
if (is_token_interpolation(tk.type)) {
+ if (uniform) {
+ _set_error("Interpolation qualifiers are not supported for uniforms!");
+ return ERR_PARSE_ERROR;
+ }
interpolation = get_token_interpolation(tk.type);
tk = _get_token();
}
if (is_token_precision(tk.type)) {
precision = get_token_precision(tk.type);
+ precision_defined = true;
tk = _get_token();
}
+ if (shader->structs.has(tk.text)) {
+ if (uniform) {
+ if (precision_defined) {
+ _set_error("Precision modifier cannot be used on structs.");
+ return ERR_PARSE_ERROR;
+ }
+ _set_error("struct datatype is not yet supported for uniforms!");
+ return ERR_PARSE_ERROR;
+ } else {
+ _set_error("struct datatype not allowed here");
+ return ERR_PARSE_ERROR;
+ }
+ }
+
if (!is_token_datatype(tk.type)) {
_set_error("Expected datatype. ");
return ERR_PARSE_ERROR;
@@ -6928,27 +7706,17 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
+ if (tk.type != TK_IDENTIFIER && tk.type != TK_BRACKET_OPEN) {
+ _set_error("Expected identifier or '['.");
+ return ERR_PARSE_ERROR;
+ }
+
if (tk.type == TK_BRACKET_OPEN) {
- if (uniform) {
- _set_error(vformat("Uniform arrays are not yet implemented!"));
- return ERR_PARSE_ERROR;
+ Error error = _parse_global_array_size(array_size);
+ if (error != OK) {
+ return error;
}
tk = _get_token();
-
- if (tk.type == TK_INT_CONSTANT && tk.constant > 0) {
- array_size = (int)tk.constant;
-
- tk = _get_token();
- if (tk.type == TK_BRACKET_CLOSE) {
- tk = _get_token();
- } else {
- _set_error("Expected ']'");
- return ERR_PARSE_ERROR;
- }
- } else {
- _set_error("Expected integer constant > 0");
- return ERR_PARSE_ERROR;
- }
}
if (tk.type != TK_IDENTIFIER) {
@@ -6985,12 +7753,32 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
ShaderNode::Uniform uniform2;
+ uniform2.type = type;
+ uniform2.scope = uniform_scope;
+ uniform2.precision = precision;
+ uniform2.array_size = array_size;
+
+ tk = _get_token();
+ if (tk.type == TK_BRACKET_OPEN) {
+ Error error = _parse_global_array_size(uniform2.array_size);
+ if (error != OK) {
+ return error;
+ }
+ tk = _get_token();
+ }
+
if (is_sampler_type(type)) {
if (uniform_scope == ShaderNode::Uniform::SCOPE_INSTANCE) {
_set_error("Uniforms with 'instance' qualifiers can't be of sampler type.");
return ERR_PARSE_ERROR;
}
uniform2.texture_order = texture_uniforms++;
+ uniform2.texture_binding = texture_binding;
+ if (uniform2.array_size > 0) {
+ texture_binding += uniform2.array_size;
+ } else {
+ ++texture_binding;
+ }
uniform2.order = -1;
if (_validate_datatype(type) != OK) {
return ERR_PARSE_ERROR;
@@ -7000,19 +7788,22 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
_set_error("Uniforms with 'instance' qualifiers can't be of matrix type.");
return ERR_PARSE_ERROR;
}
-
uniform2.texture_order = -1;
if (uniform_scope != ShaderNode::Uniform::SCOPE_INSTANCE) {
uniform2.order = uniforms++;
}
}
- uniform2.type = type;
- uniform2.scope = uniform_scope;
- uniform2.precision = precision;
-
- //todo parse default value
- tk = _get_token();
+ if (uniform2.array_size > 0) {
+ if (uniform_scope == ShaderNode::Uniform::SCOPE_GLOBAL) {
+ _set_error("'SCOPE_GLOBAL' qualifier is not yet supported for uniform array!");
+ return ERR_PARSE_ERROR;
+ }
+ if (uniform_scope == ShaderNode::Uniform::SCOPE_INSTANCE) {
+ _set_error("'SCOPE_INSTANCE' qualifier is not yet supported for uniform array!");
+ return ERR_PARSE_ERROR;
+ }
+ }
int custom_instance_index = -1;
@@ -7020,6 +7811,14 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
//hint
do {
tk = _get_token();
+
+ if (uniform2.array_size > 0) {
+ if (tk.type != TK_HINT_COLOR) {
+ _set_error("This hint is not yet supported for uniform arrays!");
+ return ERR_PARSE_ERROR;
+ }
+ }
+
if (tk.type == TK_HINT_WHITE_TEXTURE) {
uniform2.hint = ShaderNode::Uniform::HINT_WHITE;
} else if (tk.type == TK_HINT_BLACK_TEXTURE) {
@@ -7210,6 +8009,11 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
//reset scope for next uniform
if (tk.type == TK_OP_ASSIGN) {
+ if (uniform2.array_size > 0) {
+ _set_error("Setting default value to a uniform array is not yet supported!");
+ return ERR_PARSE_ERROR;
+ }
+
Node *expr = _parse_and_reduce_expression(nullptr, FunctionInfo());
if (!expr) {
return ERR_PARSE_ERROR;
@@ -7254,7 +8058,11 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
if (tk.type != TK_SEMICOLON && tk.type != TK_BRACKET_OPEN) {
- _set_error("Expected ';' or '['");
+ if (array_size == 0) {
+ _set_error("Expected ';' or '['");
+ } else {
+ _set_error("Expected ';'");
+ }
return ERR_PARSE_ERROR;
}
@@ -7279,7 +8087,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
return ERR_PARSE_ERROR;
}
} else {
- _set_error("Expected single integer constant > 0");
+ _set_error("Expected integer constant > 0");
return ERR_PARSE_ERROR;
}
}
@@ -7701,8 +8509,8 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
if (p_functions.has("global")) { // Adds global variables: 'TIME'
- for (Map<StringName, BuiltInInfo>::Element *E = p_functions["global"].built_ins.front(); E; E = E->next()) {
- builtins.built_ins.insert(E->key(), E->value());
+ for (const KeyValue<StringName, BuiltInInfo> &E : p_functions["global"].built_ins) {
+ builtins.built_ins.insert(E.key, E.value);
}
}
@@ -7974,8 +8782,8 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
bool ShaderLanguage::has_builtin(const Map<StringName, ShaderLanguage::FunctionInfo> &p_functions, const StringName &p_name) {
- for (Map<StringName, ShaderLanguage::FunctionInfo>::Element *E = p_functions.front(); E; E = E->next()) {
- if (E->get().built_ins.has(p_name)) {
+ for (const KeyValue<StringName, ShaderLanguage::FunctionInfo> &E : p_functions) {
+ if (E.value.built_ins.has(p_name)) {
return true;
}
}
@@ -8115,19 +8923,19 @@ String ShaderLanguage::get_shader_type(const String &p_code) {
#ifdef DEBUG_ENABLED
void ShaderLanguage::_check_warning_accums() {
- for (Map<ShaderWarning::Code, Map<StringName, Map<StringName, Usage>> *>::Element *E = warnings_check_map2.front(); E; E = E->next()) {
- for (Map<StringName, Map<StringName, Usage>>::Element *T = (*E->get()).front(); T; T = T->next()) {
- for (const Map<StringName, Usage>::Element *U = T->get().front(); U; U = U->next()) {
- if (!U->get().used) {
- _add_warning(E->key(), U->get().decl_line, U->key());
+ for (const KeyValue<ShaderWarning::Code, Map<StringName, Map<StringName, Usage>> *> &E : warnings_check_map2) {
+ for (Map<StringName, Map<StringName, Usage>>::Element *T = (*E.value).front(); T; T = T->next()) {
+ for (const KeyValue<StringName, Usage> &U : T->get()) {
+ if (!U.value.used) {
+ _add_warning(E.key, U.value.decl_line, U.key);
}
}
}
}
- for (Map<ShaderWarning::Code, Map<StringName, Usage> *>::Element *E = warnings_check_map.front(); E; E = E->next()) {
- for (const Map<StringName, Usage>::Element *U = (*E->get()).front(); U; U = U->next()) {
+ for (const KeyValue<ShaderWarning::Code, Map<StringName, Usage> *> &E : warnings_check_map) {
+ for (const Map<StringName, Usage>::Element *U = (*E.value).front(); U; U = U->next()) {
if (!U->get().used) {
- _add_warning(E->key(), U->get().decl_line, U->key());
+ _add_warning(E.key, U->get().decl_line, U->key());
}
}
}
@@ -8210,8 +9018,8 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
return OK;
} break;
case COMPLETION_MAIN_FUNCTION: {
- for (const Map<StringName, FunctionInfo>::Element *E = p_functions.front(); E; E = E->next()) {
- ScriptCodeCompletionOption option(E->key(), ScriptCodeCompletionOption::KIND_FUNCTION);
+ for (const KeyValue<StringName, FunctionInfo> &E : p_functions) {
+ ScriptCodeCompletionOption option(E.key, ScriptCodeCompletionOption::KIND_FUNCTION);
r_options->push_back(option);
}
@@ -8227,9 +9035,9 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
if (completion_class == TAG_GLOBAL) {
while (block) {
if (comp_ident) {
- for (const Map<StringName, BlockNode::Variable>::Element *E = block->variables.front(); E; E = E->next()) {
- if (E->get().line < completion_line) {
- matches.insert(E->key(), ScriptCodeCompletionOption::KIND_VARIABLE);
+ for (const KeyValue<StringName, BlockNode::Variable> &E : block->variables) {
+ if (E.value.line < completion_line) {
+ matches.insert(E.key, ScriptCodeCompletionOption::KIND_VARIABLE);
}
}
}
@@ -8247,30 +9055,30 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
if (comp_ident) {
if (p_functions.has("global")) {
- for (Map<StringName, BuiltInInfo>::Element *E = p_functions["global"].built_ins.front(); E; E = E->next()) {
+ for (const KeyValue<StringName, BuiltInInfo> &E : p_functions["global"].built_ins) {
ScriptCodeCompletionOption::Kind kind = ScriptCodeCompletionOption::KIND_MEMBER;
- if (E->get().constant) {
+ if (E.value.constant) {
kind = ScriptCodeCompletionOption::KIND_CONSTANT;
}
- matches.insert(E->key(), kind);
+ matches.insert(E.key, kind);
}
}
if (skip_function != StringName() && p_functions.has(skip_function)) {
- for (Map<StringName, BuiltInInfo>::Element *E = p_functions[skip_function].built_ins.front(); E; E = E->next()) {
+ for (const KeyValue<StringName, BuiltInInfo> &E : p_functions[skip_function].built_ins) {
ScriptCodeCompletionOption::Kind kind = ScriptCodeCompletionOption::KIND_MEMBER;
- if (E->get().constant) {
+ if (E.value.constant) {
kind = ScriptCodeCompletionOption::KIND_CONSTANT;
}
- matches.insert(E->key(), kind);
+ matches.insert(E.key, kind);
}
}
- for (const Map<StringName, ShaderNode::Varying>::Element *E = shader->varyings.front(); E; E = E->next()) {
- matches.insert(E->key(), ScriptCodeCompletionOption::KIND_VARIABLE);
+ for (const KeyValue<StringName, ShaderNode::Varying> &E : shader->varyings) {
+ matches.insert(E.key, ScriptCodeCompletionOption::KIND_VARIABLE);
}
- for (const Map<StringName, ShaderNode::Uniform>::Element *E = shader->uniforms.front(); E; E = E->next()) {
- matches.insert(E->key(), ScriptCodeCompletionOption::KIND_MEMBER);
+ for (const KeyValue<StringName, ShaderNode::Uniform> &E : shader->uniforms) {
+ matches.insert(E.key, ScriptCodeCompletionOption::KIND_MEMBER);
}
}
@@ -8285,8 +9093,8 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
bool low_end = RenderingServer::get_singleton()->is_low_end();
if (stages && stages->has(skip_function)) {
- for (const Map<StringName, StageFunctionInfo>::Element *E = (*stages)[skip_function].stage_functions.front(); E; E = E->next()) {
- matches.insert(String(E->key()), ScriptCodeCompletionOption::KIND_FUNCTION);
+ for (const KeyValue<StringName, StageFunctionInfo> &E : (*stages)[skip_function].stage_functions) {
+ matches.insert(String(E.key), ScriptCodeCompletionOption::KIND_FUNCTION);
}
}
@@ -8315,9 +9123,9 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
}
}
- for (Map<String, ScriptCodeCompletionOption::Kind>::Element *E = matches.front(); E; E = E->next()) {
- ScriptCodeCompletionOption option(E->key(), E->value());
- if (E->value() == ScriptCodeCompletionOption::KIND_FUNCTION) {
+ for (const KeyValue<String, ScriptCodeCompletionOption::Kind> &E : matches) {
+ ScriptCodeCompletionOption option(E.key, E.value);
+ if (E.value == ScriptCodeCompletionOption::KIND_FUNCTION) {
option.insert_text += "(";
}
r_options->push_back(option);
@@ -8409,14 +9217,14 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
bool low_end = RenderingServer::get_singleton()->is_low_end();
if (stages && stages->has(block_function)) {
- for (const Map<StringName, StageFunctionInfo>::Element *E = (*stages)[block_function].stage_functions.front(); E; E = E->next()) {
- if (completion_function == E->key()) {
- calltip += get_datatype_name(E->get().return_type);
+ for (const KeyValue<StringName, StageFunctionInfo> &E : (*stages)[block_function].stage_functions) {
+ if (completion_function == E.key) {
+ calltip += get_datatype_name(E.value.return_type);
calltip += " ";
- calltip += E->key();
+ calltip += E.key;
calltip += "(";
- for (int i = 0; i < E->get().arguments.size(); i++) {
+ for (int i = 0; i < E.value.arguments.size(); i++) {
if (i > 0) {
calltip += ", ";
} else {
@@ -8427,16 +9235,16 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
calltip += char32_t(0xFFFF);
}
- calltip += get_datatype_name(E->get().arguments[i].type);
+ calltip += get_datatype_name(E.value.arguments[i].type);
calltip += " ";
- calltip += E->get().arguments[i].name;
+ calltip += E.value.arguments[i].name;
if (i == completion_argument) {
calltip += char32_t(0xFFFF);
}
}
- if (E->get().arguments.size()) {
+ if (E.value.arguments.size()) {
calltip += " ";
}
calltip += ")";
@@ -8454,10 +9262,16 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
}
int idx2 = 0;
- int out_arg = -1;
+ Set<int> out_args;
while (builtin_func_out_args[idx2].name != nullptr) {
if (builtin_func_out_args[idx2].name == builtin_func_defs[idx].name) {
- out_arg = builtin_func_out_args[idx2].argument;
+ for (int i = 0; i < BuiltinFuncOutArgs::MAX_ARGS; i++) {
+ int arg = builtin_func_out_args[idx2].arguments[i];
+ if (arg == -1) {
+ break;
+ }
+ out_args.insert(arg);
+ }
break;
}
idx2++;
@@ -8494,7 +9308,7 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
calltip += char32_t(0xFFFF);
}
- if (out_arg >= 0 && i == out_arg) {
+ if (out_args.has(i)) {
calltip += "out ";
}
diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h
index 18525e054e..c82f71d10d 100644
--- a/servers/rendering/shader_language.h
+++ b/servers/rendering/shader_language.h
@@ -692,8 +692,10 @@ public:
int order = 0;
int texture_order = 0;
+ int texture_binding = 0;
DataType type = TYPE_VOID;
DataPrecision precision = PRECISION_DEFAULT;
+ int array_size = 0;
Vector<ConstantNode::Value> default_value;
Scope scope = SCOPE_LOCAL;
Hint hint = HINT_NONE;
@@ -776,7 +778,7 @@ public:
static bool is_scalar_type(DataType p_type);
static bool is_float_type(DataType p_type);
static bool is_sampler_type(DataType p_type);
- static Variant constant_value_to_variant(const Vector<ShaderLanguage::ConstantNode::Value> &p_value, DataType p_type, ShaderLanguage::ShaderNode::Uniform::Hint p_hint = ShaderLanguage::ShaderNode::Uniform::HINT_NONE);
+ static Variant constant_value_to_variant(const Vector<ShaderLanguage::ConstantNode::Value> &p_value, DataType p_type, int p_array_size, ShaderLanguage::ShaderNode::Uniform::Hint p_hint = ShaderLanguage::ShaderNode::Uniform::HINT_NONE);
static PropertyInfo uniform_to_property_info(const ShaderNode::Uniform &p_uniform);
static uint32_t get_type_size(DataType p_type);
@@ -874,7 +876,6 @@ private:
StringName current_function;
bool last_const = false;
- bool pass_array = false;
StringName last_name;
VaryingFunctionNames varying_function_names;
@@ -948,8 +949,16 @@ private:
};
struct BuiltinFuncOutArgs { //arguments used as out in built in functions
+ enum { MAX_ARGS = 2 };
const char *name;
- int argument;
+ const int arguments[MAX_ARGS];
+ };
+
+ struct BuiltinFuncConstArgs {
+ const char *name;
+ int arg;
+ int min;
+ int max;
};
CompletionType completion_type;
@@ -965,6 +974,7 @@ private:
bool _get_completable_identifier(BlockNode *p_block, CompletionType p_type, StringName &identifier);
static const BuiltinFuncDef builtin_func_defs[];
static const BuiltinFuncOutArgs builtin_func_out_args[];
+ static const BuiltinFuncConstArgs builtin_func_const_args[];
Error _validate_datatype(DataType p_type);
bool _compare_datatypes(DataType p_datatype_a, String p_datatype_name_a, int p_array_size_a, DataType p_datatype_b, String p_datatype_name_b, int p_array_size_b);
@@ -978,6 +988,10 @@ private:
bool _validate_varying_using(ShaderNode::Varying &p_varying, String *r_message);
bool _check_node_constness(const Node *p_node) const;
+ Node *_parse_array_size(BlockNode *p_block, const FunctionInfo &p_function_info, int &r_array_size);
+ Error _parse_global_array_size(int &r_array_size);
+ Error _parse_local_array_size(BlockNode *p_block, const FunctionInfo &p_function_info, ArrayDeclarationNode *p_node, ArrayDeclarationNode::Declaration *p_decl, int &r_array_size, bool &r_is_unknown_size);
+
Node *_parse_expression(BlockNode *p_block, const FunctionInfo &p_function_info);
Node *_parse_array_constructor(BlockNode *p_block, const FunctionInfo &p_function_info);
Node *_parse_array_constructor(BlockNode *p_block, const FunctionInfo &p_function_info, DataType p_type, const StringName &p_struct_name, int p_array_size);
diff --git a/servers/rendering/shader_warnings.cpp b/servers/rendering/shader_warnings.cpp
index 0c1d6408c9..0b8476478c 100644
--- a/servers/rendering/shader_warnings.cpp
+++ b/servers/rendering/shader_warnings.cpp
@@ -119,10 +119,10 @@ ShaderWarning::CodeFlags ShaderWarning::get_flags_from_codemap(const Map<Code, b
init_code_to_flags_map();
}
- for (Map<Code, bool>::Element *E = p_map.front(); E; E = E->next()) {
- if (E->get()) {
- ERR_FAIL_COND_V(!code_to_flags_map->has((int)E->key()), ShaderWarning::NONE_FLAG);
- result |= (*code_to_flags_map)[(int)E->key()];
+ for (const KeyValue<Code, bool> &E : p_map) {
+ if (E.value) {
+ ERR_FAIL_COND_V(!code_to_flags_map->has((int)E.key), ShaderWarning::NONE_FLAG);
+ result |= (*code_to_flags_map)[(int)E.key];
}
}
return (CodeFlags)result;
diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp
index 222ea9e622..b3efe840b6 100644
--- a/servers/rendering_server.cpp
+++ b/servers/rendering_server.cpp
@@ -500,7 +500,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint
case RS::ARRAY_CUSTOM1:
case RS::ARRAY_CUSTOM2:
case RS::ARRAY_CUSTOM3: {
- uint32_t type = (p_format >> (ARRAY_FORMAT_CUSTOM_BASE + ARRAY_FORMAT_CUSTOM_BITS * (RS::ARRAY_CUSTOM0 - ai))) & ARRAY_FORMAT_CUSTOM_MASK;
+ uint32_t type = (p_format >> (ARRAY_FORMAT_CUSTOM_BASE + ARRAY_FORMAT_CUSTOM_BITS * (ai - RS::ARRAY_CUSTOM0))) & ARRAY_FORMAT_CUSTOM_MASK;
switch (type) {
case ARRAY_CUSTOM_RGBA8_UNORM:
case ARRAY_CUSTOM_RGBA8_SNORM:
@@ -541,14 +541,14 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint
ERR_FAIL_COND_V(p_arrays[ai].get_type() != Variant::PACKED_FLOAT32_ARRAY, ERR_INVALID_PARAMETER);
Vector<float> array = p_arrays[ai];
- int32_t s = ARRAY_CUSTOM_R_FLOAT - ai + 1;
+ int32_t s = type - ARRAY_CUSTOM_R_FLOAT + 1;
ERR_FAIL_COND_V(array.size() != p_vertex_array_len * s, ERR_INVALID_PARAMETER);
const float *src = array.ptr();
for (int i = 0; i < p_vertex_array_len; i++) {
- memcpy(&aw[p_offsets[ai] + i * p_attrib_stride], &src[i * s], 4 * s);
+ memcpy(&aw[p_offsets[ai] + i * p_attrib_stride], &src[i * s], sizeof(float) * s);
}
} break;
default: {
@@ -934,7 +934,14 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa
}
}
- ERR_FAIL_COND_V((bsformat) != (format & (RS::ARRAY_FORMAT_INDEX - 1)), ERR_INVALID_PARAMETER);
+ ERR_FAIL_COND_V_MSG((bsformat & RS::ARRAY_FORMAT_BLEND_SHAPE_MASK) != (format & RS::ARRAY_FORMAT_BLEND_SHAPE_MASK), ERR_INVALID_PARAMETER, "Blend shape format must match the main array format for Vertex, Normal and Tangent arrays.");
+ }
+ }
+
+ for (uint32_t i = 0; i < RS::ARRAY_CUSTOM_COUNT; ++i) {
+ // include custom array format type.
+ if (format & (1 << (ARRAY_CUSTOM0 + i))) {
+ format |= (RS::ARRAY_FORMAT_CUSTOM_MASK << (RS::ARRAY_FORMAT_CUSTOM_BASE + i * RS::ARRAY_FORMAT_CUSTOM_BITS)) & p_compress_format;
}
}
@@ -1191,7 +1198,7 @@ Array RenderingServer::_get_array_from_surface(uint32_t p_format, Vector<uint8_t
case RS::ARRAY_CUSTOM1:
case RS::ARRAY_CUSTOM2:
case RS::ARRAY_CUSTOM3: {
- uint32_t type = (p_format >> (ARRAY_FORMAT_CUSTOM_BASE + ARRAY_FORMAT_CUSTOM_BITS * (RS::ARRAY_CUSTOM0 - i))) & ARRAY_FORMAT_CUSTOM_MASK;
+ uint32_t type = (p_format >> (ARRAY_FORMAT_CUSTOM_BASE + ARRAY_FORMAT_CUSTOM_BITS * (i - RS::ARRAY_CUSTOM0))) & ARRAY_FORMAT_CUSTOM_MASK;
switch (type) {
case ARRAY_CUSTOM_RGBA8_UNORM:
case ARRAY_CUSTOM_RGBA8_SNORM:
@@ -1219,6 +1226,8 @@ Array RenderingServer::_get_array_from_surface(uint32_t p_format, Vector<uint8_t
uint32_t s = type - ARRAY_CUSTOM_R_FLOAT + 1;
Vector<float> arr;
+ arr.resize(s * p_vertex_len);
+
float *w = arr.ptrw();
for (int j = 0; j < p_vertex_len; j++) {
@@ -1467,6 +1476,11 @@ ShaderLanguage::DataType RenderingServer::global_variable_type_get_shader_dataty
}
}
+RenderingDevice *RenderingServer::get_rendering_device() const {
+ // return the rendering device we're using globally
+ return RenderingDevice::get_singleton();
+}
+
RenderingDevice *RenderingServer::create_local_rendering_device() const {
return RenderingDevice::get_singleton()->create_local_device();
}
@@ -2138,6 +2152,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("viewport_create"), &RenderingServer::viewport_create);
ClassDB::bind_method(D_METHOD("viewport_set_use_xr", "viewport", "use_xr"), &RenderingServer::viewport_set_use_xr);
+ ClassDB::bind_method(D_METHOD("viewport_set_scale_3d", "viewport", "scale"), &RenderingServer::viewport_set_scale_3d);
ClassDB::bind_method(D_METHOD("viewport_set_size", "viewport", "width", "height"), &RenderingServer::viewport_set_size);
ClassDB::bind_method(D_METHOD("viewport_set_active", "viewport", "active"), &RenderingServer::viewport_set_active);
ClassDB::bind_method(D_METHOD("viewport_set_parent_viewport", "viewport", "parent_viewport"), &RenderingServer::viewport_set_parent_viewport);
@@ -2210,7 +2225,6 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(VIEWPORT_MSAA_2X);
BIND_ENUM_CONSTANT(VIEWPORT_MSAA_4X);
BIND_ENUM_CONSTANT(VIEWPORT_MSAA_8X);
- BIND_ENUM_CONSTANT(VIEWPORT_MSAA_16X);
BIND_ENUM_CONSTANT(VIEWPORT_MSAA_MAX);
BIND_ENUM_CONSTANT(VIEWPORT_SCREEN_SPACE_AA_DISABLED);
@@ -2278,7 +2292,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("environment_set_bg_color", "env", "color"), &RenderingServer::environment_set_bg_color);
ClassDB::bind_method(D_METHOD("environment_set_bg_energy", "env", "energy"), &RenderingServer::environment_set_bg_energy);
ClassDB::bind_method(D_METHOD("environment_set_canvas_max_layer", "env", "max_layer"), &RenderingServer::environment_set_canvas_max_layer);
- ClassDB::bind_method(D_METHOD("environment_set_ambient_light", "env", "color", "ambient", "energy", "sky_contibution", "reflection_source", "ao_color"), &RenderingServer::environment_set_ambient_light, DEFVAL(RS::ENV_AMBIENT_SOURCE_BG), DEFVAL(1.0), DEFVAL(0.0), DEFVAL(RS::ENV_REFLECTION_SOURCE_BG), DEFVAL(Color()));
+ ClassDB::bind_method(D_METHOD("environment_set_ambient_light", "env", "color", "ambient", "energy", "sky_contibution", "reflection_source"), &RenderingServer::environment_set_ambient_light, DEFVAL(RS::ENV_AMBIENT_SOURCE_BG), DEFVAL(1.0), DEFVAL(0.0), DEFVAL(RS::ENV_REFLECTION_SOURCE_BG));
ClassDB::bind_method(D_METHOD("environment_set_glow", "env", "enable", "levels", "intensity", "strength", "mix", "bloom_threshold", "blend_mode", "hdr_bleed_threshold", "hdr_bleed_scale", "hdr_luminance_cap"), &RenderingServer::environment_set_glow);
ClassDB::bind_method(D_METHOD("environment_set_tonemap", "env", "tone_mapper", "exposure", "white", "auto_exposure", "min_luminance", "max_luminance", "auto_exp_speed", "auto_exp_grey"), &RenderingServer::environment_set_tonemap);
ClassDB::bind_method(D_METHOD("environment_set_adjustment", "env", "enable", "brightness", "contrast", "saturation", "use_1d_color_correction", "color_correction"), &RenderingServer::environment_set_adjustment);
@@ -2519,6 +2533,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("canvas_item_add_rect", "item", "rect", "color"), &RenderingServer::canvas_item_add_rect);
ClassDB::bind_method(D_METHOD("canvas_item_add_circle", "item", "pos", "radius", "color"), &RenderingServer::canvas_item_add_circle);
ClassDB::bind_method(D_METHOD("canvas_item_add_texture_rect", "item", "rect", "texture", "tile", "modulate", "transpose"), &RenderingServer::canvas_item_add_texture_rect, DEFVAL(false), DEFVAL(Color(1, 1, 1)), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("canvas_item_add_msdf_texture_rect_region", "item", "rect", "texture", "src_rect", "modulate", "outline_size", "px_range"), &RenderingServer::canvas_item_add_msdf_texture_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(0), DEFVAL(1.0));
ClassDB::bind_method(D_METHOD("canvas_item_add_texture_rect_region", "item", "rect", "texture", "src_rect", "modulate", "transpose", "clip_uv"), &RenderingServer::canvas_item_add_texture_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(true));
ClassDB::bind_method(D_METHOD("canvas_item_add_nine_patch", "item", "rect", "source", "texture", "topleft", "bottomright", "x_axis_mode", "y_axis_mode", "draw_center", "modulate"), &RenderingServer::canvas_item_add_nine_patch, DEFVAL(NINE_PATCH_STRETCH), DEFVAL(NINE_PATCH_STRETCH), DEFVAL(true), DEFVAL(Color(1, 1, 1)));
ClassDB::bind_method(D_METHOD("canvas_item_add_primitive", "item", "points", "colors", "uvs", "texture", "width"), &RenderingServer::canvas_item_add_primitive, DEFVAL(1.0));
@@ -2707,6 +2722,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("force_sync"), &RenderingServer::sync);
ClassDB::bind_method(D_METHOD("force_draw", "swap_buffers", "frame_step"), &RenderingServer::draw, DEFVAL(true), DEFVAL(0.0));
+ ClassDB::bind_method(D_METHOD("get_rendering_device"), &RenderingServer::get_rendering_device);
ClassDB::bind_method(D_METHOD("create_local_rendering_device"), &RenderingServer::create_local_rendering_device);
}
@@ -2795,6 +2811,12 @@ RenderingServer::RenderingServer() {
"rendering/vulkan/rendering/back_end",
PROPERTY_HINT_ENUM, "Forward Clustered (Supports Desktop Only),Forward Mobile (Supports Desktop and Mobile)"));
+ GLOBAL_DEF("rendering/3d/viewport/scale", 1.0);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/3d/viewport/scale",
+ PropertyInfo(Variant::FLOAT,
+ "rendering/3d/viewport/scale",
+ PROPERTY_HINT_RANGE, "0.25,2.0,0.01"));
+
GLOBAL_DEF("rendering/shader_compiler/shader_cache/enabled", true);
GLOBAL_DEF("rendering/shader_compiler/shader_cache/compress", true);
GLOBAL_DEF("rendering/shader_compiler/shader_cache/use_zstd_compression", true);
diff --git a/servers/rendering_server.h b/servers/rendering_server.h
index 545270dcd9..b50da66d03 100644
--- a/servers/rendering_server.h
+++ b/servers/rendering_server.h
@@ -295,7 +295,7 @@ public:
AABB aabb;
struct LOD {
- float edge_length;
+ float edge_length = 0.0f;
Vector<uint8_t> index_data;
};
Vector<LOD> lods;
@@ -755,6 +755,7 @@ public:
virtual RID viewport_create() = 0;
virtual void viewport_set_use_xr(RID p_viewport, bool p_use_xr) = 0;
+ virtual void viewport_set_scale_3d(RID p_viewport, float p_scale_3d) = 0;
virtual void viewport_set_size(RID p_viewport, int p_width, int p_height) = 0;
virtual void viewport_set_active(RID p_viewport, bool p_active) = 0;
virtual void viewport_set_parent_viewport(RID p_viewport, RID p_parent_viewport) = 0;
@@ -826,7 +827,6 @@ public:
VIEWPORT_MSAA_2X,
VIEWPORT_MSAA_4X,
VIEWPORT_MSAA_8X,
- VIEWPORT_MSAA_16X,
VIEWPORT_MSAA_MAX,
};
@@ -952,7 +952,7 @@ public:
virtual void environment_set_bg_color(RID p_env, const Color &p_color) = 0;
virtual void environment_set_bg_energy(RID p_env, float p_energy) = 0;
virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer) = 0;
- virtual void environment_set_ambient_light(RID p_env, const Color &p_color, EnvironmentAmbientSource p_ambient = ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, EnvironmentReflectionSource p_reflection_source = ENV_REFLECTION_SOURCE_BG, const Color &p_ao_color = Color()) = 0;
+ virtual void environment_set_ambient_light(RID p_env, const Color &p_color, EnvironmentAmbientSource p_ambient = ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, EnvironmentReflectionSource p_reflection_source = ENV_REFLECTION_SOURCE_BG) = 0;
enum EnvironmentGlowBlendMode {
ENV_GLOW_BLEND_MODE_ADDITIVE,
@@ -1248,6 +1248,7 @@ public:
virtual void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color) = 0;
virtual void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false) = 0;
virtual void canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, bool p_clip_uv = false) = 0;
+ virtual void canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, float p_px_range = 1.0) = 0;
virtual void canvas_item_add_nine_patch(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector2 &p_topleft, const Vector2 &p_bottomright, NinePatchAxisMode p_x_axis_mode = NINE_PATCH_STRETCH, NinePatchAxisMode p_y_axis_mode = NINE_PATCH_STRETCH, bool p_draw_center = true, const Color &p_modulate = Color(1, 1, 1)) = 0;
virtual void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width = 1.0) = 0;
virtual void canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), RID p_texture = RID()) = 0;
@@ -1406,7 +1407,7 @@ public:
/* FREE */
- virtual void free(RID p_rid) = 0; ///< free RIDs associated with the visual server
+ virtual void free(RID p_rid) = 0; ///< free RIDs associated with the rendering server
virtual void request_frame_drawn_callback(Object *p_where, const StringName &p_method, const Variant &p_userdata) = 0;
@@ -1482,6 +1483,7 @@ public:
virtual void set_print_gpu_profile(bool p_enable) = 0;
+ RenderingDevice *get_rendering_device() const;
RenderingDevice *create_local_rendering_device() const;
bool is_render_loop_enabled() const;
diff --git a/servers/text/SCsub b/servers/text/SCsub
new file mode 100644
index 0000000000..86681f9c74
--- /dev/null
+++ b/servers/text/SCsub
@@ -0,0 +1,5 @@
+#!/usr/bin/env python
+
+Import("env")
+
+env.add_source_files(env.servers_sources, "*.cpp")
diff --git a/servers/text/text_server_extension.cpp b/servers/text/text_server_extension.cpp
new file mode 100644
index 0000000000..a44fee7c95
--- /dev/null
+++ b/servers/text/text_server_extension.cpp
@@ -0,0 +1,1281 @@
+/*************************************************************************/
+/* text_server_extension.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 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 "text_server_extension.h"
+
+void TextServerExtension::_bind_methods() {
+ GDVIRTUAL_BIND(_has_feature, "feature");
+ GDVIRTUAL_BIND(_get_name);
+ GDVIRTUAL_BIND(_get_features);
+
+ GDVIRTUAL_BIND(_free, "rid");
+ GDVIRTUAL_BIND(_has, "rid");
+ GDVIRTUAL_BIND(_load_support_data, "filename");
+
+ GDVIRTUAL_BIND(_get_support_data_filename);
+ GDVIRTUAL_BIND(_get_support_data_info);
+ GDVIRTUAL_BIND(_save_support_data, "filename");
+
+ GDVIRTUAL_BIND(_is_locale_right_to_left, "locale");
+
+ GDVIRTUAL_BIND(_name_to_tag, "name");
+ GDVIRTUAL_BIND(_tag_to_name, "tag");
+
+ /* Font interface */
+
+ GDVIRTUAL_BIND(_create_font);
+
+ GDVIRTUAL_BIND(_font_set_data, "font_rid", "data");
+ GDVIRTUAL_BIND(_font_set_data_ptr, "font_rid", "data_ptr", "data_size");
+
+ GDVIRTUAL_BIND(_font_set_antialiased, "font_rid", "antialiased");
+ GDVIRTUAL_BIND(_font_is_antialiased, "font_rid");
+
+ GDVIRTUAL_BIND(_font_set_multichannel_signed_distance_field, "font_rid", "msdf");
+ GDVIRTUAL_BIND(_font_is_multichannel_signed_distance_field, "font_rid");
+
+ GDVIRTUAL_BIND(_font_set_msdf_pixel_range, "font_rid", "msdf_pixel_range");
+ GDVIRTUAL_BIND(_font_get_msdf_pixel_range, "font_rid");
+
+ GDVIRTUAL_BIND(_font_set_msdf_size, "font_rid", "msdf_size");
+ GDVIRTUAL_BIND(_font_get_msdf_size, "font_rid");
+
+ GDVIRTUAL_BIND(_font_set_fixed_size, "font_rid", "fixed_size");
+ GDVIRTUAL_BIND(_font_get_fixed_size, "font_rid");
+
+ GDVIRTUAL_BIND(_font_set_force_autohinter, "font_rid", "force_autohinter");
+ GDVIRTUAL_BIND(_font_is_force_autohinter, "font_rid");
+
+ GDVIRTUAL_BIND(_font_set_hinting, "font_rid", "hinting");
+ GDVIRTUAL_BIND(_font_get_hinting, "font_rid");
+
+ GDVIRTUAL_BIND(_font_set_variation_coordinates, "font_rid", "variation_coordinates");
+ GDVIRTUAL_BIND(_font_get_variation_coordinates, "font_rid");
+
+ GDVIRTUAL_BIND(_font_set_oversampling, "font_rid", "oversampling");
+ GDVIRTUAL_BIND(_font_get_oversampling, "font_rid");
+
+ GDVIRTUAL_BIND(_font_get_size_cache_list, "font_rid");
+ GDVIRTUAL_BIND(_font_clear_size_cache, "font_rid");
+ GDVIRTUAL_BIND(_font_remove_size_cache, "font_rid", "size");
+
+ GDVIRTUAL_BIND(_font_set_ascent, "font_rid", "size", "ascent");
+ GDVIRTUAL_BIND(_font_get_ascent, "font_rid", "size");
+
+ GDVIRTUAL_BIND(_font_set_descent, "font_rid", "size", "descent");
+ GDVIRTUAL_BIND(_font_get_descent, "font_rid", "size");
+
+ GDVIRTUAL_BIND(_font_set_underline_position, "font_rid", "size", "underline_position");
+ GDVIRTUAL_BIND(_font_get_underline_position, "font_rid", "size");
+
+ GDVIRTUAL_BIND(_font_set_underline_thickness, "font_rid", "size", "underline_thickness");
+ GDVIRTUAL_BIND(_font_get_underline_thickness, "font_rid", "size");
+
+ GDVIRTUAL_BIND(_font_set_scale, "font_rid", "size", "scale");
+ GDVIRTUAL_BIND(_font_get_scale, "font_rid", "size");
+
+ GDVIRTUAL_BIND(_font_set_spacing, "font_rid", "size", "spacing", "value");
+ GDVIRTUAL_BIND(_font_get_spacing, "font_rid", "size", "spacing");
+
+ GDVIRTUAL_BIND(_font_get_texture_count, "font_rid", "size");
+ GDVIRTUAL_BIND(_font_clear_textures, "font_rid", "size");
+ GDVIRTUAL_BIND(_font_remove_texture, "font_rid", "size", "texture_index");
+
+ GDVIRTUAL_BIND(_font_set_texture_image, "font_rid", "size", "texture_index", "image");
+ GDVIRTUAL_BIND(_font_get_texture_image, "font_rid", "size", "texture_index");
+
+ GDVIRTUAL_BIND(_font_set_texture_offsets, "font_rid", "size", "texture_index", "offset");
+ GDVIRTUAL_BIND(_font_get_texture_offsets, "font_rid", "size", "texture_index");
+
+ GDVIRTUAL_BIND(_font_get_glyph_list, "font_rid", "size");
+ GDVIRTUAL_BIND(_font_clear_glyphs, "font_rid", "size");
+ GDVIRTUAL_BIND(_font_remove_glyph, "font_rid", "size", "glyph");
+
+ GDVIRTUAL_BIND(_font_get_glyph_advance, "font_rid", "size", "glyph");
+ GDVIRTUAL_BIND(_font_set_glyph_advance, "font_rid", "size", "glyph", "advance");
+
+ GDVIRTUAL_BIND(_font_get_glyph_offset, "font_rid", "size", "glyph");
+ GDVIRTUAL_BIND(_font_set_glyph_offset, "font_rid", "size", "glyph", "offset");
+
+ GDVIRTUAL_BIND(_font_get_glyph_size, "font_rid", "size", "glyph");
+ GDVIRTUAL_BIND(_font_set_glyph_size, "font_rid", "size", "glyph", "gl_size");
+
+ GDVIRTUAL_BIND(_font_get_glyph_uv_rect, "font_rid", "size", "glyph");
+ GDVIRTUAL_BIND(_font_set_glyph_uv_rect, "font_rid", "size", "glyph", "uv_rect");
+
+ GDVIRTUAL_BIND(_font_get_glyph_texture_idx, "font_rid", "size", "glyph");
+ GDVIRTUAL_BIND(_font_set_glyph_texture_idx, "font_rid", "size", "glyph", "texture_idx");
+
+ GDVIRTUAL_BIND(_font_get_glyph_contours, "font_rid", "size", "index");
+
+ GDVIRTUAL_BIND(_font_get_kerning_list, "font_rid", "size");
+ GDVIRTUAL_BIND(_font_clear_kerning_map, "font_rid", "size");
+ GDVIRTUAL_BIND(_font_remove_kerning, "font_rid", "size", "glyph_pair");
+
+ GDVIRTUAL_BIND(_font_set_kerning, "font_rid", "size", "glyph_pair", "kerning");
+ GDVIRTUAL_BIND(_font_get_kerning, "font_rid", "size", "glyph_pair");
+
+ GDVIRTUAL_BIND(_font_get_glyph_index, "font_rid", "size", "char", "variation_selector");
+
+ GDVIRTUAL_BIND(_font_has_char, "font_rid", "char");
+ GDVIRTUAL_BIND(_font_get_supported_chars, "font_rid");
+
+ GDVIRTUAL_BIND(_font_render_range, "font_rid", "size", "start", "end");
+ GDVIRTUAL_BIND(_font_render_glyph, "font_rid", "size", "index");
+
+ GDVIRTUAL_BIND(_font_draw_glyph, "font_rid", "canvas", "size", "pos", "index", "color");
+ GDVIRTUAL_BIND(_font_draw_glyph_outline, "font_rid", "canvas", "size", "outline_size", "pos", "index", "color");
+
+ GDVIRTUAL_BIND(_font_is_language_supported, "font_rid", "language");
+ GDVIRTUAL_BIND(_font_set_language_support_override, "font_rid", "language", "supported");
+ GDVIRTUAL_BIND(_font_get_language_support_override, "font_rid", "language");
+ GDVIRTUAL_BIND(_font_remove_language_support_override, "font_rid", "language");
+ GDVIRTUAL_BIND(_font_get_language_support_overrides, "font_rid");
+
+ GDVIRTUAL_BIND(_font_is_script_supported, "font_rid", "script");
+ GDVIRTUAL_BIND(_font_set_script_support_override, "font_rid", "script", "supported");
+ GDVIRTUAL_BIND(_font_get_script_support_override, "font_rid", "script");
+ GDVIRTUAL_BIND(_font_remove_script_support_override, "font_rid", "script");
+ GDVIRTUAL_BIND(_font_get_script_support_overrides, "font_rid");
+
+ GDVIRTUAL_BIND(_font_supported_feature_list, "font_rid");
+ GDVIRTUAL_BIND(_font_supported_variation_list, "font_rid");
+
+ GDVIRTUAL_BIND(_font_get_global_oversampling);
+ GDVIRTUAL_BIND(_font_set_global_oversampling, "oversampling");
+
+ GDVIRTUAL_BIND(_get_hex_code_box_size, "size", "index");
+ GDVIRTUAL_BIND(_draw_hex_code_box, "canvas", "size", "pos", "index", "color");
+
+ /* Shaped text buffer interface */
+
+ GDVIRTUAL_BIND(_create_shaped_text, "direction", "orientation");
+
+ GDVIRTUAL_BIND(_shaped_text_clear, "shaped");
+
+ GDVIRTUAL_BIND(_shaped_text_set_direction, "shaped", "direction");
+ GDVIRTUAL_BIND(_shaped_text_get_direction, "shaped");
+
+ GDVIRTUAL_BIND(_shaped_text_set_bidi_override, "shaped", "override");
+
+ GDVIRTUAL_BIND(_shaped_text_set_orientation, "shaped", "orientation");
+ GDVIRTUAL_BIND(_shaped_text_get_orientation, "shaped");
+
+ GDVIRTUAL_BIND(_shaped_text_set_preserve_invalid, "shaped", "enabled");
+ GDVIRTUAL_BIND(_shaped_text_get_preserve_invalid, "shaped");
+
+ GDVIRTUAL_BIND(_shaped_text_set_preserve_control, "shaped", "enabled");
+ GDVIRTUAL_BIND(_shaped_text_get_preserve_control, "shaped");
+
+ GDVIRTUAL_BIND(_shaped_text_add_string, "shaped", "text", "fonts", "size", "opentype_features", "language");
+ GDVIRTUAL_BIND(_shaped_text_add_object, "shaped", "key", "size", "inline_align", "length");
+ GDVIRTUAL_BIND(_shaped_text_resize_object, "shaped", "key", "size", "inline_align");
+
+ GDVIRTUAL_BIND(_shaped_text_substr, "shaped", "start", "length");
+ GDVIRTUAL_BIND(_shaped_text_get_parent, "shaped");
+
+ GDVIRTUAL_BIND(_shaped_text_fit_to_width, "shaped", "width", "jst_flags");
+ GDVIRTUAL_BIND(_shaped_text_tab_align, "shaped", "tab_stops");
+
+ GDVIRTUAL_BIND(_shaped_text_shape, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_update_breaks, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_update_justification_ops, "shaped");
+
+ GDVIRTUAL_BIND(_shaped_text_is_ready, "shaped");
+
+ GDVIRTUAL_BIND(_shaped_text_get_glyphs, "shaped", "r_glyphs");
+ GDVIRTUAL_BIND(_shaped_text_sort_logical, "shaped", "r_glyphs");
+ GDVIRTUAL_BIND(_shaped_text_get_glyph_count, "shaped");
+
+ GDVIRTUAL_BIND(_shaped_text_get_range, "shaped");
+
+ GDVIRTUAL_BIND(_shaped_text_get_line_breaks_adv, "shaped", "width", "start", "once", "break_flags");
+ GDVIRTUAL_BIND(_shaped_text_get_line_breaks, "shaped", "width", "start", "break_flags");
+ GDVIRTUAL_BIND(_shaped_text_get_word_breaks, "shaped", "grapheme_flags");
+
+ GDVIRTUAL_BIND(_shaped_text_get_trim_pos, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_get_ellipsis_pos, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_get_ellipsis_glyph_count, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_get_ellipsis_glyphs, "shaped", "r_glyphs");
+
+ GDVIRTUAL_BIND(_shaped_text_overrun_trim_to_width, "shaped", "width", "trim_flags");
+
+ GDVIRTUAL_BIND(_shaped_text_get_objects, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_get_object_rect, "shaped", "key");
+
+ GDVIRTUAL_BIND(_shaped_text_get_size, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_get_ascent, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_get_descent, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_get_width, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_get_underline_position, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_get_underline_thickness, "shaped");
+
+ GDVIRTUAL_BIND(_shaped_text_get_dominant_direction_in_range, "shaped", "start", "end");
+
+ GDVIRTUAL_BIND(_shaped_text_get_carets, "shaped", "position", "caret");
+ GDVIRTUAL_BIND(_shaped_text_get_selection, "shaped", "start", "end");
+
+ GDVIRTUAL_BIND(_shaped_text_hit_test_grapheme, "shaped", "coord");
+ GDVIRTUAL_BIND(_shaped_text_hit_test_position, "shaped", "coord");
+
+ GDVIRTUAL_BIND(_shaped_text_draw, "shaped", "canvas", "pos", "clip_l", "clip_r", "color");
+ GDVIRTUAL_BIND(_shaped_text_draw_outline, "shaped", "canvas", "pos", "clip_l", "clip_r", "outline_size", "color");
+
+ GDVIRTUAL_BIND(_shaped_text_next_grapheme_pos, "shaped", "pos");
+ GDVIRTUAL_BIND(_shaped_text_prev_grapheme_pos, "shaped", "pos");
+
+ GDVIRTUAL_BIND(_format_number, "string", "language");
+ GDVIRTUAL_BIND(_parse_number, "string", "language");
+ GDVIRTUAL_BIND(_percent_sign, "language");
+}
+
+bool TextServerExtension::has_feature(Feature p_feature) const {
+ bool ret;
+ if (GDVIRTUAL_CALL(_has_feature, p_feature, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+String TextServerExtension::get_name() const {
+ String ret;
+ if (GDVIRTUAL_CALL(_get_name, ret)) {
+ return ret;
+ }
+ return "Unknown";
+}
+
+uint32_t TextServerExtension::get_features() const {
+ uint32_t ret;
+ if (GDVIRTUAL_CALL(_get_features, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+void TextServerExtension::free(RID p_rid) {
+ GDVIRTUAL_CALL(_free, p_rid);
+}
+
+bool TextServerExtension::has(RID p_rid) {
+ bool ret;
+ if (GDVIRTUAL_CALL(_has, p_rid, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+bool TextServerExtension::load_support_data(const String &p_filename) {
+ bool ret;
+ if (GDVIRTUAL_CALL(_load_support_data, p_filename, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+String TextServerExtension::get_support_data_filename() const {
+ String ret;
+ if (GDVIRTUAL_CALL(_get_support_data_filename, ret)) {
+ return ret;
+ }
+ return String();
+}
+
+String TextServerExtension::get_support_data_info() const {
+ String ret;
+ if (GDVIRTUAL_CALL(_get_support_data_info, ret)) {
+ return ret;
+ }
+ return String();
+}
+
+bool TextServerExtension::save_support_data(const String &p_filename) const {
+ bool ret;
+ if (GDVIRTUAL_CALL(_save_support_data, p_filename, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+bool TextServerExtension::is_locale_right_to_left(const String &p_locale) const {
+ bool ret;
+ if (GDVIRTUAL_CALL(_is_locale_right_to_left, p_locale, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+int32_t TextServerExtension::name_to_tag(const String &p_name) const {
+ int32_t ret;
+ if (GDVIRTUAL_CALL(_name_to_tag, p_name, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+String TextServerExtension::tag_to_name(int32_t p_tag) const {
+ String ret;
+ if (GDVIRTUAL_CALL(_tag_to_name, p_tag, ret)) {
+ return ret;
+ }
+ return "";
+}
+
+/*************************************************************************/
+/* Font */
+/*************************************************************************/
+
+RID TextServerExtension::create_font() {
+ RID ret;
+ if (GDVIRTUAL_CALL(_create_font, ret)) {
+ return ret;
+ }
+ return RID();
+}
+
+void TextServerExtension::font_set_data(RID p_font_rid, const PackedByteArray &p_data) {
+ GDVIRTUAL_CALL(_font_set_data, p_font_rid, p_data);
+}
+
+void TextServerExtension::font_set_data_ptr(RID p_font_rid, const uint8_t *p_data_ptr, size_t p_data_size) {
+ GDVIRTUAL_CALL(_font_set_data_ptr, p_font_rid, p_data_ptr, p_data_size);
+}
+
+void TextServerExtension::font_set_antialiased(RID p_font_rid, bool p_antialiased) {
+ GDVIRTUAL_CALL(_font_set_antialiased, p_font_rid, p_antialiased);
+}
+
+bool TextServerExtension::font_is_antialiased(RID p_font_rid) const {
+ bool ret;
+ if (GDVIRTUAL_CALL(_font_is_antialiased, p_font_rid, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+void TextServerExtension::font_set_multichannel_signed_distance_field(RID p_font_rid, bool p_msdf) {
+ GDVIRTUAL_CALL(_font_set_multichannel_signed_distance_field, p_font_rid, p_msdf);
+}
+
+bool TextServerExtension::font_is_multichannel_signed_distance_field(RID p_font_rid) const {
+ bool ret;
+ if (GDVIRTUAL_CALL(_font_is_multichannel_signed_distance_field, p_font_rid, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+void TextServerExtension::font_set_msdf_pixel_range(RID p_font_rid, int p_msdf_pixel_range) {
+ GDVIRTUAL_CALL(_font_set_msdf_pixel_range, p_font_rid, p_msdf_pixel_range);
+}
+
+int TextServerExtension::font_get_msdf_pixel_range(RID p_font_rid) const {
+ int ret;
+ if (GDVIRTUAL_CALL(_font_get_msdf_pixel_range, p_font_rid, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+void TextServerExtension::font_set_msdf_size(RID p_font_rid, int p_msdf_size) {
+ GDVIRTUAL_CALL(_font_set_msdf_size, p_font_rid, p_msdf_size);
+}
+
+int TextServerExtension::font_get_msdf_size(RID p_font_rid) const {
+ int ret;
+ if (GDVIRTUAL_CALL(_font_get_msdf_size, p_font_rid, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+void TextServerExtension::font_set_fixed_size(RID p_font_rid, int p_fixed_size) {
+ GDVIRTUAL_CALL(_font_set_fixed_size, p_font_rid, p_fixed_size);
+}
+
+int TextServerExtension::font_get_fixed_size(RID p_font_rid) const {
+ int ret;
+ if (GDVIRTUAL_CALL(_font_get_fixed_size, p_font_rid, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+void TextServerExtension::font_set_force_autohinter(RID p_font_rid, bool p_force_autohinter) {
+ GDVIRTUAL_CALL(_font_set_force_autohinter, p_font_rid, p_force_autohinter);
+}
+
+bool TextServerExtension::font_is_force_autohinter(RID p_font_rid) const {
+ bool ret;
+ if (GDVIRTUAL_CALL(_font_is_force_autohinter, p_font_rid, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+void TextServerExtension::font_set_hinting(RID p_font_rid, TextServer::Hinting p_hinting) {
+ GDVIRTUAL_CALL(_font_set_hinting, p_font_rid, p_hinting);
+}
+
+TextServer::Hinting TextServerExtension::font_get_hinting(RID p_font_rid) const {
+ int ret;
+ if (GDVIRTUAL_CALL(_font_get_hinting, p_font_rid, ret)) {
+ return (TextServer::Hinting)ret;
+ }
+ return TextServer::Hinting::HINTING_NONE;
+}
+
+void TextServerExtension::font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) {
+ GDVIRTUAL_CALL(_font_set_variation_coordinates, p_font_rid, p_variation_coordinates);
+}
+
+Dictionary TextServerExtension::font_get_variation_coordinates(RID p_font_rid) const {
+ Dictionary ret;
+ if (GDVIRTUAL_CALL(_font_get_variation_coordinates, p_font_rid, ret)) {
+ return ret;
+ }
+ return Dictionary();
+}
+
+void TextServerExtension::font_set_oversampling(RID p_font_rid, float p_oversampling) {
+ GDVIRTUAL_CALL(_font_set_oversampling, p_font_rid, p_oversampling);
+}
+
+float TextServerExtension::font_get_oversampling(RID p_font_rid) const {
+ float ret;
+ if (GDVIRTUAL_CALL(_font_get_oversampling, p_font_rid, ret)) {
+ return ret;
+ }
+ return 0.f;
+}
+
+Array TextServerExtension::font_get_size_cache_list(RID p_font_rid) const {
+ Array ret;
+ if (GDVIRTUAL_CALL(_font_get_size_cache_list, p_font_rid, ret)) {
+ return ret;
+ }
+ return Array();
+}
+
+void TextServerExtension::font_clear_size_cache(RID p_font_rid) {
+ GDVIRTUAL_CALL(_font_clear_size_cache, p_font_rid);
+}
+
+void TextServerExtension::font_remove_size_cache(RID p_font_rid, const Vector2i &p_size) {
+ GDVIRTUAL_CALL(_font_remove_size_cache, p_font_rid, p_size);
+}
+
+void TextServerExtension::font_set_ascent(RID p_font_rid, int p_size, float p_ascent) {
+ GDVIRTUAL_CALL(_font_set_ascent, p_font_rid, p_size, p_ascent);
+}
+
+float TextServerExtension::font_get_ascent(RID p_font_rid, int p_size) const {
+ float ret;
+ if (GDVIRTUAL_CALL(_font_get_ascent, p_font_rid, p_size, ret)) {
+ return ret;
+ }
+ return 0.f;
+}
+
+void TextServerExtension::font_set_descent(RID p_font_rid, int p_size, float p_descent) {
+ GDVIRTUAL_CALL(_font_set_descent, p_font_rid, p_size, p_descent);
+}
+
+float TextServerExtension::font_get_descent(RID p_font_rid, int p_size) const {
+ float ret;
+ if (GDVIRTUAL_CALL(_font_get_descent, p_font_rid, p_size, ret)) {
+ return ret;
+ }
+ return 0.f;
+}
+
+void TextServerExtension::font_set_underline_position(RID p_font_rid, int p_size, float p_underline_position) {
+ GDVIRTUAL_CALL(_font_set_underline_position, p_font_rid, p_size, p_underline_position);
+}
+
+float TextServerExtension::font_get_underline_position(RID p_font_rid, int p_size) const {
+ float ret;
+ if (GDVIRTUAL_CALL(_font_get_underline_position, p_font_rid, p_size, ret)) {
+ return ret;
+ }
+ return 0.f;
+}
+
+void TextServerExtension::font_set_underline_thickness(RID p_font_rid, int p_size, float p_underline_thickness) {
+ GDVIRTUAL_CALL(_font_set_underline_thickness, p_font_rid, p_size, p_underline_thickness);
+}
+
+float TextServerExtension::font_get_underline_thickness(RID p_font_rid, int p_size) const {
+ float ret;
+ if (GDVIRTUAL_CALL(_font_get_underline_thickness, p_font_rid, p_size, ret)) {
+ return ret;
+ }
+ return 0.f;
+}
+
+void TextServerExtension::font_set_scale(RID p_font_rid, int p_size, float p_scale) {
+ GDVIRTUAL_CALL(_font_set_scale, p_font_rid, p_size, p_scale);
+}
+
+float TextServerExtension::font_get_scale(RID p_font_rid, int p_size) const {
+ float ret;
+ if (GDVIRTUAL_CALL(_font_get_scale, p_font_rid, p_size, ret)) {
+ return ret;
+ }
+ return 0.f;
+}
+
+void TextServerExtension::font_set_spacing(RID p_font_rid, int p_size, TextServer::SpacingType p_spacing, int p_value) {
+ GDVIRTUAL_CALL(_font_set_spacing, p_font_rid, p_size, p_spacing, p_value);
+}
+
+int TextServerExtension::font_get_spacing(RID p_font_rid, int p_size, TextServer::SpacingType p_spacing) const {
+ int ret;
+ if (GDVIRTUAL_CALL(_font_get_spacing, p_font_rid, p_size, p_spacing, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+int TextServerExtension::font_get_texture_count(RID p_font_rid, const Vector2i &p_size) const {
+ int ret;
+ if (GDVIRTUAL_CALL(_font_get_texture_count, p_font_rid, p_size, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+void TextServerExtension::font_clear_textures(RID p_font_rid, const Vector2i &p_size) {
+ GDVIRTUAL_CALL(_font_clear_textures, p_font_rid, p_size);
+}
+
+void TextServerExtension::font_remove_texture(RID p_font_rid, const Vector2i &p_size, int p_texture_index) {
+ GDVIRTUAL_CALL(_font_remove_texture, p_font_rid, p_size, p_texture_index);
+}
+
+void TextServerExtension::font_set_texture_image(RID p_font_rid, const Vector2i &p_size, int p_texture_index, const Ref<Image> &p_image) {
+ GDVIRTUAL_CALL(_font_set_texture_image, p_font_rid, p_size, p_texture_index, p_image);
+}
+
+Ref<Image> TextServerExtension::font_get_texture_image(RID p_font_rid, const Vector2i &p_size, int p_texture_index) const {
+ Ref<Image> ret;
+ if (GDVIRTUAL_CALL(_font_get_texture_image, p_font_rid, p_size, p_texture_index, ret)) {
+ return ret;
+ }
+ return Ref<Image>();
+}
+
+void TextServerExtension::font_set_texture_offsets(RID p_font_rid, const Vector2i &p_size, int p_texture_index, const PackedInt32Array &p_offset) {
+ GDVIRTUAL_CALL(_font_set_texture_offsets, p_font_rid, p_size, p_texture_index, p_offset);
+}
+
+PackedInt32Array TextServerExtension::font_get_texture_offsets(RID p_font_rid, const Vector2i &p_size, int p_texture_index) const {
+ PackedInt32Array ret;
+ if (GDVIRTUAL_CALL(_font_get_texture_offsets, p_font_rid, p_size, p_texture_index, ret)) {
+ return ret;
+ }
+ return PackedInt32Array();
+}
+
+Array TextServerExtension::font_get_glyph_list(RID p_font_rid, const Vector2i &p_size) const {
+ Array ret;
+ if (GDVIRTUAL_CALL(_font_get_glyph_list, p_font_rid, p_size, ret)) {
+ return ret;
+ }
+ return Array();
+}
+
+void TextServerExtension::font_clear_glyphs(RID p_font_rid, const Vector2i &p_size) {
+ GDVIRTUAL_CALL(_font_clear_glyphs, p_font_rid, p_size);
+}
+
+void TextServerExtension::font_remove_glyph(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) {
+ GDVIRTUAL_CALL(_font_remove_glyph, p_font_rid, p_size, p_glyph);
+}
+
+Vector2 TextServerExtension::font_get_glyph_advance(RID p_font_rid, int p_size, int32_t p_glyph) const {
+ Vector2 ret;
+ if (GDVIRTUAL_CALL(_font_get_glyph_advance, p_font_rid, p_size, p_glyph, ret)) {
+ return ret;
+ }
+ return Vector2();
+}
+
+void TextServerExtension::font_set_glyph_advance(RID p_font_rid, int p_size, int32_t p_glyph, const Vector2 &p_advance) {
+ GDVIRTUAL_CALL(_font_set_glyph_advance, p_font_rid, p_size, p_glyph, p_advance);
+}
+
+Vector2 TextServerExtension::font_get_glyph_offset(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const {
+ Vector2 ret;
+ if (GDVIRTUAL_CALL(_font_get_glyph_offset, p_font_rid, p_size, p_glyph, ret)) {
+ return ret;
+ }
+ return Vector2();
+}
+
+void TextServerExtension::font_set_glyph_offset(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, const Vector2 &p_offset) {
+ GDVIRTUAL_CALL(_font_set_glyph_offset, p_font_rid, p_size, p_glyph, p_offset);
+}
+
+Vector2 TextServerExtension::font_get_glyph_size(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const {
+ Vector2 ret;
+ if (GDVIRTUAL_CALL(_font_get_glyph_size, p_font_rid, p_size, p_glyph, ret)) {
+ return ret;
+ }
+ return Vector2();
+}
+
+void TextServerExtension::font_set_glyph_size(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, const Vector2 &p_gl_size) {
+ GDVIRTUAL_CALL(_font_set_glyph_size, p_font_rid, p_size, p_glyph, p_gl_size);
+}
+
+Rect2 TextServerExtension::font_get_glyph_uv_rect(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const {
+ Rect2 ret;
+ if (GDVIRTUAL_CALL(_font_get_glyph_uv_rect, p_font_rid, p_size, p_glyph, ret)) {
+ return ret;
+ }
+ return Rect2();
+}
+
+void TextServerExtension::font_set_glyph_uv_rect(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, const Rect2 &p_uv_rect) {
+ GDVIRTUAL_CALL(_font_set_glyph_uv_rect, p_font_rid, p_size, p_glyph, p_uv_rect);
+}
+
+int TextServerExtension::font_get_glyph_texture_idx(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const {
+ int ret;
+ if (GDVIRTUAL_CALL(_font_get_glyph_texture_idx, p_font_rid, p_size, p_glyph, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+void TextServerExtension::font_set_glyph_texture_idx(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, int p_texture_idx) {
+ GDVIRTUAL_CALL(_font_set_glyph_texture_idx, p_font_rid, p_size, p_glyph, p_texture_idx);
+}
+
+Dictionary TextServerExtension::font_get_glyph_contours(RID p_font_rid, int p_size, int32_t p_index) const {
+ Dictionary ret;
+ if (GDVIRTUAL_CALL(_font_get_glyph_contours, p_font_rid, p_size, p_index, ret)) {
+ return ret;
+ }
+ return Dictionary();
+}
+
+Array TextServerExtension::font_get_kerning_list(RID p_font_rid, int p_size) const {
+ Array ret;
+ if (GDVIRTUAL_CALL(_font_get_kerning_list, p_font_rid, p_size, ret)) {
+ return ret;
+ }
+ return Array();
+}
+
+void TextServerExtension::font_clear_kerning_map(RID p_font_rid, int p_size) {
+ GDVIRTUAL_CALL(_font_clear_kerning_map, p_font_rid, p_size);
+}
+
+void TextServerExtension::font_remove_kerning(RID p_font_rid, int p_size, const Vector2i &p_glyph_pair) {
+ GDVIRTUAL_CALL(_font_remove_kerning, p_font_rid, p_size, p_glyph_pair);
+}
+
+void TextServerExtension::font_set_kerning(RID p_font_rid, int p_size, const Vector2i &p_glyph_pair, const Vector2 &p_kerning) {
+ GDVIRTUAL_CALL(_font_set_kerning, p_font_rid, p_size, p_glyph_pair, p_kerning);
+}
+
+Vector2 TextServerExtension::font_get_kerning(RID p_font_rid, int p_size, const Vector2i &p_glyph_pair) const {
+ Vector2 ret;
+ if (GDVIRTUAL_CALL(_font_get_kerning, p_font_rid, p_size, p_glyph_pair, ret)) {
+ return ret;
+ }
+ return Vector2();
+}
+
+int32_t TextServerExtension::font_get_glyph_index(RID p_font_rid, int p_size, char32_t p_char, char32_t p_variation_selector) const {
+ int32_t ret;
+ if (GDVIRTUAL_CALL(_font_get_glyph_index, p_font_rid, p_size, p_char, p_variation_selector, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+bool TextServerExtension::font_has_char(RID p_font_rid, char32_t p_char) const {
+ bool ret;
+ if (GDVIRTUAL_CALL(_font_has_char, p_font_rid, p_char, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+String TextServerExtension::font_get_supported_chars(RID p_font_rid) const {
+ String ret;
+ if (GDVIRTUAL_CALL(_font_get_supported_chars, p_font_rid, ret)) {
+ return ret;
+ }
+ return String();
+}
+
+void TextServerExtension::font_render_range(RID p_font_rid, const Vector2i &p_size, char32_t p_start, char32_t p_end) {
+ GDVIRTUAL_CALL(_font_render_range, p_font_rid, p_size, p_start, p_end);
+}
+
+void TextServerExtension::font_render_glyph(RID p_font_rid, const Vector2i &p_size, int32_t p_index) {
+ GDVIRTUAL_CALL(_font_render_glyph, p_font_rid, p_size, p_index);
+}
+
+void TextServerExtension::font_draw_glyph(RID p_font_rid, RID p_canvas, int p_size, const Vector2 &p_pos, int32_t p_index, const Color &p_color) const {
+ GDVIRTUAL_CALL(_font_draw_glyph, p_font_rid, p_canvas, p_size, p_pos, p_index, p_color);
+}
+
+void TextServerExtension::font_draw_glyph_outline(RID p_font_rid, RID p_canvas, int p_size, int p_outline_size, const Vector2 &p_pos, int32_t p_index, const Color &p_color) const {
+ GDVIRTUAL_CALL(_font_draw_glyph_outline, p_font_rid, p_canvas, p_size, p_outline_size, p_pos, p_index, p_color);
+}
+
+bool TextServerExtension::font_is_language_supported(RID p_font_rid, const String &p_language) const {
+ bool ret;
+ if (GDVIRTUAL_CALL(_font_is_language_supported, p_font_rid, p_language, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+void TextServerExtension::font_set_language_support_override(RID p_font_rid, const String &p_language, bool p_supported) {
+ GDVIRTUAL_CALL(_font_set_language_support_override, p_font_rid, p_language, p_supported);
+}
+
+bool TextServerExtension::font_get_language_support_override(RID p_font_rid, const String &p_language) {
+ bool ret;
+ if (GDVIRTUAL_CALL(_font_get_language_support_override, p_font_rid, p_language, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+void TextServerExtension::font_remove_language_support_override(RID p_font_rid, const String &p_language) {
+ GDVIRTUAL_CALL(_font_remove_language_support_override, p_font_rid, p_language);
+}
+
+Vector<String> TextServerExtension::font_get_language_support_overrides(RID p_font_rid) {
+ Vector<String> ret;
+ if (GDVIRTUAL_CALL(_font_get_language_support_overrides, p_font_rid, ret)) {
+ return ret;
+ }
+ return Vector<String>();
+}
+
+bool TextServerExtension::font_is_script_supported(RID p_font_rid, const String &p_script) const {
+ bool ret;
+ if (GDVIRTUAL_CALL(_font_is_script_supported, p_font_rid, p_script, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+void TextServerExtension::font_set_script_support_override(RID p_font_rid, const String &p_script, bool p_supported) {
+ GDVIRTUAL_CALL(_font_set_script_support_override, p_font_rid, p_script, p_supported);
+}
+
+bool TextServerExtension::font_get_script_support_override(RID p_font_rid, const String &p_script) {
+ bool ret;
+ if (GDVIRTUAL_CALL(_font_get_script_support_override, p_font_rid, p_script, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+void TextServerExtension::font_remove_script_support_override(RID p_font_rid, const String &p_script) {
+ GDVIRTUAL_CALL(_font_remove_script_support_override, p_font_rid, p_script);
+}
+
+Vector<String> TextServerExtension::font_get_script_support_overrides(RID p_font_rid) {
+ Vector<String> ret;
+ if (GDVIRTUAL_CALL(_font_get_script_support_overrides, p_font_rid, ret)) {
+ return ret;
+ }
+ return Vector<String>();
+}
+
+Dictionary TextServerExtension::font_supported_feature_list(RID p_font_rid) const {
+ Dictionary ret;
+ if (GDVIRTUAL_CALL(_font_supported_feature_list, p_font_rid, ret)) {
+ return ret;
+ }
+ return Dictionary();
+}
+
+Dictionary TextServerExtension::font_supported_variation_list(RID p_font_rid) const {
+ Dictionary ret;
+ if (GDVIRTUAL_CALL(_font_supported_variation_list, p_font_rid, ret)) {
+ return ret;
+ }
+ return Dictionary();
+}
+
+float TextServerExtension::font_get_global_oversampling() const {
+ float ret;
+ if (GDVIRTUAL_CALL(_font_get_global_oversampling, ret)) {
+ return ret;
+ }
+ return 0.f;
+}
+
+void TextServerExtension::font_set_global_oversampling(float p_oversampling) {
+ GDVIRTUAL_CALL(_font_set_global_oversampling, p_oversampling);
+}
+
+Vector2 TextServerExtension::get_hex_code_box_size(int p_size, char32_t p_index) const {
+ Vector2 ret;
+ if (GDVIRTUAL_CALL(_get_hex_code_box_size, p_size, p_index, ret)) {
+ return ret;
+ }
+ return TextServer::get_hex_code_box_size(p_size, p_index);
+}
+
+void TextServerExtension::draw_hex_code_box(RID p_canvas, int p_size, const Vector2 &p_pos, char32_t p_index, const Color &p_color) const {
+ if (!GDVIRTUAL_CALL(_draw_hex_code_box, p_canvas, p_size, p_pos, p_index, p_color)) {
+ TextServer::draw_hex_code_box(p_canvas, p_size, p_pos, p_index, p_color);
+ }
+}
+
+/*************************************************************************/
+/* Shaped text buffer interface */
+/*************************************************************************/
+
+RID TextServerExtension::create_shaped_text(TextServer::Direction p_direction, TextServer::Orientation p_orientation) {
+ RID ret;
+ if (GDVIRTUAL_CALL(_create_shaped_text, p_direction, p_orientation, ret)) {
+ return ret;
+ }
+ return RID();
+}
+
+void TextServerExtension::shaped_text_clear(RID p_shaped) {
+ GDVIRTUAL_CALL(_shaped_text_clear, p_shaped);
+}
+
+void TextServerExtension::shaped_text_set_direction(RID p_shaped, TextServer::Direction p_direction) {
+ GDVIRTUAL_CALL(_shaped_text_set_direction, p_shaped, p_direction);
+}
+
+TextServer::Direction TextServerExtension::shaped_text_get_direction(RID p_shaped) const {
+ int ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_direction, p_shaped, ret)) {
+ return (TextServer::Direction)ret;
+ }
+ return TextServer::Direction::DIRECTION_AUTO;
+}
+
+void TextServerExtension::shaped_text_set_orientation(RID p_shaped, TextServer::Orientation p_orientation) {
+ GDVIRTUAL_CALL(_shaped_text_set_orientation, p_shaped, p_orientation);
+}
+
+TextServer::Orientation TextServerExtension::shaped_text_get_orientation(RID p_shaped) const {
+ int ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_orientation, p_shaped, ret)) {
+ return (TextServer::Orientation)ret;
+ }
+ return TextServer::Orientation::ORIENTATION_HORIZONTAL;
+}
+
+void TextServerExtension::shaped_text_set_bidi_override(RID p_shaped, const Array &p_override) {
+ GDVIRTUAL_CALL(_shaped_text_set_bidi_override, p_shaped, p_override);
+}
+
+void TextServerExtension::shaped_text_set_preserve_invalid(RID p_shaped, bool p_enabled) {
+ GDVIRTUAL_CALL(_shaped_text_set_preserve_invalid, p_shaped, p_enabled);
+}
+
+bool TextServerExtension::shaped_text_get_preserve_invalid(RID p_shaped) const {
+ bool ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_preserve_invalid, p_shaped, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+void TextServerExtension::shaped_text_set_preserve_control(RID p_shaped, bool p_enabled) {
+ GDVIRTUAL_CALL(_shaped_text_set_preserve_control, p_shaped, p_enabled);
+}
+
+bool TextServerExtension::shaped_text_get_preserve_control(RID p_shaped) const {
+ bool ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_preserve_control, p_shaped, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+bool TextServerExtension::shaped_text_add_string(RID p_shaped, const String &p_text, const Vector<RID> &p_fonts, int p_size, const Dictionary &p_opentype_features, const String &p_language) {
+ bool ret;
+ Array fonts;
+ for (int i = 0; i < p_fonts.size(); i++) {
+ fonts.push_back(p_fonts[i]);
+ }
+ if (GDVIRTUAL_CALL(_shaped_text_add_string, p_shaped, p_text, fonts, p_size, p_opentype_features, p_language, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+bool TextServerExtension::shaped_text_add_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlign p_inline_align, int p_length) {
+ bool ret;
+ if (GDVIRTUAL_CALL(_shaped_text_add_object, p_shaped, p_key, p_size, p_inline_align, p_length, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+bool TextServerExtension::shaped_text_resize_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlign p_inline_align) {
+ bool ret;
+ if (GDVIRTUAL_CALL(_shaped_text_resize_object, p_shaped, p_key, p_size, p_inline_align, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+RID TextServerExtension::shaped_text_substr(RID p_shaped, int p_start, int p_length) const {
+ RID ret;
+ if (GDVIRTUAL_CALL(_shaped_text_substr, p_shaped, p_start, p_length, ret)) {
+ return ret;
+ }
+ return RID();
+}
+
+RID TextServerExtension::shaped_text_get_parent(RID p_shaped) const {
+ RID ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_parent, p_shaped, ret)) {
+ return ret;
+ }
+ return RID();
+}
+
+float TextServerExtension::shaped_text_fit_to_width(RID p_shaped, float p_width, uint16_t p_jst_flags) {
+ float ret;
+ if (GDVIRTUAL_CALL(_shaped_text_fit_to_width, p_shaped, p_width, p_jst_flags, ret)) {
+ return ret;
+ }
+ return 0.f;
+}
+
+float TextServerExtension::shaped_text_tab_align(RID p_shaped, const PackedFloat32Array &p_tab_stops) {
+ float ret;
+ if (GDVIRTUAL_CALL(_shaped_text_tab_align, p_shaped, p_tab_stops, ret)) {
+ return ret;
+ }
+ return 0.f;
+}
+
+bool TextServerExtension::shaped_text_shape(RID p_shaped) {
+ bool ret;
+ if (GDVIRTUAL_CALL(_shaped_text_shape, p_shaped, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+bool TextServerExtension::shaped_text_update_breaks(RID p_shaped) {
+ bool ret;
+ if (GDVIRTUAL_CALL(_shaped_text_update_breaks, p_shaped, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+bool TextServerExtension::shaped_text_update_justification_ops(RID p_shaped) {
+ bool ret;
+ if (GDVIRTUAL_CALL(_shaped_text_update_justification_ops, p_shaped, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+bool TextServerExtension::shaped_text_is_ready(RID p_shaped) const {
+ bool ret;
+ if (GDVIRTUAL_CALL(_shaped_text_is_ready, p_shaped, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+const Glyph *TextServerExtension::shaped_text_get_glyphs(RID p_shaped) const {
+ const Glyph *ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_glyphs, p_shaped, &ret)) {
+ return ret;
+ }
+ return nullptr;
+}
+
+const Glyph *TextServerExtension::shaped_text_sort_logical(RID p_shaped) {
+ const Glyph *ret;
+ if (GDVIRTUAL_CALL(_shaped_text_sort_logical, p_shaped, &ret)) {
+ return ret;
+ }
+ return nullptr;
+}
+
+int TextServerExtension::shaped_text_get_glyph_count(RID p_shaped) const {
+ int ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_glyph_count, p_shaped, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+Vector2i TextServerExtension::shaped_text_get_range(RID p_shaped) const {
+ Vector2i ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_range, p_shaped, ret)) {
+ return ret;
+ }
+ return Vector2i();
+}
+
+PackedInt32Array TextServerExtension::shaped_text_get_line_breaks_adv(RID p_shaped, const PackedFloat32Array &p_width, int p_start, bool p_once, uint16_t p_break_flags) const {
+ PackedInt32Array ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_line_breaks_adv, p_shaped, p_width, p_start, p_once, p_break_flags, ret)) {
+ return ret;
+ }
+ return TextServer::shaped_text_get_line_breaks_adv(p_shaped, p_width, p_start, p_once, p_break_flags);
+}
+
+PackedInt32Array TextServerExtension::shaped_text_get_line_breaks(RID p_shaped, float p_width, int p_start, uint16_t p_break_flags) const {
+ PackedInt32Array ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_line_breaks, p_shaped, p_width, p_start, p_break_flags, ret)) {
+ return ret;
+ }
+ return TextServer::shaped_text_get_line_breaks(p_shaped, p_width, p_start, p_break_flags);
+}
+
+PackedInt32Array TextServerExtension::shaped_text_get_word_breaks(RID p_shaped, int p_grapheme_flags) const {
+ PackedInt32Array ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_word_breaks, p_shaped, p_grapheme_flags, ret)) {
+ return ret;
+ }
+ return TextServer::shaped_text_get_word_breaks(p_shaped, p_grapheme_flags);
+}
+
+int TextServerExtension::shaped_text_get_trim_pos(RID p_shaped) const {
+ int ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_trim_pos, p_shaped, ret)) {
+ return ret;
+ }
+ return -1;
+}
+
+int TextServerExtension::shaped_text_get_ellipsis_pos(RID p_shaped) const {
+ int ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_ellipsis_pos, p_shaped, ret)) {
+ return ret;
+ }
+ return -1;
+}
+
+const Glyph *TextServerExtension::shaped_text_get_ellipsis_glyphs(RID p_shaped) const {
+ const Glyph *ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_ellipsis_glyphs, p_shaped, &ret)) {
+ return ret;
+ }
+ return nullptr;
+}
+
+int TextServerExtension::shaped_text_get_ellipsis_glyph_count(RID p_shaped) const {
+ int ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_ellipsis_glyph_count, p_shaped, ret)) {
+ return ret;
+ }
+ return -1;
+}
+
+void TextServerExtension::shaped_text_overrun_trim_to_width(RID p_shaped_line, float p_width, uint16_t p_trim_flags) {
+ GDVIRTUAL_CALL(_shaped_text_overrun_trim_to_width, p_shaped_line, p_width, p_trim_flags);
+}
+
+Array TextServerExtension::shaped_text_get_objects(RID p_shaped) const {
+ Array ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_objects, p_shaped, ret)) {
+ return ret;
+ }
+ return Array();
+}
+
+Rect2 TextServerExtension::shaped_text_get_object_rect(RID p_shaped, Variant p_key) const {
+ Rect2 ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_object_rect, p_shaped, p_key, ret)) {
+ return ret;
+ }
+ return Rect2();
+}
+
+Size2 TextServerExtension::shaped_text_get_size(RID p_shaped) const {
+ Size2 ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_size, p_shaped, ret)) {
+ return ret;
+ }
+ return Size2();
+}
+
+float TextServerExtension::shaped_text_get_ascent(RID p_shaped) const {
+ float ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_ascent, p_shaped, ret)) {
+ return ret;
+ }
+ return 0.f;
+}
+
+float TextServerExtension::shaped_text_get_descent(RID p_shaped) const {
+ float ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_descent, p_shaped, ret)) {
+ return ret;
+ }
+ return 0.f;
+}
+
+float TextServerExtension::shaped_text_get_width(RID p_shaped) const {
+ float ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_width, p_shaped, ret)) {
+ return ret;
+ }
+ return 0.f;
+}
+
+float TextServerExtension::shaped_text_get_underline_position(RID p_shaped) const {
+ float ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_underline_position, p_shaped, ret)) {
+ return ret;
+ }
+ return 0.f;
+}
+
+float TextServerExtension::shaped_text_get_underline_thickness(RID p_shaped) const {
+ float ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_underline_thickness, p_shaped, ret)) {
+ return ret;
+ }
+ return 0.f;
+}
+
+TextServer::Direction TextServerExtension::shaped_text_get_dominant_direction_in_range(RID p_shaped, int p_start, int p_end) const {
+ int ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_dominant_direction_in_range, p_shaped, p_start, p_end, ret)) {
+ return (TextServer::Direction)ret;
+ }
+ return TextServer::shaped_text_get_dominant_direction_in_range(p_shaped, p_start, p_end);
+}
+
+CaretInfo TextServerExtension::shaped_text_get_carets(RID p_shaped, int p_position) const {
+ CaretInfo ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_carets, p_shaped, p_position, &ret)) {
+ return ret;
+ }
+ return TextServer::shaped_text_get_carets(p_shaped, p_position);
+}
+
+Vector<Vector2> TextServerExtension::shaped_text_get_selection(RID p_shaped, int p_start, int p_end) const {
+ Vector<Vector2> ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_selection, p_shaped, p_start, p_end, ret)) {
+ return ret;
+ }
+ return TextServer::shaped_text_get_selection(p_shaped, p_start, p_end);
+}
+
+int TextServerExtension::shaped_text_hit_test_grapheme(RID p_shaped, float p_coords) const {
+ int ret;
+ if (GDVIRTUAL_CALL(_shaped_text_hit_test_grapheme, p_shaped, p_coords, ret)) {
+ return ret;
+ }
+ return TextServer::shaped_text_hit_test_grapheme(p_shaped, p_coords);
+}
+
+int TextServerExtension::shaped_text_hit_test_position(RID p_shaped, float p_coords) const {
+ int ret;
+ if (GDVIRTUAL_CALL(_shaped_text_hit_test_position, p_shaped, p_coords, ret)) {
+ return ret;
+ }
+ return TextServer::shaped_text_hit_test_position(p_shaped, p_coords);
+}
+
+void TextServerExtension::shaped_text_draw(RID p_shaped, RID p_canvas, const Vector2 &p_pos, float p_clip_l, float p_clip_r, const Color &p_color) const {
+ if (GDVIRTUAL_CALL(_shaped_text_draw, p_shaped, p_canvas, p_pos, p_clip_l, p_clip_r, p_color)) {
+ return;
+ }
+ TextServer::shaped_text_draw(p_shaped, p_canvas, p_pos, p_clip_l, p_clip_r, p_color);
+}
+
+void TextServerExtension::shaped_text_draw_outline(RID p_shaped, RID p_canvas, const Vector2 &p_pos, float p_clip_l, float p_clip_r, int p_outline_size, const Color &p_color) const {
+ if (GDVIRTUAL_CALL(_shaped_text_draw_outline, p_shaped, p_canvas, p_pos, p_clip_l, p_clip_r, p_outline_size, p_color)) {
+ return;
+ }
+ shaped_text_draw_outline(p_shaped, p_canvas, p_pos, p_clip_l, p_clip_r, p_outline_size, p_color);
+}
+
+int TextServerExtension::shaped_text_next_grapheme_pos(RID p_shaped, int p_pos) const {
+ int ret;
+ if (GDVIRTUAL_CALL(_shaped_text_next_grapheme_pos, p_shaped, p_pos, ret)) {
+ return ret;
+ }
+ return TextServer::shaped_text_next_grapheme_pos(p_shaped, p_pos);
+}
+
+int TextServerExtension::shaped_text_prev_grapheme_pos(RID p_shaped, int p_pos) const {
+ int ret;
+ if (GDVIRTUAL_CALL(_shaped_text_prev_grapheme_pos, p_shaped, p_pos, ret)) {
+ return ret;
+ }
+ return TextServer::shaped_text_prev_grapheme_pos(p_shaped, p_pos);
+}
+
+String TextServerExtension::format_number(const String &p_string, const String &p_language) const {
+ String ret;
+ if (GDVIRTUAL_CALL(_format_number, p_string, p_language, ret)) {
+ return ret;
+ }
+ return TextServer::format_number(p_string, p_language);
+}
+
+String TextServerExtension::parse_number(const String &p_string, const String &p_language) const {
+ String ret;
+ if (GDVIRTUAL_CALL(_parse_number, p_string, p_language, ret)) {
+ return ret;
+ }
+ return TextServer::parse_number(p_string, p_language);
+}
+
+String TextServerExtension::percent_sign(const String &p_language) const {
+ String ret;
+ if (GDVIRTUAL_CALL(_percent_sign, p_language, ret)) {
+ return ret;
+ }
+ return TextServer::percent_sign(p_language);
+}
+
+TextServerExtension::TextServerExtension() {
+ //NOP
+}
+
+TextServerExtension::~TextServerExtension() {
+ //NOP
+}
diff --git a/servers/text/text_server_extension.h b/servers/text/text_server_extension.h
new file mode 100644
index 0000000000..954b2cf660
--- /dev/null
+++ b/servers/text/text_server_extension.h
@@ -0,0 +1,427 @@
+/*************************************************************************/
+/* text_server_extension.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 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 TEXT_SERVER_EXTENSION_H
+#define TEXT_SERVER_EXTENSION_H
+
+#include "core/object/gdvirtual.gen.inc"
+#include "core/object/script_language.h"
+#include "core/os/thread_safe.h"
+#include "core/variant/native_ptr.h"
+#include "servers/text_server.h"
+
+class TextServerExtension : public TextServer {
+ GDCLASS(TextServerExtension, TextServer);
+
+protected:
+ _THREAD_SAFE_CLASS_
+
+ static void _bind_methods();
+
+public:
+ virtual bool has_feature(Feature p_feature) const override;
+ virtual String get_name() const override;
+ virtual uint32_t get_features() const override;
+ GDVIRTUAL1RC(bool, _has_feature, Feature);
+ GDVIRTUAL0RC(String, _get_name);
+ GDVIRTUAL0RC(uint32_t, _get_features);
+
+ virtual void free(RID p_rid) override;
+ virtual bool has(RID p_rid) override;
+ virtual bool load_support_data(const String &p_filename) override;
+ GDVIRTUAL1(_free, RID);
+ GDVIRTUAL1R(bool, _has, RID);
+ GDVIRTUAL1R(bool, _load_support_data, const String &);
+
+ virtual String get_support_data_filename() const override;
+ virtual String get_support_data_info() const override;
+ virtual bool save_support_data(const String &p_filename) const override;
+ GDVIRTUAL0RC(String, _get_support_data_filename);
+ GDVIRTUAL0RC(String, _get_support_data_info);
+ GDVIRTUAL1RC(bool, _save_support_data, const String &);
+
+ virtual bool is_locale_right_to_left(const String &p_locale) const override;
+ GDVIRTUAL1RC(bool, _is_locale_right_to_left, const String &);
+
+ virtual int32_t name_to_tag(const String &p_name) const override;
+ virtual String tag_to_name(int32_t p_tag) const override;
+ GDVIRTUAL1RC(int32_t, _name_to_tag, const String &);
+ GDVIRTUAL1RC(String, _tag_to_name, int32_t);
+
+ /* Font interface */
+ virtual RID create_font() override;
+ GDVIRTUAL0R(RID, _create_font);
+
+ virtual void font_set_data(RID p_font_rid, const PackedByteArray &p_data) override;
+ virtual void font_set_data_ptr(RID p_font_rid, const uint8_t *p_data_ptr, size_t p_data_size) override;
+ GDVIRTUAL2(_font_set_data, RID, const PackedByteArray &);
+ GDVIRTUAL3(_font_set_data_ptr, RID, GDNativeConstPtr<const uint8_t>, uint64_t);
+
+ virtual void font_set_antialiased(RID p_font_rid, bool p_antialiased) override;
+ virtual bool font_is_antialiased(RID p_font_rid) const override;
+ GDVIRTUAL2(_font_set_antialiased, RID, bool);
+ GDVIRTUAL1RC(bool, _font_is_antialiased, RID);
+
+ virtual void font_set_multichannel_signed_distance_field(RID p_font_rid, bool p_msdf) override;
+ virtual bool font_is_multichannel_signed_distance_field(RID p_font_rid) const override;
+ GDVIRTUAL2(_font_set_multichannel_signed_distance_field, RID, bool);
+ GDVIRTUAL1RC(bool, _font_is_multichannel_signed_distance_field, RID);
+
+ virtual void font_set_msdf_pixel_range(RID p_font_rid, int p_msdf_pixel_range) override;
+ virtual int font_get_msdf_pixel_range(RID p_font_rid) const override;
+ GDVIRTUAL2(_font_set_msdf_pixel_range, RID, int);
+ GDVIRTUAL1RC(int, _font_get_msdf_pixel_range, RID);
+
+ virtual void font_set_msdf_size(RID p_font_rid, int p_msdf_size) override;
+ virtual int font_get_msdf_size(RID p_font_rid) const override;
+ GDVIRTUAL2(_font_set_msdf_size, RID, int);
+ GDVIRTUAL1RC(int, _font_get_msdf_size, RID);
+
+ virtual void font_set_fixed_size(RID p_font_rid, int p_fixed_size) override;
+ virtual int font_get_fixed_size(RID p_font_rid) const override;
+ GDVIRTUAL2(_font_set_fixed_size, RID, int);
+ GDVIRTUAL1RC(int, _font_get_fixed_size, RID);
+
+ virtual void font_set_force_autohinter(RID p_font_rid, bool p_force_autohinter) override;
+ virtual bool font_is_force_autohinter(RID p_font_rid) const override;
+ GDVIRTUAL2(_font_set_force_autohinter, RID, bool);
+ GDVIRTUAL1RC(bool, _font_is_force_autohinter, RID);
+
+ virtual void font_set_hinting(RID p_font_rid, Hinting p_hinting) override;
+ virtual Hinting font_get_hinting(RID p_font_rid) const override;
+ GDVIRTUAL2(_font_set_hinting, RID, Hinting);
+ GDVIRTUAL1RC(/*Hinting*/ int, _font_get_hinting, RID);
+
+ virtual void font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) override;
+ virtual Dictionary font_get_variation_coordinates(RID p_font_rid) const override;
+ GDVIRTUAL2(_font_set_variation_coordinates, RID, Dictionary);
+ GDVIRTUAL1RC(Dictionary, _font_get_variation_coordinates, RID);
+
+ virtual void font_set_oversampling(RID p_font_rid, float p_oversampling) override;
+ virtual float font_get_oversampling(RID p_font_rid) const override;
+ GDVIRTUAL2(_font_set_oversampling, RID, float);
+ GDVIRTUAL1RC(float, _font_get_oversampling, RID);
+
+ virtual Array font_get_size_cache_list(RID p_font_rid) const override;
+ virtual void font_clear_size_cache(RID p_font_rid) override;
+ virtual void font_remove_size_cache(RID p_font_rid, const Vector2i &p_size) override;
+ GDVIRTUAL1RC(Array, _font_get_size_cache_list, RID);
+ GDVIRTUAL1(_font_clear_size_cache, RID);
+ GDVIRTUAL2(_font_remove_size_cache, RID, const Vector2i &);
+
+ virtual void font_set_ascent(RID p_font_rid, int p_size, float p_ascent) override;
+ virtual float font_get_ascent(RID p_font_rid, int p_size) const override;
+ GDVIRTUAL3(_font_set_ascent, RID, int, float);
+ GDVIRTUAL2RC(float, _font_get_ascent, RID, int);
+
+ virtual void font_set_descent(RID p_font_rid, int p_size, float p_descent) override;
+ virtual float font_get_descent(RID p_font_rid, int p_size) const override;
+ GDVIRTUAL3(_font_set_descent, RID, int, float);
+ GDVIRTUAL2RC(float, _font_get_descent, RID, int);
+
+ virtual void font_set_underline_position(RID p_font_rid, int p_size, float p_underline_position) override;
+ virtual float font_get_underline_position(RID p_font_rid, int p_size) const override;
+ GDVIRTUAL3(_font_set_underline_position, RID, int, float);
+ GDVIRTUAL2RC(float, _font_get_underline_position, RID, int);
+
+ virtual void font_set_underline_thickness(RID p_font_rid, int p_size, float p_underline_thickness) override;
+ virtual float font_get_underline_thickness(RID p_font_rid, int p_size) const override;
+ GDVIRTUAL3(_font_set_underline_thickness, RID, int, float);
+ GDVIRTUAL2RC(float, _font_get_underline_thickness, RID, int);
+
+ virtual void font_set_scale(RID p_font_rid, int p_size, float p_scale) override;
+ virtual float font_get_scale(RID p_font_rid, int p_size) const override;
+ GDVIRTUAL3(_font_set_scale, RID, int, float);
+ GDVIRTUAL2RC(float, _font_get_scale, RID, int);
+
+ virtual void font_set_spacing(RID p_font_rid, int p_size, SpacingType p_spacing, int p_value) override;
+ virtual int font_get_spacing(RID p_font_rid, int p_size, SpacingType p_spacing) const override;
+ GDVIRTUAL4(_font_set_spacing, RID, int, SpacingType, int);
+ GDVIRTUAL3RC(int, _font_get_spacing, RID, int, SpacingType);
+
+ virtual int font_get_texture_count(RID p_font_rid, const Vector2i &p_size) const override;
+ virtual void font_clear_textures(RID p_font_rid, const Vector2i &p_size) override;
+ virtual void font_remove_texture(RID p_font_rid, const Vector2i &p_size, int p_texture_index) override;
+ GDVIRTUAL2RC(int, _font_get_texture_count, RID, const Vector2i &);
+ GDVIRTUAL2(_font_clear_textures, RID, const Vector2i &);
+ GDVIRTUAL3(_font_remove_texture, RID, const Vector2i &, int);
+
+ virtual void font_set_texture_image(RID p_font_rid, const Vector2i &p_size, int p_texture_index, const Ref<Image> &p_image) override;
+ virtual Ref<Image> font_get_texture_image(RID p_font_rid, const Vector2i &p_size, int p_texture_index) const override;
+ GDVIRTUAL4(_font_set_texture_image, RID, const Vector2i &, int, const Ref<Image> &);
+ GDVIRTUAL3RC(Ref<Image>, _font_get_texture_image, RID, const Vector2i &, int);
+
+ virtual void font_set_texture_offsets(RID p_font_rid, const Vector2i &p_size, int p_texture_index, const PackedInt32Array &p_offset) override;
+ virtual PackedInt32Array font_get_texture_offsets(RID p_font_rid, const Vector2i &p_size, int p_texture_index) const override;
+ GDVIRTUAL4(_font_set_texture_offsets, RID, const Vector2i &, int, const PackedInt32Array &);
+ GDVIRTUAL3RC(PackedInt32Array, _font_get_texture_offsets, RID, const Vector2i &, int);
+
+ virtual Array font_get_glyph_list(RID p_font_rid, const Vector2i &p_size) const override;
+ virtual void font_clear_glyphs(RID p_font_rid, const Vector2i &p_size) override;
+ virtual void font_remove_glyph(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) override;
+ GDVIRTUAL2RC(Array, _font_get_glyph_list, RID, const Vector2i &);
+ GDVIRTUAL2(_font_clear_glyphs, RID, const Vector2i &);
+ GDVIRTUAL3(_font_remove_glyph, RID, const Vector2i &, int32_t);
+
+ virtual Vector2 font_get_glyph_advance(RID p_font_rid, int p_size, int32_t p_glyph) const override;
+ virtual void font_set_glyph_advance(RID p_font_rid, int p_size, int32_t p_glyph, const Vector2 &p_advance) override;
+ GDVIRTUAL3RC(Vector2, _font_get_glyph_advance, RID, int, int32_t);
+ GDVIRTUAL4(_font_set_glyph_advance, RID, int, int32_t, const Vector2 &);
+
+ virtual Vector2 font_get_glyph_offset(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const override;
+ virtual void font_set_glyph_offset(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, const Vector2 &p_offset) override;
+ GDVIRTUAL3RC(Vector2, _font_get_glyph_offset, RID, const Vector2i &, int32_t);
+ GDVIRTUAL4(_font_set_glyph_offset, RID, const Vector2i &, int32_t, const Vector2 &);
+
+ virtual Vector2 font_get_glyph_size(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const override;
+ virtual void font_set_glyph_size(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, const Vector2 &p_gl_size) override;
+ GDVIRTUAL3RC(Vector2, _font_get_glyph_size, RID, const Vector2i &, int32_t);
+ GDVIRTUAL4(_font_set_glyph_size, RID, const Vector2i &, int32_t, const Vector2 &);
+
+ virtual Rect2 font_get_glyph_uv_rect(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const override;
+ virtual void font_set_glyph_uv_rect(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, const Rect2 &p_uv_rect) override;
+ GDVIRTUAL3RC(Rect2, _font_get_glyph_uv_rect, RID, const Vector2i &, int32_t);
+ GDVIRTUAL4(_font_set_glyph_uv_rect, RID, const Vector2i &, int32_t, const Rect2 &);
+
+ virtual int font_get_glyph_texture_idx(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const override;
+ virtual void font_set_glyph_texture_idx(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, int p_texture_idx) override;
+ GDVIRTUAL3RC(int, _font_get_glyph_texture_idx, RID, const Vector2i &, int32_t);
+ GDVIRTUAL4(_font_set_glyph_texture_idx, RID, const Vector2i &, int32_t, int);
+
+ virtual Dictionary font_get_glyph_contours(RID p_font, int p_size, int32_t p_index) const override;
+ GDVIRTUAL3RC(Dictionary, _font_get_glyph_contours, RID, int, int32_t);
+
+ virtual Array font_get_kerning_list(RID p_font_rid, int p_size) const override;
+ virtual void font_clear_kerning_map(RID p_font_rid, int p_size) override;
+ virtual void font_remove_kerning(RID p_font_rid, int p_size, const Vector2i &p_glyph_pair) override;
+ GDVIRTUAL2RC(Array, _font_get_kerning_list, RID, int);
+ GDVIRTUAL2(_font_clear_kerning_map, RID, int);
+ GDVIRTUAL3(_font_remove_kerning, RID, int, const Vector2i &);
+
+ virtual void font_set_kerning(RID p_font_rid, int p_size, const Vector2i &p_glyph_pair, const Vector2 &p_kerning) override;
+ virtual Vector2 font_get_kerning(RID p_font_rid, int p_size, const Vector2i &p_glyph_pair) const override;
+ GDVIRTUAL4(_font_set_kerning, RID, int, const Vector2i &, const Vector2 &);
+ GDVIRTUAL3RC(Vector2, _font_get_kerning, RID, int, const Vector2i &);
+
+ virtual int32_t font_get_glyph_index(RID p_font_rid, int p_size, char32_t p_char, char32_t p_variation_selector = 0) const override;
+ GDVIRTUAL4RC(int32_t, _font_get_glyph_index, RID, int, char32_t, char32_t);
+
+ virtual bool font_has_char(RID p_font_rid, char32_t p_char) const override;
+ virtual String font_get_supported_chars(RID p_font_rid) const override;
+ GDVIRTUAL2RC(bool, _font_has_char, RID, char32_t);
+ GDVIRTUAL1RC(String, _font_get_supported_chars, RID);
+
+ virtual void font_render_range(RID p_font, const Vector2i &p_size, char32_t p_start, char32_t p_end) override;
+ virtual void font_render_glyph(RID p_font_rid, const Vector2i &p_size, int32_t p_index) override;
+ GDVIRTUAL4(_font_render_range, RID, const Vector2i &, char32_t, char32_t);
+ GDVIRTUAL3(_font_render_glyph, RID, const Vector2i &, int32_t);
+
+ virtual void font_draw_glyph(RID p_font, RID p_canvas, int p_size, const Vector2 &p_pos, int32_t p_index, const Color &p_color = Color(1, 1, 1)) const override;
+ virtual void font_draw_glyph_outline(RID p_font, RID p_canvas, int p_size, int p_outline_size, const Vector2 &p_pos, int32_t p_index, const Color &p_color = Color(1, 1, 1)) const override;
+ GDVIRTUAL6C(_font_draw_glyph, RID, RID, int, const Vector2 &, int32_t, const Color &);
+ GDVIRTUAL7C(_font_draw_glyph_outline, RID, RID, int, int, const Vector2 &, int32_t, const Color &);
+
+ virtual bool font_is_language_supported(RID p_font_rid, const String &p_language) const override;
+ virtual void font_set_language_support_override(RID p_font_rid, const String &p_language, bool p_supported) override;
+ virtual bool font_get_language_support_override(RID p_font_rid, const String &p_language) override;
+ virtual void font_remove_language_support_override(RID p_font_rid, const String &p_language) override;
+ virtual Vector<String> font_get_language_support_overrides(RID p_font_rid) override;
+ GDVIRTUAL2RC(bool, _font_is_language_supported, RID, const String &);
+ GDVIRTUAL3(_font_set_language_support_override, RID, const String &, bool);
+ GDVIRTUAL2R(bool, _font_get_language_support_override, RID, const String &);
+ GDVIRTUAL2(_font_remove_language_support_override, RID, const String &);
+ GDVIRTUAL1R(Vector<String>, _font_get_language_support_overrides, RID);
+
+ virtual bool font_is_script_supported(RID p_font_rid, const String &p_script) const override;
+ virtual void font_set_script_support_override(RID p_font_rid, const String &p_script, bool p_supported) override;
+ virtual bool font_get_script_support_override(RID p_font_rid, const String &p_script) override;
+ virtual void font_remove_script_support_override(RID p_font_rid, const String &p_script) override;
+ virtual Vector<String> font_get_script_support_overrides(RID p_font_rid) override;
+ GDVIRTUAL2RC(bool, _font_is_script_supported, RID, const String &);
+ GDVIRTUAL3(_font_set_script_support_override, RID, const String &, bool);
+ GDVIRTUAL2R(bool, _font_get_script_support_override, RID, const String &);
+ GDVIRTUAL2(_font_remove_script_support_override, RID, const String &);
+ GDVIRTUAL1R(Vector<String>, _font_get_script_support_overrides, RID);
+
+ virtual Dictionary font_supported_feature_list(RID p_font_rid) const override;
+ virtual Dictionary font_supported_variation_list(RID p_font_rid) const override;
+ GDVIRTUAL1RC(Dictionary, _font_supported_feature_list, RID);
+ GDVIRTUAL1RC(Dictionary, _font_supported_variation_list, RID);
+
+ virtual float font_get_global_oversampling() const override;
+ virtual void font_set_global_oversampling(float p_oversampling) override;
+ GDVIRTUAL0RC(float, _font_get_global_oversampling);
+ GDVIRTUAL1(_font_set_global_oversampling, float);
+
+ virtual Vector2 get_hex_code_box_size(int p_size, char32_t p_index) const override;
+ virtual void draw_hex_code_box(RID p_canvas, int p_size, const Vector2 &p_pos, char32_t p_index, const Color &p_color) const override;
+ GDVIRTUAL2RC(Vector2, _get_hex_code_box_size, int, char32_t);
+ GDVIRTUAL5C(_draw_hex_code_box, RID, int, const Vector2 &, char32_t, const Color &);
+
+ /* Shaped text buffer interface */
+
+ virtual RID create_shaped_text(Direction p_direction = DIRECTION_AUTO, Orientation p_orientation = ORIENTATION_HORIZONTAL) override;
+ GDVIRTUAL2R(RID, _create_shaped_text, Direction, Orientation);
+
+ virtual void shaped_text_clear(RID p_shaped) override;
+ GDVIRTUAL1(_shaped_text_clear, RID);
+
+ virtual void shaped_text_set_direction(RID p_shaped, Direction p_direction = DIRECTION_AUTO) override;
+ virtual Direction shaped_text_get_direction(RID p_shaped) const override;
+ GDVIRTUAL2(_shaped_text_set_direction, RID, Direction);
+ GDVIRTUAL1RC(/*Direction*/ int, _shaped_text_get_direction, RID);
+
+ virtual void shaped_text_set_bidi_override(RID p_shaped, const Array &p_override) override;
+ GDVIRTUAL2(_shaped_text_set_bidi_override, RID, const Array &);
+
+ virtual void shaped_text_set_orientation(RID p_shaped, Orientation p_orientation = ORIENTATION_HORIZONTAL) override;
+ virtual Orientation shaped_text_get_orientation(RID p_shaped) const override;
+ GDVIRTUAL2(_shaped_text_set_orientation, RID, Orientation);
+ GDVIRTUAL1RC(/*Orientation*/ int, _shaped_text_get_orientation, RID);
+
+ virtual void shaped_text_set_preserve_invalid(RID p_shaped, bool p_enabled) override;
+ virtual bool shaped_text_get_preserve_invalid(RID p_shaped) const override;
+ GDVIRTUAL2(_shaped_text_set_preserve_invalid, RID, bool);
+ GDVIRTUAL1RC(bool, _shaped_text_get_preserve_invalid, RID);
+
+ virtual void shaped_text_set_preserve_control(RID p_shaped, bool p_enabled) override;
+ virtual bool shaped_text_get_preserve_control(RID p_shaped) const override;
+ GDVIRTUAL2(_shaped_text_set_preserve_control, RID, bool);
+ GDVIRTUAL1RC(bool, _shaped_text_get_preserve_control, RID);
+
+ virtual bool shaped_text_add_string(RID p_shaped, const String &p_text, const Vector<RID> &p_fonts, int p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "") override;
+ virtual bool shaped_text_add_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlign p_inline_align = INLINE_ALIGN_CENTER, int p_length = 1) override;
+ virtual bool shaped_text_resize_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlign p_inline_align = INLINE_ALIGN_CENTER) override;
+ GDVIRTUAL6R(bool, _shaped_text_add_string, RID, const String &, const Array &, int, const Dictionary &, const String &);
+ GDVIRTUAL5R(bool, _shaped_text_add_object, RID, Variant, const Size2 &, InlineAlign, int);
+ GDVIRTUAL4R(bool, _shaped_text_resize_object, RID, Variant, const Size2 &, InlineAlign);
+
+ virtual RID shaped_text_substr(RID p_shaped, int p_start, int p_length) const override;
+ virtual RID shaped_text_get_parent(RID p_shaped) const override;
+ GDVIRTUAL3RC(RID, _shaped_text_substr, RID, int, int);
+ GDVIRTUAL1RC(RID, _shaped_text_get_parent, RID);
+
+ virtual float shaped_text_fit_to_width(RID p_shaped, float p_width, uint16_t /*JustificationFlag*/ p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) override;
+ virtual float shaped_text_tab_align(RID p_shaped, const PackedFloat32Array &p_tab_stops) override;
+ GDVIRTUAL3R(float, _shaped_text_fit_to_width, RID, float, uint16_t);
+ GDVIRTUAL2R(float, _shaped_text_tab_align, RID, const PackedFloat32Array &);
+
+ virtual bool shaped_text_shape(RID p_shaped) override;
+ virtual bool shaped_text_update_breaks(RID p_shaped) override;
+ virtual bool shaped_text_update_justification_ops(RID p_shaped) override;
+ GDVIRTUAL1R(bool, _shaped_text_shape, RID);
+ GDVIRTUAL1R(bool, _shaped_text_update_breaks, RID);
+ GDVIRTUAL1R(bool, _shaped_text_update_justification_ops, RID);
+
+ virtual bool shaped_text_is_ready(RID p_shaped) const override;
+ GDVIRTUAL1RC(bool, _shaped_text_is_ready, RID);
+
+ virtual const Glyph *shaped_text_get_glyphs(RID p_shaped) const override;
+ virtual const Glyph *shaped_text_sort_logical(RID p_shaped) override;
+ virtual int shaped_text_get_glyph_count(RID p_shaped) const override;
+ GDVIRTUAL2C(_shaped_text_get_glyphs, RID, GDNativePtr<const Glyph *>);
+ GDVIRTUAL2(_shaped_text_sort_logical, RID, GDNativePtr<const Glyph *>);
+ GDVIRTUAL1RC(int, _shaped_text_get_glyph_count, RID);
+
+ virtual Vector2i shaped_text_get_range(RID p_shaped) const override;
+ GDVIRTUAL1RC(Vector2i, _shaped_text_get_range, RID);
+
+ virtual PackedInt32Array shaped_text_get_line_breaks_adv(RID p_shaped, const PackedFloat32Array &p_width, int p_start = 0, bool p_once = true, uint16_t /*TextBreakFlag*/ p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const override;
+ virtual PackedInt32Array shaped_text_get_line_breaks(RID p_shaped, float p_width, int p_start = 0, uint16_t p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const override;
+ virtual PackedInt32Array shaped_text_get_word_breaks(RID p_shaped, int p_grapheme_flags = GRAPHEME_IS_SPACE | GRAPHEME_IS_PUNCTUATION) const override;
+ GDVIRTUAL5RC(PackedInt32Array, _shaped_text_get_line_breaks_adv, RID, const PackedFloat32Array &, int, bool, uint16_t);
+ GDVIRTUAL4RC(PackedInt32Array, _shaped_text_get_line_breaks, RID, float, int, uint16_t);
+ GDVIRTUAL2RC(PackedInt32Array, _shaped_text_get_word_breaks, RID, int);
+
+ virtual int shaped_text_get_trim_pos(RID p_shaped) const override;
+ virtual int shaped_text_get_ellipsis_pos(RID p_shaped) const override;
+ virtual const Glyph *shaped_text_get_ellipsis_glyphs(RID p_shaped) const override;
+ virtual int shaped_text_get_ellipsis_glyph_count(RID p_shaped) const override;
+ GDVIRTUAL1RC(int, _shaped_text_get_trim_pos, RID);
+ GDVIRTUAL1RC(int, _shaped_text_get_ellipsis_pos, RID);
+ GDVIRTUAL2C(_shaped_text_get_ellipsis_glyphs, RID, GDNativePtr<const Glyph *>);
+ GDVIRTUAL1RC(int, _shaped_text_get_ellipsis_glyph_count, RID);
+
+ virtual void shaped_text_overrun_trim_to_width(RID p_shaped, float p_width, uint16_t p_trim_flags) override;
+ GDVIRTUAL3(_shaped_text_overrun_trim_to_width, RID, float, uint16_t);
+
+ virtual Array shaped_text_get_objects(RID p_shaped) const override;
+ virtual Rect2 shaped_text_get_object_rect(RID p_shaped, Variant p_key) const override;
+ GDVIRTUAL1RC(Array, _shaped_text_get_objects, RID);
+ GDVIRTUAL2RC(Rect2, _shaped_text_get_object_rect, RID, Variant);
+
+ virtual Size2 shaped_text_get_size(RID p_shaped) const override;
+ virtual float shaped_text_get_ascent(RID p_shaped) const override;
+ virtual float shaped_text_get_descent(RID p_shaped) const override;
+ virtual float shaped_text_get_width(RID p_shaped) const override;
+ virtual float shaped_text_get_underline_position(RID p_shaped) const override;
+ virtual float shaped_text_get_underline_thickness(RID p_shaped) const override;
+ GDVIRTUAL1RC(Size2, _shaped_text_get_size, RID);
+ GDVIRTUAL1RC(float, _shaped_text_get_ascent, RID);
+ GDVIRTUAL1RC(float, _shaped_text_get_descent, RID);
+ GDVIRTUAL1RC(float, _shaped_text_get_width, RID);
+ GDVIRTUAL1RC(float, _shaped_text_get_underline_position, RID);
+ GDVIRTUAL1RC(float, _shaped_text_get_underline_thickness, RID);
+
+ virtual Direction shaped_text_get_dominant_direction_in_range(RID p_shaped, int p_start, int p_end) const override;
+ GDVIRTUAL3RC(int, _shaped_text_get_dominant_direction_in_range, RID, int, int);
+
+ virtual CaretInfo shaped_text_get_carets(RID p_shaped, int p_position) const override;
+ virtual Vector<Vector2> shaped_text_get_selection(RID p_shaped, int p_start, int p_end) const override;
+ GDVIRTUAL3C(_shaped_text_get_carets, RID, int, GDNativePtr<CaretInfo>);
+ GDVIRTUAL3RC(Vector<Vector2>, _shaped_text_get_selection, RID, int, int);
+
+ virtual int shaped_text_hit_test_grapheme(RID p_shaped, float p_coords) const override;
+ virtual int shaped_text_hit_test_position(RID p_shaped, float p_coords) const override;
+ GDVIRTUAL2RC(int, _shaped_text_hit_test_grapheme, RID, float);
+ GDVIRTUAL2RC(int, _shaped_text_hit_test_position, RID, float);
+
+ virtual void shaped_text_draw(RID p_shaped, RID p_canvas, const Vector2 &p_pos, float p_clip_l = -1.f, float p_clip_r = -1.f, const Color &p_color = Color(1, 1, 1)) const override;
+ virtual void shaped_text_draw_outline(RID p_shaped, RID p_canvas, const Vector2 &p_pos, float p_clip_l = -1.f, float p_clip_r = -1.f, int p_outline_size = 1, const Color &p_color = Color(1, 1, 1)) const override;
+ GDVIRTUAL6C(_shaped_text_draw, RID, RID, const Vector2 &, float, float, const Color &);
+ GDVIRTUAL7C(_shaped_text_draw_outline, RID, RID, const Vector2 &, float, float, int, const Color &);
+
+ virtual int shaped_text_next_grapheme_pos(RID p_shaped, int p_pos) const override;
+ virtual int shaped_text_prev_grapheme_pos(RID p_shaped, int p_pos) const override;
+ GDVIRTUAL2RC(int, _shaped_text_next_grapheme_pos, RID, int);
+ GDVIRTUAL2RC(int, _shaped_text_prev_grapheme_pos, RID, int);
+
+ virtual String format_number(const String &p_string, const String &p_language = "") const override;
+ virtual String parse_number(const String &p_string, const String &p_language = "") const override;
+ virtual String percent_sign(const String &p_language = "") const override;
+ GDVIRTUAL2RC(String, _format_number, const String &, const String &);
+ GDVIRTUAL2RC(String, _parse_number, const String &, const String &);
+ GDVIRTUAL1RC(String, _percent_sign, const String &);
+
+ TextServerExtension();
+ ~TextServerExtension();
+};
+
+#endif // TEXT_SERVER_EXTENSION_H
diff --git a/servers/text_server.cpp b/servers/text_server.cpp
index 6bace8cf9e..5087d32a7f 100644
--- a/servers/text_server.cpp
+++ b/servers/text_server.cpp
@@ -29,125 +29,111 @@
/*************************************************************************/
#include "servers/text_server.h"
-#include "scene/main/canvas_item.h"
+#include "servers/rendering_server.h"
TextServerManager *TextServerManager::singleton = nullptr;
-TextServer *TextServerManager::server = nullptr;
-TextServerManager::TextServerCreate TextServerManager::server_create_functions[TextServerManager::MAX_SERVERS];
-int TextServerManager::server_create_count = 0;
void TextServerManager::_bind_methods() {
- ClassDB::bind_method(D_METHOD("get_interface_count"), &TextServerManager::_get_interface_count);
- ClassDB::bind_method(D_METHOD("get_interface_name", "index"), &TextServerManager::_get_interface_name);
- ClassDB::bind_method(D_METHOD("get_interface_features", "index"), &TextServerManager::_get_interface_features);
- ClassDB::bind_method(D_METHOD("get_interface", "index"), &TextServerManager::_get_interface);
- ClassDB::bind_method(D_METHOD("get_interfaces"), &TextServerManager::_get_interfaces);
- ClassDB::bind_method(D_METHOD("find_interface", "name"), &TextServerManager::_find_interface);
-
- ClassDB::bind_method(D_METHOD("set_primary_interface", "index"), &TextServerManager::_set_primary_interface);
+ ClassDB::bind_method(D_METHOD("add_interface", "interface"), &TextServerManager::add_interface);
+ ClassDB::bind_method(D_METHOD("get_interface_count"), &TextServerManager::get_interface_count);
+ ClassDB::bind_method(D_METHOD("remove_interface", "interface"), &TextServerManager::remove_interface);
+ ClassDB::bind_method(D_METHOD("get_interface", "idx"), &TextServerManager::get_interface);
+ ClassDB::bind_method(D_METHOD("get_interfaces"), &TextServerManager::get_interfaces);
+ ClassDB::bind_method(D_METHOD("find_interface", "name"), &TextServerManager::find_interface);
+
+ ClassDB::bind_method(D_METHOD("set_primary_interface", "index"), &TextServerManager::set_primary_interface);
ClassDB::bind_method(D_METHOD("get_primary_interface"), &TextServerManager::_get_primary_interface);
-}
-void TextServerManager::register_create_function(const String &p_name, uint32_t p_features, TextServerManager::CreateFunction p_function, void *p_user_data) {
- ERR_FAIL_COND(server_create_count == MAX_SERVERS);
- server_create_functions[server_create_count].name = p_name;
- server_create_functions[server_create_count].create_function = p_function;
- server_create_functions[server_create_count].user_data = p_user_data;
- server_create_functions[server_create_count].features = p_features;
- server_create_count++;
+ ADD_SIGNAL(MethodInfo("interface_added", PropertyInfo(Variant::STRING_NAME, "interface_name")));
+ ADD_SIGNAL(MethodInfo("interface_removed", PropertyInfo(Variant::STRING_NAME, "interface_name")));
}
-int TextServerManager::get_interface_count() {
- return server_create_count;
-}
+void TextServerManager::add_interface(const Ref<TextServer> &p_interface) {
+ ERR_FAIL_COND(p_interface.is_null());
-String TextServerManager::get_interface_name(int p_index) {
- ERR_FAIL_INDEX_V(p_index, server_create_count, String());
- return server_create_functions[p_index].name;
-}
+ for (int i = 0; i < interfaces.size(); i++) {
+ if (interfaces[i] == p_interface) {
+ ERR_PRINT("TextServer: Interface was already added.");
+ return;
+ };
+ };
-uint32_t TextServerManager::get_interface_features(int p_index) {
- ERR_FAIL_INDEX_V(p_index, server_create_count, 0);
- return server_create_functions[p_index].features;
+ interfaces.push_back(p_interface);
+ print_verbose("TextServer: Added interface \"" + p_interface->get_name() + "\"");
+ emit_signal(SNAME("interface_added"), p_interface->get_name());
}
-TextServer *TextServerManager::initialize(int p_index, Error &r_error) {
- ERR_FAIL_INDEX_V(p_index, server_create_count, nullptr);
- if (server_create_functions[p_index].instance == nullptr) {
- server_create_functions[p_index].instance = server_create_functions[p_index].create_function(r_error, server_create_functions[p_index].user_data);
- if (server_create_functions[p_index].instance != nullptr) {
- server_create_functions[p_index].instance->load_support_data(""); // Try loading default data.
- }
- }
- if (server_create_functions[p_index].instance != nullptr) {
- server = server_create_functions[p_index].instance;
- if (OS::get_singleton()->get_main_loop()) {
- OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_TEXT_SERVER_CHANGED);
- }
- }
- return server_create_functions[p_index].instance;
-}
+void TextServerManager::remove_interface(const Ref<TextServer> &p_interface) {
+ ERR_FAIL_COND(p_interface.is_null());
+ ERR_FAIL_COND_MSG(p_interface == primary_interface, "TextServer: Can't remove primary interface.");
-TextServer *TextServerManager::get_primary_interface() {
- return server;
-}
+ int idx = -1;
+ for (int i = 0; i < interfaces.size(); i++) {
+ if (interfaces[i] == p_interface) {
+ idx = i;
+ break;
+ };
+ };
-int TextServerManager::_get_interface_count() const {
- return server_create_count;
+ ERR_FAIL_COND(idx == -1);
+ print_verbose("TextServer: Removed interface \"" + p_interface->get_name() + "\"");
+ emit_signal(SNAME("interface_removed"), p_interface->get_name());
+ interfaces.remove(idx);
}
-String TextServerManager::_get_interface_name(int p_index) const {
- return get_interface_name(p_index);
+int TextServerManager::get_interface_count() const {
+ return interfaces.size();
}
-uint32_t TextServerManager::_get_interface_features(int p_index) const {
- return get_interface_features(p_index);
+Ref<TextServer> TextServerManager::get_interface(int p_index) const {
+ ERR_FAIL_INDEX_V(p_index, interfaces.size(), nullptr);
+ return interfaces[p_index];
}
-TextServer *TextServerManager::_get_interface(int p_index) const {
- ERR_FAIL_INDEX_V(p_index, server_create_count, nullptr);
- if (server_create_functions[p_index].instance == nullptr) {
- Error error;
- server_create_functions[p_index].instance = server_create_functions[p_index].create_function(error, server_create_functions[p_index].user_data);
- if (server_create_functions[p_index].instance != nullptr) {
- server_create_functions[p_index].instance->load_support_data(""); // Try loading default data.
- }
- }
- return server_create_functions[p_index].instance;
-}
+Ref<TextServer> TextServerManager::find_interface(const String &p_name) const {
+ int idx = -1;
+ for (int i = 0; i < interfaces.size(); i++) {
+ if (interfaces[i]->get_name() == p_name) {
+ idx = i;
+ break;
+ };
+ };
-TextServer *TextServerManager::_find_interface(const String &p_name) const {
- for (int i = 0; i < server_create_count; i++) {
- if (server_create_functions[i].name == p_name) {
- return _get_interface(i);
- }
- }
- return nullptr;
+ ERR_FAIL_COND_V(idx == -1, nullptr);
+ return interfaces[idx];
}
-Array TextServerManager::_get_interfaces() const {
+Array TextServerManager::get_interfaces() const {
Array ret;
- for (int i = 0; i < server_create_count; i++) {
+ for (int i = 0; i < interfaces.size(); i++) {
Dictionary iface_info;
iface_info["id"] = i;
- iface_info["name"] = server_create_functions[i].name;
+ iface_info["name"] = interfaces[i]->get_name();
ret.push_back(iface_info);
};
return ret;
-};
+}
-bool TextServerManager::_set_primary_interface(int p_index) {
- Error error;
- TextServerManager::initialize(p_index, error);
- return (error == OK);
+Ref<TextServer> TextServerManager::_get_primary_interface() const {
+ return primary_interface;
}
-TextServer *TextServerManager::_get_primary_interface() const {
- return server;
+void TextServerManager::set_primary_interface(const Ref<TextServer> &p_primary_interface) {
+ if (p_primary_interface.is_null()) {
+ print_verbose("TextServer: Clearing primary interface");
+ primary_interface.unref();
+ } else {
+ primary_interface = p_primary_interface;
+ print_verbose("TextServer: Primary interface set to: \"" + primary_interface->get_name() + "\".");
+
+ if (OS::get_singleton()->get_main_loop()) {
+ OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_TEXT_SERVER_CHANGED);
+ }
+ }
}
TextServerManager::TextServerManager() {
@@ -155,29 +141,29 @@ TextServerManager::TextServerManager() {
}
TextServerManager::~TextServerManager() {
- singleton = nullptr;
- for (int i = 0; i < server_create_count; i++) {
- if (server_create_functions[i].instance != nullptr) {
- memdelete(server_create_functions[i].instance);
- server_create_functions[i].instance = nullptr;
- }
+ if (primary_interface.is_valid()) {
+ primary_interface.unref();
+ }
+ while (interfaces.size() > 0) {
+ interfaces.remove(0);
}
+ singleton = nullptr;
}
/*************************************************************************/
-bool TextServer::Glyph::operator==(const Glyph &p_a) const {
+bool Glyph::operator==(const Glyph &p_a) const {
return (p_a.index == index) && (p_a.font_rid == font_rid) && (p_a.font_size == font_size) && (p_a.start == start);
}
-bool TextServer::Glyph::operator!=(const Glyph &p_a) const {
+bool Glyph::operator!=(const Glyph &p_a) const {
return (p_a.index != index) || (p_a.font_rid != font_rid) || (p_a.font_size != font_size) || (p_a.start != start);
}
-bool TextServer::Glyph::operator<(const Glyph &p_a) const {
+bool Glyph::operator<(const Glyph &p_a) const {
if (p_a.start == start) {
if (p_a.count == count) {
- if ((p_a.flags & GRAPHEME_IS_VIRTUAL) == GRAPHEME_IS_VIRTUAL) {
+ if ((p_a.flags & TextServer::GRAPHEME_IS_VIRTUAL) == TextServer::GRAPHEME_IS_VIRTUAL) {
return true;
} else {
return false;
@@ -188,10 +174,10 @@ bool TextServer::Glyph::operator<(const Glyph &p_a) const {
return p_a.start < start;
}
-bool TextServer::Glyph::operator>(const Glyph &p_a) const {
+bool Glyph::operator>(const Glyph &p_a) const {
if (p_a.start == start) {
if (p_a.count == count) {
- if ((p_a.flags & GRAPHEME_IS_VIRTUAL) == GRAPHEME_IS_VIRTUAL) {
+ if ((p_a.flags & TextServer::GRAPHEME_IS_VIRTUAL) == TextServer::GRAPHEME_IS_VIRTUAL) {
return false;
} else {
return true;
@@ -205,8 +191,13 @@ bool TextServer::Glyph::operator>(const Glyph &p_a) const {
void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("has_feature", "feature"), &TextServer::has_feature);
ClassDB::bind_method(D_METHOD("get_name"), &TextServer::get_name);
+ ClassDB::bind_method(D_METHOD("get_features"), &TextServer::get_features);
ClassDB::bind_method(D_METHOD("load_support_data", "filename"), &TextServer::load_support_data);
+ ClassDB::bind_method(D_METHOD("get_support_data_filename"), &TextServer::get_support_data_filename);
+ ClassDB::bind_method(D_METHOD("get_support_data_info"), &TextServer::get_support_data_info);
+ ClassDB::bind_method(D_METHOD("save_support_data", "filename"), &TextServer::save_support_data);
+
ClassDB::bind_method(D_METHOD("is_locale_right_to_left", "locale"), &TextServer::is_locale_right_to_left);
ClassDB::bind_method(D_METHOD("name_to_tag", "name"), &TextServer::name_to_tag);
@@ -216,83 +207,130 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("free_rid", "rid"), &TextServer::free); // shouldn't conflict with Object::free()
/* Font Interface */
- ClassDB::bind_method(D_METHOD("create_font_system", "name", "base_size"), &TextServer::create_font_system, DEFVAL(16));
- ClassDB::bind_method(D_METHOD("create_font_resource", "filename", "base_size"), &TextServer::create_font_resource, DEFVAL(16));
- ClassDB::bind_method(D_METHOD("create_font_memory", "data", "type", "base_size"), &TextServer::_create_font_memory, DEFVAL(16));
- ClassDB::bind_method(D_METHOD("create_font_bitmap", "height", "ascent", "base_size"), &TextServer::create_font_bitmap);
- ClassDB::bind_method(D_METHOD("font_bitmap_add_texture", "font", "texture"), &TextServer::font_bitmap_add_texture);
- ClassDB::bind_method(D_METHOD("font_bitmap_add_char", "font", "char", "texture_idx", "rect", "align", "advance"), &TextServer::font_bitmap_add_char);
- ClassDB::bind_method(D_METHOD("font_bitmap_add_kerning_pair", "font", "A", "B", "kerning"), &TextServer::font_bitmap_add_kerning_pair);
+ ClassDB::bind_method(D_METHOD("create_font"), &TextServer::create_font);
+
+ ClassDB::bind_method(D_METHOD("font_set_data", "font_rid", "data"), &TextServer::font_set_data);
+
+ ClassDB::bind_method(D_METHOD("font_set_antialiased", "font_rid", "antialiased"), &TextServer::font_set_antialiased);
+ ClassDB::bind_method(D_METHOD("font_is_antialiased", "font_rid"), &TextServer::font_is_antialiased);
+
+ ClassDB::bind_method(D_METHOD("font_set_multichannel_signed_distance_field", "font_rid", "msdf"), &TextServer::font_set_multichannel_signed_distance_field);
+ ClassDB::bind_method(D_METHOD("font_is_multichannel_signed_distance_field", "font_rid"), &TextServer::font_is_multichannel_signed_distance_field);
+
+ ClassDB::bind_method(D_METHOD("font_set_msdf_pixel_range", "font_rid", "msdf_pixel_range"), &TextServer::font_set_msdf_pixel_range);
+ ClassDB::bind_method(D_METHOD("font_get_msdf_pixel_range", "font_rid"), &TextServer::font_get_msdf_pixel_range);
- ClassDB::bind_method(D_METHOD("font_get_height", "font", "size"), &TextServer::font_get_height);
- ClassDB::bind_method(D_METHOD("font_get_ascent", "font", "size"), &TextServer::font_get_ascent);
- ClassDB::bind_method(D_METHOD("font_get_descent", "font", "size"), &TextServer::font_get_descent);
+ ClassDB::bind_method(D_METHOD("font_set_msdf_size", "font_rid", "msdf_size"), &TextServer::font_set_msdf_size);
+ ClassDB::bind_method(D_METHOD("font_get_msdf_size", "font_rid"), &TextServer::font_get_msdf_size);
- ClassDB::bind_method(D_METHOD("font_get_underline_position", "font", "size"), &TextServer::font_get_underline_position);
- ClassDB::bind_method(D_METHOD("font_get_underline_thickness", "font", "size"), &TextServer::font_get_underline_thickness);
+ ClassDB::bind_method(D_METHOD("font_set_fixed_size", "font_rid", "fixed_size"), &TextServer::font_set_fixed_size);
+ ClassDB::bind_method(D_METHOD("font_get_fixed_size", "font_rid"), &TextServer::font_get_fixed_size);
- ClassDB::bind_method(D_METHOD("font_get_spacing_space", "font"), &TextServer::font_get_spacing_space);
- ClassDB::bind_method(D_METHOD("font_set_spacing_space", "font", "value"), &TextServer::font_set_spacing_space);
+ ClassDB::bind_method(D_METHOD("font_set_force_autohinter", "font_rid", "force_autohinter"), &TextServer::font_set_force_autohinter);
+ ClassDB::bind_method(D_METHOD("font_is_force_autohinter", "font_rid"), &TextServer::font_is_force_autohinter);
- ClassDB::bind_method(D_METHOD("font_get_spacing_glyph", "font"), &TextServer::font_get_spacing_glyph);
- ClassDB::bind_method(D_METHOD("font_set_spacing_glyph", "font", "value"), &TextServer::font_set_spacing_glyph);
+ ClassDB::bind_method(D_METHOD("font_set_hinting", "font_rid", "_hinting"), &TextServer::font_set_hinting);
+ ClassDB::bind_method(D_METHOD("font_get_hinting", "font_rid"), &TextServer::font_get_hinting);
- ClassDB::bind_method(D_METHOD("font_set_antialiased", "font", "antialiased"), &TextServer::font_set_antialiased);
- ClassDB::bind_method(D_METHOD("font_get_antialiased", "font"), &TextServer::font_get_antialiased);
+ ClassDB::bind_method(D_METHOD("font_set_variation_coordinates", "font_rid", "variation_coordinates"), &TextServer::font_set_variation_coordinates);
+ ClassDB::bind_method(D_METHOD("font_get_variation_coordinates", "font_rid"), &TextServer::font_get_variation_coordinates);
- ClassDB::bind_method(D_METHOD("font_get_feature_list", "font"), &TextServer::font_get_feature_list);
- ClassDB::bind_method(D_METHOD("font_get_variation_list", "font"), &TextServer::font_get_variation_list);
+ ClassDB::bind_method(D_METHOD("font_set_oversampling", "font_rid", "oversampling"), &TextServer::font_set_oversampling);
+ ClassDB::bind_method(D_METHOD("font_get_oversampling", "font_rid"), &TextServer::font_get_oversampling);
- ClassDB::bind_method(D_METHOD("font_set_variation", "font", "tag", "value"), &TextServer::font_set_variation);
- ClassDB::bind_method(D_METHOD("font_get_variation", "font", "tag"), &TextServer::font_get_variation);
+ ClassDB::bind_method(D_METHOD("font_get_size_cache_list", "font_rid"), &TextServer::font_get_size_cache_list);
+ ClassDB::bind_method(D_METHOD("font_clear_size_cache", "font_rid"), &TextServer::font_clear_size_cache);
+ ClassDB::bind_method(D_METHOD("font_remove_size_cache", "font_rid", "size"), &TextServer::font_remove_size_cache);
- ClassDB::bind_method(D_METHOD("font_set_hinting", "font", "hinting"), &TextServer::font_set_hinting);
- ClassDB::bind_method(D_METHOD("font_get_hinting", "font"), &TextServer::font_get_hinting);
+ ClassDB::bind_method(D_METHOD("font_set_ascent", "font_rid", "size", "ascent"), &TextServer::font_set_ascent);
+ ClassDB::bind_method(D_METHOD("font_get_ascent", "font_rid", "size"), &TextServer::font_get_ascent);
- ClassDB::bind_method(D_METHOD("font_set_distance_field_hint", "font", "distance_field"), &TextServer::font_set_distance_field_hint);
- ClassDB::bind_method(D_METHOD("font_get_distance_field_hint", "font"), &TextServer::font_get_distance_field_hint);
+ ClassDB::bind_method(D_METHOD("font_set_descent", "font_rid", "size", "descent"), &TextServer::font_set_descent);
+ ClassDB::bind_method(D_METHOD("font_get_descent", "font_rid", "size"), &TextServer::font_get_descent);
- ClassDB::bind_method(D_METHOD("font_set_force_autohinter", "font", "enabeld"), &TextServer::font_set_force_autohinter);
- ClassDB::bind_method(D_METHOD("font_get_force_autohinter", "font"), &TextServer::font_get_force_autohinter);
+ ClassDB::bind_method(D_METHOD("font_set_underline_position", "font_rid", "size", "underline_position"), &TextServer::font_set_underline_position);
+ ClassDB::bind_method(D_METHOD("font_get_underline_position", "font_rid", "size"), &TextServer::font_get_underline_position);
- ClassDB::bind_method(D_METHOD("font_has_char", "font", "char"), &TextServer::font_has_char);
- ClassDB::bind_method(D_METHOD("font_get_supported_chars", "font"), &TextServer::font_get_supported_chars);
+ ClassDB::bind_method(D_METHOD("font_set_underline_thickness", "font_rid", "size", "underline_thickness"), &TextServer::font_set_underline_thickness);
+ ClassDB::bind_method(D_METHOD("font_get_underline_thickness", "font_rid", "size"), &TextServer::font_get_underline_thickness);
- ClassDB::bind_method(D_METHOD("font_has_outline", "font"), &TextServer::font_has_outline);
- ClassDB::bind_method(D_METHOD("font_get_base_size", "font"), &TextServer::font_get_base_size);
+ ClassDB::bind_method(D_METHOD("font_set_scale", "font_rid", "size", "scale"), &TextServer::font_set_scale);
+ ClassDB::bind_method(D_METHOD("font_get_scale", "font_rid", "size"), &TextServer::font_get_scale);
- ClassDB::bind_method(D_METHOD("font_is_language_supported", "font", "language"), &TextServer::font_is_language_supported);
- ClassDB::bind_method(D_METHOD("font_set_language_support_override", "font", "language", "supported"), &TextServer::font_set_language_support_override);
+ ClassDB::bind_method(D_METHOD("font_set_spacing", "font_rid", "size", "spacing", "value"), &TextServer::font_set_spacing);
+ ClassDB::bind_method(D_METHOD("font_get_spacing", "font_rid", "size", "spacing"), &TextServer::font_get_spacing);
- ClassDB::bind_method(D_METHOD("font_get_language_support_override", "font", "language"), &TextServer::font_get_language_support_override);
- ClassDB::bind_method(D_METHOD("font_remove_language_support_override", "font", "language"), &TextServer::font_remove_language_support_override);
- ClassDB::bind_method(D_METHOD("font_get_language_support_overrides", "font"), &TextServer::font_get_language_support_overrides);
+ ClassDB::bind_method(D_METHOD("font_get_texture_count", "font_rid", "size"), &TextServer::font_get_texture_count);
+ ClassDB::bind_method(D_METHOD("font_clear_textures", "font_rid", "size"), &TextServer::font_clear_textures);
+ ClassDB::bind_method(D_METHOD("font_remove_texture", "font_rid", "size", "texture_index"), &TextServer::font_remove_texture);
- ClassDB::bind_method(D_METHOD("font_is_script_supported", "font", "script"), &TextServer::font_is_script_supported);
- ClassDB::bind_method(D_METHOD("font_set_script_support_override", "font", "script", "supported"), &TextServer::font_set_script_support_override);
+ ClassDB::bind_method(D_METHOD("font_set_texture_image", "font_rid", "size", "texture_index", "image"), &TextServer::font_set_texture_image);
+ ClassDB::bind_method(D_METHOD("font_get_texture_image", "font_rid", "size", "texture_index"), &TextServer::font_get_texture_image);
- ClassDB::bind_method(D_METHOD("font_get_script_support_override", "font", "script"), &TextServer::font_get_script_support_override);
- ClassDB::bind_method(D_METHOD("font_remove_script_support_override", "font", "script"), &TextServer::font_remove_script_support_override);
- ClassDB::bind_method(D_METHOD("font_get_script_support_overrides", "font"), &TextServer::font_get_script_support_overrides);
+ ClassDB::bind_method(D_METHOD("font_set_texture_offsets", "font_rid", "size", "texture_index", "offset"), &TextServer::font_set_texture_offsets);
+ ClassDB::bind_method(D_METHOD("font_get_texture_offsets", "font_rid", "size", "texture_index"), &TextServer::font_get_texture_offsets);
- ClassDB::bind_method(D_METHOD("font_get_glyph_index", "font", "char", "variation_selector"), &TextServer::font_get_glyph_index, DEFVAL(0x0000));
- ClassDB::bind_method(D_METHOD("font_get_glyph_advance", "font", "index", "size"), &TextServer::font_get_glyph_advance);
- ClassDB::bind_method(D_METHOD("font_get_glyph_kerning", "font", "index_a", "index_b", "size"), &TextServer::font_get_glyph_kerning);
+ ClassDB::bind_method(D_METHOD("font_get_glyph_list", "font_rid", "size"), &TextServer::font_get_glyph_list);
+ ClassDB::bind_method(D_METHOD("font_clear_glyphs", "font_rid", "size"), &TextServer::font_clear_glyphs);
+ ClassDB::bind_method(D_METHOD("font_remove_glyph", "font_rid", "size", "glyph"), &TextServer::font_remove_glyph);
- ClassDB::bind_method(D_METHOD("font_draw_glyph", "font", "canvas", "size", "pos", "index", "color"), &TextServer::font_draw_glyph, DEFVAL(Color(1, 1, 1)));
- ClassDB::bind_method(D_METHOD("font_draw_glyph_outline", "font", "canvas", "size", "outline_size", "pos", "index", "color"), &TextServer::font_draw_glyph_outline, DEFVAL(Color(1, 1, 1)));
+ ClassDB::bind_method(D_METHOD("font_get_glyph_advance", "font_rid", "size", "glyph"), &TextServer::font_get_glyph_advance);
+ ClassDB::bind_method(D_METHOD("font_set_glyph_advance", "font_rid", "size", "glyph", "advance"), &TextServer::font_set_glyph_advance);
- ClassDB::bind_method(D_METHOD("font_get_oversampling"), &TextServer::font_get_oversampling);
- ClassDB::bind_method(D_METHOD("font_set_oversampling", "oversampling"), &TextServer::font_set_oversampling);
+ ClassDB::bind_method(D_METHOD("font_get_glyph_offset", "font_rid", "size", "glyph"), &TextServer::font_get_glyph_offset);
+ ClassDB::bind_method(D_METHOD("font_set_glyph_offset", "font_rid", "size", "glyph", "offset"), &TextServer::font_set_glyph_offset);
- ClassDB::bind_method(D_METHOD("get_system_fonts"), &TextServer::get_system_fonts);
+ ClassDB::bind_method(D_METHOD("font_get_glyph_size", "font_rid", "size", "glyph"), &TextServer::font_get_glyph_size);
+ ClassDB::bind_method(D_METHOD("font_set_glyph_size", "font_rid", "size", "glyph", "gl_size"), &TextServer::font_set_glyph_size);
+
+ ClassDB::bind_method(D_METHOD("font_get_glyph_uv_rect", "font_rid", "size", "glyph"), &TextServer::font_get_glyph_uv_rect);
+ ClassDB::bind_method(D_METHOD("font_set_glyph_uv_rect", "font_rid", "size", "glyph", "uv_rect"), &TextServer::font_set_glyph_uv_rect);
+
+ ClassDB::bind_method(D_METHOD("font_get_glyph_texture_idx", "font_rid", "size", "glyph"), &TextServer::font_get_glyph_texture_idx);
+ ClassDB::bind_method(D_METHOD("font_set_glyph_texture_idx", "font_rid", "size", "glyph", "texture_idx"), &TextServer::font_set_glyph_texture_idx);
+
+ ClassDB::bind_method(D_METHOD("font_get_glyph_contours", "font", "size", "index"), &TextServer::font_get_glyph_contours);
+
+ ClassDB::bind_method(D_METHOD("font_get_kerning_list", "font_rid", "size"), &TextServer::font_get_kerning_list);
+ ClassDB::bind_method(D_METHOD("font_clear_kerning_map", "font_rid", "size"), &TextServer::font_clear_kerning_map);
+ ClassDB::bind_method(D_METHOD("font_remove_kerning", "font_rid", "size", "glyph_pair"), &TextServer::font_remove_kerning);
+
+ ClassDB::bind_method(D_METHOD("font_set_kerning", "font_rid", "size", "glyph_pair", "kerning"), &TextServer::font_set_kerning);
+ ClassDB::bind_method(D_METHOD("font_get_kerning", "font_rid", "size", "glyph_pair"), &TextServer::font_get_kerning);
+
+ ClassDB::bind_method(D_METHOD("font_get_glyph_index", "font_rid", "size", "char", "variation_selector"), &TextServer::font_get_glyph_index);
+
+ ClassDB::bind_method(D_METHOD("font_has_char", "font_rid", "char"), &TextServer::font_has_char);
+ ClassDB::bind_method(D_METHOD("font_get_supported_chars", "font_rid"), &TextServer::font_get_supported_chars);
+
+ ClassDB::bind_method(D_METHOD("font_render_range", "font_rid", "size", "start", "end"), &TextServer::font_render_range);
+ ClassDB::bind_method(D_METHOD("font_render_glyph", "font_rid", "size", "index"), &TextServer::font_render_glyph);
+
+ ClassDB::bind_method(D_METHOD("font_draw_glyph", "font_rid", "canvas", "size", "pos", "index", "color"), &TextServer::font_draw_glyph, DEFVAL(Color(1, 1, 1)));
+ ClassDB::bind_method(D_METHOD("font_draw_glyph_outline", "font_rid", "canvas", "size", "outline_size", "pos", "index", "color"), &TextServer::font_draw_glyph_outline, DEFVAL(Color(1, 1, 1)));
+
+ ClassDB::bind_method(D_METHOD("font_is_language_supported", "font_rid", "language"), &TextServer::font_is_language_supported);
+ ClassDB::bind_method(D_METHOD("font_set_language_support_override", "font_rid", "language", "supported"), &TextServer::font_set_language_support_override);
+ ClassDB::bind_method(D_METHOD("font_get_language_support_override", "font_rid", "language"), &TextServer::font_get_language_support_override);
+ ClassDB::bind_method(D_METHOD("font_remove_language_support_override", "font_rid", "language"), &TextServer::font_remove_language_support_override);
+ ClassDB::bind_method(D_METHOD("font_get_language_support_overrides", "font_rid"), &TextServer::font_get_language_support_overrides);
+
+ ClassDB::bind_method(D_METHOD("font_is_script_supported", "font_rid", "script"), &TextServer::font_is_script_supported);
+ ClassDB::bind_method(D_METHOD("font_set_script_support_override", "font_rid", "script", "supported"), &TextServer::font_set_script_support_override);
+ ClassDB::bind_method(D_METHOD("font_get_script_support_override", "font_rid", "script"), &TextServer::font_get_script_support_override);
+ ClassDB::bind_method(D_METHOD("font_remove_script_support_override", "font_rid", "script"), &TextServer::font_remove_script_support_override);
+ ClassDB::bind_method(D_METHOD("font_get_script_support_overrides", "font_rid"), &TextServer::font_get_script_support_overrides);
+
+ ClassDB::bind_method(D_METHOD("font_supported_feature_list", "font_rid"), &TextServer::font_supported_feature_list);
+ ClassDB::bind_method(D_METHOD("font_supported_variation_list", "font_rid"), &TextServer::font_supported_variation_list);
+
+ ClassDB::bind_method(D_METHOD("font_get_global_oversampling"), &TextServer::font_get_global_oversampling);
+ ClassDB::bind_method(D_METHOD("font_set_global_oversampling", "oversampling"), &TextServer::font_set_global_oversampling);
ClassDB::bind_method(D_METHOD("get_hex_code_box_size", "size", "index"), &TextServer::get_hex_code_box_size);
ClassDB::bind_method(D_METHOD("draw_hex_code_box", "canvas", "size", "pos", "index", "color"), &TextServer::draw_hex_code_box);
- ClassDB::bind_method(D_METHOD("font_get_glyph_contours", "font", "size", "index"), &TextServer::_font_get_glyph_contours);
-
/* Shaped text buffer interface */
ClassDB::bind_method(D_METHOD("create_shaped_text", "direction", "orientation"), &TextServer::create_shaped_text, DEFVAL(DIRECTION_AUTO), DEFVAL(ORIENTATION_HORIZONTAL));
@@ -302,7 +340,7 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("shaped_text_set_direction", "shaped", "direction"), &TextServer::shaped_text_set_direction, DEFVAL(DIRECTION_AUTO));
ClassDB::bind_method(D_METHOD("shaped_text_get_direction", "shaped"), &TextServer::shaped_text_get_direction);
- ClassDB::bind_method(D_METHOD("shaped_text_set_bidi_override", "shaped", "override"), &TextServer::_shaped_text_set_bidi_override);
+ ClassDB::bind_method(D_METHOD("shaped_text_set_bidi_override", "shaped", "override"), &TextServer::shaped_text_set_bidi_override);
ClassDB::bind_method(D_METHOD("shaped_text_set_orientation", "shaped", "orientation"), &TextServer::shaped_text_set_orientation, DEFVAL(ORIENTATION_HORIZONTAL));
ClassDB::bind_method(D_METHOD("shaped_text_get_orientation", "shaped"), &TextServer::shaped_text_get_orientation);
@@ -325,12 +363,19 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("shaped_text_shape", "shaped"), &TextServer::shaped_text_shape);
ClassDB::bind_method(D_METHOD("shaped_text_is_ready", "shaped"), &TextServer::shaped_text_is_ready);
- ClassDB::bind_method(D_METHOD("shaped_text_get_glyphs", "shaped"), &TextServer::_shaped_text_get_glyphs);
+ ClassDB::bind_method(D_METHOD("shaped_text_get_glyphs", "shaped"), &TextServer::_shaped_text_get_glyphs_wrapper);
+ ClassDB::bind_method(D_METHOD("shaped_text_sort_logical", "shaped"), &TextServer::_shaped_text_sort_logical_wrapper);
+ ClassDB::bind_method(D_METHOD("shaped_text_get_glyph_count", "shaped"), &TextServer::shaped_text_get_glyph_count);
ClassDB::bind_method(D_METHOD("shaped_text_get_range", "shaped"), &TextServer::shaped_text_get_range);
- ClassDB::bind_method(D_METHOD("shaped_text_get_line_breaks_adv", "shaped", "width", "start", "once", "break_flags"), &TextServer::_shaped_text_get_line_breaks_adv, DEFVAL(0), DEFVAL(true), DEFVAL(BREAK_MANDATORY | BREAK_WORD_BOUND));
- ClassDB::bind_method(D_METHOD("shaped_text_get_line_breaks", "shaped", "width", "start", "break_flags"), &TextServer::_shaped_text_get_line_breaks, DEFVAL(0), DEFVAL(BREAK_MANDATORY | BREAK_WORD_BOUND));
- ClassDB::bind_method(D_METHOD("shaped_text_get_word_breaks", "shaped"), &TextServer::_shaped_text_get_word_breaks);
+ ClassDB::bind_method(D_METHOD("shaped_text_get_line_breaks_adv", "shaped", "width", "start", "once", "break_flags"), &TextServer::shaped_text_get_line_breaks_adv, DEFVAL(0), DEFVAL(true), DEFVAL(BREAK_MANDATORY | BREAK_WORD_BOUND));
+ ClassDB::bind_method(D_METHOD("shaped_text_get_line_breaks", "shaped", "width", "start", "break_flags"), &TextServer::shaped_text_get_line_breaks, DEFVAL(0), DEFVAL(BREAK_MANDATORY | BREAK_WORD_BOUND));
+ ClassDB::bind_method(D_METHOD("shaped_text_get_word_breaks", "shaped", "grapheme_flags"), &TextServer::shaped_text_get_word_breaks);
+
+ ClassDB::bind_method(D_METHOD("shaped_text_get_trim_pos", "shaped"), &TextServer::shaped_text_get_trim_pos);
+ ClassDB::bind_method(D_METHOD("shaped_text_get_ellipsis_pos", "shaped"), &TextServer::shaped_text_get_ellipsis_pos);
+ ClassDB::bind_method(D_METHOD("shaped_text_get_ellipsis_glyphs", "shaped"), &TextServer::_shaped_text_get_ellipsis_glyphs_wrapper);
+ ClassDB::bind_method(D_METHOD("shaped_text_get_ellipsis_glyph_count", "shaped"), &TextServer::shaped_text_get_ellipsis_glyph_count);
ClassDB::bind_method(D_METHOD("shaped_text_overrun_trim_to_width", "shaped", "width", "overrun_trim_flags"), &TextServer::shaped_text_overrun_trim_to_width, DEFVAL(0), DEFVAL(OVERRUN_NO_TRIMMING));
@@ -344,8 +389,8 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("shaped_text_get_underline_position", "shaped"), &TextServer::shaped_text_get_underline_position);
ClassDB::bind_method(D_METHOD("shaped_text_get_underline_thickness", "shaped"), &TextServer::shaped_text_get_underline_thickness);
- ClassDB::bind_method(D_METHOD("shaped_text_get_carets", "shaped", "position"), &TextServer::_shaped_text_get_carets);
- ClassDB::bind_method(D_METHOD("shaped_text_get_selection", "shaped", "start", "end"), &TextServer::_shaped_text_get_selection);
+ ClassDB::bind_method(D_METHOD("shaped_text_get_carets", "shaped", "position"), &TextServer::_shaped_text_get_carets_wrapper);
+ ClassDB::bind_method(D_METHOD("shaped_text_get_selection", "shaped", "start", "end"), &TextServer::shaped_text_get_selection);
ClassDB::bind_method(D_METHOD("shaped_text_hit_test_grapheme", "shaped", "coords"), &TextServer::shaped_text_hit_test_grapheme);
ClassDB::bind_method(D_METHOD("shaped_text_hit_test_position", "shaped", "coords"), &TextServer::shaped_text_hit_test_position);
@@ -356,7 +401,7 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("shaped_text_draw", "shaped", "canvas", "pos", "clip_l", "clip_r", "color"), &TextServer::shaped_text_draw, DEFVAL(-1), DEFVAL(-1), DEFVAL(Color(1, 1, 1)));
ClassDB::bind_method(D_METHOD("shaped_text_draw_outline", "shaped", "canvas", "pos", "clip_l", "clip_r", "outline_size", "color"), &TextServer::shaped_text_draw_outline, DEFVAL(-1), DEFVAL(-1), DEFVAL(1), DEFVAL(Color(1, 1, 1)));
- ClassDB::bind_method(D_METHOD("shaped_text_get_dominant_direciton_in_range", "shaped", "start", "end"), &TextServer::shaped_text_get_dominant_direciton_in_range);
+ ClassDB::bind_method(D_METHOD("shaped_text_get_dominant_direction_in_range", "shaped", "start", "end"), &TextServer::shaped_text_get_dominant_direction_in_range);
ClassDB::bind_method(D_METHOD("format_number", "number", "language"), &TextServer::format_number, DEFVAL(""));
ClassDB::bind_method(D_METHOD("parse_number", "number", "language"), &TextServer::parse_number, DEFVAL(""));
@@ -377,12 +422,14 @@ void TextServer::_bind_methods() {
BIND_ENUM_CONSTANT(JUSTIFICATION_WORD_BOUND);
BIND_ENUM_CONSTANT(JUSTIFICATION_TRIM_EDGE_SPACES);
BIND_ENUM_CONSTANT(JUSTIFICATION_AFTER_LAST_TAB);
+ BIND_ENUM_CONSTANT(JUSTIFICATION_CONSTRAIN_ELLIPSIS);
/* LineBreakFlag */
BIND_ENUM_CONSTANT(BREAK_NONE);
BIND_ENUM_CONSTANT(BREAK_MANDATORY);
BIND_ENUM_CONSTANT(BREAK_WORD_BOUND);
BIND_ENUM_CONSTANT(BREAK_GRAPHEME_BOUND);
+ BIND_ENUM_CONSTANT(BREAK_WORD_BOUND_ADAPTIVE);
/* TextOverrunFlag */
BIND_ENUM_CONSTANT(OVERRUN_NO_TRIMMING);
@@ -390,8 +437,10 @@ void TextServer::_bind_methods() {
BIND_ENUM_CONSTANT(OVERRUN_TRIM_WORD_ONLY);
BIND_ENUM_CONSTANT(OVERRUN_ADD_ELLIPSIS);
BIND_ENUM_CONSTANT(OVERRUN_ENFORCE_ELLIPSIS);
+ BIND_ENUM_CONSTANT(OVERRUN_JUSTIFICATION_AWARE);
/* GraphemeFlag */
+ BIND_ENUM_CONSTANT(GRAPHEME_IS_VALID);
BIND_ENUM_CONSTANT(GRAPHEME_IS_RTL);
BIND_ENUM_CONSTANT(GRAPHEME_IS_VIRTUAL);
BIND_ENUM_CONSTANT(GRAPHEME_IS_SPACE);
@@ -400,6 +449,8 @@ void TextServer::_bind_methods() {
BIND_ENUM_CONSTANT(GRAPHEME_IS_TAB);
BIND_ENUM_CONSTANT(GRAPHEME_IS_ELONGATION);
BIND_ENUM_CONSTANT(GRAPHEME_IS_PUNCTUATION);
+ BIND_ENUM_CONSTANT(GRAPHEME_IS_UNDERSCORE);
+ BIND_ENUM_CONSTANT(GRAPHEME_IS_CONNECTED);
/* Hinting */
BIND_ENUM_CONSTANT(HINTING_NONE);
@@ -420,109 +471,65 @@ void TextServer::_bind_methods() {
BIND_ENUM_CONSTANT(CONTOUR_CURVE_TAG_ON);
BIND_ENUM_CONSTANT(CONTOUR_CURVE_TAG_OFF_CONIC);
BIND_ENUM_CONSTANT(CONTOUR_CURVE_TAG_OFF_CUBIC);
-}
-Vector3 TextServer::hex_code_box_font_size[2] = { Vector3(5, 5, 1), Vector3(10, 10, 2) };
-Ref<CanvasTexture> TextServer::hex_code_box_font_tex[2] = { nullptr, nullptr };
-
-void TextServer::initialize_hex_code_box_fonts() {
- static unsigned int tamsyn5x9_png_len = 175;
- static unsigned char tamsyn5x9_png[] = {
- 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
- 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x05,
- 0x04, 0x03, 0x00, 0x00, 0x00, 0x20, 0x7c, 0x76, 0xda, 0x00, 0x00, 0x00,
- 0x0f, 0x50, 0x4c, 0x54, 0x45, 0xfd, 0x07, 0x00, 0x00, 0x00, 0x00, 0x06,
- 0x7e, 0x74, 0x00, 0x40, 0xc6, 0xff, 0xff, 0xff, 0x47, 0x9a, 0xd4, 0xc7,
- 0x00, 0x00, 0x00, 0x01, 0x74, 0x52, 0x4e, 0x53, 0x00, 0x40, 0xe6, 0xd8,
- 0x66, 0x00, 0x00, 0x00, 0x4e, 0x49, 0x44, 0x41, 0x54, 0x08, 0x1d, 0x05,
- 0xc1, 0x21, 0x01, 0x00, 0x00, 0x00, 0x83, 0x30, 0x04, 0xc1, 0x10, 0xef,
- 0x9f, 0xe9, 0x1b, 0x86, 0x2c, 0x17, 0xb9, 0xcc, 0x65, 0x0c, 0x73, 0x38,
- 0xc7, 0xe6, 0x22, 0x19, 0x88, 0x98, 0x10, 0x48, 0x4a, 0x29, 0x85, 0x14,
- 0x02, 0x89, 0x10, 0xa3, 0x1c, 0x0b, 0x31, 0xd6, 0xe6, 0x08, 0x69, 0x39,
- 0x48, 0x44, 0xa0, 0x0d, 0x4a, 0x22, 0xa1, 0x94, 0x42, 0x0a, 0x01, 0x63,
- 0x6d, 0x0e, 0x72, 0x18, 0x61, 0x8c, 0x74, 0x38, 0xc7, 0x26, 0x1c, 0xf3,
- 0x71, 0x16, 0x15, 0x27, 0x6a, 0xc2, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x49,
- 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
- };
+ /* Font Spacing*/
+ BIND_ENUM_CONSTANT(SPACING_GLYPH);
+ BIND_ENUM_CONSTANT(SPACING_SPACE);
+ BIND_ENUM_CONSTANT(SPACING_TOP);
+ BIND_ENUM_CONSTANT(SPACING_BOTTOM);
+}
- static unsigned int tamsyn10x20_png_len = 270;
- static unsigned char tamsyn10x20_png[] = {
- 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
- 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x0a,
- 0x04, 0x03, 0x00, 0x00, 0x00, 0xc1, 0x66, 0x48, 0x96, 0x00, 0x00, 0x00,
- 0x0f, 0x50, 0x4c, 0x54, 0x45, 0x00, 0x00, 0x00, 0xf9, 0x07, 0x00, 0x5d,
- 0x71, 0xa5, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x49, 0xdb, 0xcb, 0x7f,
- 0x00, 0x00, 0x00, 0x01, 0x74, 0x52, 0x4e, 0x53, 0x00, 0x40, 0xe6, 0xd8,
- 0x66, 0x00, 0x00, 0x00, 0xad, 0x49, 0x44, 0x41, 0x54, 0x28, 0xcf, 0xa5,
- 0x92, 0x4b, 0x0e, 0x03, 0x31, 0x08, 0x43, 0xdf, 0x82, 0x83, 0x79, 0xe1,
- 0xfb, 0x9f, 0xa9, 0x0b, 0x3e, 0x61, 0xa6, 0x1f, 0x55, 0xad, 0x14, 0x31,
- 0x66, 0x42, 0x1c, 0x70, 0x0c, 0xb6, 0x00, 0x01, 0xb6, 0x08, 0xdb, 0x00,
- 0x8d, 0xc2, 0x14, 0xb2, 0x55, 0xa1, 0xfe, 0x09, 0xc2, 0x26, 0xdc, 0x25,
- 0x75, 0x22, 0x97, 0x1a, 0x25, 0x77, 0x28, 0x31, 0x02, 0x80, 0xc8, 0xdd,
- 0x2c, 0x11, 0x1a, 0x54, 0x9f, 0xc8, 0xa2, 0x8a, 0x06, 0xa9, 0x93, 0x22,
- 0xbd, 0xd4, 0xd0, 0x0c, 0xcf, 0x81, 0x2b, 0xca, 0xbb, 0x83, 0xe0, 0x10,
- 0xe6, 0xad, 0xff, 0x10, 0x2a, 0x66, 0x34, 0x41, 0x58, 0x35, 0x54, 0x49,
- 0x5a, 0x63, 0xa5, 0xc2, 0x87, 0xab, 0x52, 0x76, 0x9a, 0xba, 0xc6, 0xf4,
- 0x75, 0x7a, 0x9e, 0x3c, 0x46, 0x86, 0x5c, 0xa3, 0xfd, 0x87, 0x0e, 0x75,
- 0x08, 0x7b, 0xee, 0x7e, 0xea, 0x21, 0x5c, 0x4f, 0xf6, 0xc5, 0xc8, 0x4b,
- 0xb9, 0x11, 0xf2, 0xd6, 0xe1, 0x8f, 0x84, 0x62, 0x7b, 0x67, 0xf9, 0x24,
- 0xde, 0x6d, 0xbc, 0xb2, 0xcd, 0xb1, 0xf3, 0xf2, 0x2f, 0xe8, 0xe2, 0xe4,
- 0xae, 0x4b, 0x4f, 0xcf, 0x2b, 0xdc, 0x8d, 0x0d, 0xf0, 0x00, 0x8f, 0x22,
- 0x26, 0x65, 0x75, 0x8a, 0xe6, 0x84, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45,
- 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
- };
+Vector2 TextServer::get_hex_code_box_size(int p_size, char32_t p_index) const {
+ int w = ((p_index <= 0xFF) ? 1 : ((p_index <= 0xFFFF) ? 2 : 3));
+ int sp = MAX(0, w - 1);
+ int sz = MAX(1, p_size / 15);
- if (RenderingServer::get_singleton() != nullptr) {
- Vector<uint8_t> hex_box_data;
-
- Ref<Image> image;
- image.instantiate();
-
- Ref<ImageTexture> hex_code_image_tex[2];
-
- hex_box_data.resize(tamsyn5x9_png_len);
- memcpy(hex_box_data.ptrw(), tamsyn5x9_png, tamsyn5x9_png_len);
- image->load_png_from_buffer(hex_box_data);
- hex_code_image_tex[0].instantiate();
- hex_code_image_tex[0]->create_from_image(image);
- hex_code_box_font_tex[0].instantiate();
- hex_code_box_font_tex[0]->set_diffuse_texture(hex_code_image_tex[0]);
- hex_code_box_font_tex[0]->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST);
- hex_box_data.clear();
-
- hex_box_data.resize(tamsyn10x20_png_len);
- memcpy(hex_box_data.ptrw(), tamsyn10x20_png, tamsyn10x20_png_len);
- image->load_png_from_buffer(hex_box_data);
- hex_code_image_tex[1].instantiate();
- hex_code_image_tex[1]->create_from_image(image);
- hex_code_box_font_tex[1].instantiate();
- hex_code_box_font_tex[1]->set_diffuse_texture(hex_code_image_tex[1]);
- hex_code_box_font_tex[1]->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST);
- hex_box_data.clear();
- }
+ return Vector2(4 + 3 * w + sp + 1, 15) * sz;
}
-void TextServer::finish_hex_code_box_fonts() {
- if (hex_code_box_font_tex[0].is_valid()) {
- hex_code_box_font_tex[0].unref();
+void TextServer::_draw_hex_code_box_number(RID p_canvas, int p_size, const Vector2 &p_pos, uint8_t p_index, const Color &p_color) const {
+ static uint8_t chars[] = { 0x7E, 0x30, 0x6D, 0x79, 0x33, 0x5B, 0x5F, 0x70, 0x7F, 0x7B, 0x77, 0x1F, 0x4E, 0x3D, 0x4F, 0x47, 0x00 };
+ uint8_t x = chars[p_index];
+ if (x & (1 << 6)) {
+ RenderingServer::get_singleton()->canvas_item_add_rect(p_canvas, Rect2(p_pos, Size2(3, 1) * p_size), p_color);
+ }
+ if (x & (1 << 5)) {
+ RenderingServer::get_singleton()->canvas_item_add_rect(p_canvas, Rect2(p_pos + Point2(2, 0) * p_size, Size2(1, 3) * p_size), p_color);
+ }
+ if (x & (1 << 4)) {
+ RenderingServer::get_singleton()->canvas_item_add_rect(p_canvas, Rect2(p_pos + Point2(2, 2) * p_size, Size2(1, 3) * p_size), p_color);
+ }
+ if (x & (1 << 3)) {
+ RenderingServer::get_singleton()->canvas_item_add_rect(p_canvas, Rect2(p_pos + Point2(0, 4) * p_size, Size2(3, 1) * p_size), p_color);
+ }
+ if (x & (1 << 2)) {
+ RenderingServer::get_singleton()->canvas_item_add_rect(p_canvas, Rect2(p_pos + Point2(0, 2) * p_size, Size2(1, 3) * p_size), p_color);
+ }
+ if (x & (1 << 1)) {
+ RenderingServer::get_singleton()->canvas_item_add_rect(p_canvas, Rect2(p_pos, Size2(1, 3) * p_size), p_color);
}
- if (hex_code_box_font_tex[1].is_valid()) {
- hex_code_box_font_tex[1].unref();
+ if (x & (1 << 0)) {
+ RenderingServer::get_singleton()->canvas_item_add_rect(p_canvas, Rect2(p_pos + Point2(0, 2) * p_size, Size2(3, 1) * p_size), p_color);
}
}
-Vector2 TextServer::get_hex_code_box_size(int p_size, char32_t p_index) const {
- int fnt = (p_size < 20) ? 0 : 1;
+void TextServer::draw_hex_code_box(RID p_canvas, int p_size, const Vector2 &p_pos, char32_t p_index, const Color &p_color) const {
+ if (p_index == 0) {
+ return;
+ }
- float w = ((p_index <= 0xFF) ? 1 : ((p_index <= 0xFFFF) ? 2 : 3)) * hex_code_box_font_size[fnt].x;
- float h = 2 * hex_code_box_font_size[fnt].y;
- return Vector2(w + 4, h + 3 + 2 * hex_code_box_font_size[fnt].z);
-}
+ int w = ((p_index <= 0xFF) ? 1 : ((p_index <= 0xFFFF) ? 2 : 3));
+ int sp = MAX(0, w - 1);
+ int sz = MAX(1, p_size / 15);
-void TextServer::draw_hex_code_box(RID p_canvas, int p_size, const Vector2 &p_pos, char32_t p_index, const Color &p_color) const {
- int fnt = (p_size < 20) ? 0 : 1;
+ Size2 size = Vector2(4 + 3 * w + sp, 15) * sz;
+ Point2 pos = p_pos - Point2i(0, size.y * 0.85);
- ERR_FAIL_COND(hex_code_box_font_tex[fnt].is_null());
+ // Draw frame.
+ RenderingServer::get_singleton()->canvas_item_add_rect(p_canvas, Rect2(pos + Point2(0, 0), Size2(sz, size.y)), p_color);
+ RenderingServer::get_singleton()->canvas_item_add_rect(p_canvas, Rect2(pos + Point2(size.x - sz, 0), Size2(sz, size.y)), p_color);
+ RenderingServer::get_singleton()->canvas_item_add_rect(p_canvas, Rect2(pos + Point2(0, 0), Size2(size.x, sz)), p_color);
+ RenderingServer::get_singleton()->canvas_item_add_rect(p_canvas, Rect2(pos + Point2(0, size.y - sz), Size2(size.x, sz)), p_color);
uint8_t a = p_index & 0x0F;
uint8_t b = (p_index >> 4) & 0x0F;
@@ -531,66 +538,40 @@ void TextServer::draw_hex_code_box(RID p_canvas, int p_size, const Vector2 &p_po
uint8_t e = (p_index >> 16) & 0x0F;
uint8_t f = (p_index >> 20) & 0x0F;
- Vector2 pos = p_pos;
- Rect2 dest = Rect2(Vector2(), Vector2(hex_code_box_font_size[fnt].x, hex_code_box_font_size[fnt].y));
-
- float w = ((p_index <= 0xFF) ? 1 : ((p_index <= 0xFFFF) ? 2 : 3)) * hex_code_box_font_size[fnt].x;
- float h = 2 * hex_code_box_font_size[fnt].y;
-
- pos.y -= Math::floor((h + 3 + hex_code_box_font_size[fnt].z) * 0.75);
-
- RenderingServer::get_singleton()->canvas_item_add_rect(p_canvas, Rect2(pos + Point2(0, 0), Size2(1, h + 2 + 2 * hex_code_box_font_size[fnt].z)), p_color);
- RenderingServer::get_singleton()->canvas_item_add_rect(p_canvas, Rect2(pos + Point2(w + 2, 0), Size2(1, h + 2 + 2 * hex_code_box_font_size[fnt].z)), p_color);
- RenderingServer::get_singleton()->canvas_item_add_rect(p_canvas, Rect2(pos + Point2(0, 0), Size2(w + 2, 1)), p_color);
- RenderingServer::get_singleton()->canvas_item_add_rect(p_canvas, Rect2(pos + Point2(0, h + 2 + 2 * hex_code_box_font_size[fnt].z), Size2(w + 2, 1)), p_color);
-
- pos += Point2(2, 2);
+ // Draw hex code.
if (p_index <= 0xFF) {
- dest.position = pos + Vector2(hex_code_box_font_size[fnt].x, hex_code_box_font_size[fnt].y) * Point2(0, 0);
- RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, dest, hex_code_box_font_tex[fnt]->get_rid(), Rect2(Point2(b * hex_code_box_font_size[fnt].x, 0), dest.size), p_color, false, false);
- dest.position = pos + Vector2(hex_code_box_font_size[fnt].x, hex_code_box_font_size[fnt].y) * Point2(0, 1) + Point2(0, hex_code_box_font_size[fnt].z);
- RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, dest, hex_code_box_font_tex[fnt]->get_rid(), Rect2(Point2(a * hex_code_box_font_size[fnt].x, 0), dest.size), p_color, false, false);
+ _draw_hex_code_box_number(p_canvas, sz, pos + Point2(2, 2) * sz, b, p_color);
+ _draw_hex_code_box_number(p_canvas, sz, pos + Point2(2, 8) * sz, a, p_color);
} else if (p_index <= 0xFFFF) {
- dest.position = pos + Vector2(hex_code_box_font_size[fnt].x, hex_code_box_font_size[fnt].y) * Point2(0, 0);
- RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, dest, hex_code_box_font_tex[fnt]->get_rid(), Rect2(Point2(d * hex_code_box_font_size[fnt].x, 0), dest.size), p_color, false, false);
- dest.position = pos + Vector2(hex_code_box_font_size[fnt].x, hex_code_box_font_size[fnt].y) * Point2(1, 0);
- RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, dest, hex_code_box_font_tex[fnt]->get_rid(), Rect2(Point2(c * hex_code_box_font_size[fnt].x, 0), dest.size), p_color, false, false);
- dest.position = pos + Vector2(hex_code_box_font_size[fnt].x, hex_code_box_font_size[fnt].y) * Point2(0, 1) + Point2(0, hex_code_box_font_size[fnt].z);
- RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, dest, hex_code_box_font_tex[fnt]->get_rid(), Rect2(Point2(b * hex_code_box_font_size[fnt].x, 0), dest.size), p_color, false, false);
- dest.position = pos + Vector2(hex_code_box_font_size[fnt].x, hex_code_box_font_size[fnt].y) * Point2(1, 1) + Point2(0, hex_code_box_font_size[fnt].z);
- RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, dest, hex_code_box_font_tex[fnt]->get_rid(), Rect2(Point2(a * hex_code_box_font_size[fnt].x, 0), dest.size), p_color, false, false);
+ _draw_hex_code_box_number(p_canvas, sz, pos + Point2(2, 2) * sz, d, p_color);
+ _draw_hex_code_box_number(p_canvas, sz, pos + Point2(6, 2) * sz, c, p_color);
+ _draw_hex_code_box_number(p_canvas, sz, pos + Point2(2, 8) * sz, b, p_color);
+ _draw_hex_code_box_number(p_canvas, sz, pos + Point2(6, 8) * sz, a, p_color);
} else {
- dest.position = pos + Vector2(hex_code_box_font_size[fnt].x, hex_code_box_font_size[fnt].y) * Point2(0, 0);
- RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, dest, hex_code_box_font_tex[fnt]->get_rid(), Rect2(Point2(f * hex_code_box_font_size[fnt].x, 0), dest.size), p_color, false, false);
- dest.position = pos + Vector2(hex_code_box_font_size[fnt].x, hex_code_box_font_size[fnt].y) * Point2(1, 0);
- RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, dest, hex_code_box_font_tex[fnt]->get_rid(), Rect2(Point2(e * hex_code_box_font_size[fnt].x, 0), dest.size), p_color, false, false);
- dest.position = pos + Vector2(hex_code_box_font_size[fnt].x, hex_code_box_font_size[fnt].y) * Point2(2, 0);
- RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, dest, hex_code_box_font_tex[fnt]->get_rid(), Rect2(Point2(d * hex_code_box_font_size[fnt].x, 0), dest.size), p_color, false, false);
- dest.position = pos + Vector2(hex_code_box_font_size[fnt].x, hex_code_box_font_size[fnt].y) * Point2(0, 1) + Point2(0, hex_code_box_font_size[fnt].z);
- RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, dest, hex_code_box_font_tex[fnt]->get_rid(), Rect2(Point2(c * hex_code_box_font_size[fnt].x, 0), dest.size), p_color, false, false);
- dest.position = pos + Vector2(hex_code_box_font_size[fnt].x, hex_code_box_font_size[fnt].y) * Point2(1, 1) + Point2(0, hex_code_box_font_size[fnt].z);
- RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, dest, hex_code_box_font_tex[fnt]->get_rid(), Rect2(Point2(b * hex_code_box_font_size[fnt].x, 0), dest.size), p_color, false, false);
- dest.position = pos + Vector2(hex_code_box_font_size[fnt].x, hex_code_box_font_size[fnt].y) * Point2(2, 1) + Point2(0, hex_code_box_font_size[fnt].z);
- RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, dest, hex_code_box_font_tex[fnt]->get_rid(), Rect2(Point2(a * hex_code_box_font_size[fnt].x, 0), dest.size), p_color, false, false);
+ _draw_hex_code_box_number(p_canvas, sz, pos + Point2(2, 2) * sz, f, p_color);
+ _draw_hex_code_box_number(p_canvas, sz, pos + Point2(6, 2) * sz, e, p_color);
+ _draw_hex_code_box_number(p_canvas, sz, pos + Point2(10, 2) * sz, d, p_color);
+ _draw_hex_code_box_number(p_canvas, sz, pos + Point2(2, 8) * sz, c, p_color);
+ _draw_hex_code_box_number(p_canvas, sz, pos + Point2(6, 8) * sz, b, p_color);
+ _draw_hex_code_box_number(p_canvas, sz, pos + Point2(10, 8) * sz, a, p_color);
}
}
-Vector<Vector2i> TextServer::shaped_text_get_line_breaks_adv(RID p_shaped, const Vector<float> &p_width, int p_start, bool p_once, uint8_t /*TextBreakFlag*/ p_break_flags) const {
- Vector<Vector2i> lines;
+PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(RID p_shaped, const PackedFloat32Array &p_width, int p_start, bool p_once, uint16_t /*TextBreakFlag*/ p_break_flags) const {
+ PackedInt32Array lines;
ERR_FAIL_COND_V(p_width.is_empty(), lines);
const_cast<TextServer *>(this)->shaped_text_update_breaks(p_shaped);
- const Vector<Glyph> &logical = const_cast<TextServer *>(this)->shaped_text_sort_logical(p_shaped);
const Vector2i &range = shaped_text_get_range(p_shaped);
- float width = 0.f;
+ real_t width = 0.f;
int line_start = MAX(p_start, range.x);
int last_safe_break = -1;
int chunk = 0;
- int l_size = logical.size();
- const Glyph *l_gl = logical.ptr();
+ int l_size = shaped_text_get_glyph_count(p_shaped);
+ const Glyph *l_gl = const_cast<TextServer *>(this)->shaped_text_sort_logical(p_shaped);
for (int i = 0; i < l_size; i++) {
if (l_gl[i].start < p_start) {
@@ -598,7 +579,8 @@ Vector<Vector2i> TextServer::shaped_text_get_line_breaks_adv(RID p_shaped, const
}
if (l_gl[i].count > 0) {
if ((p_width[chunk] > 0) && (width + l_gl[i].advance > p_width[chunk]) && (last_safe_break >= 0)) {
- lines.push_back(Vector2i(line_start, l_gl[last_safe_break].end));
+ lines.push_back(line_start);
+ lines.push_back(l_gl[last_safe_break].end);
line_start = l_gl[last_safe_break].end;
i = last_safe_break;
last_safe_break = -1;
@@ -614,7 +596,8 @@ Vector<Vector2i> TextServer::shaped_text_get_line_breaks_adv(RID p_shaped, const
}
if ((p_break_flags & BREAK_MANDATORY) == BREAK_MANDATORY) {
if ((l_gl[i].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD) {
- lines.push_back(Vector2i(line_start, l_gl[i].end));
+ lines.push_back(line_start);
+ lines.push_back(l_gl[i].end);
line_start = l_gl[i].end;
last_safe_break = -1;
width = 0;
@@ -638,37 +621,40 @@ Vector<Vector2i> TextServer::shaped_text_get_line_breaks_adv(RID p_shaped, const
}
if (l_size > 0) {
- lines.push_back(Vector2i(line_start, range.y));
+ if (lines.size() == 0 || lines[lines.size() - 1] < range.y) {
+ lines.push_back(line_start);
+ lines.push_back(range.y);
+ }
} else {
- lines.push_back(Vector2i(0, 0));
+ lines.push_back(0);
+ lines.push_back(0);
}
return lines;
}
-Vector<Vector2i> TextServer::shaped_text_get_line_breaks(RID p_shaped, float p_width, int p_start, uint8_t /*TextBreakFlag*/ p_break_flags) const {
- Vector<Vector2i> lines;
+PackedInt32Array TextServer::shaped_text_get_line_breaks(RID p_shaped, real_t p_width, int p_start, uint16_t /*TextBreakFlag*/ p_break_flags) const {
+ PackedInt32Array lines;
const_cast<TextServer *>(this)->shaped_text_update_breaks(p_shaped);
- const Vector<Glyph> &logical = const_cast<TextServer *>(this)->shaped_text_sort_logical(p_shaped);
const Vector2i &range = shaped_text_get_range(p_shaped);
- float width = 0.f;
+ real_t width = 0.f;
int line_start = MAX(p_start, range.x);
int last_safe_break = -1;
int word_count = 0;
- int l_size = logical.size();
- const Glyph *l_gl = logical.ptr();
+
+ int l_size = shaped_text_get_glyph_count(p_shaped);
+ const Glyph *l_gl = const_cast<TextServer *>(this)->shaped_text_sort_logical(p_shaped);
for (int i = 0; i < l_size; i++) {
if (l_gl[i].start < p_start) {
continue;
}
if (l_gl[i].count > 0) {
- //Ignore trailing spaces.
- bool is_space = (l_gl[i].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE;
- if ((p_width > 0) && (width + (is_space ? 0 : l_gl[i].advance) > p_width) && (last_safe_break >= 0)) {
- lines.push_back(Vector2i(line_start, l_gl[last_safe_break].end));
+ if ((p_width > 0) && (width + l_gl[i].advance * l_gl[i].repeat > p_width) && (last_safe_break >= 0)) {
+ lines.push_back(line_start);
+ lines.push_back(l_gl[last_safe_break].end);
line_start = l_gl[last_safe_break].end;
i = last_safe_break;
last_safe_break = -1;
@@ -678,7 +664,8 @@ Vector<Vector2i> TextServer::shaped_text_get_line_breaks(RID p_shaped, float p_w
}
if ((p_break_flags & BREAK_MANDATORY) == BREAK_MANDATORY) {
if ((l_gl[i].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD) {
- lines.push_back(Vector2i(line_start, l_gl[i].end));
+ lines.push_back(line_start);
+ lines.push_back(l_gl[i].end);
line_start = l_gl[i].end;
last_safe_break = -1;
width = 0;
@@ -698,67 +685,66 @@ Vector<Vector2i> TextServer::shaped_text_get_line_breaks(RID p_shaped, float p_w
last_safe_break = i;
}
}
- width += l_gl[i].advance;
+ width += l_gl[i].advance * l_gl[i].repeat;
}
if (l_size > 0) {
- if (lines.size() == 0 || lines[lines.size() - 1].y < range.y) {
- lines.push_back(Vector2i(line_start, range.y));
+ if (lines.size() == 0 || lines[lines.size() - 1] < range.y) {
+ lines.push_back(line_start);
+ lines.push_back(range.y);
}
} else {
- lines.push_back(Vector2i(0, 0));
+ lines.push_back(0);
+ lines.push_back(0);
}
return lines;
}
-Vector<Vector2i> TextServer::shaped_text_get_word_breaks(RID p_shaped, int p_grapheme_flags) const {
- Vector<Vector2i> words;
+PackedInt32Array TextServer::shaped_text_get_word_breaks(RID p_shaped, int p_grapheme_flags) const {
+ PackedInt32Array words;
const_cast<TextServer *>(this)->shaped_text_update_justification_ops(p_shaped);
- const Vector<Glyph> &logical = const_cast<TextServer *>(this)->shaped_text_sort_logical(p_shaped);
const Vector2i &range = shaped_text_get_range(p_shaped);
int word_start = range.x;
- int l_size = logical.size();
- const Glyph *l_gl = logical.ptr();
+ int l_size = shaped_text_get_glyph_count(p_shaped);
+ const Glyph *l_gl = const_cast<TextServer *>(this)->shaped_text_sort_logical(p_shaped);
for (int i = 0; i < l_size; i++) {
if (l_gl[i].count > 0) {
if ((l_gl[i].flags & p_grapheme_flags) != 0) {
- words.push_back(Vector2i(word_start, l_gl[i].start));
+ words.push_back(word_start);
+ words.push_back(l_gl[i].start);
word_start = l_gl[i].end;
}
}
}
if (l_size > 0) {
- words.push_back(Vector2i(word_start, range.y));
+ words.push_back(word_start);
+ words.push_back(range.y);
}
return words;
}
-TextServer::TrimData TextServer::shaped_text_get_trim_data(RID p_shaped) const {
- WARN_PRINT("Getting overrun data not supported by this TextServer.");
- return TrimData();
-}
-
-void TextServer::shaped_text_get_carets(RID p_shaped, int p_position, Rect2 &p_leading_caret, Direction &p_leading_dir, Rect2 &p_trailing_caret, Direction &p_trailing_dir) const {
+CaretInfo TextServer::shaped_text_get_carets(RID p_shaped, int p_position) const {
Vector<Rect2> carets;
- const Vector<TextServer::Glyph> visual = shaped_text_get_glyphs(p_shaped);
+
TextServer::Orientation orientation = shaped_text_get_orientation(p_shaped);
const Vector2 &range = shaped_text_get_range(p_shaped);
- float ascent = shaped_text_get_ascent(p_shaped);
- float descent = shaped_text_get_descent(p_shaped);
- float height = (ascent + descent) / 2;
+ real_t ascent = shaped_text_get_ascent(p_shaped);
+ real_t descent = shaped_text_get_descent(p_shaped);
+ real_t height = (ascent + descent) / 2;
- float off = 0.0f;
- p_leading_dir = DIRECTION_AUTO;
- p_trailing_dir = DIRECTION_AUTO;
+ real_t off = 0.0f;
+ CaretInfo caret;
+ caret.l_dir = DIRECTION_AUTO;
+ caret.t_dir = DIRECTION_AUTO;
- int v_size = visual.size();
- const Glyph *glyphs = visual.ptr();
+ int v_size = shaped_text_get_glyph_count(p_shaped);
+ const Glyph *glyphs = shaped_text_get_glyphs(p_shaped);
for (int i = 0; i < v_size; i++) {
if (glyphs[i].count > 0) {
@@ -774,13 +760,13 @@ void TextServer::shaped_text_get_carets(RID p_shaped, int p_position, Rect2 &p_l
cr.position.y = -ascent;
cr.position.x = off;
if ((glyphs[i].flags & GRAPHEME_IS_RTL) == GRAPHEME_IS_RTL) {
- p_trailing_dir = DIRECTION_RTL;
+ caret.t_dir = DIRECTION_RTL;
for (int j = 0; j < glyphs[i].count; j++) {
cr.position.x += glyphs[i + j].advance * glyphs[i + j].repeat;
cr.size.x -= glyphs[i + j].advance * glyphs[i + j].repeat;
}
} else {
- p_trailing_dir = DIRECTION_LTR;
+ caret.t_dir = DIRECTION_LTR;
for (int j = 0; j < glyphs[i].count; j++) {
cr.size.x += glyphs[i + j].advance * glyphs[i + j].repeat;
}
@@ -794,19 +780,19 @@ void TextServer::shaped_text_get_carets(RID p_shaped, int p_position, Rect2 &p_l
cr.position.x = -ascent;
cr.position.y = off;
if ((glyphs[i].flags & GRAPHEME_IS_RTL) == GRAPHEME_IS_RTL) {
- p_trailing_dir = DIRECTION_RTL;
+ caret.t_dir = DIRECTION_RTL;
for (int j = 0; j < glyphs[i].count; j++) {
cr.position.y += glyphs[i + j].advance * glyphs[i + j].repeat;
cr.size.y -= glyphs[i + j].advance * glyphs[i + j].repeat;
}
} else {
- p_trailing_dir = DIRECTION_LTR;
+ caret.t_dir = DIRECTION_LTR;
for (int j = 0; j < glyphs[i].count; j++) {
cr.size.y += glyphs[i + j].advance * glyphs[i + j].repeat;
}
}
}
- p_trailing_caret = cr;
+ caret.t_caret = cr;
}
// Caret after grapheme (bottom / right).
if (p_position == glyphs[i].end && ((glyphs[i].flags & GRAPHEME_IS_VIRTUAL) != GRAPHEME_IS_VIRTUAL)) {
@@ -821,13 +807,13 @@ void TextServer::shaped_text_get_carets(RID p_shaped, int p_position, Rect2 &p_l
}
cr.position.x = off;
if ((glyphs[i].flags & GRAPHEME_IS_RTL) != GRAPHEME_IS_RTL) {
- p_leading_dir = DIRECTION_LTR;
+ caret.l_dir = DIRECTION_LTR;
for (int j = 0; j < glyphs[i].count; j++) {
cr.position.x += glyphs[i + j].advance * glyphs[i + j].repeat;
cr.size.x -= glyphs[i + j].advance * glyphs[i + j].repeat;
}
} else {
- p_leading_dir = DIRECTION_RTL;
+ caret.l_dir = DIRECTION_RTL;
for (int j = 0; j < glyphs[i].count; j++) {
cr.size.x += glyphs[i + j].advance * glyphs[i + j].repeat;
}
@@ -843,27 +829,27 @@ void TextServer::shaped_text_get_carets(RID p_shaped, int p_position, Rect2 &p_l
}
cr.position.y = off;
if ((glyphs[i].flags & GRAPHEME_IS_RTL) != GRAPHEME_IS_RTL) {
- p_leading_dir = DIRECTION_LTR;
+ caret.l_dir = DIRECTION_LTR;
for (int j = 0; j < glyphs[i].count; j++) {
cr.position.y += glyphs[i + j].advance * glyphs[i + j].repeat;
cr.size.y -= glyphs[i + j].advance * glyphs[i + j].repeat;
}
} else {
- p_leading_dir = DIRECTION_RTL;
+ caret.l_dir = DIRECTION_RTL;
for (int j = 0; j < glyphs[i].count; j++) {
cr.size.y += glyphs[i + j].advance * glyphs[i + j].repeat;
}
}
}
- p_leading_caret = cr;
+ caret.l_caret = cr;
}
// Caret inside grapheme (middle).
if (p_position > glyphs[i].start && p_position < glyphs[i].end && (glyphs[i].flags & GRAPHEME_IS_VIRTUAL) != GRAPHEME_IS_VIRTUAL) {
- float advance = 0.f;
+ real_t advance = 0.f;
for (int j = 0; j < glyphs[i].count; j++) {
advance += glyphs[i + j].advance * glyphs[i + j].repeat;
}
- float char_adv = advance / (float)(glyphs[i].end - glyphs[i].start);
+ real_t char_adv = advance / (real_t)(glyphs[i].end - glyphs[i].start);
Rect2 cr;
if (orientation == ORIENTATION_HORIZONTAL) {
cr.size.x = 1.0f;
@@ -884,17 +870,29 @@ void TextServer::shaped_text_get_carets(RID p_shaped, int p_position, Rect2 &p_l
cr.position.y = off + char_adv * (p_position - glyphs[i].start);
}
}
- p_trailing_caret = cr;
- p_leading_caret = cr;
+ caret.t_caret = cr;
+ caret.l_caret = cr;
}
}
off += glyphs[i].advance * glyphs[i].repeat;
}
+ return caret;
}
-TextServer::Direction TextServer::shaped_text_get_dominant_direciton_in_range(RID p_shaped, int p_start, int p_end) const {
- const Vector<TextServer::Glyph> visual = shaped_text_get_glyphs(p_shaped);
+Dictionary TextServer::_shaped_text_get_carets_wrapper(RID p_shaped, int p_position) const {
+ Dictionary ret;
+
+ CaretInfo caret = shaped_text_get_carets(p_shaped, p_position);
+ ret["leading_rect"] = caret.l_caret;
+ ret["leading_direction"] = caret.l_dir;
+ ret["trailing_rect"] = caret.t_caret;
+ ret["trailing_direction"] = caret.t_dir;
+
+ return ret;
+}
+
+TextServer::Direction TextServer::shaped_text_get_dominant_direction_in_range(RID p_shaped, int p_start, int p_end) const {
if (p_start == p_end) {
return DIRECTION_AUTO;
}
@@ -905,8 +903,8 @@ TextServer::Direction TextServer::shaped_text_get_dominant_direciton_in_range(RI
int rtl = 0;
int ltr = 0;
- int v_size = visual.size();
- const Glyph *glyphs = visual.ptr();
+ int v_size = shaped_text_get_glyph_count(p_shaped);
+ const Glyph *glyphs = shaped_text_get_glyphs(p_shaped);
for (int i = 0; i < v_size; i++) {
if ((glyphs[i].end > start) && (glyphs[i].start < end)) {
@@ -930,7 +928,6 @@ TextServer::Direction TextServer::shaped_text_get_dominant_direciton_in_range(RI
Vector<Vector2> TextServer::shaped_text_get_selection(RID p_shaped, int p_start, int p_end) const {
Vector<Vector2> ranges;
- const Vector<TextServer::Glyph> visual = shaped_text_get_glyphs(p_shaped);
if (p_start == p_end) {
return ranges;
@@ -939,17 +936,17 @@ Vector<Vector2> TextServer::shaped_text_get_selection(RID p_shaped, int p_start,
int start = MIN(p_start, p_end);
int end = MAX(p_start, p_end);
- int v_size = visual.size();
- const Glyph *glyphs = visual.ptr();
+ int v_size = shaped_text_get_glyph_count(p_shaped);
+ const Glyph *glyphs = shaped_text_get_glyphs(p_shaped);
- float off = 0.0f;
+ real_t off = 0.0f;
for (int i = 0; i < v_size; i++) {
for (int k = 0; k < glyphs[i].repeat; k++) {
if ((glyphs[i].count > 0) && ((glyphs[i].index != 0) || ((glyphs[i].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE))) {
if (glyphs[i].start < end && glyphs[i].end > start) {
// Grapheme fully in selection range.
if (glyphs[i].start >= start && glyphs[i].end <= end) {
- float advance = 0.f;
+ real_t advance = 0.f;
for (int j = 0; j < glyphs[i].count; j++) {
advance += glyphs[i + j].advance;
}
@@ -957,11 +954,11 @@ Vector<Vector2> TextServer::shaped_text_get_selection(RID p_shaped, int p_start,
}
// Only start of grapheme is in selection range.
if (glyphs[i].start >= start && glyphs[i].end > end) {
- float advance = 0.f;
+ real_t advance = 0.f;
for (int j = 0; j < glyphs[i].count; j++) {
advance += glyphs[i + j].advance;
}
- float char_adv = advance / (float)(glyphs[i].end - glyphs[i].start);
+ real_t char_adv = advance / (real_t)(glyphs[i].end - glyphs[i].start);
if ((glyphs[i].flags & GRAPHEME_IS_RTL) == GRAPHEME_IS_RTL) {
ranges.push_back(Vector2(off + char_adv * (glyphs[i].end - end), off + advance));
} else {
@@ -970,11 +967,11 @@ Vector<Vector2> TextServer::shaped_text_get_selection(RID p_shaped, int p_start,
}
// Only end of grapheme is in selection range.
if (glyphs[i].start < start && glyphs[i].end <= end) {
- float advance = 0.f;
+ real_t advance = 0.f;
for (int j = 0; j < glyphs[i].count; j++) {
advance += glyphs[i + j].advance;
}
- float char_adv = advance / (float)(glyphs[i].end - glyphs[i].start);
+ real_t char_adv = advance / (real_t)(glyphs[i].end - glyphs[i].start);
if ((glyphs[i].flags & GRAPHEME_IS_RTL) == GRAPHEME_IS_RTL) {
ranges.push_back(Vector2(off, off + char_adv * (start - glyphs[i].start)));
} else {
@@ -983,11 +980,11 @@ Vector<Vector2> TextServer::shaped_text_get_selection(RID p_shaped, int p_start,
}
// Selection range is within grapheme.
if (glyphs[i].start < start && glyphs[i].end > end) {
- float advance = 0.f;
+ real_t advance = 0.f;
for (int j = 0; j < glyphs[i].count; j++) {
advance += glyphs[i + j].advance;
}
- float char_adv = advance / (float)(glyphs[i].end - glyphs[i].start);
+ real_t char_adv = advance / (real_t)(glyphs[i].end - glyphs[i].start);
if ((glyphs[i].flags & GRAPHEME_IS_RTL) == GRAPHEME_IS_RTL) {
ranges.push_back(Vector2(off + char_adv * (glyphs[i].end - end), off + char_adv * (glyphs[i].end - start)));
} else {
@@ -1022,14 +1019,12 @@ Vector<Vector2> TextServer::shaped_text_get_selection(RID p_shaped, int p_start,
return ranges;
}
-int TextServer::shaped_text_hit_test_grapheme(RID p_shaped, float p_coords) const {
- const Vector<TextServer::Glyph> visual = shaped_text_get_glyphs(p_shaped);
-
+int TextServer::shaped_text_hit_test_grapheme(RID p_shaped, real_t p_coords) const {
// Exact grapheme hit test, return -1 if missed.
- float off = 0.0f;
+ real_t off = 0.0f;
- int v_size = visual.size();
- const Glyph *glyphs = visual.ptr();
+ int v_size = shaped_text_get_glyph_count(p_shaped);
+ const Glyph *glyphs = shaped_text_get_glyphs(p_shaped);
for (int i = 0; i < v_size; i++) {
for (int j = 0; j < glyphs[i].repeat; j++) {
@@ -1042,11 +1037,9 @@ int TextServer::shaped_text_hit_test_grapheme(RID p_shaped, float p_coords) cons
return -1;
}
-int TextServer::shaped_text_hit_test_position(RID p_shaped, float p_coords) const {
- const Vector<TextServer::Glyph> visual = shaped_text_get_glyphs(p_shaped);
-
- int v_size = visual.size();
- const Glyph *glyphs = visual.ptr();
+int TextServer::shaped_text_hit_test_position(RID p_shaped, real_t p_coords) const {
+ int v_size = shaped_text_get_glyph_count(p_shaped);
+ const Glyph *glyphs = shaped_text_get_glyphs(p_shaped);
// Cursor placement hit test.
@@ -1076,10 +1069,10 @@ int TextServer::shaped_text_hit_test_position(RID p_shaped, float p_coords) cons
}
}
- float off = 0.0f;
+ real_t off = 0.0f;
for (int i = 0; i < v_size; i++) {
if (glyphs[i].count > 0) {
- float advance = 0.f;
+ real_t advance = 0.f;
for (int j = 0; j < glyphs[i].count; j++) {
advance += glyphs[i + j].advance * glyphs[i + j].repeat;
}
@@ -1112,10 +1105,9 @@ int TextServer::shaped_text_hit_test_position(RID p_shaped, float p_coords) cons
return 0;
}
-int TextServer::shaped_text_next_grapheme_pos(RID p_shaped, int p_pos) {
- const Vector<TextServer::Glyph> visual = shaped_text_get_glyphs(p_shaped);
- int v_size = visual.size();
- const Glyph *glyphs = visual.ptr();
+int TextServer::shaped_text_next_grapheme_pos(RID p_shaped, int p_pos) const {
+ int v_size = shaped_text_get_glyph_count(p_shaped);
+ const Glyph *glyphs = shaped_text_get_glyphs(p_shaped);
for (int i = 0; i < v_size; i++) {
if (p_pos >= glyphs[i].start && p_pos < glyphs[i].end) {
return glyphs[i].end;
@@ -1124,10 +1116,9 @@ int TextServer::shaped_text_next_grapheme_pos(RID p_shaped, int p_pos) {
return p_pos;
}
-int TextServer::shaped_text_prev_grapheme_pos(RID p_shaped, int p_pos) {
- const Vector<TextServer::Glyph> visual = shaped_text_get_glyphs(p_shaped);
- int v_size = visual.size();
- const Glyph *glyphs = visual.ptr();
+int TextServer::shaped_text_prev_grapheme_pos(RID p_shaped, int p_pos) const {
+ int v_size = shaped_text_get_glyph_count(p_shaped);
+ const Glyph *glyphs = shaped_text_get_glyphs(p_shaped);
for (int i = 0; i < v_size; i++) {
if (p_pos > glyphs[i].start && p_pos <= glyphs[i].end) {
return glyphs[i].start;
@@ -1137,27 +1128,31 @@ int TextServer::shaped_text_prev_grapheme_pos(RID p_shaped, int p_pos) {
return p_pos;
}
-void TextServer::shaped_text_draw(RID p_shaped, RID p_canvas, const Vector2 &p_pos, float p_clip_l, float p_clip_r, const Color &p_color) const {
- const Vector<TextServer::Glyph> visual = shaped_text_get_glyphs(p_shaped);
+void TextServer::shaped_text_draw(RID p_shaped, RID p_canvas, const Vector2 &p_pos, real_t p_clip_l, real_t p_clip_r, const Color &p_color) const {
TextServer::Orientation orientation = shaped_text_get_orientation(p_shaped);
bool hex_codes = shaped_text_get_preserve_control(p_shaped) || shaped_text_get_preserve_invalid(p_shaped);
bool rtl = shaped_text_get_direction(p_shaped) == DIRECTION_RTL;
- TrimData trim_data = shaped_text_get_trim_data(p_shaped);
- int v_size = visual.size();
- const Glyph *glyphs = visual.ptr();
+ int ellipsis_pos = shaped_text_get_ellipsis_pos(p_shaped);
+ int trim_pos = shaped_text_get_trim_pos(p_shaped);
+
+ const Glyph *ellipsis_glyphs = shaped_text_get_ellipsis_glyphs(p_shaped);
+ int ellipsis_gl_size = shaped_text_get_ellipsis_glyph_count(p_shaped);
+
+ int v_size = shaped_text_get_glyph_count(p_shaped);
+ const Glyph *glyphs = shaped_text_get_glyphs(p_shaped);
Vector2 ofs = p_pos;
// Draw RTL ellipsis string when needed.
- if (rtl && trim_data.ellipsis_pos >= 0) {
- for (int i = trim_data.ellipsis_glyph_buf.size() - 1; i >= 0; i--) {
- for (int j = 0; j < trim_data.ellipsis_glyph_buf[i].repeat; j++) {
- font_draw_glyph(trim_data.ellipsis_glyph_buf[i].font_rid, p_canvas, trim_data.ellipsis_glyph_buf[i].font_size, ofs + Vector2(trim_data.ellipsis_glyph_buf[i].x_off, trim_data.ellipsis_glyph_buf[i].y_off), trim_data.ellipsis_glyph_buf[i].index, p_color);
+ if (rtl && ellipsis_pos >= 0) {
+ for (int i = ellipsis_gl_size - 1; i >= 0; i--) {
+ for (int j = 0; j < ellipsis_glyphs[i].repeat; j++) {
+ font_draw_glyph(ellipsis_glyphs[i].font_rid, p_canvas, ellipsis_glyphs[i].font_size, ofs + Vector2(ellipsis_glyphs[i].x_off, ellipsis_glyphs[i].y_off), ellipsis_glyphs[i].index, p_color);
if (orientation == ORIENTATION_HORIZONTAL) {
- ofs.x += trim_data.ellipsis_glyph_buf[i].advance;
+ ofs.x += ellipsis_glyphs[i].advance;
} else {
- ofs.y += trim_data.ellipsis_glyph_buf[i].advance;
+ ofs.y += ellipsis_glyphs[i].advance;
}
}
}
@@ -1191,13 +1186,13 @@ void TextServer::shaped_text_draw(RID p_shaped, RID p_canvas, const Vector2 &p_p
}
}
}
- if (trim_data.trim_pos >= 0) {
+ if (trim_pos >= 0) {
if (rtl) {
- if (i < trim_data.trim_pos && (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) {
+ if (i < trim_pos && (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) {
continue;
}
} else {
- if (i >= trim_data.trim_pos && (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) {
+ if (i >= trim_pos && (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) {
break;
}
}
@@ -1216,39 +1211,43 @@ void TextServer::shaped_text_draw(RID p_shaped, RID p_canvas, const Vector2 &p_p
}
}
// Draw LTR ellipsis string when needed.
- if (!rtl && trim_data.ellipsis_pos >= 0) {
- for (int i = 0; i < trim_data.ellipsis_glyph_buf.size(); i++) {
- for (int j = 0; j < trim_data.ellipsis_glyph_buf[i].repeat; j++) {
- font_draw_glyph(trim_data.ellipsis_glyph_buf[i].font_rid, p_canvas, trim_data.ellipsis_glyph_buf[i].font_size, ofs + Vector2(trim_data.ellipsis_glyph_buf[i].x_off, trim_data.ellipsis_glyph_buf[i].y_off), trim_data.ellipsis_glyph_buf[i].index, p_color);
+ if (!rtl && ellipsis_pos >= 0) {
+ for (int i = 0; i < ellipsis_gl_size; i++) {
+ for (int j = 0; j < ellipsis_glyphs[i].repeat; j++) {
+ font_draw_glyph(ellipsis_glyphs[i].font_rid, p_canvas, ellipsis_glyphs[i].font_size, ofs + Vector2(ellipsis_glyphs[i].x_off, ellipsis_glyphs[i].y_off), ellipsis_glyphs[i].index, p_color);
if (orientation == ORIENTATION_HORIZONTAL) {
- ofs.x += trim_data.ellipsis_glyph_buf[i].advance;
+ ofs.x += ellipsis_glyphs[i].advance;
} else {
- ofs.y += trim_data.ellipsis_glyph_buf[i].advance;
+ ofs.y += ellipsis_glyphs[i].advance;
}
}
}
}
}
-void TextServer::shaped_text_draw_outline(RID p_shaped, RID p_canvas, const Vector2 &p_pos, float p_clip_l, float p_clip_r, int p_outline_size, const Color &p_color) const {
- const Vector<TextServer::Glyph> visual = shaped_text_get_glyphs(p_shaped);
+void TextServer::shaped_text_draw_outline(RID p_shaped, RID p_canvas, const Vector2 &p_pos, real_t p_clip_l, real_t p_clip_r, int p_outline_size, const Color &p_color) const {
TextServer::Orientation orientation = shaped_text_get_orientation(p_shaped);
bool rtl = (shaped_text_get_direction(p_shaped) == DIRECTION_RTL);
- TrimData trim_data = shaped_text_get_trim_data(p_shaped);
- int v_size = visual.size();
- const Glyph *glyphs = visual.ptr();
+ int ellipsis_pos = shaped_text_get_ellipsis_pos(p_shaped);
+ int trim_pos = shaped_text_get_trim_pos(p_shaped);
+
+ const Glyph *ellipsis_glyphs = shaped_text_get_ellipsis_glyphs(p_shaped);
+ int ellipsis_gl_size = shaped_text_get_ellipsis_glyph_count(p_shaped);
+
+ int v_size = shaped_text_get_glyph_count(p_shaped);
+ const Glyph *glyphs = shaped_text_get_glyphs(p_shaped);
Vector2 ofs = p_pos;
// Draw RTL ellipsis string when needed.
- if (rtl && trim_data.ellipsis_pos >= 0) {
- for (int i = trim_data.ellipsis_glyph_buf.size() - 1; i >= 0; i--) {
- for (int j = 0; j < trim_data.ellipsis_glyph_buf[i].repeat; j++) {
- font_draw_glyph(trim_data.ellipsis_glyph_buf[i].font_rid, p_canvas, trim_data.ellipsis_glyph_buf[i].font_size, ofs + Vector2(trim_data.ellipsis_glyph_buf[i].x_off, trim_data.ellipsis_glyph_buf[i].y_off), trim_data.ellipsis_glyph_buf[i].index, p_color);
+ if (rtl && ellipsis_pos >= 0) {
+ for (int i = ellipsis_gl_size - 1; i >= 0; i--) {
+ for (int j = 0; j < ellipsis_glyphs[i].repeat; j++) {
+ font_draw_glyph(ellipsis_glyphs[i].font_rid, p_canvas, ellipsis_glyphs[i].font_size, ofs + Vector2(ellipsis_glyphs[i].x_off, ellipsis_glyphs[i].y_off), ellipsis_glyphs[i].index, p_color);
if (orientation == ORIENTATION_HORIZONTAL) {
- ofs.x += trim_data.ellipsis_glyph_buf[i].advance;
+ ofs.x += ellipsis_glyphs[i].advance;
} else {
- ofs.y += trim_data.ellipsis_glyph_buf[i].advance;
+ ofs.y += ellipsis_glyphs[i].advance;
}
}
}
@@ -1282,13 +1281,13 @@ void TextServer::shaped_text_draw_outline(RID p_shaped, RID p_canvas, const Vect
}
}
}
- if (trim_data.trim_pos >= 0) {
+ if (trim_pos >= 0) {
if (rtl) {
- if (i < trim_data.trim_pos) {
+ if (i < trim_pos) {
continue;
}
} else {
- if (i >= trim_data.trim_pos && (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) {
+ if (i >= trim_pos && (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) {
break;
}
}
@@ -1304,52 +1303,26 @@ void TextServer::shaped_text_draw_outline(RID p_shaped, RID p_canvas, const Vect
}
}
// Draw LTR ellipsis string when needed.
- if (!rtl && trim_data.ellipsis_pos >= 0) {
- for (int i = 0; i < trim_data.ellipsis_glyph_buf.size(); i++) {
- for (int j = 0; j < trim_data.ellipsis_glyph_buf[i].repeat; j++) {
- font_draw_glyph(trim_data.ellipsis_glyph_buf[i].font_rid, p_canvas, trim_data.ellipsis_glyph_buf[i].font_size, ofs + Vector2(trim_data.ellipsis_glyph_buf[i].x_off, trim_data.ellipsis_glyph_buf[i].y_off), trim_data.ellipsis_glyph_buf[i].index, p_color);
+ if (!rtl && ellipsis_pos >= 0) {
+ for (int i = 0; i < ellipsis_gl_size; i++) {
+ for (int j = 0; j < ellipsis_glyphs[i].repeat; j++) {
+ font_draw_glyph(ellipsis_glyphs[i].font_rid, p_canvas, ellipsis_glyphs[i].font_size, ofs + Vector2(ellipsis_glyphs[i].x_off, ellipsis_glyphs[i].y_off), ellipsis_glyphs[i].index, p_color);
if (orientation == ORIENTATION_HORIZONTAL) {
- ofs.x += trim_data.ellipsis_glyph_buf[i].advance;
+ ofs.x += ellipsis_glyphs[i].advance;
} else {
- ofs.y += trim_data.ellipsis_glyph_buf[i].advance;
+ ofs.y += ellipsis_glyphs[i].advance;
}
}
}
}
}
-RID TextServer::_create_font_memory(const PackedByteArray &p_data, const String &p_type, int p_base_size) {
- return create_font_memory(p_data.ptr(), p_data.size(), p_type, p_base_size);
-}
-
-Dictionary TextServer::_font_get_glyph_contours(RID p_font, int p_size, uint32_t p_index) const {
- Vector<Vector3> points;
- Vector<int32_t> contours;
- bool orientation;
- bool ok = font_get_glyph_contours(p_font, p_size, p_index, points, contours, orientation);
- Dictionary out;
-
- if (ok) {
- out["points"] = points;
- out["contours"] = contours;
- out["orientation"] = orientation;
- }
- return out;
-}
-
-void TextServer::_shaped_text_set_bidi_override(RID p_shaped, const Array &p_override) {
- Vector<Vector2i> overrides;
- for (int i = 0; i < p_override.size(); i++) {
- overrides.push_back(p_override[i]);
- }
- shaped_text_set_bidi_override(p_shaped, overrides);
-}
-
-Array TextServer::_shaped_text_get_glyphs(RID p_shaped) const {
+Array TextServer::_shaped_text_get_glyphs_wrapper(RID p_shaped) const {
Array ret;
- Vector<Glyph> glyphs = shaped_text_get_glyphs(p_shaped);
- for (int i = 0; i < glyphs.size(); i++) {
+ const Glyph *glyphs = shaped_text_get_glyphs(p_shaped);
+ int gl_size = shaped_text_get_glyph_count(p_shaped);
+ for (int i = 0; i < gl_size; i++) {
Dictionary glyph;
glyph["start"] = glyphs[i].start;
@@ -1369,60 +1342,51 @@ Array TextServer::_shaped_text_get_glyphs(RID p_shaped) const {
return ret;
}
-Array TextServer::_shaped_text_get_line_breaks_adv(RID p_shaped, const PackedFloat32Array &p_width, int p_start, bool p_once, uint8_t p_break_flags) const {
+Array TextServer::_shaped_text_sort_logical_wrapper(RID p_shaped) {
Array ret;
- Vector<Vector2i> lines = shaped_text_get_line_breaks_adv(p_shaped, p_width, p_start, p_once, p_break_flags);
- for (int i = 0; i < lines.size(); i++) {
- ret.push_back(lines[i]);
- }
-
- return ret;
-}
+ const Glyph *glyphs = shaped_text_sort_logical(p_shaped);
+ int gl_size = shaped_text_get_glyph_count(p_shaped);
+ for (int i = 0; i < gl_size; i++) {
+ Dictionary glyph;
-Array TextServer::_shaped_text_get_line_breaks(RID p_shaped, float p_width, int p_start, uint8_t p_break_flags) const {
- Array ret;
+ glyph["start"] = glyphs[i].start;
+ glyph["end"] = glyphs[i].end;
+ glyph["repeat"] = glyphs[i].repeat;
+ glyph["count"] = glyphs[i].count;
+ glyph["flags"] = glyphs[i].flags;
+ glyph["offset"] = Vector2(glyphs[i].x_off, glyphs[i].y_off);
+ glyph["advance"] = glyphs[i].advance;
+ glyph["font_rid"] = glyphs[i].font_rid;
+ glyph["font_size"] = glyphs[i].font_size;
+ glyph["index"] = glyphs[i].index;
- Vector<Vector2i> lines = shaped_text_get_line_breaks(p_shaped, p_width, p_start, p_break_flags);
- for (int i = 0; i < lines.size(); i++) {
- ret.push_back(lines[i]);
+ ret.push_back(glyph);
}
return ret;
}
-Array TextServer::_shaped_text_get_word_breaks(RID p_shaped) const {
+Array TextServer::_shaped_text_get_ellipsis_glyphs_wrapper(RID p_shaped) const {
Array ret;
- Vector<Vector2i> words = shaped_text_get_word_breaks(p_shaped);
- for (int i = 0; i < words.size(); i++) {
- ret.push_back(words[i]);
- }
-
- return ret;
-}
-
-Dictionary TextServer::_shaped_text_get_carets(RID p_shaped, int p_position) const {
- Dictionary ret;
-
- Rect2 l_caret, t_caret;
- Direction l_dir, t_dir;
- shaped_text_get_carets(p_shaped, p_position, l_caret, l_dir, t_caret, t_dir);
-
- ret["leading_rect"] = l_caret;
- ret["leading_direction"] = l_dir;
- ret["trailing_rect"] = t_caret;
- ret["trailing_direction"] = t_dir;
-
- return ret;
-}
+ const Glyph *glyphs = shaped_text_get_ellipsis_glyphs(p_shaped);
+ int gl_size = shaped_text_get_ellipsis_glyph_count(p_shaped);
+ for (int i = 0; i < gl_size; i++) {
+ Dictionary glyph;
-Array TextServer::_shaped_text_get_selection(RID p_shaped, int p_start, int p_end) const {
- Array ret;
+ glyph["start"] = glyphs[i].start;
+ glyph["end"] = glyphs[i].end;
+ glyph["repeat"] = glyphs[i].repeat;
+ glyph["count"] = glyphs[i].count;
+ glyph["flags"] = glyphs[i].flags;
+ glyph["offset"] = Vector2(glyphs[i].x_off, glyphs[i].y_off);
+ glyph["advance"] = glyphs[i].advance;
+ glyph["font_rid"] = glyphs[i].font_rid;
+ glyph["font_size"] = glyphs[i].font_size;
+ glyph["index"] = glyphs[i].index;
- Vector<Vector2> ranges = shaped_text_get_selection(p_shaped, p_start, p_end);
- for (int i = 0; i < ranges.size(); i++) {
- ret.push_back(ranges[i]);
+ ret.push_back(glyph);
}
return ret;
diff --git a/servers/text_server.h b/servers/text_server.h
index 26993838a3..3a5f946fbf 100644
--- a/servers/text_server.h
+++ b/servers/text_server.h
@@ -34,13 +34,14 @@
#include "core/object/ref_counted.h"
#include "core/os/os.h"
#include "core/templates/rid.h"
+#include "core/variant/native_ptr.h"
#include "core/variant/variant.h"
-#include "scene/resources/texture.h"
-class CanvasTexture;
+struct Glyph;
+struct CaretInfo;
-class TextServer : public Object {
- GDCLASS(TextServer, Object);
+class TextServer : public RefCounted {
+ GDCLASS(TextServer, RefCounted);
public:
enum Direction {
@@ -63,12 +64,12 @@ public:
JUSTIFICATION_CONSTRAIN_ELLIPSIS = 1 << 4,
};
- enum LineBreakFlag {
+ enum LineBreakFlag { // LineBreakFlag can be passed in the same value as the JustificationFlag, do not use the same values.
BREAK_NONE = 0,
- BREAK_MANDATORY = 1 << 4,
- BREAK_WORD_BOUND = 1 << 5,
- BREAK_GRAPHEME_BOUND = 1 << 6,
- BREAK_WORD_BOUND_ADAPTIVE = 1 << 5 | 1 << 7,
+ BREAK_MANDATORY = 1 << 5,
+ BREAK_WORD_BOUND = 1 << 6,
+ BREAK_GRAPHEME_BOUND = 1 << 7,
+ BREAK_WORD_BOUND_ADAPTIVE = 1 << 6 | 1 << 8,
};
enum TextOverrunFlag {
@@ -91,6 +92,7 @@ public:
GRAPHEME_IS_ELONGATION = 1 << 7, // Elongation (e.g. kashida), glyph can be duplicated or truncated to fit line to width.
GRAPHEME_IS_PUNCTUATION = 1 << 8, // Punctuation, except underscore (can be used as word break, but not line break or justifiction).
GRAPHEME_IS_UNDERSCORE = 1 << 9, // Underscore (can be used as word break).
+ GRAPHEME_IS_CONNECTED = 1 << 10, // Connected to previous grapheme.
};
enum Hinting {
@@ -116,53 +118,25 @@ public:
CONTOUR_CURVE_TAG_OFF_CUBIC = 0x02
};
- struct Glyph {
- int start = -1; // Start offset in the source string.
- int end = -1; // End offset in the source string.
-
- uint8_t count = 0; // Number of glyphs in the grapheme, set in the first glyph only.
- uint8_t repeat = 1; // Draw multiple times in the row.
- uint16_t flags = 0; // Grapheme flags (valid, rtl, virtual), set in the first glyph only.
-
- float x_off = 0.f; // Offset from the origin of the glyph on baseline.
- float y_off = 0.f;
- float advance = 0.f; // Advance to the next glyph along baseline(x for horizontal layout, y for vertical).
-
- RID font_rid; // Font resource.
- int font_size = 0; // Font size;
- uint32_t index = 0; // Glyph index (font specific) or UTF-32 codepoint (for the invalid glyphs).
-
- bool operator==(const Glyph &p_a) const;
- bool operator!=(const Glyph &p_a) const;
-
- bool operator<(const Glyph &p_a) const;
- bool operator>(const Glyph &p_a) const;
+ enum SpacingType {
+ SPACING_GLYPH,
+ SPACING_SPACE,
+ SPACING_TOP,
+ SPACING_BOTTOM,
};
- struct GlyphCompare { // For line breaking reordering.
- _FORCE_INLINE_ bool operator()(const Glyph &l, const Glyph &r) const {
- if (l.start == r.start) {
- if (l.count == r.count) {
- if ((l.flags & GRAPHEME_IS_VIRTUAL) == GRAPHEME_IS_VIRTUAL) {
- return false;
- } else {
- return true;
- }
- }
- return l.count > r.count; // Sort first glyph with count & flags, order of the rest are irrelevant.
- } else {
- return l.start < r.start;
- }
- }
- };
+ void _draw_hex_code_box_number(RID p_canvas, int p_size, const Vector2 &p_pos, uint8_t p_index, const Color &p_color) const;
+protected:
struct TrimData {
int trim_pos = -1;
int ellipsis_pos = -1;
- Vector<TextServer::Glyph> ellipsis_glyph_buf;
+ Vector<Glyph> ellipsis_glyph_buf;
};
struct ShapedTextData {
+ Mutex mutex;
+
/* Source data */
RID parent; // Substring parent ShapedTextData.
@@ -216,113 +190,154 @@ public:
TrimData overrun_trim_data;
bool fit_width_minimum_reached = false;
- Vector<TextServer::Glyph> glyphs;
- Vector<TextServer::Glyph> glyphs_logical;
+ Vector<Glyph> glyphs;
+ Vector<Glyph> glyphs_logical;
};
-protected:
static void _bind_methods();
- static Vector3 hex_code_box_font_size[2];
- static Ref<CanvasTexture> hex_code_box_font_tex[2];
-
public:
- static void initialize_hex_code_box_fonts();
- static void finish_hex_code_box_fonts();
-
- virtual bool has_feature(Feature p_feature) = 0;
+ virtual bool has_feature(Feature p_feature) const = 0;
virtual String get_name() const = 0;
+ virtual uint32_t get_features() const = 0;
virtual void free(RID p_rid) = 0;
virtual bool has(RID p_rid) = 0;
virtual bool load_support_data(const String &p_filename) = 0;
-#ifdef TOOLS_ENABLED
- virtual String get_support_data_filename() = 0;
- virtual String get_support_data_info() = 0;
- virtual bool save_support_data(const String &p_filename) = 0;
-#endif
+ virtual String get_support_data_filename() const = 0;
+ virtual String get_support_data_info() const = 0;
+ virtual bool save_support_data(const String &p_filename) const = 0;
- virtual bool is_locale_right_to_left(const String &p_locale) = 0;
+ virtual bool is_locale_right_to_left(const String &p_locale) const = 0;
- virtual int32_t name_to_tag(const String &p_name) { return 0; };
- virtual String tag_to_name(int32_t p_tag) { return ""; };
+ virtual int32_t name_to_tag(const String &p_name) const { return 0; };
+ virtual String tag_to_name(int32_t p_tag) const { return ""; };
/* Font interface */
- virtual RID create_font_system(const String &p_name, int p_base_size = 16) = 0;
- virtual RID create_font_resource(const String &p_filename, int p_base_size = 16) = 0;
- virtual RID create_font_memory(const uint8_t *p_data, size_t p_size, const String &p_type, int p_base_size = 16) = 0;
- virtual RID create_font_bitmap(float p_height, float p_ascent, int p_base_size = 16) = 0;
+ virtual RID create_font() = 0;
+
+ virtual void font_set_data(RID p_font_rid, const PackedByteArray &p_data) = 0;
+ virtual void font_set_data_ptr(RID p_font_rid, const uint8_t *p_data_ptr, size_t p_data_size) = 0;
+
+ virtual void font_set_antialiased(RID p_font_rid, bool p_antialiased) = 0;
+ virtual bool font_is_antialiased(RID p_font_rid) const = 0;
+
+ virtual void font_set_multichannel_signed_distance_field(RID p_font_rid, bool p_msdf) = 0;
+ virtual bool font_is_multichannel_signed_distance_field(RID p_font_rid) const = 0;
+
+ virtual void font_set_msdf_pixel_range(RID p_font_rid, int p_msdf_pixel_range) = 0;
+ virtual int font_get_msdf_pixel_range(RID p_font_rid) const = 0;
+
+ virtual void font_set_msdf_size(RID p_font_rid, int p_msdf_size) = 0;
+ virtual int font_get_msdf_size(RID p_font_rid) const = 0;
+
+ virtual void font_set_fixed_size(RID p_font_rid, int p_fixed_size) = 0;
+ virtual int font_get_fixed_size(RID p_font_rid) const = 0;
+
+ virtual void font_set_force_autohinter(RID p_font_rid, bool p_force_autohinter) = 0;
+ virtual bool font_is_force_autohinter(RID p_font_rid) const = 0;
+
+ virtual void font_set_hinting(RID p_font_rid, Hinting p_hinting) = 0;
+ virtual Hinting font_get_hinting(RID p_font_rid) const = 0;
+
+ virtual void font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) = 0;
+ virtual Dictionary font_get_variation_coordinates(RID p_font_rid) const = 0;
+
+ virtual void font_set_oversampling(RID p_font_rid, float p_oversampling) = 0;
+ virtual float font_get_oversampling(RID p_font_rid) const = 0;
+
+ virtual Array font_get_size_cache_list(RID p_font_rid) const = 0;
+ virtual void font_clear_size_cache(RID p_font_rid) = 0;
+ virtual void font_remove_size_cache(RID p_font_rid, const Vector2i &p_size) = 0;
+
+ virtual void font_set_ascent(RID p_font_rid, int p_size, float p_ascent) = 0;
+ virtual float font_get_ascent(RID p_font_rid, int p_size) const = 0;
+
+ virtual void font_set_descent(RID p_font_rid, int p_size, float p_descent) = 0;
+ virtual float font_get_descent(RID p_font_rid, int p_size) const = 0;
+
+ virtual void font_set_underline_position(RID p_font_rid, int p_size, float p_underline_position) = 0;
+ virtual float font_get_underline_position(RID p_font_rid, int p_size) const = 0;
- virtual void font_bitmap_add_texture(RID p_font, const Ref<Texture> &p_texture) = 0;
- virtual void font_bitmap_add_char(RID p_font, char32_t p_char, int p_texture_idx, const Rect2 &p_rect, const Size2 &p_align, float p_advance) = 0;
- virtual void font_bitmap_add_kerning_pair(RID p_font, char32_t p_A, char32_t p_B, int p_kerning) = 0;
+ virtual void font_set_underline_thickness(RID p_font_rid, int p_size, float p_underline_thickness) = 0;
+ virtual float font_get_underline_thickness(RID p_font_rid, int p_size) const = 0;
- virtual float font_get_height(RID p_font, int p_size) const = 0;
- virtual float font_get_ascent(RID p_font, int p_size) const = 0;
- virtual float font_get_descent(RID p_font, int p_size) const = 0;
+ virtual void font_set_scale(RID p_font_rid, int p_size, float p_scale) = 0;
+ virtual float font_get_scale(RID p_font_rid, int p_size) const = 0;
- virtual int font_get_spacing_space(RID p_font) const = 0;
- virtual void font_set_spacing_space(RID p_font, int p_value) = 0;
+ virtual void font_set_spacing(RID p_font_rid, int p_size, SpacingType p_spacing, int p_value) = 0;
+ virtual int font_get_spacing(RID p_font_rid, int p_size, SpacingType p_spacing) const = 0;
- virtual int font_get_spacing_glyph(RID p_font) const = 0;
- virtual void font_set_spacing_glyph(RID p_font, int p_value) = 0;
+ virtual int font_get_texture_count(RID p_font_rid, const Vector2i &p_size) const = 0;
+ virtual void font_clear_textures(RID p_font_rid, const Vector2i &p_size) = 0;
+ virtual void font_remove_texture(RID p_font_rid, const Vector2i &p_size, int p_texture_index) = 0;
- virtual float font_get_underline_position(RID p_font, int p_size) const = 0;
- virtual float font_get_underline_thickness(RID p_font, int p_size) const = 0;
+ virtual void font_set_texture_image(RID p_font_rid, const Vector2i &p_size, int p_texture_index, const Ref<Image> &p_image) = 0;
+ virtual Ref<Image> font_get_texture_image(RID p_font_rid, const Vector2i &p_size, int p_texture_index) const = 0;
- virtual void font_set_antialiased(RID p_font, bool p_antialiased) = 0;
- virtual bool font_get_antialiased(RID p_font) const = 0;
+ virtual void font_set_texture_offsets(RID p_font_rid, const Vector2i &p_size, int p_texture_index, const PackedInt32Array &p_offset) = 0;
+ virtual PackedInt32Array font_get_texture_offsets(RID p_font_rid, const Vector2i &p_size, int p_texture_index) const = 0;
- virtual Dictionary font_get_feature_list(RID p_font) const { return Dictionary(); };
- virtual Dictionary font_get_variation_list(RID p_font) const { return Dictionary(); };
+ virtual Array font_get_glyph_list(RID p_font_rid, const Vector2i &p_size) const = 0;
+ virtual void font_clear_glyphs(RID p_font_rid, const Vector2i &p_size) = 0;
+ virtual void font_remove_glyph(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) = 0;
- virtual void font_set_variation(RID p_font, const String &p_name, double p_value){};
- virtual double font_get_variation(RID p_font, const String &p_name) const { return 0; };
+ virtual Vector2 font_get_glyph_advance(RID p_font_rid, int p_size, int32_t p_glyph) const = 0;
+ virtual void font_set_glyph_advance(RID p_font_rid, int p_size, int32_t p_glyph, const Vector2 &p_advance) = 0;
- virtual void font_set_distance_field_hint(RID p_font, bool p_distance_field) = 0;
- virtual bool font_get_distance_field_hint(RID p_font) const = 0;
+ virtual Vector2 font_get_glyph_offset(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const = 0;
+ virtual void font_set_glyph_offset(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, const Vector2 &p_offset) = 0;
- virtual void font_set_hinting(RID p_font, Hinting p_hinting) = 0;
- virtual Hinting font_get_hinting(RID p_font) const = 0;
+ virtual Vector2 font_get_glyph_size(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const = 0;
+ virtual void font_set_glyph_size(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, const Vector2 &p_gl_size) = 0;
- virtual void font_set_force_autohinter(RID p_font, bool p_enabeld) = 0;
- virtual bool font_get_force_autohinter(RID p_font) const = 0;
+ virtual Rect2 font_get_glyph_uv_rect(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const = 0;
+ virtual void font_set_glyph_uv_rect(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, const Rect2 &p_uv_rect) = 0;
- virtual bool font_has_char(RID p_font, char32_t p_char) const = 0;
- virtual String font_get_supported_chars(RID p_font) const = 0;
+ virtual int font_get_glyph_texture_idx(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const = 0;
+ virtual void font_set_glyph_texture_idx(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, int p_texture_idx) = 0;
- virtual bool font_has_outline(RID p_font) const = 0;
- virtual float font_get_base_size(RID p_font) const = 0;
+ virtual Dictionary font_get_glyph_contours(RID p_font, int p_size, int32_t p_index) const = 0;
- virtual bool font_is_language_supported(RID p_font, const String &p_language) const = 0;
- virtual void font_set_language_support_override(RID p_font, const String &p_language, bool p_supported) = 0;
- virtual bool font_get_language_support_override(RID p_font, const String &p_language) = 0;
- virtual void font_remove_language_support_override(RID p_font, const String &p_language) = 0;
- virtual Vector<String> font_get_language_support_overrides(RID p_font) = 0;
+ virtual Array font_get_kerning_list(RID p_font_rid, int p_size) const = 0;
+ virtual void font_clear_kerning_map(RID p_font_rid, int p_size) = 0;
+ virtual void font_remove_kerning(RID p_font_rid, int p_size, const Vector2i &p_glyph_pair) = 0;
- virtual bool font_is_script_supported(RID p_font, const String &p_script) const = 0;
- virtual void font_set_script_support_override(RID p_font, const String &p_script, bool p_supported) = 0;
- virtual bool font_get_script_support_override(RID p_font, const String &p_script) = 0;
- virtual void font_remove_script_support_override(RID p_font, const String &p_script) = 0;
- virtual Vector<String> font_get_script_support_overrides(RID p_font) = 0;
+ virtual void font_set_kerning(RID p_font_rid, int p_size, const Vector2i &p_glyph_pair, const Vector2 &p_kerning) = 0;
+ virtual Vector2 font_get_kerning(RID p_font_rid, int p_size, const Vector2i &p_glyph_pair) const = 0;
- virtual uint32_t font_get_glyph_index(RID p_font, char32_t p_char, char32_t p_variation_selector = 0x0000) const = 0;
- virtual Vector2 font_get_glyph_advance(RID p_font, uint32_t p_index, int p_size) const = 0;
- virtual Vector2 font_get_glyph_kerning(RID p_font, uint32_t p_index_a, uint32_t p_index_b, int p_size) const = 0;
+ virtual int32_t font_get_glyph_index(RID p_font_rid, int p_size, char32_t p_char, char32_t p_variation_selector) const = 0;
- virtual Vector2 font_draw_glyph(RID p_font, RID p_canvas, int p_size, const Vector2 &p_pos, uint32_t p_index, const Color &p_color = Color(1, 1, 1)) const = 0;
- virtual Vector2 font_draw_glyph_outline(RID p_font, RID p_canvas, int p_size, int p_outline_size, const Vector2 &p_pos, uint32_t p_index, const Color &p_color = Color(1, 1, 1)) const = 0;
+ virtual bool font_has_char(RID p_font_rid, char32_t p_char) const = 0;
+ virtual String font_get_supported_chars(RID p_font_rid) const = 0;
- virtual bool font_get_glyph_contours(RID p_font, int p_size, uint32_t p_index, Vector<Vector3> &r_points, Vector<int32_t> &r_contours, bool &r_orientation) const = 0;
+ virtual void font_render_range(RID p_font, const Vector2i &p_size, char32_t p_start, char32_t p_end) = 0;
+ virtual void font_render_glyph(RID p_font_rid, const Vector2i &p_size, int32_t p_index) = 0;
- virtual float font_get_oversampling() const = 0;
- virtual void font_set_oversampling(float p_oversampling) = 0;
+ virtual void font_draw_glyph(RID p_font, RID p_canvas, int p_size, const Vector2 &p_pos, int32_t p_index, const Color &p_color = Color(1, 1, 1)) const = 0;
+ virtual void font_draw_glyph_outline(RID p_font, RID p_canvas, int p_size, int p_outline_size, const Vector2 &p_pos, int32_t p_index, const Color &p_color = Color(1, 1, 1)) const = 0;
- Vector2 get_hex_code_box_size(int p_size, char32_t p_index) const;
- void draw_hex_code_box(RID p_canvas, int p_size, const Vector2 &p_pos, char32_t p_index, const Color &p_color) const;
+ virtual bool font_is_language_supported(RID p_font_rid, const String &p_language) const = 0;
+ virtual void font_set_language_support_override(RID p_font_rid, const String &p_language, bool p_supported) = 0;
+ virtual bool font_get_language_support_override(RID p_font_rid, const String &p_language) = 0;
+ virtual void font_remove_language_support_override(RID p_font_rid, const String &p_language) = 0;
+ virtual Vector<String> font_get_language_support_overrides(RID p_font_rid) = 0;
- virtual Vector<String> get_system_fonts() const = 0;
+ virtual bool font_is_script_supported(RID p_font_rid, const String &p_script) const = 0;
+ virtual void font_set_script_support_override(RID p_font_rid, const String &p_script, bool p_supported) = 0;
+ virtual bool font_get_script_support_override(RID p_font_rid, const String &p_script) = 0;
+ virtual void font_remove_script_support_override(RID p_font_rid, const String &p_script) = 0;
+ virtual Vector<String> font_get_script_support_overrides(RID p_font_rid) = 0;
+
+ virtual Dictionary font_supported_feature_list(RID p_font_rid) const = 0;
+ virtual Dictionary font_supported_variation_list(RID p_font_rid) const = 0;
+
+ virtual float font_get_global_oversampling() const = 0;
+ virtual void font_set_global_oversampling(float p_oversampling) = 0;
+
+ virtual Vector2 get_hex_code_box_size(int p_size, char32_t p_index) const;
+ virtual void draw_hex_code_box(RID p_canvas, int p_size, const Vector2 &p_pos, char32_t p_index, const Color &p_color) const;
/* Shaped text buffer interface */
@@ -333,7 +348,7 @@ public:
virtual void shaped_text_set_direction(RID p_shaped, Direction p_direction = DIRECTION_AUTO) = 0;
virtual Direction shaped_text_get_direction(RID p_shaped) const = 0;
- virtual void shaped_text_set_bidi_override(RID p_shaped, const Vector<Vector2i> &p_override) = 0;
+ virtual void shaped_text_set_bidi_override(RID p_shaped, const Array &p_override) = 0;
virtual void shaped_text_set_orientation(RID p_shaped, Orientation p_orientation = ORIENTATION_HORIZONTAL) = 0;
virtual Orientation shaped_text_get_orientation(RID p_shaped) const = 0;
@@ -351,8 +366,8 @@ public:
virtual RID shaped_text_substr(RID p_shaped, int p_start, int p_length) const = 0; // Copy shaped substring (e.g. line break) without reshaping, but correctly reordered, preservers range.
virtual RID shaped_text_get_parent(RID p_shaped) const = 0;
- virtual float shaped_text_fit_to_width(RID p_shaped, float p_width, uint8_t /*JustificationFlag*/ p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) = 0;
- virtual float shaped_text_tab_align(RID p_shaped, const Vector<float> &p_tab_stops) = 0;
+ virtual float shaped_text_fit_to_width(RID p_shaped, float p_width, uint16_t /*JustificationFlag*/ p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) = 0;
+ virtual float shaped_text_tab_align(RID p_shaped, const PackedFloat32Array &p_tab_stops) = 0;
virtual bool shaped_text_shape(RID p_shaped) = 0;
virtual bool shaped_text_update_breaks(RID p_shaped) = 0;
@@ -360,18 +375,26 @@ public:
virtual bool shaped_text_is_ready(RID p_shaped) const = 0;
- virtual Vector<Glyph> shaped_text_get_glyphs(RID p_shaped) const = 0;
+ virtual const Glyph *shaped_text_get_glyphs(RID p_shaped) const = 0;
+ Array _shaped_text_get_glyphs_wrapper(RID p_shaped) const;
+ virtual const Glyph *shaped_text_sort_logical(RID p_shaped) = 0;
+ Array _shaped_text_sort_logical_wrapper(RID p_shaped);
+ virtual int shaped_text_get_glyph_count(RID p_shaped) const = 0;
virtual Vector2i shaped_text_get_range(RID p_shaped) const = 0;
- virtual Vector<Glyph> shaped_text_sort_logical(RID p_shaped) = 0;
+ virtual PackedInt32Array shaped_text_get_line_breaks_adv(RID p_shaped, const PackedFloat32Array &p_width, int p_start = 0, bool p_once = true, uint16_t /*TextBreakFlag*/ p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const;
+ virtual PackedInt32Array shaped_text_get_line_breaks(RID p_shaped, float p_width, int p_start = 0, uint16_t /*TextBreakFlag*/ p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const;
+ virtual PackedInt32Array shaped_text_get_word_breaks(RID p_shaped, int p_grapheme_flags = GRAPHEME_IS_SPACE | GRAPHEME_IS_PUNCTUATION) const;
+
+ virtual int shaped_text_get_trim_pos(RID p_shaped) const = 0;
+ virtual int shaped_text_get_ellipsis_pos(RID p_shaped) const = 0;
+ virtual const Glyph *shaped_text_get_ellipsis_glyphs(RID p_shaped) const = 0;
+ Array _shaped_text_get_ellipsis_glyphs_wrapper(RID p_shaped) const;
+ virtual int shaped_text_get_ellipsis_glyph_count(RID p_shaped) const = 0;
- virtual Vector<Vector2i> shaped_text_get_line_breaks_adv(RID p_shaped, const Vector<float> &p_width, int p_start = 0, bool p_once = true, uint8_t /*TextBreakFlag*/ p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const;
- virtual Vector<Vector2i> shaped_text_get_line_breaks(RID p_shaped, float p_width, int p_start = 0, uint8_t /*TextBreakFlag*/ p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const;
- virtual Vector<Vector2i> shaped_text_get_word_breaks(RID p_shaped, int p_grapheme_flags = GRAPHEME_IS_SPACE | GRAPHEME_IS_PUNCTUATION) const;
+ virtual void shaped_text_overrun_trim_to_width(RID p_shaped, float p_width, uint16_t p_trim_flags) = 0;
- virtual TrimData shaped_text_get_trim_data(RID p_shaped) const;
- virtual void shaped_text_overrun_trim_to_width(RID p_shaped, float p_width, uint8_t p_trim_flags) = 0;
virtual Array shaped_text_get_objects(RID p_shaped) const = 0;
virtual Rect2 shaped_text_get_object_rect(RID p_shaped, Variant p_key) const = 0;
@@ -382,16 +405,18 @@ public:
virtual float shaped_text_get_underline_position(RID p_shaped) const = 0;
virtual float shaped_text_get_underline_thickness(RID p_shaped) const = 0;
- virtual Direction shaped_text_get_dominant_direciton_in_range(RID p_shaped, int p_start, int p_end) const;
+ virtual Direction shaped_text_get_dominant_direction_in_range(RID p_shaped, int p_start, int p_end) const;
+
+ virtual CaretInfo shaped_text_get_carets(RID p_shaped, int p_position) const;
+ Dictionary _shaped_text_get_carets_wrapper(RID p_shaped, int p_position) const;
- virtual void shaped_text_get_carets(RID p_shaped, int p_position, Rect2 &p_leading_caret, Direction &p_leading_dir, Rect2 &p_trailing_caret, Direction &p_trailing_dir) const;
virtual Vector<Vector2> shaped_text_get_selection(RID p_shaped, int p_start, int p_end) const;
virtual int shaped_text_hit_test_grapheme(RID p_shaped, float p_coords) const; // Return grapheme index.
virtual int shaped_text_hit_test_position(RID p_shaped, float p_coords) const; // Return caret/selection position.
- virtual int shaped_text_next_grapheme_pos(RID p_shaped, int p_pos);
- virtual int shaped_text_prev_grapheme_pos(RID p_shaped, int p_pos);
+ virtual int shaped_text_next_grapheme_pos(RID p_shaped, int p_pos) const;
+ virtual int shaped_text_prev_grapheme_pos(RID p_shaped, int p_pos) const;
// The pen position is always placed on the baseline and moveing left to right.
virtual void shaped_text_draw(RID p_shaped, RID p_canvas, const Vector2 &p_pos, float p_clip_l = -1.f, float p_clip_r = -1.f, const Color &p_color = Color(1, 1, 1)) const;
@@ -402,24 +427,57 @@ public:
virtual String parse_number(const String &p_string, const String &p_language = "") const { return p_string; };
virtual String percent_sign(const String &p_language = "") const { return "%"; };
- /* GDScript wrappers */
- RID _create_font_memory(const PackedByteArray &p_data, const String &p_type, int p_base_size = 16);
+ TextServer();
+ ~TextServer();
+};
+
+/*************************************************************************/
- Dictionary _font_get_glyph_contours(RID p_font, int p_size, uint32_t p_index) const;
+struct Glyph {
+ int start = -1; // Start offset in the source string.
+ int end = -1; // End offset in the source string.
- Array _shaped_text_get_glyphs(RID p_shaped) const;
- Dictionary _shaped_text_get_carets(RID p_shaped, int p_position) const;
+ uint8_t count = 0; // Number of glyphs in the grapheme, set in the first glyph only.
+ uint8_t repeat = 1; // Draw multiple times in the row.
+ uint16_t flags = 0; // Grapheme flags (valid, rtl, virtual), set in the first glyph only.
- void _shaped_text_set_bidi_override(RID p_shaped, const Array &p_override);
+ float x_off = 0.f; // Offset from the origin of the glyph on baseline.
+ float y_off = 0.f;
+ float advance = 0.f; // Advance to the next glyph along baseline(x for horizontal layout, y for vertical).
- Array _shaped_text_get_line_breaks_adv(RID p_shaped, const PackedFloat32Array &p_width, int p_start, bool p_once, uint8_t p_break_flags) const;
- Array _shaped_text_get_line_breaks(RID p_shaped, float p_width, int p_start, uint8_t p_break_flags) const;
- Array _shaped_text_get_word_breaks(RID p_shaped) const;
+ RID font_rid; // Font resource.
+ int font_size = 0; // Font size;
+ int32_t index = 0; // Glyph index (font specific) or UTF-32 codepoint (for the invalid glyphs).
- Array _shaped_text_get_selection(RID p_shaped, int p_start, int p_end) const;
+ bool operator==(const Glyph &p_a) const;
+ bool operator!=(const Glyph &p_a) const;
- TextServer();
- ~TextServer();
+ bool operator<(const Glyph &p_a) const;
+ bool operator>(const Glyph &p_a) const;
+};
+
+struct CaretInfo {
+ Rect2 l_caret;
+ Rect2 t_caret;
+ TextServer::Direction l_dir;
+ TextServer::Direction t_dir;
+};
+
+struct GlyphCompare { // For line breaking reordering.
+ _FORCE_INLINE_ bool operator()(const Glyph &l, const Glyph &r) const {
+ if (l.start == r.start) {
+ if (l.count == r.count) {
+ if ((l.flags & TextServer::GRAPHEME_IS_VIRTUAL) == TextServer::GRAPHEME_IS_VIRTUAL) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+ return l.count > r.count; // Sort first glyph with count & flags, order of the rest are irrelevant.
+ } else {
+ return l.start < r.start;
+ }
+ }
};
/*************************************************************************/
@@ -427,52 +485,32 @@ public:
class TextServerManager : public Object {
GDCLASS(TextServerManager, Object);
-public:
- typedef TextServer *(*CreateFunction)(Error &r_error, void *p_user_data);
-
protected:
static void _bind_methods();
private:
static TextServerManager *singleton;
- static TextServer *server;
- enum {
- MAX_SERVERS = 64
- };
-
- struct TextServerCreate {
- String name;
- CreateFunction create_function = nullptr;
- uint32_t features = 0;
- TextServer *instance = nullptr;
- void *user_data = nullptr;
- };
- static TextServerCreate server_create_functions[MAX_SERVERS];
- static int server_create_count;
+ Ref<TextServer> primary_interface;
+ Vector<Ref<TextServer>> interfaces;
public:
_FORCE_INLINE_ static TextServerManager *get_singleton() {
return singleton;
}
- static void register_create_function(const String &p_name, uint32_t p_features, CreateFunction p_function, void *p_user_data);
- static int get_interface_count();
- static String get_interface_name(int p_index);
- static uint32_t get_interface_features(int p_index);
- static TextServer *initialize(int p_index, Error &r_error);
- static TextServer *get_primary_interface();
+ void add_interface(const Ref<TextServer> &p_interface);
+ void remove_interface(const Ref<TextServer> &p_interface);
+ int get_interface_count() const;
+ Ref<TextServer> get_interface(int p_index) const;
+ Ref<TextServer> find_interface(const String &p_name) const;
+ Array get_interfaces() const;
- /* GDScript wrappers */
- int _get_interface_count() const;
- String _get_interface_name(int p_index) const;
- uint32_t _get_interface_features(int p_index) const;
- TextServer *_get_interface(int p_index) const;
- Array _get_interfaces() const;
- TextServer *_find_interface(const String &p_name) const;
-
- bool _set_primary_interface(int p_index);
- TextServer *_get_primary_interface() const;
+ _FORCE_INLINE_ Ref<TextServer> get_primary_interface() const {
+ return primary_interface;
+ }
+ Ref<TextServer> _get_primary_interface() const;
+ void set_primary_interface(const Ref<TextServer> &p_primary_interface);
TextServerManager();
~TextServerManager();
@@ -480,7 +518,7 @@ public:
/*************************************************************************/
-#define TS TextServerManager::get_primary_interface()
+#define TS TextServerManager::get_singleton()->get_primary_interface()
VARIANT_ENUM_CAST(TextServer::Direction);
VARIANT_ENUM_CAST(TextServer::Orientation);
@@ -491,5 +529,10 @@ VARIANT_ENUM_CAST(TextServer::GraphemeFlag);
VARIANT_ENUM_CAST(TextServer::Hinting);
VARIANT_ENUM_CAST(TextServer::Feature);
VARIANT_ENUM_CAST(TextServer::ContourPointTag);
+VARIANT_ENUM_CAST(TextServer::SpacingType);
+
+GDVIRTUAL_NATIVE_PTR(Glyph);
+GDVIRTUAL_NATIVE_PTR(Glyph *);
+GDVIRTUAL_NATIVE_PTR(CaretInfo);
#endif // TEXT_SERVER_H
diff --git a/servers/xr/xr_interface.cpp b/servers/xr/xr_interface.cpp
index 09e8e12f8b..bf54158905 100644
--- a/servers/xr/xr_interface.cpp
+++ b/servers/xr/xr_interface.cpp
@@ -29,28 +29,26 @@
/*************************************************************************/
#include "xr_interface.h"
-#include "servers/rendering/renderer_compositor.h"
+// #include "servers/rendering/renderer_compositor.h"
void XRInterface::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_name"), &XRInterface::get_name);
ClassDB::bind_method(D_METHOD("get_capabilities"), &XRInterface::get_capabilities);
ClassDB::bind_method(D_METHOD("is_primary"), &XRInterface::is_primary);
- ClassDB::bind_method(D_METHOD("set_is_primary", "enable"), &XRInterface::set_is_primary);
+ ClassDB::bind_method(D_METHOD("set_primary", "primary"), &XRInterface::set_primary);
ClassDB::bind_method(D_METHOD("is_initialized"), &XRInterface::is_initialized);
- ClassDB::bind_method(D_METHOD("set_is_initialized", "initialized"), &XRInterface::set_is_initialized);
ClassDB::bind_method(D_METHOD("initialize"), &XRInterface::initialize);
ClassDB::bind_method(D_METHOD("uninitialize"), &XRInterface::uninitialize);
ClassDB::bind_method(D_METHOD("get_tracking_status"), &XRInterface::get_tracking_status);
- ClassDB::bind_method(D_METHOD("get_render_targetsize"), &XRInterface::get_render_targetsize);
+ ClassDB::bind_method(D_METHOD("get_render_target_size"), &XRInterface::get_render_target_size);
ClassDB::bind_method(D_METHOD("get_view_count"), &XRInterface::get_view_count);
ADD_GROUP("Interface", "interface_");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interface_is_primary"), "set_is_primary", "is_primary");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interface_is_initialized"), "set_is_initialized", "is_initialized");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interface_is_primary"), "set_primary", "is_primary");
// we don't have any properties specific to VR yet....
@@ -77,70 +75,48 @@ void XRInterface::_bind_methods() {
BIND_ENUM_CONSTANT(XR_INSUFFICIENT_FEATURES);
BIND_ENUM_CONSTANT(XR_UNKNOWN_TRACKING);
BIND_ENUM_CONSTANT(XR_NOT_TRACKING);
-};
-
-StringName XRInterface::get_name() const {
- return "Unknown";
-};
+}
bool XRInterface::is_primary() {
XRServer *xr_server = XRServer::get_singleton();
ERR_FAIL_NULL_V(xr_server, false);
return xr_server->get_primary_interface() == this;
-};
+}
-void XRInterface::set_is_primary(bool p_is_primary) {
+void XRInterface::set_primary(bool p_primary) {
XRServer *xr_server = XRServer::get_singleton();
ERR_FAIL_NULL(xr_server);
- if (p_is_primary) {
+ if (p_primary) {
ERR_FAIL_COND(!is_initialized());
xr_server->set_primary_interface(this);
- } else {
- xr_server->clear_primary_interface_if(this);
- };
-};
-
-void XRInterface::set_is_initialized(bool p_initialized) {
- if (p_initialized) {
- if (!is_initialized()) {
- initialize();
- };
- } else {
- if (is_initialized()) {
- uninitialize();
- };
- };
-};
-
-XRInterface::Tracking_status XRInterface::get_tracking_status() const {
- return tracking_state;
-};
-
-XRInterface::XRInterface() {
- tracking_state = XR_UNKNOWN_TRACKING;
-};
+ } else if (xr_server->get_primary_interface() == this) {
+ xr_server->set_primary_interface(nullptr);
+ }
+}
-XRInterface::~XRInterface() {}
+XRInterface::XRInterface() {}
-// optional render to external texture which enhances performance on those platforms that require us to submit our end result into special textures.
-unsigned int XRInterface::get_external_texture_for_eye(XRInterface::Eyes p_eye) {
- return 0;
-};
+XRInterface::~XRInterface() {}
/** these will only be implemented on AR interfaces, so we want dummies for VR **/
bool XRInterface::get_anchor_detection_is_enabled() const {
return false;
-};
+}
void XRInterface::set_anchor_detection_is_enabled(bool p_enable) {
- // don't do anything here, this needs to be implemented on AR interface to enable/disable things like plane detection etc.
}
int XRInterface::get_camera_feed_id() {
- // don't do anything here, this needs to be implemented on AR interface to enable/disable things like plane detection etc.
-
return 0;
-};
+}
+
+/** these are optional, so we want dummies **/
+XRInterface::TrackingStatus XRInterface::get_tracking_status() const {
+ return XR_UNKNOWN_TRACKING;
+}
+
+void XRInterface::notification(int p_what) {
+}
diff --git a/servers/xr/xr_interface.h b/servers/xr/xr_interface.h
index 6b248c9554..534fa18d8a 100644
--- a/servers/xr/xr_interface.h
+++ b/servers/xr/xr_interface.h
@@ -68,7 +68,7 @@ public:
EYE_RIGHT
};
- enum Tracking_status { /* tracking status currently based on AR but we can start doing more with this for VR as well */
+ enum TrackingStatus { /* tracking status currently based on AR but we can start doing more with this for VR as well */
XR_NORMAL_TRACKING,
XR_EXCESSIVE_MOTION,
XR_INSUFFICIENT_FEATURES,
@@ -76,26 +76,25 @@ public:
XR_NOT_TRACKING
};
+private:
protected:
_THREAD_SAFE_CLASS_
- Tracking_status tracking_state;
static void _bind_methods();
public:
/** general interface information **/
- virtual StringName get_name() const;
- virtual int get_capabilities() const = 0;
+ virtual StringName get_name() const = 0;
+ virtual uint32_t get_capabilities() const = 0;
bool is_primary();
- void set_is_primary(bool p_is_primary);
+ void set_primary(bool p_is_primary);
virtual bool is_initialized() const = 0; /* returns true if we've initialized this interface */
- void set_is_initialized(bool p_initialized); /* helper function, will call initialize or uninitialize */
virtual bool initialize() = 0; /* initialize this interface, if this has an HMD it becomes the primary interface */
virtual void uninitialize() = 0; /* deinitialize this interface */
- Tracking_status get_tracking_status() const; /* get the status of our current tracking */
+ virtual TrackingStatus get_tracking_status() const; /* get the status of our current tracking */
/** specific to VR **/
// nothing yet
@@ -107,27 +106,25 @@ public:
/** rendering and internal **/
- virtual Size2 get_render_targetsize() = 0; /* returns the recommended render target size per eye for this device */
+ virtual Size2 get_render_target_size() = 0; /* returns the recommended render target size per eye for this device */
virtual uint32_t get_view_count() = 0; /* returns the view count we need (1 is monoscopic, 2 is stereoscopic but can be more) */
virtual Transform3D get_camera_transform() = 0; /* returns the position of our camera for updating our camera node. For monoscopic this is equal to the views transform, for stereoscopic this should be an average */
virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) = 0; /* get each views transform */
- virtual CameraMatrix get_projection_for_view(uint32_t p_view, real_t p_aspect, real_t p_z_near, real_t p_z_far) = 0; /* get each view projection matrix */
+ virtual CameraMatrix get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) = 0; /* get each view projection matrix */
+
+ // note, external color/depth/vrs texture support will be added here soon.
virtual Vector<BlitToScreen> commit_views(RID p_render_target, const Rect2 &p_screen_rect) = 0; /* commit rendered views to the XR interface */
virtual void process() = 0;
- virtual void notification(int p_what) = 0;
+ virtual void notification(int p_what);
XRInterface();
~XRInterface();
-
- // deprecated
- virtual unsigned int get_external_texture_for_eye(XRInterface::Eyes p_eye); /* if applicable return external texture to render to */
- virtual void commit_for_eye(XRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect) = 0; /* output the left or right eye */
};
VARIANT_ENUM_CAST(XRInterface::Capabilities);
VARIANT_ENUM_CAST(XRInterface::Eyes);
-VARIANT_ENUM_CAST(XRInterface::Tracking_status);
+VARIANT_ENUM_CAST(XRInterface::TrackingStatus);
-#endif
+#endif // !XR_INTERFACE_H
diff --git a/servers/xr/xr_interface_extension.cpp b/servers/xr/xr_interface_extension.cpp
new file mode 100644
index 0000000000..7fdf90770d
--- /dev/null
+++ b/servers/xr/xr_interface_extension.cpp
@@ -0,0 +1,267 @@
+/*************************************************************************/
+/* xr_interface_extension.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 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 "xr_interface_extension.h"
+#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
+#include "servers/rendering/renderer_storage.h"
+#include "servers/rendering/rendering_server_globals.h"
+
+void XRInterfaceExtension::_bind_methods() {
+ GDVIRTUAL_BIND(_get_name);
+ GDVIRTUAL_BIND(_get_capabilities);
+
+ GDVIRTUAL_BIND(_is_initialized);
+ GDVIRTUAL_BIND(_initialize);
+ GDVIRTUAL_BIND(_uninitialize);
+
+ GDVIRTUAL_BIND(_get_tracking_status);
+
+ GDVIRTUAL_BIND(_get_render_target_size);
+ GDVIRTUAL_BIND(_get_view_count);
+ GDVIRTUAL_BIND(_get_camera_transform);
+ GDVIRTUAL_BIND(_get_transform_for_view, "view", "cam_transform");
+ GDVIRTUAL_BIND(_get_projection_for_view, "view", "aspect", "z_near", "z_far");
+
+ GDVIRTUAL_BIND(_commit_views, "render_target", "screen_rect");
+
+ GDVIRTUAL_BIND(_process);
+ GDVIRTUAL_BIND(_notification, "what");
+
+ // we don't have any properties specific to VR yet....
+
+ // but we do have properties specific to AR....
+ GDVIRTUAL_BIND(_get_anchor_detection_is_enabled);
+ GDVIRTUAL_BIND(_set_anchor_detection_is_enabled, "enabled");
+ GDVIRTUAL_BIND(_get_camera_feed_id);
+
+ // helper methods
+ ClassDB::bind_method(D_METHOD("add_blit", "render_target", "src_rect", "dst_rect", "use_layer", "layer", "apply_lens_distortion", "eye_center", "k1", "k2", "upscale", "aspect_ratio"), &XRInterfaceExtension::add_blit);
+ ClassDB::bind_method(D_METHOD("get_render_target_texture", "render_target"), &XRInterfaceExtension::get_render_target_texture);
+ // ClassDB::bind_method(D_METHOD("get_render_target_depth", "render_target"), &XRInterfaceExtension::get_render_target_depth);
+}
+
+StringName XRInterfaceExtension::get_name() const {
+ StringName name;
+
+ if (GDVIRTUAL_CALL(_get_name, name)) {
+ return name;
+ }
+
+ return "Unknown";
+}
+
+uint32_t XRInterfaceExtension::get_capabilities() const {
+ uint32_t capabilities;
+
+ if (GDVIRTUAL_CALL(_get_capabilities, capabilities)) {
+ return capabilities;
+ }
+
+ return 0;
+}
+
+bool XRInterfaceExtension::is_initialized() const {
+ bool initialised = false;
+
+ if (GDVIRTUAL_CALL(_is_initialized, initialised)) {
+ return initialised;
+ }
+
+ return false;
+}
+
+bool XRInterfaceExtension::initialize() {
+ bool initialised = false;
+
+ if (GDVIRTUAL_CALL(_initialize, initialised)) {
+ return initialised;
+ }
+
+ return false;
+}
+
+void XRInterfaceExtension::uninitialize() {
+ GDVIRTUAL_CALL(_uninitialize);
+}
+
+XRInterface::TrackingStatus XRInterfaceExtension::get_tracking_status() const {
+ uint32_t status;
+
+ if (GDVIRTUAL_CALL(_get_tracking_status, status)) {
+ return TrackingStatus(status);
+ }
+
+ return XR_UNKNOWN_TRACKING;
+}
+
+/** these will only be implemented on AR interfaces, so we want dummies for VR **/
+bool XRInterfaceExtension::get_anchor_detection_is_enabled() const {
+ bool enabled;
+
+ if (GDVIRTUAL_CALL(_get_anchor_detection_is_enabled, enabled)) {
+ return enabled;
+ }
+
+ return false;
+}
+
+void XRInterfaceExtension::set_anchor_detection_is_enabled(bool p_enable) {
+ // don't do anything here, this needs to be implemented on AR interface to enable/disable things like plane detection etc.
+ GDVIRTUAL_CALL(_set_anchor_detection_is_enabled, p_enable);
+}
+
+int XRInterfaceExtension::get_camera_feed_id() {
+ int feed_id;
+
+ if (GDVIRTUAL_CALL(_get_camera_feed_id, feed_id)) {
+ return feed_id;
+ }
+
+ return 0;
+}
+
+Size2 XRInterfaceExtension::get_render_target_size() {
+ Size2 size;
+
+ if (GDVIRTUAL_CALL(_get_render_target_size, size)) {
+ return size;
+ }
+
+ return Size2(0, 0);
+}
+
+uint32_t XRInterfaceExtension::get_view_count() {
+ uint32_t view_count;
+
+ if (GDVIRTUAL_CALL(_get_view_count, view_count)) {
+ return view_count;
+ }
+
+ return 1;
+}
+
+Transform3D XRInterfaceExtension::get_camera_transform() {
+ Transform3D transform;
+
+ if (GDVIRTUAL_CALL(_get_camera_transform, transform)) {
+ return transform;
+ }
+
+ return Transform3D();
+}
+
+Transform3D XRInterfaceExtension::get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) {
+ Transform3D transform;
+
+ if (GDVIRTUAL_CALL(_get_transform_for_view, p_view, p_cam_transform, transform)) {
+ return transform;
+ }
+
+ return Transform3D();
+}
+
+CameraMatrix XRInterfaceExtension::get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) {
+ CameraMatrix cm;
+ PackedFloat64Array arr;
+
+ if (GDVIRTUAL_CALL(_get_projection_for_view, p_view, p_aspect, p_z_near, p_z_far, arr)) {
+ ERR_FAIL_COND_V_MSG(arr.size() != 16, CameraMatrix(), "Projection matrix must contain 16 floats");
+ real_t *m = (real_t *)cm.matrix;
+ for (int i = 0; i < 16; i++) {
+ m[i] = arr[i];
+ }
+ return cm;
+ }
+
+ return CameraMatrix();
+}
+
+void XRInterfaceExtension::add_blit(RID p_render_target, Rect2 p_src_rect, Rect2i p_dst_rect, bool p_use_layer, uint32_t p_layer, bool p_apply_lens_distortion, Vector2 p_eye_center, double p_k1, double p_k2, double p_upscale, double p_aspect_ratio) {
+ BlitToScreen blit;
+
+ ERR_FAIL_COND_MSG(!can_add_blits, "add_blit can only be called from an XR plugin from within _commit_views!");
+
+ blit.render_target = p_render_target;
+ blit.src_rect = p_src_rect;
+ blit.dst_rect = p_dst_rect;
+
+ blit.multi_view.use_layer = p_use_layer;
+ blit.multi_view.layer = p_layer;
+
+ blit.lens_distortion.apply = p_apply_lens_distortion;
+ blit.lens_distortion.eye_center = p_eye_center;
+ blit.lens_distortion.k1 = p_k1;
+ blit.lens_distortion.k2 = p_k2;
+ blit.lens_distortion.upscale = p_upscale;
+ blit.lens_distortion.aspect_ratio = p_aspect_ratio;
+
+ blits.push_back(blit);
+}
+
+Vector<BlitToScreen> XRInterfaceExtension::commit_views(RID p_render_target, const Rect2 &p_screen_rect) {
+ // This is just so our XR plugin can add blits...
+ blits.clear();
+ can_add_blits = true;
+
+ if (GDVIRTUAL_CALL(_commit_views, p_render_target, p_screen_rect)) {
+ return blits;
+ }
+
+ can_add_blits = false;
+ return blits;
+}
+
+void XRInterfaceExtension::process() {
+ GDVIRTUAL_CALL(_process);
+}
+
+void XRInterfaceExtension::notification(int p_what) {
+ GDVIRTUAL_CALL(_notification, p_what);
+}
+
+RID XRInterfaceExtension::get_render_target_texture(RID p_render_target) {
+ // In due time this will need to be enhance to return the correct INTERNAL RID for the chosen rendering engine.
+ // So once a GLES driver is implemented we'll return that and the implemented plugin needs to handle this correctly too.
+ RendererStorageRD *rd_storage = RendererStorageRD::base_singleton;
+ ERR_FAIL_NULL_V_MSG(rd_storage, RID(), "Renderer storage not setup");
+
+ return rd_storage->render_target_get_rd_texture(p_render_target);
+}
+
+/*
+RID XRInterfaceExtension::get_render_target_depth(RID p_render_target) {
+ // TODO implement this, the problem is that our depth texture isn't part of our render target as it is used for 3D rendering only
+ // but we don't have access to our render buffers from here....
+ RendererSceneRenderRD * rd_scene = ?????;
+ ERR_FAIL_NULL_V_MSG(rd_scene, RID(), "Renderer scene render not setup");
+
+ return rd_scene->render_buffers_get_depth_texture(????????????);
+}
+*/
diff --git a/servers/xr/xr_interface_extension.h b/servers/xr/xr_interface_extension.h
new file mode 100644
index 0000000000..3b7af4c0a2
--- /dev/null
+++ b/servers/xr/xr_interface_extension.h
@@ -0,0 +1,109 @@
+/*************************************************************************/
+/* xr_interface_extension.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 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 XR_INTERFACE_EXTENSION_H
+#define XR_INTERFACE_EXTENSION_H
+
+#include "servers/xr/xr_interface.h"
+
+class XRInterfaceExtension : public XRInterface {
+ GDCLASS(XRInterfaceExtension, XRInterface);
+
+public:
+private:
+ bool can_add_blits = false;
+ Vector<BlitToScreen> blits;
+
+protected:
+ _THREAD_SAFE_CLASS_
+
+ static void _bind_methods();
+
+public:
+ /** general interface information **/
+ virtual StringName get_name() const override;
+ virtual uint32_t get_capabilities() const override;
+
+ GDVIRTUAL0RC(StringName, _get_name);
+ GDVIRTUAL0RC(uint32_t, _get_capabilities);
+
+ virtual bool is_initialized() const override;
+ virtual bool initialize() override;
+ virtual void uninitialize() override;
+
+ GDVIRTUAL0RC(bool, _is_initialized);
+ GDVIRTUAL0R(bool, _initialize);
+ GDVIRTUAL0(_uninitialize);
+
+ virtual TrackingStatus get_tracking_status() const override;
+ GDVIRTUAL0RC(uint32_t, _get_tracking_status);
+
+ /** specific to VR **/
+ // nothing yet
+
+ /** specific to AR **/
+ virtual bool get_anchor_detection_is_enabled() const override;
+ virtual void set_anchor_detection_is_enabled(bool p_enable) override;
+ virtual int get_camera_feed_id() override;
+
+ GDVIRTUAL0RC(bool, _get_anchor_detection_is_enabled);
+ GDVIRTUAL1(_set_anchor_detection_is_enabled, bool);
+ GDVIRTUAL0RC(int, _get_camera_feed_id);
+
+ /** rendering and internal **/
+
+ virtual Size2 get_render_target_size() override;
+ virtual uint32_t get_view_count() override;
+ virtual Transform3D get_camera_transform() override;
+ virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) override;
+ virtual CameraMatrix get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) override;
+
+ GDVIRTUAL0R(Size2, _get_render_target_size);
+ GDVIRTUAL0R(uint32_t, _get_view_count);
+ GDVIRTUAL0R(Transform3D, _get_camera_transform);
+ GDVIRTUAL2R(Transform3D, _get_transform_for_view, uint32_t, const Transform3D &);
+ GDVIRTUAL4R(PackedFloat64Array, _get_projection_for_view, uint32_t, double, double, double);
+
+ void add_blit(RID p_render_target, Rect2 p_src_rect, Rect2i p_dst_rect, bool p_use_layer = false, uint32_t p_layer = 0, bool p_apply_lens_distortion = false, Vector2 p_eye_center = Vector2(), double p_k1 = 0.0, double p_k2 = 0.0, double p_upscale = 1.0, double p_aspect_ratio = 1.0);
+ virtual Vector<BlitToScreen> commit_views(RID p_render_target, const Rect2 &p_screen_rect) override;
+ GDVIRTUAL2(_commit_views, RID, const Rect2 &);
+
+ virtual void process() override;
+ virtual void notification(int p_what) override;
+
+ GDVIRTUAL0(_process);
+ GDVIRTUAL1(_notification, int);
+
+ /* access to some internals we need */
+ RID get_render_target_texture(RID p_render_target);
+ // RID get_render_target_depth(RID p_render_target);
+};
+
+#endif // !XR_INTERFACE_EXTENSION_H
diff --git a/servers/xr_server.cpp b/servers/xr_server.cpp
index c27656047f..780bd10fc5 100644
--- a/servers/xr_server.cpp
+++ b/servers/xr_server.cpp
@@ -41,7 +41,7 @@ XRServer *XRServer::get_singleton() {
void XRServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_world_scale"), &XRServer::get_world_scale);
- ClassDB::bind_method(D_METHOD("set_world_scale"), &XRServer::set_world_scale);
+ ClassDB::bind_method(D_METHOD("set_world_scale", "scale"), &XRServer::set_world_scale);
ClassDB::bind_method(D_METHOD("get_reference_frame"), &XRServer::get_reference_frame);
ClassDB::bind_method(D_METHOD("center_on_hmd", "rotation_mode", "keep_height"), &XRServer::center_on_hmd);
ClassDB::bind_method(D_METHOD("get_hmd_transform"), &XRServer::get_hmd_transform);
@@ -49,7 +49,6 @@ void XRServer::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "world_scale"), "set_world_scale", "get_world_scale");
ClassDB::bind_method(D_METHOD("add_interface", "interface"), &XRServer::add_interface);
- ClassDB::bind_method(D_METHOD("clear_primary_interface_if", "interface"), &XRServer::clear_primary_interface_if);
ClassDB::bind_method(D_METHOD("get_interface_count"), &XRServer::get_interface_count);
ClassDB::bind_method(D_METHOD("remove_interface", "interface"), &XRServer::remove_interface);
ClassDB::bind_method(D_METHOD("get_interface", "idx"), &XRServer::get_interface);
@@ -87,11 +86,11 @@ void XRServer::_bind_methods() {
ADD_SIGNAL(MethodInfo("tracker_removed", PropertyInfo(Variant::STRING_NAME, "tracker_name"), PropertyInfo(Variant::INT, "type"), PropertyInfo(Variant::INT, "id")));
};
-real_t XRServer::get_world_scale() const {
+double XRServer::get_world_scale() const {
return world_scale;
};
-void XRServer::set_world_scale(real_t p_world_scale) {
+void XRServer::set_world_scale(double p_world_scale) {
if (p_world_scale < 0.01) {
p_world_scale = 0.01;
} else if (p_world_scale > 1000.0) {
@@ -316,17 +315,14 @@ Ref<XRInterface> XRServer::get_primary_interface() const {
};
void XRServer::set_primary_interface(const Ref<XRInterface> &p_primary_interface) {
- ERR_FAIL_COND(p_primary_interface.is_null());
- primary_interface = p_primary_interface;
-
- print_verbose("XR: Primary interface set to: " + primary_interface->get_name());
-};
-
-void XRServer::clear_primary_interface_if(const Ref<XRInterface> &p_primary_interface) {
- if (primary_interface == p_primary_interface) {
+ if (p_primary_interface.is_null()) {
print_verbose("XR: Clearing primary interface");
primary_interface.unref();
- };
+ } else {
+ primary_interface = p_primary_interface;
+
+ print_verbose("XR: Primary interface set to: " + primary_interface->get_name());
+ }
};
uint64_t XRServer::get_last_process_usec() {
diff --git a/servers/xr_server.h b/servers/xr_server.h
index 25431844c2..6d07263755 100644
--- a/servers/xr_server.h
+++ b/servers/xr_server.h
@@ -81,7 +81,7 @@ private:
Ref<XRInterface> primary_interface; /* we'll identify one interface as primary, this will be used by our viewports */
- real_t world_scale; /* scale by which we multiply our tracker positions */
+ double world_scale; /* scale by which we multiply our tracker positions */
Transform3D world_origin; /* our world origin point, maps a location in our virtual world to the origin point in our real world tracking volume */
Transform3D reference_frame; /* our reference frame */
@@ -107,8 +107,8 @@ public:
I may remove access to this property in GDScript in favour of exposing it on the XROrigin3D node
*/
- real_t get_world_scale() const;
- void set_world_scale(real_t p_world_scale);
+ double get_world_scale() const;
+ void set_world_scale(double p_world_scale);
/*
The world maps the 0,0,0 coordinate of our real world coordinate system for our tracking volume to a location in our
@@ -159,7 +159,6 @@ public:
*/
Ref<XRInterface> get_primary_interface() const;
void set_primary_interface(const Ref<XRInterface> &p_primary_interface);
- void clear_primary_interface_if(const Ref<XRInterface> &p_primary_interface); /* this is automatically called if an interface destructs */
/*
Our trackers are objects that expose the orientation and position of physical devices such as controller, anchor points, etc.