summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/SCsub1
-rw-r--r--drivers/rtaudio/audio_driver_rtaudio.cpp76
-rw-r--r--drivers/unix/os_unix.cpp4
-rw-r--r--drivers/unix/thread_posix.cpp15
-rw-r--r--drivers/unix/thread_posix.h3
-rw-r--r--drivers/wasapi/SCsub8
-rw-r--r--drivers/wasapi/audio_driver_wasapi.cpp351
-rw-r--r--drivers/wasapi/audio_driver_wasapi.h89
-rw-r--r--editor/editor_settings.cpp1
-rw-r--r--editor/import/editor_scene_importer_gltf.cpp3
-rw-r--r--editor/plugins/polygon_2d_editor_plugin.cpp22
-rw-r--r--editor/project_settings_editor.cpp9
-rw-r--r--editor/project_settings_editor.h1
-rw-r--r--editor/spatial_editor_gizmos.cpp80
-rw-r--r--editor/spatial_editor_gizmos.h1
-rw-r--r--main/main.cpp7
-rw-r--r--main/main.h3
-rw-r--r--platform/android/export/export.cpp12
-rw-r--r--platform/android/java_glue.cpp4
-rw-r--r--platform/android/thread_jandroid.cpp15
-rw-r--r--platform/android/thread_jandroid.h3
-rw-r--r--platform/windows/detect.py4
-rw-r--r--platform/windows/os_windows.cpp3
-rw-r--r--platform/windows/os_windows.h4
-rw-r--r--scene/2d/light_2d.cpp2
-rw-r--r--servers/visual/visual_server_canvas.cpp14
26 files changed, 628 insertions, 107 deletions
diff --git a/drivers/SCsub b/drivers/SCsub
index 73a3f7898a..b8bba91378 100644
--- a/drivers/SCsub
+++ b/drivers/SCsub
@@ -16,6 +16,7 @@ SConscript('alsa/SCsub')
SConscript('pulseaudio/SCsub')
if (env["platform"] == "windows"):
SConscript("rtaudio/SCsub")
+ SConscript("wasapi/SCsub")
if (env["xaudio2"] == "yes"):
SConscript("xaudio2/SCsub")
diff --git a/drivers/rtaudio/audio_driver_rtaudio.cpp b/drivers/rtaudio/audio_driver_rtaudio.cpp
index 8e52b53ad6..7de3ff192e 100644
--- a/drivers/rtaudio/audio_driver_rtaudio.cpp
+++ b/drivers/rtaudio/audio_driver_rtaudio.cpp
@@ -104,21 +104,14 @@ Error AudioDriverRtAudio::init() {
RtAudio::StreamOptions options;
// set the desired numberOfBuffers
- unsigned int target_number_of_buffers = 4;
- options.numberOfBuffers = target_number_of_buffers;
-
- //options.
- //RtAudioStreamFlags flags; /*!< A bit-mask of stream flags (RTAUDIO_NONINTERLEAVED, RTAUDIO_MINIMIZE_LATENCY, RTAUDIO_HOG_DEVICE). *///
- //unsigned int numberOfBuffers; /*!< Number of stream buffers. */
- //std::string streamName; /*!< A stream name (currently used only in Jack). */
- //int priority; /*!< Scheduling priority of callback thread (only used with flag RTAUDIO_SCHEDULE_REALTIME). */
+ options.numberOfBuffers = 4;
parameters.firstChannel = 0;
mix_rate = GLOBAL_DEF("audio/mix_rate", 44100);
int latency = GLOBAL_DEF("audio/output_latency", 25);
- // calculate desired buffer_size, taking the desired numberOfBuffers into account (latency depends on numberOfBuffers*buffer_size)
- unsigned int buffer_size = closest_power_of_2(latency * mix_rate / 1000 / target_number_of_buffers);
+ // calculate desired buffer_size
+ unsigned int buffer_size = closest_power_of_2(latency * mix_rate / 1000);
if (OS::get_singleton()->is_stdout_verbose()) {
print_line("audio buffer size: " + itos(buffer_size));
@@ -126,56 +119,28 @@ Error AudioDriverRtAudio::init() {
short int tries = 2;
- while (true) {
- while (true) {
- switch (speaker_mode) {
- case SPEAKER_MODE_STEREO: parameters.nChannels = 2; break;
- case SPEAKER_SURROUND_51: parameters.nChannels = 6; break;
- case SPEAKER_SURROUND_71: parameters.nChannels = 8; break;
- };
-
- try {
- dac->openStream(&parameters, NULL, RTAUDIO_SINT32, mix_rate, &buffer_size, &callback, this, &options);
- active = true;
-
- break;
- } catch (RtAudioError &e) {
- // try with less channels
- ERR_PRINT("Unable to open audio, retrying with fewer channels..");
-
- switch (speaker_mode) {
- case SPEAKER_MODE_STEREO: speaker_mode = SPEAKER_MODE_STEREO; break;
- case SPEAKER_SURROUND_51: speaker_mode = SPEAKER_SURROUND_51; break;
- case SPEAKER_SURROUND_71: speaker_mode = SPEAKER_SURROUND_71; break;
- };
- }
- }
+ while (tries >= 0) {
+ switch (speaker_mode) {
+ case SPEAKER_MODE_STEREO: parameters.nChannels = 2; break;
+ case SPEAKER_SURROUND_51: parameters.nChannels = 6; break;
+ case SPEAKER_SURROUND_71: parameters.nChannels = 8; break;
+ };
- // compare actual numberOfBuffers with the desired one. If not equal, close and reopen the stream with adjusted buffer size, so the desired output_latency is still correct
- if (target_number_of_buffers != options.numberOfBuffers) {
- if (tries <= 0) {
- ERR_EXPLAIN("RtAudio: Unable to set correct number of buffers.");
- ERR_FAIL_V(ERR_UNAVAILABLE);
- break;
- }
+ try {
+ dac->openStream(&parameters, NULL, RTAUDIO_SINT32, mix_rate, &buffer_size, &callback, this, &options);
+ active = true;
- try {
- dac->closeStream();
- active = false;
- } catch (RtAudioError &e) {
- ERR_PRINT(e.what());
- ERR_FAIL_V(ERR_UNAVAILABLE);
- break;
+ break;
+ } catch (RtAudioError &e) {
+ // try with less channels
+ ERR_PRINT("Unable to open audio, retrying with fewer channels..");
+
+ switch (speaker_mode) {
+ case SPEAKER_SURROUND_51: speaker_mode = SPEAKER_MODE_STEREO; break;
+ case SPEAKER_SURROUND_71: speaker_mode = SPEAKER_SURROUND_51; break;
}
- if (OS::get_singleton()->is_stdout_verbose())
- print_line("RtAudio: Desired number of buffers (" + itos(target_number_of_buffers) + ") not available. Using " + itos(options.numberOfBuffers) + " instead. Reopening stream with adjusted buffer_size.");
- // new buffer size dependent on the ratio between set and actual numberOfBuffers
- buffer_size = buffer_size / (options.numberOfBuffers / target_number_of_buffers);
- target_number_of_buffers = options.numberOfBuffers;
tries--;
- } else {
- break;
}
}
@@ -231,6 +196,7 @@ void AudioDriverRtAudio::finish() {
AudioDriverRtAudio::AudioDriverRtAudio() {
+ active = false;
mutex = NULL;
dac = NULL;
mix_rate = 44100;
diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp
index 992b12b7cd..75c8a153f6 100644
--- a/drivers/unix/os_unix.cpp
+++ b/drivers/unix/os_unix.cpp
@@ -315,7 +315,9 @@ OS::TimeZoneInfo OS_Unix::get_time_zone_info() const {
void OS_Unix::delay_usec(uint32_t p_usec) const {
- usleep(p_usec);
+ struct timespec rem = { p_usec / 1000000, (p_usec % 1000000) * 1000 };
+ while (nanosleep(&rem, &rem) == EINTR) {
+ }
}
uint64_t OS_Unix::get_ticks_usec() const {
diff --git a/drivers/unix/thread_posix.cpp b/drivers/unix/thread_posix.cpp
index 2dd0b4a70a..5908246929 100644
--- a/drivers/unix/thread_posix.cpp
+++ b/drivers/unix/thread_posix.cpp
@@ -36,8 +36,18 @@
#include <pthread_np.h>
#endif
+#include "core/safe_refcount.h"
#include "os/memory.h"
+static pthread_key_t _create_thread_id_key() {
+ pthread_key_t key;
+ pthread_key_create(&key, NULL);
+ return key;
+}
+
+pthread_key_t ThreadPosix::thread_id_key = _create_thread_id_key();
+Thread::ID ThreadPosix::next_thread_id = 0;
+
Thread::ID ThreadPosix::get_id() const {
return id;
@@ -51,7 +61,8 @@ Thread *ThreadPosix::create_thread_posix() {
void *ThreadPosix::thread_callback(void *userdata) {
ThreadPosix *t = reinterpret_cast<ThreadPosix *>(userdata);
- t->id = (ID)pthread_self();
+ t->id = atomic_increment(&next_thread_id);
+ pthread_setspecific(thread_id_key, (void *)t->id);
ScriptServer::thread_enter(); //scripts may need to attach a stack
@@ -77,7 +88,7 @@ Thread *ThreadPosix::create_func_posix(ThreadCreateCallback p_callback, void *p_
}
Thread::ID ThreadPosix::get_thread_id_func_posix() {
- return (ID)pthread_self();
+ return (ID)pthread_getspecific(thread_id_key);
}
void ThreadPosix::wait_to_finish_func_posix(Thread *p_thread) {
diff --git a/drivers/unix/thread_posix.h b/drivers/unix/thread_posix.h
index a188d9c346..d6a41ed119 100644
--- a/drivers/unix/thread_posix.h
+++ b/drivers/unix/thread_posix.h
@@ -42,6 +42,9 @@
class ThreadPosix : public Thread {
+ static pthread_key_t thread_id_key;
+ static ID next_thread_id;
+
pthread_t pthread;
pthread_attr_t pthread_attr;
ThreadCreateCallback callback;
diff --git a/drivers/wasapi/SCsub b/drivers/wasapi/SCsub
new file mode 100644
index 0000000000..233593b0f9
--- /dev/null
+++ b/drivers/wasapi/SCsub
@@ -0,0 +1,8 @@
+#!/usr/bin/env python
+
+Import('env')
+
+# Driver source files
+env.add_source_files(env.drivers_sources, "*.cpp")
+
+Export('env')
diff --git a/drivers/wasapi/audio_driver_wasapi.cpp b/drivers/wasapi/audio_driver_wasapi.cpp
new file mode 100644
index 0000000000..6e01b5f524
--- /dev/null
+++ b/drivers/wasapi/audio_driver_wasapi.cpp
@@ -0,0 +1,351 @@
+/*************************************************************************/
+/* audio_driver_wasapi.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 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. */
+/*************************************************************************/
+#ifdef WASAPI_ENABLED
+
+#include "audio_driver_wasapi.h"
+
+#include "os/os.h"
+#include "project_settings.h"
+
+const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator);
+const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator);
+const IID IID_IAudioClient = __uuidof(IAudioClient);
+const IID IID_IAudioRenderClient = __uuidof(IAudioRenderClient);
+
+Error AudioDriverWASAPI::init_device() {
+
+ WAVEFORMATEX *pwfex;
+ IMMDeviceEnumerator *enumerator = NULL;
+ IMMDevice *device = NULL;
+
+ CoInitialize(NULL);
+
+ HRESULT hr = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void **)&enumerator);
+ ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
+
+ hr = enumerator->GetDefaultAudioEndpoint(eRender, eConsole, &device);
+ ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
+
+ hr = device->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, (void **)&audio_client);
+ ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
+
+ hr = audio_client->GetMixFormat(&pwfex);
+ ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
+
+ // Since we're using WASAPI Shared Mode we can't control any of these, we just tag along
+ channels = pwfex->nChannels;
+ mix_rate = pwfex->nSamplesPerSec;
+ format_tag = pwfex->wFormatTag;
+ bits_per_sample = pwfex->wBitsPerSample;
+
+ if (format_tag == WAVE_FORMAT_EXTENSIBLE) {
+ WAVEFORMATEXTENSIBLE *wfex = (WAVEFORMATEXTENSIBLE *)pwfex;
+
+ if (wfex->SubFormat == KSDATAFORMAT_SUBTYPE_PCM) {
+ format_tag = WAVE_FORMAT_PCM;
+ } else if (wfex->SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT) {
+ format_tag = WAVE_FORMAT_IEEE_FLOAT;
+ } else {
+ ERR_PRINT("WASAPI: Format not supported");
+ ERR_FAIL_V(ERR_CANT_OPEN);
+ }
+ } else {
+ if (format_tag != WAVE_FORMAT_PCM && format_tag != WAVE_FORMAT_IEEE_FLOAT) {
+ ERR_PRINT("WASAPI: Format not supported");
+ ERR_FAIL_V(ERR_CANT_OPEN);
+ }
+ }
+
+ int latency = GLOBAL_DEF("audio/output_latency", 25);
+ buffer_size = closest_power_of_2(latency * mix_rate / 1000);
+
+ if (OS::get_singleton()->is_stdout_verbose()) {
+ print_line("audio buffer size: " + itos(buffer_size));
+ }
+
+ hr = audio_client->Initialize(AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK, 0, 0, pwfex, NULL);
+ ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
+
+ event = CreateEvent(NULL, FALSE, FALSE, NULL);
+ ERR_FAIL_COND_V(event == NULL, ERR_CANT_OPEN);
+
+ hr = audio_client->SetEventHandle(event);
+ ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
+
+ hr = audio_client->GetService(IID_IAudioRenderClient, (void **)&render_client);
+ ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
+
+ hr = audio_client->GetBufferSize(&max_frames);
+ ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
+
+ samples_in.resize(buffer_size);
+ buffer_frames = buffer_size / channels;
+
+ return OK;
+}
+
+Error AudioDriverWASAPI::finish_device() {
+
+ if (audio_client) {
+ if (active) {
+ audio_client->Stop();
+ active = false;
+ }
+ }
+
+ if (render_client) {
+ render_client->Release();
+ render_client = NULL;
+ }
+
+ if (audio_client) {
+ audio_client->Release();
+ audio_client = NULL;
+ }
+
+ return OK;
+}
+
+Error AudioDriverWASAPI::init() {
+
+ Error err = init_device();
+ ERR_FAIL_COND_V(err != OK, err);
+
+ active = false;
+ exit_thread = false;
+ thread_exited = false;
+
+ mutex = Mutex::create(true);
+ thread = Thread::create(thread_func, this);
+
+ return OK;
+}
+
+Error AudioDriverWASAPI::reopen() {
+ Error err = finish_device();
+ if (err != OK) {
+ ERR_PRINT("WASAPI: finish_device error");
+ } else {
+ err = init_device();
+ if (err != OK) {
+ ERR_PRINT("WASAPI: init_device error");
+ } else {
+ start();
+ }
+ }
+
+ return err;
+}
+
+int AudioDriverWASAPI::get_mix_rate() const {
+
+ return mix_rate;
+}
+
+AudioDriver::SpeakerMode AudioDriverWASAPI::get_speaker_mode() const {
+
+ return SPEAKER_MODE_STEREO;
+}
+
+void AudioDriverWASAPI::thread_func(void *p_udata) {
+
+ AudioDriverWASAPI *ad = (AudioDriverWASAPI *)p_udata;
+
+ while (!ad->exit_thread) {
+ if (ad->active) {
+ ad->lock();
+
+ ad->audio_server_process(ad->buffer_frames, ad->samples_in.ptr());
+
+ ad->unlock();
+ } else {
+ for (unsigned int i = 0; i < ad->buffer_size; i++) {
+ ad->samples_in[i] = 0;
+ }
+ }
+
+ unsigned int left_frames = ad->buffer_frames;
+ unsigned int buffer_idx = 0;
+ while (left_frames > 0) {
+ WaitForSingleObject(ad->event, 1000);
+
+ UINT32 cur_frames;
+ HRESULT hr = ad->audio_client->GetCurrentPadding(&cur_frames);
+ if (hr == S_OK) {
+ // Check how much frames are available on the WASAPI buffer
+ UINT32 avail_frames = ad->max_frames - cur_frames;
+ UINT32 write_frames = avail_frames > left_frames ? left_frames : avail_frames;
+
+ BYTE *buffer = NULL;
+ hr = ad->render_client->GetBuffer(write_frames, &buffer);
+ if (hr == S_OK) {
+ // We're using WASAPI Shared Mode so we must convert the buffer
+
+ if (ad->format_tag == WAVE_FORMAT_PCM) {
+ switch (ad->bits_per_sample) {
+ case 8:
+ for (unsigned int i = 0; i < write_frames * ad->channels; i++) {
+ ((int8_t *)buffer)[i] = ad->samples_in[buffer_idx++] >> 24;
+ }
+ break;
+
+ case 16:
+ for (unsigned int i = 0; i < write_frames * ad->channels; i++) {
+ ((int16_t *)buffer)[i] = ad->samples_in[buffer_idx++] >> 16;
+ }
+ break;
+
+ case 24:
+ for (unsigned int i = 0; i < write_frames * ad->channels; i++) {
+ int32_t sample = ad->samples_in[buffer_idx++];
+ ((int8_t *)buffer)[i * 3 + 2] = sample >> 24;
+ ((int8_t *)buffer)[i * 3 + 1] = sample >> 16;
+ ((int8_t *)buffer)[i * 3 + 0] = sample >> 8;
+ }
+ break;
+
+ case 32:
+ for (unsigned int i = 0; i < write_frames * ad->channels; i++) {
+ ((int32_t *)buffer)[i] = ad->samples_in[buffer_idx++];
+ }
+ break;
+ }
+ } else if (ad->format_tag == WAVE_FORMAT_IEEE_FLOAT) {
+ for (unsigned int i = 0; i < write_frames * ad->channels; i++) {
+ ((float *)buffer)[i] = (ad->samples_in[buffer_idx++] >> 16) / 32768.f;
+ }
+ } else {
+ ERR_PRINT("WASAPI: Unknown format tag");
+ ad->exit_thread = true;
+ }
+
+ hr = ad->render_client->ReleaseBuffer(write_frames, 0);
+ if (hr != S_OK) {
+ ERR_PRINT("WASAPI: Release buffer error");
+ }
+
+ left_frames -= write_frames;
+ } else if (hr == AUDCLNT_E_DEVICE_INVALIDATED) {
+ // Device is not valid anymore, reopen it
+
+ Error err = ad->reopen();
+ if (err != OK) {
+ ad->exit_thread = true;
+ } else {
+ // We reopened the device and samples_in may have resized, so invalidate the current left_frames
+ left_frames = 0;
+ }
+ } else {
+ ERR_PRINT("WASAPI: Get buffer error");
+ ad->exit_thread = true;
+ }
+ } else if (hr == AUDCLNT_E_DEVICE_INVALIDATED) {
+ // Device is not valid anymore, reopen it
+
+ Error err = ad->reopen();
+ if (err != OK) {
+ ad->exit_thread = true;
+ } else {
+ // We reopened the device and samples_in may have resized, so invalidate the current left_frames
+ left_frames = 0;
+ }
+ } else {
+ ERR_PRINT("WASAPI: GetCurrentPadding error");
+ }
+ }
+ }
+
+ ad->thread_exited = true;
+}
+
+void AudioDriverWASAPI::start() {
+
+ HRESULT hr = audio_client->Start();
+ if (hr != S_OK) {
+ ERR_PRINT("WASAPI: Start failed");
+ } else {
+ active = true;
+ }
+}
+
+void AudioDriverWASAPI::lock() {
+
+ if (mutex)
+ mutex->lock();
+}
+
+void AudioDriverWASAPI::unlock() {
+
+ if (mutex)
+ mutex->unlock();
+}
+
+void AudioDriverWASAPI::finish() {
+
+ if (thread) {
+ exit_thread = true;
+ Thread::wait_to_finish(thread);
+
+ memdelete(thread);
+ thread = NULL;
+ }
+
+ finish_device();
+
+ if (mutex) {
+ memdelete(mutex);
+ mutex = NULL;
+ }
+}
+
+AudioDriverWASAPI::AudioDriverWASAPI() {
+
+ audio_client = NULL;
+ render_client = NULL;
+ mutex = NULL;
+ thread = NULL;
+
+ max_frames = 0;
+ format_tag = 0;
+ bits_per_sample = 0;
+
+ samples_in.clear();
+
+ buffer_size = 0;
+ channels = 0;
+ mix_rate = 0;
+ buffer_frames = 0;
+
+ thread_exited = false;
+ exit_thread = false;
+ active = false;
+}
+
+#endif
diff --git a/drivers/wasapi/audio_driver_wasapi.h b/drivers/wasapi/audio_driver_wasapi.h
new file mode 100644
index 0000000000..b91751f87e
--- /dev/null
+++ b/drivers/wasapi/audio_driver_wasapi.h
@@ -0,0 +1,89 @@
+/*************************************************************************/
+/* audio_driver_wasapi.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 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 AUDIO_DRIVER_WASAPI_H
+#define AUDIO_DRIVER_WASAPI_H
+
+#ifdef WASAPI_ENABLED
+
+#include "core/os/mutex.h"
+#include "core/os/thread.h"
+#include "servers/audio_server.h"
+
+#include <audioclient.h>
+#include <mmdeviceapi.h>
+#include <windows.h>
+
+class AudioDriverWASAPI : public AudioDriver {
+
+ HANDLE event;
+ IAudioClient *audio_client;
+ IAudioRenderClient *render_client;
+ Mutex *mutex;
+ Thread *thread;
+
+ UINT32 max_frames;
+ WORD format_tag;
+ WORD bits_per_sample;
+
+ Vector<int32_t> samples_in;
+
+ unsigned int buffer_size;
+ unsigned int channels;
+ int mix_rate;
+ int buffer_frames;
+
+ bool thread_exited;
+ mutable bool exit_thread;
+ bool active;
+
+ static void thread_func(void *p_udata);
+
+ Error init_device();
+ Error finish_device();
+ Error reopen();
+
+public:
+ virtual const char *get_name() const {
+ return "WASAPI";
+ }
+
+ virtual Error init();
+ virtual void start();
+ virtual int get_mix_rate() const;
+ virtual SpeakerMode get_speaker_mode() const;
+ virtual void lock();
+ virtual void unlock();
+ virtual void finish();
+
+ AudioDriverWASAPI();
+};
+
+#endif // AUDIO_DRIVER_WASAPI_H
+#endif
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index b9a6414b08..6398bd1623 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -694,6 +694,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
set("editors/2d/pan_speed", 20);
set("editors/poly_editor/point_grab_radius", 8);
+ set("editors/poly_editor/show_previous_outline", true);
set("run/window_placement/rect", 1);
hints["run/window_placement/rect"] = PropertyInfo(Variant::INT, "run/window_placement/rect", PROPERTY_HINT_ENUM, "Top Left,Centered,Custom Position,Force Maximized,Force Fullscreen");
diff --git a/editor/import/editor_scene_importer_gltf.cpp b/editor/import/editor_scene_importer_gltf.cpp
index 1c42bcef8a..2f03e72851 100644
--- a/editor/import/editor_scene_importer_gltf.cpp
+++ b/editor/import/editor_scene_importer_gltf.cpp
@@ -1216,7 +1216,7 @@ Error EditorSceneImporterGLTF::_parse_materials(GLTFState &state) {
if (bct.has("index")) {
Ref<Texture> t = _get_texture(state, bct["index"]);
material->set_texture(SpatialMaterial::TEXTURE_METALLIC, t);
- material->set_metallic_texture_channel(SpatialMaterial::TEXTURE_CHANNEL_RED);
+ material->set_metallic_texture_channel(SpatialMaterial::TEXTURE_CHANNEL_BLUE);
material->set_texture(SpatialMaterial::TEXTURE_ROUGHNESS, t);
material->set_roughness_texture_channel(SpatialMaterial::TEXTURE_CHANNEL_GREEN);
if (!mr.has("metallicFactor")) {
@@ -1243,6 +1243,7 @@ Error EditorSceneImporterGLTF::_parse_materials(GLTFState &state) {
Dictionary bct = d["occlusionTexture"];
if (bct.has("index")) {
material->set_texture(SpatialMaterial::TEXTURE_AMBIENT_OCCLUSION, _get_texture(state, bct["index"]));
+ material->set_ao_texture_channel(SpatialMaterial::TEXTURE_CHANNEL_RED);
material->set_feature(SpatialMaterial::FEATURE_AMBIENT_OCCLUSION, true);
}
}
diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp
index 88158d4b20..d04184f055 100644
--- a/editor/plugins/polygon_2d_editor_plugin.cpp
+++ b/editor/plugins/polygon_2d_editor_plugin.cpp
@@ -402,6 +402,11 @@ bool Polygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
cpoint = canvas_item_editor->snap_point(cpoint);
edited_point_pos = node->get_global_transform().affine_inverse().xform(cpoint);
+ Vector<Vector2> poly = Variant(node->get_polygon());
+ ERR_FAIL_INDEX_V(edited_point, poly.size(), false);
+ poly[edited_point] = edited_point_pos - node->get_offset();
+ node->set_polygon(Variant(poly));
+
canvas_item_editor->get_viewport_control()->update();
}
}
@@ -425,6 +430,23 @@ void Polygon2DEditor::_canvas_draw() {
Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
Ref<Texture> handle = get_icon("EditorHandle", "EditorIcons");
+ if (edited_point >= 0 && EDITOR_DEF("editors/poly_editor/show_previous_outline", true)) {
+
+ const Color col = node->get_color().contrasted();
+ const int n = pre_move_edit.size();
+ for (int i = 0; i < n; i++) {
+
+ Vector2 p, p2;
+ p = pre_move_edit[i] + node->get_offset();
+ p2 = pre_move_edit[(i + 1) % n] + node->get_offset();
+
+ Vector2 point = xform.xform(p);
+ Vector2 next_point = xform.xform(p2);
+
+ vpc->draw_line(point, next_point, col, 2);
+ }
+ }
+
for (int i = 0; i < poly.size(); i++) {
Vector2 p, p2;
diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp
index 58ac5bc561..94fce45733 100644
--- a/editor/project_settings_editor.cpp
+++ b/editor/project_settings_editor.cpp
@@ -866,6 +866,12 @@ void ProjectSettingsEditor::_save() {
message->popup_centered(Size2(300, 100) * EDSCALE);
}
+void ProjectSettingsEditor::_settings_prop_edited(const String &p_name) {
+
+ // Method needed to discard the mandatory argument of the property_edited signal
+ _settings_changed();
+}
+
void ProjectSettingsEditor::_settings_changed() {
timer->start();
@@ -1334,6 +1340,7 @@ void ProjectSettingsEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("_add_item"), &ProjectSettingsEditor::_add_item, DEFVAL(Variant()));
ClassDB::bind_method(D_METHOD("_device_input_add"), &ProjectSettingsEditor::_device_input_add);
ClassDB::bind_method(D_METHOD("_press_a_key_confirm"), &ProjectSettingsEditor::_press_a_key_confirm);
+ ClassDB::bind_method(D_METHOD("_settings_prop_edited"), &ProjectSettingsEditor::_settings_prop_edited);
ClassDB::bind_method(D_METHOD("_copy_to_platform"), &ProjectSettingsEditor::_copy_to_platform);
ClassDB::bind_method(D_METHOD("_update_translations"), &ProjectSettingsEditor::_update_translations);
ClassDB::bind_method(D_METHOD("_translation_delete"), &ProjectSettingsEditor::_translation_delete);
@@ -1448,7 +1455,7 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
globals_editor->register_search_box(search_box);
globals_editor->get_property_editor()->get_scene_tree()->connect("cell_selected", this, "_item_selected");
globals_editor->get_property_editor()->connect("property_toggled", this, "_item_checked", varray(), CONNECT_DEFERRED);
- globals_editor->get_property_editor()->connect("property_edited", this, "_settings_changed");
+ globals_editor->get_property_editor()->connect("property_edited", this, "_settings_prop_edited");
Button *del = memnew(Button);
hbc->add_child(del);
diff --git a/editor/project_settings_editor.h b/editor/project_settings_editor.h
index c8c5e3265b..e4e2345692 100644
--- a/editor/project_settings_editor.h
+++ b/editor/project_settings_editor.h
@@ -121,6 +121,7 @@ class ProjectSettingsEditor : public AcceptDialog {
void _press_a_key_confirm();
void _show_last_added(const Ref<InputEvent> &p_event, const String &p_name);
+ void _settings_prop_edited(const String &p_name);
void _settings_changed();
void _copy_to_platform(int p_which);
diff --git a/editor/spatial_editor_gizmos.cpp b/editor/spatial_editor_gizmos.cpp
index fb5143b486..be30369dfe 100644
--- a/editor/spatial_editor_gizmos.cpp
+++ b/editor/spatial_editor_gizmos.cpp
@@ -36,6 +36,7 @@
#include "scene/resources/capsule_shape.h"
#include "scene/resources/convex_polygon_shape.h"
#include "scene/resources/plane_shape.h"
+#include "scene/resources/primitive_meshes.h"
#include "scene/resources/ray_shape.h"
#include "scene/resources/sphere_shape.h"
#include "scene/resources/surface_tool.h"
@@ -130,9 +131,9 @@ void EditorSpatialGizmo::add_lines(const Vector<Vector3> &p_lines, const Ref<Mat
PoolVector<Color>::Write w = color.write();
for (int i = 0; i < p_lines.size(); i++) {
if (is_selected())
- w[i] = Color(1, 1, 1, 0.6);
+ w[i] = Color(1, 1, 1, 0.8);
else
- w[i] = Color(1, 1, 1, 0.25);
+ w[i] = Color(1, 1, 1, 0.2);
}
}
@@ -296,6 +297,15 @@ void EditorSpatialGizmo::add_handles(const Vector<Vector3> &p_handles, bool p_bi
}
}
+void EditorSpatialGizmo::add_solid_box(Ref<Material> &p_material, Vector3 size) {
+ CubeMesh cubem;
+ cubem.set_size(size);
+ Ref<ArrayMesh> m = memnew(ArrayMesh);
+ m->add_surface_from_arrays(cubem.surface_get_primitive_type(0), cubem.surface_get_arrays(0));
+ m->surface_set_material(0, p_material);
+ add_mesh(m);
+}
+
void EditorSpatialGizmo::set_spatial_node(Spatial *p_node) {
ERR_FAIL_NULL(p_node);
@@ -540,8 +550,9 @@ Ref<SpatialMaterial> EditorSpatialGizmo::create_material(const String &p_name, c
if (!is_editable()) {
color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/instanced");
- } else if (!is_selected()) {
- color.a *= 0.5;
+ }
+ if (!is_selected()) {
+ color.a *= 0.3;
}
Ref<SpatialMaterial> line_material;
@@ -587,7 +598,7 @@ Ref<SpatialMaterial> EditorSpatialGizmo::create_icon_material(const String &p_na
if (!is_editable()) {
color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/instanced");
} else if (!is_selected()) {
- color.a *= 0.5;
+ color.a *= 0.3;
}
Ref<SpatialMaterial> icon;
@@ -770,34 +781,32 @@ void LightSpatialGizmo::redraw() {
Ref<Material> material = create_material("light_directional_material", gizmo_color);
Ref<Material> icon = create_icon_material("light_directional_icon", SpatialEditor::get_singleton()->get_icon("GizmoDirectionalLight", "EditorIcons"));
- const int arrow_points = 5;
+ const int arrow_points = 7;
+ const float arrow_length = 1.5;
+
Vector3 arrow[arrow_points] = {
- Vector3(0, 0, 2),
- Vector3(1, 1, 2),
- Vector3(1, 1, -1),
- Vector3(2, 2, -1),
- Vector3(0, 0, -3)
+ Vector3(0, 0, -1),
+ Vector3(0, 0.8, 0),
+ Vector3(0, 0.3, 0),
+ Vector3(0, 0.3, arrow_length),
+ Vector3(0, -0.3, arrow_length),
+ Vector3(0, -0.3, 0),
+ Vector3(0, -0.8, 0)
};
- int arrow_sides = 4;
+ int arrow_sides = 2;
Vector<Vector3> lines;
for (int i = 0; i < arrow_sides; i++) {
+ for (int j = 0; j < arrow_points; j++) {
+ Basis ma(Vector3(0, 0, 1), Math_PI * i / arrow_sides);
- Basis ma(Vector3(0, 0, 1), Math_PI * 2 * float(i) / arrow_sides);
- Basis mb(Vector3(0, 0, 1), Math_PI * 2 * float(i + 1) / arrow_sides);
-
- for (int j = 1; j < arrow_points - 1; j++) {
+ Vector3 v1 = arrow[j] - Vector3(0, 0, arrow_length);
+ Vector3 v2 = arrow[(j + 1) % arrow_points] - Vector3(0, 0, arrow_length);
- if (j != 2) {
- lines.push_back(ma.xform(arrow[j]));
- lines.push_back(ma.xform(arrow[j + 1]));
- }
- if (j < arrow_points - 1) {
- lines.push_back(ma.xform(arrow[j]));
- lines.push_back(mb.xform(arrow[j]));
- }
+ lines.push_back(ma.xform(v1));
+ lines.push_back(ma.xform(v2));
}
}
@@ -2334,6 +2343,14 @@ void ParticlesGizmo::redraw() {
add_lines(lines, material);
add_collision_segments(lines);
+
+ if (is_selected()) {
+
+ gizmo_color.a = 0.1;
+ Ref<Material> solid_material = create_material("particles_solid_material", gizmo_color);
+ add_solid_box(solid_material, aabb.get_size());
+ }
+
//add_unscaled_billboard(SpatialEditorGizmos::singleton->visi,0.05);
add_handles(handles);
}
@@ -2487,6 +2504,14 @@ void ReflectionProbeGizmo::redraw() {
add_lines(lines, material);
add_lines(internal_lines, material_internal);
+
+ if (is_selected()) {
+
+ gizmo_color.a = 0.1;
+ Ref<Material> solid_material = create_material("reflection_probe_solid_material", gizmo_color);
+ add_solid_box(solid_material, probe->get_extents() * 2.0);
+ }
+
//add_unscaled_billboard(SpatialEditorGizmos::singleton->visi,0.05);
add_collision_segments(lines);
add_handles(handles);
@@ -2639,6 +2664,13 @@ void GIProbeGizmo::redraw() {
handles.push_back(ax);
}
+ if (is_selected()) {
+
+ gizmo_color.a = 0.1;
+ Ref<Material> solid_material = create_material("gi_probe_solid_material", gizmo_color);
+ add_solid_box(solid_material, aabb.get_size());
+ }
+
add_handles(handles);
}
GIProbeGizmo::GIProbeGizmo(GIProbe *p_probe) {
diff --git a/editor/spatial_editor_gizmos.h b/editor/spatial_editor_gizmos.h
index a7c7497763..d63a804055 100644
--- a/editor/spatial_editor_gizmos.h
+++ b/editor/spatial_editor_gizmos.h
@@ -102,6 +102,7 @@ protected:
void add_collision_triangles(const Ref<TriangleMesh> &p_tmesh);
void add_unscaled_billboard(const Ref<Material> &p_material, float p_scale = 1);
void add_handles(const Vector<Vector3> &p_handles, bool p_billboard = false, bool p_secondary = false);
+ void add_solid_box(Ref<Material> &p_material, Vector3 size);
void set_spatial_node(Spatial *p_node);
diff --git a/main/main.cpp b/main/main.cpp
index 00cb43b0a8..532b5277b5 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -69,7 +69,6 @@
#include "core/io/file_access_zip.h"
#include "core/io/stream_peer_ssl.h"
#include "core/io/stream_peer_tcp.h"
-#include "core/os/thread.h"
#include "main/input_default.h"
#include "performance.h"
#include "translation.h"
@@ -886,7 +885,11 @@ error:
return ERR_INVALID_PARAMETER;
}
-Error Main::setup2() {
+Error Main::setup2(Thread::ID p_main_tid_override) {
+
+ if (p_main_tid_override) {
+ Thread::_main_thread_id = p_main_tid_override;
+ }
OS::get_singleton()->initialize(video_mode, video_driver_idx, audio_driver_idx);
if (init_use_custom_pos) {
diff --git a/main/main.h b/main/main.h
index f8db0225bf..2c1d42a163 100644
--- a/main/main.h
+++ b/main/main.h
@@ -34,6 +34,7 @@
@author Juan Linietsky <reduzio@gmail.com>
*/
+#include "core/os/thread.h"
#include "error_list.h"
#include "typedefs.h"
@@ -49,7 +50,7 @@ class Main {
public:
static Error setup(const char *execpath, int argc, char *argv[], bool p_second_phase = true);
- static Error setup2();
+ static Error setup2(Thread::ID p_main_tid_override = 0);
static bool start();
static bool iteration();
static void cleanup();
diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp
index eff3a7178d..a554785591 100644
--- a/platform/android/export/export.cpp
+++ b/platform/android/export/export.cpp
@@ -1073,11 +1073,7 @@ public:
//export_temp
ep.step("Exporting APK", 0);
- bool use_adb_over_usb = bool(EDITOR_DEF("export/android/use_remote_debug_over_adb", true));
-
- if (use_adb_over_usb) {
- p_debug_flags |= DEBUG_FLAG_REMOTE_DEBUG_LOCALHOST;
- }
+ p_debug_flags |= DEBUG_FLAG_REMOTE_DEBUG_LOCALHOST;
String export_to = EditorSettings::get_singleton()->get_settings_path() + "/tmp/tmpexport.apk";
Error err = export_project(p_preset, true, export_to, p_debug_flags);
@@ -1123,7 +1119,7 @@ public:
return ERR_CANT_CREATE;
}
- if (use_adb_over_usb) {
+ if (p_debug_flags & DEBUG_FLAG_REMOTE_DEBUG) {
args.clear();
args.push_back("-s");
@@ -1142,6 +1138,9 @@ public:
OS::get_singleton()->execute(adb, args, true, NULL, NULL, &rv);
print_line("Reverse result: " + itos(rv));
+ }
+
+ if (p_debug_flags & DEBUG_FLAG_DUMB_CLIENT) {
int fs_port = EditorSettings::get_singleton()->get("filesystem/file_server/port");
@@ -1724,7 +1723,6 @@ void register_android_exporter() {
EDITOR_DEF("export/android/force_system_user", false);
EDITOR_DEF("export/android/timestamping_authority_url", "");
- EDITOR_DEF("export/android/use_remote_debug_over_adb", false);
EDITOR_DEF("export/android/shutdown_adb_on_exit", true);
Ref<EditorExportAndroid> exporter = Ref<EditorExportAndroid>(memnew(EditorExportAndroid));
diff --git a/platform/android/java_glue.cpp b/platform/android/java_glue.cpp
index 9abaae0a75..06abe9d751 100644
--- a/platform/android/java_glue.cpp
+++ b/platform/android/java_glue.cpp
@@ -1002,7 +1002,9 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env, job
ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("JavaClassWrapper", java_class_wrapper));
_initialize_java_modules();
- Main::setup2();
+ // Since Godot is initialized on the UI thread, _main_thread_id was set to that thread's id,
+ // but for Godot purposes, the main thread is the one running the game loop
+ Main::setup2(Thread::get_caller_id());
++step;
suspend_mutex->unlock();
input_mutex->unlock();
diff --git a/platform/android/thread_jandroid.cpp b/platform/android/thread_jandroid.cpp
index 9e2e5452ca..79488197ea 100644
--- a/platform/android/thread_jandroid.cpp
+++ b/platform/android/thread_jandroid.cpp
@@ -29,9 +29,19 @@
/*************************************************************************/
#include "thread_jandroid.h"
+#include "core/safe_refcount.h"
#include "os/memory.h"
#include "script_language.h"
+static pthread_key_t _create_thread_id_key() {
+ pthread_key_t key;
+ pthread_key_create(&key, NULL);
+ return key;
+}
+
+pthread_key_t ThreadAndroid::thread_id_key = _create_thread_id_key();
+Thread::ID ThreadAndroid::next_thread_id = 0;
+
Thread::ID ThreadAndroid::get_id() const {
return id;
@@ -47,7 +57,8 @@ void *ThreadAndroid::thread_callback(void *userdata) {
ThreadAndroid *t = reinterpret_cast<ThreadAndroid *>(userdata);
setup_thread();
ScriptServer::thread_enter(); //scripts may need to attach a stack
- t->id = (ID)pthread_self();
+ t->id = atomic_increment(&next_thread_id);
+ pthread_setspecific(thread_id_key, (void *)t->id);
t->callback(t->user);
ScriptServer::thread_exit();
return NULL;
@@ -68,7 +79,7 @@ Thread *ThreadAndroid::create_func_jandroid(ThreadCreateCallback p_callback, voi
Thread::ID ThreadAndroid::get_thread_id_func_jandroid() {
- return (ID)pthread_self();
+ return (ID)pthread_getspecific(thread_id_key);
}
void ThreadAndroid::wait_to_finish_func_jandroid(Thread *p_thread) {
diff --git a/platform/android/thread_jandroid.h b/platform/android/thread_jandroid.h
index bacc1ce435..b854a83e23 100644
--- a/platform/android/thread_jandroid.h
+++ b/platform/android/thread_jandroid.h
@@ -41,6 +41,9 @@
class ThreadAndroid : public Thread {
+ static pthread_key_t thread_id_key;
+ static ID next_thread_id;
+
pthread_t pthread;
pthread_attr_t pthread_attr;
ThreadCreateCallback callback;
diff --git a/platform/windows/detect.py b/platform/windows/detect.py
index 882e1a808e..d239ccf7d2 100644
--- a/platform/windows/detect.py
+++ b/platform/windows/detect.py
@@ -171,6 +171,7 @@ def configure(env):
env.Append(CCFLAGS=['/DWINDOWS_ENABLED'])
env.Append(CCFLAGS=['/DOPENGL_ENABLED'])
env.Append(CCFLAGS=['/DRTAUDIO_ENABLED'])
+ env.Append(CCFLAGS=['/DWASAPI_ENABLED'])
env.Append(CCFLAGS=['/DTYPED_METHOD_BIND'])
env.Append(CCFLAGS=['/DWIN32'])
env.Append(CCFLAGS=['/DWINVER=%s' % winver, '/D_WIN32_WINNT=%s' % winver])
@@ -252,8 +253,9 @@ def configure(env):
env.Append(CCFLAGS=['-DWINDOWS_ENABLED', '-mwindows'])
env.Append(CCFLAGS=['-DOPENGL_ENABLED'])
env.Append(CCFLAGS=['-DRTAUDIO_ENABLED'])
+ env.Append(CCFLAGS=['-DWASAPI_ENABLED'])
env.Append(CCFLAGS=['-DWINVER=%s' % winver, '-D_WIN32_WINNT=%s' % winver])
- env.Append(LIBS=['mingw32', 'opengl32', 'dsound', 'ole32', 'd3d9', 'winmm', 'gdi32', 'iphlpapi', 'shlwapi', 'wsock32', 'ws2_32', 'kernel32', 'oleaut32', 'dinput8', 'dxguid'])
+ env.Append(LIBS=['mingw32', 'opengl32', 'dsound', 'ole32', 'd3d9', 'winmm', 'gdi32', 'iphlpapi', 'shlwapi', 'wsock32', 'ws2_32', 'kernel32', 'oleaut32', 'dinput8', 'dxguid', 'ksuser'])
env.Append(CPPFLAGS=['-DMINGW_ENABLED'])
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index 7b12482383..deb9c25576 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -2359,6 +2359,9 @@ OS_Windows::OS_Windows(HINSTANCE _hInstance) {
#endif
user_proc = NULL;
+#ifdef WASAPI_ENABLED
+ AudioDriverManager::add_driver(&driver_wasapi);
+#endif
#ifdef RTAUDIO_ENABLED
AudioDriverManager::add_driver(&driver_rtaudio);
#endif
diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h
index 01d904a4cc..0c5965bf51 100644
--- a/platform/windows/os_windows.h
+++ b/platform/windows/os_windows.h
@@ -32,6 +32,7 @@
#include "context_gl_win.h"
#include "drivers/rtaudio/audio_driver_rtaudio.h"
+#include "drivers/wasapi/audio_driver_wasapi.h"
#include "os/input.h"
#include "os/os.h"
#include "power_windows.h"
@@ -123,6 +124,9 @@ class OS_Windows : public OS {
PowerWindows *power_manager;
+#ifdef WASAPI_ENABLED
+ AudioDriverWASAPI driver_wasapi;
+#endif
#ifdef RTAUDIO_ENABLED
AudioDriverRtAudio driver_rtaudio;
#endif
diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp
index 4abb51ef7c..ab8277ecf3 100644
--- a/scene/2d/light_2d.cpp
+++ b/scene/2d/light_2d.cpp
@@ -434,7 +434,7 @@ void Light2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shadow_enabled"), "set_shadow_enabled", "is_shadow_enabled");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "shadow_color"), "set_shadow_color", "get_shadow_color");
ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_buffer_size", PROPERTY_HINT_RANGE, "32,16384,1"), "set_shadow_buffer_size", "get_shadow_buffer_size");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "shadow_gradient_length", PROPERTY_HINT_RANGE, "1,4096,0.1"), "set_shadow_gradient_length", "get_shadow_gradient_length");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "shadow_gradient_length", PROPERTY_HINT_RANGE, "0,4096,0.1"), "set_shadow_gradient_length", "get_shadow_gradient_length");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "shadow_filter", PROPERTY_HINT_ENUM, "None,PCF3,PCF5,PCF9,PCF13"), "set_shadow_filter", "get_shadow_filter");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "shadow_filter_smooth", PROPERTY_HINT_RANGE, "0,64,0.1"), "set_shadow_smooth", "get_shadow_smooth");
ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_item_cull_mask", PROPERTY_HINT_LAYERS_2D_RENDER), "set_item_shadow_cull_mask", "get_item_shadow_cull_mask");
diff --git a/servers/visual/visual_server_canvas.cpp b/servers/visual/visual_server_canvas.cpp
index ad6d0f6b2b..25724981eb 100644
--- a/servers/visual/visual_server_canvas.cpp
+++ b/servers/visual/visual_server_canvas.cpp
@@ -37,10 +37,8 @@ void VisualServerCanvas::_render_canvas_item_tree(Item *p_canvas_item, const Tra
RasterizerCanvas::Item *z_list[z_range];
RasterizerCanvas::Item *z_last_list[z_range];
- for (int i = 0; i < z_range; i++) {
- z_list[i] = NULL;
- z_last_list[i] = NULL;
- }
+ memset(z_list, 0, z_range * sizeof(RasterizerCanvas::Item *));
+ memset(z_last_list, 0, z_range * sizeof(RasterizerCanvas::Item *));
_render_canvas_item(p_canvas_item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, NULL, NULL);
@@ -200,10 +198,9 @@ void VisualServerCanvas::render_canvas(Canvas *p_canvas, const Transform2D &p_tr
RasterizerCanvas::Item *z_list[z_range];
RasterizerCanvas::Item *z_last_list[z_range];
- for (int i = 0; i < z_range; i++) {
- z_list[i] = NULL;
- z_last_list[i] = NULL;
- }
+ memset(z_list, 0, z_range * sizeof(RasterizerCanvas::Item *));
+ memset(z_last_list, 0, z_range * sizeof(RasterizerCanvas::Item *));
+
for (int i = 0; i < l; i++) {
_render_canvas_item(ci[i].item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, NULL, NULL);
}
@@ -701,6 +698,7 @@ void VisualServerCanvas::canvas_item_add_triangle_array(RID p_item, const Vector
polygon->colors = p_colors;
polygon->indices = indices;
polygon->count = count;
+ polygon->antialiased = false;
canvas_item->rect_dirty = true;
canvas_item->commands.push_back(polygon);