summaryrefslogtreecommitdiff
path: root/servers
diff options
context:
space:
mode:
Diffstat (limited to 'servers')
-rw-r--r--servers/arvr/arvr_interface.h2
-rw-r--r--servers/arvr_server.cpp2
-rw-r--r--servers/audio/audio_effect.h1
-rw-r--r--servers/audio/audio_stream.cpp114
-rw-r--r--servers/audio/audio_stream.h57
-rw-r--r--servers/audio/effects/audio_effect_chorus.cpp4
-rw-r--r--servers/audio/effects/audio_effect_eq.cpp6
-rw-r--r--servers/audio/effects/audio_effect_record.cpp264
-rw-r--r--servers/audio/effects/audio_effect_record.h103
-rw-r--r--servers/audio/effects/eq.cpp8
-rw-r--r--servers/audio_server.cpp136
-rw-r--r--servers/audio_server.h34
-rw-r--r--servers/physics/body_pair_sw.cpp34
-rw-r--r--servers/physics/body_sw.cpp16
-rw-r--r--servers/physics/body_sw.h17
-rw-r--r--servers/physics/collision_object_sw.cpp18
-rw-r--r--servers/physics/collision_object_sw.h2
-rw-r--r--servers/physics/collision_solver_sat.cpp66
-rw-r--r--servers/physics/physics_server_sw.cpp14
-rw-r--r--servers/physics/physics_server_sw.h4
-rw-r--r--servers/physics/space_sw.h2
-rw-r--r--servers/physics_2d/body_2d_sw.cpp16
-rw-r--r--servers/physics_2d/body_2d_sw.h14
-rw-r--r--servers/physics_2d/body_pair_2d_sw.cpp34
-rw-r--r--servers/physics_2d/collision_object_2d_sw.cpp22
-rw-r--r--servers/physics_2d/collision_object_2d_sw.h2
-rw-r--r--servers/physics_2d/physics_2d_server_sw.cpp16
-rw-r--r--servers/physics_2d/physics_2d_server_sw.h4
-rw-r--r--servers/physics_2d/physics_2d_server_wrap_mt.h3
-rw-r--r--servers/physics_2d/shape_2d_sw.cpp16
-rw-r--r--servers/physics_2d/space_2d_sw.h2
-rw-r--r--servers/physics_2d_server.cpp4
-rw-r--r--servers/physics_2d_server.h13
-rw-r--r--servers/physics_server.cpp3
-rw-r--r--servers/physics_server.h14
-rw-r--r--servers/register_server_types.cpp5
-rw-r--r--servers/server_wrap_mt_common.h7
-rw-r--r--servers/visual/rasterizer.h29
-rw-r--r--servers/visual/shader_language.cpp283
-rw-r--r--servers/visual/shader_language.h14
-rw-r--r--servers/visual/visual_server_canvas.cpp22
-rw-r--r--servers/visual/visual_server_raster.cpp5
-rw-r--r--servers/visual/visual_server_raster.h14
-rw-r--r--servers/visual/visual_server_scene.cpp48
-rw-r--r--servers/visual/visual_server_viewport.cpp8
-rw-r--r--servers/visual/visual_server_viewport.h1
-rw-r--r--servers/visual/visual_server_wrap_mt.cpp10
-rw-r--r--servers/visual/visual_server_wrap_mt.h16
-rw-r--r--servers/visual_server.cpp34
-rw-r--r--servers/visual_server.h45
50 files changed, 1202 insertions, 406 deletions
diff --git a/servers/arvr/arvr_interface.h b/servers/arvr/arvr_interface.h
index 0b922c5892..910b401db9 100644
--- a/servers/arvr/arvr_interface.h
+++ b/servers/arvr/arvr_interface.h
@@ -88,7 +88,7 @@ public:
bool is_primary();
void set_is_primary(bool p_is_primary);
- virtual bool is_initialized() = 0; /* returns true if we've initialized this interface */
+ virtual bool is_initialized() const = 0; /* returns true if we've initialized this interface */
void set_is_initialized(bool p_initialized); /* helper function, will call initialize or uninitialize */
virtual bool initialize() = 0; /* initialize this interface, if this has an HMD it becomes the primary interface */
virtual void uninitialize() = 0; /* deinitialize this interface */
diff --git a/servers/arvr_server.cpp b/servers/arvr_server.cpp
index f48bedbdac..0d1aad0dff 100644
--- a/servers/arvr_server.cpp
+++ b/servers/arvr_server.cpp
@@ -353,7 +353,7 @@ void ARVRServer::_process() {
if (!interfaces[i].is_valid()) {
// ignore, not a valid reference
} else if (interfaces[i]->is_initialized()) {
- interfaces[i]->process();
+ interfaces.write[i]->process();
};
};
};
diff --git a/servers/audio/audio_effect.h b/servers/audio/audio_effect.h
index cf732d4bdd..b950e824c0 100644
--- a/servers/audio/audio_effect.h
+++ b/servers/audio/audio_effect.h
@@ -39,6 +39,7 @@ class AudioEffectInstance : public Reference {
public:
virtual void process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) = 0;
+ virtual bool process_silence() const { return false; }
};
class AudioEffect : public Resource {
diff --git a/servers/audio/audio_stream.cpp b/servers/audio/audio_stream.cpp
index 113f23f8f2..eef8aba0c4 100644
--- a/servers/audio/audio_stream.cpp
+++ b/servers/audio/audio_stream.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "audio_stream.h"
+#include "os/os.h"
//////////////////////////////
@@ -99,6 +100,119 @@ void AudioStream::_bind_methods() {
////////////////////////////////
+Ref<AudioStreamPlayback> AudioStreamMicrophone::instance_playback() {
+ Ref<AudioStreamPlaybackMicrophone> playback;
+ playback.instance();
+
+ playbacks.insert(playback.ptr());
+
+ playback->microphone = Ref<AudioStreamMicrophone>((AudioStreamMicrophone *)this);
+ playback->active = false;
+
+ return playback;
+}
+
+String AudioStreamMicrophone::get_stream_name() const {
+
+ //if (audio_stream.is_valid()) {
+ //return "Random: " + audio_stream->get_name();
+ //}
+ return "Microphone";
+}
+
+float AudioStreamMicrophone::get_length() const {
+ return 0;
+}
+
+void AudioStreamMicrophone::_bind_methods() {
+}
+
+AudioStreamMicrophone::AudioStreamMicrophone() {
+}
+
+void AudioStreamPlaybackMicrophone::_mix_internal(AudioFrame *p_buffer, int p_frames) {
+
+ AudioDriver::get_singleton()->lock();
+
+ Vector<int32_t> buf = AudioDriver::get_singleton()->get_input_buffer();
+ unsigned int input_size = AudioDriver::get_singleton()->get_input_size();
+
+ // p_frames is multipled by two since an AudioFrame is stereo
+ if ((p_frames + MICROPHONE_PLAYBACK_DELAY * 2) > input_size) {
+ for (int i = 0; i < p_frames; i++) {
+ p_buffer[i] = AudioFrame(0.0f, 0.0f);
+ }
+ input_ofs = 0;
+ } else {
+ for (int i = 0; i < p_frames; i++) {
+ if (input_size >= input_ofs) {
+ float l = (buf[input_ofs++] >> 16) / 32768.f;
+ if (input_ofs >= buf.size()) {
+ input_ofs = 0;
+ }
+ float r = (buf[input_ofs++] >> 16) / 32768.f;
+ if (input_ofs >= buf.size()) {
+ input_ofs = 0;
+ }
+
+ p_buffer[i] = AudioFrame(l, r);
+ } else {
+ p_buffer[i] = AudioFrame(0.0f, 0.0f);
+ }
+ }
+ }
+
+ AudioDriver::get_singleton()->unlock();
+}
+
+void AudioStreamPlaybackMicrophone::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) {
+ AudioStreamPlaybackResampled::mix(p_buffer, p_rate_scale, p_frames);
+}
+
+float AudioStreamPlaybackMicrophone::get_stream_sampling_rate() {
+ return AudioDriver::get_singleton()->get_mix_rate();
+}
+
+void AudioStreamPlaybackMicrophone::start(float p_from_pos) {
+ input_ofs = 0;
+
+ AudioDriver::get_singleton()->capture_start();
+
+ active = true;
+ _begin_resample();
+}
+
+void AudioStreamPlaybackMicrophone::stop() {
+ AudioDriver::get_singleton()->capture_stop();
+ active = false;
+}
+
+bool AudioStreamPlaybackMicrophone::is_playing() const {
+ return active;
+}
+
+int AudioStreamPlaybackMicrophone::get_loop_count() const {
+ return 0;
+}
+
+float AudioStreamPlaybackMicrophone::get_playback_position() const {
+ return 0;
+}
+
+void AudioStreamPlaybackMicrophone::seek(float p_time) {
+ return; // Can't seek a microphone input
+}
+
+AudioStreamPlaybackMicrophone::~AudioStreamPlaybackMicrophone() {
+ microphone->playbacks.erase(this);
+ stop();
+}
+
+AudioStreamPlaybackMicrophone::AudioStreamPlaybackMicrophone() {
+}
+
+////////////////////////////////
+
void AudioStreamRandomPitch::set_audio_stream(const Ref<AudioStream> &p_audio_stream) {
audio_stream = p_audio_stream;
diff --git a/servers/audio/audio_stream.h b/servers/audio/audio_stream.h
index 3312ce1ff6..66e1b6ee2f 100644
--- a/servers/audio/audio_stream.h
+++ b/servers/audio/audio_stream.h
@@ -94,6 +94,63 @@ public:
virtual float get_length() const = 0; //if supported, otherwise return 0
};
+// Microphone
+
+class AudioStreamPlaybackMicrophone;
+
+class AudioStreamMicrophone : public AudioStream {
+
+ GDCLASS(AudioStreamMicrophone, AudioStream)
+ friend class AudioStreamPlaybackMicrophone;
+
+ Set<AudioStreamPlaybackMicrophone *> playbacks;
+
+protected:
+ static void _bind_methods();
+
+public:
+ virtual Ref<AudioStreamPlayback> instance_playback();
+ virtual String get_stream_name() const;
+
+ virtual float get_length() const; //if supported, otherwise return 0
+
+ AudioStreamMicrophone();
+};
+
+class AudioStreamPlaybackMicrophone : public AudioStreamPlaybackResampled {
+
+ GDCLASS(AudioStreamPlaybackMicrophone, AudioStreamPlayback)
+ friend class AudioStreamMicrophone;
+
+ const int MICROPHONE_PLAYBACK_DELAY = 256;
+
+ bool active;
+ unsigned int input_ofs;
+
+ Ref<AudioStreamMicrophone> microphone;
+
+protected:
+ virtual void _mix_internal(AudioFrame *p_buffer, int p_frames);
+ virtual float get_stream_sampling_rate();
+
+public:
+ virtual void mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames);
+
+ virtual void start(float p_from_pos = 0.0);
+ virtual void stop();
+ virtual bool is_playing() const;
+
+ virtual int get_loop_count() const; //times it looped
+
+ virtual float get_playback_position() const;
+ virtual void seek(float p_time);
+
+ ~AudioStreamPlaybackMicrophone();
+ AudioStreamPlaybackMicrophone();
+};
+
+//
+
class AudioStreamPlaybackRandomPitch;
class AudioStreamRandomPitch : public AudioStream {
diff --git a/servers/audio/effects/audio_effect_chorus.cpp b/servers/audio/effects/audio_effect_chorus.cpp
index f2f554a09b..fd9e3311e7 100644
--- a/servers/audio/effects/audio_effect_chorus.cpp
+++ b/servers/audio/effects/audio_effect_chorus.cpp
@@ -53,7 +53,7 @@ void AudioEffectChorusInstance::_process_chunk(const AudioFrame *p_src_frames, A
//fill ringbuffer
for (int i = 0; i < p_frame_count; i++) {
- audio_buffer[(buffer_pos + i) & buffer_mask] = p_src_frames[i];
+ audio_buffer.write[(buffer_pos + i) & buffer_mask] = p_src_frames[i];
p_dst_frames[i] = p_src_frames[i] * base->dry;
}
@@ -175,7 +175,7 @@ Ref<AudioEffectInstance> AudioEffectChorus::instance() {
ins->buffer_pos = 0;
ins->audio_buffer.resize(ringbuff_size);
for (int i = 0; i < ringbuff_size; i++) {
- ins->audio_buffer[i] = AudioFrame(0, 0);
+ ins->audio_buffer.write[i] = AudioFrame(0, 0);
}
return ins;
diff --git a/servers/audio/effects/audio_effect_eq.cpp b/servers/audio/effects/audio_effect_eq.cpp
index a30fca4e8d..cf8f7d3e16 100644
--- a/servers/audio/effects/audio_effect_eq.cpp
+++ b/servers/audio/effects/audio_effect_eq.cpp
@@ -70,7 +70,7 @@ Ref<AudioEffectInstance> AudioEffectEQ::instance() {
for (int i = 0; i < 2; i++) {
ins->bands[i].resize(eq.get_band_count());
for (int j = 0; j < ins->bands[i].size(); j++) {
- ins->bands[i][j] = eq.get_band_processor(j);
+ ins->bands[i].write[j] = eq.get_band_processor(j);
}
}
@@ -79,7 +79,7 @@ Ref<AudioEffectInstance> AudioEffectEQ::instance() {
void AudioEffectEQ::set_band_gain_db(int p_band, float p_volume) {
ERR_FAIL_INDEX(p_band, gain.size());
- gain[p_band] = p_volume;
+ gain.write[p_band] = p_volume;
}
float AudioEffectEQ::get_band_gain_db(int p_band) const {
@@ -134,7 +134,7 @@ AudioEffectEQ::AudioEffectEQ(EQ::Preset p_preset) {
eq.set_preset_band_mode(p_preset);
gain.resize(eq.get_band_count());
for (int i = 0; i < gain.size(); i++) {
- gain[i] = 0.0;
+ gain.write[i] = 0.0;
String name = "band_db/" + itos(eq.get_band_frequency(i)) + "_hz";
prop_band_map[name] = i;
band_names.push_back(name);
diff --git a/servers/audio/effects/audio_effect_record.cpp b/servers/audio/effects/audio_effect_record.cpp
new file mode 100644
index 0000000000..74a6838d1a
--- /dev/null
+++ b/servers/audio/effects/audio_effect_record.cpp
@@ -0,0 +1,264 @@
+/*************************************************************************/
+/* audio_effect_record.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "audio_effect_record.h"
+
+void AudioEffectRecordInstance::process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) {
+ if (!is_recording) {
+ return;
+ }
+
+ //Add incoming audio frames to the IO ring buffer
+ const AudioFrame *src = p_src_frames;
+ AudioFrame *rb_buf = ring_buffer.ptrw();
+ for (int i = 0; i < p_frame_count; i++) {
+ rb_buf[ring_buffer_pos & ring_buffer_mask] = src[i];
+ ring_buffer_pos++;
+ }
+}
+
+bool AudioEffectRecordInstance::process_silence() {
+ return true;
+}
+
+void AudioEffectRecordInstance::_io_thread_process() {
+
+ //Reset recorder status
+ thread_active = true;
+ ring_buffer_pos = 0;
+ ring_buffer_read_pos = 0;
+
+ //We start a new recording
+ recording_data.resize(0); //Clear data completely and reset length
+ is_recording = true;
+
+ while (is_recording) {
+ //Check: The current recording has been requested to stop
+ if (is_recording && !base->recording_active) {
+ is_recording = false;
+ }
+
+ //Case: Frames are remaining in the buffer
+ if (ring_buffer_read_pos < ring_buffer_pos) {
+ //Read from the buffer into recording_data
+ _io_store_buffer();
+ }
+ //Case: The buffer is empty
+ else if (is_recording) {
+ //Wait to avoid too much busy-wait
+ OS::get_singleton()->delay_usec(500);
+ }
+ }
+
+ thread_active = false;
+}
+
+void AudioEffectRecordInstance::_io_store_buffer() {
+ int to_read = ring_buffer_pos - ring_buffer_read_pos;
+
+ AudioFrame *rb_buf = ring_buffer.ptrw();
+
+ while (to_read) {
+ AudioFrame buffered_frame = rb_buf[ring_buffer_read_pos & ring_buffer_mask];
+ recording_data.push_back(buffered_frame.l);
+ recording_data.push_back(buffered_frame.r);
+
+ ring_buffer_read_pos++;
+ to_read--;
+ }
+}
+
+void AudioEffectRecordInstance::_thread_callback(void *_instance) {
+
+ AudioEffectRecordInstance *aeri = reinterpret_cast<AudioEffectRecordInstance *>(_instance);
+
+ aeri->_io_thread_process();
+}
+
+void AudioEffectRecordInstance::init() {
+ io_thread = Thread::create(_thread_callback, this);
+}
+
+Ref<AudioEffectInstance> AudioEffectRecord::instance() {
+ Ref<AudioEffectRecordInstance> ins;
+ ins.instance();
+ ins->base = Ref<AudioEffectRecord>(this);
+ ins->is_recording = false;
+
+ //Re-using the buffer size calculations from audio_effect_delay.cpp
+ float ring_buffer_max_size = IO_BUFFER_SIZE_MS;
+ ring_buffer_max_size /= 1000.0; //convert to seconds
+ ring_buffer_max_size *= AudioServer::get_singleton()->get_mix_rate();
+
+ int ringbuff_size = ring_buffer_max_size;
+
+ int bits = 0;
+
+ while (ringbuff_size > 0) {
+ bits++;
+ ringbuff_size /= 2;
+ }
+
+ ringbuff_size = 1 << bits;
+ ins->ring_buffer_mask = ringbuff_size - 1;
+ ins->ring_buffer_pos = 0;
+
+ ins->ring_buffer.resize(ringbuff_size);
+
+ ins->ring_buffer_read_pos = 0;
+
+ ensure_thread_stopped();
+ current_instance = ins;
+ if (recording_active) {
+ ins->init();
+ }
+
+ return ins;
+}
+
+void AudioEffectRecord::ensure_thread_stopped() {
+ recording_active = false;
+ if (current_instance != 0 && current_instance->thread_active) {
+ Thread::wait_to_finish(current_instance->io_thread);
+ }
+}
+
+void AudioEffectRecord::set_recording_active(bool p_record) {
+ if (p_record) {
+ if (current_instance == 0) {
+ WARN_PRINTS("Recording should not be set as active before Godot has initialized.");
+ recording_active = false;
+ return;
+ }
+
+ ensure_thread_stopped();
+ current_instance->init();
+ }
+
+ recording_active = p_record;
+}
+
+bool AudioEffectRecord::is_recording_active() const {
+ return recording_active;
+}
+
+void AudioEffectRecord::set_format(AudioStreamSample::Format p_format) {
+ format = p_format;
+}
+
+AudioStreamSample::Format AudioEffectRecord::get_format() const {
+ return format;
+}
+
+Ref<AudioStreamSample> AudioEffectRecord::get_recording() const {
+ AudioStreamSample::Format dst_format = format;
+ bool stereo = true; //forcing mono is not implemented
+
+ PoolVector<uint8_t> dst_data;
+
+ if (dst_format == AudioStreamSample::FORMAT_8_BITS) {
+ int data_size = current_instance->recording_data.size();
+ dst_data.resize(data_size);
+ PoolVector<uint8_t>::Write w = dst_data.write();
+
+ for (int i = 0; i < data_size; i++) {
+ int8_t v = CLAMP(current_instance->recording_data[i] * 128, -128, 127);
+ w[i] = v;
+ }
+ } else if (dst_format == AudioStreamSample::FORMAT_16_BITS) {
+ int data_size = current_instance->recording_data.size();
+ dst_data.resize(data_size * 2);
+ PoolVector<uint8_t>::Write w = dst_data.write();
+
+ for (int i = 0; i < data_size; i++) {
+ int16_t v = CLAMP(current_instance->recording_data[i] * 32768, -32768, 32767);
+ encode_uint16(v, &w[i * 2]);
+ }
+ } else if (dst_format == AudioStreamSample::FORMAT_IMA_ADPCM) {
+ //byte interleave
+ Vector<float> left;
+ Vector<float> right;
+
+ int tframes = current_instance->recording_data.size() / 2;
+ left.resize(tframes);
+ right.resize(tframes);
+
+ for (int i = 0; i < tframes; i++) {
+ left.set(i, current_instance->recording_data[i * 2 + 0]);
+ right.set(i, current_instance->recording_data[i * 2 + 1]);
+ }
+
+ PoolVector<uint8_t> bleft;
+ PoolVector<uint8_t> bright;
+
+ ResourceImporterWAV::_compress_ima_adpcm(left, bleft);
+ ResourceImporterWAV::_compress_ima_adpcm(right, bright);
+
+ int dl = bleft.size();
+ dst_data.resize(dl * 2);
+
+ PoolVector<uint8_t>::Write w = dst_data.write();
+ PoolVector<uint8_t>::Read rl = bleft.read();
+ PoolVector<uint8_t>::Read rr = bright.read();
+
+ for (int i = 0; i < dl; i++) {
+ w[i * 2 + 0] = rl[i];
+ w[i * 2 + 1] = rr[i];
+ }
+ } else {
+ ERR_EXPLAIN("format not implemented");
+ }
+
+ Ref<AudioStreamSample> sample;
+ sample.instance();
+ sample->set_data(dst_data);
+ sample->set_format(dst_format);
+ sample->set_mix_rate(AudioServer::get_singleton()->get_mix_rate());
+ sample->set_loop_mode(AudioStreamSample::LOOP_DISABLED);
+ sample->set_loop_begin(0);
+ sample->set_loop_end(0);
+ sample->set_stereo(stereo);
+
+ return sample;
+}
+
+void AudioEffectRecord::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_recording_active", "record"), &AudioEffectRecord::set_recording_active);
+ ClassDB::bind_method(D_METHOD("is_recording_active"), &AudioEffectRecord::is_recording_active);
+ ClassDB::bind_method(D_METHOD("set_format", "format"), &AudioEffectRecord::set_format);
+ ClassDB::bind_method(D_METHOD("get_format"), &AudioEffectRecord::get_format);
+ ClassDB::bind_method(D_METHOD("get_recording"), &AudioEffectRecord::get_recording);
+
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "format", PROPERTY_HINT_ENUM, "8-Bit,16-Bit,IMA-ADPCM"), "set_format", "get_format");
+}
+
+AudioEffectRecord::AudioEffectRecord() {
+ format = AudioStreamSample::FORMAT_16_BITS;
+}
diff --git a/servers/audio/effects/audio_effect_record.h b/servers/audio/effects/audio_effect_record.h
new file mode 100644
index 0000000000..e4f5ba8a23
--- /dev/null
+++ b/servers/audio/effects/audio_effect_record.h
@@ -0,0 +1,103 @@
+/*************************************************************************/
+/* audio_effect_record.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef AUDIOEFFECTRECORD_H
+#define AUDIOEFFECTRECORD_H
+
+#include "core/os/thread.h"
+#include "editor/import/resource_importer_wav.h"
+#include "io/marshalls.h"
+#include "os/file_access.h"
+#include "os/os.h"
+#include "scene/resources/audio_stream_sample.h"
+#include "servers/audio/audio_effect.h"
+#include "servers/audio_server.h"
+
+class AudioEffectRecord;
+
+class AudioEffectRecordInstance : public AudioEffectInstance {
+ GDCLASS(AudioEffectRecordInstance, AudioEffectInstance)
+ friend class AudioEffectRecord;
+ Ref<AudioEffectRecord> base;
+
+ bool is_recording;
+ Thread *io_thread;
+ bool thread_active = false;
+
+ Vector<AudioFrame> ring_buffer;
+ Vector<float> recording_data;
+
+ unsigned int ring_buffer_pos;
+ unsigned int ring_buffer_mask;
+ unsigned int ring_buffer_read_pos;
+
+ void _io_thread_process();
+ void _io_store_buffer();
+ static void _thread_callback(void *_instance);
+ void _init_recording();
+
+public:
+ void init();
+ virtual void process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count);
+ virtual bool process_silence();
+};
+
+class AudioEffectRecord : public AudioEffect {
+ GDCLASS(AudioEffectRecord, AudioEffect)
+
+ friend class AudioEffectRecordInstance;
+
+ enum {
+ IO_BUFFER_SIZE_MS = 1500
+ };
+
+ bool recording_active;
+ Ref<AudioEffectRecordInstance> current_instance;
+
+ AudioStreamSample::Format format;
+
+ void ensure_thread_stopped();
+
+protected:
+ static void _bind_methods();
+ static void debug(uint64_t time_diff, int p_frame_count);
+
+public:
+ Ref<AudioEffectInstance> instance();
+ void set_recording_active(bool p_record);
+ bool is_recording_active() const;
+ void set_format(AudioStreamSample::Format p_format);
+ AudioStreamSample::Format get_format() const;
+ Ref<AudioStreamSample> get_recording() const;
+
+ AudioEffectRecord();
+};
+
+#endif // AUDIOEFFECTRECORD_H
diff --git a/servers/audio/effects/eq.cpp b/servers/audio/effects/eq.cpp
index 9ef41191f5..b15fc7ecf4 100644
--- a/servers/audio/effects/eq.cpp
+++ b/servers/audio/effects/eq.cpp
@@ -108,9 +108,9 @@ void EQ::recalculate_band_coefficients() {
ERR_CONTINUE(roots == 0);
- band[i].c1 = 2.0 * ((0.5 - r1) / 2.0);
- band[i].c2 = 2.0 * r1;
- band[i].c3 = 2.0 * (0.5 + r1) * cos(th);
+ band.write[i].c1 = 2.0 * ((0.5 - r1) / 2.0);
+ band.write[i].c2 = 2.0 * r1;
+ band.write[i].c3 = 2.0 * (0.5 + r1) * cos(th);
//printf("band %i, coefs = %f,%f,%f\n",i,(float)bands[i].c1,(float)bands[i].c2,(float)bands[i].c3);
}
}
@@ -180,7 +180,7 @@ void EQ::set_bands(const Vector<float> &p_bands) {
band.resize(p_bands.size());
for (int i = 0; i < p_bands.size(); i++) {
- band[i].freq = p_bands[i];
+ band.write[i].freq = p_bands[i];
}
recalculate_band_coefficients();
diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp
index ceb843c031..f3934e5c01 100644
--- a/servers/audio_server.cpp
+++ b/servers/audio_server.cpp
@@ -33,6 +33,7 @@
#include "os/file_access.h"
#include "os/os.h"
#include "project_settings.h"
+#include "scene/resources/audio_stream_sample.h"
#include "servers/audio/audio_driver_dummy.h"
#include "servers/audio/effects/audio_effect_compressor.h"
#ifdef TOOLS_ENABLED
@@ -79,6 +80,17 @@ double AudioDriver::get_mix_time() const {
return total;
}
+void AudioDriver::input_buffer_write(int32_t sample) {
+
+ input_buffer.write[input_position++] = sample;
+ if (input_position >= input_buffer.size()) {
+ input_position = 0;
+ }
+ if (input_size < input_buffer.size()) {
+ input_size++;
+ }
+}
+
AudioDriver::SpeakerMode AudioDriver::get_speaker_mode_by_total_channels(int p_channels) const {
switch (p_channels) {
case 4: return SPEAKER_SURROUND_31;
@@ -113,6 +125,14 @@ String AudioDriver::get_device() {
return "Default";
}
+Array AudioDriver::capture_get_device_list() {
+ Array list;
+
+ list.push_back("Default");
+
+ return list;
+}
+
AudioDriver::AudioDriver() {
_last_mix_time = 0;
@@ -123,14 +143,19 @@ AudioDriver::AudioDriver() {
#endif
}
-AudioDriver *AudioDriverManager::drivers[MAX_DRIVERS];
-int AudioDriverManager::driver_count = 0;
AudioDriverDummy AudioDriverManager::dummy_driver;
+AudioDriver *AudioDriverManager::drivers[MAX_DRIVERS] = {
+ &AudioDriverManager::dummy_driver,
+};
+int AudioDriverManager::driver_count = 1;
void AudioDriverManager::add_driver(AudioDriver *p_driver) {
ERR_FAIL_COND(driver_count >= MAX_DRIVERS);
- drivers[driver_count++] = p_driver;
+ drivers[driver_count - 1] = p_driver;
+
+ // Last driver is always our dummy driver
+ drivers[driver_count++] = &AudioDriverManager::dummy_driver;
}
int AudioDriverManager::get_driver_count() {
@@ -163,14 +188,6 @@ void AudioDriverManager::initialize(int p_driver) {
return;
}
}
-
- // Fallback to our dummy driver
- if (dummy_driver.init() == OK) {
- ERR_PRINT("AudioDriverManager: all drivers failed, falling back to dummy driver");
- dummy_driver.set_singleton();
- } else {
- ERR_PRINT("AudioDriverManager: dummy driver failed to init()");
- }
}
AudioDriver *AudioDriverManager::get_driver(int p_driver) {
@@ -264,7 +281,7 @@ void AudioServer::_mix_step() {
bus->index_cache = i; //might be moved around by editor, so..
for (int k = 0; k < bus->channels.size(); k++) {
- bus->channels[k].used = false;
+ bus->channels.write[k].used = false;
}
if (bus->solo) {
@@ -310,7 +327,7 @@ void AudioServer::_mix_step() {
if (bus->channels[k].active && !bus->channels[k].used) {
//buffer was not used, but it's still active, so it must be cleaned
- AudioFrame *buf = bus->channels[k].buffer.ptrw();
+ AudioFrame *buf = bus->channels.write[k].buffer.ptrw();
for (uint32_t j = 0; j < buffer_size; j++) {
@@ -332,21 +349,21 @@ void AudioServer::_mix_step() {
for (int k = 0; k < bus->channels.size(); k++) {
- if (!bus->channels[k].active)
+ if (!(bus->channels[k].active || bus->channels[k].effect_instances[j]->process_silence()))
continue;
- bus->channels[k].effect_instances[j]->process(bus->channels[k].buffer.ptr(), temp_buffer[k].ptrw(), buffer_size);
+ bus->channels.write[k].effect_instances.write[j]->process(bus->channels[k].buffer.ptr(), temp_buffer.write[k].ptrw(), buffer_size);
}
//swap buffers, so internal buffer always has the right data
for (int k = 0; k < bus->channels.size(); k++) {
- if (!buses[i]->channels[k].active)
+ if (!(buses[i]->channels[k].active || bus->channels[k].effect_instances[j]->process_silence()))
continue;
- SWAP(bus->channels[k].buffer, temp_buffer[k]);
+ SWAP(bus->channels.write[k].buffer, temp_buffer.write[k]);
}
#ifdef DEBUG_ENABLED
- bus->effects[j].prof_time += OS::get_singleton()->get_ticks_usec() - ticks;
+ bus->effects.write[j].prof_time += OS::get_singleton()->get_ticks_usec() - ticks;
#endif
}
}
@@ -372,7 +389,7 @@ void AudioServer::_mix_step() {
if (!bus->channels[k].active)
continue;
- AudioFrame *buf = bus->channels[k].buffer.ptrw();
+ AudioFrame *buf = bus->channels.write[k].buffer.ptrw();
AudioFrame peak = AudioFrame(0, 0);
@@ -403,15 +420,15 @@ void AudioServer::_mix_step() {
}
}
- bus->channels[k].peak_volume = AudioFrame(Math::linear2db(peak.l + 0.0000000001), Math::linear2db(peak.r + 0.0000000001));
+ bus->channels.write[k].peak_volume = AudioFrame(Math::linear2db(peak.l + 0.0000000001), Math::linear2db(peak.r + 0.0000000001));
if (!bus->channels[k].used) {
//see if any audio is contained, because channel was not used
if (MAX(peak.r, peak.l) > Math::db2linear(channel_disable_threshold_db)) {
- bus->channels[k].last_mix_with_audio = mix_frames;
+ bus->channels.write[k].last_mix_with_audio = mix_frames;
} else if (mix_frames - bus->channels[k].last_mix_with_audio > channel_disable_frames) {
- bus->channels[k].active = false;
+ bus->channels.write[k].active = false;
continue; //went inactive, don't mix.
}
}
@@ -436,12 +453,12 @@ AudioFrame *AudioServer::thread_get_channel_mix_buffer(int p_bus, int p_buffer)
ERR_FAIL_INDEX_V(p_bus, buses.size(), NULL);
ERR_FAIL_INDEX_V(p_buffer, buses[p_bus]->channels.size(), NULL);
- AudioFrame *data = buses[p_bus]->channels[p_buffer].buffer.ptrw();
+ AudioFrame *data = buses.write[p_bus]->channels.write[p_buffer].buffer.ptrw();
if (!buses[p_bus]->channels[p_buffer].used) {
- buses[p_bus]->channels[p_buffer].used = true;
- buses[p_bus]->channels[p_buffer].active = true;
- buses[p_bus]->channels[p_buffer].last_mix_with_audio = mix_frames;
+ buses.write[p_bus]->channels.write[p_buffer].used = true;
+ buses.write[p_bus]->channels.write[p_buffer].active = true;
+ buses.write[p_bus]->channels.write[p_buffer].last_mix_with_audio = mix_frames;
for (uint32_t i = 0; i < buffer_size; i++) {
data[i] = AudioFrame(0, 0);
}
@@ -506,10 +523,10 @@ void AudioServer::set_bus_count(int p_count) {
}
}
- buses[i] = memnew(Bus);
- buses[i]->channels.resize(channel_count);
+ buses.write[i] = memnew(Bus);
+ buses.write[i]->channels.resize(channel_count);
for (int j = 0; j < channel_count; j++) {
- buses[i]->channels[j].buffer.resize(buffer_size);
+ buses.write[i]->channels.write[j].buffer.resize(buffer_size);
}
buses[i]->name = attempt;
buses[i]->solo = false;
@@ -581,7 +598,7 @@ void AudioServer::add_bus(int p_at_pos) {
Bus *bus = memnew(Bus);
bus->channels.resize(channel_count);
for (int j = 0; j < channel_count; j++) {
- bus->channels[j].buffer.resize(buffer_size);
+ bus->channels.write[j].buffer.resize(buffer_size);
}
bus->name = attempt;
bus->solo = false;
@@ -764,13 +781,13 @@ bool AudioServer::is_bus_bypassing_effects(int p_bus) const {
void AudioServer::_update_bus_effects(int p_bus) {
for (int i = 0; i < buses[p_bus]->channels.size(); i++) {
- buses[p_bus]->channels[i].effect_instances.resize(buses[p_bus]->effects.size());
+ buses.write[p_bus]->channels.write[i].effect_instances.resize(buses[p_bus]->effects.size());
for (int j = 0; j < buses[p_bus]->effects.size(); j++) {
- Ref<AudioEffectInstance> fx = buses[p_bus]->effects[j].effect->instance();
+ Ref<AudioEffectInstance> fx = buses.write[p_bus]->effects.write[j].effect->instance();
if (Object::cast_to<AudioEffectCompressorInstance>(*fx)) {
Object::cast_to<AudioEffectCompressorInstance>(*fx)->set_current_channel(i);
}
- buses[p_bus]->channels[i].effect_instances[j] = fx;
+ buses.write[p_bus]->channels.write[i].effect_instances.write[j] = fx;
}
}
}
@@ -841,7 +858,7 @@ void AudioServer::swap_bus_effects(int p_bus, int p_effect, int p_by_effect) {
MARK_EDITED
lock();
- SWAP(buses[p_bus]->effects[p_effect], buses[p_bus]->effects[p_by_effect]);
+ SWAP(buses.write[p_bus]->effects.write[p_effect], buses.write[p_bus]->effects.write[p_by_effect]);
_update_bus_effects(p_bus);
unlock();
}
@@ -853,7 +870,7 @@ void AudioServer::set_bus_effect_enabled(int p_bus, int p_effect, bool p_enabled
MARK_EDITED
- buses[p_bus]->effects[p_effect].enabled = p_enabled;
+ buses.write[p_bus]->effects.write[p_effect].enabled = p_enabled;
}
bool AudioServer::is_bus_effect_enabled(int p_bus, int p_effect) const {
@@ -890,13 +907,13 @@ void AudioServer::init_channels_and_buffers() {
temp_buffer.resize(channel_count);
for (int i = 0; i < temp_buffer.size(); i++) {
- temp_buffer[i].resize(buffer_size);
+ temp_buffer.write[i].resize(buffer_size);
}
for (int i = 0; i < buses.size(); i++) {
buses[i]->channels.resize(channel_count);
for (int j = 0; j < channel_count; j++) {
- buses[i]->channels[j].buffer.resize(buffer_size);
+ buses.write[i]->channels.write[j].buffer.resize(buffer_size);
}
}
}
@@ -976,7 +993,7 @@ void AudioServer::update() {
if (!bus->effects[j].enabled)
continue;
- bus->effects[j].prof_time = 0;
+ bus->effects.write[j].prof_time = 0;
}
}
@@ -1146,11 +1163,11 @@ void AudioServer::set_bus_layout(const Ref<AudioBusLayout> &p_bus_layout) {
}
bus_map[bus->name] = bus;
- buses[i] = bus;
+ buses.write[i] = bus;
buses[i]->channels.resize(channel_count);
for (int j = 0; j < channel_count; j++) {
- buses[i]->channels[j].buffer.resize(buffer_size);
+ buses.write[i]->channels.write[j].buffer.resize(buffer_size);
}
_update_bus_effects(i);
}
@@ -1169,17 +1186,17 @@ Ref<AudioBusLayout> AudioServer::generate_bus_layout() const {
for (int i = 0; i < buses.size(); i++) {
- state->buses[i].name = buses[i]->name;
- state->buses[i].send = buses[i]->send;
- state->buses[i].mute = buses[i]->mute;
- state->buses[i].solo = buses[i]->solo;
- state->buses[i].bypass = buses[i]->bypass;
- state->buses[i].volume_db = buses[i]->volume_db;
+ state->buses.write[i].name = buses[i]->name;
+ state->buses.write[i].send = buses[i]->send;
+ state->buses.write[i].mute = buses[i]->mute;
+ state->buses.write[i].solo = buses[i]->solo;
+ state->buses.write[i].bypass = buses[i]->bypass;
+ state->buses.write[i].volume_db = buses[i]->volume_db;
for (int j = 0; j < buses[i]->effects.size(); j++) {
AudioBusLayout::Bus::Effect fx;
fx.effect = buses[i]->effects[j].effect;
fx.enabled = buses[i]->effects[j].enabled;
- state->buses[i].effects.push_back(fx);
+ state->buses.write[i].effects.push_back(fx);
}
}
@@ -1201,6 +1218,21 @@ void AudioServer::set_device(String device) {
AudioDriver::get_singleton()->set_device(device);
}
+Array AudioServer::capture_get_device_list() {
+
+ return AudioDriver::get_singleton()->capture_get_device_list();
+}
+
+String AudioServer::capture_get_device() {
+
+ return AudioDriver::get_singleton()->capture_get_device();
+}
+
+void AudioServer::capture_set_device(const String &p_name) {
+
+ AudioDriver::get_singleton()->capture_set_device(p_name);
+}
+
void AudioServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_bus_count", "amount"), &AudioServer::set_bus_count);
@@ -1251,6 +1283,10 @@ void AudioServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_device"), &AudioServer::get_device);
ClassDB::bind_method(D_METHOD("set_device"), &AudioServer::set_device);
+ ClassDB::bind_method(D_METHOD("capture_get_device_list"), &AudioServer::capture_get_device_list);
+ ClassDB::bind_method(D_METHOD("capture_get_device"), &AudioServer::capture_get_device);
+ ClassDB::bind_method(D_METHOD("capture_set_device"), &AudioServer::capture_set_device);
+
ClassDB::bind_method(D_METHOD("set_bus_layout", "bus_layout"), &AudioServer::set_bus_layout);
ClassDB::bind_method(D_METHOD("generate_bus_layout"), &AudioServer::generate_bus_layout);
@@ -1294,7 +1330,7 @@ bool AudioBusLayout::_set(const StringName &p_name, const Variant &p_value) {
buses.resize(index + 1);
}
- Bus &bus = buses[index];
+ Bus &bus = buses.write[index];
String what = s.get_slice("/", 2);
@@ -1316,7 +1352,7 @@ bool AudioBusLayout::_set(const StringName &p_name, const Variant &p_value) {
bus.effects.resize(which + 1);
}
- Bus::Effect &fx = bus.effects[which];
+ Bus::Effect &fx = bus.effects.write[which];
String fxwhat = s.get_slice("/", 4);
if (fxwhat == "effect") {
@@ -1410,5 +1446,5 @@ void AudioBusLayout::_get_property_list(List<PropertyInfo> *p_list) const {
AudioBusLayout::AudioBusLayout() {
buses.resize(1);
- buses[0].name = "Master";
+ buses.write[0].name = "Master";
}
diff --git a/servers/audio_server.h b/servers/audio_server.h
index 258fd1d9b0..2663a0f968 100644
--- a/servers/audio_server.h
+++ b/servers/audio_server.h
@@ -38,6 +38,8 @@
#include "variant.h"
class AudioDriverDummy;
+class AudioStream;
+class AudioStreamSample;
class AudioDriver {
@@ -51,8 +53,13 @@ class AudioDriver {
#endif
protected:
+ Vector<int32_t> input_buffer;
+ unsigned int input_position;
+ unsigned int input_size;
+
void audio_server_process(int p_frames, int32_t *p_buffer, bool p_update_mix_time = true);
void update_mix_time(int p_frames);
+ void input_buffer_write(int32_t sample);
#ifdef DEBUG_ENABLED
_FORCE_INLINE_ void start_counting_ticks() { prof_ticks = OS::get_singleton()->get_ticks_usec(); }
@@ -91,11 +98,21 @@ public:
virtual void unlock() = 0;
virtual void finish() = 0;
+ virtual Error capture_start() { return FAILED; }
+ virtual Error capture_stop() { return FAILED; }
+ virtual void capture_set_device(const String &p_name) {}
+ virtual String capture_get_device() { return "Default"; }
+ virtual Array capture_get_device_list(); // TODO: convert this and get_device_list to PoolStringArray
+
virtual float get_latency() { return 0; }
SpeakerMode get_speaker_mode_by_total_channels(int p_channels) const;
int get_total_channels_by_speaker_mode(SpeakerMode) const;
+ Vector<int32_t> get_input_buffer() { return input_buffer; }
+ unsigned int get_input_position() { return input_position; }
+ unsigned int get_input_size() { return input_size; }
+
#ifdef DEBUG_ENABLED
uint64_t get_profiling_time() const { return prof_time; }
void reset_profiling_time() { prof_time = 0; }
@@ -222,6 +239,18 @@ private:
void _mix_step();
+#if 0
+ struct AudioInBlock {
+
+ Ref<AudioStreamSample> audio_stream;
+ int current_position;
+ bool loops;
+ };
+
+ Map<StringName, AudioInBlock *> audio_in_block_map;
+ Vector<AudioInBlock *> audio_in_blocks;
+#endif
+
struct CallbackItem {
AudioCallback callback;
@@ -335,8 +364,11 @@ public:
String get_device();
void set_device(String device);
- float get_output_latency() { return output_latency; }
+ Array capture_get_device_list();
+ String capture_get_device();
+ void capture_set_device(const String &p_name);
+ float get_output_latency() { return output_latency; }
AudioServer();
virtual ~AudioServer();
};
diff --git a/servers/physics/body_pair_sw.cpp b/servers/physics/body_pair_sw.cpp
index 5a41b621eb..0ce38e4486 100644
--- a/servers/physics/body_pair_sw.cpp
+++ b/servers/physics/body_pair_sw.cpp
@@ -212,41 +212,11 @@ bool BodyPairSW::_test_ccd(real_t p_step, BodySW *p_A, int p_shape_A, const Tran
}
real_t combine_bounce(BodySW *A, BodySW *B) {
- const PhysicsServer::CombineMode cm = A->get_bounce_combine_mode();
-
- switch (cm) {
- case PhysicsServer::COMBINE_MODE_INHERIT:
- if (B->get_bounce_combine_mode() != PhysicsServer::COMBINE_MODE_INHERIT)
- return combine_bounce(B, A);
- // else use MAX [This is used when the two bodies doesn't use physical material]
- case PhysicsServer::COMBINE_MODE_MAX:
- return MAX(A->get_bounce(), B->get_bounce());
- case PhysicsServer::COMBINE_MODE_MIN:
- return MIN(A->get_bounce(), B->get_bounce());
- case PhysicsServer::COMBINE_MODE_MULTIPLY:
- return A->get_bounce() * B->get_bounce();
- default: // Is always PhysicsServer::COMBINE_MODE_AVERAGE:
- return (A->get_bounce() + B->get_bounce()) / 2;
- }
+ return CLAMP(A->get_bounce() + B->get_bounce(), 0, 1);
}
real_t combine_friction(BodySW *A, BodySW *B) {
- const PhysicsServer::CombineMode cm = A->get_friction_combine_mode();
-
- switch (cm) {
- case PhysicsServer::COMBINE_MODE_INHERIT:
- if (B->get_friction_combine_mode() != PhysicsServer::COMBINE_MODE_INHERIT)
- return combine_friction(B, A);
- // else use Multiply [This is used when the two bodies doesn't use physical material]
- case PhysicsServer::COMBINE_MODE_MULTIPLY:
- return A->get_friction() * B->get_friction();
- case PhysicsServer::COMBINE_MODE_MAX:
- return MAX(A->get_friction(), B->get_friction());
- case PhysicsServer::COMBINE_MODE_MIN:
- return MIN(A->get_friction(), B->get_friction());
- default: // Is always PhysicsServer::COMBINE_MODE_AVERAGE:
- return (A->get_friction() + B->get_friction()) / 2;
- }
+ return ABS(MIN(A->get_friction(), B->get_friction()));
}
bool BodyPairSW::setup(real_t p_step) {
diff --git a/servers/physics/body_sw.cpp b/servers/physics/body_sw.cpp
index 59f987fc17..cc9681193c 100644
--- a/servers/physics/body_sw.cpp
+++ b/servers/physics/body_sw.cpp
@@ -423,22 +423,6 @@ void BodySW::_compute_area_gravity_and_dampenings(const AreaSW *p_area) {
area_angular_damp += p_area->get_angular_damp();
}
-void BodySW::set_combine_mode(PhysicsServer::BodyParameter p_param, PhysicsServer::CombineMode p_mode) {
- if (p_param == PhysicsServer::BODY_PARAM_BOUNCE) {
- bounce_combine_mode = p_mode;
- } else {
- friction_combine_mode = p_mode;
- }
-}
-
-PhysicsServer::CombineMode BodySW::get_combine_mode(PhysicsServer::BodyParameter p_param) const {
- if (p_param == PhysicsServer::BODY_PARAM_BOUNCE) {
- return bounce_combine_mode;
- } else {
- return friction_combine_mode;
- }
-}
-
void BodySW::set_axis_lock(PhysicsServer::BodyAxis p_axis, bool lock) {
if (lock) {
locked_axis |= p_axis;
diff --git a/servers/physics/body_sw.h b/servers/physics/body_sw.h
index 2f77196f58..9d7b147fd6 100644
--- a/servers/physics/body_sw.h
+++ b/servers/physics/body_sw.h
@@ -49,8 +49,6 @@ class BodySW : public CollisionObjectSW {
real_t mass;
real_t bounce;
real_t friction;
- PhysicsServer::CombineMode bounce_combine_mode;
- PhysicsServer::CombineMode friction_combine_mode;
real_t linear_damp;
real_t angular_damp;
@@ -159,7 +157,7 @@ public:
_FORCE_INLINE_ void add_area(AreaSW *p_area) {
int index = areas.find(AreaCMP(p_area));
if (index > -1) {
- areas[index].refCount += 1;
+ areas.write[index].refCount += 1;
} else {
areas.ordered_insert(AreaCMP(p_area));
}
@@ -168,7 +166,7 @@ public:
_FORCE_INLINE_ void remove_area(AreaSW *p_area) {
int index = areas.find(AreaCMP(p_area));
if (index > -1) {
- areas[index].refCount -= 1;
+ areas.write[index].refCount -= 1;
if (areas[index].refCount < 1)
areas.remove(index);
}
@@ -304,12 +302,6 @@ public:
_FORCE_INLINE_ Vector3 get_gravity() const { return gravity; }
_FORCE_INLINE_ real_t get_bounce() const { return bounce; }
- void set_combine_mode(PhysicsServer::BodyParameter p_param, PhysicsServer::CombineMode p_mode);
- PhysicsServer::CombineMode get_combine_mode(PhysicsServer::BodyParameter p_param) const;
-
- _FORCE_INLINE_ PhysicsServer::CombineMode get_bounce_combine_mode() const { return bounce_combine_mode; }
- _FORCE_INLINE_ PhysicsServer::CombineMode get_friction_combine_mode() const { return friction_combine_mode; }
-
void set_axis_lock(PhysicsServer::BodyAxis p_axis, bool lock);
bool is_axis_locked(PhysicsServer::BodyAxis p_axis) const;
@@ -356,7 +348,7 @@ void BodySW::add_contact(const Vector3 &p_local_pos, const Vector3 &p_local_norm
if (c_max == 0)
return;
- Contact *c = &contacts[0];
+ Contact *c = contacts.ptrw();
int idx = -1;
@@ -442,6 +434,9 @@ public:
ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector3());
return body->contacts[p_contact_idx].local_normal;
}
+ virtual float get_contact_impulse(int p_contact_idx) const {
+ return 0.0f; // Only implemented for bullet
+ }
virtual int get_contact_local_shape(int p_contact_idx) const {
ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, -1);
return body->contacts[p_contact_idx].local_shape;
diff --git a/servers/physics/collision_object_sw.cpp b/servers/physics/collision_object_sw.cpp
index f7a58a9cf2..09f72ff39b 100644
--- a/servers/physics/collision_object_sw.cpp
+++ b/servers/physics/collision_object_sw.cpp
@@ -53,7 +53,7 @@ void CollisionObjectSW::set_shape(int p_index, ShapeSW *p_shape) {
ERR_FAIL_INDEX(p_index, shapes.size());
shapes[p_index].shape->remove_owner(this);
- shapes[p_index].shape = p_shape;
+ shapes.write[p_index].shape = p_shape;
p_shape->add_owner(this);
if (!pending_shape_update_list.in_list()) {
@@ -66,8 +66,8 @@ void CollisionObjectSW::set_shape_transform(int p_index, const Transform &p_tran
ERR_FAIL_INDEX(p_index, shapes.size());
- shapes[p_index].xform = p_transform;
- shapes[p_index].xform_inv = p_transform.affine_inverse();
+ shapes.write[p_index].xform = p_transform;
+ shapes.write[p_index].xform_inv = p_transform.affine_inverse();
if (!pending_shape_update_list.in_list()) {
PhysicsServerSW::singleton->pending_shape_update_list.add(&pending_shape_update_list);
}
@@ -97,7 +97,7 @@ void CollisionObjectSW::remove_shape(int p_index) {
continue;
//should never get here with a null owner
space->get_broadphase()->remove(shapes[i].bpid);
- shapes[i].bpid = 0;
+ shapes.write[i].bpid = 0;
}
shapes[p_index].shape->remove_owner(this);
shapes.remove(p_index);
@@ -117,7 +117,7 @@ void CollisionObjectSW::_set_static(bool p_static) {
if (!space)
return;
for (int i = 0; i < get_shape_count(); i++) {
- Shape &s = shapes[i];
+ const Shape &s = shapes[i];
if (s.bpid > 0) {
space->get_broadphase()->set_static(s.bpid, _static);
}
@@ -128,7 +128,7 @@ void CollisionObjectSW::_unregister_shapes() {
for (int i = 0; i < shapes.size(); i++) {
- Shape &s = shapes[i];
+ Shape &s = shapes.write[i];
if (s.bpid > 0) {
space->get_broadphase()->remove(s.bpid);
s.bpid = 0;
@@ -143,7 +143,7 @@ void CollisionObjectSW::_update_shapes() {
for (int i = 0; i < shapes.size(); i++) {
- Shape &s = shapes[i];
+ Shape &s = shapes.write[i];
if (s.bpid == 0) {
s.bpid = space->get_broadphase()->create(this, i);
space->get_broadphase()->set_static(s.bpid, _static);
@@ -170,7 +170,7 @@ void CollisionObjectSW::_update_shapes_with_motion(const Vector3 &p_motion) {
for (int i = 0; i < shapes.size(); i++) {
- Shape &s = shapes[i];
+ Shape &s = shapes.write[i];
if (s.bpid == 0) {
s.bpid = space->get_broadphase()->create(this, i);
space->get_broadphase()->set_static(s.bpid, _static);
@@ -195,7 +195,7 @@ void CollisionObjectSW::_set_space(SpaceSW *p_space) {
for (int i = 0; i < shapes.size(); i++) {
- Shape &s = shapes[i];
+ Shape &s = shapes.write[i];
if (s.bpid) {
space->get_broadphase()->remove(s.bpid);
s.bpid = 0;
diff --git a/servers/physics/collision_object_sw.h b/servers/physics/collision_object_sw.h
index dee28bb6df..b6430b38dc 100644
--- a/servers/physics/collision_object_sw.h
+++ b/servers/physics/collision_object_sw.h
@@ -135,7 +135,7 @@ public:
_FORCE_INLINE_ void set_ray_pickable(bool p_enable) { ray_pickable = p_enable; }
_FORCE_INLINE_ bool is_ray_pickable() const { return ray_pickable; }
- _FORCE_INLINE_ void set_shape_as_disabled(int p_idx, bool p_enable) { shapes[p_idx].disabled = p_enable; }
+ _FORCE_INLINE_ void set_shape_as_disabled(int p_idx, bool p_enable) { shapes.write[p_idx].disabled = p_enable; }
_FORCE_INLINE_ bool is_shape_set_as_disabled(int p_idx) const { return shapes[p_idx].disabled; }
_FORCE_INLINE_ void set_collision_layer(uint32_t p_layer) { collision_layer = p_layer; }
diff --git a/servers/physics/collision_solver_sat.cpp b/servers/physics/collision_solver_sat.cpp
index 44b7c9ac34..b059c20c95 100644
--- a/servers/physics/collision_solver_sat.cpp
+++ b/servers/physics/collision_solver_sat.cpp
@@ -348,7 +348,9 @@ public:
//use the smallest depth
- min_B = -min_B;
+ if (min_B < 0.0) { // could be +0.0, we don't want it to become -0.0
+ min_B = -min_B;
+ }
if (max_B < min_B) {
if (max_B < best_depth) {
@@ -558,6 +560,12 @@ static void _collision_sphere_capsule(const ShapeSW *p_a, const Transform &p_tra
}
template <bool withMargin>
+static void _collision_sphere_cylinder(const ShapeSW *p_a, const Transform &p_transform_a, const ShapeSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+
+ return;
+}
+
+template <bool withMargin>
static void _collision_sphere_convex_polygon(const ShapeSW *p_a, const Transform &p_transform_a, const ShapeSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
const SphereShapeSW *sphere_A = static_cast<const SphereShapeSW *>(p_a);
@@ -849,6 +857,12 @@ static void _collision_box_capsule(const ShapeSW *p_a, const Transform &p_transf
}
template <bool withMargin>
+static void _collision_box_cylinder(const ShapeSW *p_a, const Transform &p_transform_a, const ShapeSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+
+ return;
+}
+
+template <bool withMargin>
static void _collision_box_convex_polygon(const ShapeSW *p_a, const Transform &p_transform_a, const ShapeSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
const BoxShapeSW *box_A = static_cast<const BoxShapeSW *>(p_a);
@@ -1125,6 +1139,12 @@ static void _collision_capsule_capsule(const ShapeSW *p_a, const Transform &p_tr
}
template <bool withMargin>
+static void _collision_capsule_cylinder(const ShapeSW *p_a, const Transform &p_transform_a, const ShapeSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+
+ return;
+}
+
+template <bool withMargin>
static void _collision_capsule_convex_polygon(const ShapeSW *p_a, const Transform &p_transform_a, const ShapeSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
const CapsuleShapeSW *capsule_A = static_cast<const CapsuleShapeSW *>(p_a);
@@ -1245,6 +1265,24 @@ static void _collision_capsule_face(const ShapeSW *p_a, const Transform &p_trans
}
template <bool withMargin>
+static void _collision_cylinder_cylinder(const ShapeSW *p_a, const Transform &p_transform_a, const ShapeSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+
+ return;
+}
+
+template <bool withMargin>
+static void _collision_cylinder_convex_polygon(const ShapeSW *p_a, const Transform &p_transform_a, const ShapeSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+
+ return;
+}
+
+template <bool withMargin>
+static void _collision_cylinder_face(const ShapeSW *p_a, const Transform &p_transform_a, const ShapeSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+
+ return;
+}
+
+template <bool withMargin>
static void _collision_convex_polygon_convex_polygon(const ShapeSW *p_a, const Transform &p_transform_a, const ShapeSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
const ConvexPolygonShapeSW *convex_polygon_A = static_cast<const ConvexPolygonShapeSW *>(p_a);
@@ -1473,59 +1511,81 @@ bool sat_calculate_penetration(const ShapeSW *p_shape_A, const Transform &p_tran
ERR_FAIL_COND_V(type_B == PhysicsServer::SHAPE_RAY, false);
ERR_FAIL_COND_V(p_shape_B->is_concave(), false);
- static const CollisionFunc collision_table[5][5] = {
+ static const CollisionFunc collision_table[6][6] = {
{ _collision_sphere_sphere<false>,
_collision_sphere_box<false>,
_collision_sphere_capsule<false>,
+ _collision_sphere_cylinder<false>,
_collision_sphere_convex_polygon<false>,
_collision_sphere_face<false> },
{ 0,
_collision_box_box<false>,
_collision_box_capsule<false>,
+ _collision_box_cylinder<false>,
_collision_box_convex_polygon<false>,
_collision_box_face<false> },
{ 0,
0,
_collision_capsule_capsule<false>,
+ _collision_capsule_cylinder<false>,
_collision_capsule_convex_polygon<false>,
_collision_capsule_face<false> },
{ 0,
0,
0,
+ _collision_cylinder_cylinder<false>,
+ _collision_cylinder_convex_polygon<false>,
+ _collision_cylinder_face<false> },
+ { 0,
+ 0,
+ 0,
+ 0,
_collision_convex_polygon_convex_polygon<false>,
_collision_convex_polygon_face<false> },
{ 0,
0,
0,
0,
+ 0,
0 },
};
- static const CollisionFunc collision_table_margin[5][5] = {
+ static const CollisionFunc collision_table_margin[6][6] = {
{ _collision_sphere_sphere<true>,
_collision_sphere_box<true>,
_collision_sphere_capsule<true>,
+ _collision_sphere_cylinder<true>,
_collision_sphere_convex_polygon<true>,
_collision_sphere_face<true> },
{ 0,
_collision_box_box<true>,
_collision_box_capsule<true>,
+ _collision_box_cylinder<true>,
_collision_box_convex_polygon<true>,
_collision_box_face<true> },
{ 0,
0,
_collision_capsule_capsule<true>,
+ _collision_capsule_cylinder<true>,
_collision_capsule_convex_polygon<true>,
_collision_capsule_face<true> },
{ 0,
0,
0,
+ _collision_cylinder_cylinder<true>,
+ _collision_cylinder_convex_polygon<true>,
+ _collision_cylinder_face<true> },
+ { 0,
+ 0,
+ 0,
+ 0,
_collision_convex_polygon_convex_polygon<true>,
_collision_convex_polygon_face<true> },
{ 0,
0,
0,
0,
+ 0,
0 },
};
diff --git a/servers/physics/physics_server_sw.cpp b/servers/physics/physics_server_sw.cpp
index a06942cb2a..3a32c46a9b 100644
--- a/servers/physics/physics_server_sw.cpp
+++ b/servers/physics/physics_server_sw.cpp
@@ -701,20 +701,6 @@ real_t PhysicsServerSW::body_get_param(RID p_body, BodyParameter p_param) const
return body->get_param(p_param);
};
-void PhysicsServerSW::body_set_combine_mode(RID p_body, BodyParameter p_param, CombineMode p_mode) {
- BodySW *body = body_owner.get(p_body);
- ERR_FAIL_COND(!body);
-
- body->set_combine_mode(p_param, p_mode);
-}
-
-PhysicsServer::CombineMode PhysicsServerSW::body_get_combine_mode(RID p_body, BodyParameter p_param) const {
- BodySW *body = body_owner.get(p_body);
- ERR_FAIL_COND_V(!body, COMBINE_MODE_INHERIT);
-
- return body->get_combine_mode(p_param);
-}
-
void PhysicsServerSW::body_set_kinematic_safe_margin(RID p_body, real_t p_margin) {
BodySW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
diff --git a/servers/physics/physics_server_sw.h b/servers/physics/physics_server_sw.h
index 57037fb325..1c5754124d 100644
--- a/servers/physics/physics_server_sw.h
+++ b/servers/physics/physics_server_sw.h
@@ -188,10 +188,6 @@ public:
virtual void body_set_param(RID p_body, BodyParameter p_param, real_t p_value);
virtual real_t body_get_param(RID p_body, BodyParameter p_param) const;
- /// p_param accept only Bounce and Friction
- virtual void body_set_combine_mode(RID p_body, BodyParameter p_param, CombineMode p_mode);
- virtual CombineMode body_get_combine_mode(RID p_body, BodyParameter p_param) const;
-
virtual void body_set_kinematic_safe_margin(RID p_body, real_t p_margin);
virtual real_t body_get_kinematic_safe_margin(RID p_body) const;
diff --git a/servers/physics/space_sw.h b/servers/physics/space_sw.h
index 2452d6a187..4d864e9a51 100644
--- a/servers/physics/space_sw.h
+++ b/servers/physics/space_sw.h
@@ -186,7 +186,7 @@ public:
void set_debug_contacts(int p_amount) { contact_debug.resize(p_amount); }
_FORCE_INLINE_ bool is_debugging_contacts() const { return !contact_debug.empty(); }
_FORCE_INLINE_ void add_debug_contact(const Vector3 &p_contact) {
- if (contact_debug_count < contact_debug.size()) contact_debug[contact_debug_count++] = p_contact;
+ if (contact_debug_count < contact_debug.size()) contact_debug.write[contact_debug_count++] = p_contact;
}
_FORCE_INLINE_ Vector<Vector3> get_debug_contacts() { return contact_debug; }
_FORCE_INLINE_ int get_debug_contact_count() { return contact_debug_count; }
diff --git a/servers/physics_2d/body_2d_sw.cpp b/servers/physics_2d/body_2d_sw.cpp
index fcd2a65ee7..aa063d6c1e 100644
--- a/servers/physics_2d/body_2d_sw.cpp
+++ b/servers/physics_2d/body_2d_sw.cpp
@@ -405,22 +405,6 @@ void Body2DSW::_compute_area_gravity_and_dampenings(const Area2DSW *p_area) {
area_angular_damp += p_area->get_angular_damp();
}
-void Body2DSW::set_combine_mode(Physics2DServer::BodyParameter p_param, Physics2DServer::CombineMode p_mode) {
- if (p_param == Physics2DServer::BODY_PARAM_BOUNCE) {
- bounce_combine_mode = p_mode;
- } else {
- friction_combine_mode = p_mode;
- }
-}
-
-Physics2DServer::CombineMode Body2DSW::get_combine_mode(Physics2DServer::BodyParameter p_param) const {
- if (p_param == Physics2DServer::BODY_PARAM_BOUNCE) {
- return bounce_combine_mode;
- } else {
- return friction_combine_mode;
- }
-}
-
void Body2DSW::integrate_forces(real_t p_step) {
if (mode == Physics2DServer::BODY_MODE_STATIC)
diff --git a/servers/physics_2d/body_2d_sw.h b/servers/physics_2d/body_2d_sw.h
index 7fe805b1f9..69184ad484 100644
--- a/servers/physics_2d/body_2d_sw.h
+++ b/servers/physics_2d/body_2d_sw.h
@@ -54,8 +54,6 @@ class Body2DSW : public CollisionObject2DSW {
real_t mass;
real_t bounce;
real_t friction;
- Physics2DServer::CombineMode bounce_combine_mode;
- Physics2DServer::CombineMode friction_combine_mode;
real_t _inv_mass;
real_t _inv_inertia;
@@ -141,7 +139,7 @@ public:
_FORCE_INLINE_ void add_area(Area2DSW *p_area) {
int index = areas.find(AreaCMP(p_area));
if (index > -1) {
- areas[index].refCount += 1;
+ areas.write[index].refCount += 1;
} else {
areas.ordered_insert(AreaCMP(p_area));
}
@@ -150,7 +148,7 @@ public:
_FORCE_INLINE_ void remove_area(Area2DSW *p_area) {
int index = areas.find(AreaCMP(p_area));
if (index > -1) {
- areas[index].refCount -= 1;
+ areas.write[index].refCount -= 1;
if (areas[index].refCount < 1)
areas.remove(index);
}
@@ -274,12 +272,6 @@ public:
_FORCE_INLINE_ real_t get_linear_damp() const { return linear_damp; }
_FORCE_INLINE_ real_t get_angular_damp() const { return angular_damp; }
- void set_combine_mode(Physics2DServer::BodyParameter p_param, Physics2DServer::CombineMode p_mode);
- Physics2DServer::CombineMode get_combine_mode(Physics2DServer::BodyParameter p_param) const;
-
- _FORCE_INLINE_ Physics2DServer::CombineMode get_bounce_combine_mode() const { return bounce_combine_mode; }
- _FORCE_INLINE_ Physics2DServer::CombineMode get_friction_combine_mode() const { return friction_combine_mode; }
-
void integrate_forces(real_t p_step);
void integrate_velocities(real_t p_step);
@@ -311,7 +303,7 @@ void Body2DSW::add_contact(const Vector2 &p_local_pos, const Vector2 &p_local_no
if (c_max == 0)
return;
- Contact *c = &contacts[0];
+ Contact *c = contacts.ptrw();
int idx = -1;
diff --git a/servers/physics_2d/body_pair_2d_sw.cpp b/servers/physics_2d/body_pair_2d_sw.cpp
index be8dcf6fa8..2633edf7bb 100644
--- a/servers/physics_2d/body_pair_2d_sw.cpp
+++ b/servers/physics_2d/body_pair_2d_sw.cpp
@@ -220,41 +220,11 @@ bool BodyPair2DSW::_test_ccd(real_t p_step, Body2DSW *p_A, int p_shape_A, const
}
real_t combine_bounce(Body2DSW *A, Body2DSW *B) {
- const Physics2DServer::CombineMode cm = A->get_bounce_combine_mode();
-
- switch (cm) {
- case Physics2DServer::COMBINE_MODE_INHERIT:
- if (B->get_bounce_combine_mode() != Physics2DServer::COMBINE_MODE_INHERIT)
- return combine_bounce(B, A);
- // else use MAX [This is used when the two bodies doesn't use physical material]
- case Physics2DServer::COMBINE_MODE_MAX:
- return MAX(A->get_bounce(), B->get_bounce());
- case Physics2DServer::COMBINE_MODE_MIN:
- return MIN(A->get_bounce(), B->get_bounce());
- case Physics2DServer::COMBINE_MODE_MULTIPLY:
- return A->get_bounce() * B->get_bounce();
- default: // Is always Physics2DServer::COMBINE_MODE_AVERAGE:
- return (A->get_bounce() + B->get_bounce()) / 2;
- }
+ return CLAMP(A->get_bounce() + B->get_bounce(), 0, 1);
}
real_t combine_friction(Body2DSW *A, Body2DSW *B) {
- const Physics2DServer::CombineMode cm = A->get_friction_combine_mode();
-
- switch (cm) {
- case Physics2DServer::COMBINE_MODE_INHERIT:
- if (B->get_friction_combine_mode() != Physics2DServer::COMBINE_MODE_INHERIT)
- return combine_friction(B, A);
- // else use Multiply [This is used when the two bodies doesn't use physical material]
- case Physics2DServer::COMBINE_MODE_MULTIPLY:
- return A->get_friction() * B->get_friction();
- case Physics2DServer::COMBINE_MODE_MAX:
- return MAX(A->get_friction(), B->get_friction());
- case Physics2DServer::COMBINE_MODE_MIN:
- return MIN(A->get_friction(), B->get_friction());
- default: // Is always Physics2DServer::COMBINE_MODE_AVERAGE:
- return (A->get_friction() + B->get_friction()) / 2;
- }
+ return ABS(MIN(A->get_friction(), B->get_friction()));
}
bool BodyPair2DSW::setup(real_t p_step) {
diff --git a/servers/physics_2d/collision_object_2d_sw.cpp b/servers/physics_2d/collision_object_2d_sw.cpp
index 23084a4241..4dd5b2040f 100644
--- a/servers/physics_2d/collision_object_2d_sw.cpp
+++ b/servers/physics_2d/collision_object_2d_sw.cpp
@@ -50,7 +50,7 @@ void CollisionObject2DSW::set_shape(int p_index, Shape2DSW *p_shape) {
ERR_FAIL_INDEX(p_index, shapes.size());
shapes[p_index].shape->remove_owner(this);
- shapes[p_index].shape = p_shape;
+ shapes.write[p_index].shape = p_shape;
p_shape->add_owner(this);
_update_shapes();
@@ -60,15 +60,15 @@ void CollisionObject2DSW::set_shape(int p_index, Shape2DSW *p_shape) {
void CollisionObject2DSW::set_shape_metadata(int p_index, const Variant &p_metadata) {
ERR_FAIL_INDEX(p_index, shapes.size());
- shapes[p_index].metadata = p_metadata;
+ shapes.write[p_index].metadata = p_metadata;
}
void CollisionObject2DSW::set_shape_transform(int p_index, const Transform2D &p_transform) {
ERR_FAIL_INDEX(p_index, shapes.size());
- shapes[p_index].xform = p_transform;
- shapes[p_index].xform_inv = p_transform.affine_inverse();
+ shapes.write[p_index].xform = p_transform;
+ shapes.write[p_index].xform_inv = p_transform.affine_inverse();
_update_shapes();
_shapes_changed();
}
@@ -76,7 +76,7 @@ void CollisionObject2DSW::set_shape_transform(int p_index, const Transform2D &p_
void CollisionObject2DSW::set_shape_as_disabled(int p_idx, bool p_disabled) {
ERR_FAIL_INDEX(p_idx, shapes.size());
- CollisionObject2DSW::Shape &shape = shapes[p_idx];
+ CollisionObject2DSW::Shape &shape = shapes.write[p_idx];
if (shape.disabled == p_disabled)
return;
@@ -116,7 +116,7 @@ void CollisionObject2DSW::remove_shape(int p_index) {
continue;
//should never get here with a null owner
space->get_broadphase()->remove(shapes[i].bpid);
- shapes[i].bpid = 0;
+ shapes.write[i].bpid = 0;
}
shapes[p_index].shape->remove_owner(this);
shapes.remove(p_index);
@@ -133,7 +133,7 @@ void CollisionObject2DSW::_set_static(bool p_static) {
if (!space)
return;
for (int i = 0; i < get_shape_count(); i++) {
- Shape &s = shapes[i];
+ const Shape &s = shapes[i];
if (s.bpid > 0) {
space->get_broadphase()->set_static(s.bpid, _static);
}
@@ -144,7 +144,7 @@ void CollisionObject2DSW::_unregister_shapes() {
for (int i = 0; i < shapes.size(); i++) {
- Shape &s = shapes[i];
+ Shape &s = shapes.write[i];
if (s.bpid > 0) {
space->get_broadphase()->remove(s.bpid);
s.bpid = 0;
@@ -159,7 +159,7 @@ void CollisionObject2DSW::_update_shapes() {
for (int i = 0; i < shapes.size(); i++) {
- Shape &s = shapes[i];
+ Shape &s = shapes.write[i];
if (s.disabled)
continue;
@@ -187,7 +187,7 @@ void CollisionObject2DSW::_update_shapes_with_motion(const Vector2 &p_motion) {
for (int i = 0; i < shapes.size(); i++) {
- Shape &s = shapes[i];
+ Shape &s = shapes.write[i];
if (s.disabled)
continue;
@@ -215,7 +215,7 @@ void CollisionObject2DSW::_set_space(Space2DSW *p_space) {
for (int i = 0; i < shapes.size(); i++) {
- Shape &s = shapes[i];
+ Shape &s = shapes.write[i];
if (s.bpid) {
space->get_broadphase()->remove(s.bpid);
s.bpid = 0;
diff --git a/servers/physics_2d/collision_object_2d_sw.h b/servers/physics_2d/collision_object_2d_sw.h
index ab3e219ac0..393c4a6ed7 100644
--- a/servers/physics_2d/collision_object_2d_sw.h
+++ b/servers/physics_2d/collision_object_2d_sw.h
@@ -144,7 +144,7 @@ public:
_FORCE_INLINE_ void set_shape_as_one_way_collision(int p_idx, bool p_one_way_collision) {
ERR_FAIL_INDEX(p_idx, shapes.size());
- shapes[p_idx].one_way_collision = p_one_way_collision;
+ shapes.write[p_idx].one_way_collision = p_one_way_collision;
}
_FORCE_INLINE_ bool is_shape_set_as_one_way_collision(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, shapes.size(), false);
diff --git a/servers/physics_2d/physics_2d_server_sw.cpp b/servers/physics_2d/physics_2d_server_sw.cpp
index ba87969eea..15e80bcd5e 100644
--- a/servers/physics_2d/physics_2d_server_sw.cpp
+++ b/servers/physics_2d/physics_2d_server_sw.cpp
@@ -789,22 +789,6 @@ real_t Physics2DServerSW::body_get_param(RID p_body, BodyParameter p_param) cons
return body->get_param(p_param);
};
-void Physics2DServerSW::body_set_combine_mode(RID p_body, BodyParameter p_param, CombineMode p_mode) {
-
- Body2DSW *body = body_owner.get(p_body);
- ERR_FAIL_COND(!body);
-
- body->set_combine_mode(p_param, p_mode);
-}
-
-Physics2DServer::CombineMode Physics2DServerSW::body_get_combine_mode(RID p_body, BodyParameter p_param) const {
-
- Body2DSW *body = body_owner.get(p_body);
- ERR_FAIL_COND_V(!body, COMBINE_MODE_INHERIT);
-
- return body->get_combine_mode(p_param);
-}
-
void Physics2DServerSW::body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) {
Body2DSW *body = body_owner.get(p_body);
diff --git a/servers/physics_2d/physics_2d_server_sw.h b/servers/physics_2d/physics_2d_server_sw.h
index 0b8d3f2a31..d4fc44b1d7 100644
--- a/servers/physics_2d/physics_2d_server_sw.h
+++ b/servers/physics_2d/physics_2d_server_sw.h
@@ -200,10 +200,6 @@ public:
virtual void body_set_param(RID p_body, BodyParameter p_param, real_t p_value);
virtual real_t body_get_param(RID p_body, BodyParameter p_param) const;
- /// p_param accept only Bounce and Friction
- virtual void body_set_combine_mode(RID p_body, BodyParameter p_param, CombineMode p_mode);
- virtual CombineMode body_get_combine_mode(RID p_body, BodyParameter p_param) const;
-
virtual void body_set_state(RID p_body, BodyState p_state, const Variant &p_variant);
virtual Variant body_get_state(RID p_body, BodyState p_state) const;
diff --git a/servers/physics_2d/physics_2d_server_wrap_mt.h b/servers/physics_2d/physics_2d_server_wrap_mt.h
index b9b0f80805..6b34fb9739 100644
--- a/servers/physics_2d/physics_2d_server_wrap_mt.h
+++ b/servers/physics_2d/physics_2d_server_wrap_mt.h
@@ -211,9 +211,6 @@ public:
FUNC3(body_set_param, RID, BodyParameter, real_t);
FUNC2RC(real_t, body_get_param, RID, BodyParameter);
- FUNC3(body_set_combine_mode, RID, BodyParameter, CombineMode);
- FUNC2RC(CombineMode, body_get_combine_mode, RID, BodyParameter);
-
FUNC3(body_set_state, RID, BodyState, const Variant &);
FUNC2RC(Variant, body_get_state, RID, BodyState);
diff --git a/servers/physics_2d/shape_2d_sw.cpp b/servers/physics_2d/shape_2d_sw.cpp
index 2b0eab5999..dc8ec23e69 100644
--- a/servers/physics_2d/shape_2d_sw.cpp
+++ b/servers/physics_2d/shape_2d_sw.cpp
@@ -891,8 +891,8 @@ int ConcavePolygonShape2DSW::_generate_bvh(BVH *p_bvh, int p_len, int p_depth) {
int l = _generate_bvh(p_bvh, median, p_depth + 1);
int r = _generate_bvh(&p_bvh[median], p_len - median, p_depth + 1);
- bvh[node_idx].left = l;
- bvh[node_idx].right = r;
+ bvh.write[node_idx].left = l;
+ bvh.write[node_idx].right = r;
return node_idx;
}
@@ -953,20 +953,20 @@ void ConcavePolygonShape2DSW::set_data(const Variant &p_data) {
for (Map<Point2, int>::Element *E = pointmap.front(); E; E = E->next()) {
aabb.expand_to(E->key());
- points[E->get()] = E->key();
+ points.write[E->get()] = E->key();
}
Vector<BVH> main_vbh;
main_vbh.resize(segments.size());
for (int i = 0; i < main_vbh.size(); i++) {
- main_vbh[i].aabb.position = points[segments[i].points[0]];
- main_vbh[i].aabb.expand_to(points[segments[i].points[1]]);
- main_vbh[i].left = -1;
- main_vbh[i].right = i;
+ main_vbh.write[i].aabb.position = points[segments[i].points[0]];
+ main_vbh.write[i].aabb.expand_to(points[segments[i].points[1]]);
+ main_vbh.write[i].left = -1;
+ main_vbh.write[i].right = i;
}
- _generate_bvh(&main_vbh[0], main_vbh.size(), 1);
+ _generate_bvh(main_vbh.ptrw(), main_vbh.size(), 1);
} else {
//dictionary with arrays
diff --git a/servers/physics_2d/space_2d_sw.h b/servers/physics_2d/space_2d_sw.h
index 959e15e12d..1247317b03 100644
--- a/servers/physics_2d/space_2d_sw.h
+++ b/servers/physics_2d/space_2d_sw.h
@@ -188,7 +188,7 @@ public:
void set_debug_contacts(int p_amount) { contact_debug.resize(p_amount); }
_FORCE_INLINE_ bool is_debugging_contacts() const { return !contact_debug.empty(); }
_FORCE_INLINE_ void add_debug_contact(const Vector2 &p_contact) {
- if (contact_debug_count < contact_debug.size()) contact_debug[contact_debug_count++] = p_contact;
+ if (contact_debug_count < contact_debug.size()) contact_debug.write[contact_debug_count++] = p_contact;
}
_FORCE_INLINE_ Vector<Vector2> get_debug_contacts() { return contact_debug; }
_FORCE_INLINE_ int get_debug_contact_count() { return contact_debug_count; }
diff --git a/servers/physics_2d_server.cpp b/servers/physics_2d_server.cpp
index d6f3068e16..37c4bc83ad 100644
--- a/servers/physics_2d_server.cpp
+++ b/servers/physics_2d_server.cpp
@@ -198,7 +198,7 @@ Vector<RID> Physics2DShapeQueryParameters::get_exclude() const {
ret.resize(exclude.size());
int idx = 0;
for (Set<RID>::Element *E = exclude.front(); E; E = E->next()) {
- ret[idx] = E->get();
+ ret.write[idx] = E->get();
}
return ret;
}
@@ -595,7 +595,7 @@ void Physics2DServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("body_apply_central_impulse", "body", "impulse"), &Physics2DServer::body_apply_central_impulse);
ClassDB::bind_method(D_METHOD("body_apply_torque_impulse", "body", "impulse"), &Physics2DServer::body_apply_torque_impulse);
ClassDB::bind_method(D_METHOD("body_apply_impulse", "body", "position", "impulse"), &Physics2DServer::body_apply_impulse);
- ClassDB::bind_method(D_METHOD("body_add_central_force", "force"), &Physics2DServer::body_add_central_force);
+ ClassDB::bind_method(D_METHOD("body_add_central_force", "body", "force"), &Physics2DServer::body_add_central_force);
ClassDB::bind_method(D_METHOD("body_add_force", "body", "offset", "force"), &Physics2DServer::body_add_force);
ClassDB::bind_method(D_METHOD("body_add_torque", "body", "torque"), &Physics2DServer::body_add_torque);
ClassDB::bind_method(D_METHOD("body_set_axis_velocity", "body", "axis_velocity"), &Physics2DServer::body_set_axis_velocity);
diff --git a/servers/physics_2d_server.h b/servers/physics_2d_server.h
index 796eec1e8e..f42d9868f0 100644
--- a/servers/physics_2d_server.h
+++ b/servers/physics_2d_server.h
@@ -423,19 +423,6 @@ public:
virtual void body_set_param(RID p_body, BodyParameter p_param, float p_value) = 0;
virtual float body_get_param(RID p_body, BodyParameter p_param) const = 0;
- enum CombineMode {
- COMBINE_MODE_MAX,
- COMBINE_MODE_MIN,
- COMBINE_MODE_MULTIPLY,
- COMBINE_MODE_AVERAGE,
-
- COMBINE_MODE_INHERIT /// Inherit from other body or use COMBINE_MODE_MAX (Restitution) COMBINE_MODE_MULTIPLY (Friction)
- };
-
- /// p_param accept only Bounce and Friction
- virtual void body_set_combine_mode(RID p_body, BodyParameter p_param, CombineMode p_mode) = 0;
- virtual CombineMode body_get_combine_mode(RID p_body, BodyParameter p_param) const = 0;
-
//state
enum BodyState {
BODY_STATE_TRANSFORM,
diff --git a/servers/physics_server.cpp b/servers/physics_server.cpp
index 7dd3437360..cda3856ecc 100644
--- a/servers/physics_server.cpp
+++ b/servers/physics_server.cpp
@@ -106,6 +106,7 @@ void PhysicsDirectBodyState::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_contact_local_position", "contact_idx"), &PhysicsDirectBodyState::get_contact_local_position);
ClassDB::bind_method(D_METHOD("get_contact_local_normal", "contact_idx"), &PhysicsDirectBodyState::get_contact_local_normal);
+ ClassDB::bind_method(D_METHOD("get_contact_impulse", "contact_idx"), &PhysicsDirectBodyState::get_contact_impulse);
ClassDB::bind_method(D_METHOD("get_contact_local_shape", "contact_idx"), &PhysicsDirectBodyState::get_contact_local_shape);
ClassDB::bind_method(D_METHOD("get_contact_collider", "contact_idx"), &PhysicsDirectBodyState::get_contact_collider);
ClassDB::bind_method(D_METHOD("get_contact_collider_position", "contact_idx"), &PhysicsDirectBodyState::get_contact_collider_position);
@@ -192,7 +193,7 @@ Vector<RID> PhysicsShapeQueryParameters::get_exclude() const {
ret.resize(exclude.size());
int idx = 0;
for (Set<RID>::Element *E = exclude.front(); E; E = E->next()) {
- ret[idx] = E->get();
+ ret.write[idx] = E->get();
}
return ret;
}
diff --git a/servers/physics_server.h b/servers/physics_server.h
index 217656e2a9..948aec1a2d 100644
--- a/servers/physics_server.h
+++ b/servers/physics_server.h
@@ -77,6 +77,7 @@ public:
virtual Vector3 get_contact_local_position(int p_contact_idx) const = 0;
virtual Vector3 get_contact_local_normal(int p_contact_idx) const = 0;
+ virtual float get_contact_impulse(int p_contact_idx) const = 0;
virtual int get_contact_local_shape(int p_contact_idx) const = 0;
virtual RID get_contact_collider(int p_contact_idx) const = 0;
@@ -400,19 +401,6 @@ public:
virtual void body_set_param(RID p_body, BodyParameter p_param, float p_value) = 0;
virtual float body_get_param(RID p_body, BodyParameter p_param) const = 0;
- enum CombineMode {
- COMBINE_MODE_MAX,
- COMBINE_MODE_MIN,
- COMBINE_MODE_MULTIPLY,
- COMBINE_MODE_AVERAGE,
-
- COMBINE_MODE_INHERIT /// Inherit from other body or use COMBINE_MODE_MAX (Restitution) COMBINE_MODE_MULTIPLY (Friction)
- };
-
- /// p_param accept only Bounce and Friction
- virtual void body_set_combine_mode(RID p_body, BodyParameter p_param, CombineMode p_mode) = 0;
- virtual CombineMode body_get_combine_mode(RID p_body, BodyParameter p_param) const = 0;
-
virtual void body_set_kinematic_safe_margin(RID p_body, real_t p_margin) = 0;
virtual real_t body_get_kinematic_safe_margin(RID p_body) const = 0;
diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp
index 1bad7e652b..4c764641e3 100644
--- a/servers/register_server_types.cpp
+++ b/servers/register_server_types.cpp
@@ -48,6 +48,7 @@
#include "audio/effects/audio_effect_panner.h"
#include "audio/effects/audio_effect_phaser.h"
#include "audio/effects/audio_effect_pitch_shift.h"
+#include "audio/effects/audio_effect_record.h"
#include "audio/effects/audio_effect_reverb.h"
#include "audio/effects/audio_effect_stereo_enhance.h"
#include "audio_server.h"
@@ -72,7 +73,7 @@ static void _debugger_get_resource_usage(List<ScriptDebuggerRemote::ResourceUsag
usage.vram = E->get().bytes;
usage.id = E->get().texture;
usage.type = "Texture";
- usage.format = itos(E->get().size.width) + "x" + itos(E->get().size.height) + " " + Image::get_format_name(E->get().format);
+ usage.format = itos(E->get().width) + "x" + itos(E->get().height) + " " + Image::get_format_name(E->get().format);
r_usage->push_back(usage);
}
}
@@ -103,6 +104,7 @@ void register_server_types() {
ClassDB::register_virtual_class<AudioStream>();
ClassDB::register_virtual_class<AudioStreamPlayback>();
+ ClassDB::register_class<AudioStreamMicrophone>();
ClassDB::register_class<AudioStreamRandomPitch>();
ClassDB::register_virtual_class<AudioEffect>();
ClassDB::register_class<AudioEffectEQ>();
@@ -138,6 +140,7 @@ void register_server_types() {
ClassDB::register_class<AudioEffectLimiter>();
ClassDB::register_class<AudioEffectPitchShift>();
ClassDB::register_class<AudioEffectPhaser>();
+ ClassDB::register_class<AudioEffectRecord>();
}
ClassDB::register_virtual_class<Physics2DDirectBodyState>();
diff --git a/servers/server_wrap_mt_common.h b/servers/server_wrap_mt_common.h
index 611e25af2a..843773e5b1 100644
--- a/servers/server_wrap_mt_common.h
+++ b/servers/server_wrap_mt_common.h
@@ -197,9 +197,10 @@
}
#define FUNC5RID(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5) \
- int m_type##allocn() { \
- for (int i = 0; i < m_type##_pool_max_size; i++) { \
- m_type##_id_pool.push_back(server_name->m_type##_create()); \
+ List<RID> m_type##_id_pool; \
+ int m_type##allocn(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) { \
+ for (int i = 0; i < pool_max_size; i++) { \
+ m_type##_id_pool.push_back(server_name->m_type##_create(p1, p2, p3, p4, p5)); \
} \
return 0; \
} \
diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h
index a8f4377ce7..49dff0d557 100644
--- a/servers/visual/rasterizer.h
+++ b/servers/visual/rasterizer.h
@@ -176,17 +176,34 @@ public:
/* TEXTURE API */
virtual RID texture_create() = 0;
- virtual void texture_allocate(RID p_texture, int p_width, int p_height, Image::Format p_format, uint32_t p_flags = VS::TEXTURE_FLAGS_DEFAULT) = 0;
- virtual void texture_set_data(RID p_texture, const Ref<Image> &p_image, VS::CubeMapSide p_cube_side = VS::CUBEMAP_LEFT) = 0;
- virtual void texture_set_data_partial(RID p_texture, const Ref<Image> &p_image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int p_dst_mip, VS::CubeMapSide p_cube_side = VS::CUBEMAP_LEFT) = 0;
- virtual Ref<Image> texture_get_data(RID p_texture, VS::CubeMapSide p_cube_side = VS::CUBEMAP_LEFT) const = 0;
+ virtual void texture_allocate(RID p_texture,
+ int p_width,
+ int p_height,
+ int p_depth_3d,
+ Image::Format p_format,
+ VS::TextureType p_type,
+ uint32_t p_flags = VS::TEXTURE_FLAGS_DEFAULT) = 0;
+
+ virtual void texture_set_data(RID p_texture, const Ref<Image> &p_image, int p_level = 0) = 0;
+
+ virtual void texture_set_data_partial(RID p_texture,
+ const Ref<Image> &p_image,
+ int src_x, int src_y,
+ int src_w, int src_h,
+ int dst_x, int dst_y,
+ int p_dst_mip,
+ int p_level = 0) = 0;
+
+ virtual Ref<Image> texture_get_data(RID p_texture, int p_level = 0) const = 0;
virtual void texture_set_flags(RID p_texture, uint32_t p_flags) = 0;
virtual uint32_t texture_get_flags(RID p_texture) const = 0;
virtual Image::Format texture_get_format(RID p_texture) const = 0;
+ virtual VS::TextureType texture_get_type(RID p_texture) const = 0;
virtual uint32_t texture_get_texid(RID p_texture) const = 0;
virtual uint32_t texture_get_width(RID p_texture) const = 0;
virtual uint32_t texture_get_height(RID p_texture) const = 0;
- virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) = 0;
+ virtual uint32_t texture_get_depth(RID p_texture) const = 0;
+ virtual void texture_set_size_override(RID p_texture, int p_width, int p_height, int p_depth_3d) = 0;
virtual void texture_set_path(RID p_texture, const String &p_path) = 0;
virtual String texture_get_path(RID p_texture) const = 0;
@@ -1078,7 +1095,7 @@ public:
virtual void set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale) = 0;
virtual void initialize() = 0;
- virtual void begin_frame() = 0;
+ virtual void begin_frame(double frame_step) = 0;
virtual void set_current_render_target(RID p_render_target) = 0;
virtual void restore_render_target() = 0;
virtual void clear_render_target(const Color &p_color) = 0;
diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp
index fd1eb77143..ca50d0d049 100644
--- a/servers/visual/shader_language.cpp
+++ b/servers/visual/shader_language.cpp
@@ -123,6 +123,12 @@ const char *ShaderLanguage::token_names[TK_MAX] = {
"TYPE_SAMPLER2D",
"TYPE_ISAMPLER2D",
"TYPE_USAMPLER2D",
+ "TYPE_SAMPLER2DARRAY",
+ "TYPE_ISAMPLER2DARRAY",
+ "TYPE_USAMPLER2DARRAY",
+ "TYPE_SAMPLER3D",
+ "TYPE_ISAMPLER3D",
+ "TYPE_USAMPLER3D",
"TYPE_SAMPLERCUBE",
"INTERPOLATION_FLAT",
"INTERPOLATION_NO_PERSPECTIVE",
@@ -257,6 +263,12 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = {
{ TK_TYPE_SAMPLER2D, "sampler2D" },
{ TK_TYPE_ISAMPLER2D, "isampler2D" },
{ TK_TYPE_USAMPLER2D, "usampler2D" },
+ { TK_TYPE_SAMPLER2DARRAY, "sampler2DArray" },
+ { TK_TYPE_ISAMPLER2DARRAY, "isampler2DArray" },
+ { TK_TYPE_USAMPLER2DARRAY, "usampler2DArray" },
+ { TK_TYPE_SAMPLER3D, "sampler3D" },
+ { TK_TYPE_ISAMPLER3D, "isampler3D" },
+ { TK_TYPE_USAMPLER3D, "usampler3D" },
{ TK_TYPE_SAMPLERCUBE, "samplerCube" },
{ TK_INTERPOLATION_FLAT, "flat" },
{ TK_INTERPOLATION_NO_PERSPECTIVE, "noperspective" },
@@ -516,13 +528,14 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
bool hexa_found = false;
bool sign_found = false;
bool minus_exponent_found = false;
+ bool float_suffix_found = false;
String str;
int i = 0;
while (true) {
if (GETCHAR(i) == '.') {
- if (period_found || exponent_found)
+ if (period_found || exponent_found || hexa_found || float_suffix_found)
return _make_token(TK_ERROR, "Invalid numeric constant");
period_found = true;
} else if (GETCHAR(i) == 'x') {
@@ -530,11 +543,16 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
return _make_token(TK_ERROR, "Invalid numeric constant");
hexa_found = true;
} else if (GETCHAR(i) == 'e') {
- if (hexa_found || exponent_found)
+ if (hexa_found || exponent_found || float_suffix_found)
return _make_token(TK_ERROR, "Invalid numeric constant");
exponent_found = true;
+ } else if (GETCHAR(i) == 'f') {
+ if (hexa_found || exponent_found)
+ return _make_token(TK_ERROR, "Invalid numeric constant");
+ float_suffix_found = true;
} else if (_is_number(GETCHAR(i))) {
- //all ok
+ if (float_suffix_found)
+ return _make_token(TK_ERROR, "Invalid numeric constant");
} else if (hexa_found && _is_hex(GETCHAR(i))) {
} else if ((GETCHAR(i) == '-' || GETCHAR(i) == '+') && exponent_found) {
@@ -550,21 +568,60 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
i++;
}
- if (!_is_number(str[str.length() - 1]))
- return _make_token(TK_ERROR, "Invalid numeric constant");
+ CharType last_char = str[str.length() - 1];
+
+ if (hexa_found) {
+ //hex integers eg."0xFF" or "0x12AB", etc - NOT supported yet
+ return _make_token(TK_ERROR, "Invalid (hexadecimal) numeric constant - Not supported");
+ } else if (period_found || float_suffix_found) {
+ //floats
+ if (period_found) {
+ if (float_suffix_found) {
+ //checks for eg "1.f" or "1.99f" notations
+ if (last_char != 'f') {
+ return _make_token(TK_ERROR, "Invalid (float) numeric constant");
+ }
+ } else {
+ //checks for eg. "1." or "1.99" notations
+ if (last_char != '.' && !_is_number(last_char)) {
+ return _make_token(TK_ERROR, "Invalid (float) numeric constant");
+ }
+ }
+ } else if (float_suffix_found) {
+ // if no period found the float suffix must be the last character, like in "2f" for "2.0"
+ if (last_char != 'f') {
+ return _make_token(TK_ERROR, "Invalid (float) numeric constant");
+ }
+ }
+
+ if (float_suffix_found) {
+ //strip the suffix
+ str = str.left(str.length() - 1);
+ //compensate reading cursor position
+ char_idx += 1;
+ }
+
+ if (!str.is_valid_float()) {
+ return _make_token(TK_ERROR, "Invalid (float) numeric constant");
+ }
+ } else {
+ //integers
+ if (!_is_number(last_char)) {
+ return _make_token(TK_ERROR, "Invalid (integer) numeric constant");
+ }
+ if (!str.is_valid_integer()) {
+ return _make_token(TK_ERROR, "Invalid numeric constant");
+ }
+ }
char_idx += str.length();
Token tk;
- if (period_found || minus_exponent_found)
+ if (period_found || minus_exponent_found || float_suffix_found)
tk.type = TK_REAL_CONSTANT;
else
tk.type = TK_INT_CONSTANT;
- if (!str.is_valid_float()) {
- return _make_token(TK_ERROR, "Invalid numeric constant");
- }
-
- tk.constant = str.to_double();
+ tk.constant = str.to_double(); //wont work with hex
tk.line = tk_line;
return tk;
@@ -612,6 +669,8 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
}
ERR_PRINT("BUG");
return Token();
+
+#undef GETCHAR
}
String ShaderLanguage::token_debug(const String &p_code) {
@@ -658,6 +717,12 @@ bool ShaderLanguage::is_token_datatype(TokenType p_type) {
p_type == TK_TYPE_SAMPLER2D ||
p_type == TK_TYPE_ISAMPLER2D ||
p_type == TK_TYPE_USAMPLER2D ||
+ p_type == TK_TYPE_SAMPLER2DARRAY ||
+ p_type == TK_TYPE_ISAMPLER2DARRAY ||
+ p_type == TK_TYPE_USAMPLER2DARRAY ||
+ p_type == TK_TYPE_SAMPLER3D ||
+ p_type == TK_TYPE_ISAMPLER3D ||
+ p_type == TK_TYPE_USAMPLER3D ||
p_type == TK_TYPE_SAMPLERCUBE);
}
@@ -729,6 +794,12 @@ String ShaderLanguage::get_datatype_name(DataType p_type) {
case TYPE_SAMPLER2D: return "sampler2D";
case TYPE_ISAMPLER2D: return "isampler2D";
case TYPE_USAMPLER2D: return "usampler2D";
+ case TYPE_SAMPLER2DARRAY: return "sampler2DArray";
+ case TYPE_ISAMPLER2DARRAY: return "isampler2DArray";
+ case TYPE_USAMPLER2DARRAY: return "usampler2DArray";
+ case TYPE_SAMPLER3D: return "sampler3D";
+ case TYPE_ISAMPLER3D: return "isampler3D";
+ case TYPE_USAMPLER3D: return "usampler3D";
case TYPE_SAMPLERCUBE: return "samplerCube";
}
@@ -1376,6 +1447,15 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "bvec4", TYPE_BVEC4, { TYPE_UVEC4, TYPE_VOID } },
{ "bvec4", TYPE_BVEC4, { TYPE_VEC4, TYPE_VOID } },
+ //conversion between matrixes
+
+ { "mat2", TYPE_MAT2, { TYPE_MAT3, TYPE_VOID } },
+ { "mat2", TYPE_MAT2, { TYPE_MAT4, TYPE_VOID } },
+ { "mat3", TYPE_MAT3, { TYPE_MAT2, TYPE_VOID } },
+ { "mat3", TYPE_MAT3, { TYPE_MAT4, TYPE_VOID } },
+ { "mat4", TYPE_MAT4, { TYPE_MAT2, TYPE_VOID } },
+ { "mat4", TYPE_MAT4, { TYPE_MAT3, TYPE_VOID } },
+
//builtins - trigonometry
{ "radians", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } },
@@ -1791,6 +1871,12 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "textureSize", TYPE_IVEC2, { TYPE_SAMPLER2D, TYPE_INT, TYPE_VOID } },
{ "textureSize", TYPE_IVEC2, { TYPE_ISAMPLER2D, TYPE_INT, TYPE_VOID } },
{ "textureSize", TYPE_IVEC2, { TYPE_USAMPLER2D, TYPE_INT, TYPE_VOID } },
+ { "textureSize", TYPE_IVEC3, { TYPE_SAMPLER2DARRAY, TYPE_INT, TYPE_VOID } },
+ { "textureSize", TYPE_IVEC3, { TYPE_ISAMPLER2DARRAY, TYPE_INT, TYPE_VOID } },
+ { "textureSize", TYPE_IVEC3, { TYPE_USAMPLER2DARRAY, TYPE_INT, TYPE_VOID } },
+ { "textureSize", TYPE_IVEC3, { TYPE_SAMPLER3D, TYPE_INT, TYPE_VOID } },
+ { "textureSize", TYPE_IVEC3, { TYPE_ISAMPLER3D, TYPE_INT, TYPE_VOID } },
+ { "textureSize", TYPE_IVEC3, { TYPE_USAMPLER3D, TYPE_INT, TYPE_VOID } },
{ "textureSize", TYPE_IVEC2, { TYPE_SAMPLERCUBE, TYPE_INT, TYPE_VOID } },
{ "texture", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VOID } },
@@ -1802,6 +1888,24 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VOID } },
{ "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID } },
+ { "texture", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID } },
+ { "texture", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
+
+ { "texture", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID } },
+ { "texture", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
+
+ { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID } },
+ { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
+
+ { "texture", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_VOID } },
+ { "texture", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
+
+ { "texture", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_VOID } },
+ { "texture", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
+
+ { "texture", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_VOID } },
+ { "texture", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
+
{ "texture", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VOID } },
{ "texture", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
@@ -1820,15 +1924,38 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
{ "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID } },
+ { "textureProj", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_VOID } },
+ { "textureProj", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID } },
+
+ { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_VOID } },
+ { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID } },
+
+ { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_VOID } },
+ { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID } },
+
{ "textureLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID } },
{ "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID } },
{ "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID } },
+ { "textureLod", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
+ { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
+ { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
+ { "textureLod", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
+ { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
+ { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
{ "textureLod", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
{ "texelFetch", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID } },
{ "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID } },
{ "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID } },
+ { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID } },
+ { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID } },
+ { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID } },
+
+ { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID } },
+ { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID } },
+ { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID } },
+
{ "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
{ "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID } },
@@ -1841,6 +1968,12 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "textureGrad", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
{ "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
{ "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
+ { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
+ { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
+ { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
+ { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID } },
+ { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID } },
+ { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID } },
{ "textureGrad", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID } },
{ "dFdx", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } },
@@ -2128,7 +2261,16 @@ bool ShaderLanguage::is_scalar_type(DataType p_type) {
bool ShaderLanguage::is_sampler_type(DataType p_type) {
- return p_type == TYPE_SAMPLER2D || p_type == TYPE_ISAMPLER2D || p_type == TYPE_USAMPLER2D || p_type == TYPE_SAMPLERCUBE;
+ return p_type == TYPE_SAMPLER2D ||
+ p_type == TYPE_ISAMPLER2D ||
+ p_type == TYPE_USAMPLER2D ||
+ p_type == TYPE_SAMPLER2DARRAY ||
+ p_type == TYPE_ISAMPLER2DARRAY ||
+ p_type == TYPE_USAMPLER2DARRAY ||
+ p_type == TYPE_SAMPLER3D ||
+ p_type == TYPE_ISAMPLER3D ||
+ p_type == TYPE_USAMPLER3D ||
+ p_type == TYPE_SAMPLERCUBE;
}
void ShaderLanguage::get_keyword_list(List<String> *r_keywords) {
@@ -2295,24 +2437,54 @@ bool ShaderLanguage::_is_operator_assign(Operator p_op) const {
return false;
}
-bool ShaderLanguage::_validate_assign(Node *p_node, const Map<StringName, BuiltInInfo> &p_builtin_types) {
+bool ShaderLanguage::_validate_assign(Node *p_node, const Map<StringName, BuiltInInfo> &p_builtin_types, String *r_message) {
if (p_node->type == Node::TYPE_OPERATOR) {
OperatorNode *op = static_cast<OperatorNode *>(p_node);
+
if (op->op == OP_INDEX) {
- return _validate_assign(op->arguments[0], p_builtin_types);
+ return _validate_assign(op->arguments[0], p_builtin_types, r_message);
+
+ } else if (_is_operator_assign(op->op)) {
+ //chained assignment
+ return _validate_assign(op->arguments[1], p_builtin_types, r_message);
+
+ } else if (op->op == OP_CALL) {
+ if (r_message)
+ *r_message = RTR("Assignment to function.");
+ return false;
}
- }
- if (p_node->type == Node::TYPE_VARIABLE) {
+ } else if (p_node->type == Node::TYPE_MEMBER) {
+
+ MemberNode *member = static_cast<MemberNode *>(p_node);
+ return _validate_assign(member->owner, p_builtin_types, r_message);
+
+ } else if (p_node->type == Node::TYPE_VARIABLE) {
VariableNode *var = static_cast<VariableNode *>(p_node);
- if (p_builtin_types.has(var->name) && p_builtin_types[var->name].constant) {
- return false; //ops not valid
+
+ if (shader->uniforms.has(var->name)) {
+ if (r_message)
+ *r_message = RTR("Assignment to uniform.");
+ return false;
+ }
+
+ if (shader->varyings.has(var->name) && current_function != String("vertex")) {
+ if (r_message)
+ *r_message = RTR("Varyings can only be assigned in vertex function.");
+ return false;
+ }
+
+ if (!(p_builtin_types.has(var->name) && p_builtin_types[var->name].constant)) {
+ return true;
}
}
- return true;
+
+ if (r_message)
+ *r_message = "Assignment to constant expression.";
+ return false;
}
ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types) {
@@ -2460,7 +2632,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
//add to current function as dependency
for (int j = 0; j < shader->functions.size(); j++) {
if (shader->functions[j].name == current_function) {
- shader->functions[j].uses_function.insert(name);
+ shader->functions.write[j].uses_function.insert(name);
break;
}
}
@@ -3010,8 +3182,8 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
op->arguments.push_back(expression[i + 1].node);
- expression[i].is_op = false;
- expression[i].node = op;
+ expression.write[i].is_op = false;
+ expression.write[i].node = op;
if (!_validate_operator(op, &op->return_cache)) {
@@ -3045,8 +3217,8 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
op->arguments.push_back(expression[next_op + 1].node);
op->arguments.push_back(expression[next_op + 3].node);
- expression[next_op - 1].is_op = false;
- expression[next_op - 1].node = op;
+ expression.write[next_op - 1].is_op = false;
+ expression.write[next_op - 1].node = op;
if (!_validate_operator(op, &op->return_cache)) {
String at;
@@ -3079,10 +3251,14 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
ERR_FAIL_V(NULL);
}
- if (_is_operator_assign(op->op) && !_validate_assign(expression[next_op - 1].node, p_builtin_types)) {
+ if (_is_operator_assign(op->op)) {
- _set_error("Assignment to constant expression.");
- return NULL;
+ String assign_message;
+ if (!_validate_assign(expression[next_op - 1].node, p_builtin_types, &assign_message)) {
+
+ _set_error(assign_message);
+ return NULL;
+ }
}
if (expression[next_op + 1].is_op) {
@@ -3096,7 +3272,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
op->arguments.push_back(expression[next_op - 1].node); //expression goes as left
op->arguments.push_back(expression[next_op + 1].node); //next expression goes as right
- expression[next_op - 1].node = op;
+ expression.write[next_op - 1].node = op;
//replace all 3 nodes by this operator and make it an expression
@@ -3138,7 +3314,7 @@ ShaderLanguage::Node *ShaderLanguage::_reduce_expression(BlockNode *p_block, Sha
for (int i = 1; i < op->arguments.size(); i++) {
- op->arguments[i] = _reduce_expression(p_block, op->arguments[i]);
+ op->arguments.write[i] = _reduce_expression(p_block, op->arguments[i]);
if (op->arguments[i]->type == Node::TYPE_CONSTANT) {
ConstantNode *cn = static_cast<ConstantNode *>(op->arguments[i]);
@@ -3178,7 +3354,7 @@ ShaderLanguage::Node *ShaderLanguage::_reduce_expression(BlockNode *p_block, Sha
return cn;
} else if (op->op == OP_NEGATE) {
- op->arguments[0] = _reduce_expression(p_block, op->arguments[0]);
+ op->arguments.write[0] = _reduce_expression(p_block, op->arguments[0]);
if (op->arguments[0]->type == Node::TYPE_CONSTANT) {
ConstantNode *cn = static_cast<ConstantNode *>(op->arguments[0]);
@@ -4064,13 +4240,58 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
return OK;
}
+// skips over whitespace and /* */ and // comments
+static int _get_first_ident_pos(const String &p_code) {
+
+ int idx = 0;
+
+#define GETCHAR(m_idx) (((idx + m_idx) < p_code.length()) ? p_code[idx + m_idx] : CharType(0))
+
+ while (true) {
+ if (GETCHAR(0) == '/' && GETCHAR(1) == '/') {
+ idx += 2;
+ while (true) {
+ if (GETCHAR(0) == 0) return 0;
+ if (GETCHAR(0) == '\n') {
+ idx++;
+ break; // loop
+ }
+ idx++;
+ }
+ } else if (GETCHAR(0) == '/' && GETCHAR(1) == '*') {
+ idx += 2;
+ while (true) {
+ if (GETCHAR(0) == 0) return 0;
+ if (GETCHAR(0) == '*' && GETCHAR(1) == '/') {
+ idx += 2;
+ break; // loop
+ }
+ idx++;
+ }
+ } else {
+ switch (GETCHAR(0)) {
+ case ' ':
+ case '\t':
+ case '\r':
+ case '\n': {
+ idx++;
+ } break; // switch
+ default:
+ return idx;
+ }
+ }
+ }
+
+#undef GETCHAR
+}
+
String ShaderLanguage::get_shader_type(const String &p_code) {
bool reading_type = false;
String cur_identifier;
- for (int i = 0; i < p_code.length(); i++) {
+ for (int i = _get_first_ident_pos(p_code); i < p_code.length(); i++) {
if (p_code[i] == ';') {
break;
diff --git a/servers/visual/shader_language.h b/servers/visual/shader_language.h
index 9b84c5f195..d68f233b2f 100644
--- a/servers/visual/shader_language.h
+++ b/servers/visual/shader_language.h
@@ -72,6 +72,12 @@ public:
TK_TYPE_SAMPLER2D,
TK_TYPE_ISAMPLER2D,
TK_TYPE_USAMPLER2D,
+ TK_TYPE_SAMPLER2DARRAY,
+ TK_TYPE_ISAMPLER2DARRAY,
+ TK_TYPE_USAMPLER2DARRAY,
+ TK_TYPE_SAMPLER3D,
+ TK_TYPE_ISAMPLER3D,
+ TK_TYPE_USAMPLER3D,
TK_TYPE_SAMPLERCUBE,
TK_INTERPOLATION_FLAT,
TK_INTERPOLATION_NO_PERSPECTIVE,
@@ -186,6 +192,12 @@ public:
TYPE_SAMPLER2D,
TYPE_ISAMPLER2D,
TYPE_USAMPLER2D,
+ TYPE_SAMPLER2DARRAY,
+ TYPE_ISAMPLER2DARRAY,
+ TYPE_USAMPLER2DARRAY,
+ TYPE_SAMPLER3D,
+ TYPE_ISAMPLER3D,
+ TYPE_USAMPLER3D,
TYPE_SAMPLERCUBE,
};
@@ -617,7 +629,7 @@ private:
bool _find_identifier(const BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, const StringName &p_identifier, DataType *r_data_type = NULL, IdentifierType *r_type = NULL);
bool _is_operator_assign(Operator p_op) const;
- bool _validate_assign(Node *p_node, const Map<StringName, BuiltInInfo> &p_builtin_types);
+ bool _validate_assign(Node *p_node, const Map<StringName, BuiltInInfo> &p_builtin_types, String *r_message = NULL);
bool _validate_operator(OperatorNode *p_op, DataType *r_ret_type = NULL);
diff --git a/servers/visual/visual_server_canvas.cpp b/servers/visual/visual_server_canvas.cpp
index 6439ba8509..0b4bbffddf 100644
--- a/servers/visual/visual_server_canvas.cpp
+++ b/servers/visual/visual_server_canvas.cpp
@@ -220,7 +220,7 @@ void VisualServerCanvas::render_canvas(Canvas *p_canvas, const Transform2D &p_tr
for (int i = 0; i < l; i++) {
- Canvas::ChildItem &ci = p_canvas->child_items[i];
+ const Canvas::ChildItem &ci = p_canvas->child_items[i];
_render_canvas_item_tree(ci.item, p_transform, p_clip_rect, p_canvas->modulate, p_lights);
//mirroring (useful for scrolling backgrounds)
@@ -263,7 +263,7 @@ void VisualServerCanvas::canvas_set_item_mirroring(RID p_canvas, RID p_item, con
int idx = canvas->find_item(canvas_item);
ERR_FAIL_COND(idx == -1);
- canvas->child_items[idx].mirror = p_mirroring;
+ canvas->child_items.write[idx].mirror = p_mirroring;
}
void VisualServerCanvas::canvas_set_modulate(RID p_canvas, const Color &p_color) {
@@ -468,21 +468,21 @@ void VisualServerCanvas::canvas_item_add_polyline(RID p_item, const Vector<Point
Vector2 tangent = ((t + prev_t).normalized()) * p_width * 0.5;
if (p_antialiased) {
- pline->lines[i] = p_points[i] + tangent;
- pline->lines[p_points.size() * 2 - i - 1] = p_points[i] - tangent;
+ pline->lines.write[i] = p_points[i] + tangent;
+ pline->lines.write[p_points.size() * 2 - i - 1] = p_points[i] - tangent;
if (pline->line_colors.size() > 1) {
- pline->line_colors[i] = p_colors[i];
- pline->line_colors[p_points.size() * 2 - i - 1] = p_colors[i];
+ pline->line_colors.write[i] = p_colors[i];
+ pline->line_colors.write[p_points.size() * 2 - i - 1] = p_colors[i];
}
}
- pline->triangles[i * 2 + 0] = p_points[i] + tangent;
- pline->triangles[i * 2 + 1] = p_points[i] - tangent;
+ pline->triangles.write[i * 2 + 0] = p_points[i] + tangent;
+ pline->triangles.write[i * 2 + 1] = p_points[i] - tangent;
if (pline->triangle_colors.size() > 1) {
- pline->triangle_colors[i * 2 + 0] = p_colors[i];
- pline->triangle_colors[i * 2 + 1] = p_colors[i];
+ pline->triangle_colors.write[i * 2 + 0] = p_colors[i];
+ pline->triangle_colors.write[i * 2 + 1] = p_colors[i];
}
prev_t = t;
@@ -669,7 +669,7 @@ void VisualServerCanvas::canvas_item_add_polygon(RID p_item, const Vector<Point2
int color_size = p_colors.size();
int uv_size = p_uvs.size();
ERR_FAIL_COND(color_size != 0 && color_size != 1 && color_size != pointcount);
- ERR_FAIL_COND(uv_size != 0 && (uv_size != pointcount || !p_texture.is_valid()));
+ ERR_FAIL_COND(uv_size != 0 && (uv_size != pointcount));
#endif
Vector<int> indices = Geometry::triangulate_polygon(p_points);
diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp
index 5f207b1d3f..c7d33ec43c 100644
--- a/servers/visual/visual_server_raster.cpp
+++ b/servers/visual/visual_server_raster.cpp
@@ -93,14 +93,14 @@ void VisualServerRaster::request_frame_drawn_callback(Object *p_where, const Str
frame_drawn_callbacks.push_back(fdc);
}
-void VisualServerRaster::draw(bool p_swap_buffers) {
+void VisualServerRaster::draw(bool p_swap_buffers, double frame_step) {
//needs to be done before changes is reset to 0, to not force the editor to redraw
VS::get_singleton()->emit_signal("frame_pre_draw");
changes = 0;
- VSG::rasterizer->begin_frame();
+ VSG::rasterizer->begin_frame(frame_step);
VSG::scene->update_dirty_instances(); //update scene stuff
@@ -161,6 +161,7 @@ void VisualServerRaster::set_boot_image(const Ref<Image> &p_image, const Color &
VSG::rasterizer->set_boot_image(p_image, p_color, p_scale);
}
void VisualServerRaster::set_default_clear_color(const Color &p_color) {
+ VSG::viewport->set_default_clear_color(p_color);
}
bool VisualServerRaster::has_feature(Features p_feature) const {
diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h
index ec0d02ed2a..a00b364565 100644
--- a/servers/visual/visual_server_raster.h
+++ b/servers/visual/visual_server_raster.h
@@ -148,17 +148,19 @@ public:
/* TEXTURE API */
BIND0R(RID, texture_create)
- BIND5(texture_allocate, RID, int, int, Image::Format, uint32_t)
- BIND3(texture_set_data, RID, const Ref<Image> &, CubeMapSide)
- BIND10(texture_set_data_partial, RID, const Ref<Image> &, int, int, int, int, int, int, int, CubeMapSide)
- BIND2RC(Ref<Image>, texture_get_data, RID, CubeMapSide)
+ BIND7(texture_allocate, RID, int, int, int, Image::Format, TextureType, uint32_t)
+ BIND3(texture_set_data, RID, const Ref<Image> &, int)
+ BIND10(texture_set_data_partial, RID, const Ref<Image> &, int, int, int, int, int, int, int, int)
+ BIND2RC(Ref<Image>, texture_get_data, RID, int)
BIND2(texture_set_flags, RID, uint32_t)
BIND1RC(uint32_t, texture_get_flags, RID)
BIND1RC(Image::Format, texture_get_format, RID)
+ BIND1RC(TextureType, texture_get_type, RID)
BIND1RC(uint32_t, texture_get_texid, RID)
BIND1RC(uint32_t, texture_get_width, RID)
BIND1RC(uint32_t, texture_get_height, RID)
- BIND3(texture_set_size_override, RID, int, int)
+ BIND1RC(uint32_t, texture_get_depth, RID)
+ BIND4(texture_set_size_override, RID, int, int, int)
BIND3(texture_set_detect_3d_callback, RID, TextureDetectCallback, void *)
BIND3(texture_set_detect_srgb_callback, RID, TextureDetectCallback, void *)
@@ -660,7 +662,7 @@ public:
virtual void request_frame_drawn_callback(Object *p_where, const StringName &p_method, const Variant &p_userdata);
- virtual void draw(bool p_swap_buffers);
+ virtual void draw(bool p_swap_buffers, double frame_step);
virtual void sync();
virtual bool has_changed() const;
virtual void init();
diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp
index 887cd7429a..213b3ad8f6 100644
--- a/servers/visual/visual_server_scene.cpp
+++ b/servers/visual/visual_server_scene.cpp
@@ -589,7 +589,7 @@ void VisualServerScene::instance_set_blend_shape_weight(RID p_instance, int p_sh
}
ERR_FAIL_INDEX(p_shape, instance->blend_values.size());
- instance->blend_values[p_shape] = p_weight;
+ instance->blend_values.write[p_shape] = p_weight;
}
void VisualServerScene::instance_set_surface_material(RID p_instance, int p_surface, RID p_material) {
@@ -606,7 +606,7 @@ void VisualServerScene::instance_set_surface_material(RID p_instance, int p_surf
if (instance->materials[p_surface].is_valid()) {
VSG::storage->material_remove_instance_owner(instance->materials[p_surface], instance);
}
- instance->materials[p_surface] = p_material;
+ instance->materials.write[p_surface] = p_material;
instance->base_material_changed();
if (instance->materials[p_surface].is_valid()) {
@@ -820,7 +820,7 @@ void VisualServerScene::instance_geometry_set_flag(RID p_instance, VS::InstanceF
instance->baked_light = p_enabled;
} break;
- case VS::INSTANCE_FLAG_REDRAW_FRAME_IF_VISIBLE: {
+ case VS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE: {
instance->redraw_if_visible = p_enabled;
@@ -1253,7 +1253,7 @@ void VisualServerScene::_update_instance_lightmap_captures(Instance *p_instance)
Vector3 dir = to_cell_xform.basis.xform(cone_traces[i]).normalized();
Color capture = _light_capture_voxel_cone_trace(octree_r.ptr(), pos, dir, cone_aperture, cell_subdiv);
- p_instance->lightmap_capture_data[i] += capture;
+ p_instance->lightmap_capture_data.write[i] += capture;
}
}
}
@@ -1464,14 +1464,14 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons
light_frustum_planes.resize(6);
//right/left
- light_frustum_planes[0] = Plane(x_vec, x_max);
- light_frustum_planes[1] = Plane(-x_vec, -x_min);
+ light_frustum_planes.write[0] = Plane(x_vec, x_max);
+ light_frustum_planes.write[1] = Plane(-x_vec, -x_min);
//top/bottom
- light_frustum_planes[2] = Plane(y_vec, y_max);
- light_frustum_planes[3] = Plane(-y_vec, -y_min);
+ light_frustum_planes.write[2] = Plane(y_vec, y_max);
+ light_frustum_planes.write[3] = Plane(-y_vec, -y_min);
//near/far
- light_frustum_planes[4] = Plane(z_vec, z_max + 1e6);
- light_frustum_planes[5] = Plane(-z_vec, -z_min); // z_min is ok, since casters further than far-light plane are not needed
+ light_frustum_planes.write[4] = Plane(z_vec, z_max + 1e6);
+ light_frustum_planes.write[5] = Plane(-z_vec, -z_min); // z_min is ok, since casters further than far-light plane are not needed
int cull_count = p_scenario->octree.cull_convex(light_frustum_planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, VS::INSTANCE_GEOMETRY_MASK);
@@ -1532,11 +1532,11 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons
float z = i == 0 ? -1 : 1;
Vector<Plane> planes;
planes.resize(5);
- planes[0] = light_transform.xform(Plane(Vector3(0, 0, z), radius));
- planes[1] = light_transform.xform(Plane(Vector3(1, 0, z).normalized(), radius));
- planes[2] = light_transform.xform(Plane(Vector3(-1, 0, z).normalized(), radius));
- planes[3] = light_transform.xform(Plane(Vector3(0, 1, z).normalized(), radius));
- planes[4] = light_transform.xform(Plane(Vector3(0, -1, z).normalized(), radius));
+ planes.write[0] = light_transform.xform(Plane(Vector3(0, 0, z), radius));
+ planes.write[1] = light_transform.xform(Plane(Vector3(1, 0, z).normalized(), radius));
+ planes.write[2] = light_transform.xform(Plane(Vector3(-1, 0, z).normalized(), radius));
+ planes.write[3] = light_transform.xform(Plane(Vector3(0, 1, z).normalized(), radius));
+ planes.write[4] = light_transform.xform(Plane(Vector3(0, -1, z).normalized(), radius));
int cull_count = p_scenario->octree.cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, VS::INSTANCE_GEOMETRY_MASK);
Plane near_plane(light_transform.origin, light_transform.basis.get_axis(2) * z);
@@ -1898,7 +1898,7 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca
InstanceLightData *light = static_cast<InstanceLightData *>(E->get()->base_data);
- ins->light_instances[l++] = light->instance;
+ ins->light_instances.write[l++] = light->instance;
}
geom->lighting_dirty = false;
@@ -1913,7 +1913,7 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca
InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(E->get()->base_data);
- ins->reflection_probe_instances[l++] = reflection_probe->instance;
+ ins->reflection_probe_instances.write[l++] = reflection_probe->instance;
}
geom->reflection_dirty = false;
@@ -1928,7 +1928,7 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca
InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(E->get()->base_data);
- ins->gi_probe_instances[l++] = gi_probe->probe_instance;
+ ins->gi_probe_instances.write[l++] = gi_probe->probe_instance;
}
geom->gi_probes_dirty = false;
@@ -2372,7 +2372,7 @@ void VisualServerScene::_setup_gi_probe(Instance *p_instance) {
uint32_t key = blockz * blockw * blockh + blocky * blockw + blockx;
- Map<uint32_t, InstanceGIProbeData::CompBlockS3TC> &cmap = comp_blocks[mipmap];
+ Map<uint32_t, InstanceGIProbeData::CompBlockS3TC> &cmap = comp_blocks.write[mipmap];
if (!cmap.has(key)) {
@@ -2392,8 +2392,8 @@ void VisualServerScene::_setup_gi_probe(Instance *p_instance) {
for (int i = 0; i < mipmap_count; i++) {
print_line("S3TC level: " + itos(i) + " blocks: " + itos(comp_blocks[i].size()));
- probe->dynamic.mipmaps_s3tc[i].resize(comp_blocks[i].size());
- PoolVector<InstanceGIProbeData::CompBlockS3TC>::Write w = probe->dynamic.mipmaps_s3tc[i].write();
+ probe->dynamic.mipmaps_s3tc.write[i].resize(comp_blocks[i].size());
+ PoolVector<InstanceGIProbeData::CompBlockS3TC>::Write w = probe->dynamic.mipmaps_s3tc.write[i].write();
int block_idx = 0;
for (Map<uint32_t, InstanceGIProbeData::CompBlockS3TC>::Element *E = comp_blocks[i].front(); E; E = E->next()) {
@@ -2861,7 +2861,7 @@ void VisualServerScene::_bake_gi_probe(Instance *p_gi_probe) {
int level_cell_count = probe_data->dynamic.level_cell_lists[i].size();
const uint32_t *level_cells = probe_data->dynamic.level_cell_lists[i].ptr();
- PoolVector<uint8_t>::Write lw = probe_data->dynamic.mipmaps_3d[stage].write();
+ PoolVector<uint8_t>::Write lw = probe_data->dynamic.mipmaps_3d.write[stage].write();
uint8_t *mipmapw = lw.ptr();
uint32_t sizes[3] = { header->width >> stage, header->height >> stage, header->depth >> stage };
@@ -2890,7 +2890,7 @@ void VisualServerScene::_bake_gi_probe(Instance *p_gi_probe) {
for (int mmi = 0; mmi < mipmap_count; mmi++) {
- PoolVector<uint8_t>::Write mmw = probe_data->dynamic.mipmaps_3d[mmi].write();
+ PoolVector<uint8_t>::Write mmw = probe_data->dynamic.mipmaps_3d.write[mmi].write();
int block_count = probe_data->dynamic.mipmaps_s3tc[mmi].size();
PoolVector<InstanceGIProbeData::CompBlockS3TC>::Read mmr = probe_data->dynamic.mipmaps_s3tc[mmi].read();
@@ -3223,7 +3223,7 @@ void VisualServerScene::_update_dirty_instance(Instance *p_instance) {
if (new_blend_shape_count != p_instance->blend_values.size()) {
p_instance->blend_values.resize(new_blend_shape_count);
for (int i = 0; i < new_blend_shape_count; i++) {
- p_instance->blend_values[i] = 0;
+ p_instance->blend_values.write[i] = 0;
}
}
}
diff --git a/servers/visual/visual_server_viewport.cpp b/servers/visual/visual_server_viewport.cpp
index dd6bc3cf26..a700fcf11b 100644
--- a/servers/visual/visual_server_viewport.cpp
+++ b/servers/visual/visual_server_viewport.cpp
@@ -252,7 +252,9 @@ void VisualServerViewport::draw_viewports() {
// process all our active interfaces
ARVRServer::get_singleton()->_process();
- clear_color = GLOBAL_GET("rendering/environment/default_clear_color");
+ if (Engine::get_singleton()->is_editor_hint()) {
+ clear_color = GLOBAL_GET("rendering/environment/default_clear_color");
+ }
//sort viewports
active_viewports.sort_custom<ViewportSort>();
@@ -660,5 +662,9 @@ bool VisualServerViewport::free(RID p_rid) {
return false;
}
+void VisualServerViewport::set_default_clear_color(const Color &p_color) {
+ clear_color = p_color;
+}
+
VisualServerViewport::VisualServerViewport() {
}
diff --git a/servers/visual/visual_server_viewport.h b/servers/visual/visual_server_viewport.h
index c0c83c0450..f915e26b81 100644
--- a/servers/visual/visual_server_viewport.h
+++ b/servers/visual/visual_server_viewport.h
@@ -188,6 +188,7 @@ public:
virtual int viewport_get_render_info(RID p_viewport, VS::ViewportRenderInfo p_info);
virtual void viewport_set_debug_draw(RID p_viewport, VS::ViewportDebugDraw p_draw);
+ void set_default_clear_color(const Color &p_color);
void draw_viewports();
bool free(RID p_rid);
diff --git a/servers/visual/visual_server_wrap_mt.cpp b/servers/visual/visual_server_wrap_mt.cpp
index 094e2794ed..93f3792bdc 100644
--- a/servers/visual/visual_server_wrap_mt.cpp
+++ b/servers/visual/visual_server_wrap_mt.cpp
@@ -37,11 +37,11 @@ void VisualServerWrapMT::thread_exit() {
exit = true;
}
-void VisualServerWrapMT::thread_draw() {
+void VisualServerWrapMT::thread_draw(bool p_swap_buffers, double frame_step) {
if (!atomic_decrement(&draw_pending)) {
- visual_server->draw();
+ visual_server->draw(p_swap_buffers, frame_step);
}
}
@@ -91,15 +91,15 @@ void VisualServerWrapMT::sync() {
}
}
-void VisualServerWrapMT::draw(bool p_swap_buffers) {
+void VisualServerWrapMT::draw(bool p_swap_buffers, double frame_step) {
if (create_thread) {
atomic_increment(&draw_pending);
- command_queue.push(this, &VisualServerWrapMT::thread_draw);
+ command_queue.push(this, &VisualServerWrapMT::thread_draw, p_swap_buffers, frame_step);
} else {
- visual_server->draw(p_swap_buffers);
+ visual_server->draw(p_swap_buffers, frame_step);
}
}
diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h
index 48f0ec46f3..3a4d72c793 100644
--- a/servers/visual/visual_server_wrap_mt.h
+++ b/servers/visual/visual_server_wrap_mt.h
@@ -55,7 +55,7 @@ class VisualServerWrapMT : public VisualServer {
bool create_thread;
uint64_t draw_pending;
- void thread_draw();
+ void thread_draw(bool p_swap_buffers, double frame_step);
void thread_flush();
void thread_exit();
@@ -82,17 +82,19 @@ public:
/* EVENT QUEUING */
FUNCRID(texture)
- FUNC5(texture_allocate, RID, int, int, Image::Format, uint32_t)
- FUNC3(texture_set_data, RID, const Ref<Image> &, CubeMapSide)
- FUNC10(texture_set_data_partial, RID, const Ref<Image> &, int, int, int, int, int, int, int, CubeMapSide)
- FUNC2RC(Ref<Image>, texture_get_data, RID, CubeMapSide)
+ FUNC7(texture_allocate, RID, int, int, int, Image::Format, TextureType, uint32_t)
+ FUNC3(texture_set_data, RID, const Ref<Image> &, int)
+ FUNC10(texture_set_data_partial, RID, const Ref<Image> &, int, int, int, int, int, int, int, int)
+ FUNC2RC(Ref<Image>, texture_get_data, RID, int)
FUNC2(texture_set_flags, RID, uint32_t)
FUNC1RC(uint32_t, texture_get_flags, RID)
FUNC1RC(Image::Format, texture_get_format, RID)
+ FUNC1RC(TextureType, texture_get_type, RID)
FUNC1RC(uint32_t, texture_get_texid, RID)
FUNC1RC(uint32_t, texture_get_width, RID)
FUNC1RC(uint32_t, texture_get_height, RID)
- FUNC3(texture_set_size_override, RID, int, int)
+ FUNC1RC(uint32_t, texture_get_depth, RID)
+ FUNC4(texture_set_size_override, RID, int, int, int)
FUNC3(texture_set_detect_3d_callback, RID, TextureDetectCallback, void *)
FUNC3(texture_set_detect_srgb_callback, RID, TextureDetectCallback, void *)
@@ -578,7 +580,7 @@ public:
virtual void init();
virtual void finish();
- virtual void draw(bool p_swap_buffers);
+ virtual void draw(bool p_swap_buffers, double frame_step);
virtual void sync();
FUNC0RC(bool, has_changed)
diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp
index 1f3319dc04..bc9e9042ec 100644
--- a/servers/visual_server.cpp
+++ b/servers/visual_server.cpp
@@ -55,7 +55,7 @@ RID VisualServer::texture_create_from_image(const Ref<Image> &p_image, uint32_t
ERR_FAIL_COND_V(!p_image.is_valid(), RID());
RID texture = texture_create();
- texture_allocate(texture, p_image->get_width(), p_image->get_height(), p_image->get_format(), p_flags); //if it has mipmaps, use, else generate
+ texture_allocate(texture, p_image->get_width(), p_image->get_height(), 0, p_image->get_format(), VS::TEXTURE_TYPE_2D, p_flags); //if it has mipmaps, use, else generate
ERR_FAIL_COND_V(!texture.is_valid(), texture);
texture_set_data(texture, p_image);
@@ -72,7 +72,9 @@ Array VisualServer::_texture_debug_usage_bind() {
Dictionary dict;
dict["texture"] = E->get().texture;
- dict["size"] = E->get().size;
+ dict["width"] = E->get().width;
+ dict["height"] = E->get().height;
+ dict["depth"] = E->get().depth;
dict["format"] = E->get().format;
dict["bytes"] = E->get().bytes;
dict["path"] = E->get().path;
@@ -333,7 +335,7 @@ RID VisualServer::get_white_texture() {
}
Ref<Image> white = memnew(Image(4, 4, 0, Image::FORMAT_RGB8, wt));
white_texture = texture_create();
- texture_allocate(white_texture, 4, 4, Image::FORMAT_RGB8);
+ texture_allocate(white_texture, 4, 4, 0, Image::FORMAT_RGB8, TEXTURE_TYPE_2D);
texture_set_data(white_texture, white);
return white_texture;
}
@@ -744,7 +746,7 @@ Error VisualServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_
if (first) {
for (int i = 0; i < total_bones; i++) {
- r_bone_aabb[i].size = Vector3(-1, -1, -1); //negative means unused
+ r_bone_aabb.write[i].size = Vector3(-1, -1, -1); //negative means unused
}
}
@@ -1648,27 +1650,29 @@ Array VisualServer::_mesh_surface_get_skeleton_aabb_bind(RID p_mesh, int p_surfa
void VisualServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("force_sync"), &VisualServer::sync);
- ClassDB::bind_method(D_METHOD("force_draw", "swap_buffers"), &VisualServer::draw, DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("force_draw", "swap_buffers", "frame_step"), &VisualServer::draw, DEFVAL(true), DEFVAL(0.0));
// "draw" and "sync" are deprecated duplicates of "force_draw" and "force_sync"
// FIXME: Add deprecation messages using GH-4397 once available, and retire
// once the warnings have been enabled for a full release cycle
ClassDB::bind_method(D_METHOD("sync"), &VisualServer::sync);
- ClassDB::bind_method(D_METHOD("draw", "swap_buffers"), &VisualServer::draw, DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("draw", "swap_buffers", "frame_step"), &VisualServer::draw, DEFVAL(true), DEFVAL(0.0));
ClassDB::bind_method(D_METHOD("texture_create"), &VisualServer::texture_create);
ClassDB::bind_method(D_METHOD("texture_create_from_image", "image", "flags"), &VisualServer::texture_create_from_image, DEFVAL(TEXTURE_FLAGS_DEFAULT));
- ClassDB::bind_method(D_METHOD("texture_allocate", "texture", "width", "height", "format", "flags"), &VisualServer::texture_allocate, DEFVAL(TEXTURE_FLAGS_DEFAULT));
- ClassDB::bind_method(D_METHOD("texture_set_data", "texture", "image", "cube_side"), &VisualServer::texture_set_data, DEFVAL(CUBEMAP_LEFT));
- ClassDB::bind_method(D_METHOD("texture_set_data_partial", "texture", "image", "src_x", "src_y", "src_w", "src_h", "dst_x", "dst_y", "dst_mip", "cube_side"), &VisualServer::texture_set_data_partial, DEFVAL(CUBEMAP_LEFT));
+ ClassDB::bind_method(D_METHOD("texture_allocate", "texture", "width", "height", "depth_3d", "format", "type", "flags"), &VisualServer::texture_allocate, DEFVAL(TEXTURE_FLAGS_DEFAULT));
+ ClassDB::bind_method(D_METHOD("texture_set_data", "texture", "image", "layer"), &VisualServer::texture_set_data, DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("texture_set_data_partial", "texture", "image", "src_x", "src_y", "src_w", "src_h", "dst_x", "dst_y", "dst_mip", "layer"), &VisualServer::texture_set_data_partial, DEFVAL(0));
ClassDB::bind_method(D_METHOD("texture_get_data", "texture", "cube_side"), &VisualServer::texture_get_data, DEFVAL(CUBEMAP_LEFT));
ClassDB::bind_method(D_METHOD("texture_set_flags", "texture", "flags"), &VisualServer::texture_set_flags);
ClassDB::bind_method(D_METHOD("texture_get_flags", "texture"), &VisualServer::texture_get_flags);
ClassDB::bind_method(D_METHOD("texture_get_format", "texture"), &VisualServer::texture_get_format);
+ ClassDB::bind_method(D_METHOD("texture_get_type", "texture"), &VisualServer::texture_get_type);
ClassDB::bind_method(D_METHOD("texture_get_texid", "texture"), &VisualServer::texture_get_texid);
ClassDB::bind_method(D_METHOD("texture_get_width", "texture"), &VisualServer::texture_get_width);
ClassDB::bind_method(D_METHOD("texture_get_height", "texture"), &VisualServer::texture_get_height);
- ClassDB::bind_method(D_METHOD("texture_set_size_override", "texture", "width", "height"), &VisualServer::texture_set_size_override);
+ ClassDB::bind_method(D_METHOD("texture_get_depth", "texture"), &VisualServer::texture_get_depth);
+ ClassDB::bind_method(D_METHOD("texture_set_size_override", "texture", "width", "height", "depth"), &VisualServer::texture_set_size_override);
ClassDB::bind_method(D_METHOD("texture_set_path", "texture", "path"), &VisualServer::texture_set_path);
ClassDB::bind_method(D_METHOD("texture_get_path", "texture"), &VisualServer::texture_get_path);
ClassDB::bind_method(D_METHOD("texture_set_shrink_all_x2_on_set_data", "shrink"), &VisualServer::texture_set_shrink_all_x2_on_set_data);
@@ -1908,7 +1912,7 @@ void VisualServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("environment_set_tonemap", "env", "tone_mapper", "exposure", "white", "auto_exposure", "min_luminance", "max_luminance", "auto_exp_speed", "auto_exp_grey"), &VisualServer::environment_set_tonemap);
ClassDB::bind_method(D_METHOD("environment_set_adjustment", "env", "enable", "brightness", "contrast", "saturation", "ramp"), &VisualServer::environment_set_adjustment);
ClassDB::bind_method(D_METHOD("environment_set_ssr", "env", "enable", "max_steps", "fade_in", "fade_out", "depth_tolerance", "roughness"), &VisualServer::environment_set_ssr);
- ClassDB::bind_method(D_METHOD("environment_set_ssao", "env", "enable", "radius", "intensity", "radius2", "intensity2", "bias", "light_affect", "color", "quality", "blur", "bilateral_sharpness"), &VisualServer::environment_set_ssao);
+ ClassDB::bind_method(D_METHOD("environment_set_ssao", "env", "enable", "radius", "intensity", "radius2", "intensity2", "bias", "light_affect", "ao_channel_affect", "color", "quality", "blur", "bilateral_sharpness"), &VisualServer::environment_set_ssao);
ClassDB::bind_method(D_METHOD("environment_set_fog", "env", "enable", "color", "sun_color", "sun_amount"), &VisualServer::environment_set_fog);
ClassDB::bind_method(D_METHOD("environment_set_fog_depth", "env", "enable", "depth_begin", "depth_curve", "transmit", "transmit_curve"), &VisualServer::environment_set_fog_depth);
ClassDB::bind_method(D_METHOD("environment_set_fog_height", "env", "enable", "min_height", "max_height", "height_curve"), &VisualServer::environment_set_fog_height);
@@ -2059,13 +2063,17 @@ void VisualServer::_bind_methods() {
BIND_ENUM_CONSTANT(CUBEMAP_FRONT);
BIND_ENUM_CONSTANT(CUBEMAP_BACK);
+ BIND_ENUM_CONSTANT(TEXTURE_TYPE_2D);
+ BIND_ENUM_CONSTANT(TEXTURE_TYPE_CUBEMAP);
+ BIND_ENUM_CONSTANT(TEXTURE_TYPE_2D_ARRAY);
+ BIND_ENUM_CONSTANT(TEXTURE_TYPE_3D);
+
BIND_ENUM_CONSTANT(TEXTURE_FLAG_MIPMAPS);
BIND_ENUM_CONSTANT(TEXTURE_FLAG_REPEAT);
BIND_ENUM_CONSTANT(TEXTURE_FLAG_FILTER);
BIND_ENUM_CONSTANT(TEXTURE_FLAG_ANISOTROPIC_FILTER);
BIND_ENUM_CONSTANT(TEXTURE_FLAG_CONVERT_TO_LINEAR);
BIND_ENUM_CONSTANT(TEXTURE_FLAG_MIRRORED_REPEAT);
- BIND_ENUM_CONSTANT(TEXTURE_FLAG_CUBEMAP);
BIND_ENUM_CONSTANT(TEXTURE_FLAG_USED_FOR_STREAMING);
BIND_ENUM_CONSTANT(TEXTURE_FLAGS_DEFAULT);
@@ -2201,7 +2209,7 @@ void VisualServer::_bind_methods() {
BIND_ENUM_CONSTANT(INSTANCE_GEOMETRY_MASK);
BIND_ENUM_CONSTANT(INSTANCE_FLAG_USE_BAKED_LIGHT);
- BIND_ENUM_CONSTANT(INSTANCE_FLAG_REDRAW_FRAME_IF_VISIBLE);
+ BIND_ENUM_CONSTANT(INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE);
BIND_ENUM_CONSTANT(INSTANCE_FLAG_MAX);
BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_OFF);
diff --git a/servers/visual_server.h b/servers/visual_server.h
index 367642b7d4..0ec902c18c 100644
--- a/servers/visual_server.h
+++ b/servers/visual_server.h
@@ -90,11 +90,17 @@ public:
TEXTURE_FLAG_ANISOTROPIC_FILTER = 8,
TEXTURE_FLAG_CONVERT_TO_LINEAR = 16,
TEXTURE_FLAG_MIRRORED_REPEAT = 32, /// Repeat texture, with alternate sections mirrored
- TEXTURE_FLAG_CUBEMAP = 2048,
- TEXTURE_FLAG_USED_FOR_STREAMING = 4096,
+ TEXTURE_FLAG_USED_FOR_STREAMING = 2048,
TEXTURE_FLAGS_DEFAULT = TEXTURE_FLAG_REPEAT | TEXTURE_FLAG_MIPMAPS | TEXTURE_FLAG_FILTER
};
+ enum TextureType {
+ TEXTURE_TYPE_2D,
+ TEXTURE_TYPE_CUBEMAP,
+ TEXTURE_TYPE_2D_ARRAY,
+ TEXTURE_TYPE_3D,
+ };
+
enum CubeMapSide {
CUBEMAP_LEFT,
@@ -107,17 +113,33 @@ public:
virtual RID texture_create() = 0;
RID texture_create_from_image(const Ref<Image> &p_image, uint32_t p_flags = TEXTURE_FLAGS_DEFAULT); // helper
- virtual void texture_allocate(RID p_texture, int p_width, int p_height, Image::Format p_format, uint32_t p_flags = TEXTURE_FLAGS_DEFAULT) = 0;
- virtual void texture_set_data(RID p_texture, const Ref<Image> &p_image, CubeMapSide p_cube_side = CUBEMAP_LEFT) = 0;
- virtual void texture_set_data_partial(RID p_texture, const Ref<Image> &p_image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int p_dst_mip, CubeMapSide p_cube_side = CUBEMAP_LEFT) = 0;
- virtual Ref<Image> texture_get_data(RID p_texture, CubeMapSide p_cube_side = CUBEMAP_LEFT) const = 0;
+ virtual void texture_allocate(RID p_texture,
+ int p_width,
+ int p_height,
+ int p_depth_3d,
+ Image::Format p_format,
+ TextureType p_type,
+ uint32_t p_flags = TEXTURE_FLAGS_DEFAULT) = 0;
+
+ virtual void texture_set_data(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) = 0;
+ virtual void texture_set_data_partial(RID p_texture,
+ const Ref<Image> &p_image,
+ int src_x, int src_y,
+ int src_w, int src_h,
+ int dst_x, int dst_y,
+ int p_dst_mip,
+ int p_layer = 0) = 0;
+
+ virtual Ref<Image> texture_get_data(RID p_texture, int p_layer = 0) const = 0;
virtual void texture_set_flags(RID p_texture, uint32_t p_flags) = 0;
virtual uint32_t texture_get_flags(RID p_texture) const = 0;
virtual Image::Format texture_get_format(RID p_texture) const = 0;
+ virtual TextureType texture_get_type(RID p_texture) const = 0;
virtual uint32_t texture_get_texid(RID p_texture) const = 0;
virtual uint32_t texture_get_width(RID p_texture) const = 0;
virtual uint32_t texture_get_height(RID p_texture) const = 0;
- virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) = 0;
+ virtual uint32_t texture_get_depth(RID p_texture) const = 0;
+ virtual void texture_set_size_override(RID p_texture, int p_width, int p_height, int p_depth_3d) = 0;
virtual void texture_set_path(RID p_texture, const String &p_path) = 0;
virtual String texture_get_path(RID p_texture) const = 0;
@@ -132,7 +154,9 @@ public:
struct TextureInfo {
RID texture;
- Size2 size;
+ uint32_t width;
+ uint32_t height;
+ uint32_t depth;
Image::Format format;
int bytes;
String path;
@@ -809,7 +833,7 @@ public:
enum InstanceFlags {
INSTANCE_FLAG_USE_BAKED_LIGHT,
- INSTANCE_FLAG_REDRAW_FRAME_IF_VISIBLE,
+ INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE,
INSTANCE_FLAG_MAX
};
@@ -955,7 +979,7 @@ public:
/* EVENT QUEUING */
- virtual void draw(bool p_swap_buffers = true) = 0;
+ virtual void draw(bool p_swap_buffers = true, double frame_step = 0.0) = 0;
virtual void sync() = 0;
virtual bool has_changed() const = 0;
virtual void init() = 0;
@@ -1054,6 +1078,7 @@ VARIANT_ENUM_CAST(VisualServer::EnvironmentSSAOQuality);
VARIANT_ENUM_CAST(VisualServer::EnvironmentSSAOBlur);
VARIANT_ENUM_CAST(VisualServer::InstanceFlags);
VARIANT_ENUM_CAST(VisualServer::ShadowCastingSetting);
+VARIANT_ENUM_CAST(VisualServer::TextureType);
//typedef VisualServer VS; // makes it easier to use
#define VS VisualServer