diff options
Diffstat (limited to 'servers')
77 files changed, 1156 insertions, 477 deletions
diff --git a/servers/audio/audio_driver_dummy.cpp b/servers/audio/audio_driver_dummy.cpp index 60eb657923..729f278d4b 100644 --- a/servers/audio/audio_driver_dummy.cpp +++ b/servers/audio/audio_driver_dummy.cpp @@ -36,9 +36,8 @@ AudioDriverDummy *AudioDriverDummy::singleton = nullptr; Error AudioDriverDummy::init() { - active = false; - thread_exited = false; - exit_thread = false; + active.clear(); + exit_thread.clear(); samples_in = nullptr; if (mix_rate == -1) { @@ -60,23 +59,23 @@ void AudioDriverDummy::thread_func(void *p_udata) { uint64_t usdelay = (ad->buffer_frames / float(ad->mix_rate)) * 1000000; - while (!ad->exit_thread) { - if (ad->active) { + while (!ad->exit_thread.is_set()) { + if (ad->active.is_set()) { ad->lock(); + ad->start_counting_ticks(); ad->audio_server_process(ad->buffer_frames, ad->samples_in); + ad->stop_counting_ticks(); ad->unlock(); }; OS::get_singleton()->delay_usec(usdelay); }; - - ad->thread_exited = true; }; void AudioDriverDummy::start() { - active = true; + active.set(); }; int AudioDriverDummy::get_mix_rate() const { @@ -113,7 +112,7 @@ uint32_t AudioDriverDummy::get_channels() const { } void AudioDriverDummy::mix_audio(int p_frames, int32_t *p_buffer) { - ERR_FAIL_COND(!active); // If not active, should not mix. + ERR_FAIL_COND(!active.is_set()); // If not active, should not mix. ERR_FAIL_COND(use_threads == true); // If using threads, this will not work well. uint32_t todo = p_frames; @@ -136,7 +135,7 @@ void AudioDriverDummy::mix_audio(int p_frames, int32_t *p_buffer) { void AudioDriverDummy::finish() { if (use_threads) { - exit_thread = true; + exit_thread.set(); thread.wait_to_finish(); } diff --git a/servers/audio/audio_driver_dummy.h b/servers/audio/audio_driver_dummy.h index 8f47e64d8b..46dd2e1439 100644 --- a/servers/audio/audio_driver_dummy.h +++ b/servers/audio/audio_driver_dummy.h @@ -35,6 +35,7 @@ #include "core/os/mutex.h" #include "core/os/thread.h" +#include "core/templates/safe_refcount.h" class AudioDriverDummy : public AudioDriver { Thread thread; @@ -50,9 +51,8 @@ class AudioDriverDummy : public AudioDriver { int channels; - bool active; - bool thread_exited; - mutable bool exit_thread; + SafeFlag active; + SafeFlag exit_thread; bool use_threads = true; diff --git a/servers/audio/effects/audio_effect_chorus.cpp b/servers/audio/effects/audio_effect_chorus.cpp index e5434eac02..54c08ef644 100644 --- a/servers/audio/effects/audio_effect_chorus.cpp +++ b/servers/audio/effects/audio_effect_chorus.cpp @@ -272,11 +272,11 @@ float AudioEffectChorus::get_dry() const { return dry; } -void AudioEffectChorus::_validate_property(PropertyInfo &property) const { - if (property.name.begins_with("voice/")) { - int voice_idx = property.name.get_slice("/", 1).to_int(); +void AudioEffectChorus::_validate_property(PropertyInfo &p_property) const { + if (p_property.name.begins_with("voice/")) { + int voice_idx = p_property.name.get_slice("/", 1).to_int(); if (voice_idx > voice_count) { - property.usage = PROPERTY_USAGE_NONE; + p_property.usage = PROPERTY_USAGE_NONE; } } } diff --git a/servers/audio/effects/audio_effect_chorus.h b/servers/audio/effects/audio_effect_chorus.h index 72b495f7f9..dd4b431e7a 100644 --- a/servers/audio/effects/audio_effect_chorus.h +++ b/servers/audio/effects/audio_effect_chorus.h @@ -96,7 +96,7 @@ private: float dry; protected: - void _validate_property(PropertyInfo &property) const override; + void _validate_property(PropertyInfo &p_property) const; static void _bind_methods(); diff --git a/servers/audio/effects/audio_effect_compressor.cpp b/servers/audio/effects/audio_effect_compressor.cpp index ee71a6dba7..0e1accba16 100644 --- a/servers/audio/effects/audio_effect_compressor.cpp +++ b/servers/audio/effects/audio_effect_compressor.cpp @@ -184,15 +184,15 @@ StringName AudioEffectCompressor::get_sidechain() const { return sidechain; } -void AudioEffectCompressor::_validate_property(PropertyInfo &property) const { - if (property.name == "sidechain") { +void AudioEffectCompressor::_validate_property(PropertyInfo &p_property) const { + if (p_property.name == "sidechain") { String buses = ""; for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) { buses += ","; buses += AudioServer::get_singleton()->get_bus_name(i); } - property.hint_string = buses; + p_property.hint_string = buses; } } diff --git a/servers/audio/effects/audio_effect_compressor.h b/servers/audio/effects/audio_effect_compressor.h index 998bd3c978..886255b958 100644 --- a/servers/audio/effects/audio_effect_compressor.h +++ b/servers/audio/effects/audio_effect_compressor.h @@ -61,7 +61,7 @@ class AudioEffectCompressor : public AudioEffect { StringName sidechain; protected: - void _validate_property(PropertyInfo &property) const override; + void _validate_property(PropertyInfo &p_property) const; static void _bind_methods(); public: diff --git a/servers/audio/effects/audio_effect_delay.cpp b/servers/audio/effects/audio_effect_delay.cpp index 80e7a8223c..ae8c58f654 100644 --- a/servers/audio/effects/audio_effect_delay.cpp +++ b/servers/audio/effects/audio_effect_delay.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "audio_effect_delay.h" + #include "core/math/math_funcs.h" #include "servers/audio_server.h" @@ -286,37 +287,21 @@ void AudioEffectDelay::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dry", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_dry", "get_dry"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "tap1/active"), "set_tap1_active", "is_tap1_active"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap1/delay_ms", PROPERTY_HINT_RANGE, "0,1500,1,suffix:ms"), "set_tap1_delay_ms", "get_tap1_delay_ms"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap1/level_db", PROPERTY_HINT_RANGE, "-60,0,0.01,suffix:dB"), "set_tap1_level_db", "get_tap1_level_db"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap1/pan", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_tap1_pan", "get_tap1_pan"); - - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "tap2/active"), "set_tap2_active", "is_tap2_active"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap2/delay_ms", PROPERTY_HINT_RANGE, "0,1500,1,suffix:ms"), "set_tap2_delay_ms", "get_tap2_delay_ms"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap2/level_db", PROPERTY_HINT_RANGE, "-60,0,0.01,suffix:dB"), "set_tap2_level_db", "get_tap2_level_db"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap2/pan", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_tap2_pan", "get_tap2_pan"); - - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "feedback/active"), "set_feedback_active", "is_feedback_active"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "feedback/delay_ms", PROPERTY_HINT_RANGE, "0,1500,1,suffix:ms"), "set_feedback_delay_ms", "get_feedback_delay_ms"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "feedback/level_db", PROPERTY_HINT_RANGE, "-60,0,0.01,suffix:dB"), "set_feedback_level_db", "get_feedback_level_db"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "feedback/lowpass", PROPERTY_HINT_RANGE, "1,16000,1"), "set_feedback_lowpass", "get_feedback_lowpass"); -} - -AudioEffectDelay::AudioEffectDelay() { - tap_1_active = true; - tap_1_delay_ms = 250; - tap_1_level = -6; - tap_1_pan = 0.2; - - tap_2_active = true; - tap_2_delay_ms = 500; - tap_2_level = -12; - tap_2_pan = -0.4; - - feedback_active = false; - feedback_delay_ms = 340; - feedback_level = -6; - feedback_lowpass = 16000; - - dry = 1.0; + ADD_GROUP("Tap 1", "tap1_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "tap1_active"), "set_tap1_active", "is_tap1_active"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap1_delay_ms", PROPERTY_HINT_RANGE, "0,1500,1,suffix:ms"), "set_tap1_delay_ms", "get_tap1_delay_ms"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap1_level_db", PROPERTY_HINT_RANGE, "-60,0,0.01,suffix:dB"), "set_tap1_level_db", "get_tap1_level_db"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap1_pan", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_tap1_pan", "get_tap1_pan"); + + ADD_GROUP("Tap 2", "tap2_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "tap2_active"), "set_tap2_active", "is_tap2_active"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap2_delay_ms", PROPERTY_HINT_RANGE, "0,1500,1,suffix:ms"), "set_tap2_delay_ms", "get_tap2_delay_ms"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap2_level_db", PROPERTY_HINT_RANGE, "-60,0,0.01,suffix:dB"), "set_tap2_level_db", "get_tap2_level_db"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap2_pan", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_tap2_pan", "get_tap2_pan"); + + ADD_GROUP("Feedback", "feedback_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "feedback_active"), "set_feedback_active", "is_feedback_active"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "feedback_delay_ms", PROPERTY_HINT_RANGE, "0,1500,1,suffix:ms"), "set_feedback_delay_ms", "get_feedback_delay_ms"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "feedback_level_db", PROPERTY_HINT_RANGE, "-60,0,0.01,suffix:dB"), "set_feedback_level_db", "get_feedback_level_db"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "feedback_lowpass", PROPERTY_HINT_RANGE, "1,16000,1"), "set_feedback_lowpass", "get_feedback_lowpass"); } diff --git a/servers/audio/effects/audio_effect_delay.h b/servers/audio/effects/audio_effect_delay.h index 137a4e7dbe..020d45e79b 100644 --- a/servers/audio/effects/audio_effect_delay.h +++ b/servers/audio/effects/audio_effect_delay.h @@ -37,6 +37,7 @@ class AudioEffectDelay; class AudioEffectDelayInstance : public AudioEffectInstance { GDCLASS(AudioEffectDelayInstance, AudioEffectInstance); + friend class AudioEffectDelay; Ref<AudioEffectDelay> base; @@ -66,22 +67,22 @@ class AudioEffectDelay : public AudioEffect { MAX_TAPS = 2 }; - float dry; + float dry = 1.0f; - bool tap_1_active; - float tap_1_delay_ms; - float tap_1_level; - float tap_1_pan; + bool tap_1_active = true; + float tap_1_delay_ms = 250.0f; + float tap_1_level = -6.0f; + float tap_1_pan = 0.2f; - bool tap_2_active; - float tap_2_delay_ms; - float tap_2_level; - float tap_2_pan; + bool tap_2_active = true; + float tap_2_delay_ms = 500.0f; + float tap_2_level = -12.0f; + float tap_2_pan = -0.4f; - bool feedback_active; - float feedback_delay_ms; - float feedback_level; - float feedback_lowpass; + bool feedback_active = false; + float feedback_delay_ms = 340.0f; + float feedback_level = -6.0f; + float feedback_lowpass = 16000.0f; protected: static void _bind_methods(); @@ -128,7 +129,7 @@ public: Ref<AudioEffectInstance> instantiate() override; - AudioEffectDelay(); + AudioEffectDelay() {} }; #endif // AUDIO_EFFECT_DELAY_H diff --git a/servers/audio/effects/audio_effect_filter.h b/servers/audio/effects/audio_effect_filter.h index a40af2f13c..1510ee2af7 100644 --- a/servers/audio/effects/audio_effect_filter.h +++ b/servers/audio/effects/audio_effect_filter.h @@ -98,9 +98,9 @@ VARIANT_ENUM_CAST(AudioEffectFilter::FilterDB) class AudioEffectLowPassFilter : public AudioEffectFilter { GDCLASS(AudioEffectLowPassFilter, AudioEffectFilter); - void _validate_property(PropertyInfo &property) const override { - if (property.name == "gain") { - property.usage = PROPERTY_USAGE_NONE; + void _validate_property(PropertyInfo &p_property) const { + if (p_property.name == "gain") { + p_property.usage = PROPERTY_USAGE_NONE; } } @@ -111,9 +111,9 @@ public: class AudioEffectHighPassFilter : public AudioEffectFilter { GDCLASS(AudioEffectHighPassFilter, AudioEffectFilter); - void _validate_property(PropertyInfo &property) const override { - if (property.name == "gain") { - property.usage = PROPERTY_USAGE_NONE; + void _validate_property(PropertyInfo &p_property) const { + if (p_property.name == "gain") { + p_property.usage = PROPERTY_USAGE_NONE; } } @@ -124,9 +124,9 @@ public: class AudioEffectBandPassFilter : public AudioEffectFilter { GDCLASS(AudioEffectBandPassFilter, AudioEffectFilter); - void _validate_property(PropertyInfo &property) const override { - if (property.name == "gain") { - property.usage = PROPERTY_USAGE_NONE; + void _validate_property(PropertyInfo &p_property) const { + if (p_property.name == "gain") { + p_property.usage = PROPERTY_USAGE_NONE; } } diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp index 9052f8e05e..64695557aa 100644 --- a/servers/audio_server.cpp +++ b/servers/audio_server.cpp @@ -144,8 +144,8 @@ int AudioDriver::get_total_channels_by_speaker_mode(AudioDriver::SpeakerMode p_m ERR_FAIL_V(2); } -Array AudioDriver::get_device_list() { - Array list; +PackedStringArray AudioDriver::get_device_list() { + PackedStringArray list; list.push_back("Default"); @@ -156,8 +156,8 @@ String AudioDriver::get_device() { return "Default"; } -Array AudioDriver::capture_get_device_list() { - Array list; +PackedStringArray AudioDriver::capture_get_device_list() { + PackedStringArray list; list.push_back("Default"); @@ -1637,7 +1637,7 @@ Ref<AudioBusLayout> AudioServer::generate_bus_layout() const { return state; } -Array AudioServer::get_device_list() { +PackedStringArray AudioServer::get_device_list() { return AudioDriver::get_singleton()->get_device_list(); } @@ -1649,7 +1649,7 @@ void AudioServer::set_device(String device) { AudioDriver::get_singleton()->set_device(device); } -Array AudioServer::capture_get_device_list() { +PackedStringArray AudioServer::capture_get_device_list() { return AudioDriver::get_singleton()->capture_get_device_list(); } diff --git a/servers/audio_server.h b/servers/audio_server.h index 5613267909..588107c25d 100644 --- a/servers/audio_server.h +++ b/servers/audio_server.h @@ -94,7 +94,7 @@ public: virtual void start() = 0; virtual int get_mix_rate() const = 0; virtual SpeakerMode get_speaker_mode() const = 0; - virtual Array get_device_list(); + virtual PackedStringArray get_device_list(); virtual String get_device(); virtual void set_device(String device) {} virtual void lock() = 0; @@ -105,7 +105,7 @@ public: 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 PackedStringArray + virtual PackedStringArray capture_get_device_list(); virtual float get_latency() { return 0; } @@ -419,11 +419,11 @@ public: void set_bus_layout(const Ref<AudioBusLayout> &p_bus_layout); Ref<AudioBusLayout> generate_bus_layout() const; - Array get_device_list(); + PackedStringArray get_device_list(); String get_device(); void set_device(String device); - Array capture_get_device_list(); + PackedStringArray capture_get_device_list(); String capture_get_device(); void capture_set_device(const String &p_name); diff --git a/servers/camera_server.cpp b/servers/camera_server.cpp index 91df3afadd..b83b41a571 100644 --- a/servers/camera_server.cpp +++ b/servers/camera_server.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "camera_server.h" +#include "core/variant/typed_array.h" #include "rendering_server.h" #include "servers/camera/camera_feed.h" @@ -143,8 +144,8 @@ int CameraServer::get_feed_count() { return feeds.size(); }; -Array CameraServer::get_feeds() { - Array return_feeds; +TypedArray<CameraFeed> CameraServer::get_feeds() { + TypedArray<CameraFeed> return_feeds; int cc = get_feed_count(); return_feeds.resize(cc); diff --git a/servers/camera_server.h b/servers/camera_server.h index b70938c34f..c6fb906b3c 100644 --- a/servers/camera_server.h +++ b/servers/camera_server.h @@ -43,6 +43,8 @@ **/ class CameraFeed; +template <typename T> +class TypedArray; class CameraServer : public Object { GDCLASS(CameraServer, Object); @@ -100,7 +102,7 @@ public: // Get our feeds. Ref<CameraFeed> get_feed(int p_index); int get_feed_count(); - Array get_feeds(); + TypedArray<CameraFeed> get_feeds(); // Intended for use with custom CameraServer implementation. RID feed_texture(int p_id, FeedImage p_texture); diff --git a/servers/display_server.cpp b/servers/display_server.cpp index 4e7db7d0a5..0c05570b23 100644 --- a/servers/display_server.cpp +++ b/servers/display_server.cpp @@ -44,40 +44,49 @@ DisplayServer::DisplayServerCreate DisplayServer::server_create_functions[Displa int DisplayServer::server_create_count = 1; -void DisplayServer::global_menu_add_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { +int DisplayServer::global_menu_add_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { WARN_PRINT("Global menus not supported by this display server."); + return -1; } -void DisplayServer::global_menu_add_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { +int DisplayServer::global_menu_add_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { WARN_PRINT("Global menus not supported by this display server."); + return -1; } -void DisplayServer::global_menu_add_icon_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { +int DisplayServer::global_menu_add_icon_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { WARN_PRINT("Global menus not supported by this display server."); + return -1; } -void DisplayServer::global_menu_add_icon_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { +int DisplayServer::global_menu_add_icon_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { WARN_PRINT("Global menus not supported by this display server."); + return -1; } -void DisplayServer::global_menu_add_radio_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { +int DisplayServer::global_menu_add_radio_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { WARN_PRINT("Global menus not supported by this display server."); + return -1; } -void DisplayServer::global_menu_add_icon_radio_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { +int DisplayServer::global_menu_add_icon_radio_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { WARN_PRINT("Global menus not supported by this display server."); + return -1; } -void DisplayServer::global_menu_add_multistate_item(const String &p_menu_root, const String &p_label, int p_max_states, int p_default_state, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { +int DisplayServer::global_menu_add_multistate_item(const String &p_menu_root, const String &p_label, int p_max_states, int p_default_state, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { WARN_PRINT("Global menus not supported by this display server."); + return -1; } -void DisplayServer::global_menu_add_submenu_item(const String &p_menu_root, const String &p_label, const String &p_submenu, int p_index) { +int DisplayServer::global_menu_add_submenu_item(const String &p_menu_root, const String &p_label, const String &p_submenu, int p_index) { WARN_PRINT("Global menus not supported by this display server."); + return -1; } -void DisplayServer::global_menu_add_separator(const String &p_menu_root, int p_index) { +int DisplayServer::global_menu_add_separator(const String &p_menu_root, int p_index) { WARN_PRINT("Global menus not supported by this display server."); + return -1; } int DisplayServer::global_menu_get_item_index_from_text(const String &p_menu_root, const String &p_text) const { @@ -159,6 +168,11 @@ Ref<Texture2D> DisplayServer::global_menu_get_item_icon(const String &p_menu_roo return Ref<Texture2D>(); } +int DisplayServer::global_menu_get_item_indentation_level(const String &p_menu_root, int p_idx) const { + WARN_PRINT("Global menus not supported by this display server."); + return 0; +} + void DisplayServer::global_menu_set_item_checked(const String &p_menu_root, int p_idx, bool p_checked) { WARN_PRINT("Global menus not supported by this display server."); } @@ -207,6 +221,10 @@ void DisplayServer::global_menu_set_item_icon(const String &p_menu_root, int p_i WARN_PRINT("Global menus not supported by this display server."); } +void DisplayServer::global_menu_set_item_indentation_level(const String &p_menu_root, int p_idx, int p_level) { + WARN_PRINT("Global menus not supported by this display server."); +} + int DisplayServer::global_menu_get_item_count(const String &p_menu_root) const { WARN_PRINT("Global menus not supported by this display server."); return 0; @@ -238,14 +256,14 @@ void DisplayServer::tts_resume() { WARN_PRINT("TTS is not supported by this display server."); } -Array DisplayServer::tts_get_voices() const { +TypedArray<Dictionary> DisplayServer::tts_get_voices() const { WARN_PRINT("TTS is not supported by this display server."); - return Array(); + return TypedArray<Dictionary>(); } PackedStringArray DisplayServer::tts_get_voices_for_language(const String &p_language) const { PackedStringArray ret; - Array voices = tts_get_voices(); + TypedArray<Dictionary> voices = tts_get_voices(); for (int i = 0; i < voices.size(); i++) { const Dictionary &voice = voices[i]; if (voice.has("id") && voice.has("language") && voice["language"].operator String().begins_with(p_language)) { @@ -535,6 +553,7 @@ void DisplayServer::_bind_methods() { ClassDB::bind_method(D_METHOD("global_menu_get_item_state", "menu_root", "idx"), &DisplayServer::global_menu_get_item_state); ClassDB::bind_method(D_METHOD("global_menu_get_item_max_states", "menu_root", "idx"), &DisplayServer::global_menu_get_item_max_states); ClassDB::bind_method(D_METHOD("global_menu_get_item_icon", "menu_root", "idx"), &DisplayServer::global_menu_get_item_icon); + ClassDB::bind_method(D_METHOD("global_menu_get_item_indentation_level", "menu_root", "idx"), &DisplayServer::global_menu_get_item_indentation_level); ClassDB::bind_method(D_METHOD("global_menu_set_item_checked", "menu_root", "idx", "checked"), &DisplayServer::global_menu_set_item_checked); ClassDB::bind_method(D_METHOD("global_menu_set_item_checkable", "menu_root", "idx", "checkable"), &DisplayServer::global_menu_set_item_checkable); @@ -549,6 +568,7 @@ void DisplayServer::_bind_methods() { ClassDB::bind_method(D_METHOD("global_menu_set_item_state", "menu_root", "idx", "state"), &DisplayServer::global_menu_set_item_state); ClassDB::bind_method(D_METHOD("global_menu_set_item_max_states", "menu_root", "idx", "max_states"), &DisplayServer::global_menu_set_item_max_states); ClassDB::bind_method(D_METHOD("global_menu_set_item_icon", "menu_root", "idx", "icon"), &DisplayServer::global_menu_set_item_icon); + ClassDB::bind_method(D_METHOD("global_menu_set_item_indentation_level", "menu_root", "idx", "level"), &DisplayServer::global_menu_set_item_indentation_level); ClassDB::bind_method(D_METHOD("global_menu_remove_item", "menu_root", "idx"), &DisplayServer::global_menu_remove_item); ClassDB::bind_method(D_METHOD("global_menu_clear", "menu_root"), &DisplayServer::global_menu_clear); diff --git a/servers/display_server.h b/servers/display_server.h index 8632b53f7b..4e52c58633 100644 --- a/servers/display_server.h +++ b/servers/display_server.h @@ -127,15 +127,15 @@ public: virtual bool has_feature(Feature p_feature) const = 0; virtual String get_name() const = 0; - virtual void global_menu_add_item(const String &p_menu_root, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); - virtual void global_menu_add_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); - virtual void global_menu_add_icon_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); - virtual void global_menu_add_icon_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); - virtual void global_menu_add_radio_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); - virtual void global_menu_add_icon_radio_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); - virtual void global_menu_add_multistate_item(const String &p_menu_root, const String &p_label, int p_max_states, int p_default_state, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); - virtual void global_menu_add_submenu_item(const String &p_menu_root, const String &p_label, const String &p_submenu, int p_index = -1); - virtual void global_menu_add_separator(const String &p_menu_root, int p_index = -1); + virtual int global_menu_add_item(const String &p_menu_root, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); + virtual int global_menu_add_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); + virtual int global_menu_add_icon_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); + virtual int global_menu_add_icon_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); + virtual int global_menu_add_radio_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); + virtual int global_menu_add_icon_radio_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); + virtual int global_menu_add_multistate_item(const String &p_menu_root, const String &p_label, int p_max_states, int p_default_state, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); + virtual int global_menu_add_submenu_item(const String &p_menu_root, const String &p_label, const String &p_submenu, int p_index = -1); + virtual int global_menu_add_separator(const String &p_menu_root, int p_index = -1); virtual int global_menu_get_item_index_from_text(const String &p_menu_root, const String &p_text) const; virtual int global_menu_get_item_index_from_tag(const String &p_menu_root, const Variant &p_tag) const; @@ -153,6 +153,7 @@ public: virtual int global_menu_get_item_state(const String &p_menu_root, int p_idx) const; virtual int global_menu_get_item_max_states(const String &p_menu_root, int p_idx) const; virtual Ref<Texture2D> global_menu_get_item_icon(const String &p_menu_root, int p_idx) const; + virtual int global_menu_get_item_indentation_level(const String &p_menu_root, int p_idx) const; virtual void global_menu_set_item_checked(const String &p_menu_root, int p_idx, bool p_checked); virtual void global_menu_set_item_checkable(const String &p_menu_root, int p_idx, bool p_checkable); @@ -167,6 +168,7 @@ public: virtual void global_menu_set_item_state(const String &p_menu_root, int p_idx, int p_state); virtual void global_menu_set_item_max_states(const String &p_menu_root, int p_idx, int p_max_states); virtual void global_menu_set_item_icon(const String &p_menu_root, int p_idx, const Ref<Texture2D> &p_icon); + virtual void global_menu_set_item_indentation_level(const String &p_menu_root, int p_idx, int p_level); virtual int global_menu_get_item_count(const String &p_menu_root) const; @@ -196,7 +198,7 @@ private: public: virtual bool tts_is_speaking() const; virtual bool tts_is_paused() const; - virtual Array tts_get_voices() const; + virtual TypedArray<Dictionary> tts_get_voices() const; virtual PackedStringArray tts_get_voices_for_language(const String &p_language) const; virtual void tts_speak(const String &p_text, const String &p_voice, int p_volume = 50, float p_pitch = 1.f, float p_rate = 1.f, int p_utterance_id = 0, bool p_interrupt = false); @@ -228,7 +230,7 @@ public: virtual void clipboard_set_primary(const String &p_text); virtual String clipboard_get_primary() const; - virtual Array get_display_cutouts() const { return Array(); } + virtual TypedArray<Rect2> get_display_cutouts() const { return TypedArray<Rect2>(); } virtual Rect2i get_display_safe_area() const { return screen_get_usable_rect(); } enum { diff --git a/servers/extensions/physics_server_3d_extension.cpp b/servers/extensions/physics_server_3d_extension.cpp index 3694dcdb9a..7d797bf611 100644 --- a/servers/extensions/physics_server_3d_extension.cpp +++ b/servers/extensions/physics_server_3d_extension.cpp @@ -196,6 +196,9 @@ void PhysicsServer3DExtension::_bind_methods() { GDVIRTUAL_BIND(_body_set_collision_mask, "body", "mask"); GDVIRTUAL_BIND(_body_get_collision_mask, "body"); + GDVIRTUAL_BIND(_body_set_collision_priority, "body", "priority"); + GDVIRTUAL_BIND(_body_get_collision_priority, "body"); + GDVIRTUAL_BIND(_body_add_shape, "body", "shape", "transform", "disabled"); GDVIRTUAL_BIND(_body_set_shape, "body", "shape_idx", "shape"); GDVIRTUAL_BIND(_body_set_shape_transform, "body", "shape_idx", "transform"); diff --git a/servers/extensions/physics_server_3d_extension.h b/servers/extensions/physics_server_3d_extension.h index c4b4a00eaf..3200438253 100644 --- a/servers/extensions/physics_server_3d_extension.h +++ b/servers/extensions/physics_server_3d_extension.h @@ -319,6 +319,9 @@ public: EXBIND2(body_set_collision_mask, RID, uint32_t) EXBIND1RC(uint32_t, body_get_collision_mask, RID) + EXBIND2(body_set_collision_priority, RID, real_t) + EXBIND1RC(real_t, body_get_collision_priority, RID) + EXBIND2(body_set_user_flags, RID, uint32_t) EXBIND1RC(uint32_t, body_get_user_flags, RID) diff --git a/servers/navigation_server_2d.cpp b/servers/navigation_server_2d.cpp index 126bb08c94..0f73df8894 100644 --- a/servers/navigation_server_2d.cpp +++ b/servers/navigation_server_2d.cpp @@ -204,7 +204,7 @@ void NavigationServer2D::_bind_methods() { ClassDB::bind_method(D_METHOD("map_create"), &NavigationServer2D::map_create); ClassDB::bind_method(D_METHOD("map_set_active", "map", "active"), &NavigationServer2D::map_set_active); - ClassDB::bind_method(D_METHOD("map_is_active", "nap"), &NavigationServer2D::map_is_active); + ClassDB::bind_method(D_METHOD("map_is_active", "map"), &NavigationServer2D::map_is_active); ClassDB::bind_method(D_METHOD("map_set_cell_size", "map", "cell_size"), &NavigationServer2D::map_set_cell_size); ClassDB::bind_method(D_METHOD("map_get_cell_size", "map"), &NavigationServer2D::map_get_cell_size); ClassDB::bind_method(D_METHOD("map_set_edge_connection_margin", "map", "margin"), &NavigationServer2D::map_set_edge_connection_margin); @@ -237,7 +237,7 @@ void NavigationServer2D::_bind_methods() { ClassDB::bind_method(D_METHOD("agent_create"), &NavigationServer2D::agent_create); ClassDB::bind_method(D_METHOD("agent_set_map", "agent", "map"), &NavigationServer2D::agent_set_map); ClassDB::bind_method(D_METHOD("agent_get_map", "agent"), &NavigationServer2D::agent_get_map); - ClassDB::bind_method(D_METHOD("agent_set_neighbor_dist", "agent", "dist"), &NavigationServer2D::agent_set_neighbor_dist); + ClassDB::bind_method(D_METHOD("agent_set_neighbor_distance", "agent", "distance"), &NavigationServer2D::agent_set_neighbor_distance); ClassDB::bind_method(D_METHOD("agent_set_max_neighbors", "agent", "count"), &NavigationServer2D::agent_set_max_neighbors); ClassDB::bind_method(D_METHOD("agent_set_time_horizon", "agent", "time"), &NavigationServer2D::agent_set_time_horizon); ClassDB::bind_method(D_METHOD("agent_set_radius", "agent", "radius"), &NavigationServer2D::agent_set_radius); @@ -263,11 +263,11 @@ NavigationServer2D::~NavigationServer2D() { singleton = nullptr; } -Array FORWARD_0_C(get_maps); +TypedArray<RID> FORWARD_0_C(get_maps); -Array FORWARD_1_C(map_get_regions, RID, p_map, rid_to_rid); +TypedArray<RID> FORWARD_1_C(map_get_regions, RID, p_map, rid_to_rid); -Array FORWARD_1_C(map_get_agents, RID, p_map, rid_to_rid); +TypedArray<RID> FORWARD_1_C(map_get_agents, RID, p_map, rid_to_rid); RID FORWARD_1_C(region_get_map, RID, p_region, rid_to_rid); @@ -323,7 +323,7 @@ RID NavigationServer2D::agent_create() const { void FORWARD_2_C(agent_set_map, RID, p_agent, RID, p_map, rid_to_rid, rid_to_rid); -void FORWARD_2_C(agent_set_neighbor_dist, RID, p_agent, real_t, p_dist, rid_to_rid, real_to_real); +void FORWARD_2_C(agent_set_neighbor_distance, RID, p_agent, real_t, p_dist, rid_to_rid, real_to_real); void FORWARD_2_C(agent_set_max_neighbors, RID, p_agent, int, p_count, rid_to_rid, int_to_int); diff --git a/servers/navigation_server_2d.h b/servers/navigation_server_2d.h index 83271f990e..5e96466d66 100644 --- a/servers/navigation_server_2d.h +++ b/servers/navigation_server_2d.h @@ -53,7 +53,7 @@ public: /// MUST be used in single thread! static NavigationServer2D *get_singleton_mut() { return singleton; } - virtual Array get_maps() const; + virtual TypedArray<RID> get_maps() const; /// Create a new map. virtual RID map_create() const; @@ -82,8 +82,8 @@ public: virtual Vector2 map_get_closest_point(RID p_map, const Vector2 &p_point) const; virtual RID map_get_closest_point_owner(RID p_map, const Vector2 &p_point) const; - virtual Array map_get_regions(RID p_map) const; - virtual Array map_get_agents(RID p_map) const; + virtual TypedArray<RID> map_get_regions(RID p_map) const; + virtual TypedArray<RID> map_get_agents(RID p_map) const; virtual void map_force_update(RID p_map); @@ -133,7 +133,7 @@ public: /// time of the simulation. If the number is too /// low, the simulation will not be safe. /// Must be non-negative. - virtual void agent_set_neighbor_dist(RID p_agent, real_t p_dist) const; + virtual void agent_set_neighbor_distance(RID p_agent, real_t p_distance) const; /// The maximum number of other agents this /// agent takes into account in the navigation. diff --git a/servers/navigation_server_3d.cpp b/servers/navigation_server_3d.cpp index 115eda7b30..466b74bc64 100644 --- a/servers/navigation_server_3d.cpp +++ b/servers/navigation_server_3d.cpp @@ -41,7 +41,7 @@ void NavigationServer3D::_bind_methods() { ClassDB::bind_method(D_METHOD("map_create"), &NavigationServer3D::map_create); ClassDB::bind_method(D_METHOD("map_set_active", "map", "active"), &NavigationServer3D::map_set_active); - ClassDB::bind_method(D_METHOD("map_is_active", "nap"), &NavigationServer3D::map_is_active); + ClassDB::bind_method(D_METHOD("map_is_active", "map"), &NavigationServer3D::map_is_active); ClassDB::bind_method(D_METHOD("map_set_up", "map", "up"), &NavigationServer3D::map_set_up); ClassDB::bind_method(D_METHOD("map_get_up", "map"), &NavigationServer3D::map_get_up); ClassDB::bind_method(D_METHOD("map_set_cell_size", "map", "cell_size"), &NavigationServer3D::map_set_cell_size); @@ -79,7 +79,7 @@ void NavigationServer3D::_bind_methods() { ClassDB::bind_method(D_METHOD("agent_create"), &NavigationServer3D::agent_create); ClassDB::bind_method(D_METHOD("agent_set_map", "agent", "map"), &NavigationServer3D::agent_set_map); ClassDB::bind_method(D_METHOD("agent_get_map", "agent"), &NavigationServer3D::agent_get_map); - ClassDB::bind_method(D_METHOD("agent_set_neighbor_dist", "agent", "dist"), &NavigationServer3D::agent_set_neighbor_dist); + ClassDB::bind_method(D_METHOD("agent_set_neighbor_distance", "agent", "distance"), &NavigationServer3D::agent_set_neighbor_distance); ClassDB::bind_method(D_METHOD("agent_set_max_neighbors", "agent", "count"), &NavigationServer3D::agent_set_max_neighbors); ClassDB::bind_method(D_METHOD("agent_set_time_horizon", "agent", "time"), &NavigationServer3D::agent_set_time_horizon); ClassDB::bind_method(D_METHOD("agent_set_radius", "agent", "radius"), &NavigationServer3D::agent_set_radius); diff --git a/servers/navigation_server_3d.h b/servers/navigation_server_3d.h index f24c0117d1..3213da3d84 100644 --- a/servers/navigation_server_3d.h +++ b/servers/navigation_server_3d.h @@ -56,7 +56,7 @@ public: /// MUST be used in single thread! static NavigationServer3D *get_singleton_mut(); - virtual Array get_maps() const = 0; + virtual TypedArray<RID> get_maps() const = 0; /// Create a new map. virtual RID map_create() const = 0; @@ -93,8 +93,8 @@ public: virtual Vector3 map_get_closest_point_normal(RID p_map, const Vector3 &p_point) const = 0; virtual RID map_get_closest_point_owner(RID p_map, const Vector3 &p_point) const = 0; - virtual Array map_get_regions(RID p_map) const = 0; - virtual Array map_get_agents(RID p_map) const = 0; + virtual TypedArray<RID> map_get_regions(RID p_map) const = 0; + virtual TypedArray<RID> map_get_agents(RID p_map) const = 0; virtual void map_force_update(RID p_map) = 0; @@ -147,7 +147,7 @@ public: /// time of the simulation. If the number is too /// low, the simulation will not be safe. /// Must be non-negative. - virtual void agent_set_neighbor_dist(RID p_agent, real_t p_dist) const = 0; + virtual void agent_set_neighbor_distance(RID p_agent, real_t p_distance) const = 0; /// The maximum number of other agents this /// agent takes into account in the navigation. diff --git a/servers/physics_2d/godot_collision_object_2d.h b/servers/physics_2d/godot_collision_object_2d.h index 1a683a7b0f..7965e8a94d 100644 --- a/servers/physics_2d/godot_collision_object_2d.h +++ b/servers/physics_2d/godot_collision_object_2d.h @@ -70,6 +70,7 @@ private: Transform2D inv_transform; uint32_t collision_mask = 1; uint32_t collision_layer = 1; + real_t collision_priority = 1.0; bool _static = true; SelfList<GodotCollisionObject2D> pending_shape_update_list; @@ -166,6 +167,13 @@ public: } _FORCE_INLINE_ uint32_t get_collision_layer() const { return collision_layer; } + _FORCE_INLINE_ void set_collision_priority(real_t p_priority) { + ERR_FAIL_COND_MSG(p_priority <= 0, "Priority must be greater than 0."); + collision_priority = p_priority; + _shape_changed(); + } + _FORCE_INLINE_ real_t get_collision_priority() const { return collision_priority; } + void remove_shape(GodotShape2D *p_shape) override; void remove_shape(int p_index); diff --git a/servers/physics_2d/godot_physics_server_2d.cpp b/servers/physics_2d/godot_physics_server_2d.cpp index 99e68de07c..c728dccd4f 100644 --- a/servers/physics_2d/godot_physics_server_2d.cpp +++ b/servers/physics_2d/godot_physics_server_2d.cpp @@ -718,6 +718,20 @@ uint32_t GodotPhysicsServer2D::body_get_collision_mask(RID p_body) const { return body->get_collision_mask(); } +void GodotPhysicsServer2D::body_set_collision_priority(RID p_body, real_t p_priority) { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + body->set_collision_priority(p_priority); +} + +real_t GodotPhysicsServer2D::body_get_collision_priority(RID p_body) const { + const GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!body, 0); + + return body->get_collision_priority(); +} + void GodotPhysicsServer2D::body_set_param(RID p_body, BodyParameter p_param, const Variant &p_value) { GodotBody2D *body = body_owner.get_or_null(p_body); ERR_FAIL_COND(!body); diff --git a/servers/physics_2d/godot_physics_server_2d.h b/servers/physics_2d/godot_physics_server_2d.h index 2af6e5c97c..20e492d87a 100644 --- a/servers/physics_2d/godot_physics_server_2d.h +++ b/servers/physics_2d/godot_physics_server_2d.h @@ -199,6 +199,9 @@ public: virtual void body_set_collision_mask(RID p_body, uint32_t p_mask) override; virtual uint32_t body_get_collision_mask(RID p_body) const override; + virtual void body_set_collision_priority(RID p_body, real_t p_priority) override; + virtual real_t body_get_collision_priority(RID p_body) const override; + virtual void body_set_param(RID p_body, BodyParameter p_param, const Variant &p_value) override; virtual Variant body_get_param(RID p_body, BodyParameter p_param) const override; diff --git a/servers/physics_2d/godot_space_2d.cpp b/servers/physics_2d/godot_space_2d.cpp index 166ec3049e..4166191be8 100644 --- a/servers/physics_2d/godot_space_2d.cpp +++ b/servers/physics_2d/godot_space_2d.cpp @@ -594,6 +594,7 @@ bool GodotSpace2D::test_body_motion(GodotBody2D *p_body, const PhysicsServer2D:: const int max_results = 32; int recover_attempts = 4; Vector2 sr[max_results * 2]; + real_t priorities[max_results]; do { GodotPhysicsServer2D::CollCbkData cbk; @@ -606,6 +607,7 @@ bool GodotSpace2D::test_body_motion(GodotBody2D *p_body, const PhysicsServer2D:: GodotPhysicsServer2D::CollCbkData *cbkptr = &cbk; GodotCollisionSolver2D::CallbackResult cbkres = GodotPhysicsServer2D::_shape_col_cbk; + int priority_amount = 0; bool collided = false; @@ -664,6 +666,10 @@ bool GodotSpace2D::test_body_motion(GodotBody2D *p_body, const PhysicsServer2D:: if (GodotCollisionSolver2D::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), cbkres, cbkptr, nullptr, margin)) { did_collide = cbk.passed > current_passed; //more passed, so collision actually existed } + while (cbk.amount > priority_amount) { + priorities[priority_amount] = col_obj->get_collision_priority(); + priority_amount++; + } if (!did_collide && cbk.invalid_by_dir > 0) { //this shape must be excluded @@ -686,6 +692,12 @@ bool GodotSpace2D::test_body_motion(GodotBody2D *p_body, const PhysicsServer2D:: break; } + real_t inv_total_weight = 0.0; + for (int i = 0; i < cbk.amount; i++) { + inv_total_weight += priorities[i]; + } + inv_total_weight = Math::is_zero_approx(inv_total_weight) ? 1.0 : (real_t)cbk.amount / inv_total_weight; + recovered = true; Vector2 recover_motion; @@ -701,7 +713,7 @@ bool GodotSpace2D::test_body_motion(GodotBody2D *p_body, const PhysicsServer2D:: real_t depth = n.dot(a + recover_motion) - d; if (depth > min_contact_depth + CMP_EPSILON) { // Only recover if there is penetration. - recover_motion -= n * (depth - min_contact_depth) * 0.4; + recover_motion -= n * (depth - min_contact_depth) * 0.4 * priorities[i] * inv_total_weight; } } diff --git a/servers/physics_3d/godot_collision_object_3d.h b/servers/physics_3d/godot_collision_object_3d.h index 0f09f21962..2d342f65f3 100644 --- a/servers/physics_3d/godot_collision_object_3d.h +++ b/servers/physics_3d/godot_collision_object_3d.h @@ -59,6 +59,7 @@ private: ObjectID instance_id; uint32_t collision_layer = 1; uint32_t collision_mask = 1; + real_t collision_priority = 1.0; struct Shape { Transform3D xform; @@ -165,6 +166,13 @@ public: } _FORCE_INLINE_ uint32_t get_collision_mask() const { return collision_mask; } + _FORCE_INLINE_ void set_collision_priority(real_t p_priority) { + ERR_FAIL_COND_MSG(p_priority <= 0, "Priority must be greater than 0."); + collision_priority = p_priority; + _shape_changed(); + } + _FORCE_INLINE_ real_t get_collision_priority() const { return collision_priority; } + _FORCE_INLINE_ bool collides_with(GodotCollisionObject3D *p_other) const { return p_other->collision_layer & collision_mask; } diff --git a/servers/physics_3d/godot_physics_server_3d.cpp b/servers/physics_3d/godot_physics_server_3d.cpp index b735283ebe..9c1535f561 100644 --- a/servers/physics_3d/godot_physics_server_3d.cpp +++ b/servers/physics_3d/godot_physics_server_3d.cpp @@ -593,6 +593,20 @@ uint32_t GodotPhysicsServer3D::body_get_collision_mask(RID p_body) const { return body->get_collision_mask(); } +void GodotPhysicsServer3D::body_set_collision_priority(RID p_body, real_t p_priority) { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + body->set_collision_priority(p_priority); +} + +real_t GodotPhysicsServer3D::body_get_collision_priority(RID p_body) const { + const GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!body, 0); + + return body->get_collision_priority(); +} + void GodotPhysicsServer3D::body_attach_object_instance_id(RID p_body, ObjectID p_id) { GodotBody3D *body = body_owner.get_or_null(p_body); if (body) { diff --git a/servers/physics_3d/godot_physics_server_3d.h b/servers/physics_3d/godot_physics_server_3d.h index 1d57451925..b429f23a0c 100644 --- a/servers/physics_3d/godot_physics_server_3d.h +++ b/servers/physics_3d/godot_physics_server_3d.h @@ -192,6 +192,9 @@ public: virtual void body_set_collision_mask(RID p_body, uint32_t p_mask) override; virtual uint32_t body_get_collision_mask(RID p_body) const override; + virtual void body_set_collision_priority(RID p_body, real_t p_priority) override; + virtual real_t body_get_collision_priority(RID p_body) const override; + virtual void body_set_user_flags(RID p_body, uint32_t p_flags) override; virtual uint32_t body_get_user_flags(RID p_body) const override; diff --git a/servers/physics_3d/godot_space_3d.cpp b/servers/physics_3d/godot_space_3d.cpp index 13e9a89b2e..074232dd66 100644 --- a/servers/physics_3d/godot_space_3d.cpp +++ b/servers/physics_3d/godot_space_3d.cpp @@ -701,6 +701,7 @@ bool GodotSpace3D::test_body_motion(GodotBody3D *p_body, const PhysicsServer3D:: const int max_results = 32; int recover_attempts = 4; Vector3 sr[max_results * 2]; + real_t priorities[max_results]; do { GodotPhysicsServer3D::CollCbkData cbk; @@ -710,6 +711,7 @@ bool GodotSpace3D::test_body_motion(GodotBody3D *p_body, const PhysicsServer3D:: GodotPhysicsServer3D::CollCbkData *cbkptr = &cbk; GodotCollisionSolver3D::CallbackResult cbkres = GodotPhysicsServer3D::_shape_col_cbk; + int priority_amount = 0; bool collided = false; @@ -737,6 +739,10 @@ bool GodotSpace3D::test_body_motion(GodotBody3D *p_body, const PhysicsServer3D:: if (GodotCollisionSolver3D::solve_static(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), cbkres, cbkptr, nullptr, margin)) { collided = cbk.amount > 0; } + while (cbk.amount > priority_amount) { + priorities[priority_amount] = col_obj->get_collision_priority(); + priority_amount++; + } } } @@ -744,6 +750,12 @@ bool GodotSpace3D::test_body_motion(GodotBody3D *p_body, const PhysicsServer3D:: break; } + real_t inv_total_weight = 0.0; + for (int i = 0; i < cbk.amount; i++) { + inv_total_weight += priorities[i]; + } + inv_total_weight = Math::is_zero_approx(inv_total_weight) ? 1.0 : (real_t)cbk.amount / inv_total_weight; + recovered = true; Vector3 recover_motion; @@ -759,7 +771,7 @@ bool GodotSpace3D::test_body_motion(GodotBody3D *p_body, const PhysicsServer3D:: real_t depth = n.dot(a + recover_motion) - d; if (depth > min_contact_depth + CMP_EPSILON) { // Only recover if there is penetration. - recover_motion -= n * (depth - min_contact_depth) * 0.4; + recover_motion -= n * (depth - min_contact_depth) * 0.4 * priorities[i] * inv_total_weight; } } diff --git a/servers/physics_server_2d.cpp b/servers/physics_server_2d.cpp index 26768e300c..bfb5cd8106 100644 --- a/servers/physics_server_2d.cpp +++ b/servers/physics_server_2d.cpp @@ -32,6 +32,7 @@ #include "core/config/project_settings.h" #include "core/string/print_string.h" +#include "core/variant/typed_array.h" PhysicsServer2D *PhysicsServer2D::singleton = nullptr; @@ -347,7 +348,7 @@ Dictionary PhysicsDirectSpaceState2D::_intersect_ray(const Ref<PhysicsRayQueryPa return d; } -Array PhysicsDirectSpaceState2D::_intersect_point(const Ref<PhysicsPointQueryParameters2D> &p_point_query, int p_max_results) { +TypedArray<Dictionary> PhysicsDirectSpaceState2D::_intersect_point(const Ref<PhysicsPointQueryParameters2D> &p_point_query, int p_max_results) { ERR_FAIL_COND_V(p_point_query.is_null(), Array()); Vector<ShapeResult> ret; @@ -356,10 +357,10 @@ Array PhysicsDirectSpaceState2D::_intersect_point(const Ref<PhysicsPointQueryPar int rc = intersect_point(p_point_query->get_parameters(), ret.ptrw(), ret.size()); if (rc == 0) { - return Array(); + return TypedArray<Dictionary>(); } - Array r; + TypedArray<Dictionary> r; r.resize(rc); for (int i = 0; i < rc; i++) { Dictionary d; @@ -372,13 +373,13 @@ Array PhysicsDirectSpaceState2D::_intersect_point(const Ref<PhysicsPointQueryPar return r; } -Array PhysicsDirectSpaceState2D::_intersect_shape(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query, int p_max_results) { - ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array()); +TypedArray<Dictionary> PhysicsDirectSpaceState2D::_intersect_shape(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query, int p_max_results) { + ERR_FAIL_COND_V(!p_shape_query.is_valid(), TypedArray<Dictionary>()); Vector<ShapeResult> sr; sr.resize(p_max_results); int rc = intersect_shape(p_shape_query->get_parameters(), sr.ptrw(), sr.size()); - Array ret; + TypedArray<Dictionary> ret; ret.resize(rc); for (int i = 0; i < rc; i++) { Dictionary d; @@ -392,22 +393,22 @@ Array PhysicsDirectSpaceState2D::_intersect_shape(const Ref<PhysicsShapeQueryPar return ret; } -Array PhysicsDirectSpaceState2D::_cast_motion(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query) { - ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array()); +Vector<real_t> PhysicsDirectSpaceState2D::_cast_motion(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query) { + ERR_FAIL_COND_V(!p_shape_query.is_valid(), Vector<real_t>()); real_t closest_safe, closest_unsafe; bool res = cast_motion(p_shape_query->get_parameters(), closest_safe, closest_unsafe); if (!res) { - return Array(); + return Vector<real_t>(); } - Array ret; + Vector<real_t> ret; ret.resize(2); - ret[0] = closest_safe; - ret[1] = closest_unsafe; + ret.write[0] = closest_safe; + ret.write[1] = closest_unsafe; return ret; } -Array PhysicsDirectSpaceState2D::_collide_shape(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query, int p_max_results) { +TypedArray<PackedVector2Array> PhysicsDirectSpaceState2D::_collide_shape(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query, int p_max_results) { ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array()); Vector<Vector2> ret; @@ -415,9 +416,9 @@ Array PhysicsDirectSpaceState2D::_collide_shape(const Ref<PhysicsShapeQueryParam int rc = 0; bool res = collide_shape(p_shape_query->get_parameters(), ret.ptrw(), p_max_results, rc); if (!res) { - return Array(); + return TypedArray<PackedVector2Array>(); } - Array r; + TypedArray<PackedVector2Array> r; r.resize(rc * 2); for (int i = 0; i < rc * 2; i++) { r[i] = ret[i]; @@ -706,6 +707,9 @@ void PhysicsServer2D::_bind_methods() { ClassDB::bind_method(D_METHOD("body_set_collision_mask", "body", "mask"), &PhysicsServer2D::body_set_collision_mask); ClassDB::bind_method(D_METHOD("body_get_collision_mask", "body"), &PhysicsServer2D::body_get_collision_mask); + ClassDB::bind_method(D_METHOD("body_set_collision_priority", "body", "priority"), &PhysicsServer2D::body_set_collision_priority); + ClassDB::bind_method(D_METHOD("body_get_collision_priority", "body"), &PhysicsServer2D::body_get_collision_priority); + ClassDB::bind_method(D_METHOD("body_set_param", "body", "param", "value"), &PhysicsServer2D::body_set_param); ClassDB::bind_method(D_METHOD("body_get_param", "body", "param"), &PhysicsServer2D::body_get_param); diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h index 6d95c591c2..d0c5a7189b 100644 --- a/servers/physics_server_2d.h +++ b/servers/physics_server_2d.h @@ -36,6 +36,8 @@ #include "core/object/ref_counted.h" class PhysicsDirectSpaceState2D; +template <typename T> +class TypedArray; class PhysicsDirectBodyState2D : public Object { GDCLASS(PhysicsDirectBodyState2D, Object); @@ -114,10 +116,10 @@ class PhysicsDirectSpaceState2D : public Object { GDCLASS(PhysicsDirectSpaceState2D, Object); Dictionary _intersect_ray(const Ref<PhysicsRayQueryParameters2D> &p_ray_query); - Array _intersect_point(const Ref<PhysicsPointQueryParameters2D> &p_point_query, int p_max_results = 32); - Array _intersect_shape(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query, int p_max_results = 32); - Array _cast_motion(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query); - Array _collide_shape(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query, int p_max_results = 32); + TypedArray<Dictionary> _intersect_point(const Ref<PhysicsPointQueryParameters2D> &p_point_query, int p_max_results = 32); + TypedArray<Dictionary> _intersect_shape(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query, int p_max_results = 32); + Vector<real_t> _cast_motion(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query); + TypedArray<PackedVector2Array> _collide_shape(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query, int p_max_results = 32); Dictionary _get_rest_info(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query); protected: @@ -393,6 +395,9 @@ public: virtual void body_set_collision_mask(RID p_body, uint32_t p_mask) = 0; virtual uint32_t body_get_collision_mask(RID p_body) const = 0; + virtual void body_set_collision_priority(RID p_body, real_t p_priority) = 0; + virtual real_t body_get_collision_priority(RID p_body) const = 0; + // common body variables enum BodyParameter { BODY_PARAM_BOUNCE, diff --git a/servers/physics_server_2d_wrap_mt.h b/servers/physics_server_2d_wrap_mt.h index ddb071f603..d080aac438 100644 --- a/servers/physics_server_2d_wrap_mt.h +++ b/servers/physics_server_2d_wrap_mt.h @@ -205,6 +205,9 @@ public: FUNC2(body_set_collision_mask, RID, uint32_t); FUNC1RC(uint32_t, body_get_collision_mask, RID); + FUNC2(body_set_collision_priority, RID, real_t); + FUNC1RC(real_t, body_get_collision_priority, RID); + FUNC3(body_set_param, RID, BodyParameter, const Variant &); FUNC2RC(Variant, body_get_param, RID, BodyParameter); diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp index f25db22e66..6dd5be9ea8 100644 --- a/servers/physics_server_3d.cpp +++ b/servers/physics_server_3d.cpp @@ -32,6 +32,7 @@ #include "core/config/project_settings.h" #include "core/string/print_string.h" +#include "core/variant/typed_array.h" void PhysicsServer3DRenderingServerHandler::set_vertex(int p_vertex_id, const void *p_vector3) { GDVIRTUAL_REQUIRED_CALL(_set_vertex, p_vertex_id, p_vector3); @@ -366,8 +367,8 @@ Dictionary PhysicsDirectSpaceState3D::_intersect_ray(const Ref<PhysicsRayQueryPa return d; } -Array PhysicsDirectSpaceState3D::_intersect_point(const Ref<PhysicsPointQueryParameters3D> &p_point_query, int p_max_results) { - ERR_FAIL_COND_V(p_point_query.is_null(), Array()); +TypedArray<Dictionary> PhysicsDirectSpaceState3D::_intersect_point(const Ref<PhysicsPointQueryParameters3D> &p_point_query, int p_max_results) { + ERR_FAIL_COND_V(p_point_query.is_null(), TypedArray<Dictionary>()); Vector<ShapeResult> ret; ret.resize(p_max_results); @@ -375,10 +376,10 @@ Array PhysicsDirectSpaceState3D::_intersect_point(const Ref<PhysicsPointQueryPar int rc = intersect_point(p_point_query->get_parameters(), ret.ptrw(), ret.size()); if (rc == 0) { - return Array(); + return TypedArray<Dictionary>(); } - Array r; + TypedArray<Dictionary> r; r.resize(rc); for (int i = 0; i < rc; i++) { Dictionary d; @@ -391,13 +392,13 @@ Array PhysicsDirectSpaceState3D::_intersect_point(const Ref<PhysicsPointQueryPar return r; } -Array PhysicsDirectSpaceState3D::_intersect_shape(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, int p_max_results) { - ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array()); +TypedArray<Dictionary> PhysicsDirectSpaceState3D::_intersect_shape(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, int p_max_results) { + ERR_FAIL_COND_V(!p_shape_query.is_valid(), TypedArray<Dictionary>()); Vector<ShapeResult> sr; sr.resize(p_max_results); int rc = intersect_shape(p_shape_query->get_parameters(), sr.ptrw(), sr.size()); - Array ret; + TypedArray<Dictionary> ret; ret.resize(rc); for (int i = 0; i < rc; i++) { Dictionary d; @@ -411,22 +412,22 @@ Array PhysicsDirectSpaceState3D::_intersect_shape(const Ref<PhysicsShapeQueryPar return ret; } -Array PhysicsDirectSpaceState3D::_cast_motion(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query) { - ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array()); +Vector<real_t> PhysicsDirectSpaceState3D::_cast_motion(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query) { + ERR_FAIL_COND_V(!p_shape_query.is_valid(), Vector<real_t>()); real_t closest_safe = 1.0f, closest_unsafe = 1.0f; bool res = cast_motion(p_shape_query->get_parameters(), closest_safe, closest_unsafe); if (!res) { - return Array(); + return Vector<real_t>(); } - Array ret; + Vector<real_t> ret; ret.resize(2); - ret[0] = closest_safe; - ret[1] = closest_unsafe; + ret.write[0] = closest_safe; + ret.write[1] = closest_unsafe; return ret; } -Array PhysicsDirectSpaceState3D::_collide_shape(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, int p_max_results) { +TypedArray<PackedVector2Array> PhysicsDirectSpaceState3D::_collide_shape(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, int p_max_results) { ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array()); Vector<Vector3> ret; @@ -434,9 +435,9 @@ Array PhysicsDirectSpaceState3D::_collide_shape(const Ref<PhysicsShapeQueryParam int rc = 0; bool res = collide_shape(p_shape_query->get_parameters(), ret.ptrw(), p_max_results, rc); if (!res) { - return Array(); + return TypedArray<PackedVector2Array>(); } - Array r; + TypedArray<PackedVector2Array> r; r.resize(rc * 2); for (int i = 0; i < rc * 2; i++) { r[i] = ret[i]; @@ -750,6 +751,9 @@ void PhysicsServer3D::_bind_methods() { ClassDB::bind_method(D_METHOD("body_set_collision_mask", "body", "mask"), &PhysicsServer3D::body_set_collision_mask); ClassDB::bind_method(D_METHOD("body_get_collision_mask", "body"), &PhysicsServer3D::body_get_collision_mask); + ClassDB::bind_method(D_METHOD("body_set_collision_priority", "body", "priority"), &PhysicsServer3D::body_set_collision_priority); + ClassDB::bind_method(D_METHOD("body_get_collision_priority", "body"), &PhysicsServer3D::body_get_collision_priority); + ClassDB::bind_method(D_METHOD("body_add_shape", "body", "shape", "transform", "disabled"), &PhysicsServer3D::body_add_shape, DEFVAL(Transform3D()), DEFVAL(false)); ClassDB::bind_method(D_METHOD("body_set_shape", "body", "shape_idx", "shape"), &PhysicsServer3D::body_set_shape); ClassDB::bind_method(D_METHOD("body_set_shape_transform", "body", "shape_idx", "transform"), &PhysicsServer3D::body_set_shape_transform); diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h index 12497c0bdf..d5c4d9713b 100644 --- a/servers/physics_server_3d.h +++ b/servers/physics_server_3d.h @@ -38,6 +38,8 @@ #include "core/variant/native_ptr.h" class PhysicsDirectSpaceState3D; +template <typename T> +class TypedArray; class PhysicsDirectBodyState3D : public Object { GDCLASS(PhysicsDirectBodyState3D, Object); @@ -120,10 +122,10 @@ class PhysicsDirectSpaceState3D : public Object { private: Dictionary _intersect_ray(const Ref<PhysicsRayQueryParameters3D> &p_ray_query); - Array _intersect_point(const Ref<PhysicsPointQueryParameters3D> &p_point_query, int p_max_results = 32); - Array _intersect_shape(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, int p_max_results = 32); - Array _cast_motion(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query); - Array _collide_shape(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, int p_max_results = 32); + TypedArray<Dictionary> _intersect_point(const Ref<PhysicsPointQueryParameters3D> &p_point_query, int p_max_results = 32); + TypedArray<Dictionary> _intersect_shape(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, int p_max_results = 32); + Vector<real_t> _cast_motion(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query); + TypedArray<PackedVector2Array> _collide_shape(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, int p_max_results = 32); Dictionary _get_rest_info(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query); protected: @@ -421,6 +423,9 @@ public: virtual void body_set_collision_mask(RID p_body, uint32_t p_mask) = 0; virtual uint32_t body_get_collision_mask(RID p_body) const = 0; + virtual void body_set_collision_priority(RID p_body, real_t p_priority) = 0; + virtual real_t body_get_collision_priority(RID p_body) const = 0; + virtual void body_set_user_flags(RID p_body, uint32_t p_flags) = 0; virtual uint32_t body_get_user_flags(RID p_body) const = 0; diff --git a/servers/physics_server_3d_wrap_mt.h b/servers/physics_server_3d_wrap_mt.h index d4a4ad3132..ed4546b240 100644 --- a/servers/physics_server_3d_wrap_mt.h +++ b/servers/physics_server_3d_wrap_mt.h @@ -202,6 +202,9 @@ public: FUNC2(body_set_collision_mask, RID, uint32_t); FUNC1RC(uint32_t, body_get_collision_mask, RID); + FUNC2(body_set_collision_priority, RID, real_t); + FUNC1RC(real_t, body_get_collision_priority, RID); + FUNC2(body_set_user_flags, RID, uint32_t); FUNC1RC(uint32_t, body_get_user_flags, RID); diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp index 86e5e4802b..aa9772a483 100644 --- a/servers/rendering/renderer_canvas_cull.cpp +++ b/servers/rendering/renderer_canvas_cull.cpp @@ -1183,6 +1183,38 @@ void RendererCanvasCull::canvas_item_add_msdf_texture_rect_region(RID p_item, co rect->px_range = p_px_range; } +void RendererCanvasCull::canvas_item_add_lcd_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate) { + Item *canvas_item = canvas_item_owner.get_or_null(p_item); + ERR_FAIL_COND(!canvas_item); + + Item::CommandRect *rect = canvas_item->alloc_command<Item::CommandRect>(); + ERR_FAIL_COND(!rect); + rect->modulate = p_modulate; + rect->rect = p_rect; + + rect->texture = p_texture; + + rect->source = p_src_rect; + rect->flags = RendererCanvasRender::CANVAS_RECT_REGION | RendererCanvasRender::CANVAS_RECT_LCD; + + if (p_rect.size.x < 0) { + rect->flags |= RendererCanvasRender::CANVAS_RECT_FLIP_H; + rect->rect.size.x = -rect->rect.size.x; + } + if (p_src_rect.size.x < 0) { + rect->flags ^= RendererCanvasRender::CANVAS_RECT_FLIP_H; + rect->source.size.x = -rect->source.size.x; + } + if (p_rect.size.y < 0) { + rect->flags |= RendererCanvasRender::CANVAS_RECT_FLIP_V; + rect->rect.size.y = -rect->rect.size.y; + } + if (p_src_rect.size.y < 0) { + rect->flags ^= RendererCanvasRender::CANVAS_RECT_FLIP_V; + rect->source.size.y = -rect->source.size.y; + } +} + void RendererCanvasCull::canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, bool p_clip_uv) { Item *canvas_item = canvas_item_owner.get_or_null(p_item); ERR_FAIL_COND(!canvas_item); diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h index e8c54310c9..0d6a4006f8 100644 --- a/servers/rendering/renderer_canvas_cull.h +++ b/servers/rendering/renderer_canvas_cull.h @@ -225,6 +225,7 @@ public: void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false); void canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, bool p_clip_uv = false); void canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, float p_px_range = 1.0); + void canvas_item_add_lcd_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1)); void canvas_item_add_nine_patch(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector2 &p_topleft, const Vector2 &p_bottomright, RS::NinePatchAxisMode p_x_axis_mode = RS::NINE_PATCH_STRETCH, RS::NinePatchAxisMode p_y_axis_mode = RS::NINE_PATCH_STRETCH, bool p_draw_center = true, const Color &p_modulate = Color(1, 1, 1)); void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width = 1.0); void canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), RID p_texture = RID()); diff --git a/servers/rendering/renderer_canvas_render.h b/servers/rendering/renderer_canvas_render.h index 11a7d34291..6791ed9626 100644 --- a/servers/rendering/renderer_canvas_render.h +++ b/servers/rendering/renderer_canvas_render.h @@ -46,6 +46,7 @@ public: CANVAS_RECT_CLIP_UV = 32, CANVAS_RECT_IS_GROUP = 64, CANVAS_RECT_MSDF = 128, + CANVAS_RECT_LCD = 256, }; struct Light { @@ -193,7 +194,7 @@ public: Rect2 rect; Color modulate; Rect2 source; - uint8_t flags; + uint16_t flags; float outline; float px_range; diff --git a/servers/rendering/renderer_rd/environment/sky.cpp b/servers/rendering/renderer_rd/environment/sky.cpp index 6433a39863..d3601274b5 100644 --- a/servers/rendering/renderer_rd/environment/sky.cpp +++ b/servers/rendering/renderer_rd/environment/sky.cpp @@ -114,12 +114,16 @@ void SkyRD::SkyShaderData::set_code(const String &p_code) { for (int i = 0; i < gen_code.defines.size(); i++) { print_line(gen_code.defines[i]); } + + HashMap<String, String>::Iterator el = gen_code.code.begin(); + while (el) { + print_line("\n**code " + el->key + ":\n" + el->value); + ++el; + } + print_line("\n**uniforms:\n" + gen_code.uniforms); - // print_line("\n**vertex_globals:\n" + gen_code.vertex_global); - // print_line("\n**vertex_code:\n" + gen_code.vertex); - print_line("\n**fragment_globals:\n" + gen_code.fragment_global); - print_line("\n**fragment_code:\n" + gen_code.fragment); - print_line("\n**light_code:\n" + gen_code.light); + print_line("\n**vertex_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX]); + print_line("\n**fragment_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT]); #endif scene_singleton->sky.sky_shader.shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines); diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp index 556db086b2..0911ee595f 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp @@ -150,6 +150,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { depth_draw = DepthDraw(depth_drawi); depth_test = DepthTest(depth_testi); cull_mode = Cull(cull_modei); + uses_screen_texture_mipmaps = gen_code.uses_screen_texture_mipmaps; #if 0 print_line("**compiling shader:"); @@ -158,11 +159,10 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { print_line(gen_code.defines[i]); } - RBMap<String, String>::Element *el = gen_code.code.front(); + HashMap<String, String>::Iterator el = gen_code.code.begin(); while (el) { - print_line("\n**code " + el->key() + ":\n" + el->value()); - - el = el->next(); + print_line("\n**code " + el->key + ":\n" + el->value); + ++el; } print_line("\n**uniforms:\n" + gen_code.uniforms); @@ -396,7 +396,11 @@ void SceneShaderForwardClustered::ShaderData::get_shader_uniform_list(List<Prope HashMap<int, StringName> order; for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { - if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) { + if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL || + E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE || + E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE || + E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) { + // Don't expose any of these. continue; } diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h index fa9ebde1b2..d6b526fa4a 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h @@ -174,6 +174,7 @@ public: bool uses_time = false; bool writes_modelview_or_projection = false; bool uses_world_coordinates = false; + bool uses_screen_texture_mipmaps = false; Cull cull_mode = CULL_DISABLED; uint64_t last_pass = 0; diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp index 01b54607bc..85c9e1db2a 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp @@ -158,11 +158,10 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) { print_line(gen_code.defines[i]); } - RBMap<String, String>::Element * el = gen_code.code.front(); + HashMap<String, String>::Iterator el = gen_code.code.begin(); while (el) { - print_line("\n**code " + el->key() + ":\n" + el->value()); - - el = el->next(); + print_line("\n**code " + el->key + ":\n" + el->value); + ++el; } print_line("\n**uniforms:\n" + gen_code.uniforms); @@ -353,7 +352,10 @@ void SceneShaderForwardMobile::ShaderData::get_shader_uniform_list(List<Property HashMap<int, StringName> order; for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { - if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) { + if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL || + E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE || + E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE || + E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) { continue; } diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index c1b08ee4c9..937585c98b 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -494,7 +494,11 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend } //bind pipeline - { + if (rect->flags & CANVAS_RECT_LCD) { + RID pipeline = pipeline_variants->variants[light_mode][PIPELINE_VARIANT_QUAD_LCD_BLEND].get_render_pipeline(RD::INVALID_ID, p_framebuffer_format); + RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline); + RD::get_singleton()->draw_list_set_blend_constants(p_draw_list, rect->modulate); + } else { RID pipeline = pipeline_variants->variants[light_mode][PIPELINE_VARIANT_QUAD].get_render_pipeline(RD::INVALID_ID, p_framebuffer_format); RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline); } @@ -556,6 +560,8 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend push_constant.msdf[1] = rect->outline; // Outline size. push_constant.msdf[2] = 0.f; // Reserved. push_constant.msdf[3] = 0.f; // Reserved. + } else if (rect->flags & CANVAS_RECT_LCD) { + push_constant.flags |= FLAGS_USE_LCD; } push_constant.modulation[0] = rect->modulate.r * base_color.r; @@ -1361,6 +1367,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p Item *ci = p_item_list; Rect2 back_buffer_rect; bool backbuffer_copy = false; + bool backbuffer_gen_mipmaps = false; Item *canvas_group_owner = nullptr; @@ -1389,6 +1396,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p if (!material_screen_texture_found) { backbuffer_copy = true; back_buffer_rect = Rect2(); + backbuffer_gen_mipmaps = md->shader_data->uses_screen_texture_mipmaps; } } @@ -1474,9 +1482,10 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list); item_count = 0; - texture_storage->render_target_copy_to_back_buffer(p_to_render_target, back_buffer_rect, true); + texture_storage->render_target_copy_to_back_buffer(p_to_render_target, back_buffer_rect, backbuffer_gen_mipmaps); backbuffer_copy = false; + backbuffer_gen_mipmaps = false; material_screen_texture_found = true; //after a backbuffer copy, screen texture makes no further copies } @@ -1980,6 +1989,7 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) { ubo_size = 0; uniforms.clear(); uses_screen_texture = false; + uses_screen_texture_mipmaps = false; uses_sdf = false; uses_time = false; @@ -1990,7 +2000,6 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) { ShaderCompiler::GeneratedCode gen_code; int blend_mode = BLEND_MODE_MIX; - uses_screen_texture = false; ShaderCompiler::IdentifierActions actions; actions.entry_point_stages["vertex"] = ShaderCompiler::STAGE_VERTEX; @@ -2015,6 +2024,8 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) { Error err = canvas_singleton->shader.compiler.compile(RS::SHADER_CANVAS_ITEM, code, &actions, path, gen_code); ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed."); + uses_screen_texture_mipmaps = gen_code.uses_screen_texture_mipmaps; + if (version.is_null()) { version = canvas_singleton->shader.canvas_shader.version_create(); } @@ -2025,12 +2036,16 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) { for (int i = 0; i < gen_code.defines.size(); i++) { print_line(gen_code.defines[i]); } + + HashMap<String, String>::Iterator el = gen_code.code.begin(); + while (el) { + print_line("\n**code " + el->key + ":\n" + el->value); + ++el; + } + print_line("\n**uniforms:\n" + gen_code.uniforms); - print_line("\n**vertex_globals:\n" + gen_code.vertex_global); - print_line("\n**vertex_code:\n" + gen_code.vertex); - print_line("\n**fragment_globals:\n" + gen_code.fragment_global); - print_line("\n**fragment_code:\n" + gen_code.fragment); - print_line("\n**light_code:\n" + gen_code.light); + print_line("\n**vertex_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX]); + print_line("\n**fragment_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT]); #endif canvas_singleton->shader.canvas_shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines); ERR_FAIL_COND(!canvas_singleton->shader.canvas_shader.version_is_valid(version)); @@ -2104,6 +2119,18 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) { RD::PipelineColorBlendState blend_state; blend_state.attachments.push_back(attachment); + RD::PipelineColorBlendState::Attachment attachment_lcd; + attachment_lcd.enable_blend = true; + attachment_lcd.alpha_blend_op = RD::BLEND_OP_ADD; + attachment_lcd.color_blend_op = RD::BLEND_OP_ADD; + attachment_lcd.src_color_blend_factor = RD::BLEND_FACTOR_CONSTANT_COLOR; + attachment_lcd.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_COLOR; + attachment_lcd.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE; + attachment_lcd.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + + RD::PipelineColorBlendState blend_state_lcd; + blend_state_lcd.attachments.push_back(attachment_lcd); + //update pipelines for (int i = 0; i < PIPELINE_LIGHT_MODE_MAX; i++) { @@ -2119,10 +2146,12 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) { RD::RENDER_PRIMITIVE_LINES, RD::RENDER_PRIMITIVE_LINESTRIPS, RD::RENDER_PRIMITIVE_POINTS, + RD::RENDER_PRIMITIVE_TRIANGLES, }; ShaderVariant shader_variants[PIPELINE_LIGHT_MODE_MAX][PIPELINE_VARIANT_MAX] = { - { //non lit + { + //non lit SHADER_VARIANT_QUAD, SHADER_VARIANT_NINEPATCH, SHADER_VARIANT_PRIMITIVE, @@ -2132,8 +2161,11 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) { SHADER_VARIANT_ATTRIBUTES, SHADER_VARIANT_ATTRIBUTES, SHADER_VARIANT_ATTRIBUTES, - SHADER_VARIANT_ATTRIBUTES_POINTS }, - { //lit + SHADER_VARIANT_ATTRIBUTES_POINTS, + SHADER_VARIANT_QUAD, + }, + { + //lit SHADER_VARIANT_QUAD_LIGHT, SHADER_VARIANT_NINEPATCH_LIGHT, SHADER_VARIANT_PRIMITIVE_LIGHT, @@ -2143,11 +2175,17 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) { SHADER_VARIANT_ATTRIBUTES_LIGHT, SHADER_VARIANT_ATTRIBUTES_LIGHT, SHADER_VARIANT_ATTRIBUTES_LIGHT, - SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT }, + SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT, + SHADER_VARIANT_QUAD_LIGHT, + }, }; RID shader_variant = canvas_singleton->shader.canvas_shader.version_get_shader(version, shader_variants[i][j]); - pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0); + if (j == PIPELINE_VARIANT_QUAD_LCD_BLEND) { + pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state_lcd, RD::DYNAMIC_STATE_BLEND_CONSTANTS); + } else { + pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0); + } } } @@ -2175,7 +2213,11 @@ void RendererCanvasRenderRD::CanvasShaderData::get_shader_uniform_list(List<Prop HashMap<int, StringName> order; for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { - if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) { + if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL || + E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE || + E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE || + E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) { + // Don't expose any of these. continue; } if (E.value.texture_order >= 0) { @@ -2350,6 +2392,18 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() { blend_state.attachments.push_back(blend_attachment); + RD::PipelineColorBlendState::Attachment attachment_lcd; + attachment_lcd.enable_blend = true; + attachment_lcd.alpha_blend_op = RD::BLEND_OP_ADD; + attachment_lcd.color_blend_op = RD::BLEND_OP_ADD; + attachment_lcd.src_color_blend_factor = RD::BLEND_FACTOR_CONSTANT_COLOR; + attachment_lcd.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_COLOR; + attachment_lcd.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE; + attachment_lcd.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + + RD::PipelineColorBlendState blend_state_lcd; + blend_state_lcd.attachments.push_back(attachment_lcd); + for (int i = 0; i < PIPELINE_LIGHT_MODE_MAX; i++) { for (int j = 0; j < PIPELINE_VARIANT_MAX; j++) { RD::RenderPrimitive primitive[PIPELINE_VARIANT_MAX] = { @@ -2363,10 +2417,12 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() { RD::RENDER_PRIMITIVE_LINES, RD::RENDER_PRIMITIVE_LINESTRIPS, RD::RENDER_PRIMITIVE_POINTS, + RD::RENDER_PRIMITIVE_TRIANGLES, }; ShaderVariant shader_variants[PIPELINE_LIGHT_MODE_MAX][PIPELINE_VARIANT_MAX] = { - { //non lit + { + //non lit SHADER_VARIANT_QUAD, SHADER_VARIANT_NINEPATCH, SHADER_VARIANT_PRIMITIVE, @@ -2376,8 +2432,11 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() { SHADER_VARIANT_ATTRIBUTES, SHADER_VARIANT_ATTRIBUTES, SHADER_VARIANT_ATTRIBUTES, - SHADER_VARIANT_ATTRIBUTES_POINTS }, - { //lit + SHADER_VARIANT_ATTRIBUTES_POINTS, + SHADER_VARIANT_QUAD, + }, + { + //lit SHADER_VARIANT_QUAD_LIGHT, SHADER_VARIANT_NINEPATCH_LIGHT, SHADER_VARIANT_PRIMITIVE_LIGHT, @@ -2387,11 +2446,17 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() { SHADER_VARIANT_ATTRIBUTES_LIGHT, SHADER_VARIANT_ATTRIBUTES_LIGHT, SHADER_VARIANT_ATTRIBUTES_LIGHT, - SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT }, + SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT, + SHADER_VARIANT_QUAD_LIGHT, + }, }; RID shader_variant = shader.canvas_shader.version_get_shader(shader.default_version, shader_variants[i][j]); - shader.pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0); + if (j == PIPELINE_VARIANT_QUAD_LCD_BLEND) { + shader.pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state_lcd, RD::DYNAMIC_STATE_BLEND_CONSTANTS); + } else { + shader.pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0); + } } } } diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h index 5eb4cee4c6..54077a5b9a 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h @@ -85,6 +85,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender { FLAGS_DEFAULT_SPECULAR_MAP_USED = (1 << 27), FLAGS_USE_MSDF = (1 << 28), + FLAGS_USE_LCD = (1 << 29), }; enum { @@ -122,6 +123,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender { PIPELINE_VARIANT_ATTRIBUTE_LINES, PIPELINE_VARIANT_ATTRIBUTE_LINES_STRIP, PIPELINE_VARIANT_ATTRIBUTE_POINTS, + PIPELINE_VARIANT_QUAD_LCD_BLEND, PIPELINE_VARIANT_MAX }; enum PipelineLightMode { @@ -174,6 +176,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender { HashMap<StringName, HashMap<int, RID>> default_texture_params; bool uses_screen_texture = false; + bool uses_screen_texture_mipmaps = false; bool uses_sdf = false; bool uses_time = false; diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index 6c219933b0..d8499681ad 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -2868,7 +2868,9 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const WARN_PRINT_ONCE("The DirectionalLight3D PSSM splits debug draw mode is not reimplemented yet."); } - light_data.shadow_opacity = p_using_shadows && light_storage->light_has_shadow(base) ? light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_OPACITY) : 0.0; + light_data.shadow_opacity = (p_using_shadows && light_storage->light_has_shadow(base)) + ? light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_OPACITY) + : 0.0; float angular_diameter = light_storage->light_get_param(base, RS::LIGHT_PARAM_SIZE); if (angular_diameter > 0.0) { @@ -3122,7 +3124,11 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const light_data.projector_rect[3] = 0; } - const bool needs_shadow = shadow_atlas && shadow_atlas->shadow_owners.has(li->self); + const bool needs_shadow = + shadow_atlas && + shadow_atlas->shadow_owners.has(li->self) && + p_using_shadows && + light_storage->light_has_shadow(base); bool in_shadow_range = true; if (needs_shadow && light_storage->light_is_distance_fade_enabled(li->light)) { diff --git a/servers/rendering/renderer_rd/shaders/canvas.glsl b/servers/rendering/renderer_rd/shaders/canvas.glsl index f8e9020f9f..459d798a80 100644 --- a/servers/rendering/renderer_rd/shaders/canvas.glsl +++ b/servers/rendering/renderer_rd/shaders/canvas.glsl @@ -509,7 +509,13 @@ void main() { float a = clamp(d * px_size + 0.5, 0.0, 1.0); color.a = a * color.a; } - + } else if (bool(draw_data.flags & FLAGS_USE_LCD)) { + vec4 lcd_sample = texture(sampler2D(color_texture, texture_sampler), uv); + if (lcd_sample.a == 1.0) { + color.rgb = lcd_sample.rgb * color.a; + } else { + color = vec4(0.0, 0.0, 0.0, 0.0); + } } else { #else { diff --git a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl index 2ea6965c09..1b627a3e81 100644 --- a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl @@ -25,6 +25,7 @@ #define FLAGS_DEFAULT_SPECULAR_MAP_USED (1 << 27) #define FLAGS_USE_MSDF (1 << 28) +#define FLAGS_USE_LCD (1 << 29) #define SAMPLER_NEAREST_CLAMP 0 #define SAMPLER_LINEAR_CLAMP 1 diff --git a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl index 0438671dd2..0b43af7738 100644 --- a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl @@ -30,7 +30,7 @@ layout(set = 1, binding = 0) uniform sampler2D source_bokeh; #ifdef MODE_GEN_BLUR_SIZE float get_depth_at_pos(vec2 uv) { - float depth = textureLod(source_depth, uv, 0.0).x; + float depth = textureLod(source_depth, uv, 0.0).x * 2.0 - 1.0; if (params.orthogonal) { depth = ((depth + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0; } else { diff --git a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl index a3b3938ee9..a06cacfabe 100644 --- a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl @@ -52,7 +52,7 @@ layout(set = 2, binding = 0) uniform sampler2D original_weight; #ifdef MODE_GEN_BLUR_SIZE float get_depth_at_pos(vec2 uv) { - float depth = textureLod(source_depth, uv, 0.0).x; + float depth = textureLod(source_depth, uv, 0.0).x * 2.0 - 1.0; if (params.orthogonal) { depth = ((depth + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0; } else { diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl index e9515c7670..6b4e4a5a16 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl @@ -15,11 +15,11 @@ layout(location = 0) in vec3 vertex_attrib; //only for pure render depth when normal is not used #ifdef NORMAL_USED -layout(location = 1) in vec3 normal_attrib; +layout(location = 1) in vec2 normal_attrib; #endif #if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) -layout(location = 2) in vec4 tangent_attrib; +layout(location = 2) in vec2 tangent_attrib; #endif #if defined(COLOR_USED) @@ -58,6 +58,13 @@ layout(location = 10) in uvec4 bone_attrib; layout(location = 11) in vec4 weight_attrib; #endif +vec3 oct_to_vec3(vec2 e) { + vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y)); + float t = max(-v.z, 0.0); + v.xy += t * -sign(v.xy); + return v; +} + /* Varyings */ layout(location = 0) out vec3 vertex_interp; @@ -231,12 +238,13 @@ void vertex_shader(in uint instance_index, in bool is_multimesh, in SceneData sc vec3 vertex = vertex_attrib; #ifdef NORMAL_USED - vec3 normal = normal_attrib * 2.0 - 1.0; + vec3 normal = oct_to_vec3(normal_attrib * 2.0 - 1.0); #endif #if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) - vec3 tangent = tangent_attrib.xyz * 2.0 - 1.0; - float binormalf = tangent_attrib.a * 2.0 - 1.0; + vec2 signed_tangent_attrib = tangent_attrib * 2.0 - 1.0; + vec3 tangent = oct_to_vec3(vec2(signed_tangent_attrib.x, abs(signed_tangent_attrib.y) * 2.0 - 1.0)); + float binormalf = sign(signed_tangent_attrib.y); vec3 binormal = normalize(cross(normal, tangent) * binormalf); #endif diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl index 6548793bee..0960533917 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl @@ -16,11 +16,11 @@ layout(location = 0) in vec3 vertex_attrib; //only for pure render depth when normal is not used #ifdef NORMAL_USED -layout(location = 1) in vec3 normal_attrib; +layout(location = 1) in vec2 normal_attrib; #endif #if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) -layout(location = 2) in vec4 tangent_attrib; +layout(location = 2) in vec2 tangent_attrib; #endif #if defined(COLOR_USED) @@ -59,6 +59,13 @@ layout(location = 10) in uvec4 bone_attrib; layout(location = 11) in vec4 weight_attrib; #endif +vec3 oct_to_vec3(vec2 e) { + vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y)); + float t = max(-v.z, 0.0); + v.xy += t * -sign(v.xy); + return v; +} + /* Varyings */ layout(location = 0) highp out vec3 vertex_interp; @@ -229,12 +236,13 @@ void main() { vec3 vertex = vertex_attrib; #ifdef NORMAL_USED - vec3 normal = normal_attrib * 2.0 - 1.0; + vec3 normal = oct_to_vec3(normal_attrib * 2.0 - 1.0); #endif #if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) - vec3 tangent = tangent_attrib.xyz * 2.0 - 1.0; - float binormalf = tangent_attrib.a * 2.0 - 1.0; + vec3 signed_tangent_attrib = tangent_attrib * 2.0 - 1.0; + vec3 tangent = oct_to_vec3(vec2(signed_tangent_attrib.x, abs(signed_tangent_attrib.y) * 2.0 - 1.0)); + float binormalf = sign(signed_tangent_attrib.y); vec3 binormal = normalize(cross(normal, tangent) * binormalf); #endif diff --git a/servers/rendering/renderer_rd/shaders/skeleton.glsl b/servers/rendering/renderer_rd/shaders/skeleton.glsl index a893a66c94..75bea9300b 100644 --- a/servers/rendering/renderer_rd/shaders/skeleton.glsl +++ b/servers/rendering/renderer_rd/shaders/skeleton.glsl @@ -54,14 +54,54 @@ layout(push_constant, std430) uniform Params { } params; -vec4 decode_abgr_2_10_10_10(uint base) { - uvec4 abgr_2_10_10_10 = (uvec4(base) >> uvec4(0, 10, 20, 30)) & uvec4(0x3FF, 0x3FF, 0x3FF, 0x3); - return vec4(abgr_2_10_10_10) / vec4(1023.0, 1023.0, 1023.0, 3.0) * 2.0 - 1.0; +vec2 uint_to_vec2(uint base) { + uvec2 decode = (uvec2(base) >> uvec2(0, 16)) & uvec2(0xFFFF, 0xFFFF); + return vec2(decode) / vec2(65535.0, 65535.0) * 2.0 - 1.0; } -uint encode_abgr_2_10_10_10(vec4 base) { - uvec4 abgr_2_10_10_10 = uvec4(clamp(ivec4((base * 0.5 + 0.5) * vec4(1023.0, 1023.0, 1023.0, 3.0)), ivec4(0), ivec4(0x3FF, 0x3FF, 0x3FF, 0x3))) << uvec4(0, 10, 20, 30); - return abgr_2_10_10_10.x | abgr_2_10_10_10.y | abgr_2_10_10_10.z | abgr_2_10_10_10.w; +vec3 oct_to_vec3(vec2 oct) { + vec3 v = vec3(oct.xy, 1.0 - abs(oct.x) - abs(oct.y)); + float t = max(-v.z, 0.0); + v.xy += t * -sign(v.xy); + return v; +} + +vec3 decode_uint_oct_to_norm(uint base) { + return oct_to_vec3(uint_to_vec2(base)); +} + +vec4 decode_uint_oct_to_tang(uint base) { + vec2 oct_sign_encoded = uint_to_vec2(base); + // Binormal sign encoded in y component + vec2 oct = vec2(oct_sign_encoded.x, abs(oct_sign_encoded.y) * 2.0 - 1.0); + return vec4(oct_to_vec3(oct), sign(oct_sign_encoded.y)); +} + +vec2 signNotZero(vec2 v) { + return mix(vec2(-1.0), vec2(1.0), greaterThanEqual(v.xy, vec2(0.0))); +} + +uint vec2_to_uint(vec2 base) { + uvec2 enc = uvec2(clamp(ivec2(base * vec2(65535, 65535)), ivec2(0), ivec2(0xFFFF, 0xFFFF))) << uvec2(0, 16); + return enc.x | enc.y; +} + +vec2 vec3_to_oct(vec3 e) { + e /= abs(e.x) + abs(e.y) + abs(e.z); + vec2 oct = e.z >= 0.0f ? e.xy : (vec2(1.0f) - abs(e.yx)) * signNotZero(e.xy); + return oct * 0.5f + 0.5f; +} + +uint encode_norm_to_uint_oct(vec3 base) { + return vec2_to_uint(vec3_to_oct(base)); +} + +uint encode_tang_to_uint_oct(vec4 base) { + vec2 oct = vec3_to_oct(base.xyz); + // Encode binormal sign in y component + oct.y = oct.y * 0.5f + 0.5f; + oct.y = base.w >= 0.0f ? oct.y : 1 - oct.y; + return vec2_to_uint(oct); } void main() { @@ -131,12 +171,12 @@ void main() { src_offset += 3; if (params.has_normal) { - normal = decode_abgr_2_10_10_10(src_vertices.data[src_offset]).rgb; + normal = decode_uint_oct_to_norm(src_vertices.data[src_offset]); src_offset++; } if (params.has_tangent) { - tangent = decode_abgr_2_10_10_10(src_vertices.data[src_offset]); + tangent = decode_uint_oct_to_tang(src_vertices.data[src_offset]); } if (params.has_blend_shape) { @@ -155,12 +195,12 @@ void main() { base_offset += 3; if (params.has_normal) { - blend_normal += decode_abgr_2_10_10_10(src_blend_shapes.data[base_offset]).rgb * w; + blend_normal += decode_uint_oct_to_norm(src_blend_shapes.data[base_offset]) * w; base_offset++; } if (params.has_tangent) { - blend_tangent += decode_abgr_2_10_10_10(src_blend_shapes.data[base_offset]).rgb * w; + blend_tangent += decode_uint_oct_to_tang(src_blend_shapes.data[base_offset]).rgb * w; } blend_total += w; @@ -234,12 +274,12 @@ void main() { dst_offset += 3; if (params.has_normal) { - dst_vertices.data[dst_offset] = encode_abgr_2_10_10_10(vec4(normal, 0.0)); + dst_vertices.data[dst_offset] = encode_norm_to_uint_oct(normal); dst_offset++; } if (params.has_tangent) { - dst_vertices.data[dst_offset] = encode_abgr_2_10_10_10(tangent); + dst_vertices.data[dst_offset] = encode_tang_to_uint_oct(tangent); } #endif diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp index 41dd1ccc40..fa8406e7a1 100644 --- a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp @@ -941,6 +941,12 @@ void MaterialStorage::MaterialData::update_uniform_buffer(const HashMap<StringNa continue; //instance uniforms don't appear in the buffer } + if (E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE || + E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE || + E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) { + continue; + } + if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) { //this is a global variable, get the index to it GlobalShaderUniforms::Variable *gv = material_storage->global_shader_uniforms.variables.getptr(E.key); @@ -1052,6 +1058,12 @@ void MaterialStorage::MaterialData::update_textures(const HashMap<StringName, Va Vector<RID> textures; + if (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE || + p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE || + p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) { + continue; + } + if (p_texture_uniforms[i].global) { uses_global_textures = true; @@ -1307,7 +1319,7 @@ bool MaterialStorage::MaterialData::update_parameters_uniform_set(const HashMap< update_textures(p_parameters, p_default_texture_params, p_texture_uniforms, texture_cache.ptrw(), true); } - if (p_ubo_size == 0 && p_texture_uniforms.size() == 0) { + if (p_ubo_size == 0 && (p_texture_uniforms.size() == 0)) { // This material does not require an uniform set, so don't create it. return false; } diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp index dc3f35f942..49d7198ec2 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp @@ -327,8 +327,10 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) bool use_as_storage = (p_surface.skin_data.size() || mesh->blend_shape_count > 0); - s->vertex_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.vertex_data.size(), p_surface.vertex_data, use_as_storage); - s->vertex_buffer_size = p_surface.vertex_data.size(); + if (p_surface.vertex_data.size()) { + s->vertex_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.vertex_data.size(), p_surface.vertex_data, use_as_storage); + s->vertex_buffer_size = p_surface.vertex_data.size(); + } if (p_surface.attribute_data.size()) { s->attribute_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.attribute_data.size(), p_surface.attribute_data); @@ -345,7 +347,7 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) } if (p_surface.index_count) { - bool is_index_16 = p_surface.vertex_count <= 65536; + bool is_index_16 = p_surface.vertex_count <= 65536 && p_surface.vertex_count > 0; s->index_buffer = RD::get_singleton()->index_buffer_create(p_surface.index_count, is_index_16 ? RD::INDEX_BUFFER_FORMAT_UINT16 : RD::INDEX_BUFFER_FORMAT_UINT32, p_surface.index_data, false); s->index_count = p_surface.index_count; @@ -364,6 +366,8 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) } } + ERR_FAIL_COND_MSG(!p_surface.index_count && !p_surface.vertex_count, "Meshes must contain a vertex array, an index array, or both"); + s->aabb = p_surface.aabb; s->bone_aabbs = p_surface.bone_aabbs; //only really useful for returning them. @@ -377,7 +381,11 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) RD::Uniform u; u.binding = 0; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.append_id(s->vertex_buffer); + if (s->vertex_buffer.is_valid()) { + u.append_id(s->vertex_buffer); + } else { + u.append_id(default_rd_storage_buffer); + } uniforms.push_back(u); } { @@ -416,7 +424,10 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) mesh->bone_aabbs.resize(p_surface.bone_aabbs.size()); } for (int i = 0; i < p_surface.bone_aabbs.size(); i++) { - mesh->bone_aabbs.write[i].merge_with(p_surface.bone_aabbs[i]); + const AABB &bone = p_surface.bone_aabbs[i]; + if (!bone.has_no_volume()) { + mesh->bone_aabbs.write[i].merge_with(bone); + } } mesh->aabb.merge_with(p_surface.aabb); } @@ -467,6 +478,7 @@ void MeshStorage::mesh_surface_update_vertex_region(RID p_mesh, int p_surface, i ERR_FAIL_COND(!mesh); ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count); ERR_FAIL_COND(p_data.size() == 0); + ERR_FAIL_COND(mesh->surfaces[p_surface]->vertex_buffer.is_null()); uint64_t data_size = p_data.size(); const uint8_t *r = p_data.ptr(); @@ -524,7 +536,9 @@ RS::SurfaceData MeshStorage::mesh_get_surface(RID p_mesh, int p_surface) const { RS::SurfaceData sd; sd.format = s.format; - sd.vertex_data = RD::get_singleton()->buffer_get_data(s.vertex_buffer); + if (s.vertex_buffer.is_valid()) { + sd.vertex_data = RD::get_singleton()->buffer_get_data(s.vertex_buffer); + } if (s.attribute_buffer.is_valid()) { sd.attribute_data = RD::get_singleton()->buffer_get_data(s.attribute_buffer); } @@ -702,7 +716,9 @@ void MeshStorage::mesh_clear(RID p_mesh) { ERR_FAIL_COND(!mesh); for (uint32_t i = 0; i < mesh->surface_count; i++) { Mesh::Surface &s = *mesh->surfaces[i]; - RD::get_singleton()->free(s.vertex_buffer); //clears arrays as dependency automatically, including all versions + if (s.vertex_buffer.is_valid()) { + RD::get_singleton()->free(s.vertex_buffer); //clears arrays as dependency automatically, including all versions + } if (s.attribute_buffer.is_valid()) { RD::get_singleton()->free(s.attribute_buffer); } @@ -848,7 +864,7 @@ void MeshStorage::_mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint3 } MeshInstance::Surface s; - if (mesh->blend_shape_count > 0 || (mesh->surfaces[p_surface]->format & RS::ARRAY_FORMAT_BONES)) { + if ((mesh->blend_shape_count > 0 || (mesh->surfaces[p_surface]->format & RS::ARRAY_FORMAT_BONES)) && mesh->surfaces[p_surface]->vertex_buffer_size > 0) { //surface warrants transform s.vertex_buffer = RD::get_singleton()->vertex_buffer_create(mesh->surfaces[p_surface]->vertex_buffer_size, Vector<uint8_t>(), true); @@ -1057,10 +1073,9 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V } break; case RS::ARRAY_NORMAL: { vd.offset = stride; + vd.format = RD::DATA_FORMAT_R16G16_UNORM; + stride += sizeof(uint16_t) * 2; - vd.format = RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32; - - stride += sizeof(uint32_t); if (mis) { buffer = mis->vertex_buffer; } else { @@ -1069,9 +1084,9 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V } break; case RS::ARRAY_TANGENT: { vd.offset = stride; + vd.format = RD::DATA_FORMAT_R16G16_UNORM; + stride += sizeof(uint16_t) * 2; - vd.format = RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32; - stride += sizeof(uint32_t); if (mis) { buffer = mis->vertex_buffer; } else { diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp index ba644e7eb9..022b027644 100644 --- a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp @@ -134,7 +134,7 @@ void process() { material_storage->material_initialize(particles_shader.default_material); material_storage->material_set_shader(particles_shader.default_material, particles_shader.default_shader); - ParticlesMaterialData *md = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(particles_shader.default_material, MaterialStorage::SHADER_TYPE_PARTICLES)); + ParticleProcessMaterialData *md = static_cast<ParticleProcessMaterialData *>(material_storage->material_get_data(particles_shader.default_material, MaterialStorage::SHADER_TYPE_PARTICLES)); particles_shader.default_shader_rd = particles_shader.shader.version_get_shader(md->shader_data->version, 0); Vector<RD::Uniform> uniforms; @@ -1072,9 +1072,9 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta RD::get_singleton()->buffer_update(p_particles->frame_params_buffer, 0, sizeof(ParticlesFrameParams) * p_particles->trail_params.size(), p_particles->trail_params.ptr()); - ParticlesMaterialData *m = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(p_particles->process_material, MaterialStorage::SHADER_TYPE_PARTICLES)); + ParticleProcessMaterialData *m = static_cast<ParticleProcessMaterialData *>(material_storage->material_get_data(p_particles->process_material, MaterialStorage::SHADER_TYPE_PARTICLES)); if (!m) { - m = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(particles_shader.default_material, MaterialStorage::SHADER_TYPE_PARTICLES)); + m = static_cast<ParticleProcessMaterialData *>(material_storage->material_get_data(particles_shader.default_material, MaterialStorage::SHADER_TYPE_PARTICLES)); } ERR_FAIL_COND(!m); @@ -1696,16 +1696,16 @@ MaterialStorage::ShaderData *ParticlesStorage::_create_particles_shader_func() { return shader_data; } -bool ParticlesStorage::ParticlesMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { +bool ParticlesStorage::ParticleProcessMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, ParticlesStorage::get_singleton()->particles_shader.shader.version_get_shader(shader_data->version, 0), 3); } -ParticlesStorage::ParticlesMaterialData::~ParticlesMaterialData() { +ParticlesStorage::ParticleProcessMaterialData::~ParticleProcessMaterialData() { free_parameters_uniform_set(uniform_set); } MaterialStorage::MaterialData *ParticlesStorage::_create_particles_material_func(ParticlesShaderData *p_shader) { - ParticlesMaterialData *material_data = memnew(ParticlesMaterialData); + ParticleProcessMaterialData *material_data = memnew(ParticleProcessMaterialData); material_data->shader_data = p_shader; //update will happen later anyway so do nothing. return material_data; diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.h b/servers/rendering/renderer_rd/storage_rd/particles_storage.h index 97d100e2da..299fdc6ec8 100644 --- a/servers/rendering/renderer_rd/storage_rd/particles_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.h @@ -354,14 +354,14 @@ private: return ParticlesStorage::get_singleton()->_create_particles_shader_func(); } - struct ParticlesMaterialData : public MaterialStorage::MaterialData { + struct ParticleProcessMaterialData : public MaterialStorage::MaterialData { ParticlesShaderData *shader_data = nullptr; RID uniform_set; virtual void set_render_priority(int p_priority) {} virtual void set_next_pass(RID p_pass) {} virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); - virtual ~ParticlesMaterialData(); + virtual ~ParticleProcessMaterialData(); }; MaterialStorage::MaterialData *_create_particles_material_func(ParticlesShaderData *p_shader); diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp index 0b20bb372a..9f5eb85c2f 100644 --- a/servers/rendering/renderer_scene_cull.cpp +++ b/servers/rendering/renderer_scene_cull.cpp @@ -506,7 +506,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) { } if (instance->mesh_instance.is_valid()) { - RSG::mesh_storage->mesh_free(instance->mesh_instance); + RSG::mesh_storage->mesh_instance_free(instance->mesh_instance); instance->mesh_instance = RID(); // no need to set instance data flag here, as it was freed above } diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp index 73b03966c5..bfb81925bc 100644 --- a/servers/rendering/renderer_viewport.cpp +++ b/servers/rendering/renderer_viewport.cpp @@ -72,6 +72,41 @@ static Transform2D _canvas_get_transform(RendererViewport::Viewport *p_viewport, return xf; } +Vector<RendererViewport::Viewport *> RendererViewport::_sort_active_viewports() { + // We need to sort the viewports in a "topological order", + // children first and parents last, we use the Kahn's algorithm to achieve that. + + Vector<Viewport *> result; + List<Viewport *> nodes; + + for (Viewport *viewport : active_viewports) { + if (viewport->parent.is_valid()) { + continue; + } + + nodes.push_back(viewport); + } + + while (!nodes.is_empty()) { + Viewport *node = nodes[0]; + nodes.pop_front(); + + result.insert(0, node); + + for (Viewport *child : active_viewports) { + if (child->parent != node->self) { + continue; + } + + if (!nodes.find(child)) { + nodes.push_back(child); + } + } + } + + return result; +} + void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) { if (p_viewport->render_buffers.is_valid()) { if (p_viewport->size.width == 0 || p_viewport->size.height == 0) { @@ -548,8 +583,10 @@ void RendererViewport::draw_viewports() { set_default_clear_color(GLOBAL_GET("rendering/environment/defaults/default_clear_color")); } - //sort viewports - active_viewports.sort_custom<ViewportSort>(); + if (sorted_active_viewports_dirty) { + sorted_active_viewports = _sort_active_viewports(); + sorted_active_viewports_dirty = false; + } HashMap<DisplayServer::WindowID, Vector<BlitToScreen>> blit_to_screen_list; //draw viewports @@ -558,9 +595,9 @@ void RendererViewport::draw_viewports() { //determine what is visible draw_viewports_pass++; - for (int i = active_viewports.size() - 1; i >= 0; i--) { //to compute parent dependency, must go in reverse draw order + for (int i = sorted_active_viewports.size() - 1; i >= 0; i--) { //to compute parent dependency, must go in reverse draw order - Viewport *vp = active_viewports[i]; + Viewport *vp = sorted_active_viewports[i]; if (vp->update_mode == RS::VIEWPORT_UPDATE_DISABLED) { continue; @@ -621,8 +658,8 @@ void RendererViewport::draw_viewports() { int objects_drawn = 0; int draw_calls_used = 0; - for (int i = 0; i < active_viewports.size(); i++) { - Viewport *vp = active_viewports[i]; + for (int i = 0; i < sorted_active_viewports.size(); i++) { + Viewport *vp = sorted_active_viewports[i]; if (vp->last_pass != draw_viewports_pass) { continue; //should not draw @@ -814,6 +851,8 @@ void RendererViewport::viewport_set_active(RID p_viewport, bool p_active) { } else { active_viewports.erase(viewport); } + + sorted_active_viewports_dirty = true; } void RendererViewport::viewport_set_parent_viewport(RID p_viewport, RID p_parent_viewport) { @@ -1243,6 +1282,7 @@ bool RendererViewport::free(RID p_rid) { viewport_set_scenario(p_rid, RID()); active_viewports.erase(viewport); + sorted_active_viewports_dirty = true; if (viewport->use_occlusion_culling) { RendererSceneOcclusionCull::get_singleton()->remove_buffer(p_rid); diff --git a/servers/rendering/renderer_viewport.h b/servers/rendering/renderer_viewport.h index 5e37c96336..ab4893a908 100644 --- a/servers/rendering/renderer_viewport.h +++ b/servers/rendering/renderer_viewport.h @@ -185,25 +185,16 @@ public: mutable RID_Owner<Viewport, true> viewport_owner; - struct ViewportSort { - _FORCE_INLINE_ bool operator()(const Viewport *p_left, const Viewport *p_right) const { - bool left_to_screen = p_left->viewport_to_screen_rect.size != Size2(); - bool right_to_screen = p_right->viewport_to_screen_rect.size != Size2(); - - if (left_to_screen == right_to_screen) { - return p_right->parent == p_left->self; - } - return (right_to_screen ? 0 : 1) < (left_to_screen ? 0 : 1); - } - }; - Vector<Viewport *> active_viewports; + Vector<Viewport *> sorted_active_viewports; + bool sorted_active_viewports_dirty = false; int total_objects_drawn = 0; int total_vertices_drawn = 0; int total_draw_calls_used = 0; private: + Vector<Viewport *> _sort_active_viewports(); void _configure_3d_render_buffers(Viewport *p_viewport); void _draw_3d(Viewport *p_viewport); void _draw_viewport(Viewport *p_viewport); diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp index c07a783302..2fefdbff52 100644 --- a/servers/rendering/rendering_device.cpp +++ b/servers/rendering/rendering_device.cpp @@ -429,6 +429,7 @@ void RenderingDevice::_bind_methods() { ClassDB::bind_method(D_METHOD("draw_list_begin", "framebuffer", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region", "storage_textures"), &RenderingDevice::draw_list_begin, DEFVAL(Vector<Color>()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2()), DEFVAL(TypedArray<RID>())); ClassDB::bind_method(D_METHOD("draw_list_begin_split", "framebuffer", "splits", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region", "storage_textures"), &RenderingDevice::_draw_list_begin_split, DEFVAL(Vector<Color>()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2()), DEFVAL(TypedArray<RID>())); + ClassDB::bind_method(D_METHOD("draw_list_set_blend_constants", "draw_list", "color"), &RenderingDevice::draw_list_set_blend_constants); ClassDB::bind_method(D_METHOD("draw_list_bind_render_pipeline", "draw_list", "render_pipeline"), &RenderingDevice::draw_list_bind_render_pipeline); ClassDB::bind_method(D_METHOD("draw_list_bind_uniform_set", "draw_list", "uniform_set", "set_index"), &RenderingDevice::draw_list_bind_uniform_set); ClassDB::bind_method(D_METHOD("draw_list_bind_vertex_array", "draw_list", "vertex_array"), &RenderingDevice::draw_list_bind_vertex_array); diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h index a864cfa74c..6dadcab383 100644 --- a/servers/rendering/rendering_device.h +++ b/servers/rendering/rendering_device.h @@ -1129,6 +1129,7 @@ public: virtual DrawListID draw_list_begin(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const Vector<RID> &p_storage_textures = Vector<RID>()) = 0; virtual Error draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, DrawListID *r_split_ids, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const Vector<RID> &p_storage_textures = Vector<RID>()) = 0; + virtual void draw_list_set_blend_constants(DrawListID p_list, const Color &p_color) = 0; virtual void draw_list_bind_render_pipeline(DrawListID p_list, RID p_render_pipeline) = 0; virtual void draw_list_bind_uniform_set(DrawListID p_list, RID p_uniform_set, uint32_t p_index) = 0; virtual void draw_list_bind_vertex_array(DrawListID p_list, RID p_vertex_array) = 0; diff --git a/servers/rendering/rendering_device_binds.h b/servers/rendering/rendering_device_binds.h index 8bdd3deea1..a56b7eb241 100644 --- a/servers/rendering/rendering_device_binds.h +++ b/servers/rendering/rendering_device_binds.h @@ -443,8 +443,8 @@ public: void add_id(const RID &p_id) { base.append_id(p_id); } void clear_ids() { base.clear_ids(); } - Array get_ids() const { - Array ids; + TypedArray<RID> get_ids() const { + TypedArray<RID> ids; for (uint32_t i = 0; i < base.get_id_count(); i++) { ids.push_back(base.get_id(i)); } @@ -452,7 +452,7 @@ public: } protected: - void _set_ids(const Array &p_ids) { + void _set_ids(const TypedArray<RID> &p_ids) { base.clear_ids(); for (int i = 0; i < p_ids.size(); i++) { RID id = p_ids[i]; diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index cc79d09503..9b174d5879 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -831,6 +831,7 @@ public: FUNC6(canvas_item_add_texture_rect, RID, const Rect2 &, RID, bool, const Color &, bool) FUNC7(canvas_item_add_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, bool, bool) FUNC7(canvas_item_add_msdf_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, int, float) + FUNC5(canvas_item_add_lcd_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &) FUNC10(canvas_item_add_nine_patch, RID, const Rect2 &, const Rect2 &, RID, const Vector2 &, const Vector2 &, NinePatchAxisMode, NinePatchAxisMode, bool, const Color &) FUNC6(canvas_item_add_primitive, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, float) FUNC5(canvas_item_add_polygon, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID) diff --git a/servers/rendering/shader_compiler.cpp b/servers/rendering/shader_compiler.cpp index c2cf08812c..f14350305a 100644 --- a/servers/rendering/shader_compiler.cpp +++ b/servers/rendering/shader_compiler.cpp @@ -498,6 +498,11 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene for (const KeyValue<StringName, SL::ShaderNode::Uniform> &E : pnode->uniforms) { if (SL::is_sampler_type(E.value.type)) { + if (E.value.hint == SL::ShaderNode::Uniform::HINT_SCREEN_TEXTURE || + E.value.hint == SL::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE || + E.value.hint == SL::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) { + continue; // Don't create uniforms in the generated code for these. + } max_texture_uniforms++; } else { if (E.value.scope == SL::ShaderNode::Uniform::SCOPE_INSTANCE) { @@ -537,6 +542,13 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene p_actions.uniforms->insert(uniform_name, uniform); continue; // Instances are indexed directly, don't need index uniforms. } + + if (uniform.hint == SL::ShaderNode::Uniform::HINT_SCREEN_TEXTURE || + uniform.hint == SL::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE || + uniform.hint == SL::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) { + continue; // Don't create uniforms in the generated code for these. + } + if (SL::is_sampler_type(uniform.type)) { // Texture layouts are different for OpenGL GLSL and Vulkan GLSL if (!RS::get_singleton()->is_low_end()) { @@ -892,12 +904,39 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene if (p_default_actions.renames.has(vnode->name)) { code = p_default_actions.renames[vnode->name]; + if (vnode->name == "SCREEN_TEXTURE") { + r_gen_code.uses_screen_texture_mipmaps = true; + } } else { if (shader->uniforms.has(vnode->name)) { //its a uniform! const ShaderLanguage::ShaderNode::Uniform &u = shader->uniforms[vnode->name]; if (u.texture_order >= 0) { - code = _mkid(vnode->name); //texture, use as is + StringName name = vnode->name; + if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE) { + name = "SCREEN_TEXTURE"; + if (u.filter >= ShaderLanguage::FILTER_NEAREST_MIPMAP) { + r_gen_code.uses_screen_texture_mipmaps = true; + } + } else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE) { + name = "NORMAL_ROUGHNESS_TEXTURE"; + } else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) { + name = "DEPTH_TEXTURE"; + } else { + name = _mkid(vnode->name); //texture, use as is + } + + if (p_default_actions.renames.has(name)) { + code = p_default_actions.renames[name]; + } else { + code = name; + } + + if (p_actions.usage_flag_pointers.has(name) && !used_flag_pointers.has(name)) { + *p_actions.usage_flag_pointers[name] = true; + used_flag_pointers.insert(name); + } + } else { //a scalar or vector if (u.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) { @@ -1155,6 +1194,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene } if (correct_texture_uniform) { + //TODO Needs to detect screen_texture hint as well is_screen_texture = (texture_uniform == "SCREEN_TEXTURE"); String sampler_name; @@ -1404,6 +1444,7 @@ Error ShaderCompiler::compile(RS::ShaderMode p_mode, const String &p_code, Ident r_gen_code.uses_fragment_time = false; r_gen_code.uses_vertex_time = false; r_gen_code.uses_global_textures = false; + r_gen_code.uses_screen_texture_mipmaps = false; used_name_defines.clear(); used_rmode_defines.clear(); diff --git a/servers/rendering/shader_compiler.h b/servers/rendering/shader_compiler.h index 06f42e9f0f..1ad43daf5f 100644 --- a/servers/rendering/shader_compiler.h +++ b/servers/rendering/shader_compiler.h @@ -80,6 +80,7 @@ public: bool uses_global_textures; bool uses_fragment_time; bool uses_vertex_time; + bool uses_screen_texture_mipmaps; }; struct DefaultIdentifierActions { diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index 81e4d5e217..2bbc5e4dfb 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -200,6 +200,9 @@ const char *ShaderLanguage::token_names[TK_MAX] = { "HINT_ANISOTROPY_TEXTURE", "HINT_RANGE", "HINT_INSTANCE_INDEX", + "HINT_SCREEN_TEXTURE", + "HINT_NORMAL_ROUGHNESS_TEXTURE", + "HINT_DEPTH_TEXTURE", "FILTER_NEAREST", "FILTER_LINEAR", "FILTER_NEAREST_MIPMAP", @@ -363,6 +366,10 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = { { TK_HINT_ROUGHNESS_A, "hint_roughness_a", CF_UNSPECIFIED, {}, {} }, { TK_HINT_ROUGHNESS_NORMAL_TEXTURE, "hint_roughness_normal", CF_UNSPECIFIED, {}, {} }, { TK_HINT_ROUGHNESS_GRAY, "hint_roughness_gray", CF_UNSPECIFIED, {}, {} }, + { TK_HINT_SCREEN_TEXTURE, "hint_screen_texture", CF_UNSPECIFIED, {}, {} }, + { TK_HINT_NORMAL_ROUGHNESS_TEXTURE, "hint_normal_roughness_texture", CF_UNSPECIFIED, {}, {} }, + { TK_HINT_DEPTH_TEXTURE, "hint_depth_texture", CF_UNSPECIFIED, {}, {} }, + { TK_FILTER_NEAREST, "filter_nearest", CF_UNSPECIFIED, {}, {} }, { TK_FILTER_LINEAR, "filter_linear", CF_UNSPECIFIED, {}, {} }, { TK_FILTER_NEAREST_MIPMAP, "filter_nearest_mipmap", CF_UNSPECIFIED, {}, {} }, @@ -1096,6 +1103,15 @@ String ShaderLanguage::get_uniform_hint_name(ShaderNode::Uniform::Hint p_hint) { case ShaderNode::Uniform::HINT_ANISOTROPY: { result = "hint_anisotropy"; } break; + case ShaderNode::Uniform::HINT_SCREEN_TEXTURE: { + result = "hint_screen_texture"; + } break; + case ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE: { + result = "hint_normal_roughness_texture"; + } break; + case ShaderNode::Uniform::HINT_DEPTH_TEXTURE: { + result = "hint_depth_texture"; + } break; default: break; } @@ -5361,6 +5377,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } _set_tkpos(prev_pos); + ShaderNode::Varying &var = shader->varyings[identifier]; String error; if (is_token_operator_assign(next_token.type)) { if (!_validate_varying_assign(shader->varyings[identifier], &error)) { @@ -5368,8 +5385,6 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons return nullptr; } } else { - ShaderNode::Varying &var = shader->varyings[identifier]; - switch (var.stage) { case ShaderNode::Varying::STAGE_VERTEX: if (current_function == varying_function_names.fragment || current_function == varying_function_names.light) { @@ -5385,6 +5400,12 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons break; } } + + if ((var.stage != ShaderNode::Varying::STAGE_FRAGMENT && var.stage != ShaderNode::Varying::STAGE_FRAGMENT_TO_LIGHT) && var.type < TYPE_FLOAT && var.interpolation != INTERPOLATION_FLAT) { + _set_tkpos(var.tkpos); + _set_error(RTR("Varying with integer data type must be declared with `flat` interpolation qualifier.")); + return nullptr; + } } if (ident_type == IDENTIFIER_FUNCTION) { @@ -8283,8 +8304,8 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f return ERR_PARSE_ERROR; } - if (!is_uniform && (type < TYPE_FLOAT || type > TYPE_MAT4)) { - _set_error(RTR("Invalid type for varying, only 'float', 'vec2', 'vec3', 'vec4', 'mat2', 'mat3', 'mat4', or arrays of these types are allowed.")); + if (!is_uniform && type > TYPE_MAT4) { + _set_error(RTR("Invalid data type for varying.")); return ERR_PARSE_ERROR; } @@ -8605,6 +8626,15 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f return ERR_PARSE_ERROR; } } break; + case TK_HINT_SCREEN_TEXTURE: { + new_hint = ShaderNode::Uniform::HINT_SCREEN_TEXTURE; + } break; + case TK_HINT_NORMAL_ROUGHNESS_TEXTURE: { + new_hint = ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE; + } break; + case TK_HINT_DEPTH_TEXTURE: { + new_hint = ShaderNode::Uniform::HINT_DEPTH_TEXTURE; + } break; case TK_FILTER_NEAREST: { new_filter = FILTER_NEAREST; } break; @@ -8629,6 +8659,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f case TK_REPEAT_ENABLE: { new_repeat = REPEAT_ENABLE; } break; + default: break; } @@ -8653,9 +8684,9 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f if (new_filter != FILTER_DEFAULT) { if (uniform.filter != FILTER_DEFAULT) { if (uniform.filter == new_filter) { - _set_error(vformat(RTR("Duplicated hint: '%s'."), get_texture_filter_name(new_filter))); + _set_error(vformat(RTR("Duplicated filter mode: '%s'."), get_texture_filter_name(new_filter))); } else { - _set_error(vformat(RTR("Redefinition of hint: '%s'. The filter mode has already been set to '%s'."), get_texture_filter_name(new_filter), get_texture_filter_name(uniform.filter))); + _set_error(vformat(RTR("Redefinition of filter mode: '%s'. The filter mode has already been set to '%s'."), get_texture_filter_name(new_filter), get_texture_filter_name(uniform.filter))); } return ERR_PARSE_ERROR; } else { @@ -8666,9 +8697,9 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f if (new_repeat != REPEAT_DEFAULT) { if (uniform.repeat != REPEAT_DEFAULT) { if (uniform.repeat == new_repeat) { - _set_error(vformat(RTR("Duplicated hint: '%s'."), get_texture_repeat_name(new_repeat))); + _set_error(vformat(RTR("Duplicated repeat mode: '%s'."), get_texture_repeat_name(new_repeat))); } else { - _set_error(vformat(RTR("Redefinition of hint: '%s'. The repeat mode has already been set to '%s'."), get_texture_repeat_name(new_repeat), get_texture_repeat_name(uniform.repeat))); + _set_error(vformat(RTR("Redefinition of repeat mode: '%s'. The repeat mode has already been set to '%s'."), get_texture_repeat_name(new_repeat), get_texture_repeat_name(uniform.repeat))); } return ERR_PARSE_ERROR; } else { @@ -10309,6 +10340,9 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ options.push_back("hint_roughness_gray"); options.push_back("hint_roughness_normal"); options.push_back("hint_roughness_r"); + options.push_back("hint_screen_texture"); + options.push_back("hint_normal_roughness_texture"); + options.push_back("hint_depth_texture"); options.push_back("source_color"); options.push_back("repeat_enable"); options.push_back("repeat_disable"); diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h index bfec6e1df6..75b713d167 100644 --- a/servers/rendering/shader_language.h +++ b/servers/rendering/shader_language.h @@ -176,6 +176,9 @@ public: TK_HINT_SOURCE_COLOR, TK_HINT_RANGE, TK_HINT_INSTANCE_INDEX, + TK_HINT_SCREEN_TEXTURE, + TK_HINT_NORMAL_ROUGHNESS_TEXTURE, + TK_HINT_DEPTH_TEXTURE, TK_FILTER_NEAREST, TK_FILTER_LINEAR, TK_FILTER_NEAREST_MIPMAP, @@ -667,6 +670,9 @@ public: HINT_DEFAULT_WHITE, HINT_DEFAULT_TRANSPARENT, HINT_ANISOTROPY, + HINT_SCREEN_TEXTURE, + HINT_NORMAL_ROUGHNESS_TEXTURE, + HINT_DEPTH_TEXTURE, HINT_MAX }; diff --git a/servers/rendering/shader_preprocessor.cpp b/servers/rendering/shader_preprocessor.cpp index d118c73c4a..3766477070 100644 --- a/servers/rendering/shader_preprocessor.cpp +++ b/servers/rendering/shader_preprocessor.cpp @@ -349,6 +349,8 @@ void ShaderPreprocessor::process_directive(Tokenizer *p_tokenizer) { process_ifdef(p_tokenizer); } else if (directive == "ifndef") { process_ifndef(p_tokenizer); + } else if (directive == "elif") { + process_elif(p_tokenizer); } else if (directive == "else") { process_else(p_tokenizer); } else if (directive == "endif") { @@ -415,10 +417,67 @@ void ShaderPreprocessor::process_define(Tokenizer *p_tokenizer) { } } +void ShaderPreprocessor::process_elif(Tokenizer *p_tokenizer) { + const int line = p_tokenizer->get_line(); + + if (state->current_branch == nullptr || state->current_branch->else_defined) { + set_error(RTR("Unmatched elif."), line); + return; + } + if (state->previous_region != nullptr) { + state->previous_region->to_line = line - 1; + } + + String body = tokens_to_string(p_tokenizer->advance('\n')).strip_edges(); + if (body.is_empty()) { + set_error(RTR("Missing condition."), line); + return; + } + + Error error = expand_condition(body, line, body); + if (error != OK) { + return; + } + + error = expand_macros(body, line, body); + if (error != OK) { + return; + } + + Expression expression; + Vector<String> names; + error = expression.parse(body, names); + if (error != OK) { + set_error(expression.get_error_text(), line); + return; + } + + Variant v = expression.execute(Array(), nullptr, false); + if (v.get_type() == Variant::NIL) { + set_error(RTR("Condition evaluation error."), line); + return; + } + + bool skip = false; + for (int i = 0; i < state->current_branch->conditions.size(); i++) { + if (state->current_branch->conditions[i]) { + skip = true; + break; + } + } + + bool success = !skip && v.booleanize(); + start_branch_condition(p_tokenizer, success, true); + + if (state->save_regions) { + add_region(line + 1, success, state->previous_region->parent); + } +} + void ShaderPreprocessor::process_else(Tokenizer *p_tokenizer) { const int line = p_tokenizer->get_line(); - if (state->skip_stack_else.is_empty()) { + if (state->current_branch == nullptr || state->current_branch->else_defined) { set_error(RTR("Unmatched else."), line); return; } @@ -428,17 +487,14 @@ void ShaderPreprocessor::process_else(Tokenizer *p_tokenizer) { p_tokenizer->advance('\n'); - bool skip = state->skip_stack_else[state->skip_stack_else.size() - 1]; - state->skip_stack_else.remove_at(state->skip_stack_else.size() - 1); - - Vector<SkippedCondition *> vec = state->skipped_conditions[state->current_filename]; - int index = vec.size() - 1; - if (index >= 0) { - SkippedCondition *cond = vec[index]; - if (cond->end_line == -1) { - cond->end_line = p_tokenizer->get_line(); + bool skip = false; + for (int i = 0; i < state->current_branch->conditions.size(); i++) { + if (state->current_branch->conditions[i]) { + skip = true; + break; } } + state->current_branch->else_defined = true; if (state->save_regions) { add_region(line + 1, !skip, state->previous_region->parent); @@ -462,16 +518,10 @@ void ShaderPreprocessor::process_endif(Tokenizer *p_tokenizer) { state->previous_region = state->previous_region->parent; } - Vector<SkippedCondition *> vec = state->skipped_conditions[state->current_filename]; - int index = vec.size() - 1; - if (index >= 0) { - SkippedCondition *cond = vec[index]; - if (cond->end_line == -1) { - cond->end_line = p_tokenizer->get_line(); - } - } - p_tokenizer->advance('\n'); + + state->current_branch = state->current_branch->parent; + state->branches.pop_back(); } void ShaderPreprocessor::process_if(Tokenizer *p_tokenizer) { @@ -483,7 +533,12 @@ void ShaderPreprocessor::process_if(Tokenizer *p_tokenizer) { return; } - Error error = expand_macros(body, line, body); + Error error = expand_condition(body, line, body); + if (error != OK) { + return; + } + + error = expand_macros(body, line, body); if (error != OK) { return; } @@ -703,24 +758,19 @@ void ShaderPreprocessor::add_region(int p_line, bool p_enabled, Region *p_parent state->previous_region = &state->regions[region.file].push_back(region)->get(); } -void ShaderPreprocessor::start_branch_condition(Tokenizer *p_tokenizer, bool p_success) { - state->condition_depth++; - - if (p_success) { - state->skip_stack_else.push_back(true); +void ShaderPreprocessor::start_branch_condition(Tokenizer *p_tokenizer, bool p_success, bool p_continue) { + if (!p_continue) { + state->condition_depth++; + state->current_branch = &state->branches.push_back(Branch(p_success, state->current_branch))->get(); } else { - SkippedCondition *cond = memnew(SkippedCondition()); - cond->start_line = p_tokenizer->get_line(); - state->skipped_conditions[state->current_filename].push_back(cond); - + state->current_branch->conditions.push_back(p_success); + } + if (!p_success) { Vector<String> ends; + ends.push_back("elif"); ends.push_back("else"); ends.push_back("endif"); - if (next_directive(p_tokenizer, ends) == "else") { - state->skip_stack_else.push_back(false); - } else { - state->skip_stack_else.push_back(true); - } + next_directive(p_tokenizer, ends); } } @@ -737,47 +787,173 @@ void ShaderPreprocessor::expand_output_macros(int p_start, int p_line_number) { add_to_output(line); } -Error ShaderPreprocessor::expand_macros(const String &p_string, int p_line, String &r_expanded) { - Vector<Pair<String, Define *>> active_defines; - active_defines.resize(state->defines.size()); - int index = 0; - for (const RBMap<String, Define *>::Element *E = state->defines.front(); E; E = E->next()) { - active_defines.set(index++, Pair<String, Define *>(E->key(), E->get())); +Error ShaderPreprocessor::expand_condition(const String &p_string, int p_line, String &r_expanded) { + // Checks bracket count to be even + check the cursor position. + { + int bracket_start_count = 0; + int bracket_end_count = 0; + + for (int i = 0; i < p_string.size(); i++) { + switch (p_string[i]) { + case CURSOR: + state->completion_type = COMPLETION_TYPE_CONDITION; + break; + case '(': + bracket_start_count++; + break; + case ')': + bracket_end_count++; + break; + } + } + if (bracket_start_count > bracket_end_count) { + _set_expected_error(")", p_line); + return FAILED; + } + if (bracket_end_count > bracket_start_count) { + _set_expected_error("(", p_line); + return FAILED; + } } - return expand_macros(p_string, p_line, active_defines, r_expanded); + String result = p_string; + + int index = 0; + int index_start = 0; + int index_end = 0; + + while (find_match(result, "defined", index, index_start)) { + bool open_bracket = false; + bool found_word = false; + bool word_completed = false; + + LocalVector<char32_t> text; + int post_bracket_index = -1; + int size = result.size(); + + for (int i = (index_start - 1); i < size; i++) { + char32_t c = result[i]; + if (c == 0) { + if (found_word) { + word_completed = true; + } + break; + } + char32_t cs[] = { c, '\0' }; + String s = String(cs); + bool is_space = is_char_space(c); + + if (word_completed) { + if (c == ')') { + continue; + } + if (c == '|' || c == '&') { + if (open_bracket) { + _set_unexpected_token_error(s, p_line); + return FAILED; + } + break; + } else if (!is_space) { + _set_unexpected_token_error(s, p_line); + return FAILED; + } + } else if (is_space) { + if (found_word && !open_bracket) { + index_end = i; + word_completed = true; + } + } else if (c == '(') { + if (open_bracket) { + _set_unexpected_token_error(s, p_line); + return FAILED; + } + open_bracket = true; + } else if (c == ')') { + if (open_bracket) { + if (!found_word) { + _set_unexpected_token_error(s, p_line); + return FAILED; + } + open_bracket = false; + post_bracket_index = i + 1; + } else { + index_end = i; + } + word_completed = true; + } else if (is_char_word(c)) { + text.push_back(c); + found_word = true; + } else { + _set_unexpected_token_error(s, p_line); + return FAILED; + } + } + + if (word_completed) { + if (open_bracket) { + _set_expected_error(")", p_line); + return FAILED; + } + if (post_bracket_index != -1) { + index_end = post_bracket_index; + } + + String body = state->defines.has(vector_to_string(text)) ? "true" : "false"; + String temp = result; + + result = result.substr(0, index) + body; + index_start = result.length(); + if (index_end > 0) { + result += temp.substr(index_end); + } + } else { + set_error(RTR("Invalid macro name."), p_line); + return FAILED; + } + } + r_expanded = result; + return OK; } -Error ShaderPreprocessor::expand_macros(const String &p_string, int p_line, Vector<Pair<String, Define *>> p_defines, String &r_expanded) { - r_expanded = p_string; - // When expanding macros we must only evaluate them once. - // Later we continue expanding but with the already - // evaluated macros removed. - for (int i = 0; i < p_defines.size(); i++) { - Pair<String, Define *> define_pair = p_defines[i]; - - Error error = expand_macros_once(r_expanded, p_line, define_pair, r_expanded); - if (error != OK) { - return error; +Error ShaderPreprocessor::expand_macros(const String &p_string, int p_line, String &r_expanded) { + String iterative = p_string; + int pass_count = 0; + bool expanded = true; + + while (expanded) { + expanded = false; + + // As long as we find something to expand, keep going. + for (const RBMap<String, Define *>::Element *E = state->defines.front(); E; E = E->next()) { + if (expand_macros_once(iterative, p_line, E, iterative)) { + expanded = true; + } } - // Remove expanded macro and recursively replace remaining. - p_defines.remove_at(i); - return expand_macros(r_expanded, p_line, p_defines, r_expanded); + pass_count++; + if (pass_count > 50) { + set_error(RTR("Macro expansion limit exceeded."), p_line); + break; + } } + r_expanded = iterative; + + if (!state->error.is_empty()) { + return FAILED; + } return OK; } -Error ShaderPreprocessor::expand_macros_once(const String &p_line, int p_line_number, Pair<String, Define *> p_define_pair, String &r_expanded) { +bool ShaderPreprocessor::expand_macros_once(const String &p_line, int p_line_number, const RBMap<String, Define *>::Element *p_define_pair, String &r_expanded) { String result = p_line; - const String &key = p_define_pair.first; - const Define *define = p_define_pair.second; + const String &key = p_define_pair->key(); + const Define *define = p_define_pair->value(); int index_start = 0; int index = 0; - while (find_match(result, key, index, index_start)) { + if (find_match(result, key, index, index_start)) { String body = define->body; if (define->arguments.size() > 0) { // Complex macro with arguments. @@ -785,14 +961,14 @@ Error ShaderPreprocessor::expand_macros_once(const String &p_line, int p_line_nu int args_end = p_line.find(")", args_start); if (args_start == -1 || args_end == -1) { set_error(RTR("Missing macro argument parenthesis."), p_line_number); - return FAILED; + return false; } String values = result.substr(args_start + 1, args_end - (args_start + 1)); Vector<String> args = values.split(","); if (args.size() != define->arguments.size()) { set_error(RTR("Invalid macro argument count."), p_line_number); - return FAILED; + return false; } // Insert macro arguments into the body. @@ -814,11 +990,13 @@ Error ShaderPreprocessor::expand_macros_once(const String &p_line, int p_line_nu // Manually reset index_start to where the body value of the define finishes. // This ensures we don't skip another instance of this macro in the string. index_start = index + body.length() + 1; - break; } + + r_expanded = result; + return true; } - r_expanded = result; - return OK; + + return false; } bool ShaderPreprocessor::find_match(const String &p_string, const String &p_value, int &r_index, int &r_index_start) { @@ -909,12 +1087,6 @@ void ShaderPreprocessor::clear() { memdelete(E->get()); } - for (const RBMap<String, Vector<SkippedCondition *>>::Element *E = state->skipped_conditions.front(); E; E = E->next()) { - for (SkippedCondition *condition : E->get()) { - memdelete(condition); - } - } - memdelete(state); } state_owner = false; @@ -1030,7 +1202,7 @@ Error ShaderPreprocessor::preprocess(const String &p_code, const String &p_filen switch (pp_state.completion_type) { case COMPLETION_TYPE_DIRECTIVE: { List<String> options; - get_keyword_list(&options, true); + get_keyword_list(&options, true, true); for (const String &E : options) { ScriptLanguage::CodeCompletionOption option(E, ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT); @@ -1049,6 +1221,11 @@ Error ShaderPreprocessor::preprocess(const String &p_code, const String &p_filen } } break; + case COMPLETION_TYPE_CONDITION: { + ScriptLanguage::CodeCompletionOption option("defined", ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT); + r_completion_options->push_back(option); + + } break; case COMPLETION_TYPE_INCLUDE_PATH: { if (p_include_completion_func && r_completion_options) { p_include_completion_func(r_completion_options); @@ -1062,8 +1239,12 @@ Error ShaderPreprocessor::preprocess(const String &p_code, const String &p_filen return err; } -void ShaderPreprocessor::get_keyword_list(List<String> *r_keywords, bool p_include_shader_keywords) { +void ShaderPreprocessor::get_keyword_list(List<String> *r_keywords, bool p_include_shader_keywords, bool p_ignore_context_keywords) { r_keywords->push_back("define"); + if (!p_ignore_context_keywords) { + r_keywords->push_back("defined"); + } + r_keywords->push_back("elif"); if (p_include_shader_keywords) { r_keywords->push_back("else"); } diff --git a/servers/rendering/shader_preprocessor.h b/servers/rendering/shader_preprocessor.h index 41b574298d..b4e7c7199f 100644 --- a/servers/rendering/shader_preprocessor.h +++ b/servers/rendering/shader_preprocessor.h @@ -50,6 +50,7 @@ public: COMPLETION_TYPE_DIRECTIVE, COMPLETION_TYPE_PRAGMA_DIRECTIVE, COMPLETION_TYPE_PRAGMA, + COMPLETION_TYPE_CONDITION, COMPLETION_TYPE_INCLUDE_PATH, }; @@ -130,14 +131,23 @@ private: String body; }; - struct SkippedCondition { - int start_line = -1; - int end_line = -1; + struct Branch { + Vector<bool> conditions; + Branch *parent = nullptr; + bool else_defined = false; + + Branch() {} + + Branch(bool p_condition, Branch *p_parent) : + parent(p_parent) { + conditions.push_back(p_condition); + } }; struct State { RBMap<String, Define *> defines; - Vector<bool> skip_stack_else; + List<Branch> branches; + Branch *current_branch = nullptr; int condition_depth = 0; RBSet<String> includes; List<uint64_t> cyclic_include_hashes; // Holds code hash of includes. @@ -149,7 +159,6 @@ private: bool save_regions = false; RBMap<String, List<Region>> regions; Region *previous_region = nullptr; - RBMap<String, Vector<SkippedCondition *>> skipped_conditions; bool disabled = false; CompletionType completion_type = COMPLETION_TYPE_NONE; HashSet<Ref<ShaderInclude>> shader_includes; @@ -167,8 +176,17 @@ private: static String vector_to_string(const LocalVector<char32_t> &p_v, int p_start = 0, int p_end = -1); static String tokens_to_string(const LocalVector<Token> &p_tokens); + void _set_expected_error(const String &p_what, int p_line) { + set_error(vformat(RTR("Expected a '%s'."), p_what), p_line); + } + + void _set_unexpected_token_error(const String &p_what, int p_line) { + set_error(vformat(RTR("Unexpected token '%s'."), p_what), p_line); + } + void process_directive(Tokenizer *p_tokenizer); void process_define(Tokenizer *p_tokenizer); + void process_elif(Tokenizer *p_tokenizer); void process_else(Tokenizer *p_tokenizer); void process_endif(Tokenizer *p_tokenizer); void process_if(Tokenizer *p_tokenizer); @@ -179,12 +197,12 @@ private: void process_undef(Tokenizer *p_tokenizer); void add_region(int p_line, bool p_enabled, Region *p_parent_region); - void start_branch_condition(Tokenizer *p_tokenizer, bool p_success); + void start_branch_condition(Tokenizer *p_tokenizer, bool p_success, bool p_continue = false); + Error expand_condition(const String &p_string, int p_line, String &r_result); void expand_output_macros(int p_start, int p_line); Error expand_macros(const String &p_string, int p_line, String &r_result); - Error expand_macros(const String &p_string, int p_line, Vector<Pair<String, Define *>> p_defines, String &r_result); - Error expand_macros_once(const String &p_line, int p_line_number, Pair<String, Define *> p_define_pair, String &r_expanded); + bool expand_macros_once(const String &p_line, int p_line_number, const RBMap<String, Define *>::Element *p_define_pair, String &r_expanded); bool find_match(const String &p_string, const String &p_value, int &r_index, int &r_index_start); String next_directive(Tokenizer *p_tokenizer, const Vector<String> &p_directives); @@ -202,7 +220,7 @@ public: Error preprocess(const String &p_code, const String &p_filename, String &r_result, String *r_error_text = nullptr, List<FilePosition> *r_error_position = nullptr, List<Region> *r_regions = nullptr, HashSet<Ref<ShaderInclude>> *r_includes = nullptr, List<ScriptLanguage::CodeCompletionOption> *r_completion_options = nullptr, IncludeCompletionFunction p_include_completion_func = nullptr); - static void get_keyword_list(List<String> *r_keywords, bool p_include_shader_keywords); + static void get_keyword_list(List<String> *r_keywords, bool p_include_shader_keywords, bool p_ignore_context_keywords = false); static void get_pragma_list(List<String> *r_pragmas); ShaderPreprocessor(); diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index a54d4f0384..30b6faa360 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -31,6 +31,7 @@ #include "rendering_server.h" #include "core/config/project_settings.h" +#include "core/variant/typed_array.h" #include "servers/rendering/rendering_server_globals.h" #include "servers/rendering/shader_language.h" @@ -69,44 +70,44 @@ Array RenderingServer::_texture_debug_usage_bind() { return arr; } -static Array to_array(const Vector<ObjectID> &ids) { - Array a; +static PackedInt64Array to_int_array(const Vector<ObjectID> &ids) { + PackedInt64Array a; a.resize(ids.size()); for (int i = 0; i < ids.size(); ++i) { - a[i] = ids[i]; + a.write[i] = ids[i]; } return a; } -Array RenderingServer::_instances_cull_aabb_bind(const AABB &p_aabb, RID p_scenario) const { +PackedInt64Array RenderingServer::_instances_cull_aabb_bind(const AABB &p_aabb, RID p_scenario) const { if (RSG::threaded) { WARN_PRINT_ONCE("Using this function with a threaded renderer hurts performance, as it causes a server stall."); } Vector<ObjectID> ids = instances_cull_aabb(p_aabb, p_scenario); - return to_array(ids); + return to_int_array(ids); } -Array RenderingServer::_instances_cull_ray_bind(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario) const { +PackedInt64Array RenderingServer::_instances_cull_ray_bind(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario) const { if (RSG::threaded) { WARN_PRINT_ONCE("Using this function with a threaded renderer hurts performance, as it causes a server stall."); } Vector<ObjectID> ids = instances_cull_ray(p_from, p_to, p_scenario); - return to_array(ids); + return to_int_array(ids); } -Array RenderingServer::_instances_cull_convex_bind(const Array &p_convex, RID p_scenario) const { +PackedInt64Array RenderingServer::_instances_cull_convex_bind(const Array &p_convex, RID p_scenario) const { if (RSG::threaded) { WARN_PRINT_ONCE("Using this function with a threaded renderer hurts performance, as it causes a server stall."); } Vector<Plane> planes; for (int i = 0; i < p_convex.size(); ++i) { Variant v = p_convex[i]; - ERR_FAIL_COND_V(v.get_type() != Variant::PLANE, Array()); + ERR_FAIL_COND_V(v.get_type() != Variant::PLANE, PackedInt64Array()); planes.push_back(v); } Vector<ObjectID> ids = instances_cull_convex(planes, p_scenario); - return to_array(ids); + return to_int_array(ids); } RID RenderingServer::get_test_texture() { @@ -398,16 +399,14 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint const Vector3 *src = array.ptr(); for (int i = 0; i < p_vertex_array_len; i++) { - Vector3 n = src[i] * Vector3(0.5, 0.5, 0.5) + Vector3(0.5, 0.5, 0.5); - - uint32_t value = 0; - value |= CLAMP(int(n.x * 1023.0), 0, 1023); - value |= CLAMP(int(n.y * 1023.0), 0, 1023) << 10; - value |= CLAMP(int(n.z * 1023.0), 0, 1023) << 20; + Vector2 res = src[i].octahedron_encode(); + int16_t vector[2] = { + (int16_t)CLAMP(res.x * 65535, 0, 65535), + (int16_t)CLAMP(res.y * 65535, 0, 65535), + }; - memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], &value, 4); + memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], vector, 4); } - } break; case RS::ARRAY_TANGENT: { @@ -416,33 +415,32 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint if (type == Variant::PACKED_FLOAT32_ARRAY) { Vector<float> array = p_arrays[ai]; ERR_FAIL_COND_V(array.size() != p_vertex_array_len * 4, ERR_INVALID_PARAMETER); - const float *src = array.ptr(); + const float *src_ptr = array.ptr(); for (int i = 0; i < p_vertex_array_len; i++) { - uint32_t value = 0; - value |= CLAMP(int((src[i * 4 + 0] * 0.5 + 0.5) * 1023.0), 0, 1023); - value |= CLAMP(int((src[i * 4 + 1] * 0.5 + 0.5) * 1023.0), 0, 1023) << 10; - value |= CLAMP(int((src[i * 4 + 2] * 0.5 + 0.5) * 1023.0), 0, 1023) << 20; - if (src[i * 4 + 3] > 0) { - value |= 3UL << 30; - } - - memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], &value, 4); + const Vector3 src(src_ptr[i * 4 + 0], src_ptr[i * 4 + 1], src_ptr[i * 4 + 2]); + Vector2 res = src.octahedron_tangent_encode(src_ptr[i * 4 + 3]); + int16_t vector[2] = { + (int16_t)CLAMP(res.x * 65535, 0, 65535), + (int16_t)CLAMP(res.y * 65535, 0, 65535), + }; + + memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], vector, 4); } } else { // PACKED_FLOAT64_ARRAY Vector<double> array = p_arrays[ai]; ERR_FAIL_COND_V(array.size() != p_vertex_array_len * 4, ERR_INVALID_PARAMETER); - const double *src = array.ptr(); + const double *src_ptr = array.ptr(); for (int i = 0; i < p_vertex_array_len; i++) { - uint32_t value = 0; - value |= CLAMP(int((src[i * 4 + 0] * 0.5 + 0.5) * 1023.0), 0, 1023); - value |= CLAMP(int((src[i * 4 + 1] * 0.5 + 0.5) * 1023.0), 0, 1023) << 10; - value |= CLAMP(int((src[i * 4 + 2] * 0.5 + 0.5) * 1023.0), 0, 1023) << 20; - if (src[i * 4 + 3] > 0) { - value |= 3UL << 30; - } - memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], &value, 4); + const Vector3 src(src_ptr[i * 4 + 0], src_ptr[i * 4 + 1], src_ptr[i * 4 + 2]); + Vector2 res = src.octahedron_tangent_encode(src_ptr[i * 4 + 3]); + int16_t vector[2] = { + (int16_t)CLAMP(res.x * 65535, 0, 65535), + (int16_t)CLAMP(res.y * 65535, 0, 65535), + }; + + memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], vector, 4); } } } break; @@ -627,7 +625,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint const int *src = indices.ptr(); for (int i = 0; i < p_index_array_len; i++) { - if (p_vertex_array_len < (1 << 16)) { + if (p_vertex_array_len < (1 << 16) && p_vertex_array_len > 0) { uint16_t v = src[i]; memcpy(&iw[i * 2], &v, 2); @@ -836,9 +834,8 @@ void RenderingServer::mesh_surface_make_offsets_from_format(uint32_t p_format, i break; } /* determine whether using 16 or 32 bits indices */ - if (p_vertex_len >= (1 << 16)) { + if (p_vertex_len >= (1 << 16) || p_vertex_len == 0) { elem_size = 4; - } else { elem_size = 2; } @@ -909,8 +906,6 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa } } - ERR_FAIL_COND_V((format & RS::ARRAY_FORMAT_VERTEX) == 0, ERR_INVALID_PARAMETER); // Mandatory - if (p_blend_shapes.size()) { // Validate format for morphs. for (int i = 0; i < p_blend_shapes.size(); i++) { @@ -944,6 +939,12 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa uint32_t mask = (1 << ARRAY_MAX) - 1; format |= (~mask) & p_compress_format; // Make the full format. + if ((format & RS::ARRAY_FORMAT_VERTEX) == 0 && !(format & RS::ARRAY_FLAG_USES_EMPTY_VERTEX_ARRAY)) { + ERR_PRINT("Mesh created without vertex array. This mesh will not be visible with the default shader. If using an empty vertex array is intentional, create the mesh with the ARRAY_FLAG_USES_EMPTY_VERTEX_ARRAY flag to silence this error."); + // Set the flag here after warning to suppress errors down the pipeline. + format |= RS::ARRAY_FLAG_USES_EMPTY_VERTEX_ARRAY; + } + int vertex_array_size = vertex_element_size * array_len; int attrib_array_size = attrib_element_size * array_len; int skin_array_size = skin_element_size * array_len; @@ -1337,7 +1338,7 @@ Dictionary RenderingServer::mesh_surface_get_lods(RID p_mesh, int p_surface) con return ret; } -Array RenderingServer::mesh_surface_get_blend_shape_arrays(RID p_mesh, int p_surface) const { +TypedArray<Array> RenderingServer::mesh_surface_get_blend_shape_arrays(RID p_mesh, int p_surface) const { SurfaceData sd = mesh_get_surface(p_mesh, p_surface); ERR_FAIL_COND_V(sd.vertex_count == 0, Array()); @@ -1359,7 +1360,7 @@ Array RenderingServer::mesh_surface_get_blend_shape_arrays(RID p_mesh, int p_sur ERR_FAIL_COND_V(blend_shape_count != (uint32_t)mesh_get_blend_shape_count(p_mesh), Array()); - Array blend_shape_array; + TypedArray<Array> blend_shape_array; blend_shape_array.resize(mesh_get_blend_shape_count(p_mesh)); for (uint32_t i = 0; i < blend_shape_count; i++) { Vector<uint8_t> bs_data = blend_shape_data.slice(i * divisor, (i + 1) * divisor); @@ -1369,7 +1370,7 @@ Array RenderingServer::mesh_surface_get_blend_shape_arrays(RID p_mesh, int p_sur return blend_shape_array; } else { - return Array(); + return TypedArray<Array>(); } } @@ -1378,7 +1379,7 @@ Array RenderingServer::mesh_create_arrays_from_surface_data(const SurfaceData &p Vector<uint8_t> attrib_data = p_data.attribute_data; Vector<uint8_t> skin_data = p_data.skin_data; - ERR_FAIL_COND_V(vertex_data.size() == 0, Array()); + ERR_FAIL_COND_V(vertex_data.size() == 0 && (p_data.format & RS::ARRAY_FORMAT_VERTEX), Array()); int vertex_len = p_data.vertex_count; Vector<uint8_t> index_data = p_data.index_data; @@ -1625,7 +1626,7 @@ Dictionary RenderingServer::_mesh_get_surface(RID p_mesh, int p_idx) { return d; } -Array RenderingServer::_instance_geometry_get_shader_uniform_list(RID p_instance) const { +TypedArray<Dictionary> RenderingServer::_instance_geometry_get_shader_uniform_list(RID p_instance) const { List<PropertyInfo> params; instance_geometry_get_shader_uniform_list(p_instance, ¶ms); return convert_property_list(¶ms); @@ -2579,6 +2580,7 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("canvas_item_add_circle", "item", "pos", "radius", "color"), &RenderingServer::canvas_item_add_circle); ClassDB::bind_method(D_METHOD("canvas_item_add_texture_rect", "item", "rect", "texture", "tile", "modulate", "transpose"), &RenderingServer::canvas_item_add_texture_rect, DEFVAL(false), DEFVAL(Color(1, 1, 1)), DEFVAL(false)); ClassDB::bind_method(D_METHOD("canvas_item_add_msdf_texture_rect_region", "item", "rect", "texture", "src_rect", "modulate", "outline_size", "px_range"), &RenderingServer::canvas_item_add_msdf_texture_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(0), DEFVAL(1.0)); + ClassDB::bind_method(D_METHOD("canvas_item_add_lcd_texture_rect_region", "item", "rect", "texture", "src_rect", "modulate"), &RenderingServer::canvas_item_add_lcd_texture_rect_region); ClassDB::bind_method(D_METHOD("canvas_item_add_texture_rect_region", "item", "rect", "texture", "src_rect", "modulate", "transpose", "clip_uv"), &RenderingServer::canvas_item_add_texture_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(true)); ClassDB::bind_method(D_METHOD("canvas_item_add_nine_patch", "item", "rect", "source", "texture", "topleft", "bottomright", "x_axis_mode", "y_axis_mode", "draw_center", "modulate"), &RenderingServer::canvas_item_add_nine_patch, DEFVAL(NINE_PATCH_STRETCH), DEFVAL(NINE_PATCH_STRETCH), DEFVAL(true), DEFVAL(Color(1, 1, 1))); ClassDB::bind_method(D_METHOD("canvas_item_add_primitive", "item", "points", "colors", "uvs", "texture", "width"), &RenderingServer::canvas_item_add_primitive, DEFVAL(1.0)); diff --git a/servers/rendering_server.h b/servers/rendering_server.h index a2fe9caf19..56295a2c5f 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -42,6 +42,9 @@ #include "servers/display_server.h" #include "servers/rendering/rendering_device.h" +template <typename T> +class TypedArray; + class RenderingServer : public Object { GDCLASS(RenderingServer, Object); @@ -244,7 +247,7 @@ public: enum ArrayFormat { /* ARRAY FORMAT FLAGS */ - ARRAY_FORMAT_VERTEX = 1 << ARRAY_VERTEX, // Mandatory + ARRAY_FORMAT_VERTEX = 1 << ARRAY_VERTEX, ARRAY_FORMAT_NORMAL = 1 << ARRAY_NORMAL, ARRAY_FORMAT_TANGENT = 1 << ARRAY_TANGENT, ARRAY_FORMAT_COLOR = 1 << ARRAY_COLOR, @@ -262,17 +265,19 @@ public: ARRAY_FORMAT_CUSTOM_BASE = (ARRAY_INDEX + 1), ARRAY_FORMAT_CUSTOM_BITS = 3, + ARRAY_FORMAT_CUSTOM_MASK = 0x7, ARRAY_FORMAT_CUSTOM0_SHIFT = (ARRAY_FORMAT_CUSTOM_BASE + 0), ARRAY_FORMAT_CUSTOM1_SHIFT = (ARRAY_FORMAT_CUSTOM_BASE + ARRAY_FORMAT_CUSTOM_BITS), ARRAY_FORMAT_CUSTOM2_SHIFT = (ARRAY_FORMAT_CUSTOM_BASE + ARRAY_FORMAT_CUSTOM_BITS * 2), ARRAY_FORMAT_CUSTOM3_SHIFT = (ARRAY_FORMAT_CUSTOM_BASE + ARRAY_FORMAT_CUSTOM_BITS * 3), - ARRAY_FORMAT_CUSTOM_MASK = 0x7, ARRAY_COMPRESS_FLAGS_BASE = (ARRAY_INDEX + 1 + 12), ARRAY_FLAG_USE_2D_VERTICES = 1 << (ARRAY_COMPRESS_FLAGS_BASE + 0), ARRAY_FLAG_USE_DYNAMIC_UPDATE = 1 << (ARRAY_COMPRESS_FLAGS_BASE + 1), ARRAY_FLAG_USE_8_BONE_WEIGHTS = 1 << (ARRAY_COMPRESS_FLAGS_BASE + 2), + + ARRAY_FLAG_USES_EMPTY_VERTEX_ARRAY = 1 << (ARRAY_INDEX + 1 + 15), }; enum PrimitiveType { @@ -323,7 +328,7 @@ public: virtual Error mesh_create_surface_data_from_arrays(SurfaceData *r_surface_data, PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), const Dictionary &p_lods = Dictionary(), uint32_t p_compress_format = 0); Array mesh_create_arrays_from_surface_data(const SurfaceData &p_data) const; Array mesh_surface_get_arrays(RID p_mesh, int p_surface) const; - Array mesh_surface_get_blend_shape_arrays(RID p_mesh, int p_surface) const; + TypedArray<Array> mesh_surface_get_blend_shape_arrays(RID p_mesh, int p_surface) const; Dictionary mesh_surface_get_lods(RID p_mesh, int p_surface) const; virtual void mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), const Dictionary &p_lods = Dictionary(), uint32_t p_compress_format = 0); @@ -1211,9 +1216,9 @@ public: virtual Vector<ObjectID> instances_cull_ray(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario = RID()) const = 0; virtual Vector<ObjectID> instances_cull_convex(const Vector<Plane> &p_convex, RID p_scenario = RID()) const = 0; - Array _instances_cull_aabb_bind(const AABB &p_aabb, RID p_scenario = RID()) const; - Array _instances_cull_ray_bind(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario = RID()) const; - Array _instances_cull_convex_bind(const Array &p_convex, RID p_scenario = RID()) const; + PackedInt64Array _instances_cull_aabb_bind(const AABB &p_aabb, RID p_scenario = RID()) const; + PackedInt64Array _instances_cull_ray_bind(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario = RID()) const; + PackedInt64Array _instances_cull_convex_bind(const Array &p_convex, RID p_scenario = RID()) const; enum InstanceFlags { INSTANCE_FLAG_USE_BAKED_LIGHT, @@ -1321,6 +1326,7 @@ public: virtual void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false) = 0; virtual void canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, bool p_clip_uv = false) = 0; virtual void canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, float p_px_range = 1.0) = 0; + virtual void canvas_item_add_lcd_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1)) = 0; virtual void canvas_item_add_nine_patch(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector2 &p_topleft, const Vector2 &p_bottomright, NinePatchAxisMode p_x_axis_mode = NINE_PATCH_STRETCH, NinePatchAxisMode p_y_axis_mode = NINE_PATCH_STRETCH, bool p_draw_center = true, const Color &p_modulate = Color(1, 1, 1)) = 0; virtual void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width = 1.0) = 0; virtual void canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), RID p_texture = RID()) = 0; @@ -1576,7 +1582,7 @@ private: RID _mesh_create_from_surfaces(const TypedArray<Dictionary> &p_surfaces, int p_blend_shape_count); void _mesh_add_surface(RID p_mesh, const Dictionary &p_surface); Dictionary _mesh_get_surface(RID p_mesh, int p_idx); - Array _instance_geometry_get_shader_uniform_list(RID p_instance) const; + TypedArray<Dictionary> _instance_geometry_get_shader_uniform_list(RID p_instance) const; TypedArray<Image> _bake_render_uv2(RID p_base, const TypedArray<RID> &p_material_overrides, const Size2i &p_image_size); void _particles_set_trail_bind_poses(RID p_particles, const TypedArray<Transform3D> &p_bind_poses); }; diff --git a/servers/text/text_server_extension.cpp b/servers/text/text_server_extension.cpp index 59310ab69b..74ae2bfff0 100644 --- a/servers/text/text_server_extension.cpp +++ b/servers/text/text_server_extension.cpp @@ -69,8 +69,8 @@ void TextServerExtension::_bind_methods() { GDVIRTUAL_BIND(font_set_style_name, "font_rid", "name_style"); GDVIRTUAL_BIND(font_get_style_name, "font_rid"); - GDVIRTUAL_BIND(font_set_antialiased, "font_rid", "antialiased"); - GDVIRTUAL_BIND(font_is_antialiased, "font_rid"); + GDVIRTUAL_BIND(font_set_antialiasing, "font_rid", "antialiasing"); + GDVIRTUAL_BIND(font_get_antialiasing, "font_rid"); GDVIRTUAL_BIND(font_set_generate_mipmaps, "font_rid", "generate_mipmaps"); GDVIRTUAL_BIND(font_get_generate_mipmaps, "font_rid"); @@ -478,16 +478,16 @@ String TextServerExtension::font_get_name(const RID &p_font_rid) const { return String(); } -void TextServerExtension::font_set_antialiased(const RID &p_font_rid, bool p_antialiased) { - GDVIRTUAL_CALL(font_set_antialiased, p_font_rid, p_antialiased); +void TextServerExtension::font_set_antialiasing(RID p_font_rid, TextServer::FontAntialiasing p_antialiasing) { + GDVIRTUAL_CALL(font_set_antialiasing, p_font_rid, p_antialiasing); } -bool TextServerExtension::font_is_antialiased(const RID &p_font_rid) const { - bool ret; - if (GDVIRTUAL_CALL(font_is_antialiased, p_font_rid, ret)) { +TextServer::FontAntialiasing TextServerExtension::font_get_antialiasing(RID p_font_rid) const { + TextServer::FontAntialiasing ret; + if (GDVIRTUAL_CALL(font_get_antialiasing, p_font_rid, ret)) { return ret; } - return false; + return TextServer::FONT_ANTIALIASING_NONE; } void TextServerExtension::font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) { @@ -634,12 +634,12 @@ double TextServerExtension::font_get_oversampling(const RID &p_font_rid) const { return 0.0; } -Array TextServerExtension::font_get_size_cache_list(const RID &p_font_rid) const { - Array ret; +TypedArray<Vector2i> TextServerExtension::font_get_size_cache_list(const RID &p_font_rid) const { + TypedArray<Vector2i> ret; if (GDVIRTUAL_CALL(font_get_size_cache_list, p_font_rid, ret)) { return ret; } - return Array(); + return TypedArray<Vector2i>(); } void TextServerExtension::font_clear_size_cache(const RID &p_font_rid) { @@ -750,12 +750,12 @@ PackedInt32Array TextServerExtension::font_get_texture_offsets(const RID &p_font return PackedInt32Array(); } -Array TextServerExtension::font_get_glyph_list(const RID &p_font_rid, const Vector2i &p_size) const { - Array ret; +PackedInt32Array TextServerExtension::font_get_glyph_list(const RID &p_font_rid, const Vector2i &p_size) const { + PackedInt32Array ret; if (GDVIRTUAL_CALL(font_get_glyph_list, p_font_rid, p_size, ret)) { return ret; } - return Array(); + return PackedInt32Array(); } void TextServerExtension::font_clear_glyphs(const RID &p_font_rid, const Vector2i &p_size) { @@ -850,12 +850,12 @@ Dictionary TextServerExtension::font_get_glyph_contours(const RID &p_font_rid, i return Dictionary(); } -Array TextServerExtension::font_get_kerning_list(const RID &p_font_rid, int64_t p_size) const { - Array ret; +TypedArray<Vector2i> TextServerExtension::font_get_kerning_list(const RID &p_font_rid, int64_t p_size) const { + TypedArray<Vector2i> ret; if (GDVIRTUAL_CALL(font_get_kerning_list, p_font_rid, p_size, ret)) { return ret; } - return Array(); + return TypedArray<Vector2i>(); } void TextServerExtension::font_clear_kerning_map(const RID &p_font_rid, int64_t p_size) { @@ -1534,12 +1534,12 @@ String TextServerExtension::string_to_lower(const String &p_string, const String return p_string; } -Array TextServerExtension::parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const { - Array ret; +TypedArray<Vector2i> TextServerExtension::parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const { + TypedArray<Vector2i> ret; if (GDVIRTUAL_CALL(parse_structured_text, p_parser_type, p_args, p_text, ret)) { return ret; } - return Array(); + return TypedArray<Vector2i>(); } PackedInt32Array TextServerExtension::string_get_word_breaks(const String &p_string, const String &p_language) const { diff --git a/servers/text/text_server_extension.h b/servers/text/text_server_extension.h index 81af1b60e5..6a2c199898 100644 --- a/servers/text/text_server_extension.h +++ b/servers/text/text_server_extension.h @@ -35,6 +35,7 @@ #include "core/object/script_language.h" #include "core/os/thread_safe.h" #include "core/variant/native_ptr.h" +#include "core/variant/typed_array.h" #include "servers/text_server.h" class TextServerExtension : public TextServer { @@ -107,10 +108,10 @@ public: GDVIRTUAL2(font_set_style_name, RID, const String &); GDVIRTUAL1RC(String, font_get_style_name, RID); - virtual void font_set_antialiased(const RID &p_font_rid, bool p_antialiased) override; - virtual bool font_is_antialiased(const RID &p_font_rid) const override; - GDVIRTUAL2(font_set_antialiased, RID, bool); - GDVIRTUAL1RC(bool, font_is_antialiased, RID); + virtual void font_set_antialiasing(RID p_font_rid, TextServer::FontAntialiasing p_antialiasing) override; + virtual TextServer::FontAntialiasing font_get_antialiasing(RID p_font_rid) const override; + GDVIRTUAL2(font_set_antialiasing, RID, TextServer::FontAntialiasing); + GDVIRTUAL1RC(TextServer::FontAntialiasing, font_get_antialiasing, RID); virtual void font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) override; virtual bool font_get_generate_mipmaps(const RID &p_font_rid) const override; @@ -172,10 +173,10 @@ public: GDVIRTUAL2(font_set_oversampling, RID, double); GDVIRTUAL1RC(double, font_get_oversampling, RID); - virtual Array font_get_size_cache_list(const RID &p_font_rid) const override; + virtual TypedArray<Vector2i> font_get_size_cache_list(const RID &p_font_rid) const override; virtual void font_clear_size_cache(const RID &p_font_rid) override; virtual void font_remove_size_cache(const RID &p_font_rid, const Vector2i &p_size) override; - GDVIRTUAL1RC(Array, font_get_size_cache_list, RID); + GDVIRTUAL1RC(TypedArray<Vector2i>, font_get_size_cache_list, RID); GDVIRTUAL1(font_clear_size_cache, RID); GDVIRTUAL2(font_remove_size_cache, RID, const Vector2i &); @@ -221,10 +222,10 @@ public: GDVIRTUAL4(font_set_texture_offsets, RID, const Vector2i &, int64_t, const PackedInt32Array &); GDVIRTUAL3RC(PackedInt32Array, font_get_texture_offsets, RID, const Vector2i &, int64_t); - virtual Array font_get_glyph_list(const RID &p_font_rid, const Vector2i &p_size) const override; + virtual PackedInt32Array font_get_glyph_list(const RID &p_font_rid, const Vector2i &p_size) const override; virtual void font_clear_glyphs(const RID &p_font_rid, const Vector2i &p_size) override; virtual void font_remove_glyph(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) override; - GDVIRTUAL2RC(Array, font_get_glyph_list, RID, const Vector2i &); + GDVIRTUAL2RC(PackedInt32Array, font_get_glyph_list, RID, const Vector2i &); GDVIRTUAL2(font_clear_glyphs, RID, const Vector2i &); GDVIRTUAL3(font_remove_glyph, RID, const Vector2i &, int64_t); @@ -262,10 +263,10 @@ public: virtual Dictionary font_get_glyph_contours(const RID &p_font, int64_t p_size, int64_t p_index) const override; GDVIRTUAL3RC(Dictionary, font_get_glyph_contours, RID, int64_t, int64_t); - virtual Array font_get_kerning_list(const RID &p_font_rid, int64_t p_size) const override; + virtual TypedArray<Vector2i> font_get_kerning_list(const RID &p_font_rid, int64_t p_size) const override; virtual void font_clear_kerning_map(const RID &p_font_rid, int64_t p_size) override; virtual void font_remove_kerning(const RID &p_font_rid, int64_t p_size, const Vector2i &p_glyph_pair) override; - GDVIRTUAL2RC(Array, font_get_kerning_list, RID, int64_t); + GDVIRTUAL2RC(TypedArray<Vector2i>, font_get_kerning_list, RID, int64_t); GDVIRTUAL2(font_clear_kerning_map, RID, int64_t); GDVIRTUAL3(font_remove_kerning, RID, int64_t, const Vector2i &); @@ -504,8 +505,8 @@ public: GDVIRTUAL2RC(String, string_to_upper, const String &, const String &); GDVIRTUAL2RC(String, string_to_lower, const String &, const String &); - Array parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const; - GDVIRTUAL3RC(Array, parse_structured_text, StructuredTextParser, const Array &, const String &); + TypedArray<Vector2i> parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const; + GDVIRTUAL3RC(TypedArray<Vector2i>, parse_structured_text, StructuredTextParser, const Array &, const String &); virtual int is_confusable(const String &p_string, const PackedStringArray &p_dict) const override; virtual bool spoof_check(const String &p_string) const override; diff --git a/servers/text_server.cpp b/servers/text_server.cpp index 2bf0837d88..393160fe9e 100644 --- a/servers/text_server.cpp +++ b/servers/text_server.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "servers/text_server.h" +#include "core/variant/typed_array.h" #include "servers/rendering_server.h" TextServerManager *TextServerManager::singleton = nullptr; @@ -103,8 +104,8 @@ Ref<TextServer> TextServerManager::find_interface(const String &p_name) const { return interfaces[idx]; } -Array TextServerManager::get_interfaces() const { - Array ret; +TypedArray<Dictionary> TextServerManager::get_interfaces() const { + TypedArray<Dictionary> ret; for (int i = 0; i < interfaces.size(); i++) { Dictionary iface_info; @@ -222,8 +223,8 @@ void TextServer::_bind_methods() { ClassDB::bind_method(D_METHOD("font_set_style_name", "font_rid", "name"), &TextServer::font_set_style_name); ClassDB::bind_method(D_METHOD("font_get_style_name", "font_rid"), &TextServer::font_get_style_name); - ClassDB::bind_method(D_METHOD("font_set_antialiased", "font_rid", "antialiased"), &TextServer::font_set_antialiased); - ClassDB::bind_method(D_METHOD("font_is_antialiased", "font_rid"), &TextServer::font_is_antialiased); + ClassDB::bind_method(D_METHOD("font_set_antialiasing", "font_rid", "antialiasing"), &TextServer::font_set_antialiasing); + ClassDB::bind_method(D_METHOD("font_get_antialiasing", "font_rid"), &TextServer::font_get_antialiasing); ClassDB::bind_method(D_METHOD("font_set_generate_mipmaps", "font_rid", "generate_mipmaps"), &TextServer::font_set_generate_mipmaps); ClassDB::bind_method(D_METHOD("font_get_generate_mipmaps", "font_rid"), &TextServer::font_get_generate_mipmaps); @@ -457,6 +458,17 @@ void TextServer::_bind_methods() { ClassDB::bind_method(D_METHOD("parse_structured_text", "parser_type", "args", "text"), &TextServer::parse_structured_text); + /* Font AA */ + BIND_ENUM_CONSTANT(FONT_ANTIALIASING_NONE); + BIND_ENUM_CONSTANT(FONT_ANTIALIASING_GRAY); + BIND_ENUM_CONSTANT(FONT_ANTIALIASING_LCD); + + BIND_ENUM_CONSTANT(FONT_LCD_SUBPIXEL_LAYOUT_NONE); + BIND_ENUM_CONSTANT(FONT_LCD_SUBPIXEL_LAYOUT_HRGB); + BIND_ENUM_CONSTANT(FONT_LCD_SUBPIXEL_LAYOUT_HBGR); + BIND_ENUM_CONSTANT(FONT_LCD_SUBPIXEL_LAYOUT_VRGB); + BIND_ENUM_CONSTANT(FONT_LCD_SUBPIXEL_LAYOUT_VBGR); + /* Direction */ BIND_ENUM_CONSTANT(DIRECTION_AUTO); BIND_ENUM_CONSTANT(DIRECTION_LTR); @@ -1585,8 +1597,8 @@ String TextServer::strip_diacritics(const String &p_string) const { return result; } -Array TextServer::parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const { - Array ret; +TypedArray<Vector2i> TextServer::parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const { + TypedArray<Vector2i> ret; switch (p_parser_type) { case STRUCTURED_TEXT_URI: { int prev = 0; @@ -1627,7 +1639,7 @@ Array TextServer::parse_structured_text(StructuredTextParser p_parser_type, cons ret.push_back(Vector2i(prev, i)); ret.push_back(Vector2i(i, i + 1)); prev = i + 1; - } else if (!local & (p_text[i] == '.')) { // Add each dot separated "domain" part as context. + } else if (!local && (p_text[i] == '.')) { // Add each dot separated "domain" part as context. if (prev != i) { ret.push_back(Vector2i(prev, i)); } @@ -1662,8 +1674,8 @@ Array TextServer::parse_structured_text(StructuredTextParser p_parser_type, cons return ret; } -Array TextServer::_shaped_text_get_glyphs_wrapper(const RID &p_shaped) const { - Array ret; +TypedArray<Dictionary> TextServer::_shaped_text_get_glyphs_wrapper(const RID &p_shaped) const { + TypedArray<Dictionary> ret; const Glyph *glyphs = shaped_text_get_glyphs(p_shaped); int gl_size = shaped_text_get_glyph_count(p_shaped); @@ -1687,7 +1699,7 @@ Array TextServer::_shaped_text_get_glyphs_wrapper(const RID &p_shaped) const { return ret; } -Array TextServer::_shaped_text_sort_logical_wrapper(const RID &p_shaped) { +TypedArray<Dictionary> TextServer::_shaped_text_sort_logical_wrapper(const RID &p_shaped) { Array ret; const Glyph *glyphs = shaped_text_sort_logical(p_shaped); @@ -1712,8 +1724,8 @@ Array TextServer::_shaped_text_sort_logical_wrapper(const RID &p_shaped) { return ret; } -Array TextServer::_shaped_text_get_ellipsis_glyphs_wrapper(const RID &p_shaped) const { - Array ret; +TypedArray<Dictionary> TextServer::_shaped_text_get_ellipsis_glyphs_wrapper(const RID &p_shaped) const { + TypedArray<Dictionary> ret; const Glyph *glyphs = shaped_text_get_ellipsis_glyphs(p_shaped); int gl_size = shaped_text_get_ellipsis_glyph_count(p_shaped); diff --git a/servers/text_server.h b/servers/text_server.h index d45bea3271..9304771d1b 100644 --- a/servers/text_server.h +++ b/servers/text_server.h @@ -37,6 +37,9 @@ #include "core/variant/native_ptr.h" #include "core/variant/variant.h" +template <typename T> +class TypedArray; + struct Glyph; struct CaretInfo; @@ -44,6 +47,21 @@ class TextServer : public RefCounted { GDCLASS(TextServer, RefCounted); public: + enum FontAntialiasing { + FONT_ANTIALIASING_NONE, + FONT_ANTIALIASING_GRAY, + FONT_ANTIALIASING_LCD, + }; + + enum FontLCDSubpixelLayout { + FONT_LCD_SUBPIXEL_LAYOUT_NONE, + FONT_LCD_SUBPIXEL_LAYOUT_HRGB, + FONT_LCD_SUBPIXEL_LAYOUT_HBGR, + FONT_LCD_SUBPIXEL_LAYOUT_VRGB, + FONT_LCD_SUBPIXEL_LAYOUT_VBGR, + FONT_LCD_SUBPIXEL_LAYOUT_MAX, + }; + enum Direction { DIRECTION_AUTO, DIRECTION_LTR, @@ -230,8 +248,8 @@ public: virtual void font_set_style_name(const RID &p_font_rid, const String &p_name) = 0; virtual String font_get_style_name(const RID &p_font_rid) const = 0; - virtual void font_set_antialiased(const RID &p_font_rid, bool p_antialiased) = 0; - virtual bool font_is_antialiased(const RID &p_font_rid) const = 0; + virtual void font_set_antialiasing(RID p_font_rid, FontAntialiasing p_antialiasing) = 0; + virtual FontAntialiasing font_get_antialiasing(RID p_font_rid) const = 0; virtual void font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) = 0; virtual bool font_get_generate_mipmaps(const RID &p_font_rid) const = 0; @@ -269,7 +287,7 @@ public: virtual void font_set_oversampling(const RID &p_font_rid, double p_oversampling) = 0; virtual double font_get_oversampling(const RID &p_font_rid) const = 0; - virtual Array font_get_size_cache_list(const RID &p_font_rid) const = 0; + virtual TypedArray<Vector2i> font_get_size_cache_list(const RID &p_font_rid) const = 0; virtual void font_clear_size_cache(const RID &p_font_rid) = 0; virtual void font_remove_size_cache(const RID &p_font_rid, const Vector2i &p_size) = 0; @@ -298,7 +316,7 @@ public: virtual void font_set_texture_offsets(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index, const PackedInt32Array &p_offset) = 0; virtual PackedInt32Array font_get_texture_offsets(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) const = 0; - virtual Array font_get_glyph_list(const RID &p_font_rid, const Vector2i &p_size) const = 0; + virtual PackedInt32Array font_get_glyph_list(const RID &p_font_rid, const Vector2i &p_size) const = 0; virtual void font_clear_glyphs(const RID &p_font_rid, const Vector2i &p_size) = 0; virtual void font_remove_glyph(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) = 0; @@ -321,7 +339,7 @@ public: virtual Dictionary font_get_glyph_contours(const RID &p_font, int64_t p_size, int64_t p_index) const = 0; - virtual Array font_get_kerning_list(const RID &p_font_rid, int64_t p_size) const = 0; + virtual TypedArray<Vector2i> font_get_kerning_list(const RID &p_font_rid, int64_t p_size) const = 0; virtual void font_clear_kerning_map(const RID &p_font_rid, int64_t p_size) = 0; virtual void font_remove_kerning(const RID &p_font_rid, int64_t p_size, const Vector2i &p_glyph_pair) = 0; @@ -411,9 +429,9 @@ public: virtual bool shaped_text_is_ready(const RID &p_shaped) const = 0; virtual const Glyph *shaped_text_get_glyphs(const RID &p_shaped) const = 0; - Array _shaped_text_get_glyphs_wrapper(const RID &p_shaped) const; + TypedArray<Dictionary> _shaped_text_get_glyphs_wrapper(const RID &p_shaped) const; virtual const Glyph *shaped_text_sort_logical(const RID &p_shaped) = 0; - Array _shaped_text_sort_logical_wrapper(const RID &p_shaped); + TypedArray<Dictionary> _shaped_text_sort_logical_wrapper(const RID &p_shaped); virtual int64_t shaped_text_get_glyph_count(const RID &p_shaped) const = 0; virtual Vector2i shaped_text_get_range(const RID &p_shaped) const = 0; @@ -425,7 +443,7 @@ public: virtual int64_t shaped_text_get_trim_pos(const RID &p_shaped) const = 0; virtual int64_t shaped_text_get_ellipsis_pos(const RID &p_shaped) const = 0; virtual const Glyph *shaped_text_get_ellipsis_glyphs(const RID &p_shaped) const = 0; - Array _shaped_text_get_ellipsis_glyphs_wrapper(const RID &p_shaped) const; + TypedArray<Dictionary> _shaped_text_get_ellipsis_glyphs_wrapper(const RID &p_shaped) const; virtual int64_t shaped_text_get_ellipsis_glyph_count(const RID &p_shaped) const = 0; virtual void shaped_text_overrun_trim_to_width(const RID &p_shaped, double p_width, BitField<TextServer::TextOverrunFlag> p_trim_flags) = 0; @@ -476,7 +494,7 @@ public: virtual String string_to_upper(const String &p_string, const String &p_language = "") const = 0; virtual String string_to_lower(const String &p_string, const String &p_language = "") const = 0; - Array parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const; + TypedArray<Vector2i> parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const; TextServer(); ~TextServer(); @@ -538,7 +556,7 @@ public: int get_interface_count() const; Ref<TextServer> get_interface(int p_index) const; Ref<TextServer> find_interface(const String &p_name) const; - Array get_interfaces() const; + TypedArray<Dictionary> get_interfaces() const; _FORCE_INLINE_ Ref<TextServer> get_primary_interface() const { return primary_interface; @@ -569,6 +587,8 @@ VARIANT_ENUM_CAST(TextServer::ContourPointTag); VARIANT_ENUM_CAST(TextServer::SpacingType); VARIANT_BITFIELD_CAST(TextServer::FontStyle); VARIANT_ENUM_CAST(TextServer::StructuredTextParser); +VARIANT_ENUM_CAST(TextServer::FontAntialiasing); +VARIANT_ENUM_CAST(TextServer::FontLCDSubpixelLayout); GDVIRTUAL_NATIVE_PTR(Glyph); GDVIRTUAL_NATIVE_PTR(CaretInfo); diff --git a/servers/xr_server.cpp b/servers/xr_server.cpp index 990281d96d..e26212ada1 100644 --- a/servers/xr_server.cpp +++ b/servers/xr_server.cpp @@ -226,7 +226,7 @@ Ref<XRInterface> XRServer::find_interface(const String &p_name) const { return interfaces[idx]; }; -Array XRServer::get_interfaces() const { +TypedArray<Dictionary> XRServer::get_interfaces() const { Array ret; for (int i = 0; i < interfaces.size(); i++) { diff --git a/servers/xr_server.h b/servers/xr_server.h index 74128bfb54..57e42deccb 100644 --- a/servers/xr_server.h +++ b/servers/xr_server.h @@ -157,7 +157,7 @@ public: int get_interface_count() const; Ref<XRInterface> get_interface(int p_index) const; Ref<XRInterface> find_interface(const String &p_name) const; - Array get_interfaces() const; + TypedArray<Dictionary> get_interfaces() const; /* note, more then one interface can technically be active, especially on mobile, but only one interface is used for |