summaryrefslogtreecommitdiffstats
path: root/servers
diff options
context:
space:
mode:
Diffstat (limited to 'servers')
-rw-r--r--servers/SCsub31
-rw-r--r--servers/audio/effects/audio_effect_hard_limiter.cpp161
-rw-r--r--servers/audio/effects/audio_effect_hard_limiter.h89
-rw-r--r--servers/audio/effects/audio_effect_pitch_shift.cpp17
-rw-r--r--servers/audio/effects/audio_effect_pitch_shift.h50
-rw-r--r--servers/audio_server.cpp13
-rw-r--r--servers/audio_server.h4
-rw-r--r--servers/camera_server.h4
-rw-r--r--servers/display/SCsub5
-rw-r--r--servers/display/native_menu.cpp444
-rw-r--r--servers/display/native_menu.h160
-rw-r--r--servers/display_server.cpp329
-rw-r--r--servers/display_server.h17
-rw-r--r--servers/display_server_headless.h13
-rw-r--r--servers/extensions/SCsub5
-rw-r--r--servers/navigation_server_3d.cpp7
-rw-r--r--servers/physics_2d/godot_broad_phase_2d_bvh.h4
-rw-r--r--servers/physics_2d/godot_collision_solver_2d_sat.cpp2
-rw-r--r--servers/physics_3d/godot_broad_phase_3d_bvh.h4
-rw-r--r--servers/physics_3d/godot_collision_solver_3d_sat.cpp4
-rw-r--r--servers/physics_3d/godot_shape_3d.cpp4
-rw-r--r--servers/physics_3d/godot_soft_body_3d.cpp2
-rw-r--r--servers/physics_3d/godot_space_3d.cpp2
-rw-r--r--servers/physics_server_3d.cpp14
-rw-r--r--servers/physics_server_3d.h4
-rw-r--r--servers/register_server_types.cpp60
-rw-r--r--servers/rendering/dummy/storage/light_storage.h1
-rw-r--r--servers/rendering/renderer_canvas_cull.cpp270
-rw-r--r--servers/rendering/renderer_canvas_cull.h45
-rw-r--r--servers/rendering/renderer_canvas_render.h42
-rw-r--r--servers/rendering/renderer_compositor.cpp2
-rw-r--r--servers/rendering/renderer_rd/cluster_builder_rd.cpp6
-rw-r--r--servers/rendering/renderer_rd/effects/copy_effects.cpp8
-rw-r--r--servers/rendering/renderer_rd/effects/debug_effects.cpp4
-rw-r--r--servers/rendering/renderer_rd/effects/fsr2.cpp3
-rw-r--r--servers/rendering/renderer_rd/effects/ss_effects.cpp8
-rw-r--r--servers/rendering/renderer_rd/effects/tone_mapper.cpp16
-rw-r--r--servers/rendering/renderer_rd/effects/vrs.cpp7
-rw-r--r--servers/rendering/renderer_rd/environment/fog.cpp13
-rw-r--r--servers/rendering/renderer_rd/environment/gi.cpp17
-rw-r--r--servers/rendering/renderer_rd/environment/sky.cpp7
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp44
-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.cpp14
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp15
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h2
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp14
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp36
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.h2
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp9
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl4
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl4
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl28
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/cube_to_dp.glsl6
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_scale.glsl4
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/tonemap.glsl34
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/vrs.glsl26
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/gi.glsl4
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/sky.glsl8
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl6
-rw-r--r--servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl4
-rw-r--r--servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl4
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl11
-rw-r--r--servers/rendering/renderer_rd/storage_rd/light_storage.cpp30
-rw-r--r--servers/rendering/renderer_rd/storage_rd/light_storage.h2
-rw-r--r--servers/rendering/renderer_rd/storage_rd/particles_storage.cpp14
-rw-r--r--servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp7
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.cpp5
-rw-r--r--servers/rendering/renderer_scene_cull.cpp75
-rw-r--r--servers/rendering/renderer_scene_cull.h10
-rw-r--r--servers/rendering/renderer_scene_occlusion_cull.cpp7
-rw-r--r--servers/rendering/renderer_scene_occlusion_cull.h52
-rw-r--r--servers/rendering/renderer_viewport.cpp71
-rw-r--r--servers/rendering/renderer_viewport.h6
-rw-r--r--servers/rendering/rendering_device.cpp27
-rw-r--r--servers/rendering/rendering_device.h4
-rw-r--r--servers/rendering/rendering_device_commons.cpp7
-rw-r--r--servers/rendering/rendering_device_commons.h4
-rw-r--r--servers/rendering/rendering_device_driver.cpp2
-rw-r--r--servers/rendering/rendering_device_driver.h10
-rw-r--r--servers/rendering/rendering_device_graph.cpp6
-rw-r--r--servers/rendering/rendering_light_culler.cpp19
-rw-r--r--servers/rendering/rendering_light_culler.h33
-rw-r--r--servers/rendering/rendering_method.h7
-rw-r--r--servers/rendering/rendering_server_default.cpp13
-rw-r--r--servers/rendering/rendering_server_default.h19
-rw-r--r--servers/rendering/shader_compiler.h4
-rw-r--r--servers/rendering/shader_language.h2
-rw-r--r--servers/rendering/storage/light_storage.h1
-rw-r--r--servers/rendering/storage/variant_converters.h4
-rw-r--r--servers/rendering_server.cpp17
-rw-r--r--servers/rendering_server.h19
-rw-r--r--servers/text/text_server_dummy.h84
-rw-r--r--servers/text/text_server_extension.cpp214
-rw-r--r--servers/text/text_server_extension.h11
-rw-r--r--servers/text_server.cpp92
-rw-r--r--servers/text_server.h13
-rw-r--r--servers/xr/xr_body_tracker.cpp171
-rw-r--r--servers/xr/xr_body_tracker.h170
-rw-r--r--servers/xr_server.cpp48
-rw-r--r--servers/xr_server.h10
101 files changed, 2892 insertions, 577 deletions
diff --git a/servers/SCsub b/servers/SCsub
index 788a368a4f..736bed68ec 100644
--- a/servers/SCsub
+++ b/servers/SCsub
@@ -3,19 +3,36 @@
Import("env")
env.servers_sources = []
-env.add_source_files(env.servers_sources, "*.cpp")
-SConscript("xr/SCsub")
-SConscript("camera/SCsub")
-SConscript("physics_3d/SCsub")
-SConscript("physics_2d/SCsub")
-SConscript("rendering/SCsub")
+env.add_source_files(env.servers_sources, "audio_server.cpp")
+env.add_source_files(env.servers_sources, "camera_server.cpp")
+env.add_source_files(env.servers_sources, "display_server.cpp")
+env.add_source_files(env.servers_sources, "navigation_server_2d.cpp")
+env.add_source_files(env.servers_sources, "navigation_server_3d.cpp")
+env.add_source_files(env.servers_sources, "physics_server_2d.cpp")
+env.add_source_files(env.servers_sources, "physics_server_2d_wrap_mt.cpp")
+env.add_source_files(env.servers_sources, "register_server_types.cpp")
+env.add_source_files(env.servers_sources, "rendering_server.cpp")
+env.add_source_files(env.servers_sources, "text_server.cpp")
+
SConscript("audio/SCsub")
-SConscript("text/SCsub")
+SConscript("camera/SCsub")
SConscript("debugger/SCsub")
+SConscript("display/SCsub")
SConscript("extensions/SCsub")
SConscript("movie_writer/SCsub")
SConscript("navigation/SCsub")
+SConscript("rendering/SCsub")
+SConscript("text/SCsub")
+
+SConscript("physics_2d/SCsub")
+
+if not env["disable_3d"]:
+ SConscript("physics_3d/SCsub")
+ env.add_source_files(env.servers_sources, "physics_server_3d.cpp")
+ env.add_source_files(env.servers_sources, "physics_server_3d_wrap_mt.cpp")
+ SConscript("xr/SCsub")
+ env.add_source_files(env.servers_sources, "xr_server.cpp")
lib = env.add_library("servers", env.servers_sources)
diff --git a/servers/audio/effects/audio_effect_hard_limiter.cpp b/servers/audio/effects/audio_effect_hard_limiter.cpp
new file mode 100644
index 0000000000..e717557af2
--- /dev/null
+++ b/servers/audio/effects/audio_effect_hard_limiter.cpp
@@ -0,0 +1,161 @@
+/**************************************************************************/
+/* audio_effect_hard_limiter.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#include "audio_effect_hard_limiter.h"
+
+#include "servers/audio_server.h"
+
+void AudioEffectHardLimiterInstance::process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) {
+ float sample_rate = AudioServer::get_singleton()->get_mix_rate();
+
+ float ceiling = Math::db_to_linear(base->ceiling);
+ float release = base->release;
+ float attack = base->attack;
+ float pre_gain = Math::db_to_linear(base->pre_gain);
+
+ for (int i = 0; i < p_frame_count; i++) {
+ float sample_left = p_src_frames[i].left;
+ float sample_right = p_src_frames[i].right;
+
+ sample_left *= pre_gain;
+ sample_right *= pre_gain;
+
+ float largest_sample = MAX(ABS(sample_left), ABS(sample_right));
+
+ release_factor = MAX(0.0, release_factor - 1.0 / sample_rate);
+ release_factor = MIN(release_factor, release);
+
+ if (release_factor > 0.0) {
+ gain = Math::lerp(gain_target, 1.0f, 1.0f - release_factor / release);
+ }
+
+ if (largest_sample * gain > ceiling) {
+ gain_target = ceiling / largest_sample;
+ release_factor = release;
+ attack_factor = attack;
+ }
+
+ // Lerp gain over attack time to avoid distortion.
+ attack_factor = MAX(0.0f, attack_factor - 1.0f / sample_rate);
+ if (attack_factor > 0.0) {
+ gain = Math::lerp(gain_target, gain, 1.0f - attack_factor / attack);
+ }
+
+ int bucket_id = gain_bucket_cursor / gain_bucket_size;
+
+ // If first item within the current bucket, reset the bucket.
+ if (gain_bucket_cursor % gain_bucket_size == 0) {
+ gain_buckets[bucket_id] = 1.0f;
+ }
+
+ gain_buckets[bucket_id] = MIN(gain_buckets[bucket_id], gain);
+
+ gain_bucket_cursor = (gain_bucket_cursor + 1) % gain_samples_to_store;
+
+ for (int j = 0; j < (int)gain_buckets.size(); j++) {
+ gain = MIN(gain, gain_buckets[j]);
+ }
+
+ // Introduce latency by grabbing the AudioFrame stored previously,
+ // then overwrite it with current audioframe, then update circular
+ // buffer cursor.
+ float dst_buffer_left = sample_buffer_left[sample_cursor];
+ float dst_buffer_right = sample_buffer_right[sample_cursor];
+
+ sample_buffer_left[sample_cursor] = sample_left;
+ sample_buffer_right[sample_cursor] = sample_right;
+
+ sample_cursor = (sample_cursor + 1) % sample_buffer_left.size();
+
+ p_dst_frames[i].left = dst_buffer_left * gain;
+ p_dst_frames[i].right = dst_buffer_right * gain;
+ }
+}
+
+Ref<AudioEffectInstance> AudioEffectHardLimiter::instantiate() {
+ Ref<AudioEffectHardLimiterInstance> ins;
+ ins.instantiate();
+ ins->base = Ref<AudioEffectHardLimiter>(this);
+
+ float mix_rate = AudioServer::get_singleton()->get_mix_rate();
+
+ for (int i = 0; i < (int)Math::ceil(mix_rate * attack) + 1; i++) {
+ ins->sample_buffer_left.push_back(0.0f);
+ ins->sample_buffer_right.push_back(0.0f);
+ }
+
+ ins->gain_samples_to_store = (int)Math::ceil(mix_rate * (attack + sustain) + 1);
+ ins->gain_bucket_size = (int)(mix_rate * attack);
+
+ for (int i = 0; i < ins->gain_samples_to_store; i += ins->gain_bucket_size) {
+ ins->gain_buckets.push_back(1.0f);
+ }
+
+ return ins;
+}
+
+void AudioEffectHardLimiter::set_ceiling_db(float p_ceiling) {
+ ceiling = p_ceiling;
+}
+
+float AudioEffectHardLimiter::get_ceiling_db() const {
+ return ceiling;
+}
+
+float AudioEffectHardLimiter::get_pre_gain_db() const {
+ return pre_gain;
+}
+
+void AudioEffectHardLimiter::set_pre_gain_db(const float p_pre_gain) {
+ pre_gain = p_pre_gain;
+}
+
+float AudioEffectHardLimiter::get_release() const {
+ return release;
+}
+
+void AudioEffectHardLimiter::set_release(const float p_release) {
+ release = p_release;
+}
+
+void AudioEffectHardLimiter::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_ceiling_db", "ceiling"), &AudioEffectHardLimiter::set_ceiling_db);
+ ClassDB::bind_method(D_METHOD("get_ceiling_db"), &AudioEffectHardLimiter::get_ceiling_db);
+
+ ClassDB::bind_method(D_METHOD("set_pre_gain_db", "p_pre_gain"), &AudioEffectHardLimiter::set_pre_gain_db);
+ ClassDB::bind_method(D_METHOD("get_pre_gain_db"), &AudioEffectHardLimiter::get_pre_gain_db);
+
+ ClassDB::bind_method(D_METHOD("set_release", "p_release"), &AudioEffectHardLimiter::set_release);
+ ClassDB::bind_method(D_METHOD("get_release"), &AudioEffectHardLimiter::get_release);
+
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pre_gain_db", PROPERTY_HINT_RANGE, "-24,24,0.01,suffix:dB"), "set_pre_gain_db", "get_pre_gain_db");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ceiling_db", PROPERTY_HINT_RANGE, "-24,0.0,0.01,suffix:dB"), "set_ceiling_db", "get_ceiling_db");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "release", PROPERTY_HINT_RANGE, "0.01,3,0.01"), "set_release", "get_release");
+}
diff --git a/servers/audio/effects/audio_effect_hard_limiter.h b/servers/audio/effects/audio_effect_hard_limiter.h
new file mode 100644
index 0000000000..7e28480797
--- /dev/null
+++ b/servers/audio/effects/audio_effect_hard_limiter.h
@@ -0,0 +1,89 @@
+/**************************************************************************/
+/* audio_effect_hard_limiter.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef AUDIO_EFFECT_HARD_LIMITER_H
+#define AUDIO_EFFECT_HARD_LIMITER_H
+
+#include "servers/audio/audio_effect.h"
+
+class AudioEffectHardLimiter;
+
+class AudioEffectHardLimiterInstance : public AudioEffectInstance {
+ GDCLASS(AudioEffectHardLimiterInstance, AudioEffectInstance);
+ friend class AudioEffectHardLimiter;
+ Ref<AudioEffectHardLimiter> base;
+
+private:
+ int sample_cursor = 0;
+
+ float release_factor = 0;
+ float attack_factor = 0;
+ float gain = 1;
+ float gain_target = 1;
+
+ LocalVector<float> sample_buffer_left;
+ LocalVector<float> sample_buffer_right;
+
+ int gain_samples_to_store = 0;
+ int gain_bucket_cursor = 0;
+ int gain_bucket_size = 0;
+ LocalVector<float> gain_buckets;
+
+public:
+ virtual void process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) override;
+};
+
+class AudioEffectHardLimiter : public AudioEffect {
+ GDCLASS(AudioEffectHardLimiter, AudioEffect);
+
+ friend class AudioEffectHardLimiterInstance;
+ float pre_gain = 0.0f;
+ float ceiling = -0.3f;
+ float sustain = 0.02f;
+ float release = 0.1f;
+ const float attack = 0.002;
+
+protected:
+ static void _bind_methods();
+
+public:
+ void set_ceiling_db(float p_ceiling);
+ float get_ceiling_db() const;
+
+ void set_release(float p_release);
+ float get_release() const;
+
+ void set_pre_gain_db(float p_pre_gain);
+ float get_pre_gain_db() const;
+
+ Ref<AudioEffectInstance> instantiate() override;
+};
+
+#endif // AUDIO_EFFECT_HARD_LIMITER_H
diff --git a/servers/audio/effects/audio_effect_pitch_shift.cpp b/servers/audio/effects/audio_effect_pitch_shift.cpp
index ddb17e050a..beca503904 100644
--- a/servers/audio/effects/audio_effect_pitch_shift.cpp
+++ b/servers/audio/effects/audio_effect_pitch_shift.cpp
@@ -87,10 +87,8 @@ void SMBPitchShift::PitchShift(float pitchShift, long numSampsToProcess, long ff
double magn, phase, tmp, window, real, imag;
double freqPerBin, expct;
long i,k, qpd, index, inFifoLatency, stepSize, fftFrameSize2;
- unsigned long fftFrameBufferSize;
/* set up some handy variables */
- fftFrameBufferSize = (unsigned long)fftFrameSize*sizeof(float);
fftFrameSize2 = fftFrameSize/2;
stepSize = fftFrameSize/osamp;
freqPerBin = sampleRate/(double)fftFrameSize;
@@ -162,8 +160,8 @@ void SMBPitchShift::PitchShift(float pitchShift, long numSampsToProcess, long ff
/* ***************** PROCESSING ******************* */
/* this does the actual pitch shifting */
- memset(gSynMagn, 0, fftFrameBufferSize);
- memset(gSynFreq, 0, fftFrameBufferSize);
+ memset(gSynMagn, 0, fftFrameSize*sizeof(float));
+ memset(gSynFreq, 0, fftFrameSize*sizeof(float));
for (k = 0; k <= fftFrameSize2; k++) {
index = k*pitchShift;
if (index <= fftFrameSize2) {
@@ -216,7 +214,7 @@ void SMBPitchShift::PitchShift(float pitchShift, long numSampsToProcess, long ff
}
/* shift accumulator */
- memmove(gOutputAccum, gOutputAccum+stepSize, fftFrameBufferSize);
+ memmove(gOutputAccum, gOutputAccum+stepSize, fftFrameSize*sizeof(float));
/* move input FIFO */
for (k = 0; k < inFifoLatency; k++) { gInFIFO[k] = gInFIFO[k+stepSize];
@@ -358,12 +356,3 @@ void AudioEffectPitchShift::_bind_methods() {
BIND_ENUM_CONSTANT(FFT_SIZE_4096);
BIND_ENUM_CONSTANT(FFT_SIZE_MAX);
}
-
-AudioEffectPitchShift::AudioEffectPitchShift() {
- pitch_scale = 1.0;
- oversampling = 4;
- fft_size = FFT_SIZE_2048;
- wet = 0.0;
- dry = 0.0;
- filter = false;
-}
diff --git a/servers/audio/effects/audio_effect_pitch_shift.h b/servers/audio/effects/audio_effect_pitch_shift.h
index f372cc2124..949ce96057 100644
--- a/servers/audio/effects/audio_effect_pitch_shift.h
+++ b/servers/audio/effects/audio_effect_pitch_shift.h
@@ -38,34 +38,22 @@ class SMBPitchShift {
MAX_FRAME_LENGTH = 8192
};
- float gInFIFO[MAX_FRAME_LENGTH];
- float gOutFIFO[MAX_FRAME_LENGTH];
- float gFFTworksp[2 * MAX_FRAME_LENGTH];
- float gLastPhase[MAX_FRAME_LENGTH / 2 + 1];
- float gSumPhase[MAX_FRAME_LENGTH / 2 + 1];
- float gOutputAccum[2 * MAX_FRAME_LENGTH];
- float gAnaFreq[MAX_FRAME_LENGTH];
- float gAnaMagn[MAX_FRAME_LENGTH];
- float gSynFreq[MAX_FRAME_LENGTH];
- float gSynMagn[MAX_FRAME_LENGTH];
- long gRover;
+ float gInFIFO[MAX_FRAME_LENGTH] = {};
+ float gOutFIFO[MAX_FRAME_LENGTH] = {};
+ float gFFTworksp[2 * MAX_FRAME_LENGTH] = {};
+ float gLastPhase[MAX_FRAME_LENGTH / 2 + 1] = {};
+ float gSumPhase[MAX_FRAME_LENGTH / 2 + 1] = {};
+ float gOutputAccum[2 * MAX_FRAME_LENGTH] = {};
+ float gAnaFreq[MAX_FRAME_LENGTH] = {};
+ float gAnaMagn[MAX_FRAME_LENGTH] = {};
+ float gSynFreq[MAX_FRAME_LENGTH] = {};
+ float gSynMagn[MAX_FRAME_LENGTH] = {};
+ long gRover = 0;
void smbFft(float *fftBuffer, long fftFrameSize, long sign);
public:
void PitchShift(float pitchShift, long numSampsToProcess, long fftFrameSize, long osamp, float sampleRate, float *indata, float *outdata, int stride);
-
- SMBPitchShift() {
- gRover = 0;
- memset(gInFIFO, 0, MAX_FRAME_LENGTH * sizeof(float));
- memset(gOutFIFO, 0, MAX_FRAME_LENGTH * sizeof(float));
- memset(gFFTworksp, 0, 2 * MAX_FRAME_LENGTH * sizeof(float));
- memset(gLastPhase, 0, (MAX_FRAME_LENGTH / 2 + 1) * sizeof(float));
- memset(gSumPhase, 0, (MAX_FRAME_LENGTH / 2 + 1) * sizeof(float));
- memset(gOutputAccum, 0, 2 * MAX_FRAME_LENGTH * sizeof(float));
- memset(gAnaFreq, 0, MAX_FRAME_LENGTH * sizeof(float));
- memset(gAnaMagn, 0, MAX_FRAME_LENGTH * sizeof(float));
- }
};
class AudioEffectPitchShift;
@@ -75,7 +63,7 @@ class AudioEffectPitchShiftInstance : public AudioEffectInstance {
friend class AudioEffectPitchShift;
Ref<AudioEffectPitchShift> base;
- int fft_size;
+ int fft_size = 0;
SMBPitchShift shift_l;
SMBPitchShift shift_r;
@@ -98,12 +86,12 @@ public:
FFT_SIZE_MAX
};
- float pitch_scale;
- int oversampling;
- FFTSize fft_size;
- float wet;
- float dry;
- bool filter;
+ float pitch_scale = 1.0;
+ int oversampling = 4;
+ FFTSize fft_size = FFT_SIZE_2048;
+ float wet = 0.0;
+ float dry = 0.0;
+ bool filter = false;
protected:
static void _bind_methods();
@@ -119,8 +107,6 @@ public:
void set_fft_size(FFTSize);
FFTSize get_fft_size() const;
-
- AudioEffectPitchShift();
};
VARIANT_ENUM_CAST(AudioEffectPitchShift::FFTSize);
diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp
index 69a66a7d62..820e0bbeb6 100644
--- a/servers/audio_server.cpp
+++ b/servers/audio_server.cpp
@@ -1692,6 +1692,19 @@ void AudioServer::set_enable_tagging_used_audio_streams(bool p_enable) {
tag_used_audio_streams = p_enable;
}
+#ifdef TOOLS_ENABLED
+void AudioServer::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const {
+ const String pf = p_function;
+ if ((p_idx == 0 && pf == "get_bus_index") || (p_idx == 1 && pf == "set_bus_send")) {
+ for (const AudioServer::Bus *E : buses) {
+ r_options->push_back(String(E->name).quote());
+ }
+ }
+
+ Object::get_argument_options(p_function, p_idx, r_options);
+}
+#endif
+
void AudioServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_bus_count", "amount"), &AudioServer::set_bus_count);
ClassDB::bind_method(D_METHOD("get_bus_count"), &AudioServer::get_bus_count);
diff --git a/servers/audio_server.h b/servers/audio_server.h
index a7b764d1a5..7dd81beabe 100644
--- a/servers/audio_server.h
+++ b/servers/audio_server.h
@@ -436,6 +436,10 @@ public:
void set_enable_tagging_used_audio_streams(bool p_enable);
+#ifdef TOOLS_ENABLED
+ virtual void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const override;
+#endif
+
AudioServer();
virtual ~AudioServer();
};
diff --git a/servers/camera_server.h b/servers/camera_server.h
index 4e0b75fbf6..e9bcd771d2 100644
--- a/servers/camera_server.h
+++ b/servers/camera_server.h
@@ -71,7 +71,7 @@ protected:
static void _bind_methods();
- template <class T>
+ template <typename T>
static CameraServer *_create_builtin() {
return memnew(T);
}
@@ -79,7 +79,7 @@ protected:
public:
static CameraServer *get_singleton();
- template <class T>
+ template <typename T>
static void make_default() {
create_func = _create_builtin<T>;
}
diff --git a/servers/display/SCsub b/servers/display/SCsub
new file mode 100644
index 0000000000..86681f9c74
--- /dev/null
+++ b/servers/display/SCsub
@@ -0,0 +1,5 @@
+#!/usr/bin/env python
+
+Import("env")
+
+env.add_source_files(env.servers_sources, "*.cpp")
diff --git a/servers/display/native_menu.cpp b/servers/display/native_menu.cpp
new file mode 100644
index 0000000000..ca46560c7c
--- /dev/null
+++ b/servers/display/native_menu.cpp
@@ -0,0 +1,444 @@
+/**************************************************************************/
+/* native_menu.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#include "native_menu.h"
+
+#include "scene/resources/image_texture.h"
+
+NativeMenu *NativeMenu::singleton = nullptr;
+
+void NativeMenu::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("has_feature", "feature"), &NativeMenu::has_feature);
+
+ ClassDB::bind_method(D_METHOD("has_system_menu", "menu_id"), &NativeMenu::has_system_menu);
+ ClassDB::bind_method(D_METHOD("get_system_menu", "menu_id"), &NativeMenu::get_system_menu);
+ ClassDB::bind_method(D_METHOD("get_system_menu_name", "menu_id"), &NativeMenu::get_system_menu_name);
+
+ ClassDB::bind_method(D_METHOD("create_menu"), &NativeMenu::create_menu);
+ ClassDB::bind_method(D_METHOD("has_menu", "rid"), &NativeMenu::has_menu);
+ ClassDB::bind_method(D_METHOD("free_menu", "rid"), &NativeMenu::free_menu);
+
+ ClassDB::bind_method(D_METHOD("get_size", "rid"), &NativeMenu::get_size);
+ ClassDB::bind_method(D_METHOD("popup", "rid", "position"), &NativeMenu::popup);
+
+ ClassDB::bind_method(D_METHOD("set_interface_direction", "rid", "is_rtl"), &NativeMenu::set_interface_direction);
+ ClassDB::bind_method(D_METHOD("set_popup_open_callback", "rid", "callback"), &NativeMenu::set_popup_open_callback);
+ ClassDB::bind_method(D_METHOD("get_popup_open_callback", "rid"), &NativeMenu::get_popup_open_callback);
+ ClassDB::bind_method(D_METHOD("set_popup_close_callback", "rid", "callback"), &NativeMenu::set_popup_close_callback);
+ ClassDB::bind_method(D_METHOD("get_popup_close_callback", "rid"), &NativeMenu::get_popup_close_callback);
+ ClassDB::bind_method(D_METHOD("set_minimum_width", "rid", "width"), &NativeMenu::set_minimum_width);
+ ClassDB::bind_method(D_METHOD("get_minimum_width", "rid"), &NativeMenu::get_minimum_width);
+
+ ClassDB::bind_method(D_METHOD("add_submenu_item", "rid", "label", "submenu_rid", "tag", "index"), &NativeMenu::add_submenu_item, DEFVAL(Variant()), DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("add_item", "rid", "label", "callback", "key_callback", "tag", "accelerator", "index"), &NativeMenu::add_item, DEFVAL(Callable()), DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("add_check_item", "rid", "label", "callback", "key_callback", "tag", "accelerator", "index"), &NativeMenu::add_check_item, DEFVAL(Callable()), DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("add_icon_item", "rid", "icon", "label", "callback", "key_callback", "tag", "accelerator", "index"), &NativeMenu::add_icon_item, DEFVAL(Callable()), DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("add_icon_check_item", "rid", "icon", "label", "callback", "key_callback", "tag", "accelerator", "index"), &NativeMenu::add_icon_check_item, DEFVAL(Callable()), DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("add_radio_check_item", "rid", "label", "callback", "key_callback", "tag", "accelerator", "index"), &NativeMenu::add_radio_check_item, DEFVAL(Callable()), DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("add_icon_radio_check_item", "rid", "icon", "label", "callback", "key_callback", "tag", "accelerator", "index"), &NativeMenu::add_icon_radio_check_item, DEFVAL(Callable()), DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("add_multistate_item", "rid", "label", "max_states", "default_state", "callback", "key_callback", "tag", "accelerator", "index"), &NativeMenu::add_multistate_item, DEFVAL(Callable()), DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("add_separator", "rid", "index"), &NativeMenu::add_separator, DEFVAL(-1));
+
+ ClassDB::bind_method(D_METHOD("find_item_index_with_text", "rid", "text"), &NativeMenu::find_item_index_with_text);
+ ClassDB::bind_method(D_METHOD("find_item_index_with_tag", "rid", "tag"), &NativeMenu::find_item_index_with_tag);
+ ClassDB::bind_method(D_METHOD("find_item_index_with_submenu", "rid", "submenu_rid"), &NativeMenu::find_item_index_with_submenu);
+
+ ClassDB::bind_method(D_METHOD("is_item_checked", "rid", "idx"), &NativeMenu::is_item_checked);
+ ClassDB::bind_method(D_METHOD("is_item_checkable", "rid", "idx"), &NativeMenu::is_item_checkable);
+ ClassDB::bind_method(D_METHOD("is_item_radio_checkable", "rid", "idx"), &NativeMenu::is_item_radio_checkable);
+ ClassDB::bind_method(D_METHOD("get_item_callback", "rid", "idx"), &NativeMenu::get_item_callback);
+ ClassDB::bind_method(D_METHOD("get_item_key_callback", "rid", "idx"), &NativeMenu::get_item_key_callback);
+ ClassDB::bind_method(D_METHOD("get_item_tag", "rid", "idx"), &NativeMenu::get_item_tag);
+ ClassDB::bind_method(D_METHOD("get_item_text", "rid", "idx"), &NativeMenu::get_item_text);
+ ClassDB::bind_method(D_METHOD("get_item_submenu", "rid", "idx"), &NativeMenu::get_item_submenu);
+ ClassDB::bind_method(D_METHOD("get_item_accelerator", "rid", "idx"), &NativeMenu::get_item_accelerator);
+ ClassDB::bind_method(D_METHOD("is_item_disabled", "rid", "idx"), &NativeMenu::is_item_disabled);
+ ClassDB::bind_method(D_METHOD("is_item_hidden", "rid", "idx"), &NativeMenu::is_item_hidden);
+ ClassDB::bind_method(D_METHOD("get_item_tooltip", "rid", "idx"), &NativeMenu::get_item_tooltip);
+ ClassDB::bind_method(D_METHOD("get_item_state", "rid", "idx"), &NativeMenu::get_item_state);
+ ClassDB::bind_method(D_METHOD("get_item_max_states", "rid", "idx"), &NativeMenu::get_item_max_states);
+ ClassDB::bind_method(D_METHOD("get_item_icon", "rid", "idx"), &NativeMenu::get_item_icon);
+ ClassDB::bind_method(D_METHOD("get_item_indentation_level", "rid", "idx"), &NativeMenu::get_item_indentation_level);
+
+ ClassDB::bind_method(D_METHOD("set_item_checked", "rid", "idx", "checked"), &NativeMenu::set_item_checked);
+ ClassDB::bind_method(D_METHOD("set_item_checkable", "rid", "idx", "checkable"), &NativeMenu::set_item_checkable);
+ ClassDB::bind_method(D_METHOD("set_item_radio_checkable", "rid", "idx", "checkable"), &NativeMenu::set_item_radio_checkable);
+ ClassDB::bind_method(D_METHOD("set_item_callback", "rid", "idx", "callback"), &NativeMenu::set_item_callback);
+ ClassDB::bind_method(D_METHOD("set_item_hover_callbacks", "rid", "idx", "callback"), &NativeMenu::set_item_hover_callbacks);
+ ClassDB::bind_method(D_METHOD("set_item_key_callback", "rid", "idx", "key_callback"), &NativeMenu::set_item_key_callback);
+ ClassDB::bind_method(D_METHOD("set_item_tag", "rid", "idx", "tag"), &NativeMenu::set_item_tag);
+ ClassDB::bind_method(D_METHOD("set_item_text", "rid", "idx", "text"), &NativeMenu::set_item_text);
+ ClassDB::bind_method(D_METHOD("set_item_submenu", "rid", "idx", "submenu_rid"), &NativeMenu::set_item_submenu);
+ ClassDB::bind_method(D_METHOD("set_item_accelerator", "rid", "idx", "keycode"), &NativeMenu::set_item_accelerator);
+ ClassDB::bind_method(D_METHOD("set_item_disabled", "rid", "idx", "disabled"), &NativeMenu::set_item_disabled);
+ ClassDB::bind_method(D_METHOD("set_item_hidden", "rid", "idx", "hidden"), &NativeMenu::set_item_hidden);
+ ClassDB::bind_method(D_METHOD("set_item_tooltip", "rid", "idx", "tooltip"), &NativeMenu::set_item_tooltip);
+ ClassDB::bind_method(D_METHOD("set_item_state", "rid", "idx", "state"), &NativeMenu::set_item_state);
+ ClassDB::bind_method(D_METHOD("set_item_max_states", "rid", "idx", "max_states"), &NativeMenu::set_item_max_states);
+ ClassDB::bind_method(D_METHOD("set_item_icon", "rid", "idx", "icon"), &NativeMenu::set_item_icon);
+ ClassDB::bind_method(D_METHOD("set_item_indentation_level", "rid", "idx", "level"), &NativeMenu::set_item_indentation_level);
+
+ ClassDB::bind_method(D_METHOD("get_item_count", "rid"), &NativeMenu::get_item_count);
+ ClassDB::bind_method(D_METHOD("is_system_menu", "rid"), &NativeMenu::is_system_menu);
+
+ ClassDB::bind_method(D_METHOD("remove_item", "rid", "idx"), &NativeMenu::remove_item);
+ ClassDB::bind_method(D_METHOD("clear", "rid"), &NativeMenu::clear);
+
+ BIND_ENUM_CONSTANT(FEATURE_GLOBAL_MENU);
+ BIND_ENUM_CONSTANT(FEATURE_POPUP_MENU);
+ BIND_ENUM_CONSTANT(FEATURE_OPEN_CLOSE_CALLBACK);
+ BIND_ENUM_CONSTANT(FEATURE_HOVER_CALLBACK);
+ BIND_ENUM_CONSTANT(FEATURE_KEY_CALLBACK);
+
+ BIND_ENUM_CONSTANT(INVALID_MENU_ID);
+ BIND_ENUM_CONSTANT(MAIN_MENU_ID);
+ BIND_ENUM_CONSTANT(APPLICATION_MENU_ID);
+ BIND_ENUM_CONSTANT(WINDOW_MENU_ID);
+ BIND_ENUM_CONSTANT(HELP_MENU_ID);
+ BIND_ENUM_CONSTANT(DOCK_MENU_ID);
+}
+
+bool NativeMenu::has_feature(Feature p_feature) const {
+ return false;
+}
+
+bool NativeMenu::has_system_menu(SystemMenus p_menu_id) const {
+ return false;
+}
+
+RID NativeMenu::get_system_menu(SystemMenus p_menu_id) const {
+ WARN_PRINT("Global menus are not supported on this platform.");
+ return RID();
+}
+
+String NativeMenu::get_system_menu_name(SystemMenus p_menu_id) const {
+ switch (p_menu_id) {
+ case MAIN_MENU_ID:
+ return "Main menu";
+ case APPLICATION_MENU_ID:
+ return "Application menu";
+ case WINDOW_MENU_ID:
+ return "Window menu";
+ case HELP_MENU_ID:
+ return "Help menu";
+ case DOCK_MENU_ID:
+ return "Dock menu";
+ default:
+ return "Invalid";
+ }
+}
+
+RID NativeMenu::create_menu() {
+ WARN_PRINT("Global menus are not supported on this platform.");
+ return RID();
+}
+
+bool NativeMenu::has_menu(const RID &p_rid) const {
+ WARN_PRINT("Global menus are not supported on this platform.");
+ return false;
+}
+
+void NativeMenu::free_menu(const RID &p_rid) {
+ WARN_PRINT("Global menus are not supported on this platform.");
+}
+
+Size2 NativeMenu::get_size(const RID &p_rid) const {
+ WARN_PRINT("Global menus are not supported on this platform.");
+ return Size2();
+}
+
+void NativeMenu::popup(const RID &p_rid, const Vector2i &p_position) {
+ WARN_PRINT("Global menus are not supported on this platform.");
+}
+
+void NativeMenu::set_interface_direction(const RID &p_rid, bool p_is_rtl) {
+ WARN_PRINT("Global menus are not supported on this platform.");
+}
+
+void NativeMenu::set_popup_open_callback(const RID &p_rid, const Callable &p_callback) {
+ WARN_PRINT("Global menus are not supported on this platform.");
+}
+
+Callable NativeMenu::get_popup_open_callback(const RID &p_rid) const {
+ WARN_PRINT("Global menus are not supported on this platform.");
+ return Callable();
+}
+
+void NativeMenu::set_popup_close_callback(const RID &p_rid, const Callable &p_callback) {
+ WARN_PRINT("Global menus are not supported on this platform.");
+}
+
+Callable NativeMenu::get_popup_close_callback(const RID &p_rid) const {
+ WARN_PRINT("Global menus are not supported on this platform.");
+ return Callable();
+}
+
+void NativeMenu::set_minimum_width(const RID &p_rid, float p_width) {
+ WARN_PRINT("Global menus are not supported on this platform.");
+}
+
+float NativeMenu::get_minimum_width(const RID &p_rid) const {
+ WARN_PRINT("Global menus are not supported on this platform.");
+ return 0.f;
+}
+
+int NativeMenu::add_submenu_item(const RID &p_rid, const String &p_label, const RID &p_submenu_rid, const Variant &p_tag, int p_index) {
+ WARN_PRINT("Global menus are not supported on this platform.");
+ return -1;
+}
+
+int NativeMenu::add_item(const RID &p_rid, const String &p_label, const Callable &p_callback, const Callable &p_key_callback, const Variant &p_tag, Key p_accel, int p_index) {
+ WARN_PRINT("Global menus are not supported on this platform.");
+ return -1;
+}
+
+int NativeMenu::add_check_item(const RID &p_rid, const String &p_label, const Callable &p_callback, const Callable &p_key_callback, const Variant &p_tag, Key p_accel, int p_index) {
+ WARN_PRINT("Global menus are not supported on this platform.");
+ return -1;
+}
+
+int NativeMenu::add_icon_item(const RID &p_rid, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Callable &p_key_callback, const Variant &p_tag, Key p_accel, int p_index) {
+ WARN_PRINT("Global menus are not supported on this platform.");
+ return -1;
+}
+
+int NativeMenu::add_icon_check_item(const RID &p_rid, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Callable &p_key_callback, const Variant &p_tag, Key p_accel, int p_index) {
+ WARN_PRINT("Global menus are not supported on this platform.");
+ return -1;
+}
+
+int NativeMenu::add_radio_check_item(const RID &p_rid, const String &p_label, const Callable &p_callback, const Callable &p_key_callback, const Variant &p_tag, Key p_accel, int p_index) {
+ WARN_PRINT("Global menus are not supported on this platform.");
+ return -1;
+}
+
+int NativeMenu::add_icon_radio_check_item(const RID &p_rid, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Callable &p_key_callback, const Variant &p_tag, Key p_accel, int p_index) {
+ WARN_PRINT("Global menus are not supported on this platform.");
+ return -1;
+}
+
+int NativeMenu::add_multistate_item(const RID &p_rid, const String &p_label, int p_max_states, int p_default_state, const Callable &p_callback, const Callable &p_key_callback, const Variant &p_tag, Key p_accel, int p_index) {
+ WARN_PRINT("Global menus are not supported on this platform.");
+ return -1;
+}
+
+int NativeMenu::add_separator(const RID &p_rid, int p_index) {
+ WARN_PRINT("Global menus are not supported on this platform.");
+ return -1;
+}
+
+int NativeMenu::find_item_index_with_text(const RID &p_rid, const String &p_text) const {
+ WARN_PRINT("Global menus are not supported on this platform.");
+ return -1;
+}
+
+int NativeMenu::find_item_index_with_tag(const RID &p_rid, const Variant &p_tag) const {
+ WARN_PRINT("Global menus are not supported on this platform.");
+ return -1;
+}
+
+int NativeMenu::find_item_index_with_submenu(const RID &p_rid, const RID &p_submenu_rid) const {
+ if (!has_menu(p_rid) || !has_menu(p_submenu_rid)) {
+ return -1;
+ }
+ int count = get_item_count(p_rid);
+ for (int i = 0; i < count; i++) {
+ if (p_submenu_rid == get_item_submenu(p_rid, i)) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+bool NativeMenu::is_item_checked(const RID &p_rid, int p_idx) const {
+ WARN_PRINT("Global menus are not supported on this platform.");
+ return false;
+}
+
+bool NativeMenu::is_item_checkable(const RID &p_rid, int p_idx) const {
+ WARN_PRINT("Global menus are not supported on this platform.");
+ return false;
+}
+
+bool NativeMenu::is_item_radio_checkable(const RID &p_rid, int p_idx) const {
+ WARN_PRINT("Global menus are not supported on this platform.");
+ return false;
+}
+
+Callable NativeMenu::get_item_callback(const RID &p_rid, int p_idx) const {
+ WARN_PRINT("Global menus are not supported on this platform.");
+ return Callable();
+}
+
+Callable NativeMenu::get_item_key_callback(const RID &p_rid, int p_idx) const {
+ WARN_PRINT("Global menus are not supported on this platform.");
+ return Callable();
+}
+
+Variant NativeMenu::get_item_tag(const RID &p_rid, int p_idx) const {
+ WARN_PRINT("Global menus are not supported on this platform.");
+ return Variant();
+}
+
+String NativeMenu::get_item_text(const RID &p_rid, int p_idx) const {
+ WARN_PRINT("Global menus are not supported on this platform.");
+ return String();
+}
+
+RID NativeMenu::get_item_submenu(const RID &p_rid, int p_idx) const {
+ WARN_PRINT("Global menus are not supported on this platform.");
+ return RID();
+}
+
+Key NativeMenu::get_item_accelerator(const RID &p_rid, int p_idx) const {
+ WARN_PRINT("Global menus are not supported on this platform.");
+ return Key::NONE;
+}
+
+bool NativeMenu::is_item_disabled(const RID &p_rid, int p_idx) const {
+ WARN_PRINT("Global menus are not supported on this platform.");
+ return false;
+}
+
+bool NativeMenu::is_item_hidden(const RID &p_rid, int p_idx) const {
+ WARN_PRINT("Global menus are not supported on this platform.");
+ return false;
+}
+
+String NativeMenu::get_item_tooltip(const RID &p_rid, int p_idx) const {
+ WARN_PRINT("Global menus are not supported on this platform.");
+ return String();
+}
+
+int NativeMenu::get_item_state(const RID &p_rid, int p_idx) const {
+ WARN_PRINT("Global menus are not supported on this platform.");
+ return -1;
+}
+
+int NativeMenu::get_item_max_states(const RID &p_rid, int p_idx) const {
+ WARN_PRINT("Global menus are not supported on this platform.");
+ return -1;
+}
+
+Ref<Texture2D> NativeMenu::get_item_icon(const RID &p_rid, int p_idx) const {
+ WARN_PRINT("Global menus are not supported on this platform.");
+ return Ref<Texture2D>();
+}
+
+int NativeMenu::get_item_indentation_level(const RID &p_rid, int p_idx) const {
+ WARN_PRINT("Global menus are not supported on this platform.");
+ return 0;
+}
+
+void NativeMenu::set_item_checked(const RID &p_rid, int p_idx, bool p_checked) {
+ WARN_PRINT("Global menus are not supported on this platform.");
+}
+
+void NativeMenu::set_item_checkable(const RID &p_rid, int p_idx, bool p_checkable) {
+ WARN_PRINT("Global menus are not supported on this platform.");
+}
+
+void NativeMenu::set_item_radio_checkable(const RID &p_rid, int p_idx, bool p_checkable) {
+ WARN_PRINT("Global menus are not supported on this platform.");
+}
+
+void NativeMenu::set_item_callback(const RID &p_rid, int p_idx, const Callable &p_callback) {
+ WARN_PRINT("Global menus are not supported on this platform.");
+}
+
+void NativeMenu::set_item_key_callback(const RID &p_rid, int p_idx, const Callable &p_key_callback) {
+ WARN_PRINT("Global menus are not supported on this platform.");
+}
+
+void NativeMenu::set_item_hover_callbacks(const RID &p_rid, int p_idx, const Callable &p_callback) {
+ WARN_PRINT("Global menus are not supported on this platform.");
+}
+
+void NativeMenu::set_item_tag(const RID &p_rid, int p_idx, const Variant &p_tag) {
+ WARN_PRINT("Global menus are not supported on this platform.");
+}
+
+void NativeMenu::set_item_text(const RID &p_rid, int p_idx, const String &p_text) {
+ WARN_PRINT("Global menus are not supported on this platform.");
+}
+
+void NativeMenu::set_item_submenu(const RID &p_rid, int p_idx, const RID &p_submenu_rid) {
+ WARN_PRINT("Global menus are not supported on this platform.");
+}
+
+void NativeMenu::set_item_accelerator(const RID &p_rid, int p_idx, Key p_keycode) {
+ WARN_PRINT("Global menus are not supported on this platform.");
+}
+
+void NativeMenu::set_item_disabled(const RID &p_rid, int p_idx, bool p_disabled) {
+ WARN_PRINT("Global menus are not supported on this platform.");
+}
+
+void NativeMenu::set_item_hidden(const RID &p_rid, int p_idx, bool p_hidden) {
+ WARN_PRINT("Global menus are not supported on this platform.");
+}
+
+void NativeMenu::set_item_tooltip(const RID &p_rid, int p_idx, const String &p_tooltip) {
+ WARN_PRINT("Global menus are not supported on this platform.");
+}
+
+void NativeMenu::set_item_state(const RID &p_rid, int p_idx, int p_state) {
+ WARN_PRINT("Global menus are not supported on this platform.");
+}
+
+void NativeMenu::set_item_max_states(const RID &p_rid, int p_idx, int p_max_states) {
+ WARN_PRINT("Global menus are not supported on this platform.");
+}
+
+void NativeMenu::set_item_icon(const RID &p_rid, int p_idx, const Ref<Texture2D> &p_icon) {
+ WARN_PRINT("Global menus are not supported on this platform.");
+}
+
+void NativeMenu::set_item_indentation_level(const RID &p_rid, int p_idx, int p_level) {
+ WARN_PRINT("Global menus are not supported on this platform.");
+}
+
+int NativeMenu::get_item_count(const RID &p_rid) const {
+ WARN_PRINT("Global menus are not supported on this platform.");
+ return 0;
+}
+
+bool NativeMenu::is_system_menu(const RID &p_rid) const {
+ WARN_PRINT("Global menus are not supported on this platform.");
+ return false;
+}
+
+void NativeMenu::remove_item(const RID &p_rid, int p_idx) {
+ WARN_PRINT("Global menus are not supported on this platform.");
+}
+
+void NativeMenu::clear(const RID &p_rid) {
+ WARN_PRINT("Global menus are not supported on this platform.");
+}
diff --git a/servers/display/native_menu.h b/servers/display/native_menu.h
new file mode 100644
index 0000000000..2bc061a216
--- /dev/null
+++ b/servers/display/native_menu.h
@@ -0,0 +1,160 @@
+/**************************************************************************/
+/* native_menu.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef NATIVE_MENU_H
+#define NATIVE_MENU_H
+
+#include "core/input/input.h"
+#include "core/io/resource.h"
+#include "core/os/os.h"
+#include "core/variant/callable.h"
+
+class Texture2D;
+
+class NativeMenu : public Object {
+ GDCLASS(NativeMenu, Object)
+
+ static NativeMenu *singleton;
+
+protected:
+ static void _bind_methods();
+
+public:
+ _FORCE_INLINE_ static NativeMenu *get_singleton() {
+ return singleton;
+ }
+
+ enum Feature {
+ FEATURE_GLOBAL_MENU,
+ FEATURE_POPUP_MENU,
+ FEATURE_OPEN_CLOSE_CALLBACK,
+ FEATURE_HOVER_CALLBACK,
+ FEATURE_KEY_CALLBACK,
+ };
+
+ enum SystemMenus {
+ INVALID_MENU_ID,
+ MAIN_MENU_ID,
+ APPLICATION_MENU_ID,
+ WINDOW_MENU_ID,
+ HELP_MENU_ID,
+ DOCK_MENU_ID,
+ };
+
+ virtual bool has_feature(Feature p_feature) const;
+
+ virtual bool has_system_menu(SystemMenus p_menu_id) const;
+ virtual RID get_system_menu(SystemMenus p_menu_id) const;
+ virtual String get_system_menu_name(SystemMenus p_menu_id) const;
+
+ virtual RID create_menu();
+ virtual bool has_menu(const RID &p_rid) const;
+ virtual void free_menu(const RID &p_rid);
+
+ virtual Size2 get_size(const RID &p_rid) const;
+ virtual void popup(const RID &p_rid, const Vector2i &p_position);
+
+ virtual void set_interface_direction(const RID &p_rid, bool p_is_rtl);
+
+ virtual void set_popup_open_callback(const RID &p_rid, const Callable &p_callback);
+ virtual Callable get_popup_open_callback(const RID &p_rid) const;
+ virtual void set_popup_close_callback(const RID &p_rid, const Callable &p_callback);
+ virtual Callable get_popup_close_callback(const RID &p_rid) const;
+ virtual void set_minimum_width(const RID &p_rid, float p_width);
+ virtual float get_minimum_width(const RID &p_rid) const;
+
+ virtual int add_submenu_item(const RID &p_rid, const String &p_label, const RID &p_submenu_rid, const Variant &p_tag = Variant(), int p_index = -1);
+ virtual int add_item(const RID &p_rid, const String &p_label, const Callable &p_callback = Callable(), const Callable &p_key_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1);
+ virtual int add_check_item(const RID &p_rid, const String &p_label, const Callable &p_callback = Callable(), const Callable &p_key_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1);
+ virtual int add_icon_item(const RID &p_rid, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback = Callable(), const Callable &p_key_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1);
+ virtual int add_icon_check_item(const RID &p_rid, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback = Callable(), const Callable &p_key_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1);
+ virtual int add_radio_check_item(const RID &p_rid, const String &p_label, const Callable &p_callback = Callable(), const Callable &p_key_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1);
+ virtual int add_icon_radio_check_item(const RID &p_rid, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback = Callable(), const Callable &p_key_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1);
+ virtual int add_multistate_item(const RID &p_rid, const String &p_label, int p_max_states, int p_default_state, const Callable &p_callback = Callable(), const Callable &p_key_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1);
+ virtual int add_separator(const RID &p_rid, int p_index = -1);
+
+ virtual int find_item_index_with_text(const RID &p_rid, const String &p_text) const;
+ virtual int find_item_index_with_tag(const RID &p_rid, const Variant &p_tag) const;
+ virtual int find_item_index_with_submenu(const RID &p_rid, const RID &p_submenu_rid) const;
+
+ virtual bool is_item_checked(const RID &p_rid, int p_idx) const;
+ virtual bool is_item_checkable(const RID &p_rid, int p_idx) const;
+ virtual bool is_item_radio_checkable(const RID &p_rid, int p_idx) const;
+ virtual Callable get_item_callback(const RID &p_rid, int p_idx) const;
+ virtual Callable get_item_key_callback(const RID &p_rid, int p_idx) const;
+ virtual Variant get_item_tag(const RID &p_rid, int p_idx) const;
+ virtual String get_item_text(const RID &p_rid, int p_idx) const;
+ virtual RID get_item_submenu(const RID &p_rid, int p_idx) const;
+ virtual Key get_item_accelerator(const RID &p_rid, int p_idx) const;
+ virtual bool is_item_disabled(const RID &p_rid, int p_idx) const;
+ virtual bool is_item_hidden(const RID &p_rid, int p_idx) const;
+ virtual String get_item_tooltip(const RID &p_rid, int p_idx) const;
+ virtual int get_item_state(const RID &p_rid, int p_idx) const;
+ virtual int get_item_max_states(const RID &p_rid, int p_idx) const;
+ virtual Ref<Texture2D> get_item_icon(const RID &p_rid, int p_idx) const;
+ virtual int get_item_indentation_level(const RID &p_rid, int p_idx) const;
+
+ virtual void set_item_checked(const RID &p_rid, int p_idx, bool p_checked);
+ virtual void set_item_checkable(const RID &p_rid, int p_idx, bool p_checkable);
+ virtual void set_item_radio_checkable(const RID &p_rid, int p_idx, bool p_checkable);
+ virtual void set_item_callback(const RID &p_rid, int p_idx, const Callable &p_callback);
+ virtual void set_item_key_callback(const RID &p_rid, int p_idx, const Callable &p_key_callback);
+ virtual void set_item_hover_callbacks(const RID &p_rid, int p_idx, const Callable &p_callback);
+ virtual void set_item_tag(const RID &p_rid, int p_idx, const Variant &p_tag);
+ virtual void set_item_text(const RID &p_rid, int p_idx, const String &p_text);
+ virtual void set_item_submenu(const RID &p_rid, int p_idx, const RID &p_submenu_rid);
+ virtual void set_item_accelerator(const RID &p_rid, int p_idx, Key p_keycode);
+ virtual void set_item_disabled(const RID &p_rid, int p_idx, bool p_disabled);
+ virtual void set_item_hidden(const RID &p_rid, int p_idx, bool p_hidden);
+ virtual void set_item_tooltip(const RID &p_rid, int p_idx, const String &p_tooltip);
+ virtual void set_item_state(const RID &p_rid, int p_idx, int p_state);
+ virtual void set_item_max_states(const RID &p_rid, int p_idx, int p_max_states);
+ virtual void set_item_icon(const RID &p_rid, int p_idx, const Ref<Texture2D> &p_icon);
+ virtual void set_item_indentation_level(const RID &p_rid, int p_idx, int p_level);
+
+ virtual int get_item_count(const RID &p_rid) const;
+ virtual bool is_system_menu(const RID &p_rid) const;
+
+ virtual void remove_item(const RID &p_rid, int p_idx);
+ virtual void clear(const RID &p_rid);
+
+ NativeMenu() {
+ singleton = this;
+ }
+
+ ~NativeMenu() {
+ singleton = nullptr;
+ }
+};
+
+VARIANT_ENUM_CAST(NativeMenu::Feature);
+VARIANT_ENUM_CAST(NativeMenu::SystemMenus);
+
+#endif // NATIVE_MENU_H
diff --git a/servers/display_server.cpp b/servers/display_server.cpp
index 6631d44f63..9ceb6909fe 100644
--- a/servers/display_server.cpp
+++ b/servers/display_server.cpp
@@ -31,6 +31,7 @@
#include "display_server.h"
#include "core/input/input.h"
+#include "scene/resources/atlas_texture.h"
#include "scene/resources/texture.h"
#include "servers/display_server_headless.h"
@@ -51,231 +52,352 @@ void DisplayServer::help_set_search_callbacks(const Callable &p_search_callback,
WARN_PRINT("Native help is not supported by this display server.");
}
+#ifndef DISABLE_DEPRECATED
+
+RID DisplayServer::_get_rid_from_name(NativeMenu *p_nmenu, const String &p_menu_root) const {
+ if (p_menu_root == "_main") {
+ return p_nmenu->get_system_menu(NativeMenu::MAIN_MENU_ID);
+ } else if (p_menu_root == "_apple") {
+ return p_nmenu->get_system_menu(NativeMenu::APPLICATION_MENU_ID);
+ } else if (p_menu_root == "_dock") {
+ return p_nmenu->get_system_menu(NativeMenu::DOCK_MENU_ID);
+ } else if (p_menu_root == "_help") {
+ return p_nmenu->get_system_menu(NativeMenu::HELP_MENU_ID);
+ } else if (p_menu_root == "_window") {
+ return p_nmenu->get_system_menu(NativeMenu::WINDOW_MENU_ID);
+ } else if (menu_names.has(p_menu_root)) {
+ return menu_names[p_menu_root];
+ }
+
+ RID rid = p_nmenu->create_menu();
+ menu_names[p_menu_root] = rid;
+ return rid;
+}
+
int DisplayServer::global_menu_add_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Callable &p_key_callback, const Variant &p_tag, Key p_accel, int p_index) {
- WARN_PRINT("Global menus not supported by this display server.");
- return -1;
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL_V(nmenu, -1);
+ return nmenu->add_item(_get_rid_from_name(nmenu, p_menu_root), p_label, p_callback, p_key_callback, p_tag, p_accel, p_index);
}
int DisplayServer::global_menu_add_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Callable &p_key_callback, const Variant &p_tag, Key p_accel, int p_index) {
- WARN_PRINT("Global menus not supported by this display server.");
- return -1;
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL_V(nmenu, -1);
+ return nmenu->add_check_item(_get_rid_from_name(nmenu, p_menu_root), p_label, p_callback, p_key_callback, p_tag, p_accel, p_index);
}
int DisplayServer::global_menu_add_icon_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Callable &p_key_callback, const Variant &p_tag, Key p_accel, int p_index) {
- WARN_PRINT("Global menus not supported by this display server.");
- return -1;
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL_V(nmenu, -1);
+ return nmenu->add_icon_item(_get_rid_from_name(nmenu, p_menu_root), p_icon, p_label, p_callback, p_key_callback, p_tag, p_accel, p_index);
}
int DisplayServer::global_menu_add_icon_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Callable &p_key_callback, const Variant &p_tag, Key p_accel, int p_index) {
- WARN_PRINT("Global menus not supported by this display server.");
- return -1;
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL_V(nmenu, -1);
+ return nmenu->add_icon_check_item(_get_rid_from_name(nmenu, p_menu_root), p_icon, p_label, p_callback, p_key_callback, p_tag, p_accel, p_index);
}
int DisplayServer::global_menu_add_radio_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Callable &p_key_callback, const Variant &p_tag, Key p_accel, int p_index) {
- WARN_PRINT("Global menus not supported by this display server.");
- return -1;
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL_V(nmenu, -1);
+ return nmenu->add_radio_check_item(_get_rid_from_name(nmenu, p_menu_root), p_label, p_callback, p_key_callback, p_tag, p_accel, p_index);
}
int DisplayServer::global_menu_add_icon_radio_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Callable &p_key_callback, const Variant &p_tag, Key p_accel, int p_index) {
- WARN_PRINT("Global menus not supported by this display server.");
- return -1;
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL_V(nmenu, -1);
+ return nmenu->add_icon_radio_check_item(_get_rid_from_name(nmenu, p_menu_root), p_icon, p_label, p_callback, p_key_callback, p_tag, p_accel, p_index);
}
int DisplayServer::global_menu_add_multistate_item(const String &p_menu_root, const String &p_label, int p_max_states, int p_default_state, const Callable &p_callback, const Callable &p_key_callback, const Variant &p_tag, Key p_accel, int p_index) {
- WARN_PRINT("Global menus not supported by this display server.");
- return -1;
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL_V(nmenu, -1);
+ return nmenu->add_multistate_item(_get_rid_from_name(nmenu, p_menu_root), p_label, p_max_states, p_default_state, p_callback, p_key_callback, p_tag, p_accel, p_index);
}
-void DisplayServer::global_menu_set_popup_callbacks(const String &p_menu_root, const Callable &p_open_callbacs, const Callable &p_close_callback) {
- WARN_PRINT("Global menus not supported by this display server.");
+void DisplayServer::global_menu_set_popup_callbacks(const String &p_menu_root, const Callable &p_open_callback, const Callable &p_close_callback) {
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL(nmenu);
+ nmenu->set_popup_open_callback(_get_rid_from_name(nmenu, p_menu_root), p_open_callback);
+ nmenu->set_popup_open_callback(_get_rid_from_name(nmenu, p_menu_root), p_close_callback);
}
int DisplayServer::global_menu_add_submenu_item(const String &p_menu_root, const String &p_label, const String &p_submenu, int p_index) {
- WARN_PRINT("Global menus not supported by this display server.");
- return -1;
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL_V(nmenu, -1);
+ return nmenu->add_submenu_item(_get_rid_from_name(nmenu, p_menu_root), p_label, _get_rid_from_name(nmenu, p_submenu), Variant(), p_index);
}
int DisplayServer::global_menu_add_separator(const String &p_menu_root, int p_index) {
- WARN_PRINT("Global menus not supported by this display server.");
- return -1;
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL_V(nmenu, -1);
+ return nmenu->add_separator(_get_rid_from_name(nmenu, p_menu_root), p_index);
}
int DisplayServer::global_menu_get_item_index_from_text(const String &p_menu_root, const String &p_text) const {
- WARN_PRINT("Global menus not supported by this display server.");
- return -1;
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL_V(nmenu, -1);
+ return nmenu->find_item_index_with_text(_get_rid_from_name(nmenu, p_menu_root), p_text);
}
int DisplayServer::global_menu_get_item_index_from_tag(const String &p_menu_root, const Variant &p_tag) const {
- WARN_PRINT("Global menus not supported by this display server.");
- return -1;
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL_V(nmenu, -1);
+ return nmenu->find_item_index_with_tag(_get_rid_from_name(nmenu, p_menu_root), p_tag);
}
void DisplayServer::global_menu_set_item_callback(const String &p_menu_root, int p_idx, const Callable &p_callback) {
- WARN_PRINT("Global menus not supported by this display server.");
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL(nmenu);
+ nmenu->set_item_callback(_get_rid_from_name(nmenu, p_menu_root), p_idx, p_callback);
}
void DisplayServer::global_menu_set_item_hover_callbacks(const String &p_menu_root, int p_idx, const Callable &p_callback) {
- WARN_PRINT("Global menus not supported by this display server.");
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL(nmenu);
+ nmenu->set_item_hover_callbacks(_get_rid_from_name(nmenu, p_menu_root), p_idx, p_callback);
}
void DisplayServer::global_menu_set_item_key_callback(const String &p_menu_root, int p_idx, const Callable &p_key_callback) {
- WARN_PRINT("Global menus not supported by this display server.");
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL(nmenu);
+ nmenu->set_item_key_callback(_get_rid_from_name(nmenu, p_menu_root), p_idx, p_key_callback);
}
bool DisplayServer::global_menu_is_item_checked(const String &p_menu_root, int p_idx) const {
- WARN_PRINT("Global menus not supported by this display server.");
- return false;
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL_V(nmenu, false);
+ return nmenu->is_item_checked(_get_rid_from_name(nmenu, p_menu_root), p_idx);
}
bool DisplayServer::global_menu_is_item_checkable(const String &p_menu_root, int p_idx) const {
- WARN_PRINT("Global menus not supported by this display server.");
- return false;
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL_V(nmenu, false);
+ return nmenu->is_item_checkable(_get_rid_from_name(nmenu, p_menu_root), p_idx);
}
bool DisplayServer::global_menu_is_item_radio_checkable(const String &p_menu_root, int p_idx) const {
- WARN_PRINT("Global menus not supported by this display server.");
- return false;
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL_V(nmenu, false);
+ return nmenu->is_item_radio_checkable(_get_rid_from_name(nmenu, p_menu_root), p_idx);
}
Callable DisplayServer::global_menu_get_item_callback(const String &p_menu_root, int p_idx) const {
- WARN_PRINT("Global menus not supported by this display server.");
- return Callable();
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL_V(nmenu, Callable());
+ return nmenu->get_item_callback(_get_rid_from_name(nmenu, p_menu_root), p_idx);
}
Callable DisplayServer::global_menu_get_item_key_callback(const String &p_menu_root, int p_idx) const {
- WARN_PRINT("Global menus not supported by this display server.");
- return Callable();
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL_V(nmenu, Callable());
+ return nmenu->get_item_key_callback(_get_rid_from_name(nmenu, p_menu_root), p_idx);
}
Variant DisplayServer::global_menu_get_item_tag(const String &p_menu_root, int p_idx) const {
- WARN_PRINT("Global menus not supported by this display server.");
- return Variant();
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL_V(nmenu, Variant());
+ return nmenu->get_item_tag(_get_rid_from_name(nmenu, p_menu_root), p_idx);
}
String DisplayServer::global_menu_get_item_text(const String &p_menu_root, int p_idx) const {
- WARN_PRINT("Global menus not supported by this display server.");
- return String();
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL_V(nmenu, String());
+ return nmenu->get_item_text(_get_rid_from_name(nmenu, p_menu_root), p_idx);
}
String DisplayServer::global_menu_get_item_submenu(const String &p_menu_root, int p_idx) const {
- WARN_PRINT("Global menus not supported by this display server.");
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL_V(nmenu, String());
+ RID rid = nmenu->get_item_submenu(_get_rid_from_name(nmenu, p_menu_root), p_idx);
+ if (!nmenu->is_system_menu(rid)) {
+ for (HashMap<String, RID>::Iterator E = menu_names.begin(); E;) {
+ if (E->value == rid) {
+ return E->key;
+ }
+ }
+ }
return String();
}
Key DisplayServer::global_menu_get_item_accelerator(const String &p_menu_root, int p_idx) const {
- WARN_PRINT("Global menus not supported by this display server.");
- return Key::NONE;
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL_V(nmenu, Key::NONE);
+ return nmenu->get_item_accelerator(_get_rid_from_name(nmenu, p_menu_root), p_idx);
}
bool DisplayServer::global_menu_is_item_disabled(const String &p_menu_root, int p_idx) const {
- WARN_PRINT("Global menus not supported by this display server.");
- return false;
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL_V(nmenu, false);
+ return nmenu->is_item_disabled(_get_rid_from_name(nmenu, p_menu_root), p_idx);
}
bool DisplayServer::global_menu_is_item_hidden(const String &p_menu_root, int p_idx) const {
- WARN_PRINT("Global menus not supported by this display server.");
- return false;
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL_V(nmenu, false);
+ return nmenu->is_item_hidden(_get_rid_from_name(nmenu, p_menu_root), p_idx);
}
String DisplayServer::global_menu_get_item_tooltip(const String &p_menu_root, int p_idx) const {
- WARN_PRINT("Global menus not supported by this display server.");
- return String();
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL_V(nmenu, String());
+ return nmenu->get_item_tooltip(_get_rid_from_name(nmenu, p_menu_root), p_idx);
}
int DisplayServer::global_menu_get_item_state(const String &p_menu_root, int p_idx) const {
- WARN_PRINT("Global menus not supported by this display server.");
- return -1;
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL_V(nmenu, -1);
+ return nmenu->get_item_state(_get_rid_from_name(nmenu, p_menu_root), p_idx);
}
int DisplayServer::global_menu_get_item_max_states(const String &p_menu_root, int p_idx) const {
- WARN_PRINT("Global menus not supported by this display server.");
- return -1;
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL_V(nmenu, -1);
+ return nmenu->get_item_max_states(_get_rid_from_name(nmenu, p_menu_root), p_idx);
}
Ref<Texture2D> DisplayServer::global_menu_get_item_icon(const String &p_menu_root, int p_idx) const {
- WARN_PRINT("Global menus not supported by this display server.");
- return Ref<Texture2D>();
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL_V(nmenu, Ref<Texture2D>());
+ return nmenu->get_item_icon(_get_rid_from_name(nmenu, p_menu_root), p_idx);
}
int DisplayServer::global_menu_get_item_indentation_level(const String &p_menu_root, int p_idx) const {
- WARN_PRINT("Global menus not supported by this display server.");
- return 0;
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL_V(nmenu, 0);
+ return nmenu->get_item_indentation_level(_get_rid_from_name(nmenu, p_menu_root), p_idx);
}
void DisplayServer::global_menu_set_item_checked(const String &p_menu_root, int p_idx, bool p_checked) {
- WARN_PRINT("Global menus not supported by this display server.");
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL(nmenu);
+ nmenu->set_item_checked(_get_rid_from_name(nmenu, p_menu_root), p_idx, p_checked);
}
void DisplayServer::global_menu_set_item_checkable(const String &p_menu_root, int p_idx, bool p_checkable) {
- WARN_PRINT("Global menus not supported by this display server.");
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL(nmenu);
+ nmenu->set_item_checkable(_get_rid_from_name(nmenu, p_menu_root), p_idx, p_checkable);
}
void DisplayServer::global_menu_set_item_radio_checkable(const String &p_menu_root, int p_idx, bool p_checkable) {
- WARN_PRINT("Global menus not supported by this display server.");
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL(nmenu);
+ nmenu->set_item_radio_checkable(_get_rid_from_name(nmenu, p_menu_root), p_idx, p_checkable);
}
void DisplayServer::global_menu_set_item_tag(const String &p_menu_root, int p_idx, const Variant &p_tag) {
- WARN_PRINT("Global menus not supported by this display server.");
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL(nmenu);
+ nmenu->set_item_tag(_get_rid_from_name(nmenu, p_menu_root), p_idx, p_tag);
}
void DisplayServer::global_menu_set_item_text(const String &p_menu_root, int p_idx, const String &p_text) {
- WARN_PRINT("Global menus not supported by this display server.");
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL(nmenu);
+ nmenu->set_item_text(_get_rid_from_name(nmenu, p_menu_root), p_idx, p_text);
}
void DisplayServer::global_menu_set_item_submenu(const String &p_menu_root, int p_idx, const String &p_submenu) {
- WARN_PRINT("Global menus not supported by this display server.");
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL(nmenu);
+ nmenu->set_item_submenu(_get_rid_from_name(nmenu, p_menu_root), p_idx, _get_rid_from_name(nmenu, p_submenu));
}
void DisplayServer::global_menu_set_item_accelerator(const String &p_menu_root, int p_idx, Key p_keycode) {
- WARN_PRINT("Global menus not supported by this display server.");
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL(nmenu);
+ nmenu->set_item_accelerator(_get_rid_from_name(nmenu, p_menu_root), p_idx, p_keycode);
}
void DisplayServer::global_menu_set_item_disabled(const String &p_menu_root, int p_idx, bool p_disabled) {
- WARN_PRINT("Global menus not supported by this display server.");
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL(nmenu);
+ nmenu->set_item_disabled(_get_rid_from_name(nmenu, p_menu_root), p_idx, p_disabled);
}
void DisplayServer::global_menu_set_item_hidden(const String &p_menu_root, int p_idx, bool p_hidden) {
- WARN_PRINT("Global menus not supported by this display server.");
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL(nmenu);
+ nmenu->set_item_hidden(_get_rid_from_name(nmenu, p_menu_root), p_idx, p_hidden);
}
void DisplayServer::global_menu_set_item_tooltip(const String &p_menu_root, int p_idx, const String &p_tooltip) {
- WARN_PRINT("Global menus not supported by this display server.");
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL(nmenu);
+ nmenu->set_item_tooltip(_get_rid_from_name(nmenu, p_menu_root), p_idx, p_tooltip);
}
void DisplayServer::global_menu_set_item_state(const String &p_menu_root, int p_idx, int p_state) {
- WARN_PRINT("Global menus not supported by this display server.");
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL(nmenu);
+ nmenu->set_item_state(_get_rid_from_name(nmenu, p_menu_root), p_idx, p_state);
}
void DisplayServer::global_menu_set_item_max_states(const String &p_menu_root, int p_idx, int p_max_states) {
- WARN_PRINT("Global menus not supported by this display server.");
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL(nmenu);
+ nmenu->set_item_max_states(_get_rid_from_name(nmenu, p_menu_root), p_idx, p_max_states);
}
void DisplayServer::global_menu_set_item_icon(const String &p_menu_root, int p_idx, const Ref<Texture2D> &p_icon) {
- WARN_PRINT("Global menus not supported by this display server.");
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL(nmenu);
+ nmenu->set_item_icon(_get_rid_from_name(nmenu, p_menu_root), p_idx, p_icon);
}
void DisplayServer::global_menu_set_item_indentation_level(const String &p_menu_root, int p_idx, int p_level) {
- WARN_PRINT("Global menus not supported by this display server.");
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL(nmenu);
+ nmenu->set_item_indentation_level(_get_rid_from_name(nmenu, p_menu_root), p_idx, p_level);
}
int DisplayServer::global_menu_get_item_count(const String &p_menu_root) const {
- WARN_PRINT("Global menus not supported by this display server.");
- return 0;
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL_V(nmenu, 0);
+ return nmenu->get_item_count(_get_rid_from_name(nmenu, p_menu_root));
}
void DisplayServer::global_menu_remove_item(const String &p_menu_root, int p_idx) {
- WARN_PRINT("Global menus not supported by this display server.");
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL(nmenu);
+ nmenu->remove_item(_get_rid_from_name(nmenu, p_menu_root), p_idx);
}
void DisplayServer::global_menu_clear(const String &p_menu_root) {
- WARN_PRINT("Global menus not supported by this display server.");
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL(nmenu);
+ RID rid = _get_rid_from_name(nmenu, p_menu_root);
+ nmenu->clear(rid);
+ if (!nmenu->is_system_menu(rid)) {
+ nmenu->free_menu(rid);
+ menu_names.erase(p_menu_root);
+ }
}
Dictionary DisplayServer::global_menu_get_system_menu_roots() const {
- WARN_PRINT("Global menus not supported by this display server.");
- return Dictionary();
+ NativeMenu *nmenu = NativeMenu::get_singleton();
+ ERR_FAIL_NULL_V(nmenu, Dictionary());
+
+ Dictionary out;
+ if (nmenu->has_system_menu(NativeMenu::DOCK_MENU_ID)) {
+ out["_dock"] = "@Dock";
+ }
+ if (nmenu->has_system_menu(NativeMenu::APPLICATION_MENU_ID)) {
+ out["_apple"] = "@Apple";
+ }
+ if (nmenu->has_system_menu(NativeMenu::WINDOW_MENU_ID)) {
+ out["_window"] = "Window";
+ }
+ if (nmenu->has_system_menu(NativeMenu::HELP_MENU_ID)) {
+ out["_help"] = "Help";
+ }
+ return out;
}
+#endif
+
bool DisplayServer::tts_is_speaking() const {
WARN_PRINT("TTS is not supported by this display server.");
return false;
@@ -523,22 +645,22 @@ void DisplayServer::enable_for_stealing_focus(OS::ProcessID pid) {
Error DisplayServer::dialog_show(String p_title, String p_description, Vector<String> p_buttons, const Callable &p_callback) {
WARN_PRINT("Native dialogs not supported by this display server.");
- return OK;
+ return ERR_UNAVAILABLE;
}
Error DisplayServer::dialog_input_text(String p_title, String p_description, String p_partial, const Callable &p_callback) {
WARN_PRINT("Native dialogs not supported by this display server.");
- return OK;
+ return ERR_UNAVAILABLE;
}
Error DisplayServer::file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback) {
WARN_PRINT("Native dialogs not supported by this display server.");
- return OK;
+ return ERR_UNAVAILABLE;
}
Error DisplayServer::file_dialog_with_options_show(const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback) {
WARN_PRINT("Native dialogs not supported by this display server.");
- return OK;
+ return ERR_UNAVAILABLE;
}
int DisplayServer::keyboard_get_layout_count() const {
@@ -639,6 +761,7 @@ void DisplayServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("help_set_search_callbacks", "search_callback", "action_callback"), &DisplayServer::help_set_search_callbacks);
+#ifndef DISABLE_DEPRECATED
ClassDB::bind_method(D_METHOD("global_menu_set_popup_callbacks", "menu_root", "open_callback", "close_callback"), &DisplayServer::global_menu_set_popup_callbacks);
ClassDB::bind_method(D_METHOD("global_menu_add_submenu_item", "menu_root", "label", "submenu", "index"), &DisplayServer::global_menu_add_submenu_item, DEFVAL(-1));
ClassDB::bind_method(D_METHOD("global_menu_add_item", "menu_root", "label", "callback", "key_callback", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_item, DEFVAL(Callable()), DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1));
@@ -694,6 +817,7 @@ void DisplayServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("global_menu_clear", "menu_root"), &DisplayServer::global_menu_clear);
ClassDB::bind_method(D_METHOD("global_menu_get_system_menu_roots"), &DisplayServer::global_menu_get_system_menu_roots);
+#endif
ClassDB::bind_method(D_METHOD("tts_is_speaking"), &DisplayServer::tts_is_speaking);
ClassDB::bind_method(D_METHOD("tts_is_paused"), &DisplayServer::tts_is_paused);
@@ -865,7 +989,9 @@ void DisplayServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("tablet_get_current_driver"), &DisplayServer::tablet_get_current_driver);
ClassDB::bind_method(D_METHOD("tablet_set_current_driver", "name"), &DisplayServer::tablet_set_current_driver);
+#ifndef DISABLE_DEPRECATED
BIND_ENUM_CONSTANT(FEATURE_GLOBAL_MENU);
+#endif
BIND_ENUM_CONSTANT(FEATURE_SUBWINDOWS);
BIND_ENUM_CONSTANT(FEATURE_TOUCHSCREEN);
BIND_ENUM_CONSTANT(FEATURE_MOUSE);
@@ -888,6 +1014,8 @@ void DisplayServer::_bind_methods() {
BIND_ENUM_CONSTANT(FEATURE_SCREEN_CAPTURE);
BIND_ENUM_CONSTANT(FEATURE_STATUS_INDICATOR);
BIND_ENUM_CONSTANT(FEATURE_NATIVE_HELP);
+ BIND_ENUM_CONSTANT(FEATURE_NATIVE_DIALOG_INPUT);
+ BIND_ENUM_CONSTANT(FEATURE_NATIVE_DIALOG_FILE);
BIND_ENUM_CONSTANT(MOUSE_MODE_VISIBLE);
BIND_ENUM_CONSTANT(MOUSE_MODE_HIDDEN);
@@ -987,6 +1115,43 @@ void DisplayServer::_bind_methods() {
BIND_ENUM_CONSTANT(TTS_UTTERANCE_BOUNDARY);
}
+Ref<Image> DisplayServer::_get_cursor_image_from_resource(const Ref<Resource> &p_cursor, const Vector2 &p_hotspot, Rect2 &r_atlas_rect) {
+ Ref<Image> image;
+ ERR_FAIL_COND_V_MSG(p_hotspot.x < 0 || p_hotspot.y < 0, image, "Hotspot outside cursor image.");
+
+ Size2 texture_size;
+
+ Ref<Texture2D> texture = p_cursor;
+ if (texture.is_valid()) {
+ Ref<AtlasTexture> atlas_texture = p_cursor;
+
+ if (atlas_texture.is_valid()) {
+ texture = atlas_texture->get_atlas();
+ r_atlas_rect.size = texture->get_size();
+ r_atlas_rect.position = atlas_texture->get_region().position;
+ texture_size = atlas_texture->get_region().size;
+ } else {
+ texture_size = texture->get_size();
+ }
+ image = texture->get_image();
+ } else {
+ image = p_cursor;
+ ERR_FAIL_COND_V(image.is_null(), image);
+ texture_size = image->get_size();
+ }
+
+ ERR_FAIL_COND_V_MSG(p_hotspot.x > texture_size.width || p_hotspot.y > texture_size.height, image, "Hotspot outside cursor image.");
+ ERR_FAIL_COND_V_MSG(texture_size.width > 256 || texture_size.height > 256, image, "Cursor image too big. Max supported size is 256x256.");
+
+ ERR_FAIL_COND_V(image.is_null(), image);
+ if (image->is_compressed()) {
+ image = image->duplicate(true);
+ Error err = image->decompress();
+ ERR_FAIL_COND_V_MSG(err != OK, Ref<Image>(), "Couldn't decompress VRAM-compressed custom mouse cursor image. Switch to a lossless compression mode in the Import dock.");
+ }
+ return image;
+}
+
void DisplayServer::register_create_function(const char *p_name, CreateFunction p_function, GetRenderingDriversFunction p_get_drivers) {
ERR_FAIL_COND(server_create_count == MAX_SERVERS);
// Headless display server is always last
diff --git a/servers/display_server.h b/servers/display_server.h
index 0f6c43ebe0..f1a98c2c17 100644
--- a/servers/display_server.h
+++ b/servers/display_server.h
@@ -36,7 +36,10 @@
#include "core/os/os.h"
#include "core/variant/callable.h"
+#include "display/native_menu.h"
+
class Texture2D;
+class Image;
class DisplayServer : public Object {
GDCLASS(DisplayServer, Object)
@@ -44,6 +47,12 @@ class DisplayServer : public Object {
static DisplayServer *singleton;
static bool hidpi_allowed;
+#ifndef DISABLE_DEPRECATED
+ mutable HashMap<String, RID> menu_names;
+
+ RID _get_rid_from_name(NativeMenu *p_nmenu, const String &p_menu_root) const;
+#endif
+
public:
_FORCE_INLINE_ static DisplayServer *get_singleton() {
return singleton;
@@ -86,6 +95,8 @@ private:
protected:
static void _bind_methods();
+ static Ref<Image> _get_cursor_image_from_resource(const Ref<Resource> &p_cursor, const Vector2 &p_hotspot, Rect2 &r_atlas_rect);
+
enum {
MAX_SERVERS = 64
};
@@ -103,7 +114,9 @@ protected:
public:
enum Feature {
+#ifndef DISABLE_DEPRECATED
FEATURE_GLOBAL_MENU,
+#endif
FEATURE_SUBWINDOWS,
FEATURE_TOUCHSCREEN,
FEATURE_MOUSE,
@@ -127,6 +140,8 @@ public:
FEATURE_SCREEN_CAPTURE,
FEATURE_STATUS_INDICATOR,
FEATURE_NATIVE_HELP,
+ FEATURE_NATIVE_DIALOG_INPUT,
+ FEATURE_NATIVE_DIALOG_FILE,
};
virtual bool has_feature(Feature p_feature) const = 0;
@@ -134,6 +149,7 @@ public:
virtual void help_set_search_callbacks(const Callable &p_search_callback = Callable(), const Callable &p_action_callback = Callable());
+#ifndef DISABLE_DEPRECATED
virtual void global_menu_set_popup_callbacks(const String &p_menu_root, const Callable &p_open_callback = Callable(), const Callable &p_close_callback = Callable());
virtual int global_menu_add_submenu_item(const String &p_menu_root, const String &p_label, const String &p_submenu, int p_index = -1);
@@ -190,6 +206,7 @@ public:
virtual void global_menu_clear(const String &p_menu_root);
virtual Dictionary global_menu_get_system_menu_roots() const;
+#endif
struct TTSUtterance {
String text;
diff --git a/servers/display_server_headless.h b/servers/display_server_headless.h
index af13f8db21..7a44645b1e 100644
--- a/servers/display_server_headless.h
+++ b/servers/display_server_headless.h
@@ -51,6 +51,8 @@ private:
return memnew(DisplayServerHeadless());
}
+ NativeMenu *native_menu = nullptr;
+
public:
bool has_feature(Feature p_feature) const override { return false; }
String get_name() const override { return "headless"; }
@@ -132,8 +134,15 @@ public:
void set_icon(const Ref<Image> &p_icon) override {}
- DisplayServerHeadless() {}
- ~DisplayServerHeadless() {}
+ DisplayServerHeadless() {
+ native_menu = memnew(NativeMenu);
+ }
+ ~DisplayServerHeadless() {
+ if (native_menu) {
+ memdelete(native_menu);
+ native_menu = nullptr;
+ }
+ }
};
#endif // DISPLAY_SERVER_HEADLESS_H
diff --git a/servers/extensions/SCsub b/servers/extensions/SCsub
index ba73353f2a..95c7f5d319 100644
--- a/servers/extensions/SCsub
+++ b/servers/extensions/SCsub
@@ -4,4 +4,7 @@ Import("env")
env_object = env.Clone()
-env_object.add_source_files(env.servers_sources, "*.cpp")
+env_object.add_source_files(env.servers_sources, "physics_server_2d_extension.cpp")
+
+if not env["disable_3d"]:
+ env_object.add_source_files(env.servers_sources, "physics_server_3d_extension.cpp")
diff --git a/servers/navigation_server_3d.cpp b/servers/navigation_server_3d.cpp
index 00db1440f6..e460bcb9c6 100644
--- a/servers/navigation_server_3d.cpp
+++ b/servers/navigation_server_3d.cpp
@@ -29,7 +29,9 @@
/**************************************************************************/
#include "navigation_server_3d.h"
+
#include "core/config/project_settings.h"
+#include "scene/main/node.h"
NavigationServer3D *NavigationServer3D::singleton = nullptr;
@@ -233,6 +235,7 @@ NavigationServer3D::NavigationServer3D() {
GLOBAL_DEF("navigation/avoidance/thread_model/avoidance_use_multiple_threads", true);
GLOBAL_DEF("navigation/avoidance/thread_model/avoidance_use_high_priority_threads", true);
+ GLOBAL_DEF("navigation/baking/use_crash_prevention_checks", true);
GLOBAL_DEF("navigation/baking/thread_model/baking_use_multiple_threads", true);
GLOBAL_DEF("navigation/baking/thread_model/baking_use_high_priority_threads", true);
@@ -291,7 +294,11 @@ void NavigationServer3D::set_debug_enabled(bool p_enabled) {
debug_enabled = p_enabled;
if (debug_dirty) {
+ navigation_debug_dirty = true;
callable_mp(this, &NavigationServer3D::_emit_navigation_debug_changed_signal).call_deferred();
+
+ avoidance_debug_dirty = true;
+ callable_mp(this, &NavigationServer3D::_emit_avoidance_debug_changed_signal).call_deferred();
}
#endif // DEBUG_ENABLED
}
diff --git a/servers/physics_2d/godot_broad_phase_2d_bvh.h b/servers/physics_2d/godot_broad_phase_2d_bvh.h
index 36fd1223b0..6c1fae5cb2 100644
--- a/servers/physics_2d/godot_broad_phase_2d_bvh.h
+++ b/servers/physics_2d/godot_broad_phase_2d_bvh.h
@@ -38,7 +38,7 @@
#include "core/math/vector2.h"
class GodotBroadPhase2DBVH : public GodotBroadPhase2D {
- template <class T>
+ template <typename T>
class UserPairTestFunction {
public:
static bool user_pair_check(const T *p_a, const T *p_b) {
@@ -47,7 +47,7 @@ class GodotBroadPhase2DBVH : public GodotBroadPhase2D {
}
};
- template <class T>
+ template <typename T>
class UserCullTestFunction {
public:
static bool user_cull_check(const T *p_a, const T *p_b) {
diff --git a/servers/physics_2d/godot_collision_solver_2d_sat.cpp b/servers/physics_2d/godot_collision_solver_2d_sat.cpp
index c85fdc592a..daa9982b2e 100644
--- a/servers/physics_2d/godot_collision_solver_2d_sat.cpp
+++ b/servers/physics_2d/godot_collision_solver_2d_sat.cpp
@@ -171,7 +171,7 @@ static void _generate_contacts_from_supports(const Vector2 *p_points_A, int p_po
contacts_func(points_A, pointcount_A, points_B, pointcount_B, p_collector);
}
-template <class ShapeA, class ShapeB, bool castA = false, bool castB = false, bool withMargin = false>
+template <typename ShapeA, typename ShapeB, bool castA = false, bool castB = false, bool withMargin = false>
class SeparatorAxisTest2D {
const ShapeA *shape_A = nullptr;
const ShapeB *shape_B = nullptr;
diff --git a/servers/physics_3d/godot_broad_phase_3d_bvh.h b/servers/physics_3d/godot_broad_phase_3d_bvh.h
index 6279658ec4..63968dea64 100644
--- a/servers/physics_3d/godot_broad_phase_3d_bvh.h
+++ b/servers/physics_3d/godot_broad_phase_3d_bvh.h
@@ -36,7 +36,7 @@
#include "core/math/bvh.h"
class GodotBroadPhase3DBVH : public GodotBroadPhase3D {
- template <class T>
+ template <typename T>
class UserPairTestFunction {
public:
static bool user_pair_check(const T *p_a, const T *p_b) {
@@ -45,7 +45,7 @@ class GodotBroadPhase3DBVH : public GodotBroadPhase3D {
}
};
- template <class T>
+ template <typename T>
class UserCullTestFunction {
public:
static bool user_cull_check(const T *p_a, const T *p_b) {
diff --git a/servers/physics_3d/godot_collision_solver_3d_sat.cpp b/servers/physics_3d/godot_collision_solver_3d_sat.cpp
index 3aa2f256c1..c53c8481f4 100644
--- a/servers/physics_3d/godot_collision_solver_3d_sat.cpp
+++ b/servers/physics_3d/godot_collision_solver_3d_sat.cpp
@@ -612,7 +612,7 @@ static void _generate_contacts_from_supports(const Vector3 *p_points_A, int p_po
contacts_func(points_A, pointcount_A, points_B, pointcount_B, p_callback);
}
-template <class ShapeA, class ShapeB, bool withMargin = false>
+template <typename ShapeA, typename ShapeB, bool withMargin = false>
class SeparatorAxisTest {
const ShapeA *shape_A = nullptr;
const ShapeB *shape_B = nullptr;
@@ -1962,7 +1962,7 @@ static void _collision_cylinder_face(const GodotShape3D *p_a, const Transform3D
// Points of B, cylinder lateral surface.
for (int i = 0; i < 3; i++) {
- const Vector3 &point = vertex[i];
+ const Vector3 point = vertex[i] - p_transform_a.origin;
Vector3 axis = Plane(cyl_axis).project(point).normalized();
if (axis.dot(normal) < 0.0) {
axis *= -1.0;
diff --git a/servers/physics_3d/godot_shape_3d.cpp b/servers/physics_3d/godot_shape_3d.cpp
index 872d26aff6..ea389ff59c 100644
--- a/servers/physics_3d/godot_shape_3d.cpp
+++ b/servers/physics_3d/godot_shape_3d.cpp
@@ -2016,9 +2016,7 @@ void GodotHeightMapShape3D::_get_cell(const Vector3 &p_point, int &r_x, int &r_y
Vector3 pos_local = shape_aabb.position + local_origin;
Vector3 clamped_point(p_point);
- clamped_point.x = CLAMP(p_point.x, pos_local.x, pos_local.x + shape_aabb.size.x);
- clamped_point.y = CLAMP(p_point.y, pos_local.y, pos_local.y + shape_aabb.size.y);
- clamped_point.z = CLAMP(p_point.z, pos_local.z, pos_local.z + shape_aabb.size.z);
+ clamped_point = p_point.clamp(pos_local, pos_local + shape_aabb.size);
r_x = (clamped_point.x < 0.0) ? (clamped_point.x - 0.5) : (clamped_point.x + 0.5);
r_y = (clamped_point.y < 0.0) ? (clamped_point.y - 0.5) : (clamped_point.y + 0.5);
diff --git a/servers/physics_3d/godot_soft_body_3d.cpp b/servers/physics_3d/godot_soft_body_3d.cpp
index 0c2b935554..e621977326 100644
--- a/servers/physics_3d/godot_soft_body_3d.cpp
+++ b/servers/physics_3d/godot_soft_body_3d.cpp
@@ -595,7 +595,7 @@ void GodotSoftBody3D::generate_bending_constraints(int p_distance) {
const uint32_t adj_size = n * n;
unsigned *adj = memnew_arr(unsigned, adj_size);
-#define IDX(_x_, _y_) ((_y_)*n + (_x_))
+#define IDX(_x_, _y_) ((_y_) * n + (_x_))
for (j = 0; j < n; ++j) {
for (i = 0; i < n; ++i) {
int idx_ij = j * n + i;
diff --git a/servers/physics_3d/godot_space_3d.cpp b/servers/physics_3d/godot_space_3d.cpp
index 46b6689533..9a6ba776b4 100644
--- a/servers/physics_3d/godot_space_3d.cpp
+++ b/servers/physics_3d/godot_space_3d.cpp
@@ -655,7 +655,7 @@ bool GodotSpace3D::test_body_motion(GodotBody3D *p_body, const PhysicsServer3D::
//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);
+ ERR_FAIL_COND_V(p_parameters.max_collisions < 0 || p_parameters.max_collisions > PhysicsServer3D::MotionResult::MAX_COLLISIONS, false);
if (r_result) {
*r_result = PhysicsServer3D::MotionResult();
diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp
index 686388f237..f56ef11c14 100644
--- a/servers/physics_server_3d.cpp
+++ b/servers/physics_server_3d.cpp
@@ -28,6 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
+#ifndef _3D_DISABLED
+
#include "physics_server_3d.h"
#include "core/config/project_settings.h"
@@ -983,6 +985,9 @@ void PhysicsServer3D::_bind_methods() {
BIND_ENUM_CONSTANT(G6DOF_JOINT_LINEAR_DAMPING);
BIND_ENUM_CONSTANT(G6DOF_JOINT_LINEAR_MOTOR_TARGET_VELOCITY);
BIND_ENUM_CONSTANT(G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT);
+ BIND_ENUM_CONSTANT(G6DOF_JOINT_LINEAR_SPRING_STIFFNESS);
+ BIND_ENUM_CONSTANT(G6DOF_JOINT_LINEAR_SPRING_DAMPING);
+ BIND_ENUM_CONSTANT(G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT);
BIND_ENUM_CONSTANT(G6DOF_JOINT_ANGULAR_LOWER_LIMIT);
BIND_ENUM_CONSTANT(G6DOF_JOINT_ANGULAR_UPPER_LIMIT);
BIND_ENUM_CONSTANT(G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS);
@@ -992,11 +997,18 @@ void PhysicsServer3D::_bind_methods() {
BIND_ENUM_CONSTANT(G6DOF_JOINT_ANGULAR_ERP);
BIND_ENUM_CONSTANT(G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY);
BIND_ENUM_CONSTANT(G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT);
+ BIND_ENUM_CONSTANT(G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS);
+ BIND_ENUM_CONSTANT(G6DOF_JOINT_ANGULAR_SPRING_DAMPING);
+ BIND_ENUM_CONSTANT(G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT);
+ BIND_ENUM_CONSTANT(G6DOF_JOINT_MAX);
BIND_ENUM_CONSTANT(G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT);
BIND_ENUM_CONSTANT(G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT);
+ BIND_ENUM_CONSTANT(G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING);
+ BIND_ENUM_CONSTANT(G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING);
BIND_ENUM_CONSTANT(G6DOF_JOINT_FLAG_ENABLE_MOTOR);
BIND_ENUM_CONSTANT(G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR);
+ BIND_ENUM_CONSTANT(G6DOF_JOINT_FLAG_MAX);
ClassDB::bind_method(D_METHOD("joint_get_type", "joint"), &PhysicsServer3D::joint_get_type);
@@ -1213,3 +1225,5 @@ PhysicsServer3DManager::PhysicsServer3DManager() {
PhysicsServer3DManager::~PhysicsServer3DManager() {
singleton = nullptr;
}
+
+#endif // _3D_DISABLED
diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h
index 248b6cd8f8..ea785fa03f 100644
--- a/servers/physics_server_3d.h
+++ b/servers/physics_server_3d.h
@@ -31,6 +31,8 @@
#ifndef PHYSICS_SERVER_3D_H
#define PHYSICS_SERVER_3D_H
+#ifndef _3D_DISABLED
+
#include "core/io/resource.h"
#include "core/object/class_db.h"
#include "core/object/gdvirtual.gen.inc"
@@ -1055,4 +1057,6 @@ VARIANT_ENUM_CAST(PhysicsServer3D::G6DOFJointAxisFlag);
VARIANT_ENUM_CAST(PhysicsServer3D::AreaBodyStatus);
VARIANT_ENUM_CAST(PhysicsServer3D::ProcessInfo);
+#endif // _3D_DISABLED
+
#endif // PHYSICS_SERVER_3D_H
diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp
index 380500769c..c03c0b7a40 100644
--- a/servers/register_server_types.cpp
+++ b/servers/register_server_types.cpp
@@ -43,6 +43,7 @@
#include "audio/effects/audio_effect_distortion.h"
#include "audio/effects/audio_effect_eq.h"
#include "audio/effects/audio_effect_filter.h"
+#include "audio/effects/audio_effect_hard_limiter.h"
#include "audio/effects/audio_effect_limiter.h"
#include "audio/effects/audio_effect_panner.h"
#include "audio/effects/audio_effect_phaser.h"
@@ -56,6 +57,7 @@
#include "camera/camera_feed.h"
#include "camera_server.h"
#include "debugger/servers_debugger.h"
+#include "display/native_menu.h"
#include "display_server.h"
#include "movie_writer/movie_writer.h"
#include "movie_writer/movie_writer_mjpeg.h"
@@ -76,12 +78,6 @@
#include "text/text_server_dummy.h"
#include "text/text_server_extension.h"
#include "text_server.h"
-#include "xr/xr_face_tracker.h"
-#include "xr/xr_hand_tracker.h"
-#include "xr/xr_interface.h"
-#include "xr/xr_interface_extension.h"
-#include "xr/xr_positional_tracker.h"
-#include "xr_server.h"
// 2D physics and navigation.
#include "navigation_server_2d.h"
@@ -97,6 +93,13 @@
#include "physics_server_3d.h"
#include "physics_server_3d_wrap_mt.h"
#include "servers/extensions/physics_server_3d_extension.h"
+#include "xr/xr_body_tracker.h"
+#include "xr/xr_face_tracker.h"
+#include "xr/xr_hand_tracker.h"
+#include "xr/xr_interface.h"
+#include "xr/xr_interface_extension.h"
+#include "xr/xr_positional_tracker.h"
+#include "xr_server.h"
#endif // _3D_DISABLED
ShaderTypes *shader_types = nullptr;
@@ -161,25 +164,12 @@ void register_server_types() {
GDREGISTER_ABSTRACT_CLASS(RenderingServer);
GDREGISTER_CLASS(AudioServer);
- GDREGISTER_ABSTRACT_CLASS(NavigationServer2D);
- GDREGISTER_ABSTRACT_CLASS(NavigationServer3D);
- GDREGISTER_CLASS(NavigationPathQueryParameters2D);
- GDREGISTER_CLASS(NavigationPathQueryParameters3D);
- GDREGISTER_CLASS(NavigationPathQueryResult2D);
- GDREGISTER_CLASS(NavigationPathQueryResult3D);
+ GDREGISTER_CLASS(NativeMenu);
- GDREGISTER_CLASS(XRServer);
GDREGISTER_CLASS(CameraServer);
GDREGISTER_ABSTRACT_CLASS(RenderingDevice);
- GDREGISTER_ABSTRACT_CLASS(XRInterface);
- GDREGISTER_CLASS(XRHandTracker);
- GDREGISTER_CLASS(XRInterfaceExtension); // can't register this as virtual because we need a creation function for our extensions.
- GDREGISTER_CLASS(XRPose);
- GDREGISTER_CLASS(XRPositionalTracker);
- GDREGISTER_CLASS(XRFaceTracker);
-
GDREGISTER_CLASS(AudioStream);
GDREGISTER_CLASS(AudioStreamPlayback);
GDREGISTER_VIRTUAL_CLASS(AudioStreamPlaybackResampled);
@@ -221,6 +211,7 @@ void register_server_types() {
GDREGISTER_CLASS(AudioEffectDelay);
GDREGISTER_CLASS(AudioEffectCompressor);
GDREGISTER_CLASS(AudioEffectLimiter);
+ GDREGISTER_CLASS(AudioEffectHardLimiter);
GDREGISTER_CLASS(AudioEffectPitchShift);
GDREGISTER_CLASS(AudioEffectPhaser);
@@ -298,6 +289,10 @@ void register_server_types() {
PhysicsServer2DManager::get_singleton()->register_server("GodotPhysics2D", callable_mp_static(_createGodotPhysics2DCallback));
PhysicsServer2DManager::get_singleton()->set_default_server("GodotPhysics2D");
+ GDREGISTER_ABSTRACT_CLASS(NavigationServer2D);
+ GDREGISTER_CLASS(NavigationPathQueryParameters2D);
+ GDREGISTER_CLASS(NavigationPathQueryResult2D);
+
#ifndef _3D_DISABLED
// Physics 3D
GDREGISTER_CLASS(PhysicsServer3DManager);
@@ -327,8 +322,21 @@ void register_server_types() {
PhysicsServer3DManager::get_singleton()->register_server("GodotPhysics3D", callable_mp_static(_createGodotPhysics3DCallback));
PhysicsServer3DManager::get_singleton()->set_default_server("GodotPhysics3D");
+
+ GDREGISTER_ABSTRACT_CLASS(XRInterface);
+ GDREGISTER_CLASS(XRBodyTracker);
+ GDREGISTER_CLASS(XRFaceTracker);
+ GDREGISTER_CLASS(XRHandTracker);
+ GDREGISTER_CLASS(XRInterfaceExtension); // can't register this as virtual because we need a creation function for our extensions.
+ GDREGISTER_CLASS(XRPose);
+ GDREGISTER_CLASS(XRPositionalTracker);
+ GDREGISTER_CLASS(XRServer);
#endif // _3D_DISABLED
+ GDREGISTER_ABSTRACT_CLASS(NavigationServer3D);
+ GDREGISTER_CLASS(NavigationPathQueryParameters3D);
+ GDREGISTER_CLASS(NavigationPathQueryResult3D);
+
writer_mjpeg = memnew(MovieWriterMJPEG);
MovieWriter::add_writer(writer_mjpeg);
@@ -352,17 +360,19 @@ void unregister_server_types() {
void register_server_singletons() {
OS::get_singleton()->benchmark_begin_measure("Servers", "Register Singletons");
+ Engine::get_singleton()->add_singleton(Engine::Singleton("AudioServer", AudioServer::get_singleton(), "AudioServer"));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("CameraServer", CameraServer::get_singleton(), "CameraServer"));
Engine::get_singleton()->add_singleton(Engine::Singleton("DisplayServer", DisplayServer::get_singleton(), "DisplayServer"));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("NativeMenu", NativeMenu::get_singleton(), "NativeMenu"));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("NavigationServer2D", NavigationServer2D::get_singleton(), "NavigationServer2D"));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("NavigationServer3D", NavigationServer3D::get_singleton(), "NavigationServer3D"));
Engine::get_singleton()->add_singleton(Engine::Singleton("RenderingServer", RenderingServer::get_singleton(), "RenderingServer"));
- Engine::get_singleton()->add_singleton(Engine::Singleton("AudioServer", AudioServer::get_singleton(), "AudioServer"));
+
Engine::get_singleton()->add_singleton(Engine::Singleton("PhysicsServer2D", PhysicsServer2D::get_singleton(), "PhysicsServer2D"));
#ifndef _3D_DISABLED
Engine::get_singleton()->add_singleton(Engine::Singleton("PhysicsServer3D", PhysicsServer3D::get_singleton(), "PhysicsServer3D"));
-#endif // _3D_DISABLED
- Engine::get_singleton()->add_singleton(Engine::Singleton("NavigationServer2D", NavigationServer2D::get_singleton(), "NavigationServer2D"));
- Engine::get_singleton()->add_singleton(Engine::Singleton("NavigationServer3D", NavigationServer3D::get_singleton(), "NavigationServer3D"));
Engine::get_singleton()->add_singleton(Engine::Singleton("XRServer", XRServer::get_singleton(), "XRServer"));
- Engine::get_singleton()->add_singleton(Engine::Singleton("CameraServer", CameraServer::get_singleton(), "CameraServer"));
+#endif // _3D_DISABLED
OS::get_singleton()->benchmark_end_measure("Servers", "Register Singletons");
}
diff --git a/servers/rendering/dummy/storage/light_storage.h b/servers/rendering/dummy/storage/light_storage.h
index 61a825f8c5..a76305cdaa 100644
--- a/servers/rendering/dummy/storage/light_storage.h
+++ b/servers/rendering/dummy/storage/light_storage.h
@@ -135,6 +135,7 @@ public:
virtual RID reflection_probe_instance_create(RID p_probe) override { return RID(); }
virtual void reflection_probe_instance_free(RID p_instance) override {}
virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) override {}
+ virtual bool reflection_probe_has_atlas_index(RID p_instance) override { return false; }
virtual void reflection_probe_release_atlas_index(RID p_instance) override {}
virtual bool reflection_probe_instance_needs_redraw(RID p_instance) override { return false; }
virtual bool reflection_probe_instance_has_reflection(RID p_instance) override { return false; }
diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp
index 65fcdb9751..e32164ea98 100644
--- a/servers/rendering/renderer_canvas_cull.cpp
+++ b/servers/rendering/renderer_canvas_cull.cpp
@@ -32,22 +32,20 @@
#include "core/config/project_settings.h"
#include "core/math/geometry_2d.h"
+#include "core/math/transform_interpolator.h"
#include "renderer_viewport.h"
#include "rendering_server_default.h"
#include "rendering_server_globals.h"
#include "servers/rendering/storage/texture_storage.h"
-void RendererCanvasCull::_render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, uint32_t p_canvas_cull_mask, RenderingMethod::RenderInfo *r_render_info) {
+void RendererCanvasCull::_render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, uint32_t p_canvas_cull_mask, RenderingMethod::RenderInfo *r_render_info) {
RENDER_TIMESTAMP("Cull CanvasItem Tree");
memset(z_list, 0, z_range * sizeof(RendererCanvasRender::Item *));
memset(z_last_list, 0, z_range * sizeof(RendererCanvasRender::Item *));
for (int i = 0; i < p_child_item_count; i++) {
- _cull_canvas_item(p_child_items[i].item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, nullptr, nullptr, true, p_canvas_cull_mask);
- }
- if (p_canvas_item) {
- _cull_canvas_item(p_canvas_item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, nullptr, nullptr, true, p_canvas_cull_mask);
+ _cull_canvas_item(p_child_items[i].item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, nullptr, nullptr, true, p_canvas_cull_mask, p_child_items[i].mirror, 1);
}
RendererCanvasRender::Item *list = nullptr;
@@ -84,7 +82,7 @@ void _collect_ysort_children(RendererCanvasCull::Item *p_canvas_item, Transform2
if (r_items) {
r_items[r_index] = child_items[i];
child_items[i]->ysort_xform = p_transform;
- child_items[i]->ysort_pos = p_transform.xform(child_items[i]->xform.columns[2]);
+ child_items[i]->ysort_pos = p_transform.xform(child_items[i]->xform_curr.columns[2]);
child_items[i]->material_owner = child_items[i]->use_parent_material ? p_material_owner : nullptr;
child_items[i]->ysort_modulate = p_modulate;
child_items[i]->ysort_index = r_index;
@@ -101,7 +99,7 @@ void _collect_ysort_children(RendererCanvasCull::Item *p_canvas_item, Transform2
r_index++;
if (child_items[i]->sort_y) {
- _collect_ysort_children(child_items[i], p_transform * child_items[i]->xform, child_items[i]->use_parent_material ? p_material_owner : child_items[i], p_modulate * child_items[i]->modulate, r_items, r_index, abs_z);
+ _collect_ysort_children(child_items[i], p_transform * child_items[i]->xform_curr, child_items[i]->use_parent_material ? p_material_owner : child_items[i], p_modulate * child_items[i]->modulate, r_items, r_index, abs_z);
}
}
}
@@ -223,7 +221,7 @@ void RendererCanvasCull::_attach_canvas_item_for_draw(RendererCanvasCull::Item *
}
}
-void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2D &p_parent_xform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RendererCanvasRender::Item **r_z_list, RendererCanvasRender::Item **r_z_last_list, Item *p_canvas_clip, Item *p_material_owner, bool p_allow_y_sort, uint32_t p_canvas_cull_mask) {
+void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2D &p_parent_xform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RendererCanvasRender::Item **r_z_list, RendererCanvasRender::Item **r_z_last_list, Item *p_canvas_clip, Item *p_material_owner, bool p_allow_y_sort, uint32_t p_canvas_cull_mask, const Point2 &p_repeat_size, int p_repeat_times) {
Item *ci = p_canvas_item;
if (!ci->visible) {
@@ -247,17 +245,40 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2
}
}
- Transform2D xform = ci->xform;
+ Transform2D final_xform;
+ if (!_interpolation_data.interpolation_enabled || !ci->interpolated) {
+ final_xform = ci->xform_curr;
+ } else {
+ real_t f = Engine::get_singleton()->get_physics_interpolation_fraction();
+ TransformInterpolator::interpolate_transform_2d(ci->xform_prev, ci->xform_curr, final_xform, f);
+ }
+
Transform2D parent_xform = p_parent_xform;
+ Point2 repeat_size = p_repeat_size;
+ int repeat_times = p_repeat_times;
+
+ if (ci->repeat_source) {
+ repeat_size = ci->repeat_size;
+ repeat_times = ci->repeat_times;
+ } else {
+ ci->repeat_size = repeat_size;
+ ci->repeat_times = repeat_times;
+
+ if (repeat_size.x || repeat_size.y) {
+ rect.size += repeat_size * repeat_times / final_xform.get_scale();
+ rect.position -= repeat_size * (repeat_times / 2);
+ }
+ }
+
if (snapping_2d_transforms_to_pixel) {
- xform.columns[2] = xform.columns[2].round();
+ final_xform.columns[2] = final_xform.columns[2].round();
parent_xform.columns[2] = parent_xform.columns[2].round();
}
- xform = parent_xform * xform;
+ final_xform = parent_xform * final_xform;
- Rect2 global_rect = xform.xform(rect);
+ Rect2 global_rect = final_xform.xform(rect);
global_rect.position += p_clip_rect.position;
if (ci->use_parent_material && p_material_owner) {
@@ -311,7 +332,7 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2
child_item_count = ci->ysort_children_count + 1;
child_items = (Item **)alloca(child_item_count * sizeof(Item *));
- ci->ysort_xform = ci->xform.affine_inverse();
+ ci->ysort_xform = final_xform.affine_inverse();
ci->ysort_pos = Vector2();
ci->ysort_modulate = Color(1, 1, 1, 1);
ci->ysort_index = 0;
@@ -324,7 +345,7 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2
sorter.sort(child_items, child_item_count);
for (i = 0; i < child_item_count; i++) {
- _cull_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate * child_items[i]->ysort_modulate, child_items[i]->ysort_parent_abs_z_index, r_z_list, r_z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner, false, p_canvas_cull_mask);
+ _cull_canvas_item(child_items[i], final_xform * child_items[i]->ysort_xform, p_clip_rect, modulate * child_items[i]->ysort_modulate, child_items[i]->ysort_parent_abs_z_index, r_z_list, r_z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner, false, p_canvas_cull_mask, repeat_size, repeat_times);
}
} else {
RendererCanvasRender::Item *canvas_group_from = nullptr;
@@ -334,7 +355,7 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2
canvas_group_from = r_z_last_list[zidx];
}
- _attach_canvas_item_for_draw(ci, p_canvas_clip, r_z_list, r_z_last_list, xform, p_clip_rect, global_rect, modulate, p_z, p_material_owner, use_canvas_group, canvas_group_from);
+ _attach_canvas_item_for_draw(ci, p_canvas_clip, r_z_list, r_z_last_list, final_xform, p_clip_rect, global_rect, modulate, p_z, p_material_owner, use_canvas_group, canvas_group_from);
}
} else {
RendererCanvasRender::Item *canvas_group_from = nullptr;
@@ -348,14 +369,14 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2
if (!child_items[i]->behind && !use_canvas_group) {
continue;
}
- _cull_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, r_z_list, r_z_last_list, (Item *)ci->final_clip_owner, p_material_owner, true, p_canvas_cull_mask);
+ _cull_canvas_item(child_items[i], final_xform, p_clip_rect, modulate, p_z, r_z_list, r_z_last_list, (Item *)ci->final_clip_owner, p_material_owner, true, p_canvas_cull_mask, repeat_size, repeat_times);
}
- _attach_canvas_item_for_draw(ci, p_canvas_clip, r_z_list, r_z_last_list, xform, p_clip_rect, global_rect, modulate, p_z, p_material_owner, use_canvas_group, canvas_group_from);
+ _attach_canvas_item_for_draw(ci, p_canvas_clip, r_z_list, r_z_last_list, final_xform, p_clip_rect, global_rect, modulate, p_z, p_material_owner, use_canvas_group, canvas_group_from);
for (int i = 0; i < child_item_count; i++) {
if (child_items[i]->behind || use_canvas_group) {
continue;
}
- _cull_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, r_z_list, r_z_last_list, (Item *)ci->final_clip_owner, p_material_owner, true, p_canvas_cull_mask);
+ _cull_canvas_item(child_items[i], final_xform, p_clip_rect, modulate, p_z, r_z_list, r_z_last_list, (Item *)ci->final_clip_owner, p_material_owner, true, p_canvas_cull_mask, repeat_size, repeat_times);
}
}
}
@@ -374,38 +395,7 @@ void RendererCanvasCull::render_canvas(RID p_render_target, Canvas *p_canvas, co
int l = p_canvas->child_items.size();
Canvas::ChildItem *ci = p_canvas->child_items.ptrw();
- bool has_mirror = false;
- for (int i = 0; i < l; i++) {
- if (ci[i].mirror.x || ci[i].mirror.y) {
- has_mirror = true;
- break;
- }
- }
-
- if (!has_mirror) {
- _render_canvas_item_tree(p_render_target, ci, l, nullptr, p_transform, p_clip_rect, p_canvas->modulate, p_lights, p_directional_lights, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel, canvas_cull_mask, r_render_info);
-
- } else {
- //used for parallaxlayer mirroring
- for (int i = 0; i < l; i++) {
- const Canvas::ChildItem &ci2 = p_canvas->child_items[i];
- _render_canvas_item_tree(p_render_target, nullptr, 0, ci2.item, p_transform, p_clip_rect, p_canvas->modulate, p_lights, p_directional_lights, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel, canvas_cull_mask, r_render_info);
-
- //mirroring (useful for scrolling backgrounds)
- if (ci2.mirror.x != 0) {
- Transform2D xform2 = p_transform * Transform2D(0, Vector2(ci2.mirror.x, 0));
- _render_canvas_item_tree(p_render_target, nullptr, 0, ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights, p_directional_lights, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel, canvas_cull_mask, r_render_info);
- }
- if (ci2.mirror.y != 0) {
- Transform2D xform2 = p_transform * Transform2D(0, Vector2(0, ci2.mirror.y));
- _render_canvas_item_tree(p_render_target, nullptr, 0, ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights, p_directional_lights, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel, canvas_cull_mask, r_render_info);
- }
- if (ci2.mirror.y != 0 && ci2.mirror.x != 0) {
- Transform2D xform2 = p_transform * Transform2D(0, ci2.mirror);
- _render_canvas_item_tree(p_render_target, nullptr, 0, ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights, p_directional_lights, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel, canvas_cull_mask, r_render_info);
- }
- }
- }
+ _render_canvas_item_tree(p_render_target, ci, l, p_transform, p_clip_rect, p_canvas->modulate, p_lights, p_directional_lights, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel, canvas_cull_mask, r_render_info);
RENDER_TIMESTAMP("< Render Canvas");
}
@@ -432,6 +422,15 @@ void RendererCanvasCull::canvas_set_item_mirroring(RID p_canvas, RID p_item, con
canvas->child_items.write[idx].mirror = p_mirroring;
}
+void RendererCanvasCull::canvas_set_item_repeat(RID p_item, const Point2 &p_repeat_size, int p_repeat_times) {
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
+ ERR_FAIL_NULL(canvas_item);
+
+ canvas_item->repeat_source = true;
+ canvas_item->repeat_size = p_repeat_size;
+ canvas_item->repeat_times = p_repeat_times;
+}
+
void RendererCanvasCull::canvas_set_modulate(RID p_canvas, const Color &p_color) {
Canvas *canvas = canvas_owner.get_or_null(p_canvas);
ERR_FAIL_NULL(canvas);
@@ -521,7 +520,16 @@ void RendererCanvasCull::canvas_item_set_transform(RID p_item, const Transform2D
Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_NULL(canvas_item);
- canvas_item->xform = p_transform;
+ if (_interpolation_data.interpolation_enabled && canvas_item->interpolated) {
+ if (!canvas_item->on_interpolate_transform_list) {
+ _interpolation_data.canvas_item_transform_update_list_curr->push_back(p_item);
+ canvas_item->on_interpolate_transform_list = true;
+ } else {
+ DEV_ASSERT(_interpolation_data.canvas_item_transform_update_list_curr->size() > 0);
+ }
+ }
+
+ canvas_item->xform_curr = p_transform;
}
void RendererCanvasCull::canvas_item_set_visibility_layer(RID p_item, uint32_t p_visibility_layer) {
@@ -1631,6 +1639,26 @@ bool RendererCanvasCull::canvas_item_get_debug_redraw() const {
return debug_redraw;
}
+void RendererCanvasCull::canvas_item_set_interpolated(RID p_item, bool p_interpolated) {
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
+ ERR_FAIL_NULL(canvas_item);
+ canvas_item->interpolated = p_interpolated;
+}
+
+void RendererCanvasCull::canvas_item_reset_physics_interpolation(RID p_item) {
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
+ ERR_FAIL_NULL(canvas_item);
+ canvas_item->xform_prev = canvas_item->xform_curr;
+}
+
+// Useful especially for origin shifting.
+void RendererCanvasCull::canvas_item_transform_physics_interpolation(RID p_item, const Transform2D &p_transform) {
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
+ ERR_FAIL_NULL(canvas_item);
+ canvas_item->xform_prev = p_transform * canvas_item->xform_prev;
+ canvas_item->xform_curr = p_transform * canvas_item->xform_curr;
+}
+
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.get_or_null(p_item);
ERR_FAIL_NULL(canvas_item);
@@ -1729,7 +1757,16 @@ void RendererCanvasCull::canvas_light_set_transform(RID p_light, const Transform
RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);
ERR_FAIL_NULL(clight);
- clight->xform = p_transform;
+ if (_interpolation_data.interpolation_enabled && clight->interpolated) {
+ if (!clight->on_interpolate_transform_list) {
+ _interpolation_data.canvas_light_transform_update_list_curr->push_back(p_light);
+ clight->on_interpolate_transform_list = true;
+ } else {
+ DEV_ASSERT(_interpolation_data.canvas_light_transform_update_list_curr->size() > 0);
+ }
+ }
+
+ clight->xform_curr = p_transform;
}
void RendererCanvasCull::canvas_light_set_texture(RID p_light, RID p_texture) {
@@ -1848,6 +1885,25 @@ void RendererCanvasCull::canvas_light_set_shadow_smooth(RID p_light, float p_smo
clight->shadow_smooth = p_smooth;
}
+void RendererCanvasCull::canvas_light_set_interpolated(RID p_light, bool p_interpolated) {
+ RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);
+ ERR_FAIL_NULL(clight);
+ clight->interpolated = p_interpolated;
+}
+
+void RendererCanvasCull::canvas_light_reset_physics_interpolation(RID p_light) {
+ RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);
+ ERR_FAIL_NULL(clight);
+ clight->xform_prev = clight->xform_curr;
+}
+
+void RendererCanvasCull::canvas_light_transform_physics_interpolation(RID p_light, const Transform2D &p_transform) {
+ RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);
+ ERR_FAIL_NULL(clight);
+ clight->xform_prev = p_transform * clight->xform_prev;
+ clight->xform_curr = p_transform * clight->xform_curr;
+}
+
RID RendererCanvasCull::canvas_light_occluder_allocate() {
return canvas_light_occluder_owner.allocate_rid();
}
@@ -1920,7 +1976,16 @@ void RendererCanvasCull::canvas_light_occluder_set_transform(RID p_occluder, con
RendererCanvasRender::LightOccluderInstance *occluder = canvas_light_occluder_owner.get_or_null(p_occluder);
ERR_FAIL_NULL(occluder);
- occluder->xform = p_xform;
+ if (_interpolation_data.interpolation_enabled && occluder->interpolated) {
+ if (!occluder->on_interpolate_transform_list) {
+ _interpolation_data.canvas_light_occluder_transform_update_list_curr->push_back(p_occluder);
+ occluder->on_interpolate_transform_list = true;
+ } else {
+ DEV_ASSERT(_interpolation_data.canvas_light_occluder_transform_update_list_curr->size() > 0);
+ }
+ }
+
+ occluder->xform_curr = p_xform;
}
void RendererCanvasCull::canvas_light_occluder_set_light_mask(RID p_occluder, int p_mask) {
@@ -1930,6 +1995,25 @@ void RendererCanvasCull::canvas_light_occluder_set_light_mask(RID p_occluder, in
occluder->light_mask = p_mask;
}
+void RendererCanvasCull::canvas_light_occluder_set_interpolated(RID p_occluder, bool p_interpolated) {
+ RendererCanvasRender::LightOccluderInstance *occluder = canvas_light_occluder_owner.get_or_null(p_occluder);
+ ERR_FAIL_NULL(occluder);
+ occluder->interpolated = p_interpolated;
+}
+
+void RendererCanvasCull::canvas_light_occluder_reset_physics_interpolation(RID p_occluder) {
+ RendererCanvasRender::LightOccluderInstance *occluder = canvas_light_occluder_owner.get_or_null(p_occluder);
+ ERR_FAIL_NULL(occluder);
+ occluder->xform_prev = occluder->xform_curr;
+}
+
+void RendererCanvasCull::canvas_light_occluder_transform_physics_interpolation(RID p_occluder, const Transform2D &p_transform) {
+ RendererCanvasRender::LightOccluderInstance *occluder = canvas_light_occluder_owner.get_or_null(p_occluder);
+ ERR_FAIL_NULL(occluder);
+ occluder->xform_prev = p_transform * occluder->xform_prev;
+ occluder->xform_curr = p_transform * occluder->xform_curr;
+}
+
RID RendererCanvasCull::canvas_occluder_polygon_allocate() {
return canvas_light_occluder_polygon_owner.allocate_rid();
}
@@ -2084,6 +2168,7 @@ bool RendererCanvasCull::free(RID p_rid) {
} else if (canvas_item_owner.owns(p_rid)) {
Item *canvas_item = canvas_item_owner.get_or_null(p_rid);
ERR_FAIL_NULL_V(canvas_item, true);
+ _interpolation_data.notify_free_canvas_item(p_rid, *canvas_item);
if (canvas_item->parent.is_valid()) {
if (canvas_owner.owns(canvas_item->parent)) {
@@ -2123,6 +2208,7 @@ bool RendererCanvasCull::free(RID p_rid) {
} else if (canvas_light_owner.owns(p_rid)) {
RendererCanvasRender::Light *canvas_light = canvas_light_owner.get_or_null(p_rid);
ERR_FAIL_NULL_V(canvas_light, true);
+ _interpolation_data.notify_free_canvas_light(p_rid, *canvas_light);
if (canvas_light->canvas.is_valid()) {
Canvas *canvas = canvas_owner.get_or_null(canvas_light->canvas);
@@ -2138,6 +2224,7 @@ bool RendererCanvasCull::free(RID p_rid) {
} else if (canvas_light_occluder_owner.owns(p_rid)) {
RendererCanvasRender::LightOccluderInstance *occluder = canvas_light_occluder_owner.get_or_null(p_rid);
ERR_FAIL_NULL_V(occluder, true);
+ _interpolation_data.notify_free_canvas_light_occluder(p_rid, *occluder);
if (occluder->polygon.is_valid()) {
LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get_or_null(occluder->polygon);
@@ -2171,7 +2258,7 @@ bool RendererCanvasCull::free(RID p_rid) {
return true;
}
-template <class T>
+template <typename T>
void RendererCanvasCull::_free_rids(T &p_owner, const char *p_type) {
List<RID> owned;
p_owner.get_owned_list(&owned);
@@ -2195,6 +2282,81 @@ void RendererCanvasCull::finalize() {
_free_rids(canvas_light_occluder_polygon_owner, "CanvasLightOccluderPolygon");
}
+void RendererCanvasCull::tick() {
+ if (_interpolation_data.interpolation_enabled) {
+ update_interpolation_tick(true);
+ }
+}
+
+void RendererCanvasCull::update_interpolation_tick(bool p_process) {
+#define GODOT_UPDATE_INTERPOLATION_TICK(m_list_prev, m_list_curr, m_type, m_owner_list) \
+ /* Detect any that were on the previous transform list that are no longer active. */ \
+ for (unsigned int n = 0; n < _interpolation_data.m_list_prev->size(); n++) { \
+ const RID &rid = (*_interpolation_data.m_list_prev)[n]; \
+ m_type *item = m_owner_list.get_or_null(rid); \
+ /* no longer active? (either the instance deleted or no longer being transformed) */ \
+ if (item && !item->on_interpolate_transform_list) { \
+ item->xform_prev = item->xform_curr; \
+ } \
+ } \
+ /* and now for any in the transform list (being actively interpolated), */ \
+ /* keep the previous transform value up to date and ready for next tick */ \
+ if (p_process) { \
+ for (unsigned int n = 0; n < _interpolation_data.m_list_curr->size(); n++) { \
+ const RID &rid = (*_interpolation_data.m_list_curr)[n]; \
+ m_type *item = m_owner_list.get_or_null(rid); \
+ if (item) { \
+ item->xform_prev = item->xform_curr; \
+ item->on_interpolate_transform_list = false; \
+ } \
+ } \
+ } \
+ SWAP(_interpolation_data.m_list_curr, _interpolation_data.m_list_prev); \
+ _interpolation_data.m_list_curr->clear();
+
+ GODOT_UPDATE_INTERPOLATION_TICK(canvas_item_transform_update_list_prev, canvas_item_transform_update_list_curr, Item, canvas_item_owner);
+ GODOT_UPDATE_INTERPOLATION_TICK(canvas_light_transform_update_list_prev, canvas_light_transform_update_list_curr, RendererCanvasRender::Light, canvas_light_owner);
+ GODOT_UPDATE_INTERPOLATION_TICK(canvas_light_occluder_transform_update_list_prev, canvas_light_occluder_transform_update_list_curr, RendererCanvasRender::LightOccluderInstance, canvas_light_occluder_owner);
+
+#undef GODOT_UPDATE_INTERPOLATION_TICK
+}
+
+void RendererCanvasCull::InterpolationData::notify_free_canvas_item(RID p_rid, RendererCanvasCull::Item &r_canvas_item) {
+ r_canvas_item.on_interpolate_transform_list = false;
+
+ if (!interpolation_enabled) {
+ return;
+ }
+
+ // If the instance was on any of the lists, remove.
+ canvas_item_transform_update_list_curr->erase_multiple_unordered(p_rid);
+ canvas_item_transform_update_list_prev->erase_multiple_unordered(p_rid);
+}
+
+void RendererCanvasCull::InterpolationData::notify_free_canvas_light(RID p_rid, RendererCanvasRender::Light &r_canvas_light) {
+ r_canvas_light.on_interpolate_transform_list = false;
+
+ if (!interpolation_enabled) {
+ return;
+ }
+
+ // If the instance was on any of the lists, remove.
+ canvas_light_transform_update_list_curr->erase_multiple_unordered(p_rid);
+ canvas_light_transform_update_list_prev->erase_multiple_unordered(p_rid);
+}
+
+void RendererCanvasCull::InterpolationData::notify_free_canvas_light_occluder(RID p_rid, RendererCanvasRender::LightOccluderInstance &r_canvas_light_occluder) {
+ r_canvas_light_occluder.on_interpolate_transform_list = false;
+
+ if (!interpolation_enabled) {
+ return;
+ }
+
+ // If the instance was on any of the lists, remove.
+ canvas_light_occluder_transform_update_list_curr->erase_multiple_unordered(p_rid);
+ canvas_light_occluder_transform_update_list_prev->erase_multiple_unordered(p_rid);
+}
+
RendererCanvasCull::RendererCanvasCull() {
z_list = (RendererCanvasRender::Item **)memalloc(z_range * sizeof(RendererCanvasRender::Item *));
z_last_list = (RendererCanvasRender::Item **)memalloc(z_range * sizeof(RendererCanvasRender::Item *));
diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h
index 00f69766b1..961506ca28 100644
--- a/servers/rendering/renderer_canvas_cull.h
+++ b/servers/rendering/renderer_canvas_cull.h
@@ -170,7 +170,7 @@ public:
RID_Owner<Item, true> canvas_item_owner;
RID_Owner<RendererCanvasRender::Light, true> canvas_light_owner;
- template <class T>
+ template <typename T>
void _free_rids(T &p_owner, const char *p_type);
bool disable_scale;
@@ -187,8 +187,8 @@ public:
_FORCE_INLINE_ void _attach_canvas_item_for_draw(Item *ci, Item *p_canvas_clip, RendererCanvasRender::Item **r_z_list, RendererCanvasRender::Item **r_z_last_list, const Transform2D &p_transform, const Rect2 &p_clip_rect, Rect2 p_global_rect, const Color &modulate, int p_z, RendererCanvasCull::Item *p_material_owner, bool p_use_canvas_group, RendererCanvasRender::Item *r_canvas_group_from);
private:
- void _render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, uint32_t p_canvas_cull_mask, RenderingMethod::RenderInfo *r_render_info = nullptr);
- void _cull_canvas_item(Item *p_canvas_item, const Transform2D &p_parent_xform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RendererCanvasRender::Item **r_z_list, RendererCanvasRender::Item **r_z_last_list, Item *p_canvas_clip, Item *p_material_owner, bool p_allow_y_sort, uint32_t p_canvas_cull_mask);
+ void _render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, uint32_t p_canvas_cull_mask, RenderingMethod::RenderInfo *r_render_info = nullptr);
+ void _cull_canvas_item(Item *p_canvas_item, const Transform2D &p_parent_xform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RendererCanvasRender::Item **r_z_list, RendererCanvasRender::Item **r_z_last_list, Item *p_canvas_clip, Item *p_material_owner, bool p_allow_y_sort, uint32_t p_canvas_cull_mask, const Point2 &p_repeat_size, int p_repeat_times);
static constexpr int z_range = RS::CANVAS_ITEM_Z_MAX - RS::CANVAS_ITEM_Z_MIN + 1;
@@ -204,6 +204,7 @@ public:
void canvas_initialize(RID p_rid);
void canvas_set_item_mirroring(RID p_canvas, RID p_item, const Point2 &p_mirroring);
+ void canvas_set_item_repeat(RID p_item, const Point2 &p_repeat_size, int p_repeat_times);
void canvas_set_modulate(RID p_canvas, const Color &p_color);
void canvas_set_parent(RID p_canvas, RID p_parent, float p_scale);
void canvas_set_disable_scale(bool p_disable);
@@ -270,6 +271,10 @@ public:
void canvas_item_set_debug_redraw(bool p_enabled);
bool canvas_item_get_debug_redraw() const;
+ void canvas_item_set_interpolated(RID p_item, bool p_interpolated);
+ void canvas_item_reset_physics_interpolation(RID p_item);
+ void canvas_item_transform_physics_interpolation(RID p_item, const Transform2D &p_transform);
+
RID canvas_light_allocate();
void canvas_light_initialize(RID p_rid);
@@ -296,6 +301,10 @@ public:
void canvas_light_set_shadow_color(RID p_light, const Color &p_color);
void canvas_light_set_shadow_smooth(RID p_light, float p_smooth);
+ void canvas_light_set_interpolated(RID p_light, bool p_interpolated);
+ void canvas_light_reset_physics_interpolation(RID p_light);
+ void canvas_light_transform_physics_interpolation(RID p_light, const Transform2D &p_transform);
+
RID canvas_light_occluder_allocate();
void canvas_light_occluder_initialize(RID p_rid);
@@ -306,6 +315,10 @@ public:
void canvas_light_occluder_set_transform(RID p_occluder, const Transform2D &p_xform);
void canvas_light_occluder_set_light_mask(RID p_occluder, int p_mask);
+ void canvas_light_occluder_set_interpolated(RID p_occluder, bool p_interpolated);
+ void canvas_light_occluder_reset_physics_interpolation(RID p_occluder);
+ void canvas_light_occluder_transform_physics_interpolation(RID p_occluder, const Transform2D &p_transform);
+
RID canvas_occluder_polygon_allocate();
void canvas_occluder_polygon_initialize(RID p_rid);
@@ -335,6 +348,32 @@ public:
void finalize();
+ /* INTERPOLATION */
+
+ void tick();
+ void update_interpolation_tick(bool p_process = true);
+ void set_physics_interpolation_enabled(bool p_enabled) { _interpolation_data.interpolation_enabled = p_enabled; }
+
+ struct InterpolationData {
+ void notify_free_canvas_item(RID p_rid, RendererCanvasCull::Item &r_canvas_item);
+ void notify_free_canvas_light(RID p_rid, RendererCanvasRender::Light &r_canvas_light);
+ void notify_free_canvas_light_occluder(RID p_rid, RendererCanvasRender::LightOccluderInstance &r_canvas_light_occluder);
+
+ LocalVector<RID> canvas_item_transform_update_lists[2];
+ LocalVector<RID> *canvas_item_transform_update_list_curr = &canvas_item_transform_update_lists[0];
+ LocalVector<RID> *canvas_item_transform_update_list_prev = &canvas_item_transform_update_lists[1];
+
+ LocalVector<RID> canvas_light_transform_update_lists[2];
+ LocalVector<RID> *canvas_light_transform_update_list_curr = &canvas_light_transform_update_lists[0];
+ LocalVector<RID> *canvas_light_transform_update_list_prev = &canvas_light_transform_update_lists[1];
+
+ LocalVector<RID> canvas_light_occluder_transform_update_lists[2];
+ LocalVector<RID> *canvas_light_occluder_transform_update_list_curr = &canvas_light_occluder_transform_update_lists[0];
+ LocalVector<RID> *canvas_light_occluder_transform_update_list_prev = &canvas_light_occluder_transform_update_lists[1];
+
+ bool interpolation_enabled = false;
+ } _interpolation_data;
+
RendererCanvasCull();
~RendererCanvasCull();
};
diff --git a/servers/rendering/renderer_canvas_render.h b/servers/rendering/renderer_canvas_render.h
index 3b78df5fab..4a56548932 100644
--- a/servers/rendering/renderer_canvas_render.h
+++ b/servers/rendering/renderer_canvas_render.h
@@ -51,9 +51,12 @@ public:
};
struct Light {
- bool enabled;
+ bool enabled : 1;
+ bool on_interpolate_transform_list : 1;
+ bool interpolated : 1;
Color color;
- Transform2D xform;
+ Transform2D xform_curr;
+ Transform2D xform_prev;
float height;
float energy;
float scale;
@@ -97,6 +100,8 @@ public:
Light() {
version = 0;
enabled = true;
+ on_interpolate_transform_list = false;
+ interpolated = true;
color = Color(1, 1, 1);
shadow_color = Color(0, 0, 0, 0);
height = 0;
@@ -307,11 +312,17 @@ public:
Rect2 rect;
};
- Transform2D xform;
- bool clip;
- bool visible;
- bool behind;
- bool update_when_visible;
+ // For interpolation we store the current local xform,
+ // and the previous xform from the previous tick.
+ Transform2D xform_curr;
+ Transform2D xform_prev;
+
+ bool clip : 1;
+ bool visible : 1;
+ bool behind : 1;
+ bool update_when_visible : 1;
+ bool on_interpolate_transform_list : 1;
+ bool interpolated : 1;
struct CanvasGroup {
RS::CanvasGroupMode mode;
@@ -350,6 +361,9 @@ public:
ViewportRender *vp_render = nullptr;
bool distance_field;
bool light_masked;
+ bool repeat_source;
+ Point2 repeat_size;
+ int repeat_times = 1;
Rect2 global_rect_cache;
@@ -363,7 +377,7 @@ public:
mutable double debug_redraw_time = 0;
#endif
- template <class T>
+ template <typename T>
T *alloc_command() {
T *command = nullptr;
if (commands == nullptr) {
@@ -468,6 +482,9 @@ public:
z_final = 0;
texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT;
texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT;
+ repeat_source = false;
+ on_interpolate_transform_list = false;
+ interpolated = true;
}
virtual ~Item() {
clear();
@@ -483,12 +500,15 @@ public:
virtual void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_list, const Transform2D &p_canvas_transform, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used, RenderingMethod::RenderInfo *r_render_info = nullptr) = 0;
struct LightOccluderInstance {
- bool enabled;
+ bool enabled : 1;
+ bool on_interpolate_transform_list : 1;
+ bool interpolated : 1;
RID canvas;
RID polygon;
RID occluder;
Rect2 aabb_cache;
- Transform2D xform;
+ Transform2D xform_curr;
+ Transform2D xform_prev;
Transform2D xform_cache;
int light_mask;
bool sdf_collision;
@@ -498,6 +518,8 @@ public:
LightOccluderInstance() {
enabled = true;
+ on_interpolate_transform_list = false;
+ interpolated = false;
sdf_collision = false;
next = nullptr;
light_mask = 1;
diff --git a/servers/rendering/renderer_compositor.cpp b/servers/rendering/renderer_compositor.cpp
index c36da51e50..d364de5633 100644
--- a/servers/rendering/renderer_compositor.cpp
+++ b/servers/rendering/renderer_compositor.cpp
@@ -49,9 +49,11 @@ bool RendererCompositor::is_xr_enabled() const {
RendererCompositor::RendererCompositor() {
singleton = this;
+#ifndef _3D_DISABLED
if (XRServer::get_xr_mode() == XRServer::XRMODE_DEFAULT) {
xr_enabled = GLOBAL_GET("xr/shaders/enabled");
} else {
xr_enabled = XRServer::get_xr_mode() == XRServer::XRMODE_ON;
}
+#endif // _3D_DISABLED
}
diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.cpp b/servers/rendering/renderer_rd/cluster_builder_rd.cpp
index e661fd9217..41df6107a8 100644
--- a/servers/rendering/renderer_rd/cluster_builder_rd.cpp
+++ b/servers/rendering/renderer_rd/cluster_builder_rd.cpp
@@ -62,15 +62,17 @@ ClusterBuilderSharedDataRD::ClusterBuilderSharedDataRD() {
defines = "\n#define USE_ATTACHMENT\n";
}
+ RD::PipelineRasterizationState rasterization_state;
+ rasterization_state.enable_depth_clamp = true;
Vector<String> versions;
versions.push_back("");
cluster_render.cluster_render_shader.initialize(versions, defines);
cluster_render.shader_version = cluster_render.cluster_render_shader.version_create();
cluster_render.shader = cluster_render.cluster_render_shader.version_get_shader(cluster_render.shader_version, 0);
- cluster_render.shader_pipelines[ClusterRender::PIPELINE_NORMAL] = RD::get_singleton()->render_pipeline_create(cluster_render.shader, fb_format, vertex_format, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0);
+ cluster_render.shader_pipelines[ClusterRender::PIPELINE_NORMAL] = RD::get_singleton()->render_pipeline_create(cluster_render.shader, fb_format, vertex_format, RD::RENDER_PRIMITIVE_TRIANGLES, rasterization_state, RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0);
RD::PipelineMultisampleState ms;
ms.sample_count = RD::TEXTURE_SAMPLES_4;
- cluster_render.shader_pipelines[ClusterRender::PIPELINE_MSAA] = RD::get_singleton()->render_pipeline_create(cluster_render.shader, fb_format, vertex_format, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), ms, RD::PipelineDepthStencilState(), blend_state, 0);
+ cluster_render.shader_pipelines[ClusterRender::PIPELINE_MSAA] = RD::get_singleton()->render_pipeline_create(cluster_render.shader, fb_format, vertex_format, RD::RENDER_PRIMITIVE_TRIANGLES, rasterization_state, ms, RD::PipelineDepthStencilState(), blend_state, 0);
}
{
Vector<String> versions;
diff --git a/servers/rendering/renderer_rd/effects/copy_effects.cpp b/servers/rendering/renderer_rd/effects/copy_effects.cpp
index fd6409d6bf..1568867663 100644
--- a/servers/rendering/renderer_rd/effects/copy_effects.cpp
+++ b/servers/rendering/renderer_rd/effects/copy_effects.cpp
@@ -107,8 +107,8 @@ CopyEffects::CopyEffects(bool p_prefer_raster_effects) {
copy_modes.push_back("\n#define MODE_PANORAMA_TO_DP\n"); // COPY_TO_FB_COPY_PANORAMA_TO_DP
copy_modes.push_back("\n#define MODE_TWO_SOURCES\n"); // COPY_TO_FB_COPY2
copy_modes.push_back("\n#define MODE_SET_COLOR\n"); // COPY_TO_FB_SET_COLOR
- copy_modes.push_back("\n#define MULTIVIEW\n"); // COPY_TO_FB_MULTIVIEW
- copy_modes.push_back("\n#define MULTIVIEW\n#define MODE_TWO_SOURCES\n"); // COPY_TO_FB_MULTIVIEW_WITH_DEPTH
+ copy_modes.push_back("\n#define USE_MULTIVIEW\n"); // COPY_TO_FB_MULTIVIEW
+ copy_modes.push_back("\n#define USE_MULTIVIEW\n#define MODE_TWO_SOURCES\n"); // COPY_TO_FB_MULTIVIEW_WITH_DEPTH
copy_to_fb.shader.initialize(copy_modes);
@@ -583,7 +583,7 @@ void CopyEffects::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffe
RID shader = copy_to_fb.shader.version_get_shader(copy_to_fb.shader_version, mode);
ERR_FAIL_COND(shader.is_null());
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, p_rect);
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 0.0, 0, p_rect);
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_to_fb.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
if (p_secondary.is_valid()) {
@@ -982,7 +982,7 @@ void CopyEffects::set_color_raster(RID p_dest_texture, const Color &p_color, con
RID shader = copy_to_fb.shader.version_get_shader(copy_to_fb.shader_version, mode);
ERR_FAIL_COND(shader.is_null());
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, p_region);
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 0.0, 0, p_region);
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_to_fb.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(dest_framebuffer)));
RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
RD::get_singleton()->draw_list_set_push_constant(draw_list, &copy_to_fb.push_constant, sizeof(CopyToFbPushConstant));
diff --git a/servers/rendering/renderer_rd/effects/debug_effects.cpp b/servers/rendering/renderer_rd/effects/debug_effects.cpp
index a57a65fd5a..017ad41fdc 100644
--- a/servers/rendering/renderer_rd/effects/debug_effects.cpp
+++ b/servers/rendering/renderer_rd/effects/debug_effects.cpp
@@ -282,7 +282,7 @@ void DebugEffects::draw_shadow_frustum(RID p_light, const Projection &p_cam_proj
// And draw our frustum.
RD::FramebufferFormatID fb_format_id = RD::get_singleton()->framebuffer_get_format(p_dest_fb);
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_fb, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, rect);
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_fb, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 0.0, 0, rect);
RID pipeline = shadow_frustum.pipelines[SFP_TRANSPARENT].get_render_pipeline(frustum.vertex_format, fb_format_id);
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, pipeline);
@@ -326,7 +326,7 @@ void DebugEffects::draw_shadow_frustum(RID p_light, const Projection &p_cam_proj
rect.size.x *= atlas_rect_norm.size.x;
rect.size.y *= atlas_rect_norm.size.y;
- draw_list = RD::get_singleton()->draw_list_begin(p_dest_fb, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, rect);
+ draw_list = RD::get_singleton()->draw_list_begin(p_dest_fb, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 0.0, 0, rect);
pipeline = shadow_frustum.pipelines[SFP_TRANSPARENT].get_render_pipeline(frustum.vertex_format, fb_format_id);
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, pipeline);
diff --git a/servers/rendering/renderer_rd/effects/fsr2.cpp b/servers/rendering/renderer_rd/effects/fsr2.cpp
index bebbf51d51..925352a7d1 100644
--- a/servers/rendering/renderer_rd/effects/fsr2.cpp
+++ b/servers/rendering/renderer_rd/effects/fsr2.cpp
@@ -527,6 +527,7 @@ FSR2Effect::FSR2Effect() {
"\n#define FFX_GLSL 1\n"
"\n#define FFX_FSR2_OPTION_LOW_RESOLUTION_MOTION_VECTORS 1\n"
"\n#define FFX_FSR2_OPTION_HDR_COLOR_INPUT 1\n"
+ "\n#define FFX_FSR2_OPTION_INVERTED_DEPTH 1\n"
"\n#define FFX_FSR2_OPTION_GODOT_REACTIVE_MASK_CLAMP 1\n"
"\n#define FFX_FSR2_OPTION_GODOT_DERIVE_INVALID_MOTION_VECTORS 1\n";
@@ -808,7 +809,7 @@ FSR2Effect::~FSR2Effect() {
FSR2Context *FSR2Effect::create_context(Size2i p_internal_size, Size2i p_target_size) {
FSR2Context *context = memnew(RendererRD::FSR2Context);
- context->fsr_desc.flags = FFX_FSR2_ENABLE_HIGH_DYNAMIC_RANGE;
+ context->fsr_desc.flags = FFX_FSR2_ENABLE_HIGH_DYNAMIC_RANGE | FFX_FSR2_ENABLE_DEPTH_INVERTED;
context->fsr_desc.maxRenderSize.width = p_internal_size.x;
context->fsr_desc.maxRenderSize.height = p_internal_size.y;
context->fsr_desc.displaySize.width = p_target_size.x;
diff --git a/servers/rendering/renderer_rd/effects/ss_effects.cpp b/servers/rendering/renderer_rd/effects/ss_effects.cpp
index bdd687d9f4..3db82c8fbd 100644
--- a/servers/rendering/renderer_rd/effects/ss_effects.cpp
+++ b/servers/rendering/renderer_rd/effects/ss_effects.cpp
@@ -483,8 +483,12 @@ void SSEffects::downsample_depth(Ref<RenderSceneBuffersRD> p_render_buffers, uin
downsample_uniform_set = uniform_set_cache->get_cache_vec(shader, 2, u_depths);
}
- float depth_linearize_mul = -p_projection.columns[3][2] * 0.5;
- float depth_linearize_add = p_projection.columns[2][2];
+ Projection correction;
+ correction.set_depth_correction(false);
+ Projection temp = correction * p_projection;
+
+ float depth_linearize_mul = -temp.columns[3][2];
+ float depth_linearize_add = temp.columns[2][2];
if (depth_linearize_mul * depth_linearize_add < 0) {
depth_linearize_add = -depth_linearize_add;
}
diff --git a/servers/rendering/renderer_rd/effects/tone_mapper.cpp b/servers/rendering/renderer_rd/effects/tone_mapper.cpp
index ee0b6adb4d..e943071f0e 100644
--- a/servers/rendering/renderer_rd/effects/tone_mapper.cpp
+++ b/servers/rendering/renderer_rd/effects/tone_mapper.cpp
@@ -47,12 +47,12 @@ ToneMapper::ToneMapper() {
tonemap_modes.push_back("\n#define SUBPASS\n#define USE_1D_LUT\n");
// multiview versions of our shaders
- tonemap_modes.push_back("\n#define MULTIVIEW\n");
- tonemap_modes.push_back("\n#define MULTIVIEW\n#define USE_GLOW_FILTER_BICUBIC\n");
- tonemap_modes.push_back("\n#define MULTIVIEW\n#define USE_1D_LUT\n");
- tonemap_modes.push_back("\n#define MULTIVIEW\n#define USE_GLOW_FILTER_BICUBIC\n#define USE_1D_LUT\n");
- tonemap_modes.push_back("\n#define MULTIVIEW\n#define SUBPASS\n");
- tonemap_modes.push_back("\n#define MULTIVIEW\n#define SUBPASS\n#define USE_1D_LUT\n");
+ tonemap_modes.push_back("\n#define USE_MULTIVIEW\n");
+ tonemap_modes.push_back("\n#define USE_MULTIVIEW\n#define USE_GLOW_FILTER_BICUBIC\n");
+ tonemap_modes.push_back("\n#define USE_MULTIVIEW\n#define USE_1D_LUT\n");
+ tonemap_modes.push_back("\n#define USE_MULTIVIEW\n#define USE_GLOW_FILTER_BICUBIC\n#define USE_1D_LUT\n");
+ tonemap_modes.push_back("\n#define USE_MULTIVIEW\n#define SUBPASS\n");
+ tonemap_modes.push_back("\n#define USE_MULTIVIEW\n#define SUBPASS\n#define USE_1D_LUT\n");
tonemap.shader.initialize(tonemap_modes);
@@ -130,7 +130,7 @@ void ToneMapper::tonemapper(RID p_source_color, RID p_dst_framebuffer, const Ton
tonemap.push_constant.flags |= p_settings.convert_to_srgb ? TONEMAP_FLAG_CONVERT_TO_SRGB : 0;
if (p_settings.view_count > 1) {
- // Use MULTIVIEW versions
+ // Use USE_MULTIVIEW versions
mode += 6;
}
@@ -196,7 +196,7 @@ void ToneMapper::tonemapper(RD::DrawListID p_subpass_draw_list, RID p_source_col
int mode = p_settings.use_1d_color_correction ? TONEMAP_MODE_SUBPASS_1D_LUT : TONEMAP_MODE_SUBPASS;
if (p_settings.view_count > 1) {
- // Use MULTIVIEW versions
+ // Use USE_MULTIVIEW versions
mode += 6;
}
diff --git a/servers/rendering/renderer_rd/effects/vrs.cpp b/servers/rendering/renderer_rd/effects/vrs.cpp
index 41a6b2d622..30c318fb9a 100644
--- a/servers/rendering/renderer_rd/effects/vrs.cpp
+++ b/servers/rendering/renderer_rd/effects/vrs.cpp
@@ -32,7 +32,10 @@
#include "../renderer_compositor_rd.h"
#include "../storage_rd/texture_storage.h"
#include "../uniform_set_cache_rd.h"
+
+#ifndef _3D_DISABLED
#include "servers/xr_server.h"
+#endif // _3D_DISABLED
using namespace RendererRD;
@@ -40,7 +43,7 @@ VRS::VRS() {
{
Vector<String> vrs_modes;
vrs_modes.push_back("\n"); // VRS_DEFAULT
- vrs_modes.push_back("\n#define MULTIVIEW\n"); // VRS_MULTIVIEW
+ vrs_modes.push_back("\n#define USE_MULTIVIEW\n"); // VRS_MULTIVIEW
vrs_shader.shader.initialize(vrs_modes);
@@ -124,6 +127,7 @@ void VRS::update_vrs_texture(RID p_vrs_fb, RID p_render_target) {
copy_vrs(rd_texture, p_vrs_fb, layers > 1);
}
}
+#ifndef _3D_DISABLED
} else if (vrs_mode == RS::VIEWPORT_VRS_XR) {
Ref<XRInterface> interface = XRServer::get_singleton()->get_primary_interface();
if (interface.is_valid()) {
@@ -138,6 +142,7 @@ void VRS::update_vrs_texture(RID p_vrs_fb, RID p_render_target) {
}
}
}
+#endif // _3D_DISABLED
}
RD::get_singleton()->draw_command_end_label();
diff --git a/servers/rendering/renderer_rd/environment/fog.cpp b/servers/rendering/renderer_rd/environment/fog.cpp
index 78ab6f3650..48537a97d9 100644
--- a/servers/rendering/renderer_rd/environment/fog.cpp
+++ b/servers/rendering/renderer_rd/environment/fog.cpp
@@ -509,9 +509,7 @@ Vector3i Fog::_point_get_position_in_froxel_volume(const Vector3 &p_point, float
fog_position.z = Math::pow(float(fog_position.z), float(1.0 / volumetric_fog_detail_spread));
fog_position = fog_position * fog_size - Vector3(0.5, 0.5, 0.5);
- fog_position.x = CLAMP(fog_position.x, 0.0, fog_size.x);
- fog_position.y = CLAMP(fog_position.y, 0.0, fog_size.y);
- fog_position.z = CLAMP(fog_position.z, 0.0, fog_size.z);
+ fog_position = fog_position.clamp(Vector3(), fog_size);
return Vector3i(fog_position);
}
@@ -680,8 +678,8 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
max = Vector3i(1, 1, 1);
for (int j = 0; j < 8; j++) {
- min = Vector3i(MIN(min.x, points[j].x), MIN(min.y, points[j].y), MIN(min.z, points[j].z));
- max = Vector3i(MAX(max.x, points[j].x), MAX(max.y, points[j].y), MAX(max.z, points[j].z));
+ min = min.min(points[j]);
+ max = max.max(points[j]);
}
kernel_size = max - min;
@@ -931,9 +929,10 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
uniforms.push_back(u);
}
- if (fog->copy_uniform_set.is_null()) {
- fog->copy_uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY), 0);
+ if (fog->copy_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(fog->copy_uniform_set)) {
+ RD::get_singleton()->free(fog->copy_uniform_set);
}
+ fog->copy_uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY), 0);
if (!gi_dependent_sets_valid) {
fog->gi_dependent_sets.process_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0);
diff --git a/servers/rendering/renderer_rd/environment/gi.cpp b/servers/rendering/renderer_rd/environment/gi.cpp
index 6da828df45..c7752f8a86 100644
--- a/servers/rendering/renderer_rd/environment/gi.cpp
+++ b/servers/rendering/renderer_rd/environment/gi.cpp
@@ -3407,7 +3407,7 @@ void GI::init(SkyRD *p_sky) {
RD::PipelineDepthStencilState ds;
ds.enable_depth_test = true;
ds.enable_depth_write = true;
- ds.depth_compare_operator = RD::COMPARE_OP_LESS_OR_EQUAL;
+ ds.depth_compare_operator = RD::COMPARE_OP_GREATER_OR_EQUAL;
voxel_gi_debug_shader_version_pipelines[i].setup(voxel_gi_debug_shader_version_shaders[i], RD::RENDER_PRIMITIVE_TRIANGLES, rs, RD::PipelineMultisampleState(), ds, RD::PipelineColorBlendState::create_disabled(), 0);
}
@@ -3575,7 +3575,7 @@ void GI::init(SkyRD *p_sky) {
RD::PipelineDepthStencilState ds;
ds.enable_depth_test = true;
ds.enable_depth_write = true;
- ds.depth_compare_operator = RD::COMPARE_OP_LESS_OR_EQUAL;
+ ds.depth_compare_operator = RD::COMPARE_OP_GREATER_OR_EQUAL;
for (int i = 0; i < SDFGIShader::PROBE_DEBUG_MAX; i++) {
// TODO check if version is enabled
@@ -3725,6 +3725,12 @@ void GI::setup_voxel_gi_instances(RenderDataRD *p_render_data, Ref<RenderSceneBu
}
rbgi->uniform_set[v] = RID();
}
+
+ if (p_render_buffers->has_custom_data(RB_SCOPE_FOG)) {
+ // VoxelGI instances have changed, so we need to update volumetric fog.
+ Ref<RendererRD::Fog::VolumetricFog> fog = p_render_buffers->get_custom_data(RB_SCOPE_FOG);
+ fog->sync_gi_dependent_sets_validity(true);
+ }
}
if (p_voxel_gi_instances.size() > 0) {
@@ -3804,8 +3810,13 @@ void GI::process_gi(Ref<RenderSceneBuffersRD> p_render_buffers, const RID *p_nor
rbgi->scene_data_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(SceneData));
}
+ Projection correction;
+ correction.set_depth_correction(false);
+
for (uint32_t v = 0; v < p_view_count; v++) {
- RendererRD::MaterialStorage::store_camera(p_projections[v].inverse(), scene_data.inv_projection[v]);
+ Projection temp = correction * p_projections[v];
+
+ RendererRD::MaterialStorage::store_camera(temp.inverse(), scene_data.inv_projection[v]);
scene_data.eye_offset[v][0] = p_eye_offsets[v].x;
scene_data.eye_offset[v][1] = p_eye_offsets[v].y;
scene_data.eye_offset[v][2] = p_eye_offsets[v].z;
diff --git a/servers/rendering/renderer_rd/environment/sky.cpp b/servers/rendering/renderer_rd/environment/sky.cpp
index 41609dc74d..27c07f23fa 100644
--- a/servers/rendering/renderer_rd/environment/sky.cpp
+++ b/servers/rendering/renderer_rd/environment/sky.cpp
@@ -141,7 +141,7 @@ void SkyRD::SkyShaderData::set_code(const String &p_code) {
for (int i = 0; i < SKY_VERSION_MAX; i++) {
RD::PipelineDepthStencilState depth_stencil_state;
depth_stencil_state.enable_depth_test = true;
- depth_stencil_state.depth_compare_operator = RD::COMPARE_OP_LESS_OR_EQUAL;
+ depth_stencil_state.depth_compare_operator = RD::COMPARE_OP_GREATER_OR_EQUAL;
if (scene_singleton->sky.sky_shader.shader.is_variant_enabled(i)) {
RID shader_variant = scene_singleton->sky.sky_shader.shader.version_get_shader(version, i);
@@ -1174,6 +1174,7 @@ void SkyRD::setup_sky(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, con
}
Projection correction;
+ correction.set_depth_correction(false, true);
correction.add_jitter_offset(p_jitter);
sky_scene_state.view_count = p_view_count;
@@ -1184,10 +1185,12 @@ void SkyRD::setup_sky(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, con
for (uint32_t i = 0; i < p_view_count; i++) {
Projection view_inv_projection = (correction * p_view_projections[i]).inverse();
if (p_view_count > 1) {
+ // Reprojection is used when we need to have things in combined space.
RendererRD::MaterialStorage::store_camera(p_cam_projection * view_inv_projection, sky_scene_state.ubo.combined_reprojection[i]);
} else {
+ // This is unused so just reset to identity.
Projection ident;
- RendererRD::MaterialStorage::store_camera(correction, sky_scene_state.ubo.combined_reprojection[i]);
+ RendererRD::MaterialStorage::store_camera(ident, sky_scene_state.ubo.combined_reprojection[i]);
}
RendererRD::MaterialStorage::store_camera(view_inv_projection, sky_scene_state.ubo.view_inv_projections[i]);
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 fa6e78750b..0e69ad99b8 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
@@ -546,6 +546,8 @@ void RenderForwardClustered::_render_list(RenderingDevice::DrawListID p_draw_lis
VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_MULTIVIEW);
VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_MULTIVIEW | COLOR_PASS_FLAG_MOTION_VECTORS);
VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_MOTION_VECTORS);
+ VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_SEPARATE_SPECULAR | COLOR_PASS_FLAG_MULTIVIEW | COLOR_PASS_FLAG_MOTION_VECTORS);
+ VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_TRANSPARENT | COLOR_PASS_FLAG_MULTIVIEW | COLOR_PASS_FLAG_MOTION_VECTORS);
default: {
ERR_FAIL_MSG("Invalid color pass flag combination " + itos(p_params->color_pass_flags));
}
@@ -1130,6 +1132,7 @@ void RenderForwardClustered::_update_sdfgi(RenderDataRD *p_render_data) {
}
if (rb.is_valid() && rb->has_custom_data(RB_SCOPE_SDFGI)) {
+ RENDER_TIMESTAMP("Render SDFGI");
Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI);
float exposure_normalization = 1.0;
@@ -1401,7 +1404,8 @@ void RenderForwardClustered::_pre_opaque_render(RenderDataRD *p_render_data, boo
}
}
- //cube shadows are rendered in their own way
+ RENDER_TIMESTAMP("Render OmniLight Shadows");
+ // Cube shadows are rendered in their own way.
for (const int &index : p_render_data->cube_shadows) {
_render_shadow_pass(p_render_data->render_shadows[index].light, p_render_data->shadow_atlas, p_render_data->render_shadows[index].pass, p_render_data->render_shadows[index].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, true, true, true, p_render_data->render_info, viewport_size, p_render_data->scene_data->cam_transform);
}
@@ -1457,6 +1461,7 @@ void RenderForwardClustered::_pre_opaque_render(RenderDataRD *p_render_data, boo
// drawcalls per eye/view. It will all sync up at the barrier.
if (p_use_ssao || p_use_ssil) {
+ RENDER_TIMESTAMP("Prepare Depth for SSAO/SSIL");
// Convert our depth buffer data to linear data in
for (uint32_t v = 0; v < rb->get_view_count(); v++) {
ss_effects->downsample_depth(rb, v, p_render_data->scene_data->view_projection[v]);
@@ -1472,6 +1477,8 @@ void RenderForwardClustered::_pre_opaque_render(RenderDataRD *p_render_data, boo
}
}
+ RENDER_TIMESTAMP("Pre Opaque Render");
+
if (current_cluster_builder) {
// Note: when rendering stereoscopic (multiview) we are using our combined frustum projection to create
// our cluster data. We use reprojection in the shader to adjust for our left/right eye.
@@ -1504,6 +1511,7 @@ void RenderForwardClustered::_pre_opaque_render(RenderDataRD *p_render_data, boo
}
if (rb_data.is_valid()) {
+ RENDER_TIMESTAMP("Update Volumetric Fog");
bool directional_shadows = RendererRD::LightStorage::get_singleton()->has_directional_shadows(directional_light_count);
_update_volumetric_fog(rb, p_render_data->environment, p_render_data->scene_data->cam_projection, p_render_data->scene_data->cam_transform, p_render_data->scene_data->prev_cam_transform.affine_inverse(), p_render_data->shadow_atlas, directional_light_count, directional_shadows, positional_light_count, p_render_data->voxel_gi_count, *p_render_data->fog_volumes);
}
@@ -1615,15 +1623,16 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
gi.setup_voxel_gi_instances(p_render_data, p_render_data->render_buffers, p_render_data->scene_data->cam_transform, *p_render_data->voxel_gi_instances, p_render_data->voxel_gi_count);
} else {
- ERR_PRINT("No render buffer nor reflection atlas, bug"); //should never happen, will crash
+ ERR_PRINT("No render buffer nor reflection atlas, bug"); // Should never happen!
current_cluster_builder = nullptr;
+ return; // No point in continuing, we'll just crash.
}
- if (current_cluster_builder != nullptr) {
- p_render_data->cluster_buffer = current_cluster_builder->get_cluster_buffer();
- p_render_data->cluster_size = current_cluster_builder->get_cluster_size();
- p_render_data->cluster_max_elements = current_cluster_builder->get_max_cluster_elements();
- }
+ ERR_FAIL_NULL(current_cluster_builder);
+
+ p_render_data->cluster_buffer = current_cluster_builder->get_cluster_buffer();
+ p_render_data->cluster_size = current_cluster_builder->get_cluster_size();
+ p_render_data->cluster_max_elements = current_cluster_builder->get_max_cluster_elements();
_update_vrs(rb);
@@ -1964,6 +1973,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
WARN_PRINT_ONCE("Pre opaque rendering effects can't access resolved depth buffers.");
}
+ RENDER_TIMESTAMP("Process Pre Opaque Compositor Effects");
_process_compositor_effects(RS::COMPOSITOR_EFFECT_CALLBACK_TYPE_PRE_OPAQUE, p_render_data);
}
@@ -1975,6 +1985,8 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
}
_pre_opaque_render(p_render_data, using_ssao, using_ssil, using_sdfgi || using_voxelgi, normal_roughness_views, rb_data.is_valid() && rb_data->has_voxelgi() ? rb_data->get_voxelgi() : RID());
+ RENDER_TIMESTAMP("Render Opaque Pass");
+
RD::get_singleton()->draw_command_begin_label("Render Opaque Pass");
p_render_data->scene_data->directional_light_count = p_render_data->directional_light_count;
@@ -1985,8 +1997,6 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
_setup_environment(p_render_data, is_reflection_probe, screen_size, !is_reflection_probe, p_default_bg_color, true, using_motion_pass);
- RENDER_TIMESTAMP("Render Opaque Pass");
-
RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_OPAQUE, p_render_data, radiance_texture, samplers, true);
{
@@ -2011,7 +2021,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
uint32_t opaque_color_pass_flags = using_motion_pass ? (color_pass_flags & ~COLOR_PASS_FLAG_MOTION_VECTORS) : color_pass_flags;
RID opaque_framebuffer = using_motion_pass ? rb_data->get_color_pass_fb(opaque_color_pass_flags) : color_framebuffer;
RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, PASS_MODE_COLOR, opaque_color_pass_flags, rb_data.is_null(), p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count, 0, spec_constant_base_flags);
- _render_list_with_draw_list(&render_list_params, opaque_framebuffer, load_color ? RD::INITIAL_ACTION_LOAD : RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, depth_pre_pass ? RD::INITIAL_ACTION_LOAD : RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, c, 1.0, 0);
+ _render_list_with_draw_list(&render_list_params, opaque_framebuffer, load_color ? RD::INITIAL_ACTION_LOAD : RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, depth_pre_pass ? RD::INITIAL_ACTION_LOAD : RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, c, 0.0, 0);
}
RD::get_singleton()->draw_command_end_label();
@@ -2050,6 +2060,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
}
}
+ RENDER_TIMESTAMP("Process Post Opaque Compositor Effects");
_process_compositor_effects(RS::COMPOSITOR_EFFECT_CALLBACK_TYPE_POST_OPAQUE, p_render_data);
}
@@ -2110,6 +2121,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
}
{
+ RENDER_TIMESTAMP("Process Post Sky Compositor Effects");
// Don't need to check for depth or color resolve here, we've already triggered it.
_process_compositor_effects(RS::COMPOSITOR_EFFECT_CALLBACK_TYPE_POST_SKY, p_render_data);
}
@@ -2187,6 +2199,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
}
}
+ RENDER_TIMESTAMP("Process Pre Transparent Compositor Effects");
_process_compositor_effects(RS::COMPOSITOR_EFFECT_CALLBACK_TYPE_PRE_TRANSPARENT, p_render_data);
}
@@ -2231,6 +2244,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
RD::get_singleton()->draw_command_end_label();
{
+ RENDER_TIMESTAMP("Process Post Transparent Compositor Effects");
_process_compositor_effects(RS::COMPOSITOR_EFFECT_CALLBACK_TYPE_POST_TRANSPARENT, p_render_data);
}
@@ -2626,7 +2640,7 @@ void RenderForwardClustered::_render_shadow_end() {
for (SceneState::ShadowPass &shadow_pass : scene_state.shadow_passes) {
RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, 0, true, false, shadow_pass.rp_uniform_set, false, Vector2(), shadow_pass.lod_distance_multiplier, shadow_pass.screen_mesh_lod_threshold, 1, shadow_pass.element_from);
- _render_list_with_draw_list(&render_list_parameters, shadow_pass.framebuffer, RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_DISCARD, shadow_pass.initial_depth_action, RD::FINAL_ACTION_STORE, Vector<Color>(), 1.0, 0, shadow_pass.rect);
+ _render_list_with_draw_list(&render_list_parameters, shadow_pass.framebuffer, RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_DISCARD, shadow_pass.initial_depth_action, RD::FINAL_ACTION_STORE, Vector<Color>(), 0.0, 0, shadow_pass.rect);
}
RD::get_singleton()->draw_command_end_label();
@@ -2726,7 +2740,7 @@ void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform
Color(0, 0, 0, 0)
};
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, clear, 1.0, 0, p_region);
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, clear, 0.0, 0, p_region);
_render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), &render_list_params, 0, render_list_params.element_count);
RD::get_singleton()->draw_list_end();
}
@@ -2776,7 +2790,7 @@ void RenderForwardClustered::_render_uv2(const PagedArray<RenderGeometryInstance
Color(0, 0, 0, 0),
Color(0, 0, 0, 0)
};
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, clear, 1.0, 0, p_region);
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, clear, 0.0, 0, p_region);
const int uv_offset_count = 9;
static const Vector2 uv_offsets[uv_offset_count] = {
@@ -2882,7 +2896,7 @@ void RenderForwardClustered::_render_sdfgi(Ref<RenderSceneBuffersRD> p_render_bu
}
RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, 0, true, false, rp_uniform_set, false);
- _render_list_with_draw_list(&render_list_params, E->value, RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, Rect2());
+ _render_list_with_draw_list(&render_list_params, E->value, RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 0.0, 0, Rect2());
}
RD::get_singleton()->draw_command_end_label();
@@ -4262,7 +4276,7 @@ RenderForwardClustered::RenderForwardClustered() {
sampler.mag_filter = RD::SAMPLER_FILTER_NEAREST;
sampler.min_filter = RD::SAMPLER_FILTER_NEAREST;
sampler.enable_compare = true;
- sampler.compare_op = RD::COMPARE_OP_LESS;
+ sampler.compare_op = RD::COMPARE_OP_GREATER;
shadow_sampler = RD::get_singleton()->sampler_create(sampler);
}
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 12af8822b4..1f12d92754 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
@@ -379,7 +379,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
template <PassMode p_pass_mode, uint32_t p_color_pass_flags = 0>
_FORCE_INLINE_ void _render_list_template(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element);
void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element);
- void _render_list_with_draw_list(RenderListParameters *p_params, RID p_framebuffer, RD::InitialAction p_initial_color_action, RD::FinalAction p_final_color_action, RD::InitialAction p_initial_depth_action, RD::FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2());
+ void _render_list_with_draw_list(RenderListParameters *p_params, RID p_framebuffer, RD::InitialAction p_initial_color_action, RD::FinalAction p_final_color_action, RD::InitialAction p_initial_depth_action, RD::FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 0.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2());
void _update_instance_data_buffer(RenderListType p_render_list);
void _fill_instance_data(RenderListType p_render_list, int *p_render_info = nullptr, uint32_t p_offset = 0, int32_t p_max_elements = -1, bool p_update_buffer = true);
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 55c6c420eb..209fabeddf 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
@@ -260,7 +260,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
if (depth_test != DEPTH_TEST_DISABLED) {
depth_stencil_state.enable_depth_test = true;
- depth_stencil_state.depth_compare_operator = RD::COMPARE_OP_LESS_OR_EQUAL;
+ depth_stencil_state.depth_compare_operator = RD::COMPARE_OP_GREATER_OR_EQUAL;
depth_stencil_state.enable_depth_write = depth_draw != DEPTH_DRAW_DISABLED ? true : false;
}
bool depth_pre_pass_enabled = bool(GLOBAL_GET("rendering/driver/depth_prepass/enable"));
@@ -737,7 +737,7 @@ void SceneShaderForwardClustered::init(const String p_defines) {
default_shader = material_storage->shader_allocate();
material_storage->shader_initialize(default_shader);
material_storage->shader_set_code(default_shader, R"(
-// Default 3D material shader (clustered).
+// Default 3D material shader (Forward+).
shader_type spatial;
@@ -768,11 +768,11 @@ void fragment() {
material_storage->shader_initialize(overdraw_material_shader);
// Use relatively low opacity so that more "layers" of overlapping objects can be distinguished.
material_storage->shader_set_code(overdraw_material_shader, R"(
-// 3D editor Overdraw debug draw mode shader (clustered).
+// 3D editor Overdraw debug draw mode shader (Forward+).
shader_type spatial;
-render_mode blend_add, unshaded;
+render_mode blend_add, unshaded, fog_disabled;
void fragment() {
ALBEDO = vec3(0.4, 0.8, 0.8);
@@ -792,11 +792,11 @@ void fragment() {
debug_shadow_splits_material_shader = material_storage->shader_allocate();
material_storage->shader_initialize(debug_shadow_splits_material_shader);
material_storage->shader_set_code(debug_shadow_splits_material_shader, R"(
-// 3D debug shadow splits mode shader(mobile).
+// 3D debug shadow splits mode shader (Forward+).
shader_type spatial;
-render_mode debug_shadow_splits;
+render_mode debug_shadow_splits, fog_disabled;
void fragment() {
ALBEDO = vec3(1.0, 1.0, 1.0);
@@ -827,7 +827,7 @@ void fragment() {
sampler.mag_filter = RD::SAMPLER_FILTER_LINEAR;
sampler.min_filter = RD::SAMPLER_FILTER_LINEAR;
sampler.enable_compare = true;
- sampler.compare_op = RD::COMPARE_OP_LESS;
+ sampler.compare_op = RD::COMPARE_OP_GREATER;
shadow_sampler = RD::get_singleton()->sampler_create(sampler);
}
}
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 ac93aca6bb..48c9cda253 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
@@ -777,7 +777,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
if (rb->get_scaling_3d_mode() != RS::VIEWPORT_SCALING_3D_MODE_OFF) {
// can't do blit subpass because we're scaling
using_subpass_post_process = false;
- } else if (p_render_data->environment.is_valid() && (environment_get_glow_enabled(p_render_data->environment) || RSG::camera_attributes->camera_attributes_uses_auto_exposure(p_render_data->camera_attributes) || RSG::camera_attributes->camera_attributes_uses_dof(p_render_data->camera_attributes))) {
+ } else if (p_render_data->environment.is_valid() && (environment_get_glow_enabled(p_render_data->environment) || RSG::camera_attributes->camera_attributes_uses_auto_exposure(p_render_data->camera_attributes) || RSG::camera_attributes->camera_attributes_uses_dof(p_render_data->camera_attributes) || environment_get_background(p_render_data->environment) == RS::ENV_BG_CANVAS)) {
// can't do blit subpass because we're using post processes
using_subpass_post_process = false;
}
@@ -984,7 +984,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
}
}
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, load_color ? RD::INITIAL_ACTION_LOAD : RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, c, 1.0, 0);
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, load_color ? RD::INITIAL_ACTION_LOAD : RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, c, 0.0, 0);
RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(framebuffer);
if (copy_canvas) {
@@ -1385,7 +1385,7 @@ void RenderForwardMobile::_render_shadow_end() {
for (SceneState::ShadowPass &shadow_pass : scene_state.shadow_passes) {
RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, shadow_pass.rp_uniform_set, 0, false, Vector2(), shadow_pass.lod_distance_multiplier, shadow_pass.screen_mesh_lod_threshold, 1, shadow_pass.element_from);
- _render_list_with_draw_list(&render_list_parameters, shadow_pass.framebuffer, RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_DISCARD, shadow_pass.initial_depth_action, RD::FINAL_ACTION_STORE, Vector<Color>(), 1.0, 0, shadow_pass.rect);
+ _render_list_with_draw_list(&render_list_parameters, shadow_pass.framebuffer, RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_DISCARD, shadow_pass.initial_depth_action, RD::FINAL_ACTION_STORE, Vector<Color>(), 0.0, 0, shadow_pass.rect);
}
RD::get_singleton()->draw_command_end_label();
@@ -1437,7 +1437,7 @@ void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, c
Color(0, 0, 0, 0),
Color(0, 0, 0, 0)
};
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, clear, 1.0, 0, p_region);
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, clear, 0.0, 0, p_region);
_render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), &render_list_params, 0, render_list_params.element_count);
RD::get_singleton()->draw_list_end();
}
@@ -1483,7 +1483,7 @@ void RenderForwardMobile::_render_uv2(const PagedArray<RenderGeometryInstance *>
Color(0, 0, 0, 0)
};
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, clear, 1.0, 0, p_region);
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, clear, 0.0, 0, p_region);
const int uv_offset_count = 9;
static const Vector2 uv_offsets[uv_offset_count] = {
@@ -2835,6 +2835,11 @@ RenderForwardMobile::~RenderForwardMobile() {
for (const RID &rid : scene_state.uniform_buffers) {
RD::get_singleton()->free(rid);
}
+ for (uint32_t i = 0; i < RENDER_LIST_MAX; i++) {
+ if (scene_state.instance_buffer[i].is_valid()) {
+ RD::get_singleton()->free(scene_state.instance_buffer[i]);
+ }
+ }
RD::get_singleton()->free(scene_state.lightmap_buffer);
RD::get_singleton()->free(scene_state.lightmap_capture_buffer);
memdelete_arr(scene_state.lightmap_captures);
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 5c02204627..f29503e5ec 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
@@ -350,7 +350,7 @@ private:
template <PassMode p_pass_mode>
_FORCE_INLINE_ void _render_list_template(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element);
void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element);
- void _render_list_with_draw_list(RenderListParameters *p_params, RID p_framebuffer, RD::InitialAction p_initial_color_action, RD::FinalAction p_final_color_action, RD::InitialAction p_initial_depth_action, RD::FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2());
+ void _render_list_with_draw_list(RenderListParameters *p_params, RID p_framebuffer, RD::InitialAction p_initial_color_action, RD::FinalAction p_final_color_action, RD::InitialAction p_initial_depth_action, RD::FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 0.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2());
RenderList render_list[RENDER_LIST_MAX];
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 3592ee2f6d..a2f112669c 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
@@ -271,7 +271,7 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
if (depth_test != DEPTH_TEST_DISABLED) {
depth_stencil_state.enable_depth_test = true;
- depth_stencil_state.depth_compare_operator = RD::COMPARE_OP_LESS_OR_EQUAL;
+ depth_stencil_state.depth_compare_operator = RD::COMPARE_OP_GREATER_OR_EQUAL;
depth_stencil_state.enable_depth_write = depth_draw != DEPTH_DRAW_DISABLED ? true : false;
}
@@ -641,7 +641,7 @@ void SceneShaderForwardMobile::init(const String p_defines) {
default_shader = material_storage->shader_allocate();
material_storage->shader_initialize(default_shader);
material_storage->shader_set_code(default_shader, R"(
-// Default 3D material shader (mobile).
+// Default 3D material shader (Mobile).
shader_type spatial;
@@ -671,11 +671,11 @@ void fragment() {
material_storage->shader_initialize(overdraw_material_shader);
// Use relatively low opacity so that more "layers" of overlapping objects can be distinguished.
material_storage->shader_set_code(overdraw_material_shader, R"(
-// 3D editor Overdraw debug draw mode shader (mobile).
+// 3D editor Overdraw debug draw mode shader (Mobile).
shader_type spatial;
-render_mode blend_add, unshaded;
+render_mode blend_add, unshaded, fog_disabled;
void fragment() {
ALBEDO = vec3(0.4, 0.8, 0.8);
@@ -696,11 +696,11 @@ void fragment() {
material_storage->shader_initialize(debug_shadow_splits_material_shader);
// Use relatively low opacity so that more "layers" of overlapping objects can be distinguished.
material_storage->shader_set_code(debug_shadow_splits_material_shader, R"(
-// 3D debug shadow splits mode shader(mobile).
+// 3D debug shadow splits mode shader (Mobile).
shader_type spatial;
-render_mode debug_shadow_splits;
+render_mode debug_shadow_splits, fog_disabled;
void fragment() {
ALBEDO = vec3(1.0, 1.0, 1.0);
@@ -731,7 +731,7 @@ void fragment() {
sampler.mag_filter = RD::SAMPLER_FILTER_LINEAR;
sampler.min_filter = RD::SAMPLER_FILTER_LINEAR;
sampler.enable_compare = true;
- sampler.compare_op = RD::COMPARE_OP_LESS;
+ sampler.compare_op = RD::COMPARE_OP_GREATER;
shadow_sampler = RD::get_singleton()->sampler_create(sampler);
}
}
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
index 00604d0d4b..6f56711151 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
@@ -34,6 +34,7 @@
#include "core/math/geometry_2d.h"
#include "core/math/math_defs.h"
#include "core/math/math_funcs.h"
+#include "core/math/transform_interpolator.h"
#include "renderer_compositor_rd.h"
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/particles_storage.h"
@@ -406,7 +407,7 @@ _FORCE_INLINE_ static uint32_t _indices_to_primitives(RS::PrimitiveType p_primit
return (p_indices - subtractor[p_primitive]) / divisor[p_primitive];
}
-void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_render_target, const Item *p_item, RD::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, Light *p_lights, PipelineVariants *p_pipeline_variants, bool &r_sdf_used, RenderingMethod::RenderInfo *r_render_info) {
+void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_render_target, const Item *p_item, RD::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, Light *p_lights, PipelineVariants *p_pipeline_variants, bool &r_sdf_used, const Point2 &p_offset, RenderingMethod::RenderInfo *r_render_info) {
//create an empty push constant
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
@@ -425,6 +426,11 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
PushConstant push_constant;
Transform2D base_transform = p_canvas_transform_inverse * p_item->final_transform;
+
+ if (p_offset.x || p_offset.y) {
+ base_transform *= Transform2D(0, p_offset / p_item->xform_curr.get_scale()); // TODO: Interpolate or explain why not needed.
+ }
+
Transform2D draw_transform;
_update_transform_2d_to_mat2x3(base_transform, push_constant.world);
@@ -1240,7 +1246,23 @@ void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_co
}
}
- _render_item(draw_list, p_to_render_target, ci, fb_format, canvas_transform_inverse, current_clip, p_lights, pipeline_variants, r_sdf_used, r_render_info);
+ if (!ci->repeat_size.x && !ci->repeat_size.y) {
+ _render_item(draw_list, p_to_render_target, ci, fb_format, canvas_transform_inverse, current_clip, p_lights, pipeline_variants, r_sdf_used, Point2(), r_render_info);
+ } else {
+ Point2 start_pos = ci->repeat_size * -(ci->repeat_times / 2);
+ Point2 end_pos = ci->repeat_size * ci->repeat_times + ci->repeat_size + start_pos;
+ Point2 pos = start_pos;
+
+ do {
+ do {
+ _render_item(draw_list, p_to_render_target, ci, fb_format, canvas_transform_inverse, current_clip, p_lights, pipeline_variants, r_sdf_used, pos, r_render_info);
+ pos.y += ci->repeat_size.y;
+ } while (pos.y < end_pos.y);
+
+ pos.x += ci->repeat_size.x;
+ pos.y = start_pos.y;
+ } while (pos.x < end_pos.x);
+ }
prev_material = material;
}
@@ -1345,7 +1367,15 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
ERR_CONTINUE(!clight);
}
- Vector2 canvas_light_pos = p_canvas_transform.xform(l->xform.get_origin()); //convert light position to canvas coordinates, as all computation is done in canvas coords to avoid precision loss
+ Transform2D final_xform;
+ if (!RSG::canvas->_interpolation_data.interpolation_enabled || !l->interpolated) {
+ final_xform = l->xform_curr;
+ } else {
+ real_t f = Engine::get_singleton()->get_physics_interpolation_fraction();
+ TransformInterpolator::interpolate_transform_2d(l->xform_prev, l->xform_curr, final_xform, f);
+ }
+ // Convert light position to canvas coordinates, as all computation is done in canvas coordinates to avoid precision loss.
+ Vector2 canvas_light_pos = p_canvas_transform.xform(final_xform.get_origin());
state.light_uniforms[index].position[0] = canvas_light_pos.x;
state.light_uniforms[index].position[1] = canvas_light_pos.y;
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
index 6da3774fc2..c7c5d34314 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
@@ -424,7 +424,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
double debug_redraw_time = 1.0;
inline void _bind_canvas_texture(RD::DrawListID p_draw_list, RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID &r_last_texture, PushConstant &push_constant, Size2 &r_texpixel_size, bool p_texture_is_data = false); //recursive, so regular inline used instead.
- void _render_item(RenderingDevice::DrawListID p_draw_list, RID p_render_target, const Item *p_item, RenderingDevice::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, Light *p_lights, PipelineVariants *p_pipeline_variants, bool &r_sdf_used, RenderingMethod::RenderInfo *r_render_info = nullptr);
+ void _render_item(RenderingDevice::DrawListID p_draw_list, RID p_render_target, const Item *p_item, RenderingDevice::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, Light *p_lights, PipelineVariants *p_pipeline_variants, bool &r_sdf_used, const Point2 &p_offset, RenderingMethod::RenderInfo *r_render_info = nullptr);
void _render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool &r_sdf_used, bool p_to_backbuffer = false, RenderingMethod::RenderInfo *r_render_info = nullptr);
_FORCE_INLINE_ void _update_transform_2d_to_mat2x4(const Transform2D &p_transform, float *p_mat2x4);
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index 62ecec3991..e61bb9eae8 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -1153,12 +1153,19 @@ void RendererSceneRenderRD::render_scene(const Ref<RenderSceneBuffers> &p_render
PagedArray<RID> empty;
- if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_UNSHADED) {
+ if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_UNSHADED || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_OVERDRAW) {
render_data.lights = &empty;
render_data.reflection_probes = &empty;
render_data.voxel_gi_instances = &empty;
}
+ if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_UNSHADED ||
+ get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_OVERDRAW ||
+ get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_LIGHTING ||
+ get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_PSSM_SPLITS) {
+ render_data.decals = &empty;
+ }
+
Color clear_color;
if (p_render_buffers.is_valid() && p_reflection_probe.is_null()) {
clear_color = texture_storage->render_target_get_clear_request_color(rb->get_render_target());
diff --git a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl
index fe770ac065..48c1b0a3f6 100644
--- a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl
@@ -32,9 +32,9 @@ layout(set = 1, binding = 0) uniform sampler2D source_bokeh;
float get_depth_at_pos(vec2 uv) {
float depth = textureLod(source_depth, uv, 0.0).x * 2.0 - 1.0;
if (params.orthogonal) {
- depth = ((depth + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0;
+ depth = -(depth * (params.z_far - params.z_near) - (params.z_far + params.z_near)) / 2.0;
} else {
- depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - depth * (params.z_far - params.z_near));
+ depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near + depth * (params.z_far - params.z_near));
}
return depth;
}
diff --git a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl
index 947aa793d9..2010b58474 100644
--- a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl
@@ -53,9 +53,9 @@ layout(set = 2, binding = 0) uniform sampler2D original_weight;
float get_depth_at_pos(vec2 uv) {
float depth = textureLod(source_depth, uv, 0.0).x * 2.0 - 1.0;
if (params.orthogonal) {
- depth = ((depth + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0;
+ depth = -(depth * (params.z_far - params.z_near) - (params.z_far + params.z_near)) / 2.0;
} else {
- depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - depth * (params.z_far - params.z_near));
+ depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near + depth * (params.z_far - params.z_near));
}
return depth;
}
diff --git a/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl b/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl
index 1b065a8dd3..7192e596eb 100644
--- a/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl
@@ -4,14 +4,14 @@
#VERSION_DEFINES
-#ifdef MULTIVIEW
+#ifdef USE_MULTIVIEW
#ifdef has_VK_KHR_multiview
#extension GL_EXT_multiview : enable
#define ViewIndex gl_ViewIndex
#else // has_VK_KHR_multiview
#define ViewIndex 0
#endif // has_VK_KHR_multiview
-#endif //MULTIVIEW
+#endif //USE_MULTIVIEW
#define FLAG_FLIP_Y (1 << 0)
#define FLAG_USE_SECTION (1 << 1)
@@ -22,7 +22,7 @@
#define FLAG_LINEAR (1 << 6)
#define FLAG_NORMAL (1 << 7)
-#ifdef MULTIVIEW
+#ifdef USE_MULTIVIEW
layout(location = 0) out vec3 uv_interp;
#else
layout(location = 0) out vec2 uv_interp;
@@ -41,7 +41,7 @@ params;
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_interp.xy = base_arr[gl_VertexIndex];
-#ifdef MULTIVIEW
+#ifdef USE_MULTIVIEW
uv_interp.z = ViewIndex;
#endif
vec2 vpos = uv_interp.xy;
@@ -62,14 +62,14 @@ void main() {
#VERSION_DEFINES
-#ifdef MULTIVIEW
+#ifdef USE_MULTIVIEW
#ifdef has_VK_KHR_multiview
#extension GL_EXT_multiview : enable
#define ViewIndex gl_ViewIndex
#else // has_VK_KHR_multiview
#define ViewIndex 0
#endif // has_VK_KHR_multiview
-#endif //MULTIVIEW
+#endif //USE_MULTIVIEW
#define FLAG_FLIP_Y (1 << 0)
#define FLAG_USE_SECTION (1 << 1)
@@ -91,24 +91,24 @@ layout(push_constant, std430) uniform Params {
params;
#ifndef MODE_SET_COLOR
-#ifdef MULTIVIEW
+#ifdef USE_MULTIVIEW
layout(location = 0) in vec3 uv_interp;
#else
layout(location = 0) in vec2 uv_interp;
#endif
-#ifdef MULTIVIEW
+#ifdef USE_MULTIVIEW
layout(set = 0, binding = 0) uniform sampler2DArray source_color;
#ifdef MODE_TWO_SOURCES
layout(set = 1, binding = 0) uniform sampler2DArray source_depth;
layout(location = 1) out float depth;
#endif /* MODE_TWO_SOURCES */
-#else /* MULTIVIEW */
+#else /* USE_MULTIVIEW */
layout(set = 0, binding = 0) uniform sampler2D source_color;
#ifdef MODE_TWO_SOURCES
layout(set = 1, binding = 0) uniform sampler2D source_color2;
#endif /* MODE_TWO_SOURCES */
-#endif /* MULTIVIEW */
+#endif /* USE_MULTIVIEW */
#endif /* !SET_COLOR */
layout(location = 0) out vec4 frag_color;
@@ -129,7 +129,7 @@ void main() {
frag_color = params.color;
#else
-#ifdef MULTIVIEW
+#ifdef USE_MULTIVIEW
vec3 uv = uv_interp;
#else
vec2 uv = uv_interp;
@@ -165,19 +165,19 @@ void main() {
}
#endif /* MODE_PANORAMA_TO_DP */
-#ifdef MULTIVIEW
+#ifdef USE_MULTIVIEW
vec4 color = textureLod(source_color, uv, 0.0);
#ifdef MODE_TWO_SOURCES
// In multiview our 2nd input will be our depth map
depth = textureLod(source_depth, uv, 0.0).r;
#endif /* MODE_TWO_SOURCES */
-#else /* MULTIVIEW */
+#else /* USE_MULTIVIEW */
vec4 color = textureLod(source_color, uv, 0.0);
#ifdef MODE_TWO_SOURCES
color += textureLod(source_color2, uv, 0.0);
#endif /* MODE_TWO_SOURCES */
-#endif /* MULTIVIEW */
+#endif /* USE_MULTIVIEW */
if (bool(params.flags & FLAG_FORCE_LUMINANCE)) {
color.rgb = vec3(max(max(color.r, color.g), color.b));
diff --git a/servers/rendering/renderer_rd/shaders/effects/cube_to_dp.glsl b/servers/rendering/renderer_rd/shaders/effects/cube_to_dp.glsl
index e77d0de719..3fb93dda35 100644
--- a/servers/rendering/renderer_rd/shaders/effects/cube_to_dp.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/cube_to_dp.glsl
@@ -77,8 +77,8 @@ void main() {
float depth_fix = 1.0 / dot(normal, unorm);
depth = 2.0 * depth - 1.0;
- float linear_depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - depth * (params.z_far - params.z_near));
- depth = (linear_depth * depth_fix) / params.z_far;
-
+ float linear_depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near + depth * (params.z_far - params.z_near));
+ // linear_depth equal to view space depth
+ depth = (params.z_far - linear_depth * depth_fix) / params.z_far;
gl_FragDepth = depth;
}
diff --git a/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_scale.glsl b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_scale.glsl
index 51caa67d3c..d9e21b8cd1 100644
--- a/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_scale.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_scale.glsl
@@ -98,9 +98,9 @@ void main() {
// unproject our Z value so we can use it directly.
depth = depth * 2.0 - 1.0;
if (params.orthogonal) {
- depth = ((depth + (params.camera_z_far + params.camera_z_near) / (params.camera_z_far - params.camera_z_near)) * (params.camera_z_far - params.camera_z_near)) / 2.0;
+ depth = -(depth * (params.camera_z_far - params.camera_z_near) - (params.camera_z_far + params.camera_z_near)) / 2.0;
} else {
- depth = 2.0 * params.camera_z_near * params.camera_z_far / (params.camera_z_far + params.camera_z_near - depth * (params.camera_z_far - params.camera_z_near));
+ depth = 2.0 * params.camera_z_near * params.camera_z_far / (params.camera_z_far + params.camera_z_near + depth * (params.camera_z_far - params.camera_z_near));
}
depth = -depth;
}
diff --git a/servers/rendering/renderer_rd/shaders/effects/tonemap.glsl b/servers/rendering/renderer_rd/shaders/effects/tonemap.glsl
index 33ec991107..38eec2b61a 100644
--- a/servers/rendering/renderer_rd/shaders/effects/tonemap.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/tonemap.glsl
@@ -4,7 +4,7 @@
#VERSION_DEFINES
-#ifdef MULTIVIEW
+#ifdef USE_MULTIVIEW
#ifdef has_VK_KHR_multiview
#extension GL_EXT_multiview : enable
#endif
@@ -24,27 +24,27 @@ void main() {
#VERSION_DEFINES
-#ifdef MULTIVIEW
+#ifdef USE_MULTIVIEW
#ifdef has_VK_KHR_multiview
#extension GL_EXT_multiview : enable
#define ViewIndex gl_ViewIndex
#else // has_VK_KHR_multiview
#define ViewIndex 0
#endif // has_VK_KHR_multiview
-#endif //MULTIVIEW
+#endif //USE_MULTIVIEW
layout(location = 0) in vec2 uv_interp;
#ifdef SUBPASS
layout(input_attachment_index = 0, set = 0, binding = 0) uniform subpassInput input_color;
-#elif defined(MULTIVIEW)
+#elif defined(USE_MULTIVIEW)
layout(set = 0, binding = 0) uniform sampler2DArray source_color;
#else
layout(set = 0, binding = 0) uniform sampler2D source_color;
#endif
layout(set = 1, binding = 0) uniform sampler2D source_auto_exposure;
-#ifdef MULTIVIEW
+#ifdef USE_MULTIVIEW
layout(set = 2, binding = 0) uniform sampler2DArray source_glow;
#else
layout(set = 2, binding = 0) uniform sampler2D source_glow;
@@ -125,7 +125,7 @@ float h1(float a) {
return 1.0f + w3(a) / (w2(a) + w3(a));
}
-#ifdef MULTIVIEW
+#ifdef USE_MULTIVIEW
vec4 texture2D_bicubic(sampler2DArray tex, vec2 uv, int p_lod) {
float lod = float(p_lod);
vec2 tex_size = vec2(params.glow_texture_size >> p_lod);
@@ -153,7 +153,7 @@ vec4 texture2D_bicubic(sampler2DArray tex, vec2 uv, int p_lod) {
}
#define GLOW_TEXTURE_SAMPLE(m_tex, m_uv, m_lod) texture2D_bicubic(m_tex, m_uv, m_lod)
-#else // MULTIVIEW
+#else // USE_MULTIVIEW
vec4 texture2D_bicubic(sampler2D tex, vec2 uv, int p_lod) {
float lod = float(p_lod);
@@ -182,15 +182,15 @@ vec4 texture2D_bicubic(sampler2D tex, vec2 uv, int p_lod) {
}
#define GLOW_TEXTURE_SAMPLE(m_tex, m_uv, m_lod) texture2D_bicubic(m_tex, m_uv, m_lod)
-#endif // !MULTIVIEW
+#endif // !USE_MULTIVIEW
#else // USE_GLOW_FILTER_BICUBIC
-#ifdef MULTIVIEW
+#ifdef USE_MULTIVIEW
#define GLOW_TEXTURE_SAMPLE(m_tex, m_uv, m_lod) textureLod(m_tex, vec3(m_uv, ViewIndex), float(m_lod))
-#else // MULTIVIEW
+#else // USE_MULTIVIEW
#define GLOW_TEXTURE_SAMPLE(m_tex, m_uv, m_lod) textureLod(m_tex, m_uv, float(m_lod))
-#endif // !MULTIVIEW
+#endif // !USE_MULTIVIEW
#endif // !USE_GLOW_FILTER_BICUBIC
@@ -273,11 +273,11 @@ vec3 apply_tonemapping(vec3 color, float white) { // inputs are LINEAR, always o
}
}
-#ifdef MULTIVIEW
+#ifdef USE_MULTIVIEW
vec3 gather_glow(sampler2DArray tex, vec2 uv) { // sample all selected glow levels, view is added to uv later
#else
vec3 gather_glow(sampler2D tex, vec2 uv) { // sample all selected glow levels
-#endif // defined(MULTIVIEW)
+#endif // defined(USE_MULTIVIEW)
vec3 glow = vec3(0.0f);
if (params.glow_levels[0] > 0.0001) {
@@ -364,7 +364,7 @@ vec3 do_fxaa(vec3 color, float exposure, vec2 uv_interp) {
const float FXAA_REDUCE_MUL = (1.0 / 8.0);
const float FXAA_SPAN_MAX = 8.0;
-#ifdef MULTIVIEW
+#ifdef USE_MULTIVIEW
vec3 rgbNW = textureLod(source_color, vec3(uv_interp + vec2(-0.5, -0.5) * params.pixel_size, ViewIndex), 0.0).xyz * exposure * params.luminance_multiplier;
vec3 rgbNE = textureLod(source_color, vec3(uv_interp + vec2(0.5, -0.5) * params.pixel_size, ViewIndex), 0.0).xyz * exposure * params.luminance_multiplier;
vec3 rgbSW = textureLod(source_color, vec3(uv_interp + vec2(-0.5, 0.5) * params.pixel_size, ViewIndex), 0.0).xyz * exposure * params.luminance_multiplier;
@@ -399,7 +399,7 @@ vec3 do_fxaa(vec3 color, float exposure, vec2 uv_interp) {
dir * rcpDirMin)) *
params.pixel_size;
-#ifdef MULTIVIEW
+#ifdef USE_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) * 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
@@ -430,9 +430,9 @@ 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
+ // SUBPASS and USE_MULTIVIEW can be combined but in that case we're already reading from the correct layer
vec4 color = subpassLoad(input_color);
-#elif defined(MULTIVIEW)
+#elif defined(USE_MULTIVIEW)
vec4 color = textureLod(source_color, vec3(uv_interp, ViewIndex), 0.0f);
#else
vec4 color = textureLod(source_color, uv_interp, 0.0f);
diff --git a/servers/rendering/renderer_rd/shaders/effects/vrs.glsl b/servers/rendering/renderer_rd/shaders/effects/vrs.glsl
index d3d39a8b92..23b0373eef 100644
--- a/servers/rendering/renderer_rd/shaders/effects/vrs.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/vrs.glsl
@@ -4,16 +4,16 @@
#VERSION_DEFINES
-#ifdef MULTIVIEW
+#ifdef USE_MULTIVIEW
#ifdef has_VK_KHR_multiview
#extension GL_EXT_multiview : enable
#define ViewIndex gl_ViewIndex
#else // has_VK_KHR_multiview
#define ViewIndex 0
#endif // has_VK_KHR_multiview
-#endif //MULTIVIEW
+#endif //USE_MULTIVIEW
-#ifdef MULTIVIEW
+#ifdef USE_MULTIVIEW
layout(location = 0) out vec3 uv_interp;
#else
layout(location = 0) out vec2 uv_interp;
@@ -23,7 +23,7 @@ void main() {
vec2 base_arr[3] = vec2[](vec2(-1.0, -1.0), vec2(-1.0, 3.0), vec2(3.0, -1.0));
gl_Position = vec4(base_arr[gl_VertexIndex], 0.0, 1.0);
uv_interp.xy = clamp(gl_Position.xy, vec2(0.0, 0.0), vec2(1.0, 1.0)) * 2.0; // saturate(x) * 2.0
-#ifdef MULTIVIEW
+#ifdef USE_MULTIVIEW
uv_interp.z = ViewIndex;
#endif
}
@@ -34,36 +34,36 @@ void main() {
#VERSION_DEFINES
-#ifdef MULTIVIEW
+#ifdef USE_MULTIVIEW
#ifdef has_VK_KHR_multiview
#extension GL_EXT_multiview : enable
#define ViewIndex gl_ViewIndex
#else // has_VK_KHR_multiview
#define ViewIndex 0
#endif // has_VK_KHR_multiview
-#endif //MULTIVIEW
+#endif //USE_MULTIVIEW
-#ifdef MULTIVIEW
+#ifdef USE_MULTIVIEW
layout(location = 0) in vec3 uv_interp;
layout(set = 0, binding = 0) uniform sampler2DArray source_color;
-#else /* MULTIVIEW */
+#else /* USE_MULTIVIEW */
layout(location = 0) in vec2 uv_interp;
layout(set = 0, binding = 0) uniform sampler2D source_color;
-#endif /* MULTIVIEW */
+#endif /* USE_MULTIVIEW */
layout(location = 0) out uint frag_color;
void main() {
-#ifdef MULTIVIEW
+#ifdef USE_MULTIVIEW
vec3 uv = uv_interp;
#else
vec2 uv = uv_interp;
#endif
-#ifdef MULTIVIEW
+#ifdef USE_MULTIVIEW
vec4 color = textureLod(source_color, uv, 0.0);
frag_color = uint(color.r * 255.0);
-#else /* MULTIVIEW */
+#else /* USE_MULTIVIEW */
vec4 color = textureLod(source_color, uv, 0.0);
// for user supplied VRS map we do a color mapping
@@ -75,5 +75,5 @@ void main() {
// note 1x4, 4x1, 1x8, 8x1, 2x8 and 8x2 are not supported
// 4x8, 8x4 and 8x8 are only available on some GPUs
-#endif /* MULTIVIEW */
+#endif /* USE_MULTIVIEW */
}
diff --git a/servers/rendering/renderer_rd/shaders/environment/gi.glsl b/servers/rendering/renderer_rd/shaders/environment/gi.glsl
index 80ed34cda1..480172f9dc 100644
--- a/servers/rendering/renderer_rd/shaders/environment/gi.glsl
+++ b/servers/rendering/renderer_rd/shaders/environment/gi.glsl
@@ -174,9 +174,9 @@ vec3 reconstruct_position(ivec2 screen_pos) {
pos.z = pos.z * 2.0 - 1.0;
if (params.orthogonal) {
- pos.z = ((pos.z + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0;
+ pos.z = -(pos.z * (params.z_far - params.z_near) - (params.z_far + params.z_near)) / 2.0;
} else {
- pos.z = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - pos.z * (params.z_far - params.z_near));
+ pos.z = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near + pos.z * (params.z_far - params.z_near));
}
pos.z = -pos.z;
diff --git a/servers/rendering/renderer_rd/shaders/environment/sky.glsl b/servers/rendering/renderer_rd/shaders/environment/sky.glsl
index 4e5b11aed8..35457a2482 100644
--- a/servers/rendering/renderer_rd/shaders/environment/sky.glsl
+++ b/servers/rendering/renderer_rd/shaders/environment/sky.glsl
@@ -25,7 +25,7 @@ params;
void main() {
vec2 base_arr[3] = vec2[](vec2(-1.0, -3.0), vec2(-1.0, 1.0), vec2(3.0, 1.0));
uv_interp = base_arr[gl_VertexIndex];
- gl_Position = vec4(uv_interp, 1.0, 1.0);
+ gl_Position = vec4(uv_interp, 0.0, 1.0);
}
#[fragment]
@@ -158,7 +158,7 @@ vec3 interleaved_gradient_noise(vec2 pos) {
vec4 volumetric_fog_process(vec2 screen_uv) {
#ifdef USE_MULTIVIEW
- vec4 reprojected = sky_scene_data.combined_reprojection[ViewIndex] * (vec4(screen_uv * 2.0 - 1.0, 1.0, 1.0) * sky_scene_data.z_far);
+ vec4 reprojected = sky_scene_data.combined_reprojection[ViewIndex] * vec4(screen_uv * 2.0 - 1.0, 0.0, 1.0); // Unproject at the far plane
vec3 fog_pos = vec3(reprojected.xy / reprojected.w, 1.0) * 0.5 + 0.5;
#else
vec3 fog_pos = vec3(screen_uv, 1.0);
@@ -187,9 +187,11 @@ void main() {
vec3 cube_normal;
#ifdef USE_MULTIVIEW
// In multiview our projection matrices will contain positional and rotational offsets that we need to properly unproject.
- vec4 unproject = vec4(uv_interp.x, -uv_interp.y, 1.0, 1.0);
+ vec4 unproject = vec4(uv_interp.x, -uv_interp.y, 0.0, 1.0); // unproject at the far plane
vec4 unprojected = sky_scene_data.view_inv_projections[ViewIndex] * unproject;
cube_normal = unprojected.xyz / unprojected.w;
+
+ // Unproject will give us the position between the eyes, need to re-offset
cube_normal += sky_scene_data.view_eye_offsets[ViewIndex].xyz;
#else
cube_normal.z = -1.0;
diff --git a/servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl
index 57b9a4c320..d0cfe6a3b8 100644
--- a/servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl
+++ b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl
@@ -416,7 +416,7 @@ void main() {
}
float depth = texture(sampler2D(directional_shadow_atlas, linear_sampler), pssm_coord.xy).r;
- float shadow = exp(min(0.0, (depth - pssm_coord.z)) * z_range * INV_FOG_FADE);
+ float shadow = exp(min(0.0, (pssm_coord.z - depth)) * z_range * INV_FOG_FADE);
shadow = mix(shadow, 1.0, smoothstep(directional_lights.data[i].fade_from, directional_lights.data[i].fade_to, view_pos.z)); //done with negative values for performance
@@ -519,7 +519,7 @@ void main() {
float depth = texture(sampler2D(shadow_atlas, linear_sampler), pos.xy).r;
- shadow_attenuation = mix(1.0 - omni_lights.data[light_index].shadow_opacity, 1.0, exp(min(0.0, (depth - pos.z)) / omni_lights.data[light_index].inv_radius * INV_FOG_FADE));
+ shadow_attenuation = mix(1.0 - omni_lights.data[light_index].shadow_opacity, 1.0, exp(min(0.0, (pos.z - depth)) / omni_lights.data[light_index].inv_radius * INV_FOG_FADE));
}
total_light += light * attenuation * shadow_attenuation * henyey_greenstein(dot(normalize(light_pos - view_pos), normalize(view_pos)), params.phase_g) * omni_lights.data[light_index].volumetric_fog_energy;
}
@@ -597,7 +597,7 @@ void main() {
float depth = texture(sampler2D(shadow_atlas, linear_sampler), pos.xy).r;
- shadow_attenuation = mix(1.0 - spot_lights.data[light_index].shadow_opacity, 1.0, exp(min(0.0, (depth - pos.z)) / spot_lights.data[light_index].inv_radius * INV_FOG_FADE));
+ shadow_attenuation = mix(1.0 - spot_lights.data[light_index].shadow_opacity, 1.0, exp(min(0.0, (pos.z - depth)) / spot_lights.data[light_index].inv_radius * INV_FOG_FADE));
}
total_light += light * attenuation * shadow_attenuation * henyey_greenstein(dot(normalize(light_rel_vec), normalize(view_pos)), params.phase_g) * spot_lights.data[light_index].volumetric_fog_energy;
}
diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl
index 6eae64c04e..359d7799e5 100644
--- a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl
+++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl
@@ -487,8 +487,8 @@ void vertex_shader(vec3 vertex_input,
#ifdef MODE_RENDER_DEPTH
if (scene_data.pancake_shadows) {
- if (gl_Position.z <= 0.00001) {
- gl_Position.z = 0.00001;
+ if (gl_Position.z >= 0.9999) {
+ gl_Position.z = 0.9999;
}
}
#endif
diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl
index 259edc63a0..c26313092b 100644
--- a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl
+++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl
@@ -475,8 +475,8 @@ void main() {
#ifdef MODE_RENDER_DEPTH
if (scene_data.pancake_shadows) {
- if (gl_Position.z <= 0.00001) {
- gl_Position.z = 0.00001;
+ if (gl_Position.z >= 0.9999) {
+ gl_Position.z = 0.9999;
}
}
#endif // MODE_RENDER_DEPTH
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 e9722bad1f..47e6fe5873 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
@@ -454,7 +454,7 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) {
vec3 v0 = abs(basis_normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0);
vec3 tangent = normalize(cross(v0, basis_normal));
vec3 bitangent = normalize(cross(tangent, basis_normal));
- float z_norm = shadow_len * omni_lights.data[idx].inv_radius;
+ float z_norm = 1.0 - shadow_len * omni_lights.data[idx].inv_radius;
tangent *= omni_lights.data[idx].soft_shadow_size * omni_lights.data[idx].soft_shadow_scale;
bitangent *= omni_lights.data[idx].soft_shadow_size * omni_lights.data[idx].soft_shadow_scale;
@@ -479,7 +479,7 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) {
pos.xy = uv_rect.xy + pos.xy * uv_rect.zw;
float d = textureLod(sampler2D(shadow_atlas, SAMPLER_LINEAR_CLAMP), pos.xy, 0.0).r;
- if (d < z_norm) {
+ if (d > z_norm) {
blocker_average += d;
blocker_count += 1.0;
}
@@ -488,11 +488,11 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) {
if (blocker_count > 0.0) {
//blockers found, do soft shadow
blocker_average /= blocker_count;
- float penumbra = (z_norm - blocker_average) / blocker_average;
+ float penumbra = (z_norm + blocker_average) / blocker_average;
tangent *= penumbra;
bitangent *= penumbra;
- z_norm -= omni_lights.data[idx].inv_radius * omni_lights.data[idx].shadow_bias;
+ z_norm += omni_lights.data[idx].inv_radius * omni_lights.data[idx].shadow_bias;
shadow = 0.0;
for (uint i = 0; i < sc_penumbra_shadow_samples; i++) {
@@ -536,6 +536,7 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) {
vec2 pos = shadow_sample.xy / shadow_sample.z;
float depth = shadow_len - omni_lights.data[idx].shadow_bias;
depth *= omni_lights.data[idx].inv_radius;
+ depth = 1.0 - depth;
shadow = mix(1.0, sample_omni_pcf_shadow(shadow_atlas, omni_lights.data[idx].soft_shadow_scale / shadow_sample.z, pos, uv_rect, flip_offset, depth), omni_lights.data[idx].shadow_opacity);
}
@@ -706,7 +707,7 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) {
vec4 v = vec4(vertex + normal_bias, 1.0);
vec4 splane = (spot_lights.data[idx].shadow_matrix * v);
- splane.z -= spot_lights.data[idx].shadow_bias / (light_length * spot_lights.data[idx].inv_radius);
+ splane.z += spot_lights.data[idx].shadow_bias / (light_length * spot_lights.data[idx].inv_radius);
splane /= splane.w;
float shadow;
diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
index 2786af65eb..d1ff9fc362 100644
--- a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
@@ -668,7 +668,9 @@ void LightStorage::update_light_buffers(RenderDataRD *p_render_data, const Paged
light_data.blend_splits = (smode != RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL) && light->directional_blend_splits;
for (int j = 0; j < 4; j++) {
Rect2 atlas_rect = light_instance->shadow_transform[j].atlas_rect;
- Projection matrix = light_instance->shadow_transform[j].camera;
+ Projection correction;
+ correction.set_depth_correction(false, true, false);
+ Projection matrix = correction * light_instance->shadow_transform[j].camera;
float split = light_instance->shadow_transform[MIN(limit, j)].split;
Projection bias;
@@ -967,7 +969,9 @@ void LightStorage::update_light_buffers(RenderDataRD *p_render_data, const Paged
Projection bias;
bias.set_light_bias();
- Projection cm = light_instance->shadow_transform[0].camera;
+ Projection correction;
+ correction.set_depth_correction(false, true, false);
+ Projection cm = correction * light_instance->shadow_transform[0].camera;
Projection shadow_mtx = bias * cm * modelview;
RendererRD::MaterialStorage::store_camera(shadow_mtx, light_data.shadow_matrix);
@@ -1370,6 +1374,17 @@ void LightStorage::reflection_probe_instance_set_transform(RID p_instance, const
rpi->dirty = true;
}
+bool LightStorage::reflection_probe_has_atlas_index(RID p_instance) {
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
+ ERR_FAIL_NULL_V(rpi, false);
+
+ if (rpi->atlas.is_null()) {
+ return false;
+ }
+
+ return rpi->atlas_index >= 0;
+}
+
void LightStorage::reflection_probe_release_atlas_index(RID p_instance) {
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
ERR_FAIL_NULL(rpi);
@@ -1384,6 +1399,14 @@ void LightStorage::reflection_probe_release_atlas_index(RID p_instance) {
// TODO investigate if this is enough? shouldn't we be freeing our textures and framebuffers?
+ if (rpi->rendering) {
+ // We were cancelled mid rendering, trigger refresh.
+ rpi->rendering = false;
+ rpi->dirty = true;
+ rpi->processing_layer = 1;
+ rpi->processing_side = 0;
+ }
+
rpi->atlas_index = -1;
rpi->atlas = RID();
}
@@ -1535,11 +1558,10 @@ bool LightStorage::reflection_probe_instance_postprocess_step(RID p_instance) {
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
ERR_FAIL_NULL_V(rpi, false);
ERR_FAIL_COND_V(!rpi->rendering, false);
- ERR_FAIL_COND_V(rpi->atlas.is_null(), false);
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)
+ // Does not belong to an atlas anymore, cancel (was removed from atlas or atlas changed while rendering).
rpi->rendering = false;
return false;
}
diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.h b/servers/rendering/renderer_rd/storage_rd/light_storage.h
index b3d27cc6ed..b3d6bf5254 100644
--- a/servers/rendering/renderer_rd/storage_rd/light_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/light_storage.h
@@ -277,7 +277,6 @@ private:
int processing_layer = 1;
int processing_side = 0;
- uint32_t render_step = 0;
uint64_t last_pass = 0;
uint32_t cull_mask = 0;
@@ -848,6 +847,7 @@ public:
virtual RID reflection_probe_instance_create(RID p_probe) override;
virtual void reflection_probe_instance_free(RID p_instance) override;
virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) override;
+ virtual bool reflection_probe_has_atlas_index(RID p_instance) override;
virtual void reflection_probe_release_atlas_index(RID p_instance) override;
virtual bool reflection_probe_instance_needs_redraw(RID p_instance) override;
virtual bool reflection_probe_instance_has_reflection(RID p_instance) override;
diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
index a854e78f53..c9c7c53d04 100644
--- a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
@@ -620,8 +620,9 @@ AABB ParticlesStorage::particles_get_current_aabb(RID p_particles) {
total_amount *= particles->trail_bind_poses.size();
}
+ uint32_t particle_data_size = sizeof(ParticleData) + sizeof(float) * 4 * particles->userdata_count;
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());
+ ERR_FAIL_COND_V(buffer.size() != (int)(total_amount * particle_data_size), AABB());
Transform3D inv = particles->emission_transform.affine_inverse();
@@ -630,7 +631,6 @@ AABB ParticlesStorage::particles_get_current_aabb(RID p_particles) {
bool first = true;
const uint8_t *data_ptr = (const uint8_t *)buffer.ptr();
- uint32_t particle_data_size = sizeof(ParticleData) + sizeof(float) * particles->userdata_count;
for (int i = 0; i < total_amount; i++) {
const ParticleData &particle_data = *(const ParticleData *)&data_ptr[particle_data_size * i];
@@ -1388,6 +1388,11 @@ void ParticlesStorage::_particles_update_buffers(Particles *particles) {
}
}
void ParticlesStorage::update_particles() {
+ if (!particle_update_list.first()) {
+ return;
+ }
+
+ RENDER_TIMESTAMP("Update GPUParticles");
uint32_t frame = RSG::rasterizer->get_frame_number();
bool uses_motion_vectors = RSG::viewport->get_num_viewports_with_motion_vectors() > 0;
while (particle_update_list.first()) {
@@ -1452,6 +1457,11 @@ void ParticlesStorage::update_particles() {
if (uint32_t(history_size) != particles->frame_history.size()) {
particles->frame_history.resize(history_size);
memset(particles->frame_history.ptr(), 0, sizeof(ParticlesFrameParams) * history_size);
+ // Set the frame number so that we are able to distinguish an uninitialized
+ // frame from the true frame number zero. See issue #88712 for details.
+ for (int i = 0; i < history_size; i++) {
+ particles->frame_history[i].frame = UINT32_MAX;
+ }
}
if (uint32_t(trail_steps) != particles->trail_params.size() || particles->frame_params_buffer.is_null()) {
diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp
index 8dc74820e2..c5d74d395f 100644
--- a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp
@@ -128,6 +128,13 @@ void RenderSceneBuffersRD::cleanup() {
free_named_texture(E.value);
}
named_textures.clear();
+
+ // Clear weight_buffer / blur textures.
+ for (const WeightBuffers &weight_buffer : weight_buffers) {
+ if (weight_buffer.weight.is_valid()) {
+ RD::get_singleton()->free(weight_buffer.weight);
+ }
+ }
}
void RenderSceneBuffersRD::configure(const RenderSceneBuffersConfiguration *p_config) {
diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
index dd94982f1a..da046bf6b1 100644
--- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
@@ -2965,7 +2965,7 @@ void TextureStorage::update_decal_buffer(const PagedArray<RID> &p_decals, const
dd.emission_rect[3] = 0;
}
- Color modulate = decal->modulate;
+ Color modulate = decal->modulate.srgb_to_linear();
dd.modulate[0] = modulate.r;
dd.modulate[1] = modulate.g;
dd.modulate[2] = modulate.b;
@@ -3637,8 +3637,7 @@ void TextureStorage::_render_target_allocate_sdf(RenderTarget *rt) {
}
rt->process_size = size * scale / 100;
- rt->process_size.x = MAX(rt->process_size.x, 1);
- rt->process_size.y = MAX(rt->process_size.y, 1);
+ rt->process_size = rt->process_size.max(Size2i(1, 1));
tformat.format = RD::DATA_FORMAT_R16G16_SINT;
tformat.width = rt->process_size.width;
diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp
index 59d70958f1..b33de9d6f4 100644
--- a/servers/rendering/renderer_scene_cull.cpp
+++ b/servers/rendering/renderer_scene_cull.cpp
@@ -1720,6 +1720,7 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
idata.base_rid = p_instance->base;
idata.parent_array_index = p_instance->visibility_parent ? p_instance->visibility_parent->array_index : -1;
idata.visibility_index = p_instance->visibility_index;
+ idata.occlusion_timeout = 0;
for (Instance *E : p_instance->visibility_dependencies) {
Instance *dep_instance = E;
@@ -2053,7 +2054,7 @@ void RendererSceneCull::_update_instance_lightmap_captures(Instance *p_instance)
Vector3 inner_pos = ((lm_pos - bounds.position) / bounds.size) * 2.0 - Vector3(1.0, 1.0, 1.0);
- real_t blend = MAX(inner_pos.x, MAX(inner_pos.y, inner_pos.z));
+ real_t blend = MAX(ABS(inner_pos.x), MAX(ABS(inner_pos.y), ABS(inner_pos.z)));
//make blend more rounded
blend = Math::lerp(inner_pos.length(), blend, blend);
blend *= blend;
@@ -2775,7 +2776,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
#define VIS_RANGE_CHECK ((idata.visibility_index == -1) || _visibility_range_check<false>(cull_data.scenario->instance_visibility[idata.visibility_index], cull_data.cam_transform.origin, cull_data.visibility_viewport_mask) == 0)
#define VIS_PARENT_CHECK (_visibility_parent_check(cull_data, idata))
#define VIS_CHECK (visibility_check < 0 ? (visibility_check = (visibility_flags != InstanceData::FLAG_VISIBILITY_DEPENDENCY_NEEDS_CHECK || (VIS_RANGE_CHECK && VIS_PARENT_CHECK))) : visibility_check)
-#define OCCLUSION_CULLED (cull_data.occlusion_buffer != nullptr && (cull_data.scenario->instance_data[i].flags & InstanceData::FLAG_IGNORE_OCCLUSION_CULLING) == 0 && cull_data.occlusion_buffer->is_occluded(cull_data.scenario->instance_aabbs[i].bounds, cull_data.cam_transform.origin, inv_cam_transform, *cull_data.camera_matrix, z_near))
+#define OCCLUSION_CULLED (cull_data.occlusion_buffer != nullptr && (cull_data.scenario->instance_data[i].flags & InstanceData::FLAG_IGNORE_OCCLUSION_CULLING) == 0 && cull_data.occlusion_buffer->is_occluded(cull_data.scenario->instance_aabbs[i].bounds, cull_data.cam_transform.origin, inv_cam_transform, *cull_data.camera_matrix, z_near, cull_data.scenario->instance_data[i].occlusion_timeout))
if (!HIDDEN_BY_VISIBILITY_CHECKS) {
if ((LAYER_CHECK && IN_FRUSTUM(cull_data.cull->frustum) && VIS_CHECK && !OCCLUSION_CULLED) || (cull_data.scenario->instance_data[i].flags & InstanceData::FLAG_IGNORE_ALL_CULLING)) {
@@ -3482,8 +3483,13 @@ bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int
if (p_step == 0) {
if (!RSG::light_storage->reflection_probe_instance_begin_render(reflection_probe->instance, scenario->reflection_atlas)) {
- return true; //all full
+ return true; // All full, no atlas entry to render to.
}
+ } else if (!RSG::light_storage->reflection_probe_has_atlas_index(reflection_probe->instance)) {
+ // We don't have an atlas to render to, just round off.
+ // This is likely due to the atlas being reset.
+ // If so the probe will be marked as dirty and start over.
+ return true;
}
if (p_step >= 0 && p_step < 6) {
@@ -3558,41 +3564,51 @@ void RendererSceneCull::render_probes() {
/* REFLECTION PROBES */
SelfList<InstanceReflectionProbeData> *ref_probe = reflection_probe_render_list.first();
+ Vector<SelfList<InstanceReflectionProbeData> *> done_list;
bool busy = false;
- while (ref_probe) {
- SelfList<InstanceReflectionProbeData> *next = ref_probe->next();
- RID base = ref_probe->self()->owner->base;
+ if (ref_probe) {
+ RENDER_TIMESTAMP("Render ReflectionProbes");
- switch (RSG::light_storage->reflection_probe_get_update_mode(base)) {
- case RS::REFLECTION_PROBE_UPDATE_ONCE: {
- if (busy) { //already rendering something
- break;
- }
+ while (ref_probe) {
+ SelfList<InstanceReflectionProbeData> *next = ref_probe->next();
+ RID base = ref_probe->self()->owner->base;
- bool done = _render_reflection_probe_step(ref_probe->self()->owner, ref_probe->self()->render_step);
- if (done) {
- reflection_probe_render_list.remove(ref_probe);
- } else {
- ref_probe->self()->render_step++;
- }
+ switch (RSG::light_storage->reflection_probe_get_update_mode(base)) {
+ case RS::REFLECTION_PROBE_UPDATE_ONCE: {
+ if (busy) { // Already rendering something.
+ break;
+ }
- busy = true; //do not render another one of this kind
- } break;
- case RS::REFLECTION_PROBE_UPDATE_ALWAYS: {
- int step = 0;
- bool done = false;
- while (!done) {
- done = _render_reflection_probe_step(ref_probe->self()->owner, step);
- step++;
- }
+ bool done = _render_reflection_probe_step(ref_probe->self()->owner, ref_probe->self()->render_step);
+ if (done) {
+ done_list.push_back(ref_probe);
+ } else {
+ ref_probe->self()->render_step++;
+ }
- reflection_probe_render_list.remove(ref_probe);
- } break;
+ busy = true; // Do not render another one of this kind.
+ } break;
+ case RS::REFLECTION_PROBE_UPDATE_ALWAYS: {
+ int step = 0;
+ bool done = false;
+ while (!done) {
+ done = _render_reflection_probe_step(ref_probe->self()->owner, step);
+ step++;
+ }
+
+ done_list.push_back(ref_probe);
+ } break;
+ }
+
+ ref_probe = next;
}
- ref_probe = next;
+ // Now remove from our list
+ for (SelfList<InstanceReflectionProbeData> *rp : done_list) {
+ reflection_probe_render_list.remove(rp);
+ }
}
/* VOXEL GIS */
@@ -4241,6 +4257,7 @@ RendererSceneCull::RendererSceneCull() {
indexer_update_iterations = GLOBAL_GET("rendering/limits/spatial_indexer/update_iterations_per_frame");
thread_cull_threshold = GLOBAL_GET("rendering/limits/spatial_indexer/threaded_cull_minimum_instances");
thread_cull_threshold = MAX(thread_cull_threshold, (uint32_t)WorkerThreadPool::get_singleton()->get_thread_count()); //make sure there is at least one thread per CPU
+ RendererSceneOcclusionCull::HZBuffer::occlusion_jitter_enabled = GLOBAL_GET("rendering/occlusion_culling/jitter_projection");
dummy_occlusion_culling = memnew(RendererSceneOcclusionCull);
diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h
index 86090aa416..0039d14475 100644
--- a/servers/rendering/renderer_scene_cull.h
+++ b/servers/rendering/renderer_scene_cull.h
@@ -44,7 +44,10 @@
#include "servers/rendering/rendering_method.h"
#include "servers/rendering/rendering_server_globals.h"
#include "servers/rendering/storage/utilities.h"
+
+#ifndef _3D_DISABLED
#include "servers/xr/xr_interface.h"
+#endif // _3D_DISABLED
class RenderingLightCuller;
@@ -283,6 +286,13 @@ public:
Instance *instance = nullptr;
int32_t parent_array_index = -1;
int32_t visibility_index = -1;
+
+ // Each time occlusion culling determines an instance is visible,
+ // set this to occlusion_frame plus some delay.
+ // Once the timeout is reached, allow the instance to be occlusion culled.
+ // This creates a delay for occlusion culling, which prevents flickering
+ // when jittering the raster occlusion projection.
+ uint64_t occlusion_timeout = 0;
};
struct InstanceVisibilityData {
diff --git a/servers/rendering/renderer_scene_occlusion_cull.cpp b/servers/rendering/renderer_scene_occlusion_cull.cpp
index c4f0177c73..1f0239411a 100644
--- a/servers/rendering/renderer_scene_occlusion_cull.cpp
+++ b/servers/rendering/renderer_scene_occlusion_cull.cpp
@@ -43,6 +43,8 @@ const Vector3 RendererSceneOcclusionCull::HZBuffer::corners[8] = {
Vector3(1, 1, 1)
};
+bool RendererSceneOcclusionCull::HZBuffer::occlusion_jitter_enabled = false;
+
bool RendererSceneOcclusionCull::HZBuffer::is_empty() const {
return sizes.is_empty();
}
@@ -66,6 +68,8 @@ void RendererSceneOcclusionCull::HZBuffer::clear() {
}
void RendererSceneOcclusionCull::HZBuffer::resize(const Size2i &p_size) {
+ occlusion_buffer_size = p_size;
+
if (p_size == Size2i()) {
clear();
return;
@@ -124,6 +128,9 @@ void RendererSceneOcclusionCull::HZBuffer::resize(const Size2i &p_size) {
}
void RendererSceneOcclusionCull::HZBuffer::update_mips() {
+ // Keep this up to date as a local to be used for occlusion timers.
+ occlusion_frame = Engine::get_singleton()->get_frames_drawn();
+
if (sizes.is_empty()) {
return;
}
diff --git a/servers/rendering/renderer_scene_occlusion_cull.h b/servers/rendering/renderer_scene_occlusion_cull.h
index 565b393094..5adba5dc6a 100644
--- a/servers/rendering/renderer_scene_occlusion_cull.h
+++ b/servers/rendering/renderer_scene_occlusion_cull.h
@@ -53,19 +53,15 @@ public:
PackedByteArray debug_data;
float debug_tex_range = 0.0f;
- public:
- bool is_empty() const;
- virtual void clear();
- virtual void resize(const Size2i &p_size);
-
- void update_mips();
+ uint64_t occlusion_frame = 0;
+ Size2i occlusion_buffer_size;
- _FORCE_INLINE_ bool is_occluded(const real_t p_bounds[6], const Vector3 &p_cam_position, const Transform3D &p_cam_inv_transform, const Projection &p_cam_projection, real_t p_near) const {
+ _FORCE_INLINE_ bool _is_occluded(const real_t p_bounds[6], const Vector3 &p_cam_position, const Transform3D &p_cam_inv_transform, const Projection &p_cam_projection, real_t p_near) const {
if (is_empty()) {
return false;
}
- Vector3 closest_point = Vector3(CLAMP(p_cam_position.x, p_bounds[0], p_bounds[3]), CLAMP(p_cam_position.y, p_bounds[1], p_bounds[4]), CLAMP(p_cam_position.z, p_bounds[2], p_bounds[5]));
+ Vector3 closest_point = p_cam_position.clamp(Vector3(p_bounds[0], p_bounds[1], p_bounds[2]), Vector3(p_bounds[3], p_bounds[4], p_bounds[5]));
if (closest_point == p_cam_position) {
return false;
@@ -154,7 +150,47 @@ public:
return !visible;
}
+ public:
+ static bool occlusion_jitter_enabled;
+
+ bool is_empty() const;
+ virtual void clear();
+ virtual void resize(const Size2i &p_size);
+
+ void update_mips();
+
+ // Thin wrapper around _is_occluded(),
+ // allowing occlusion timers to delay the disappearance
+ // of objects to prevent flickering when using jittering.
+ _FORCE_INLINE_ bool is_occluded(const real_t p_bounds[6], const Vector3 &p_cam_position, const Transform3D &p_cam_inv_transform, const Projection &p_cam_projection, real_t p_near, uint64_t &r_occlusion_timeout) const {
+ bool occluded = _is_occluded(p_bounds, p_cam_position, p_cam_inv_transform, p_cam_projection, p_near);
+
+ // Special case, temporal jitter disabled,
+ // so we don't use occlusion timers.
+ if (!occlusion_jitter_enabled) {
+ return occluded;
+ }
+
+ if (!occluded) {
+//#define DEBUG_RASTER_OCCLUSION_JITTER
+#ifdef DEBUG_RASTER_OCCLUSION_JITTER
+ r_occlusion_timeout = occlusion_frame + 1;
+#else
+ r_occlusion_timeout = occlusion_frame + 9;
+#endif
+ } else if (r_occlusion_timeout) {
+ // Regular timeout, allow occlusion culling
+ // to proceed as normal after the delay.
+ if (occlusion_frame >= r_occlusion_timeout) {
+ r_occlusion_timeout = 0;
+ }
+ }
+
+ return occluded && !r_occlusion_timeout;
+ }
+
RID get_debug_texture();
+ const Size2i &get_occlusion_buffer_size() const { return occlusion_buffer_size; }
virtual ~HZBuffer(){};
};
diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp
index 445a1b265e..31d5a9074c 100644
--- a/servers/rendering/renderer_viewport.cpp
+++ b/servers/rendering/renderer_viewport.cpp
@@ -31,6 +31,7 @@
#include "renderer_viewport.h"
#include "core/config/project_settings.h"
+#include "core/math/transform_interpolator.h"
#include "core/object/worker_thread_pool.h"
#include "renderer_canvas_cull.h"
#include "renderer_scene_cull.h"
@@ -220,6 +221,7 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) {
}
void RendererViewport::_draw_3d(Viewport *p_viewport) {
+#ifndef _3D_DISABLED
RENDER_TIMESTAMP("> Render 3D Scene");
Ref<XRInterface> xr_interface;
@@ -246,6 +248,7 @@ void RendererViewport::_draw_3d(Viewport *p_viewport) {
RSG::scene->render_camera(p_viewport->render_buffers, p_viewport->camera, p_viewport->scenario, p_viewport->self, p_viewport->internal_size, p_viewport->jitter_phase_count, screen_mesh_lod_threshold, p_viewport->shadow_atlas, xr_interface, &p_viewport->render_info);
RENDER_TIMESTAMP("< Render 3D Scene");
+#endif // _3D_DISABLED
}
void RendererViewport::_draw_viewport(Viewport *p_viewport) {
@@ -337,7 +340,14 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
if (!F->enabled) {
continue;
}
- F->xform_cache = xf * F->xform;
+
+ if (!RSG::canvas->_interpolation_data.interpolation_enabled || !F->interpolated) {
+ F->xform_cache = xf * F->xform_curr;
+ } else {
+ real_t f = Engine::get_singleton()->get_physics_interpolation_fraction();
+ TransformInterpolator::interpolate_transform_2d(F->xform_prev, F->xform_curr, F->xform_cache, f);
+ F->xform_cache = xf * F->xform_cache;
+ }
if (sdf_rect.intersects_transformed(F->xform_cache, F->aabb_cache)) {
F->next = occluders;
@@ -376,7 +386,14 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
Vector2 offset = tsize / 2.0;
cl->rect_cache = Rect2(-offset + cl->texture_offset, tsize);
- cl->xform_cache = xf * cl->xform;
+
+ if (!RSG::canvas->_interpolation_data.interpolation_enabled || !cl->interpolated) {
+ cl->xform_cache = xf * cl->xform_curr;
+ } else {
+ real_t f = Engine::get_singleton()->get_physics_interpolation_fraction();
+ TransformInterpolator::interpolate_transform_2d(cl->xform_prev, cl->xform_curr, cl->xform_cache, f);
+ cl->xform_cache = xf * cl->xform_cache;
+ }
if (clip_rect.intersects_transformed(cl->xform_cache, cl->rect_cache)) {
cl->filter_next_ptr = lights;
@@ -384,7 +401,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
Transform2D scale;
scale.scale(cl->rect_cache.size);
scale.columns[2] = cl->rect_cache.position;
- cl->light_shader_xform = xf * cl->xform * scale;
+ cl->light_shader_xform = cl->xform_cache * scale;
if (cl->use_shadow) {
cl->shadows_next_ptr = lights_with_shadow;
if (lights_with_shadow == nullptr) {
@@ -404,7 +421,13 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
if (cl->enabled) {
cl->filter_next_ptr = directional_lights;
directional_lights = cl;
- cl->xform_cache = xf * cl->xform;
+ if (!RSG::canvas->_interpolation_data.interpolation_enabled || !cl->interpolated) {
+ cl->xform_cache = xf * cl->xform_curr;
+ } else {
+ real_t f = Engine::get_singleton()->get_physics_interpolation_fraction();
+ TransformInterpolator::interpolate_transform_2d(cl->xform_prev, cl->xform_curr, cl->xform_cache, f);
+ cl->xform_cache = xf * cl->xform_cache;
+ }
cl->xform_cache.columns[2] = Vector2(); //translation is pointless
if (cl->use_shadow) {
cl->shadows_next_ptr = directional_lights_with_shadow;
@@ -439,7 +462,13 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
if (!F->enabled) {
continue;
}
- F->xform_cache = xf * F->xform;
+ if (!RSG::canvas->_interpolation_data.interpolation_enabled || !F->interpolated) {
+ F->xform_cache = xf * F->xform_curr;
+ } else {
+ real_t f = Engine::get_singleton()->get_physics_interpolation_fraction();
+ TransformInterpolator::interpolate_transform_2d(F->xform_prev, F->xform_curr, F->xform_cache, f);
+ F->xform_cache = xf * F->xform_cache;
+ }
if (shadow_rect.intersects_transformed(F->xform_cache, F->aabb_cache)) {
F->next = occluders;
occluders = F;
@@ -519,7 +548,13 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
if (!F->enabled) {
continue;
}
- F->xform_cache = xf * F->xform;
+ if (!RSG::canvas->_interpolation_data.interpolation_enabled || !F->interpolated) {
+ F->xform_cache = xf * F->xform_curr;
+ } else {
+ real_t f = Engine::get_singleton()->get_physics_interpolation_fraction();
+ TransformInterpolator::interpolate_transform_2d(F->xform_prev, F->xform_curr, F->xform_cache, f);
+ F->xform_cache = xf * F->xform_cache;
+ }
Transform2D localizer = F->xform_cache.affine_inverse();
for (int j = 0; j < point_count; j++) {
@@ -629,6 +664,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
void RendererViewport::draw_viewports(bool p_swap_buffers) {
timestamp_vp_map.clear();
+#ifndef _3D_DISABLED
// get our xr interface in case we need it
Ref<XRInterface> xr_interface;
XRServer *xr_server = XRServer::get_singleton();
@@ -639,6 +675,7 @@ void RendererViewport::draw_viewports(bool p_swap_buffers) {
// retrieve the interface responsible for rendering
xr_interface = xr_server->get_primary_interface();
}
+#endif // _3D_DISABLED
if (Engine::get_singleton()->is_editor_hint()) {
set_default_clear_color(GLOBAL_GET("rendering/environment/defaults/default_clear_color"));
@@ -671,6 +708,7 @@ void RendererViewport::draw_viewports(bool p_swap_buffers) {
bool visible = vp->viewport_to_screen_rect != Rect2();
+#ifndef _3D_DISABLED
if (vp->use_xr) {
if (xr_interface.is_valid()) {
// Ignore update mode we have to commit frames to our XR interface
@@ -684,7 +722,9 @@ void RendererViewport::draw_viewports(bool p_swap_buffers) {
visible = false;
vp->size = Size2();
}
- } else {
+ } else
+#endif // _3D_DISABLED
+ {
if (vp->update_mode == RS::VIEWPORT_UPDATE_ALWAYS || vp->update_mode == RS::VIEWPORT_UPDATE_ONCE) {
visible = true;
}
@@ -722,6 +762,7 @@ void RendererViewport::draw_viewports(bool p_swap_buffers) {
RENDER_TIMESTAMP("> Render Viewport " + itos(i));
RSG::texture_storage->render_target_set_as_unused(vp->render_target);
+#ifndef _3D_DISABLED
if (vp->use_xr && xr_interface.is_valid()) {
// Inform XR interface we're about to render its viewport,
// if this returns false we don't render.
@@ -758,9 +799,9 @@ void RendererViewport::draw_viewports(bool p_swap_buffers) {
RSG::rasterizer->end_viewport(p_swap_buffers && blits.size() > 0);
}
}
- } else {
- RSG::texture_storage->render_target_set_override(vp->render_target, RID(), RID(), RID());
-
+ } else
+#endif // _3D_DISABLED
+ {
RSG::scene->set_debug_draw_mode(vp->debug_draw);
// render standard mono camera
@@ -1019,6 +1060,13 @@ void RendererViewport::viewport_set_update_mode(RID p_viewport, RS::ViewportUpda
viewport->update_mode = p_mode;
}
+RS::ViewportUpdateMode RendererViewport::viewport_get_update_mode(RID p_viewport) const {
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
+ ERR_FAIL_NULL_V(viewport, RS::VIEWPORT_UPDATE_DISABLED);
+
+ return viewport->update_mode;
+}
+
RID RendererViewport::viewport_get_render_target(RID p_viewport) const {
const Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_NULL_V(viewport, RID());
@@ -1148,6 +1196,9 @@ 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.get_or_null(p_viewport);
ERR_FAIL_NULL(viewport);
+ if (viewport->transparent_bg == p_enabled) {
+ return;
+ }
RSG::texture_storage->render_target_set_transparent(viewport->render_target, p_enabled);
viewport->transparent_bg = p_enabled;
diff --git a/servers/rendering/renderer_viewport.h b/servers/rendering/renderer_viewport.h
index a0ec9e6318..5107398c54 100644
--- a/servers/rendering/renderer_viewport.h
+++ b/servers/rendering/renderer_viewport.h
@@ -37,9 +37,12 @@
#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering/rendering_method.h"
#include "servers/rendering_server.h"
-#include "servers/xr/xr_interface.h"
#include "storage/render_scene_buffers.h"
+#ifndef _3D_DISABLED
+#include "servers/xr/xr_interface.h"
+#endif // _3D_DISABLED
+
class RendererViewport {
public:
struct CanvasBase {
@@ -233,6 +236,7 @@ public:
void viewport_set_texture_mipmap_bias(RID p_viewport, float p_mipmap_bias);
void viewport_set_update_mode(RID p_viewport, RS::ViewportUpdateMode p_mode);
+ RS::ViewportUpdateMode viewport_get_update_mode(RID p_viewport) const;
void viewport_set_vflip(RID p_viewport, bool p_enable);
void viewport_set_clear_mode(RID p_viewport, RS::ViewportClearMode p_clear_mode);
diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp
index 943d6b364b..2b6644e893 100644
--- a/servers/rendering/rendering_device.cpp
+++ b/servers/rendering/rendering_device.cpp
@@ -5089,14 +5089,15 @@ Error RenderingDevice::initialize(RenderingContextDriver *p_context, DisplayServ
draw_list = nullptr;
compute_list = nullptr;
- if (main_instance) {
+ bool project_pipeline_cache_enable = GLOBAL_GET("rendering/rendering_device/pipeline_cache/enable");
+ if (main_instance && project_pipeline_cache_enable) {
// Only the instance that is not a local device and is also the singleton is allowed to manage a pipeline cache.
- pipeline_cache_file_path = "user://vulkan/pipelines";
- pipeline_cache_file_path += "." + device.name.validate_filename().replace(" ", "_").to_lower();
+ pipeline_cache_file_path = vformat("user://vulkan/pipelines.%s.%s",
+ OS::get_singleton()->get_current_rendering_method(),
+ device.name.validate_filename().replace(" ", "_").to_lower());
if (Engine::get_singleton()->is_editor_hint()) {
pipeline_cache_file_path += ".editor";
}
-
pipeline_cache_file_path += ".cache";
Vector<uint8_t> cache_data = _load_pipeline_cache();
@@ -5182,7 +5183,7 @@ void RenderingDevice::_save_pipeline_cache(void *p_data) {
}
}
-template <class T>
+template <typename T>
void RenderingDevice::_free_rids(T &p_owner, const char *p_type) {
List<RID> owned;
p_owner.get_owned_list(&owned);
@@ -5223,8 +5224,12 @@ uint64_t RenderingDevice::get_driver_resource(DriverResource p_resource, RID p_r
case DRIVER_RESOURCE_LOGICAL_DEVICE:
case DRIVER_RESOURCE_PHYSICAL_DEVICE:
case DRIVER_RESOURCE_TOPMOST_OBJECT:
+ break;
case DRIVER_RESOURCE_COMMAND_QUEUE:
+ driver_id = main_queue.id;
+ break;
case DRIVER_RESOURCE_QUEUE_FAMILY:
+ driver_id = main_queue_family.id;
break;
case DRIVER_RESOURCE_TEXTURE:
case DRIVER_RESOURCE_TEXTURE_VIEW:
@@ -5232,19 +5237,19 @@ uint64_t RenderingDevice::get_driver_resource(DriverResource p_resource, RID p_r
Texture *tex = texture_owner.get_or_null(p_rid);
ERR_FAIL_NULL_V(tex, 0);
- driver_id = tex->driver_id;
+ driver_id = tex->driver_id.id;
} break;
case DRIVER_RESOURCE_SAMPLER: {
RDD::SamplerID *sampler_driver_id = sampler_owner.get_or_null(p_rid);
ERR_FAIL_NULL_V(sampler_driver_id, 0);
- driver_id = *sampler_driver_id;
+ driver_id = (*sampler_driver_id).id;
} break;
case DRIVER_RESOURCE_UNIFORM_SET: {
UniformSet *uniform_set = uniform_set_owner.get_or_null(p_rid);
ERR_FAIL_NULL_V(uniform_set, 0);
- driver_id = uniform_set->driver_id;
+ driver_id = uniform_set->driver_id.id;
} break;
case DRIVER_RESOURCE_BUFFER: {
Buffer *buffer = nullptr;
@@ -5261,19 +5266,19 @@ uint64_t RenderingDevice::get_driver_resource(DriverResource p_resource, RID p_r
}
ERR_FAIL_NULL_V(buffer, 0);
- driver_id = buffer->driver_id;
+ driver_id = buffer->driver_id.id;
} break;
case DRIVER_RESOURCE_COMPUTE_PIPELINE: {
ComputePipeline *compute_pipeline = compute_pipeline_owner.get_or_null(p_rid);
ERR_FAIL_NULL_V(compute_pipeline, 0);
- driver_id = compute_pipeline->driver_id;
+ driver_id = compute_pipeline->driver_id.id;
} break;
case DRIVER_RESOURCE_RENDER_PIPELINE: {
RenderPipeline *render_pipeline = render_pipeline_owner.get_or_null(p_rid);
ERR_FAIL_NULL_V(render_pipeline, 0);
- driver_id = render_pipeline->driver_id;
+ driver_id = render_pipeline->driver_id.id;
} break;
default: {
ERR_FAIL_V(0);
diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h
index 8c88c08950..c8277024cf 100644
--- a/servers/rendering/rendering_device.h
+++ b/servers/rendering/rendering_device.h
@@ -1103,7 +1103,7 @@ private:
public:
DrawListID draw_list_begin_for_screen(DisplayServer::WindowID p_screen = 0, const Color &p_clear_color = Color());
- DrawListID draw_list_begin(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2());
+ DrawListID draw_list_begin(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 0.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2());
void draw_list_set_blend_constants(DrawListID p_list, const Color &p_color);
void draw_list_bind_render_pipeline(DrawListID p_list, RID p_render_pipeline);
@@ -1294,7 +1294,7 @@ private:
void _stall_for_previous_frames();
void _flush_and_stall_for_all_frames();
- template <class T>
+ template <typename T>
void _free_rids(T &p_owner, const char *p_type);
#ifdef DEV_ENABLED
diff --git a/servers/rendering/rendering_device_commons.cpp b/servers/rendering/rendering_device_commons.cpp
index c8b7980633..4dbd0e3964 100644
--- a/servers/rendering/rendering_device_commons.cpp
+++ b/servers/rendering/rendering_device_commons.cpp
@@ -711,12 +711,13 @@ uint32_t RenderingDeviceCommons::get_image_format_required_size(DataFormat p_for
uint32_t pixel_size = get_image_format_pixel_size(p_format);
uint32_t pixel_rshift = get_compressed_image_format_pixel_rshift(p_format);
- uint32_t blockw, blockh;
+ uint32_t blockw = 0;
+ uint32_t blockh = 0;
get_compressed_image_format_block_dimensions(p_format, blockw, blockh);
for (uint32_t i = 0; i < p_mipmaps; i++) {
- uint32_t bw = w % blockw != 0 ? w + (blockw - w % blockw) : w;
- uint32_t bh = h % blockh != 0 ? h + (blockh - h % blockh) : h;
+ uint32_t bw = STEPIFY(w, blockw);
+ uint32_t bh = STEPIFY(h, blockh);
uint32_t s = bw * bh;
diff --git a/servers/rendering/rendering_device_commons.h b/servers/rendering/rendering_device_commons.h
index 688a6441a7..28d641c879 100644
--- a/servers/rendering/rendering_device_commons.h
+++ b/servers/rendering/rendering_device_commons.h
@@ -878,6 +878,7 @@ protected:
static const char *SHADER_STAGE_NAMES[SHADER_STAGE_MAX];
+public:
struct ShaderUniform {
UniformType type = UniformType::UNIFORM_TYPE_MAX;
bool writable = false;
@@ -911,6 +912,8 @@ protected:
struct ShaderSpecializationConstant : public PipelineSpecializationConstant {
BitField<ShaderStage> stages;
+
+ bool operator<(const ShaderSpecializationConstant &p_other) const { return constant_id < p_other.constant_id; }
};
struct ShaderDescription {
@@ -925,6 +928,7 @@ protected:
Vector<ShaderStage> stages;
};
+protected:
struct ShaderReflection : public ShaderDescription {
BitField<ShaderStage> stages;
BitField<ShaderStage> push_constant_stages;
diff --git a/servers/rendering/rendering_device_driver.cpp b/servers/rendering/rendering_device_driver.cpp
index 9e05a6a133..be74467340 100644
--- a/servers/rendering/rendering_device_driver.cpp
+++ b/servers/rendering/rendering_device_driver.cpp
@@ -265,6 +265,8 @@ Error RenderingDeviceDriver::_reflect_spirv(VectorView<ShaderStageSPIRVData> p_s
r_reflection.specialization_constants.push_back(sconst);
}
}
+
+ r_reflection.specialization_constants.sort();
}
}
diff --git a/servers/rendering/rendering_device_driver.h b/servers/rendering/rendering_device_driver.h
index ee33dc103c..e9464ba321 100644
--- a/servers/rendering/rendering_device_driver.h
+++ b/servers/rendering/rendering_device_driver.h
@@ -56,7 +56,7 @@
// This may one day be used in Godot for interoperability between C arrays, Vector and LocalVector.
// (See https://github.com/godotengine/godot-proposals/issues/5144.)
-template <class T>
+template <typename T>
class VectorView {
const T *_ptr = nullptr;
const uint32_t _size = 0;
@@ -97,20 +97,20 @@ public:
#define ENUM_MEMBERS_EQUAL(m_a, m_b) ((int64_t)m_a == (int64_t)m_b)
// This helps using a single paged allocator for many resource types.
-template <class... RESOURCE_TYPES>
+template <typename... RESOURCE_TYPES>
struct VersatileResourceTemplate {
static constexpr size_t RESOURCE_SIZES[] = { sizeof(RESOURCE_TYPES)... };
static constexpr size_t MAX_RESOURCE_SIZE = std::max_element(RESOURCE_SIZES, RESOURCE_SIZES + sizeof...(RESOURCE_TYPES))[0];
uint8_t data[MAX_RESOURCE_SIZE];
- template <class T>
+ template <typename T>
static T *allocate(PagedAllocator<VersatileResourceTemplate> &p_allocator) {
T *obj = (T *)p_allocator.alloc();
memnew_placement(obj, T);
return obj;
}
- template <class T>
+ template <typename T>
static void free(PagedAllocator<VersatileResourceTemplate> &p_allocator, T *p_object) {
p_object->~T();
p_allocator.free((VersatileResourceTemplate *)p_object);
@@ -128,7 +128,7 @@ public:
#define DEFINE_ID(m_name) \
struct m_name##ID : public ID { \
- _ALWAYS_INLINE_ operator bool() const { return id != 0; } \
+ _ALWAYS_INLINE_ explicit operator bool() const { return id != 0; } \
_ALWAYS_INLINE_ m_name##ID &operator=(m_name##ID p_other) { \
id = p_other.id; \
return *this; \
diff --git a/servers/rendering/rendering_device_graph.cpp b/servers/rendering/rendering_device_graph.cpp
index 4b85d1c2bf..adac7ee3eb 100644
--- a/servers/rendering/rendering_device_graph.cpp
+++ b/servers/rendering/rendering_device_graph.cpp
@@ -261,7 +261,7 @@ void RenderingDeviceGraph::_add_command_to_graph(ResourceTracker **p_resource_tr
}
if (resource_tracker->parent->usage == RESOURCE_USAGE_NONE) {
- if (resource_tracker->parent->texture_driver_id != 0) {
+ if (resource_tracker->parent->texture_driver_id.id != 0) {
// If the resource is a texture, we transition it entirely to the layout determined by the first slice that uses it.
_add_texture_barrier_to_command(resource_tracker->parent->texture_driver_id, RDD::BarrierAccessBits(0), new_usage_access, RDG::RESOURCE_USAGE_NONE, new_resource_usage, resource_tracker->parent->texture_subresources, command_normalization_barriers, r_command->normalization_barrier_index, r_command->normalization_barrier_count);
}
@@ -324,7 +324,7 @@ void RenderingDeviceGraph::_add_command_to_graph(ResourceTracker **p_resource_tr
ERR_FAIL_MSG("Texture slices that overlap can't be used in the same command.");
} else {
// Delete the slice from the dirty list and revert it to the usage of the parent.
- if (current_tracker->texture_driver_id != 0) {
+ if (current_tracker->texture_driver_id.id != 0) {
_add_texture_barrier_to_command(current_tracker->texture_driver_id, current_tracker->usage_access, new_usage_access, current_tracker->usage, resource_tracker->parent->usage, current_tracker->texture_subresources, command_normalization_barriers, r_command->normalization_barrier_index, r_command->normalization_barrier_count);
// Merge the area of the slice with the current tracking area of the command and indicate it's a write usage as well.
@@ -383,7 +383,7 @@ void RenderingDeviceGraph::_add_command_to_graph(ResourceTracker **p_resource_tr
while (current_tracker != nullptr) {
current_tracker->reset_if_outdated(tracking_frame);
- if (current_tracker->texture_driver_id != 0) {
+ if (current_tracker->texture_driver_id.id != 0) {
// Transition all slices to the layout of the parent resource.
_add_texture_barrier_to_command(current_tracker->texture_driver_id, current_tracker->usage_access, new_usage_access, current_tracker->usage, resource_tracker->usage, current_tracker->texture_subresources, command_normalization_barriers, r_command->normalization_barrier_index, r_command->normalization_barrier_count);
}
diff --git a/servers/rendering/rendering_light_culler.cpp b/servers/rendering/rendering_light_culler.cpp
index 3d82683bc2..0889898f0b 100644
--- a/servers/rendering/rendering_light_culler.cpp
+++ b/servers/rendering/rendering_light_culler.cpp
@@ -33,7 +33,6 @@
#include "core/math/plane.h"
#include "core/math/projection.h"
#include "rendering_server_globals.h"
-#include "scene/3d/camera_3d.h"
#ifdef RENDERING_LIGHT_CULLER_DEBUG_STRINGS
const char *RenderingLightCuller::Data::string_planes[] = {
@@ -428,15 +427,19 @@ bool RenderingLightCuller::_add_light_camera_planes(LightCullPlanes &r_cull_plan
uint8_t *entry = &data.LUT_entries[lookup][0];
int n_edges = data.LUT_entry_sizes[lookup] - 1;
+ const Vector3 &pt2 = p_light_source.pos;
+
for (int e = 0; e < n_edges; e++) {
int i0 = entry[e];
int i1 = entry[e + 1];
const Vector3 &pt0 = data.frustum_points[i0];
const Vector3 &pt1 = data.frustum_points[i1];
- // Create plane from 3 points.
- Plane p(pt0, pt1, p_light_source.pos);
- r_cull_planes.add_cull_plane(p);
+ if (!_is_colinear_tri(pt0, pt1, pt2)) {
+ // Create plane from 3 points.
+ Plane p(pt0, pt1, pt2);
+ r_cull_planes.add_cull_plane(p);
+ }
}
// Last to 0 edge.
@@ -447,9 +450,11 @@ bool RenderingLightCuller::_add_light_camera_planes(LightCullPlanes &r_cull_plan
const Vector3 &pt0 = data.frustum_points[i0];
const Vector3 &pt1 = data.frustum_points[i1];
- // Create plane from 3 points.
- Plane p(pt0, pt1, p_light_source.pos);
- r_cull_planes.add_cull_plane(p);
+ if (!_is_colinear_tri(pt0, pt1, pt2)) {
+ // Create plane from 3 points.
+ Plane p(pt0, pt1, pt2);
+ r_cull_planes.add_cull_plane(p);
+ }
}
#ifdef LIGHT_CULLER_DEBUG_LOGGING
diff --git a/servers/rendering/rendering_light_culler.h b/servers/rendering/rendering_light_culler.h
index 602543850a..0bf975430b 100644
--- a/servers/rendering/rendering_light_culler.h
+++ b/servers/rendering/rendering_light_culler.h
@@ -163,6 +163,39 @@ private:
bool _prepare_light(const RendererSceneCull::Instance &p_instance, int32_t p_directional_light_id = -1);
+ // Avoid adding extra culling planes derived from near colinear triangles.
+ // The normals derived from these will be inaccurate, and can lead to false
+ // culling of objects that should be within the light volume.
+ bool _is_colinear_tri(const Vector3 &p_a, const Vector3 &p_b, const Vector3 &p_c) const {
+ // Lengths of sides a, b and c.
+ float la = (p_b - p_a).length();
+ float lb = (p_c - p_b).length();
+ float lc = (p_c - p_a).length();
+
+ // Get longest side into lc.
+ if (lb < la) {
+ SWAP(la, lb);
+ }
+ if (lc < lb) {
+ SWAP(lb, lc);
+ }
+
+ // Prevent divide by zero.
+ if (lc > 0.00001f) {
+ // If the summed length of the smaller two
+ // sides is close to the length of the longest side,
+ // the points are colinear, and the triangle is near degenerate.
+ float ld = ((la + lb) - lc) / lc;
+
+ // ld will be close to zero for colinear tris.
+ return ld < 0.00001f;
+ }
+
+ // Don't create planes from tiny triangles,
+ // they won't be accurate.
+ return true;
+ }
+
// Internal version uses LightSource.
bool _add_light_camera_planes(LightCullPlanes &r_cull_planes, const LightSource &p_light_source);
diff --git a/servers/rendering/rendering_method.h b/servers/rendering/rendering_method.h
index 4569846752..aa5e7d83cc 100644
--- a/servers/rendering/rendering_method.h
+++ b/servers/rendering/rendering_method.h
@@ -33,7 +33,14 @@
#include "servers/rendering/storage/render_scene_buffers.h"
#include "servers/rendering_server.h"
+
+#ifdef _3D_DISABLED
+// RendererSceneCull::render_camera is empty when 3D is disabled, but
+// it and RenderingMethod::render_camera have a parameter for XRInterface.
+#define XRInterface RefCounted
+#else // 3D enabled
#include "servers/xr/xr_interface.h"
+#endif // _3D_DISABLED
class RenderingMethod {
public:
diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp
index bf8ab27722..5bf0ab0ba6 100644
--- a/servers/rendering/rendering_server_default.cpp
+++ b/servers/rendering/rendering_server_default.cpp
@@ -80,6 +80,7 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
uint64_t time_usec = OS::get_singleton()->get_ticks_usec();
+ RENDER_TIMESTAMP("Prepare Render Frame");
RSG::scene->update(); //update scenes stuff before updating instances
frame_setup_time = double(OS::get_singleton()->get_ticks_usec() - time_usec) / 1000.0;
@@ -93,11 +94,13 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
RSG::rasterizer->end_frame(p_swap_buffers);
+#ifndef _3D_DISABLED
XRServer *xr_server = XRServer::get_singleton();
if (xr_server != nullptr) {
// let our XR server know we're done so we can get our frame timing
xr_server->end_frame();
}
+#endif // _3D_DISABLED
RSG::canvas->update_visibility_notifiers();
RSG::scene->update_visibility_notifiers();
@@ -368,6 +371,16 @@ void RenderingServerDefault::_thread_loop() {
_finish();
}
+/* INTERPOLATION */
+
+void RenderingServerDefault::tick() {
+ RSG::canvas->tick();
+}
+
+void RenderingServerDefault::set_physics_interpolation_enabled(bool p_enabled) {
+ RSG::canvas->set_physics_interpolation_enabled(p_enabled);
+}
+
/* EVENT QUEUING */
void RenderingServerDefault::sync() {
diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h
index 17622ba311..c50472c0cd 100644
--- a/servers/rendering/rendering_server_default.h
+++ b/servers/rendering/rendering_server_default.h
@@ -625,6 +625,7 @@ public:
FUNC2(viewport_set_texture_mipmap_bias, RID, float)
FUNC2(viewport_set_update_mode, RID, ViewportUpdateMode)
+ FUNC1RC(ViewportUpdateMode, viewport_get_update_mode, RID)
FUNC1RC(RID, viewport_get_render_target, RID)
FUNC1RC(RID, viewport_get_texture, RID)
@@ -852,6 +853,7 @@ public:
FUNCRIDSPLIT(canvas)
FUNC3(canvas_set_item_mirroring, RID, RID, const Point2 &)
+ FUNC3(canvas_set_item_repeat, RID, const Point2 &, int)
FUNC2(canvas_set_modulate, RID, const Color &)
FUNC3(canvas_set_parent, RID, RID, float)
FUNC1(canvas_set_disable_scale, bool)
@@ -925,6 +927,10 @@ public:
FUNC1(canvas_item_set_debug_redraw, bool)
FUNC0RC(bool, canvas_item_get_debug_redraw)
+ FUNC2(canvas_item_set_interpolated, RID, bool)
+ FUNC1(canvas_item_reset_physics_interpolation, RID)
+ FUNC2(canvas_item_transform_physics_interpolation, RID, const Transform2D &)
+
FUNCRIDSPLIT(canvas_light)
FUNC2(canvas_light_set_mode, RID, CanvasLightMode)
@@ -951,6 +957,10 @@ public:
FUNC2(canvas_light_set_shadow_color, RID, const Color &)
FUNC2(canvas_light_set_shadow_smooth, RID, float)
+ FUNC2(canvas_light_set_interpolated, RID, bool)
+ FUNC1(canvas_light_reset_physics_interpolation, RID)
+ FUNC2(canvas_light_transform_physics_interpolation, RID, const Transform2D &)
+
FUNCRIDSPLIT(canvas_light_occluder)
FUNC2(canvas_light_occluder_attach_to_canvas, RID, RID)
FUNC2(canvas_light_occluder_set_enabled, RID, bool)
@@ -959,6 +969,10 @@ public:
FUNC2(canvas_light_occluder_set_transform, RID, const Transform2D &)
FUNC2(canvas_light_occluder_set_light_mask, RID, int)
+ FUNC2(canvas_light_occluder_set_interpolated, RID, bool)
+ FUNC1(canvas_light_occluder_reset_physics_interpolation, RID)
+ FUNC2(canvas_light_occluder_transform_physics_interpolation, RID, const Transform2D &)
+
FUNCRIDSPLIT(canvas_occluder_polygon)
FUNC3(canvas_occluder_polygon_set_shape, RID, const Vector<Vector2> &, bool)
@@ -1020,6 +1034,11 @@ public:
}
}
+ /* INTERPOLATION */
+
+ virtual void tick() override;
+ virtual void set_physics_interpolation_enabled(bool p_enabled) override;
+
/* EVENT QUEUING */
virtual void request_frame_drawn_callback(const Callable &p_callable) override;
diff --git a/servers/rendering/shader_compiler.h b/servers/rendering/shader_compiler.h
index e0ec42a4d1..66106d7eb7 100644
--- a/servers/rendering/shader_compiler.h
+++ b/servers/rendering/shader_compiler.h
@@ -91,8 +91,8 @@ public:
HashMap<StringName, String> render_mode_defines;
HashMap<StringName, String> usage_defines;
HashMap<StringName, String> custom_samplers;
- ShaderLanguage::TextureFilter default_filter = ShaderLanguage::TextureFilter::FILTER_DEFAULT;
- ShaderLanguage::TextureRepeat default_repeat = ShaderLanguage::TextureRepeat::REPEAT_DEFAULT;
+ ShaderLanguage::TextureFilter default_filter = ShaderLanguage::TextureFilter::FILTER_NEAREST;
+ ShaderLanguage::TextureRepeat default_repeat = ShaderLanguage::TextureRepeat::REPEAT_DISABLE;
int base_texture_binding_index = 0;
int texture_layout_set = 0;
String base_uniform_string;
diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h
index 737545b8ca..816a202b50 100644
--- a/servers/rendering/shader_language.h
+++ b/servers/rendering/shader_language.h
@@ -383,7 +383,7 @@ public:
virtual ~Node() {}
};
- template <class T>
+ template <typename T>
T *alloc_node() {
T *node = memnew(T);
node->next = nodes;
diff --git a/servers/rendering/storage/light_storage.h b/servers/rendering/storage/light_storage.h
index 27407305d1..d439598f3d 100644
--- a/servers/rendering/storage/light_storage.h
+++ b/servers/rendering/storage/light_storage.h
@@ -143,6 +143,7 @@ public:
virtual RID reflection_probe_instance_create(RID p_probe) = 0;
virtual void reflection_probe_instance_free(RID p_instance) = 0;
virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) = 0;
+ virtual bool reflection_probe_has_atlas_index(RID p_instance) = 0;
virtual void reflection_probe_release_atlas_index(RID p_instance) = 0;
virtual bool reflection_probe_instance_needs_redraw(RID p_instance) = 0;
virtual bool reflection_probe_instance_has_reflection(RID p_instance) = 0;
diff --git a/servers/rendering/storage/variant_converters.h b/servers/rendering/storage/variant_converters.h
index 6e3c07237e..7dbdb0f517 100644
--- a/servers/rendering/storage/variant_converters.h
+++ b/servers/rendering/storage/variant_converters.h
@@ -242,10 +242,10 @@ inline bool is_convertible_array(Variant::Type type) {
type == Variant::PACKED_COLOR_ARRAY;
}
-template <class, class = void>
+template <typename, typename = void>
inline constexpr bool is_vector_type_v = false;
-template <class T>
+template <typename T>
inline constexpr bool is_vector_type_v<T, std::void_t<decltype(T::AXIS_COUNT)>> = true;
template <typename T, typename P>
diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp
index e5d8800366..96d317ebd3 100644
--- a/servers/rendering_server.cpp
+++ b/servers/rendering_server.cpp
@@ -2209,15 +2209,15 @@ void RenderingServer::fix_surface_compatibility(SurfaceData &p_surface, const St
#ifdef TOOLS_ENABLED
void RenderingServer::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const {
- String pf = p_function;
+ const String pf = p_function;
if (p_idx == 0) {
if (pf == "global_shader_parameter_set" || pf == "global_shader_parameter_set_override" ||
pf == "global_shader_parameter_get" || pf == "global_shader_parameter_get_type" || pf == "global_shader_parameter_remove") {
- for (StringName E : global_shader_parameter_get_list()) {
+ for (const StringName &E : global_shader_parameter_get_list()) {
r_options->push_back(E.operator String().quote());
}
} else if (pf == "has_os_feature") {
- for (String E : { "\"rgtc\"", "\"s3tc\"", "\"bptc\"", "\"etc\"", "\"etc2\"", "\"astc\"" }) {
+ for (const String E : { "\"rgtc\"", "\"s3tc\"", "\"bptc\"", "\"etc\"", "\"etc2\"", "\"astc\"" }) {
r_options->push_back(E);
}
}
@@ -2783,6 +2783,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("viewport_set_fsr_sharpness", "viewport", "sharpness"), &RenderingServer::viewport_set_fsr_sharpness);
ClassDB::bind_method(D_METHOD("viewport_set_texture_mipmap_bias", "viewport", "mipmap_bias"), &RenderingServer::viewport_set_texture_mipmap_bias);
ClassDB::bind_method(D_METHOD("viewport_set_update_mode", "viewport", "update_mode"), &RenderingServer::viewport_set_update_mode);
+ ClassDB::bind_method(D_METHOD("viewport_get_update_mode", "viewport"), &RenderingServer::viewport_get_update_mode);
ClassDB::bind_method(D_METHOD("viewport_set_clear_mode", "viewport", "clear_mode"), &RenderingServer::viewport_set_clear_mode);
ClassDB::bind_method(D_METHOD("viewport_get_render_target", "viewport"), &RenderingServer::viewport_get_render_target);
ClassDB::bind_method(D_METHOD("viewport_get_texture", "viewport"), &RenderingServer::viewport_get_texture);
@@ -3186,6 +3187,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("canvas_create"), &RenderingServer::canvas_create);
ClassDB::bind_method(D_METHOD("canvas_set_item_mirroring", "canvas", "item", "mirroring"), &RenderingServer::canvas_set_item_mirroring);
+ ClassDB::bind_method(D_METHOD("canvas_set_item_repeat", "item", "repeat_size", "repeat_times"), &RenderingServer::canvas_set_item_repeat);
ClassDB::bind_method(D_METHOD("canvas_set_modulate", "canvas", "color"), &RenderingServer::canvas_set_modulate);
ClassDB::bind_method(D_METHOD("canvas_set_disable_scale", "disable"), &RenderingServer::canvas_set_disable_scale);
@@ -3218,6 +3220,9 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("canvas_item_set_modulate", "item", "color"), &RenderingServer::canvas_item_set_modulate);
ClassDB::bind_method(D_METHOD("canvas_item_set_self_modulate", "item", "color"), &RenderingServer::canvas_item_set_self_modulate);
ClassDB::bind_method(D_METHOD("canvas_item_set_draw_behind_parent", "item", "enabled"), &RenderingServer::canvas_item_set_draw_behind_parent);
+ ClassDB::bind_method(D_METHOD("canvas_item_set_interpolated", "item", "interpolated"), &RenderingServer::canvas_item_set_interpolated);
+ ClassDB::bind_method(D_METHOD("canvas_item_reset_physics_interpolation", "item"), &RenderingServer::canvas_item_reset_physics_interpolation);
+ ClassDB::bind_method(D_METHOD("canvas_item_transform_physics_interpolation", "item", "transform"), &RenderingServer::canvas_item_transform_physics_interpolation);
/* Primitives */
@@ -3301,6 +3306,9 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_color", "light", "color"), &RenderingServer::canvas_light_set_shadow_color);
ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_smooth", "light", "smooth"), &RenderingServer::canvas_light_set_shadow_smooth);
ClassDB::bind_method(D_METHOD("canvas_light_set_blend_mode", "light", "mode"), &RenderingServer::canvas_light_set_blend_mode);
+ ClassDB::bind_method(D_METHOD("canvas_light_set_interpolated", "light", "interpolated"), &RenderingServer::canvas_light_set_interpolated);
+ ClassDB::bind_method(D_METHOD("canvas_light_reset_physics_interpolation", "light"), &RenderingServer::canvas_light_reset_physics_interpolation);
+ ClassDB::bind_method(D_METHOD("canvas_light_transform_physics_interpolation", "light", "transform"), &RenderingServer::canvas_light_transform_physics_interpolation);
BIND_ENUM_CONSTANT(CANVAS_LIGHT_MODE_POINT);
BIND_ENUM_CONSTANT(CANVAS_LIGHT_MODE_DIRECTIONAL);
@@ -3323,6 +3331,9 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("canvas_light_occluder_set_as_sdf_collision", "occluder", "enable"), &RenderingServer::canvas_light_occluder_set_as_sdf_collision);
ClassDB::bind_method(D_METHOD("canvas_light_occluder_set_transform", "occluder", "transform"), &RenderingServer::canvas_light_occluder_set_transform);
ClassDB::bind_method(D_METHOD("canvas_light_occluder_set_light_mask", "occluder", "mask"), &RenderingServer::canvas_light_occluder_set_light_mask);
+ ClassDB::bind_method(D_METHOD("canvas_light_occluder_set_interpolated", "occluder", "interpolated"), &RenderingServer::canvas_light_occluder_set_interpolated);
+ ClassDB::bind_method(D_METHOD("canvas_light_occluder_reset_physics_interpolation", "occluder"), &RenderingServer::canvas_light_occluder_reset_physics_interpolation);
+ ClassDB::bind_method(D_METHOD("canvas_light_occluder_transform_physics_interpolation", "occluder", "transform"), &RenderingServer::canvas_light_occluder_transform_physics_interpolation);
/* CANVAS LIGHT OCCLUDER POLYGON */
diff --git a/servers/rendering_server.h b/servers/rendering_server.h
index 02a90dad3b..8f0150f180 100644
--- a/servers/rendering_server.h
+++ b/servers/rendering_server.h
@@ -873,6 +873,7 @@ public:
};
virtual void viewport_set_update_mode(RID p_viewport, ViewportUpdateMode p_mode) = 0;
+ virtual ViewportUpdateMode viewport_get_update_mode(RID p_viewport) const = 0;
enum ViewportClearMode {
VIEWPORT_CLEAR_ALWAYS,
@@ -1378,6 +1379,7 @@ public:
virtual RID canvas_create() = 0;
virtual void canvas_set_item_mirroring(RID p_canvas, RID p_item, const Point2 &p_mirroring) = 0;
+ virtual void canvas_set_item_repeat(RID p_item, const Point2 &p_repeat_size, int p_repeat_times) = 0;
virtual void canvas_set_modulate(RID p_canvas, const Color &p_color) = 0;
virtual void canvas_set_parent(RID p_canvas, RID p_parent, float p_scale) = 0;
@@ -1475,6 +1477,10 @@ public:
virtual void canvas_item_set_debug_redraw(bool p_enabled) = 0;
virtual bool canvas_item_get_debug_redraw() const = 0;
+ virtual void canvas_item_set_interpolated(RID p_item, bool p_interpolated) = 0;
+ virtual void canvas_item_reset_physics_interpolation(RID p_item) = 0;
+ virtual void canvas_item_transform_physics_interpolation(RID p_item, const Transform2D &p_transform) = 0;
+
/* CANVAS LIGHT */
virtual RID canvas_light_create() = 0;
@@ -1522,6 +1528,10 @@ public:
virtual void canvas_light_set_shadow_color(RID p_light, const Color &p_color) = 0;
virtual void canvas_light_set_shadow_smooth(RID p_light, float p_smooth) = 0;
+ virtual void canvas_light_set_interpolated(RID p_light, bool p_interpolated) = 0;
+ virtual void canvas_light_reset_physics_interpolation(RID p_light) = 0;
+ virtual void canvas_light_transform_physics_interpolation(RID p_light, const Transform2D &p_transform) = 0;
+
/* CANVAS LIGHT OCCLUDER */
virtual RID canvas_light_occluder_create() = 0;
@@ -1532,6 +1542,10 @@ public:
virtual void canvas_light_occluder_set_transform(RID p_occluder, const Transform2D &p_xform) = 0;
virtual void canvas_light_occluder_set_light_mask(RID p_occluder, int p_mask) = 0;
+ virtual void canvas_light_occluder_set_interpolated(RID p_occluder, bool p_interpolated) = 0;
+ virtual void canvas_light_occluder_reset_physics_interpolation(RID p_occluder) = 0;
+ virtual void canvas_light_occluder_transform_physics_interpolation(RID p_occluder, const Transform2D &p_transform) = 0;
+
/* CANVAS LIGHT OCCLUDER POLYGON */
virtual RID canvas_occluder_polygon_create() = 0;
@@ -1603,6 +1617,11 @@ public:
virtual void free(RID p_rid) = 0; // Free RIDs associated with the rendering server.
+ /* INTERPOLATION */
+
+ virtual void tick() = 0;
+ virtual void set_physics_interpolation_enabled(bool p_enabled) = 0;
+
/* EVENT QUEUING */
virtual void request_frame_drawn_callback(const Callable &p_callable) = 0;
diff --git a/servers/text/text_server_dummy.h b/servers/text/text_server_dummy.h
index 77b6ecf319..a5ab444f55 100644
--- a/servers/text/text_server_dummy.h
+++ b/servers/text/text_server_dummy.h
@@ -40,9 +40,87 @@ class TextServerDummy : public TextServerExtension {
_THREAD_SAFE_CLASS_
public:
- virtual String get_name() const override {
- return "Dummy";
- }
+ virtual bool has_feature(Feature p_feature) const override { return false; }
+ virtual String get_name() const override { return "Dummy"; }
+ virtual int64_t get_features() const override { return 0; }
+ virtual void free_rid(const RID &p_rid) override {}
+ virtual bool has(const RID &p_rid) override { return false; }
+
+ virtual RID create_font() override { return RID(); }
+ virtual void font_set_fixed_size(const RID &p_font_rid, int64_t p_fixed_size) override {}
+ virtual int64_t font_get_fixed_size(const RID &p_font_rid) const override { return 0; }
+ virtual void font_set_fixed_size_scale_mode(const RID &p_font_rid, TextServer::FixedSizeScaleMode p_fixed_size_scale_mode) override {}
+ virtual TextServer::FixedSizeScaleMode font_get_fixed_size_scale_mode(const RID &p_font_rid) const override { return FIXED_SIZE_SCALE_DISABLE; }
+ virtual TypedArray<Vector2i> font_get_size_cache_list(const RID &p_font_rid) const override { return TypedArray<Vector2i>(); }
+ virtual void font_clear_size_cache(const RID &p_font_rid) override {}
+ virtual void font_remove_size_cache(const RID &p_font_rid, const Vector2i &p_size) override {}
+ virtual void font_set_ascent(const RID &p_font_rid, int64_t p_size, double p_ascent) override {}
+ virtual double font_get_ascent(const RID &p_font_rid, int64_t p_size) const override { return 0; }
+ virtual void font_set_descent(const RID &p_font_rid, int64_t p_size, double p_descent) override {}
+ virtual double font_get_descent(const RID &p_font_rid, int64_t p_size) const override { return 0; }
+ virtual void font_set_underline_position(const RID &p_font_rid, int64_t p_size, double p_underline_position) override {}
+ virtual double font_get_underline_position(const RID &p_font_rid, int64_t p_size) const override { return 0; }
+ virtual void font_set_underline_thickness(const RID &p_font_rid, int64_t p_size, double p_underline_thickness) override {}
+ virtual double font_get_underline_thickness(const RID &p_font_rid, int64_t p_size) const override { return 0; }
+ virtual void font_set_scale(const RID &p_font_rid, int64_t p_size, double p_scale) override {}
+ virtual double font_get_scale(const RID &p_font_rid, int64_t p_size) const override { return 0; }
+ virtual int64_t font_get_texture_count(const RID &p_font_rid, const Vector2i &p_size) const override { return 0; }
+ virtual void font_clear_textures(const RID &p_font_rid, const Vector2i &p_size) override {}
+ virtual void font_remove_texture(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) override {}
+ virtual void font_set_texture_image(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index, const Ref<Image> &p_image) override {}
+ virtual Ref<Image> font_get_texture_image(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) const override { return Ref<Image>(); }
+ virtual PackedInt32Array font_get_glyph_list(const RID &p_font_rid, const Vector2i &p_size) const override { return PackedInt32Array(); }
+ virtual void font_clear_glyphs(const RID &p_font_rid, const Vector2i &p_size) override {}
+ virtual void font_remove_glyph(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) override {}
+ virtual Vector2 font_get_glyph_advance(const RID &p_font_rid, int64_t p_size, int64_t p_glyph) const override { return Vector2(); }
+ virtual void font_set_glyph_advance(const RID &p_font_rid, int64_t p_size, int64_t p_glyph, const Vector2 &p_advance) override {}
+ virtual Vector2 font_get_glyph_offset(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const override { return Vector2(); }
+ virtual void font_set_glyph_offset(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, const Vector2 &p_offset) override {}
+ virtual Vector2 font_get_glyph_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const override { return Vector2(); }
+ virtual void font_set_glyph_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, const Vector2 &p_gl_size) override {}
+ virtual Rect2 font_get_glyph_uv_rect(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const override { return Rect2(); }
+ virtual void font_set_glyph_uv_rect(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, const Rect2 &p_uv_rect) override {}
+ virtual int64_t font_get_glyph_texture_idx(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const override { return 0; }
+ virtual void font_set_glyph_texture_idx(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, int64_t p_texture_idx) override {}
+ virtual RID font_get_glyph_texture_rid(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const override { return RID(); }
+ virtual Size2 font_get_glyph_texture_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const override { return Size2(); }
+ virtual int64_t font_get_glyph_index(const RID &p_font_rid, int64_t p_size, int64_t p_char, int64_t p_variation_selector) const override { return 0; }
+ virtual int64_t font_get_char_from_glyph_index(const RID &p_font_rid, int64_t p_size, int64_t p_glyph_index) const override { return 0; }
+ virtual bool font_has_char(const RID &p_font_rid, int64_t p_char) const override { return false; }
+ virtual String font_get_supported_chars(const RID &p_font_rid) const override { return String(); }
+ virtual void font_draw_glyph(const RID &p_font_rid, const RID &p_canvas, int64_t p_size, const Vector2 &p_pos, int64_t p_index, const Color &p_color) const override {}
+ virtual void font_draw_glyph_outline(const RID &p_font_rid, const RID &p_canvas, int64_t p_size, int64_t p_outline_size, const Vector2 &p_pos, int64_t p_index, const Color &p_color) const override {}
+
+ virtual RID create_shaped_text(TextServer::Direction p_direction, TextServer::Orientation p_orientation) override { return RID(); }
+ virtual void shaped_text_clear(const RID &p_shaped) override {}
+ virtual bool shaped_text_add_string(const RID &p_shaped, const String &p_text, const TypedArray<RID> &p_fonts, int64_t p_size, const Dictionary &p_opentype_features, const String &p_language, const Variant &p_meta) override { return false; }
+ virtual bool shaped_text_add_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align, int64_t p_length, double p_baseline) override { return false; }
+ virtual bool shaped_text_resize_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align, double p_baseline) override { return false; }
+ virtual int64_t shaped_get_span_count(const RID &p_shaped) const override { return 0; }
+ virtual Variant shaped_get_span_meta(const RID &p_shaped, int64_t p_index) const override { return Variant(); }
+ virtual void shaped_set_span_update_font(const RID &p_shaped, int64_t p_index, const TypedArray<RID> &p_fonts, int64_t p_size, const Dictionary &p_opentype_features) override {}
+ virtual RID shaped_text_substr(const RID &p_shaped, int64_t p_start, int64_t p_length) const override { return RID(); }
+ virtual RID shaped_text_get_parent(const RID &p_shaped) const override { return RID(); }
+ virtual bool shaped_text_shape(const RID &p_shaped) override { return false; }
+ virtual bool shaped_text_is_ready(const RID &p_shaped) const override { return false; }
+ virtual const Glyph *shaped_text_get_glyphs(const RID &p_shaped) const override { return nullptr; }
+ virtual const Glyph *shaped_text_sort_logical(const RID &p_shaped) override { return nullptr; }
+ virtual int64_t shaped_text_get_glyph_count(const RID &p_shaped) const override { return 0; }
+ virtual Vector2i shaped_text_get_range(const RID &p_shaped) const override { return Vector2i(); }
+ virtual int64_t shaped_text_get_trim_pos(const RID &p_shaped) const override { return -1; }
+ virtual int64_t shaped_text_get_ellipsis_pos(const RID &p_shaped) const override { return -1; }
+ virtual const Glyph *shaped_text_get_ellipsis_glyphs(const RID &p_shaped) const override { return nullptr; }
+ virtual int64_t shaped_text_get_ellipsis_glyph_count(const RID &p_shaped) const override { return -1; }
+ virtual Array shaped_text_get_objects(const RID &p_shaped) const override { return Array(); }
+ virtual Rect2 shaped_text_get_object_rect(const RID &p_shaped, const Variant &p_key) const override { return Rect2(); }
+ virtual Vector2i shaped_text_get_object_range(const RID &p_shaped, const Variant &p_key) const override { return Vector2i(); }
+ virtual int64_t shaped_text_get_object_glyph(const RID &p_shaped, const Variant &p_key) const override { return -1; }
+ virtual Size2 shaped_text_get_size(const RID &p_shaped) const override { return Size2(); }
+ virtual double shaped_text_get_ascent(const RID &p_shaped) const override { return 0; }
+ virtual double shaped_text_get_descent(const RID &p_shaped) const override { return 0; }
+ virtual double shaped_text_get_width(const RID &p_shaped) const override { return 0; }
+ virtual double shaped_text_get_underline_position(const RID &p_shaped) const override { return 0; }
+ virtual double shaped_text_get_underline_thickness(const RID &p_shaped) const override { return 0; }
};
#endif // TEXT_SERVER_DUMMY_H
diff --git a/servers/text/text_server_extension.cpp b/servers/text/text_server_extension.cpp
index d5080e586d..53e1d119fd 100644
--- a/servers/text/text_server_extension.cpp
+++ b/servers/text/text_server_extension.cpp
@@ -80,6 +80,9 @@ void TextServerExtension::_bind_methods() {
GDVIRTUAL_BIND(_font_set_antialiasing, "font_rid", "antialiasing");
GDVIRTUAL_BIND(_font_get_antialiasing, "font_rid");
+ GDVIRTUAL_BIND(_font_set_disable_embedded_bitmaps, "font_rid", "disable_embedded_bitmaps");
+ GDVIRTUAL_BIND(_font_get_disable_embedded_bitmaps, "font_rid");
+
GDVIRTUAL_BIND(_font_set_generate_mipmaps, "font_rid", "generate_mipmaps");
GDVIRTUAL_BIND(_font_get_generate_mipmaps, "font_rid");
@@ -293,6 +296,8 @@ void TextServerExtension::_bind_methods() {
GDVIRTUAL_BIND(_shaped_text_get_objects, "shaped");
GDVIRTUAL_BIND(_shaped_text_get_object_rect, "shaped", "key");
+ GDVIRTUAL_BIND(_shaped_text_get_object_range, "shaped", "key");
+ GDVIRTUAL_BIND(_shaped_text_get_object_glyph, "shaped", "key");
GDVIRTUAL_BIND(_shaped_text_get_size, "shaped");
GDVIRTUAL_BIND(_shaped_text_get_ascent, "shaped");
@@ -321,8 +326,8 @@ void TextServerExtension::_bind_methods() {
GDVIRTUAL_BIND(_shaped_text_prev_character_pos, "shaped", "pos");
GDVIRTUAL_BIND(_shaped_text_closest_character_pos, "shaped", "pos");
- GDVIRTUAL_BIND(_format_number, "string", "language");
- GDVIRTUAL_BIND(_parse_number, "string", "language");
+ GDVIRTUAL_BIND(_format_number, "number", "language");
+ GDVIRTUAL_BIND(_parse_number, "number", "language");
GDVIRTUAL_BIND(_percent_sign, "language");
GDVIRTUAL_BIND(_strip_diacritics, "string");
@@ -336,6 +341,7 @@ void TextServerExtension::_bind_methods() {
GDVIRTUAL_BIND(_string_to_upper, "string", "language");
GDVIRTUAL_BIND(_string_to_lower, "string", "language");
+ GDVIRTUAL_BIND(_string_to_title, "string", "language");
GDVIRTUAL_BIND(_parse_structured_text, "parser_type", "args", "text");
@@ -344,29 +350,29 @@ void TextServerExtension::_bind_methods() {
bool TextServerExtension::has_feature(Feature p_feature) const {
bool ret = false;
- GDVIRTUAL_CALL(_has_feature, p_feature, ret);
+ GDVIRTUAL_REQUIRED_CALL(_has_feature, p_feature, ret);
return ret;
}
String TextServerExtension::get_name() const {
String ret = "Unknown";
- GDVIRTUAL_CALL(_get_name, ret);
+ GDVIRTUAL_REQUIRED_CALL(_get_name, ret);
return ret;
}
int64_t TextServerExtension::get_features() const {
int64_t ret = 0;
- GDVIRTUAL_CALL(_get_features, ret);
+ GDVIRTUAL_REQUIRED_CALL(_get_features, ret);
return ret;
}
void TextServerExtension::free_rid(const RID &p_rid) {
- GDVIRTUAL_CALL(_free_rid, p_rid);
+ GDVIRTUAL_REQUIRED_CALL(_free_rid, p_rid);
}
bool TextServerExtension::has(const RID &p_rid) {
bool ret = false;
- GDVIRTUAL_CALL(_has, p_rid, ret);
+ GDVIRTUAL_REQUIRED_CALL(_has, p_rid, ret);
return ret;
}
@@ -402,14 +408,18 @@ bool TextServerExtension::is_locale_right_to_left(const String &p_locale) const
int64_t TextServerExtension::name_to_tag(const String &p_name) const {
int64_t ret = 0;
- GDVIRTUAL_CALL(_name_to_tag, p_name, ret);
- return ret;
+ if (GDVIRTUAL_CALL(_name_to_tag, p_name, ret)) {
+ return ret;
+ }
+ return TextServer::name_to_tag(p_name);
}
String TextServerExtension::tag_to_name(int64_t p_tag) const {
String ret;
- GDVIRTUAL_CALL(_tag_to_name, p_tag, ret);
- return ret;
+ if (GDVIRTUAL_CALL(_tag_to_name, p_tag, ret)) {
+ return ret;
+ }
+ return TextServer::tag_to_name(p_tag);
}
/*************************************************************************/
@@ -418,7 +428,7 @@ String TextServerExtension::tag_to_name(int64_t p_tag) const {
RID TextServerExtension::create_font() {
RID ret;
- GDVIRTUAL_CALL(_create_font, ret);
+ GDVIRTUAL_REQUIRED_CALL(_create_font, ret);
return ret;
}
@@ -447,7 +457,7 @@ int64_t TextServerExtension::font_get_face_index(const RID &p_font_rid) const {
}
int64_t TextServerExtension::font_get_face_count(const RID &p_font_rid) const {
- int64_t ret = 0;
+ int64_t ret = 1;
GDVIRTUAL_CALL(_font_get_face_count, p_font_rid, ret);
return ret;
}
@@ -518,6 +528,16 @@ TextServer::FontAntialiasing TextServerExtension::font_get_antialiasing(const RI
return ret;
}
+void TextServerExtension::font_set_disable_embedded_bitmaps(const RID &p_font_rid, bool p_disable_embedded_bitmaps) {
+ GDVIRTUAL_CALL(_font_set_disable_embedded_bitmaps, p_font_rid, p_disable_embedded_bitmaps);
+}
+
+bool TextServerExtension::font_get_disable_embedded_bitmaps(const RID &p_font_rid) const {
+ bool ret = false;
+ GDVIRTUAL_CALL(_font_get_disable_embedded_bitmaps, p_font_rid, ret);
+ return ret;
+}
+
void TextServerExtension::font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) {
GDVIRTUAL_CALL(_font_set_generate_mipmaps, p_font_rid, p_generate_mipmaps);
}
@@ -559,22 +579,22 @@ int64_t TextServerExtension::font_get_msdf_size(const RID &p_font_rid) const {
}
void TextServerExtension::font_set_fixed_size(const RID &p_font_rid, int64_t p_fixed_size) {
- GDVIRTUAL_CALL(_font_set_fixed_size, p_font_rid, p_fixed_size);
+ GDVIRTUAL_REQUIRED_CALL(_font_set_fixed_size, p_font_rid, p_fixed_size);
}
int64_t TextServerExtension::font_get_fixed_size(const RID &p_font_rid) const {
int64_t ret = 0;
- GDVIRTUAL_CALL(_font_get_fixed_size, p_font_rid, ret);
+ GDVIRTUAL_REQUIRED_CALL(_font_get_fixed_size, p_font_rid, ret);
return ret;
}
void TextServerExtension::font_set_fixed_size_scale_mode(const RID &p_font_rid, TextServer::FixedSizeScaleMode p_fixed_size_scale_mode) {
- GDVIRTUAL_CALL(_font_set_fixed_size_scale_mode, p_font_rid, p_fixed_size_scale_mode);
+ GDVIRTUAL_REQUIRED_CALL(_font_set_fixed_size_scale_mode, p_font_rid, p_fixed_size_scale_mode);
}
TextServer::FixedSizeScaleMode TextServerExtension::font_get_fixed_size_scale_mode(const RID &p_font_rid) const {
FixedSizeScaleMode ret = FIXED_SIZE_SCALE_DISABLE;
- GDVIRTUAL_CALL(_font_get_fixed_size_scale_mode, p_font_rid, ret);
+ GDVIRTUAL_REQUIRED_CALL(_font_get_fixed_size_scale_mode, p_font_rid, ret);
return ret;
}
@@ -680,89 +700,89 @@ double TextServerExtension::font_get_oversampling(const RID &p_font_rid) const {
TypedArray<Vector2i> TextServerExtension::font_get_size_cache_list(const RID &p_font_rid) const {
TypedArray<Vector2i> ret;
- GDVIRTUAL_CALL(_font_get_size_cache_list, p_font_rid, ret);
+ GDVIRTUAL_REQUIRED_CALL(_font_get_size_cache_list, p_font_rid, ret);
return ret;
}
void TextServerExtension::font_clear_size_cache(const RID &p_font_rid) {
- GDVIRTUAL_CALL(_font_clear_size_cache, p_font_rid);
+ GDVIRTUAL_REQUIRED_CALL(_font_clear_size_cache, p_font_rid);
}
void TextServerExtension::font_remove_size_cache(const RID &p_font_rid, const Vector2i &p_size) {
- GDVIRTUAL_CALL(_font_remove_size_cache, p_font_rid, p_size);
+ GDVIRTUAL_REQUIRED_CALL(_font_remove_size_cache, p_font_rid, p_size);
}
void TextServerExtension::font_set_ascent(const RID &p_font_rid, int64_t p_size, double p_ascent) {
- GDVIRTUAL_CALL(_font_set_ascent, p_font_rid, p_size, p_ascent);
+ GDVIRTUAL_REQUIRED_CALL(_font_set_ascent, p_font_rid, p_size, p_ascent);
}
double TextServerExtension::font_get_ascent(const RID &p_font_rid, int64_t p_size) const {
double ret = 0;
- GDVIRTUAL_CALL(_font_get_ascent, p_font_rid, p_size, ret);
+ GDVIRTUAL_REQUIRED_CALL(_font_get_ascent, p_font_rid, p_size, ret);
return ret;
}
void TextServerExtension::font_set_descent(const RID &p_font_rid, int64_t p_size, double p_descent) {
- GDVIRTUAL_CALL(_font_set_descent, p_font_rid, p_size, p_descent);
+ GDVIRTUAL_REQUIRED_CALL(_font_set_descent, p_font_rid, p_size, p_descent);
}
double TextServerExtension::font_get_descent(const RID &p_font_rid, int64_t p_size) const {
double ret = 0;
- GDVIRTUAL_CALL(_font_get_descent, p_font_rid, p_size, ret);
+ GDVIRTUAL_REQUIRED_CALL(_font_get_descent, p_font_rid, p_size, ret);
return ret;
}
void TextServerExtension::font_set_underline_position(const RID &p_font_rid, int64_t p_size, double p_underline_position) {
- GDVIRTUAL_CALL(_font_set_underline_position, p_font_rid, p_size, p_underline_position);
+ GDVIRTUAL_REQUIRED_CALL(_font_set_underline_position, p_font_rid, p_size, p_underline_position);
}
double TextServerExtension::font_get_underline_position(const RID &p_font_rid, int64_t p_size) const {
double ret = 0;
- GDVIRTUAL_CALL(_font_get_underline_position, p_font_rid, p_size, ret);
+ GDVIRTUAL_REQUIRED_CALL(_font_get_underline_position, p_font_rid, p_size, ret);
return ret;
}
void TextServerExtension::font_set_underline_thickness(const RID &p_font_rid, int64_t p_size, double p_underline_thickness) {
- GDVIRTUAL_CALL(_font_set_underline_thickness, p_font_rid, p_size, p_underline_thickness);
+ GDVIRTUAL_REQUIRED_CALL(_font_set_underline_thickness, p_font_rid, p_size, p_underline_thickness);
}
double TextServerExtension::font_get_underline_thickness(const RID &p_font_rid, int64_t p_size) const {
double ret = 0;
- GDVIRTUAL_CALL(_font_get_underline_thickness, p_font_rid, p_size, ret);
+ GDVIRTUAL_REQUIRED_CALL(_font_get_underline_thickness, p_font_rid, p_size, ret);
return ret;
}
void TextServerExtension::font_set_scale(const RID &p_font_rid, int64_t p_size, double p_scale) {
- GDVIRTUAL_CALL(_font_set_scale, p_font_rid, p_size, p_scale);
+ GDVIRTUAL_REQUIRED_CALL(_font_set_scale, p_font_rid, p_size, p_scale);
}
double TextServerExtension::font_get_scale(const RID &p_font_rid, int64_t p_size) const {
double ret = 0;
- GDVIRTUAL_CALL(_font_get_scale, p_font_rid, p_size, ret);
+ GDVIRTUAL_REQUIRED_CALL(_font_get_scale, p_font_rid, p_size, ret);
return ret;
}
int64_t TextServerExtension::font_get_texture_count(const RID &p_font_rid, const Vector2i &p_size) const {
int64_t ret = 0;
- GDVIRTUAL_CALL(_font_get_texture_count, p_font_rid, p_size, ret);
+ GDVIRTUAL_REQUIRED_CALL(_font_get_texture_count, p_font_rid, p_size, ret);
return ret;
}
void TextServerExtension::font_clear_textures(const RID &p_font_rid, const Vector2i &p_size) {
- GDVIRTUAL_CALL(_font_clear_textures, p_font_rid, p_size);
+ GDVIRTUAL_REQUIRED_CALL(_font_clear_textures, p_font_rid, p_size);
}
void TextServerExtension::font_remove_texture(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) {
- GDVIRTUAL_CALL(_font_remove_texture, p_font_rid, p_size, p_texture_index);
+ GDVIRTUAL_REQUIRED_CALL(_font_remove_texture, p_font_rid, p_size, p_texture_index);
}
void TextServerExtension::font_set_texture_image(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index, const Ref<Image> &p_image) {
- GDVIRTUAL_CALL(_font_set_texture_image, p_font_rid, p_size, p_texture_index, p_image);
+ GDVIRTUAL_REQUIRED_CALL(_font_set_texture_image, p_font_rid, p_size, p_texture_index, p_image);
}
Ref<Image> TextServerExtension::font_get_texture_image(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) const {
Ref<Image> ret;
- GDVIRTUAL_CALL(_font_get_texture_image, p_font_rid, p_size, p_texture_index, ret);
+ GDVIRTUAL_REQUIRED_CALL(_font_get_texture_image, p_font_rid, p_size, p_texture_index, ret);
return ret;
}
@@ -778,77 +798,77 @@ PackedInt32Array TextServerExtension::font_get_texture_offsets(const RID &p_font
PackedInt32Array TextServerExtension::font_get_glyph_list(const RID &p_font_rid, const Vector2i &p_size) const {
PackedInt32Array ret;
- GDVIRTUAL_CALL(_font_get_glyph_list, p_font_rid, p_size, ret);
+ GDVIRTUAL_REQUIRED_CALL(_font_get_glyph_list, p_font_rid, p_size, ret);
return ret;
}
void TextServerExtension::font_clear_glyphs(const RID &p_font_rid, const Vector2i &p_size) {
- GDVIRTUAL_CALL(_font_clear_glyphs, p_font_rid, p_size);
+ GDVIRTUAL_REQUIRED_CALL(_font_clear_glyphs, p_font_rid, p_size);
}
void TextServerExtension::font_remove_glyph(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) {
- GDVIRTUAL_CALL(_font_remove_glyph, p_font_rid, p_size, p_glyph);
+ GDVIRTUAL_REQUIRED_CALL(_font_remove_glyph, p_font_rid, p_size, p_glyph);
}
Vector2 TextServerExtension::font_get_glyph_advance(const RID &p_font_rid, int64_t p_size, int64_t p_glyph) const {
Vector2 ret;
- GDVIRTUAL_CALL(_font_get_glyph_advance, p_font_rid, p_size, p_glyph, ret);
+ GDVIRTUAL_REQUIRED_CALL(_font_get_glyph_advance, p_font_rid, p_size, p_glyph, ret);
return ret;
}
void TextServerExtension::font_set_glyph_advance(const RID &p_font_rid, int64_t p_size, int64_t p_glyph, const Vector2 &p_advance) {
- GDVIRTUAL_CALL(_font_set_glyph_advance, p_font_rid, p_size, p_glyph, p_advance);
+ GDVIRTUAL_REQUIRED_CALL(_font_set_glyph_advance, p_font_rid, p_size, p_glyph, p_advance);
}
Vector2 TextServerExtension::font_get_glyph_offset(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const {
Vector2 ret;
- GDVIRTUAL_CALL(_font_get_glyph_offset, p_font_rid, p_size, p_glyph, ret);
+ GDVIRTUAL_REQUIRED_CALL(_font_get_glyph_offset, p_font_rid, p_size, p_glyph, ret);
return ret;
}
void TextServerExtension::font_set_glyph_offset(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, const Vector2 &p_offset) {
- GDVIRTUAL_CALL(_font_set_glyph_offset, p_font_rid, p_size, p_glyph, p_offset);
+ GDVIRTUAL_REQUIRED_CALL(_font_set_glyph_offset, p_font_rid, p_size, p_glyph, p_offset);
}
Vector2 TextServerExtension::font_get_glyph_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const {
Vector2 ret;
- GDVIRTUAL_CALL(_font_get_glyph_size, p_font_rid, p_size, p_glyph, ret);
+ GDVIRTUAL_REQUIRED_CALL(_font_get_glyph_size, p_font_rid, p_size, p_glyph, ret);
return ret;
}
void TextServerExtension::font_set_glyph_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, const Vector2 &p_gl_size) {
- GDVIRTUAL_CALL(_font_set_glyph_size, p_font_rid, p_size, p_glyph, p_gl_size);
+ GDVIRTUAL_REQUIRED_CALL(_font_set_glyph_size, p_font_rid, p_size, p_glyph, p_gl_size);
}
Rect2 TextServerExtension::font_get_glyph_uv_rect(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const {
Rect2 ret;
- GDVIRTUAL_CALL(_font_get_glyph_uv_rect, p_font_rid, p_size, p_glyph, ret);
+ GDVIRTUAL_REQUIRED_CALL(_font_get_glyph_uv_rect, p_font_rid, p_size, p_glyph, ret);
return ret;
}
void TextServerExtension::font_set_glyph_uv_rect(const RID &p_font_rid, const Vector2i &p_size, int64_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);
+ GDVIRTUAL_REQUIRED_CALL(_font_set_glyph_uv_rect, p_font_rid, p_size, p_glyph, p_uv_rect);
}
int64_t TextServerExtension::font_get_glyph_texture_idx(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const {
int64_t ret = 0;
- GDVIRTUAL_CALL(_font_get_glyph_texture_idx, p_font_rid, p_size, p_glyph, ret);
+ GDVIRTUAL_REQUIRED_CALL(_font_get_glyph_texture_idx, p_font_rid, p_size, p_glyph, ret);
return ret;
}
void TextServerExtension::font_set_glyph_texture_idx(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, int64_t p_texture_idx) {
- GDVIRTUAL_CALL(_font_set_glyph_texture_idx, p_font_rid, p_size, p_glyph, p_texture_idx);
+ GDVIRTUAL_REQUIRED_CALL(_font_set_glyph_texture_idx, p_font_rid, p_size, p_glyph, p_texture_idx);
}
RID TextServerExtension::font_get_glyph_texture_rid(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const {
RID ret;
- GDVIRTUAL_CALL(_font_get_glyph_texture_rid, p_font_rid, p_size, p_glyph, ret);
+ GDVIRTUAL_REQUIRED_CALL(_font_get_glyph_texture_rid, p_font_rid, p_size, p_glyph, ret);
return ret;
}
Size2 TextServerExtension::font_get_glyph_texture_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const {
Size2 ret;
- GDVIRTUAL_CALL(_font_get_glyph_texture_size, p_font_rid, p_size, p_glyph, ret);
+ GDVIRTUAL_REQUIRED_CALL(_font_get_glyph_texture_size, p_font_rid, p_size, p_glyph, ret);
return ret;
}
@@ -884,25 +904,25 @@ Vector2 TextServerExtension::font_get_kerning(const RID &p_font_rid, int64_t p_s
int64_t TextServerExtension::font_get_glyph_index(const RID &p_font_rid, int64_t p_size, int64_t p_char, int64_t p_variation_selector) const {
int64_t ret = 0;
- GDVIRTUAL_CALL(_font_get_glyph_index, p_font_rid, p_size, p_char, p_variation_selector, ret);
+ GDVIRTUAL_REQUIRED_CALL(_font_get_glyph_index, p_font_rid, p_size, p_char, p_variation_selector, ret);
return ret;
}
int64_t TextServerExtension::font_get_char_from_glyph_index(const RID &p_font_rid, int64_t p_size, int64_t p_glyph_index) const {
int64_t ret = 0;
- GDVIRTUAL_CALL(_font_get_char_from_glyph_index, p_font_rid, p_size, p_glyph_index, ret);
+ GDVIRTUAL_REQUIRED_CALL(_font_get_char_from_glyph_index, p_font_rid, p_size, p_glyph_index, ret);
return ret;
}
bool TextServerExtension::font_has_char(const RID &p_font_rid, int64_t p_char) const {
bool ret = false;
- GDVIRTUAL_CALL(_font_has_char, p_font_rid, p_char, ret);
+ GDVIRTUAL_REQUIRED_CALL(_font_has_char, p_font_rid, p_char, ret);
return ret;
}
String TextServerExtension::font_get_supported_chars(const RID &p_font_rid) const {
String ret;
- GDVIRTUAL_CALL(_font_get_supported_chars, p_font_rid, ret);
+ GDVIRTUAL_REQUIRED_CALL(_font_get_supported_chars, p_font_rid, ret);
return ret;
}
@@ -915,11 +935,11 @@ void TextServerExtension::font_render_glyph(const RID &p_font_rid, const Vector2
}
void TextServerExtension::font_draw_glyph(const RID &p_font_rid, const RID &p_canvas, int64_t p_size, const Vector2 &p_pos, int64_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);
+ GDVIRTUAL_REQUIRED_CALL(_font_draw_glyph, p_font_rid, p_canvas, p_size, p_pos, p_index, p_color);
}
void TextServerExtension::font_draw_glyph_outline(const RID &p_font_rid, const RID &p_canvas, int64_t p_size, int64_t p_outline_size, const Vector2 &p_pos, int64_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);
+ GDVIRTUAL_REQUIRED_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(const RID &p_font_rid, const String &p_language) const {
@@ -1026,12 +1046,12 @@ void TextServerExtension::draw_hex_code_box(const RID &p_canvas, int64_t p_size,
RID TextServerExtension::create_shaped_text(TextServer::Direction p_direction, TextServer::Orientation p_orientation) {
RID ret;
- GDVIRTUAL_CALL(_create_shaped_text, p_direction, p_orientation, ret);
+ GDVIRTUAL_REQUIRED_CALL(_create_shaped_text, p_direction, p_orientation, ret);
return ret;
}
void TextServerExtension::shaped_text_clear(const RID &p_shaped) {
- GDVIRTUAL_CALL(_shaped_text_clear, p_shaped);
+ GDVIRTUAL_REQUIRED_CALL(_shaped_text_clear, p_shaped);
}
void TextServerExtension::shaped_text_set_direction(const RID &p_shaped, TextServer::Direction p_direction) {
@@ -1116,47 +1136,47 @@ int64_t TextServerExtension::shaped_text_get_spacing(const RID &p_shaped, TextSe
bool TextServerExtension::shaped_text_add_string(const RID &p_shaped, const String &p_text, const TypedArray<RID> &p_fonts, int64_t p_size, const Dictionary &p_opentype_features, const String &p_language, const Variant &p_meta) {
bool ret = false;
- GDVIRTUAL_CALL(_shaped_text_add_string, p_shaped, p_text, p_fonts, p_size, p_opentype_features, p_language, p_meta, ret);
+ GDVIRTUAL_REQUIRED_CALL(_shaped_text_add_string, p_shaped, p_text, p_fonts, p_size, p_opentype_features, p_language, p_meta, ret);
return ret;
}
bool TextServerExtension::shaped_text_add_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align, int64_t p_length, double p_baseline) {
bool ret = false;
- GDVIRTUAL_CALL(_shaped_text_add_object, p_shaped, p_key, p_size, p_inline_align, p_length, p_baseline, ret);
+ GDVIRTUAL_REQUIRED_CALL(_shaped_text_add_object, p_shaped, p_key, p_size, p_inline_align, p_length, p_baseline, ret);
return ret;
}
bool TextServerExtension::shaped_text_resize_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align, double p_baseline) {
bool ret = false;
- GDVIRTUAL_CALL(_shaped_text_resize_object, p_shaped, p_key, p_size, p_inline_align, p_baseline, ret);
+ GDVIRTUAL_REQUIRED_CALL(_shaped_text_resize_object, p_shaped, p_key, p_size, p_inline_align, p_baseline, ret);
return ret;
}
int64_t TextServerExtension::shaped_get_span_count(const RID &p_shaped) const {
int64_t ret = 0;
- GDVIRTUAL_CALL(_shaped_get_span_count, p_shaped, ret);
+ GDVIRTUAL_REQUIRED_CALL(_shaped_get_span_count, p_shaped, ret);
return ret;
}
Variant TextServerExtension::shaped_get_span_meta(const RID &p_shaped, int64_t p_index) const {
Variant ret = false;
- GDVIRTUAL_CALL(_shaped_get_span_meta, p_shaped, p_index, ret);
+ GDVIRTUAL_REQUIRED_CALL(_shaped_get_span_meta, p_shaped, p_index, ret);
return ret;
}
void TextServerExtension::shaped_set_span_update_font(const RID &p_shaped, int64_t p_index, const TypedArray<RID> &p_fonts, int64_t p_size, const Dictionary &p_opentype_features) {
- GDVIRTUAL_CALL(_shaped_set_span_update_font, p_shaped, p_index, p_fonts, p_size, p_opentype_features);
+ GDVIRTUAL_REQUIRED_CALL(_shaped_set_span_update_font, p_shaped, p_index, p_fonts, p_size, p_opentype_features);
}
RID TextServerExtension::shaped_text_substr(const RID &p_shaped, int64_t p_start, int64_t p_length) const {
RID ret;
- GDVIRTUAL_CALL(_shaped_text_substr, p_shaped, p_start, p_length, ret);
+ GDVIRTUAL_REQUIRED_CALL(_shaped_text_substr, p_shaped, p_start, p_length, ret);
return ret;
}
RID TextServerExtension::shaped_text_get_parent(const RID &p_shaped) const {
RID ret;
- GDVIRTUAL_CALL(_shaped_text_get_parent, p_shaped, ret);
+ GDVIRTUAL_REQUIRED_CALL(_shaped_text_get_parent, p_shaped, ret);
return ret;
}
@@ -1174,7 +1194,7 @@ double TextServerExtension::shaped_text_tab_align(const RID &p_shaped, const Pac
bool TextServerExtension::shaped_text_shape(const RID &p_shaped) {
bool ret = false;
- GDVIRTUAL_CALL(_shaped_text_shape, p_shaped, ret);
+ GDVIRTUAL_REQUIRED_CALL(_shaped_text_shape, p_shaped, ret);
return ret;
}
@@ -1192,31 +1212,31 @@ bool TextServerExtension::shaped_text_update_justification_ops(const RID &p_shap
bool TextServerExtension::shaped_text_is_ready(const RID &p_shaped) const {
bool ret = false;
- GDVIRTUAL_CALL(_shaped_text_is_ready, p_shaped, ret);
+ GDVIRTUAL_REQUIRED_CALL(_shaped_text_is_ready, p_shaped, ret);
return ret;
}
const Glyph *TextServerExtension::shaped_text_get_glyphs(const RID &p_shaped) const {
GDExtensionConstPtr<const Glyph> ret;
- GDVIRTUAL_CALL(_shaped_text_get_glyphs, p_shaped, ret);
+ GDVIRTUAL_REQUIRED_CALL(_shaped_text_get_glyphs, p_shaped, ret);
return ret;
}
const Glyph *TextServerExtension::shaped_text_sort_logical(const RID &p_shaped) {
GDExtensionConstPtr<const Glyph> ret;
- GDVIRTUAL_CALL(_shaped_text_sort_logical, p_shaped, ret);
+ GDVIRTUAL_REQUIRED_CALL(_shaped_text_sort_logical, p_shaped, ret);
return ret;
}
int64_t TextServerExtension::shaped_text_get_glyph_count(const RID &p_shaped) const {
int64_t ret = 0;
- GDVIRTUAL_CALL(_shaped_text_get_glyph_count, p_shaped, ret);
+ GDVIRTUAL_REQUIRED_CALL(_shaped_text_get_glyph_count, p_shaped, ret);
return ret;
}
Vector2i TextServerExtension::shaped_text_get_range(const RID &p_shaped) const {
Vector2i ret;
- GDVIRTUAL_CALL(_shaped_text_get_range, p_shaped, ret);
+ GDVIRTUAL_REQUIRED_CALL(_shaped_text_get_range, p_shaped, ret);
return ret;
}
@@ -1246,25 +1266,25 @@ PackedInt32Array TextServerExtension::shaped_text_get_word_breaks(const RID &p_s
int64_t TextServerExtension::shaped_text_get_trim_pos(const RID &p_shaped) const {
int64_t ret = -1;
- GDVIRTUAL_CALL(_shaped_text_get_trim_pos, p_shaped, ret);
+ GDVIRTUAL_REQUIRED_CALL(_shaped_text_get_trim_pos, p_shaped, ret);
return ret;
}
int64_t TextServerExtension::shaped_text_get_ellipsis_pos(const RID &p_shaped) const {
int64_t ret = -1;
- GDVIRTUAL_CALL(_shaped_text_get_ellipsis_pos, p_shaped, ret);
+ GDVIRTUAL_REQUIRED_CALL(_shaped_text_get_ellipsis_pos, p_shaped, ret);
return ret;
}
const Glyph *TextServerExtension::shaped_text_get_ellipsis_glyphs(const RID &p_shaped) const {
GDExtensionConstPtr<const Glyph> ret;
- GDVIRTUAL_CALL(_shaped_text_get_ellipsis_glyphs, p_shaped, ret);
+ GDVIRTUAL_REQUIRED_CALL(_shaped_text_get_ellipsis_glyphs, p_shaped, ret);
return ret;
}
int64_t TextServerExtension::shaped_text_get_ellipsis_glyph_count(const RID &p_shaped) const {
int64_t ret = -1;
- GDVIRTUAL_CALL(_shaped_text_get_ellipsis_glyph_count, p_shaped, ret);
+ GDVIRTUAL_REQUIRED_CALL(_shaped_text_get_ellipsis_glyph_count, p_shaped, ret);
return ret;
}
@@ -1274,49 +1294,61 @@ void TextServerExtension::shaped_text_overrun_trim_to_width(const RID &p_shaped_
Array TextServerExtension::shaped_text_get_objects(const RID &p_shaped) const {
Array ret;
- GDVIRTUAL_CALL(_shaped_text_get_objects, p_shaped, ret);
+ GDVIRTUAL_REQUIRED_CALL(_shaped_text_get_objects, p_shaped, ret);
return ret;
}
Rect2 TextServerExtension::shaped_text_get_object_rect(const RID &p_shaped, const Variant &p_key) const {
Rect2 ret;
- GDVIRTUAL_CALL(_shaped_text_get_object_rect, p_shaped, p_key, ret);
+ GDVIRTUAL_REQUIRED_CALL(_shaped_text_get_object_rect, p_shaped, p_key, ret);
+ return ret;
+}
+
+Vector2i TextServerExtension::shaped_text_get_object_range(const RID &p_shaped, const Variant &p_key) const {
+ Vector2i ret;
+ GDVIRTUAL_REQUIRED_CALL(_shaped_text_get_object_range, p_shaped, p_key, ret);
+ return ret;
+}
+
+int64_t TextServerExtension::shaped_text_get_object_glyph(const RID &p_shaped, const Variant &p_key) const {
+ int64_t ret = -1;
+ GDVIRTUAL_REQUIRED_CALL(_shaped_text_get_object_glyph, p_shaped, p_key, ret);
return ret;
}
Size2 TextServerExtension::shaped_text_get_size(const RID &p_shaped) const {
Size2 ret;
- GDVIRTUAL_CALL(_shaped_text_get_size, p_shaped, ret);
+ GDVIRTUAL_REQUIRED_CALL(_shaped_text_get_size, p_shaped, ret);
return ret;
}
double TextServerExtension::shaped_text_get_ascent(const RID &p_shaped) const {
double ret = 0;
- GDVIRTUAL_CALL(_shaped_text_get_ascent, p_shaped, ret);
+ GDVIRTUAL_REQUIRED_CALL(_shaped_text_get_ascent, p_shaped, ret);
return ret;
}
double TextServerExtension::shaped_text_get_descent(const RID &p_shaped) const {
double ret = 0;
- GDVIRTUAL_CALL(_shaped_text_get_descent, p_shaped, ret);
+ GDVIRTUAL_REQUIRED_CALL(_shaped_text_get_descent, p_shaped, ret);
return ret;
}
double TextServerExtension::shaped_text_get_width(const RID &p_shaped) const {
double ret = 0;
- GDVIRTUAL_CALL(_shaped_text_get_width, p_shaped, ret);
+ GDVIRTUAL_REQUIRED_CALL(_shaped_text_get_width, p_shaped, ret);
return ret;
}
double TextServerExtension::shaped_text_get_underline_position(const RID &p_shaped) const {
double ret = 0;
- GDVIRTUAL_CALL(_shaped_text_get_underline_position, p_shaped, ret);
+ GDVIRTUAL_REQUIRED_CALL(_shaped_text_get_underline_position, p_shaped, ret);
return ret;
}
double TextServerExtension::shaped_text_get_underline_thickness(const RID &p_shaped) const {
double ret = 0;
- GDVIRTUAL_CALL(_shaped_text_get_underline_thickness, p_shaped, ret);
+ GDVIRTUAL_REQUIRED_CALL(_shaped_text_get_underline_thickness, p_shaped, ret);
return ret;
}
@@ -1476,6 +1508,14 @@ String TextServerExtension::string_to_upper(const String &p_string, const String
return p_string;
}
+String TextServerExtension::string_to_title(const String &p_string, const String &p_language) const {
+ String ret;
+ if (GDVIRTUAL_CALL(_string_to_title, p_string, p_language, ret)) {
+ return ret;
+ }
+ return p_string;
+}
+
String TextServerExtension::string_to_lower(const String &p_string, const String &p_language) const {
String ret;
if (GDVIRTUAL_CALL(_string_to_lower, p_string, p_language, ret)) {
@@ -1486,8 +1526,10 @@ String TextServerExtension::string_to_lower(const String &p_string, const String
TypedArray<Vector3i> TextServerExtension::parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const {
TypedArray<Vector3i> ret;
- GDVIRTUAL_CALL(_parse_structured_text, p_parser_type, p_args, p_text, ret);
- return ret;
+ if (GDVIRTUAL_CALL(_parse_structured_text, p_parser_type, p_args, p_text, ret)) {
+ return ret;
+ }
+ return TextServer::parse_structured_text(p_parser_type, p_args, p_text);
}
PackedInt32Array TextServerExtension::string_get_word_breaks(const String &p_string, const String &p_language, int64_t p_chars_per_line) const {
diff --git a/servers/text/text_server_extension.h b/servers/text/text_server_extension.h
index 4f9ea55d33..53d30abee4 100644
--- a/servers/text/text_server_extension.h
+++ b/servers/text/text_server_extension.h
@@ -128,6 +128,11 @@ public:
GDVIRTUAL2(_font_set_antialiasing, RID, TextServer::FontAntialiasing);
GDVIRTUAL1RC(TextServer::FontAntialiasing, _font_get_antialiasing, RID);
+ virtual void font_set_disable_embedded_bitmaps(const RID &p_font_rid, bool p_disable_embedded_bitmaps) override;
+ virtual bool font_get_disable_embedded_bitmaps(const RID &p_font_rid) const override;
+ GDVIRTUAL2(_font_set_disable_embedded_bitmaps, RID, bool);
+ GDVIRTUAL1RC(bool, _font_get_disable_embedded_bitmaps, RID);
+
virtual void font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) override;
virtual bool font_get_generate_mipmaps(const RID &p_font_rid) const override;
GDVIRTUAL2(_font_set_generate_mipmaps, RID, bool);
@@ -486,8 +491,12 @@ public:
virtual Array shaped_text_get_objects(const RID &p_shaped) const override;
virtual Rect2 shaped_text_get_object_rect(const RID &p_shaped, const Variant &p_key) const override;
+ virtual Vector2i shaped_text_get_object_range(const RID &p_shaped, const Variant &p_key) const override;
+ virtual int64_t shaped_text_get_object_glyph(const RID &p_shaped, const Variant &p_key) const override;
GDVIRTUAL1RC(Array, _shaped_text_get_objects, RID);
GDVIRTUAL2RC(Rect2, _shaped_text_get_object_rect, RID, const Variant &);
+ GDVIRTUAL2RC(Vector2i, _shaped_text_get_object_range, RID, const Variant &);
+ GDVIRTUAL2RC(int64_t, _shaped_text_get_object_glyph, RID, const Variant &);
virtual Size2 shaped_text_get_size(const RID &p_shaped) const override;
virtual double shaped_text_get_ascent(const RID &p_shaped) const override;
@@ -557,8 +566,10 @@ public:
virtual String string_to_upper(const String &p_string, const String &p_language = "") const override;
virtual String string_to_lower(const String &p_string, const String &p_language = "") const override;
+ virtual String string_to_title(const String &p_string, const String &p_language = "") const override;
GDVIRTUAL2RC(String, _string_to_upper, const String &, const String &);
GDVIRTUAL2RC(String, _string_to_lower, const String &, const String &);
+ GDVIRTUAL2RC(String, _string_to_title, const String &, const String &);
TypedArray<Vector3i> parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const;
GDVIRTUAL3RC(TypedArray<Vector3i>, _parse_structured_text, StructuredTextParser, const Array &, const String &);
diff --git a/servers/text_server.cpp b/servers/text_server.cpp
index b67a698615..fac9e32d01 100644
--- a/servers/text_server.cpp
+++ b/servers/text_server.cpp
@@ -234,6 +234,9 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("font_set_antialiasing", "font_rid", "antialiasing"), &TextServer::font_set_antialiasing);
ClassDB::bind_method(D_METHOD("font_get_antialiasing", "font_rid"), &TextServer::font_get_antialiasing);
+ ClassDB::bind_method(D_METHOD("font_set_disable_embedded_bitmaps", "font_rid", "disable_embedded_bitmaps"), &TextServer::font_set_disable_embedded_bitmaps);
+ ClassDB::bind_method(D_METHOD("font_get_disable_embedded_bitmaps", "font_rid"), &TextServer::font_get_disable_embedded_bitmaps);
+
ClassDB::bind_method(D_METHOD("font_set_generate_mipmaps", "font_rid", "generate_mipmaps"), &TextServer::font_set_generate_mipmaps);
ClassDB::bind_method(D_METHOD("font_get_generate_mipmaps", "font_rid"), &TextServer::font_get_generate_mipmaps);
@@ -443,6 +446,8 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("shaped_text_get_objects", "shaped"), &TextServer::shaped_text_get_objects);
ClassDB::bind_method(D_METHOD("shaped_text_get_object_rect", "shaped", "key"), &TextServer::shaped_text_get_object_rect);
+ ClassDB::bind_method(D_METHOD("shaped_text_get_object_range", "shaped", "key"), &TextServer::shaped_text_get_object_range);
+ ClassDB::bind_method(D_METHOD("shaped_text_get_object_glyph", "shaped", "key"), &TextServer::shaped_text_get_object_glyph);
ClassDB::bind_method(D_METHOD("shaped_text_get_size", "shaped"), &TextServer::shaped_text_get_size);
ClassDB::bind_method(D_METHOD("shaped_text_get_ascent", "shaped"), &TextServer::shaped_text_get_ascent);
@@ -486,6 +491,7 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("string_to_upper", "string", "language"), &TextServer::string_to_upper, DEFVAL(""));
ClassDB::bind_method(D_METHOD("string_to_lower", "string", "language"), &TextServer::string_to_lower, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("string_to_title", "string", "language"), &TextServer::string_to_title, DEFVAL(""));
ClassDB::bind_method(D_METHOD("parse_structured_text", "parser_type", "args", "text"), &TextServer::parse_structured_text);
@@ -535,6 +541,7 @@ void TextServer::_bind_methods() {
BIND_BITFIELD_FLAG(BREAK_GRAPHEME_BOUND);
BIND_BITFIELD_FLAG(BREAK_ADAPTIVE);
BIND_BITFIELD_FLAG(BREAK_TRIM_EDGE_SPACES);
+ BIND_BITFIELD_FLAG(BREAK_TRIM_INDENT);
/* VisibleCharactersBehavior */
BIND_ENUM_CONSTANT(VC_CHARS_BEFORE_SHAPING);
@@ -636,6 +643,48 @@ void TextServer::_bind_methods() {
BIND_ENUM_CONSTANT(FIXED_SIZE_SCALE_ENABLED);
}
+_FORCE_INLINE_ int32_t ot_tag_from_string(const char *p_str, int p_len) {
+ char tag[4];
+ uint32_t i;
+
+ if (!p_str || !p_len || !*p_str) {
+ return OT_TAG(0, 0, 0, 0);
+ }
+
+ if (p_len < 0 || p_len > 4) {
+ p_len = 4;
+ }
+ for (i = 0; i < (uint32_t)p_len && p_str[i]; i++) {
+ tag[i] = p_str[i];
+ }
+
+ for (; i < 4; i++) {
+ tag[i] = ' ';
+ }
+
+ return OT_TAG(tag[0], tag[1], tag[2], tag[3]);
+}
+
+int64_t TextServer::name_to_tag(const String &p_name) const {
+ // No readable name, use tag string.
+ return ot_tag_from_string(p_name.replace("custom_", "").ascii().get_data(), -1);
+}
+
+_FORCE_INLINE_ void ot_tag_to_string(int32_t p_tag, char *p_buf) {
+ p_buf[0] = (char)(uint8_t)(p_tag >> 24);
+ p_buf[1] = (char)(uint8_t)(p_tag >> 16);
+ p_buf[2] = (char)(uint8_t)(p_tag >> 8);
+ p_buf[3] = (char)(uint8_t)(p_tag >> 0);
+}
+
+String TextServer::tag_to_name(int64_t p_tag) const {
+ // No readable name, use tag string.
+ char name[5];
+ memset(name, 0, 5);
+ ot_tag_to_string(p_tag, name);
+ return String("custom_") + String(name);
+}
+
Vector2 TextServer::get_hex_code_box_size(int64_t p_size, int64_t p_index) const {
int w = ((p_index <= 0xFF) ? 1 : ((p_index <= 0xFFFF) ? 2 : 3));
int sp = MAX(0, w - 1);
@@ -750,13 +799,28 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped
int l_size = shaped_text_get_glyph_count(p_shaped);
const Glyph *l_gl = const_cast<TextServer *>(this)->shaped_text_sort_logical(p_shaped);
+ double indent = 0.0;
+ if (p_break_flags.has_flag(BREAK_TRIM_INDENT)) {
+ for (int i = 0; i < l_size; i++) {
+ if ((l_gl[i].flags & GRAPHEME_IS_TAB) == GRAPHEME_IS_TAB || (l_gl[i].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE) {
+ indent += l_gl[i].advance * l_gl[i].repeat;
+ } else {
+ break;
+ }
+ }
+ }
+
for (int i = 0; i < l_size; i++) {
+ double l_width = p_width[chunk];
+ if (l_width > indent) {
+ l_width -= indent;
+ }
if (l_gl[i].start < p_start) {
prev_safe_break = i + 1;
continue;
}
if (l_gl[i].count > 0) {
- if ((p_width[chunk] > 0) && (width + l_gl[i].advance > p_width[chunk]) && (last_safe_break >= 0)) {
+ if ((l_width > 0) && (width + l_gl[i].advance > l_width) && (last_safe_break >= 0)) {
if (p_break_flags.has_flag(BREAK_TRIM_EDGE_SPACES)) {
int start_pos = prev_safe_break;
int end_pos = last_safe_break;
@@ -891,13 +955,25 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do
int l_size = shaped_text_get_glyph_count(p_shaped);
const Glyph *l_gl = const_cast<TextServer *>(this)->shaped_text_sort_logical(p_shaped);
+ double indent = 0.0;
+ if (p_break_flags.has_flag(BREAK_TRIM_INDENT)) {
+ for (int i = 0; i < l_size; i++) {
+ if ((l_gl[i].flags & GRAPHEME_IS_TAB) == GRAPHEME_IS_TAB || (l_gl[i].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE) {
+ indent += l_gl[i].advance * l_gl[i].repeat;
+ } else {
+ break;
+ }
+ }
+ }
+
+ double l_width = p_width;
for (int i = 0; i < l_size; i++) {
if (l_gl[i].start < p_start) {
prev_safe_break = i + 1;
continue;
}
if (l_gl[i].count > 0) {
- if ((p_width > 0) && (width + l_gl[i].advance * l_gl[i].repeat > p_width) && (last_safe_break >= 0)) {
+ if ((l_width > 0) && (width + l_gl[i].advance * l_gl[i].repeat > l_width) && (last_safe_break >= 0)) {
if (p_break_flags.has_flag(BREAK_TRIM_EDGE_SPACES)) {
int start_pos = prev_safe_break;
int end_pos = last_safe_break;
@@ -910,6 +986,9 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do
if (last_end <= l_gl[start_pos].start) {
lines.push_back(l_gl[start_pos].start);
lines.push_back(l_gl[end_pos].end);
+ if (p_width > indent) {
+ l_width = p_width - indent;
+ }
last_end = l_gl[end_pos].end;
}
trim_next = true;
@@ -917,6 +996,9 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do
if (last_end <= line_start) {
lines.push_back(line_start);
lines.push_back(l_gl[last_safe_break].end);
+ if (p_width > indent) {
+ l_width = p_width - indent;
+ }
last_end = l_gl[last_safe_break].end;
}
}
@@ -943,12 +1025,18 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do
if (last_end <= l_gl[start_pos].start) {
lines.push_back(l_gl[start_pos].start);
lines.push_back(l_gl[end_pos].end);
+ if (p_width > indent) {
+ l_width = p_width - indent;
+ }
last_end = l_gl[end_pos].end;
}
} else {
if (last_end <= line_start) {
lines.push_back(line_start);
lines.push_back(l_gl[i].end);
+ if (p_width > indent) {
+ l_width = p_width - indent;
+ }
last_end = l_gl[i].end;
}
}
diff --git a/servers/text_server.h b/servers/text_server.h
index c2cc444646..396d7ca8e5 100644
--- a/servers/text_server.h
+++ b/servers/text_server.h
@@ -43,6 +43,8 @@ class TypedArray;
struct Glyph;
struct CaretInfo;
+#define OT_TAG(m_c1, m_c2, m_c3, m_c4) ((int32_t)((((uint32_t)(m_c1) & 0xff) << 24) | (((uint32_t)(m_c2) & 0xff) << 16) | (((uint32_t)(m_c3) & 0xff) << 8) | ((uint32_t)(m_c4) & 0xff)))
+
class TextServer : public RefCounted {
GDCLASS(TextServer, RefCounted);
@@ -108,6 +110,7 @@ public:
BREAK_GRAPHEME_BOUND = 1 << 2,
BREAK_ADAPTIVE = 1 << 3,
BREAK_TRIM_EDGE_SPACES = 1 << 4,
+ BREAK_TRIM_INDENT = 1 << 5,
};
enum OverrunBehavior {
@@ -238,8 +241,8 @@ public:
virtual bool is_locale_right_to_left(const String &p_locale) const = 0;
- virtual int64_t name_to_tag(const String &p_name) const { return 0; };
- virtual String tag_to_name(int64_t p_tag) const { return ""; };
+ virtual int64_t name_to_tag(const String &p_name) const;
+ virtual String tag_to_name(int64_t p_tag) const;
/* Font interface */
@@ -273,6 +276,9 @@ public:
virtual void font_set_antialiasing(const RID &p_font_rid, FontAntialiasing p_antialiasing) = 0;
virtual FontAntialiasing font_get_antialiasing(const RID &p_font_rid) const = 0;
+ virtual void font_set_disable_embedded_bitmaps(const RID &p_font_rid, bool p_disable_embedded_bitmaps) = 0;
+ virtual bool font_get_disable_embedded_bitmaps(const RID &p_font_rid) const = 0;
+
virtual void font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) = 0;
virtual bool font_get_generate_mipmaps(const RID &p_font_rid) const = 0;
@@ -489,6 +495,8 @@ public:
virtual Array shaped_text_get_objects(const RID &p_shaped) const = 0;
virtual Rect2 shaped_text_get_object_rect(const RID &p_shaped, const Variant &p_key) const = 0;
+ virtual Vector2i shaped_text_get_object_range(const RID &p_shaped, const Variant &p_key) const = 0;
+ virtual int64_t shaped_text_get_object_glyph(const RID &p_shaped, const Variant &p_key) const = 0;
virtual Size2 shaped_text_get_size(const RID &p_shaped) const = 0;
virtual double shaped_text_get_ascent(const RID &p_shaped) const = 0;
@@ -538,6 +546,7 @@ public:
// Other string operations.
virtual String string_to_upper(const String &p_string, const String &p_language = "") const = 0;
virtual String string_to_lower(const String &p_string, const String &p_language = "") const = 0;
+ virtual String string_to_title(const String &p_string, const String &p_language = "") const = 0;
TypedArray<Vector3i> parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const;
diff --git a/servers/xr/xr_body_tracker.cpp b/servers/xr/xr_body_tracker.cpp
new file mode 100644
index 0000000000..cd58c14348
--- /dev/null
+++ b/servers/xr/xr_body_tracker.cpp
@@ -0,0 +1,171 @@
+/**************************************************************************/
+/* xr_body_tracker.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#include "xr_body_tracker.h"
+
+void XRBodyTracker::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_has_tracking_data", "has_data"), &XRBodyTracker::set_has_tracking_data);
+ ClassDB::bind_method(D_METHOD("get_has_tracking_data"), &XRBodyTracker::get_has_tracking_data);
+
+ ClassDB::bind_method(D_METHOD("set_body_flags", "flags"), &XRBodyTracker::set_body_flags);
+ ClassDB::bind_method(D_METHOD("get_body_flags"), &XRBodyTracker::get_body_flags);
+
+ ClassDB::bind_method(D_METHOD("set_joint_flags", "joint", "flags"), &XRBodyTracker::set_joint_flags);
+ ClassDB::bind_method(D_METHOD("get_joint_flags", "joint"), &XRBodyTracker::get_joint_flags);
+
+ ClassDB::bind_method(D_METHOD("set_joint_transform", "joint", "transform"), &XRBodyTracker::set_joint_transform);
+ ClassDB::bind_method(D_METHOD("get_joint_transform", "joint"), &XRBodyTracker::get_joint_transform);
+
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "has_tracking_data", PROPERTY_HINT_NONE), "set_has_tracking_data", "get_has_tracking_data");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "body_flags", PROPERTY_HINT_FLAGS, "Upper Body,Lower Body,Hands"), "set_body_flags", "get_body_flags");
+
+ BIND_BITFIELD_FLAG(BODY_FLAG_UPPER_BODY_SUPPORTED);
+ BIND_BITFIELD_FLAG(BODY_FLAG_LOWER_BODY_SUPPORTED);
+ BIND_BITFIELD_FLAG(BODY_FLAG_HANDS_SUPPORTED);
+
+ BIND_ENUM_CONSTANT(JOINT_ROOT);
+ BIND_ENUM_CONSTANT(JOINT_HIPS);
+ BIND_ENUM_CONSTANT(JOINT_SPINE);
+ BIND_ENUM_CONSTANT(JOINT_CHEST);
+ BIND_ENUM_CONSTANT(JOINT_UPPER_CHEST);
+ BIND_ENUM_CONSTANT(JOINT_NECK);
+ BIND_ENUM_CONSTANT(JOINT_HEAD);
+ BIND_ENUM_CONSTANT(JOINT_HEAD_TIP);
+ BIND_ENUM_CONSTANT(JOINT_LEFT_SHOULDER);
+ BIND_ENUM_CONSTANT(JOINT_LEFT_UPPER_ARM);
+ BIND_ENUM_CONSTANT(JOINT_LEFT_LOWER_ARM);
+ BIND_ENUM_CONSTANT(JOINT_RIGHT_SHOULDER);
+ BIND_ENUM_CONSTANT(JOINT_RIGHT_UPPER_ARM);
+ BIND_ENUM_CONSTANT(JOINT_RIGHT_LOWER_ARM);
+ BIND_ENUM_CONSTANT(JOINT_LEFT_UPPER_LEG);
+ BIND_ENUM_CONSTANT(JOINT_LEFT_LOWER_LEG);
+ BIND_ENUM_CONSTANT(JOINT_LEFT_FOOT);
+ BIND_ENUM_CONSTANT(JOINT_LEFT_TOES);
+ BIND_ENUM_CONSTANT(JOINT_RIGHT_UPPER_LEG);
+ BIND_ENUM_CONSTANT(JOINT_RIGHT_LOWER_LEG);
+ BIND_ENUM_CONSTANT(JOINT_RIGHT_FOOT);
+ BIND_ENUM_CONSTANT(JOINT_RIGHT_TOES);
+ BIND_ENUM_CONSTANT(JOINT_LEFT_HAND);
+ BIND_ENUM_CONSTANT(JOINT_LEFT_PALM);
+ BIND_ENUM_CONSTANT(JOINT_LEFT_WRIST);
+ BIND_ENUM_CONSTANT(JOINT_LEFT_THUMB_METACARPAL);
+ BIND_ENUM_CONSTANT(JOINT_LEFT_THUMB_PHALANX_PROXIMAL);
+ BIND_ENUM_CONSTANT(JOINT_LEFT_THUMB_PHALANX_DISTAL);
+ BIND_ENUM_CONSTANT(JOINT_LEFT_THUMB_TIP);
+ BIND_ENUM_CONSTANT(JOINT_LEFT_INDEX_FINGER_METACARPAL);
+ BIND_ENUM_CONSTANT(JOINT_LEFT_INDEX_FINGER_PHALANX_PROXIMAL);
+ BIND_ENUM_CONSTANT(JOINT_LEFT_INDEX_FINGER_PHALANX_INTERMEDIATE);
+ BIND_ENUM_CONSTANT(JOINT_LEFT_INDEX_FINGER_PHALANX_DISTAL);
+ BIND_ENUM_CONSTANT(JOINT_LEFT_INDEX_FINGER_TIP);
+ BIND_ENUM_CONSTANT(JOINT_LEFT_MIDDLE_FINGER_METACARPAL);
+ BIND_ENUM_CONSTANT(JOINT_LEFT_MIDDLE_FINGER_PHALANX_PROXIMAL);
+ BIND_ENUM_CONSTANT(JOINT_LEFT_MIDDLE_FINGER_PHALANX_INTERMEDIATE);
+ BIND_ENUM_CONSTANT(JOINT_LEFT_MIDDLE_FINGER_PHALANX_DISTAL);
+ BIND_ENUM_CONSTANT(JOINT_LEFT_MIDDLE_FINGER_TIP);
+ BIND_ENUM_CONSTANT(JOINT_LEFT_RING_FINGER_METACARPAL);
+ BIND_ENUM_CONSTANT(JOINT_LEFT_RING_FINGER_PHALANX_PROXIMAL);
+ BIND_ENUM_CONSTANT(JOINT_LEFT_RING_FINGER_PHALANX_INTERMEDIATE);
+ BIND_ENUM_CONSTANT(JOINT_LEFT_RING_FINGER_PHALANX_DISTAL);
+ BIND_ENUM_CONSTANT(JOINT_LEFT_RING_FINGER_TIP);
+ BIND_ENUM_CONSTANT(JOINT_LEFT_PINKY_FINGER_METACARPAL);
+ BIND_ENUM_CONSTANT(JOINT_LEFT_PINKY_FINGER_PHALANX_PROXIMAL);
+ BIND_ENUM_CONSTANT(JOINT_LEFT_PINKY_FINGER_PHALANX_INTERMEDIATE);
+ BIND_ENUM_CONSTANT(JOINT_LEFT_PINKY_FINGER_PHALANX_DISTAL);
+ BIND_ENUM_CONSTANT(JOINT_LEFT_PINKY_FINGER_TIP);
+ BIND_ENUM_CONSTANT(JOINT_RIGHT_HAND);
+ BIND_ENUM_CONSTANT(JOINT_RIGHT_PALM);
+ BIND_ENUM_CONSTANT(JOINT_RIGHT_WRIST);
+ BIND_ENUM_CONSTANT(JOINT_RIGHT_THUMB_METACARPAL);
+ BIND_ENUM_CONSTANT(JOINT_RIGHT_THUMB_PHALANX_PROXIMAL);
+ BIND_ENUM_CONSTANT(JOINT_RIGHT_THUMB_PHALANX_DISTAL);
+ BIND_ENUM_CONSTANT(JOINT_RIGHT_THUMB_TIP);
+ BIND_ENUM_CONSTANT(JOINT_RIGHT_INDEX_FINGER_METACARPAL);
+ BIND_ENUM_CONSTANT(JOINT_RIGHT_INDEX_FINGER_PHALANX_PROXIMAL);
+ BIND_ENUM_CONSTANT(JOINT_RIGHT_INDEX_FINGER_PHALANX_INTERMEDIATE);
+ BIND_ENUM_CONSTANT(JOINT_RIGHT_INDEX_FINGER_PHALANX_DISTAL);
+ BIND_ENUM_CONSTANT(JOINT_RIGHT_INDEX_FINGER_TIP);
+ BIND_ENUM_CONSTANT(JOINT_RIGHT_MIDDLE_FINGER_METACARPAL);
+ BIND_ENUM_CONSTANT(JOINT_RIGHT_MIDDLE_FINGER_PHALANX_PROXIMAL);
+ BIND_ENUM_CONSTANT(JOINT_RIGHT_MIDDLE_FINGER_PHALANX_INTERMEDIATE);
+ BIND_ENUM_CONSTANT(JOINT_RIGHT_MIDDLE_FINGER_PHALANX_DISTAL);
+ BIND_ENUM_CONSTANT(JOINT_RIGHT_MIDDLE_FINGER_TIP);
+ BIND_ENUM_CONSTANT(JOINT_RIGHT_RING_FINGER_METACARPAL);
+ BIND_ENUM_CONSTANT(JOINT_RIGHT_RING_FINGER_PHALANX_PROXIMAL);
+ BIND_ENUM_CONSTANT(JOINT_RIGHT_RING_FINGER_PHALANX_INTERMEDIATE);
+ BIND_ENUM_CONSTANT(JOINT_RIGHT_RING_FINGER_PHALANX_DISTAL);
+ BIND_ENUM_CONSTANT(JOINT_RIGHT_RING_FINGER_TIP);
+ BIND_ENUM_CONSTANT(JOINT_RIGHT_PINKY_FINGER_METACARPAL);
+ BIND_ENUM_CONSTANT(JOINT_RIGHT_PINKY_FINGER_PHALANX_PROXIMAL);
+ BIND_ENUM_CONSTANT(JOINT_RIGHT_PINKY_FINGER_PHALANX_INTERMEDIATE);
+ BIND_ENUM_CONSTANT(JOINT_RIGHT_PINKY_FINGER_PHALANX_DISTAL);
+ BIND_ENUM_CONSTANT(JOINT_RIGHT_PINKY_FINGER_TIP);
+ BIND_ENUM_CONSTANT(JOINT_MAX);
+
+ BIND_BITFIELD_FLAG(JOINT_FLAG_ORIENTATION_VALID);
+ BIND_BITFIELD_FLAG(JOINT_FLAG_ORIENTATION_TRACKED);
+ BIND_BITFIELD_FLAG(JOINT_FLAG_POSITION_VALID);
+ BIND_BITFIELD_FLAG(JOINT_FLAG_POSITION_TRACKED);
+}
+
+void XRBodyTracker::set_has_tracking_data(bool p_has_tracking_data) {
+ has_tracking_data = p_has_tracking_data;
+}
+
+bool XRBodyTracker::get_has_tracking_data() const {
+ return has_tracking_data;
+}
+
+void XRBodyTracker::set_body_flags(BitField<BodyFlags> p_body_flags) {
+ body_flags = p_body_flags;
+}
+
+BitField<XRBodyTracker::BodyFlags> XRBodyTracker::get_body_flags() const {
+ return body_flags;
+}
+
+void XRBodyTracker::set_joint_flags(Joint p_joint, BitField<JointFlags> p_flags) {
+ ERR_FAIL_INDEX(p_joint, JOINT_MAX);
+ joint_flags[p_joint] = p_flags;
+}
+
+BitField<XRBodyTracker::JointFlags> XRBodyTracker::get_joint_flags(Joint p_joint) const {
+ ERR_FAIL_INDEX_V(p_joint, JOINT_MAX, BitField<JointFlags>());
+ return joint_flags[p_joint];
+}
+
+void XRBodyTracker::set_joint_transform(Joint p_joint, const Transform3D &p_transform) {
+ ERR_FAIL_INDEX(p_joint, JOINT_MAX);
+ joint_transforms[p_joint] = p_transform;
+}
+
+Transform3D XRBodyTracker::get_joint_transform(Joint p_joint) const {
+ ERR_FAIL_INDEX_V(p_joint, JOINT_MAX, Transform3D());
+ return joint_transforms[p_joint];
+}
diff --git a/servers/xr/xr_body_tracker.h b/servers/xr/xr_body_tracker.h
new file mode 100644
index 0000000000..659aa39df1
--- /dev/null
+++ b/servers/xr/xr_body_tracker.h
@@ -0,0 +1,170 @@
+/**************************************************************************/
+/* xr_body_tracker.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef XR_BODY_TRACKER_H
+#define XR_BODY_TRACKER_H
+
+#include "core/object/ref_counted.h"
+
+class XRBodyTracker : public RefCounted {
+ GDCLASS(XRBodyTracker, RefCounted);
+ _THREAD_SAFE_CLASS_
+
+public:
+ enum BodyFlags {
+ BODY_FLAG_UPPER_BODY_SUPPORTED = 1,
+ BODY_FLAG_LOWER_BODY_SUPPORTED = 2,
+ BODY_FLAG_HANDS_SUPPORTED = 4,
+ };
+
+ enum Joint {
+ JOINT_ROOT,
+
+ // Upper Body Joints
+ JOINT_HIPS,
+ JOINT_SPINE,
+ JOINT_CHEST,
+ JOINT_UPPER_CHEST,
+ JOINT_NECK,
+ JOINT_HEAD,
+ JOINT_HEAD_TIP,
+ JOINT_LEFT_SHOULDER,
+ JOINT_LEFT_UPPER_ARM,
+ JOINT_LEFT_LOWER_ARM,
+ JOINT_RIGHT_SHOULDER,
+ JOINT_RIGHT_UPPER_ARM,
+ JOINT_RIGHT_LOWER_ARM,
+
+ // Lower Body Joints
+ JOINT_LEFT_UPPER_LEG,
+ JOINT_LEFT_LOWER_LEG,
+ JOINT_LEFT_FOOT,
+ JOINT_LEFT_TOES,
+ JOINT_RIGHT_UPPER_LEG,
+ JOINT_RIGHT_LOWER_LEG,
+ JOINT_RIGHT_FOOT,
+ JOINT_RIGHT_TOES,
+
+ // Left Hand Joints
+ JOINT_LEFT_HAND,
+ JOINT_LEFT_PALM,
+ JOINT_LEFT_WRIST,
+ JOINT_LEFT_THUMB_METACARPAL,
+ JOINT_LEFT_THUMB_PHALANX_PROXIMAL,
+ JOINT_LEFT_THUMB_PHALANX_DISTAL,
+ JOINT_LEFT_THUMB_TIP,
+ JOINT_LEFT_INDEX_FINGER_METACARPAL,
+ JOINT_LEFT_INDEX_FINGER_PHALANX_PROXIMAL,
+ JOINT_LEFT_INDEX_FINGER_PHALANX_INTERMEDIATE,
+ JOINT_LEFT_INDEX_FINGER_PHALANX_DISTAL,
+ JOINT_LEFT_INDEX_FINGER_TIP,
+ JOINT_LEFT_MIDDLE_FINGER_METACARPAL,
+ JOINT_LEFT_MIDDLE_FINGER_PHALANX_PROXIMAL,
+ JOINT_LEFT_MIDDLE_FINGER_PHALANX_INTERMEDIATE,
+ JOINT_LEFT_MIDDLE_FINGER_PHALANX_DISTAL,
+ JOINT_LEFT_MIDDLE_FINGER_TIP,
+ JOINT_LEFT_RING_FINGER_METACARPAL,
+ JOINT_LEFT_RING_FINGER_PHALANX_PROXIMAL,
+ JOINT_LEFT_RING_FINGER_PHALANX_INTERMEDIATE,
+ JOINT_LEFT_RING_FINGER_PHALANX_DISTAL,
+ JOINT_LEFT_RING_FINGER_TIP,
+ JOINT_LEFT_PINKY_FINGER_METACARPAL,
+ JOINT_LEFT_PINKY_FINGER_PHALANX_PROXIMAL,
+ JOINT_LEFT_PINKY_FINGER_PHALANX_INTERMEDIATE,
+ JOINT_LEFT_PINKY_FINGER_PHALANX_DISTAL,
+ JOINT_LEFT_PINKY_FINGER_TIP,
+
+ // Right Hand Joints
+ JOINT_RIGHT_HAND,
+ JOINT_RIGHT_PALM,
+ JOINT_RIGHT_WRIST,
+ JOINT_RIGHT_THUMB_METACARPAL,
+ JOINT_RIGHT_THUMB_PHALANX_PROXIMAL,
+ JOINT_RIGHT_THUMB_PHALANX_DISTAL,
+ JOINT_RIGHT_THUMB_TIP,
+ JOINT_RIGHT_INDEX_FINGER_METACARPAL,
+ JOINT_RIGHT_INDEX_FINGER_PHALANX_PROXIMAL,
+ JOINT_RIGHT_INDEX_FINGER_PHALANX_INTERMEDIATE,
+ JOINT_RIGHT_INDEX_FINGER_PHALANX_DISTAL,
+ JOINT_RIGHT_INDEX_FINGER_TIP,
+ JOINT_RIGHT_MIDDLE_FINGER_METACARPAL,
+ JOINT_RIGHT_MIDDLE_FINGER_PHALANX_PROXIMAL,
+ JOINT_RIGHT_MIDDLE_FINGER_PHALANX_INTERMEDIATE,
+ JOINT_RIGHT_MIDDLE_FINGER_PHALANX_DISTAL,
+ JOINT_RIGHT_MIDDLE_FINGER_TIP,
+ JOINT_RIGHT_RING_FINGER_METACARPAL,
+ JOINT_RIGHT_RING_FINGER_PHALANX_PROXIMAL,
+ JOINT_RIGHT_RING_FINGER_PHALANX_INTERMEDIATE,
+ JOINT_RIGHT_RING_FINGER_PHALANX_DISTAL,
+ JOINT_RIGHT_RING_FINGER_TIP,
+ JOINT_RIGHT_PINKY_FINGER_METACARPAL,
+ JOINT_RIGHT_PINKY_FINGER_PHALANX_PROXIMAL,
+ JOINT_RIGHT_PINKY_FINGER_PHALANX_INTERMEDIATE,
+ JOINT_RIGHT_PINKY_FINGER_PHALANX_DISTAL,
+ JOINT_RIGHT_PINKY_FINGER_TIP,
+
+ JOINT_MAX,
+ };
+
+ enum JointFlags {
+ JOINT_FLAG_ORIENTATION_VALID = 1,
+ JOINT_FLAG_ORIENTATION_TRACKED = 2,
+ JOINT_FLAG_POSITION_VALID = 4,
+ JOINT_FLAG_POSITION_TRACKED = 8,
+ };
+
+ void set_has_tracking_data(bool p_has_tracking_data);
+ bool get_has_tracking_data() const;
+
+ void set_body_flags(BitField<BodyFlags> p_body_flags);
+ BitField<BodyFlags> get_body_flags() const;
+
+ void set_joint_flags(Joint p_joint, BitField<JointFlags> p_flags);
+ BitField<JointFlags> get_joint_flags(Joint p_joint) const;
+
+ void set_joint_transform(Joint p_joint, const Transform3D &p_transform);
+ Transform3D get_joint_transform(Joint p_joint) const;
+
+protected:
+ static void _bind_methods();
+
+private:
+ bool has_tracking_data = false;
+ BitField<BodyFlags> body_flags;
+
+ BitField<JointFlags> joint_flags[JOINT_MAX];
+ Transform3D joint_transforms[JOINT_MAX];
+};
+
+VARIANT_BITFIELD_CAST(XRBodyTracker::BodyFlags)
+VARIANT_ENUM_CAST(XRBodyTracker::Joint)
+VARIANT_BITFIELD_CAST(XRBodyTracker::JointFlags)
+
+#endif // XR_BODY_TRACKER_H
diff --git a/servers/xr_server.cpp b/servers/xr_server.cpp
index 1e497e22c3..af14ba4a00 100644
--- a/servers/xr_server.cpp
+++ b/servers/xr_server.cpp
@@ -30,6 +30,7 @@
#include "xr_server.h"
#include "core/config/project_settings.h"
+#include "xr/xr_body_tracker.h"
#include "xr/xr_face_tracker.h"
#include "xr/xr_hand_tracker.h"
#include "xr/xr_interface.h"
@@ -86,6 +87,11 @@ void XRServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_face_trackers"), &XRServer::get_face_trackers);
ClassDB::bind_method(D_METHOD("get_face_tracker", "tracker_name"), &XRServer::get_face_tracker);
+ ClassDB::bind_method(D_METHOD("add_body_tracker", "tracker_name", "body_tracker"), &XRServer::add_body_tracker);
+ ClassDB::bind_method(D_METHOD("remove_body_tracker", "tracker_name"), &XRServer::remove_body_tracker);
+ ClassDB::bind_method(D_METHOD("get_body_trackers"), &XRServer::get_body_trackers);
+ ClassDB::bind_method(D_METHOD("get_body_tracker", "tracker_name"), &XRServer::get_body_tracker);
+
ClassDB::bind_method(D_METHOD("get_primary_interface"), &XRServer::get_primary_interface);
ClassDB::bind_method(D_METHOD("set_primary_interface", "interface"), &XRServer::set_primary_interface);
@@ -117,6 +123,10 @@ void XRServer::_bind_methods() {
ADD_SIGNAL(MethodInfo("face_tracker_added", PropertyInfo(Variant::STRING_NAME, "tracker_name"), PropertyInfo(Variant::OBJECT, "face_tracker", PROPERTY_HINT_RESOURCE_TYPE, "XRFaceTracker")));
ADD_SIGNAL(MethodInfo("face_tracker_updated", PropertyInfo(Variant::STRING_NAME, "tracker_name"), PropertyInfo(Variant::OBJECT, "face_tracker", PROPERTY_HINT_RESOURCE_TYPE, "XRFaceTracker")));
ADD_SIGNAL(MethodInfo("face_tracker_removed", PropertyInfo(Variant::STRING_NAME, "tracker_name")));
+
+ ADD_SIGNAL(MethodInfo("body_tracker_added", PropertyInfo(Variant::STRING_NAME, "tracker_name"), PropertyInfo(Variant::OBJECT, "body_tracker", PROPERTY_HINT_RESOURCE_TYPE, "XRBodyTracker")));
+ ADD_SIGNAL(MethodInfo("body_tracker_updated", PropertyInfo(Variant::STRING_NAME, "tracker_name"), PropertyInfo(Variant::OBJECT, "body_tracker", PROPERTY_HINT_RESOURCE_TYPE, "XRBodyTracker")));
+ ADD_SIGNAL(MethodInfo("body_tracker_removed", PropertyInfo(Variant::STRING_NAME, "tracker_name")));
};
double XRServer::get_world_scale() const {
@@ -448,6 +458,44 @@ Ref<XRFaceTracker> XRServer::get_face_tracker(const StringName &p_tracker_name)
return face_trackers[p_tracker_name];
}
+void XRServer::add_body_tracker(const StringName &p_tracker_name, Ref<XRBodyTracker> p_body_tracker) {
+ ERR_FAIL_COND(p_body_tracker.is_null());
+
+ if (!body_trackers.has(p_tracker_name)) {
+ // We don't have a tracker with this name, we're going to add it.
+ body_trackers[p_tracker_name] = p_body_tracker;
+ emit_signal(SNAME("body_tracker_added"), p_tracker_name, p_body_tracker);
+ } else if (body_trackers[p_tracker_name] != p_body_tracker) {
+ // We already have a tracker with this name, we're going to replace it.
+ body_trackers[p_tracker_name] = p_body_tracker;
+ emit_signal(SNAME("body_tracker_updated"), p_tracker_name, p_body_tracker);
+ }
+}
+
+void XRServer::remove_body_tracker(const StringName &p_tracker_name) {
+ // Skip if no face tracker is found.
+ if (!body_trackers.has(p_tracker_name)) {
+ return;
+ }
+
+ // Send the removed signal, then remove the face tracker.
+ emit_signal(SNAME("body_tracker_removed"), p_tracker_name);
+ body_trackers.erase(p_tracker_name);
+}
+
+Dictionary XRServer::get_body_trackers() const {
+ return body_trackers;
+}
+
+Ref<XRBodyTracker> XRServer::get_body_tracker(const StringName &p_tracker_name) const {
+ // Skip if no tracker is found.
+ if (!body_trackers.has(p_tracker_name)) {
+ return Ref<XRBodyTracker>();
+ }
+
+ return body_trackers[p_tracker_name];
+}
+
void XRServer::_process() {
// called from our main game loop before we handle physics and game logic
// note that we can have multiple interfaces active if we have interfaces that purely handle tracking
diff --git a/servers/xr_server.h b/servers/xr_server.h
index 3e45bbb76c..6aaa34b21d 100644
--- a/servers/xr_server.h
+++ b/servers/xr_server.h
@@ -41,6 +41,7 @@ class XRInterface;
class XRPositionalTracker;
class XRHandTracker;
class XRFaceTracker;
+class XRBodyTracker;
/**
The XR server is a singleton object that gives access to the various
@@ -89,6 +90,7 @@ private:
Dictionary trackers;
Dictionary hand_trackers;
Dictionary face_trackers;
+ Dictionary body_trackers;
Ref<XRInterface> primary_interface; /* we'll identify one interface as primary, this will be used by our viewports */
@@ -203,6 +205,14 @@ public:
Dictionary get_face_trackers() const;
Ref<XRFaceTracker> get_face_tracker(const StringName &p_tracker_name) const;
+ /*
+ Body trackers are objects that expose the tracked joints of a body.
+ */
+ void add_body_tracker(const StringName &p_tracker_name, Ref<XRBodyTracker> p_face_tracker);
+ void remove_body_tracker(const StringName &p_tracker_name);
+ Dictionary get_body_trackers() const;
+ Ref<XRBodyTracker> get_body_tracker(const StringName &p_tracker_name) const;
+
// Process is called before we handle our physics process and game process. This is where our interfaces will update controller data and such.
void _process();