diff options
22 files changed, 187 insertions, 139 deletions
diff --git a/doc/classes/AnimationNodeTransition.xml b/doc/classes/AnimationNodeTransition.xml index 57e79ac161..a067b0a9ba 100644 --- a/doc/classes/AnimationNodeTransition.xml +++ b/doc/classes/AnimationNodeTransition.xml @@ -12,6 +12,13 @@ <link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link> </tutorials> <methods> + <method name="is_input_reset" qualifiers="const"> + <return type="bool" /> + <param index="0" name="input" type="int" /> + <description> + Returns whether the animation restarts when the animation transitions from the other animation. + </description> + </method> <method name="is_input_set_as_auto_advance" qualifiers="const"> <return type="bool" /> <param index="0" name="input" type="int" /> @@ -27,14 +34,19 @@ Enables or disables auto-advance for the given [param input] index. If enabled, state changes to the next input after playing the animation once. If enabled for the last input state, it loops to the first. </description> </method> + <method name="set_input_reset"> + <return type="void" /> + <param index="0" name="input" type="int" /> + <param index="1" name="enable" type="bool" /> + <description> + If [code]true[/code], the destination animation is restarted when the animation transitions. + </description> + </method> </methods> <members> <member name="input_count" type="int" setter="set_input_count" getter="get_input_count" default="0"> The number of enabled input ports for this node. </member> - <member name="reset" type="bool" setter="set_reset" getter="is_reset" default="true"> - If [code]true[/code], the destination animation is played back from the beginning when switched. - </member> <member name="xfade_curve" type="Curve" setter="set_xfade_curve" getter="get_xfade_curve"> Determines how cross-fading between animations is eased. If empty, the transition will be linear. </member> diff --git a/doc/classes/EditorImportPlugin.xml b/doc/classes/EditorImportPlugin.xml index c395815117..ec9efcc9c4 100644 --- a/doc/classes/EditorImportPlugin.xml +++ b/doc/classes/EditorImportPlugin.xml @@ -37,8 +37,8 @@ return [{"name": "my_option", "default_value": false}] func _import(source_file, save_path, options, platform_variants, gen_files): - var file = File.new() - if file.open(source_file, File.READ) != OK: + var file = FileAccess.open(source_file, FileAccess.READ) + if file == null: return FAILED var mesh = ArrayMesh.new() # Fill the Mesh with data read in "file", left as an exercise to the reader. diff --git a/doc/classes/EditorTranslationParserPlugin.xml b/doc/classes/EditorTranslationParserPlugin.xml index df10c645ef..89746363d8 100644 --- a/doc/classes/EditorTranslationParserPlugin.xml +++ b/doc/classes/EditorTranslationParserPlugin.xml @@ -15,8 +15,7 @@ extends EditorTranslationParserPlugin func _parse_file(path, msgids, msgids_context_plural): - var file = File.new() - file.open(path, File.READ) + var file = FileAccess.open(path, FileAccess.READ) var text = file.get_as_text() var split_strs = text.split(",", false) for s in split_strs: diff --git a/doc/classes/HashingContext.xml b/doc/classes/HashingContext.xml index 6e3092e618..7c2be6f817 100644 --- a/doc/classes/HashingContext.xml +++ b/doc/classes/HashingContext.xml @@ -11,15 +11,14 @@ const CHUNK_SIZE = 102 func hash_file(path): - var ctx = HashingContext.new() - var file = File.new() - # Start a SHA-256 context. - ctx.start(HashingContext.HASH_SHA256) # Check that file exists. - if not file.file_exists(path): + if not FileAccess.file_exists(path): return + # Start a SHA-256 context. + var ctx = HashingContext.new() + ctx.start(HashingContext.HASH_SHA256) # Open the file to hash. - file.open(path, File.READ) + var file = FileAccess.open(path, FileAccess.READ) # Update the context after reading each chunk. while not file.eof_reached(): ctx.update(file.get_buffer(CHUNK_SIZE)) diff --git a/editor/export/editor_export_platform.cpp b/editor/export/editor_export_platform.cpp index b2a3085c36..fe67813d65 100644 --- a/editor/export/editor_export_platform.cpp +++ b/editor/export/editor_export_platform.cpp @@ -785,10 +785,10 @@ String EditorExportPlatform::_export_customize(const String &p_path, LocalVector break; } } - } - if (_export_customize_object(res.ptr(), customize_resources_plugins)) { - modified = true; + if (_export_customize_object(res.ptr(), customize_resources_plugins)) { + modified = true; + } } if (modified || p_force_save) { diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index c78dd1528f..6acdc9f212 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -196,7 +196,11 @@ static bool _is_exact_type(const PropertyInfo &p_par_type, const GDScriptDataTyp } } -static bool _have_exact_arguments(const MethodBind *p_method, const Vector<GDScriptCodeGenerator::Address> &p_arguments) { +static bool _can_use_ptrcall(const MethodBind *p_method, const Vector<GDScriptCodeGenerator::Address> &p_arguments) { + if (p_method->is_vararg()) { + // ptrcall won't work with vararg methods. + return false; + } if (p_method->get_argument_count() != p_arguments.size()) { // ptrcall won't work with default arguments. return false; @@ -563,7 +567,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code self.mode = GDScriptCodeGenerator::Address::SELF; MethodBind *method = ClassDB::get_method(codegen.script->native->get_name(), call->function_name); - if (_have_exact_arguments(method, arguments)) { + if (_can_use_ptrcall(method, arguments)) { // Exact arguments, use ptrcall. gen->write_call_ptrcall(result, self, method, arguments); } else { @@ -613,7 +617,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code } if (ClassDB::class_exists(class_name) && ClassDB::has_method(class_name, call->function_name)) { MethodBind *method = ClassDB::get_method(class_name, call->function_name); - if (_have_exact_arguments(method, arguments)) { + if (_can_use_ptrcall(method, arguments)) { // Exact arguments, use ptrcall. gen->write_call_ptrcall(result, base, method, arguments); } else { diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index 06c66b155f..66374d0a6d 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -1906,10 +1906,8 @@ GDScriptParser::MatchNode *GDScriptParser::parse_match() { return match; } -#ifdef DEBUG_ENABLED bool all_have_return = true; bool have_wildcard = false; -#endif while (!check(GDScriptTokenizer::Token::DEDENT) && !is_at_end()) { MatchBranchNode *branch = parse_match_branch(); @@ -1922,21 +1920,19 @@ GDScriptParser::MatchNode *GDScriptParser::parse_match() { if (have_wildcard && !branch->patterns.is_empty()) { push_warning(branch->patterns[0], GDScriptWarning::UNREACHABLE_PATTERN); } +#endif have_wildcard = have_wildcard || branch->has_wildcard; all_have_return = all_have_return && branch->block->has_return; -#endif match->branches.push_back(branch); } complete_extents(match); consume(GDScriptTokenizer::Token::DEDENT, R"(Expected an indented block after "match" statement.)"); -#ifdef DEBUG_ENABLED if (all_have_return && have_wildcard) { current_suite->has_return = true; } -#endif return match; } diff --git a/modules/gdscript/tests/scripts/analyzer/features/vararg_call.gd b/modules/gdscript/tests/scripts/analyzer/features/vararg_call.gd new file mode 100644 index 0000000000..d444250f1e --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/features/vararg_call.gd @@ -0,0 +1,6 @@ +signal ok() + +@warning_ignore("return_value_discarded") +func test(): + ok.connect(func(): print('ok')) + emit_signal(&'ok') diff --git a/modules/gdscript/tests/scripts/analyzer/features/vararg_call.out b/modules/gdscript/tests/scripts/analyzer/features/vararg_call.out new file mode 100644 index 0000000000..1b47ed10dc --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/features/vararg_call.out @@ -0,0 +1,2 @@ +GDTEST_OK +ok diff --git a/modules/minimp3/doc_classes/AudioStreamMP3.xml b/modules/minimp3/doc_classes/AudioStreamMP3.xml index 8f03681c06..a88ff23b6b 100644 --- a/modules/minimp3/doc_classes/AudioStreamMP3.xml +++ b/modules/minimp3/doc_classes/AudioStreamMP3.xml @@ -21,21 +21,17 @@ [codeblocks] [gdscript] func load_mp3(path): - var file = File.new() - file.open(path, File.READ) + var file = FileAccess.open(path, FileAccess.READ) var sound = AudioStreamMP3.new() sound.data = file.get_buffer(file.get_length()) - file.close() return sound [/gdscript] [csharp] public AudioStreamMP3 LoadMP3(string path) { - var file = new File(); - file.Open(path, File.READ); + using var file = FileAccess.Open(path, FileAccess.ModeFlags.Read); var sound = new AudioStreamMP3(); sound.Data = file.GetBuffer(file.GetLength()); - file.Close(); return sound; } [/csharp] diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp index e53aef965a..9b474bf2ce 100644 --- a/modules/text_server_adv/text_server_adv.cpp +++ b/modules/text_server_adv/text_server_adv.cpp @@ -4068,7 +4068,6 @@ void TextServerAdvanced::_realign(ShapedTextDataAdvanced *p_sd) const { RID TextServerAdvanced::_shaped_text_substr(const RID &p_shaped, int64_t p_start, int64_t p_length) const { _THREAD_SAFE_METHOD_ - const ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); ERR_FAIL_COND_V(!sd, RID()); @@ -5513,6 +5512,7 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int64_t p_star } bool TextServerAdvanced::_shaped_text_shape(const RID &p_shaped) { + _THREAD_SAFE_METHOD_ ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); ERR_FAIL_COND_V(!sd, false); @@ -6569,6 +6569,7 @@ TextServerAdvanced::TextServerAdvanced() { } void TextServerAdvanced::_cleanup() { + _THREAD_SAFE_METHOD_ for (const KeyValue<SystemFontKey, SystemFontCache> &E : system_fonts) { const Vector<SystemFontCacheRec> &sysf_cache = E.value.var; for (const SystemFontCacheRec &F : sysf_cache) { diff --git a/scene/animation/animation_blend_tree.cpp b/scene/animation/animation_blend_tree.cpp index d2073f4f23..45f4f690b9 100644 --- a/scene/animation/animation_blend_tree.cpp +++ b/scene/animation/animation_blend_tree.cpp @@ -667,6 +667,8 @@ bool AnimationNodeTransition::_set(const StringName &p_path, const Variant &p_va set_input_name(which, p_value); } else if (what == "auto_advance") { set_input_as_auto_advance(which, p_value); + } else if (what == "reset") { + set_input_reset(which, p_value); } else { return false; } @@ -690,6 +692,8 @@ bool AnimationNodeTransition::_get(const StringName &p_path, Variant &r_ret) con r_ret = get_input_name(which); } else if (what == "auto_advance") { r_ret = is_input_set_as_auto_advance(which); + } else if (what == "reset") { + r_ret = is_input_reset(which); } else { return false; } @@ -749,25 +753,35 @@ void AnimationNodeTransition::set_input_count(int p_inputs) { bool AnimationNodeTransition::add_input(const String &p_name) { if (AnimationNode::add_input(p_name)) { - input_as_auto_advance.push_back(false); + input_data.push_back(InputData()); return true; } return false; } void AnimationNodeTransition::remove_input(int p_index) { - input_as_auto_advance.remove_at(p_index); + input_data.remove_at(p_index); AnimationNode::remove_input(p_index); } void AnimationNodeTransition::set_input_as_auto_advance(int p_input, bool p_enable) { ERR_FAIL_INDEX(p_input, get_input_count()); - input_as_auto_advance.write[p_input] = p_enable; + input_data.write[p_input].auto_advance = p_enable; } bool AnimationNodeTransition::is_input_set_as_auto_advance(int p_input) const { ERR_FAIL_INDEX_V(p_input, get_input_count(), false); - return input_as_auto_advance[p_input]; + return input_data[p_input].auto_advance; +} + +void AnimationNodeTransition::set_input_reset(int p_input, bool p_enable) { + ERR_FAIL_INDEX(p_input, get_input_count()); + input_data.write[p_input].reset = p_enable; +} + +bool AnimationNodeTransition::is_input_reset(int p_input) const { + ERR_FAIL_INDEX_V(p_input, get_input_count(), true); + return input_data[p_input].reset; } void AnimationNodeTransition::set_xfade_time(double p_fade) { @@ -786,14 +800,6 @@ Ref<Curve> AnimationNodeTransition::get_xfade_curve() const { return xfade_curve; } -void AnimationNodeTransition::set_reset(bool p_reset) { - reset = p_reset; -} - -bool AnimationNodeTransition::is_reset() const { - return reset; -} - double AnimationNodeTransition::process(double p_time, bool p_seek, bool p_is_external_seeking) { String cur_transition_request = get_parameter(transition_request); int cur_current_index = get_parameter(current_index); @@ -810,7 +816,7 @@ double AnimationNodeTransition::process(double p_time, bool p_seek, bool p_is_ex if (new_idx >= 0) { if (cur_current_index == new_idx) { // Transition to same state. - restart = reset; + restart = input_data[cur_current_index].reset; cur_prev_xfading = 0; set_parameter(prev_xfading, 0); cur_prev_index = -1; @@ -865,7 +871,7 @@ double AnimationNodeTransition::process(double p_time, bool p_seek, bool p_is_ex cur_time += p_time; } - if (input_as_auto_advance[cur_current_index] && rem <= xfade_time) { + if (input_data[cur_current_index].auto_advance && rem <= xfade_time) { set_parameter(transition_request, get_input_name((cur_current_index + 1) % get_input_count())); } @@ -878,7 +884,7 @@ double AnimationNodeTransition::process(double p_time, bool p_seek, bool p_is_ex // Blend values must be more than CMP_EPSILON to process discrete keys in edge. real_t blend_inv = 1.0 - blend; - if (reset && !p_seek && switched) { //just switched, seek to start of current + if (input_data[cur_current_index].reset && !p_seek && switched) { //just switched, seek to start of current rem = blend_input(cur_current_index, 0, true, p_is_external_seeking, Math::is_zero_approx(blend_inv) ? CMP_EPSILON : blend_inv, FILTER_IGNORE, true); } else { rem = blend_input(cur_current_index, p_time, p_seek, p_is_external_seeking, Math::is_zero_approx(blend_inv) ? CMP_EPSILON : blend_inv, FILTER_IGNORE, true); @@ -907,6 +913,7 @@ void AnimationNodeTransition::_get_property_list(List<PropertyInfo> *p_list) con for (int i = 0; i < get_input_count(); i++) { p_list->push_back(PropertyInfo(Variant::STRING, "input_" + itos(i) + "/name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_INTERNAL)); p_list->push_back(PropertyInfo(Variant::BOOL, "input_" + itos(i) + "/auto_advance", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_INTERNAL)); + p_list->push_back(PropertyInfo(Variant::BOOL, "input_" + itos(i) + "/reset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_INTERNAL)); } } @@ -916,18 +923,17 @@ void AnimationNodeTransition::_bind_methods() { ClassDB::bind_method(D_METHOD("set_input_as_auto_advance", "input", "enable"), &AnimationNodeTransition::set_input_as_auto_advance); ClassDB::bind_method(D_METHOD("is_input_set_as_auto_advance", "input"), &AnimationNodeTransition::is_input_set_as_auto_advance); + ClassDB::bind_method(D_METHOD("set_input_reset", "input", "enable"), &AnimationNodeTransition::set_input_reset); + ClassDB::bind_method(D_METHOD("is_input_reset", "input"), &AnimationNodeTransition::is_input_reset); + ClassDB::bind_method(D_METHOD("set_xfade_time", "time"), &AnimationNodeTransition::set_xfade_time); ClassDB::bind_method(D_METHOD("get_xfade_time"), &AnimationNodeTransition::get_xfade_time); ClassDB::bind_method(D_METHOD("set_xfade_curve", "curve"), &AnimationNodeTransition::set_xfade_curve); ClassDB::bind_method(D_METHOD("get_xfade_curve"), &AnimationNodeTransition::get_xfade_curve); - ClassDB::bind_method(D_METHOD("set_reset", "reset"), &AnimationNodeTransition::set_reset); - ClassDB::bind_method(D_METHOD("is_reset"), &AnimationNodeTransition::is_reset); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "xfade_time", PROPERTY_HINT_RANGE, "0,120,0.01,suffix:s"), "set_xfade_time", "get_xfade_time"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "xfade_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_xfade_curve", "get_xfade_curve"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "reset"), "set_reset", "is_reset"); ADD_PROPERTY(PropertyInfo(Variant::INT, "input_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_ARRAY | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED, "Inputs,input_"), "set_input_count", "get_input_count"); } diff --git a/scene/animation/animation_blend_tree.h b/scene/animation/animation_blend_tree.h index 09bf567db7..3c27edbf70 100644 --- a/scene/animation/animation_blend_tree.h +++ b/scene/animation/animation_blend_tree.h @@ -276,7 +276,11 @@ public: class AnimationNodeTransition : public AnimationNodeSync { GDCLASS(AnimationNodeTransition, AnimationNodeSync); - Vector<bool> input_as_auto_advance; + struct InputData { + bool auto_advance = false; + bool reset = true; + }; + Vector<InputData> input_data; StringName time = "time"; StringName prev_xfading = "prev_xfading"; @@ -290,7 +294,6 @@ class AnimationNodeTransition : public AnimationNodeSync { double xfade_time = 0.0; Ref<Curve> xfade_curve; - bool reset = true; protected: bool _get(const StringName &p_path, Variant &r_ret) const; @@ -313,15 +316,15 @@ public: void set_input_as_auto_advance(int p_input, bool p_enable); bool is_input_set_as_auto_advance(int p_input) const; + void set_input_reset(int p_input, bool p_enable); + bool is_input_reset(int p_input) const; + void set_xfade_time(double p_fade); double get_xfade_time() const; void set_xfade_curve(const Ref<Curve> &p_curve); Ref<Curve> get_xfade_curve() const; - void set_reset(bool p_reset); - bool is_reset() const; - double process(double p_time, bool p_seek, bool p_is_external_seeking) override; AnimationNodeTransition(); diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index 1b7615befa..2e25d685d6 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -1816,15 +1816,18 @@ float AnimationPlayer::get_playing_speed() const { } void AnimationPlayer::seek(double p_time, bool p_update) { + playback.current.pos = p_time; + if (!playback.current.from) { if (playback.assigned) { ERR_FAIL_COND_MSG(!animation_set.has(playback.assigned), vformat("Animation not found: %s.", playback.assigned)); playback.current.from = &animation_set[playback.assigned]; } - ERR_FAIL_COND(!playback.current.from); + if (!playback.current.from) { + return; // There is no animation. + } } - playback.current.pos = p_time; playback.seeked = true; if (p_update) { _animation_process(0); @@ -1832,20 +1835,22 @@ void AnimationPlayer::seek(double p_time, bool p_update) { } void AnimationPlayer::seek_delta(double p_time, double p_delta) { + playback.current.pos = p_time - p_delta; + if (!playback.current.from) { if (playback.assigned) { ERR_FAIL_COND_MSG(!animation_set.has(playback.assigned), vformat("Animation not found: %s.", playback.assigned)); playback.current.from = &animation_set[playback.assigned]; } - ERR_FAIL_COND(!playback.current.from); + if (!playback.current.from) { + return; // There is no animation. + } } - playback.current.pos = p_time - p_delta; if (speed_scale != 0.0) { p_delta /= speed_scale; } _animation_process(p_delta); - //playback.current.pos=p_time; } bool AnimationPlayer::is_valid() const { diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp index 39d1793368..abc7814877 100644 --- a/scene/animation/tween.cpp +++ b/scene/animation/tween.cpp @@ -594,7 +594,7 @@ PropertyTweener::PropertyTweener(Object *p_target, NodePath p_property, Variant } PropertyTweener::PropertyTweener() { - ERR_FAIL_MSG("Can't create empty PropertyTweener. Use get_tree().tween_property() or tween_property() instead."); + ERR_FAIL_MSG("PropertyTweener can't be created directly. Use the tween_property() method in Tween."); } void IntervalTweener::start() { @@ -625,7 +625,7 @@ IntervalTweener::IntervalTweener(double p_time) { } IntervalTweener::IntervalTweener() { - ERR_FAIL_MSG("Can't create empty IntervalTweener. Use get_tree().tween_interval() instead."); + ERR_FAIL_MSG("IntervalTweener can't be created directly. Use the tween_interval() method in Tween."); } Ref<CallbackTweener> CallbackTweener::set_delay(double p_delay) { @@ -676,7 +676,7 @@ CallbackTweener::CallbackTweener(Callable p_callback) { } CallbackTweener::CallbackTweener() { - ERR_FAIL_MSG("Can't create empty CallbackTweener. Use get_tree().tween_callback() instead."); + ERR_FAIL_MSG("CallbackTweener can't be created directly. Use the tween_callback() method in Tween."); } Ref<MethodTweener> MethodTweener::set_delay(double p_delay) { @@ -769,5 +769,5 @@ MethodTweener::MethodTweener(Callable p_callback, Variant p_from, Variant p_to, } MethodTweener::MethodTweener() { - ERR_FAIL_MSG("Can't create empty MethodTweener. Use get_tree().tween_method() instead."); + ERR_FAIL_MSG("MethodTweener can't be created directly. Use the tween_method() method in Tween."); } diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 71ee3c8d0d..3051502dd0 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -1797,7 +1797,9 @@ void RichTextLabel::_notification(int p_what) { } break; case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { - queue_redraw(); + if (is_visible_in_tree()) { + queue_redraw(); + } } break; case NOTIFICATION_DRAW: { @@ -2665,19 +2667,26 @@ bool RichTextLabel::_find_layout_subitem(Item *from, Item *to) { return false; } -void RichTextLabel::_thread_function(void *self) { - RichTextLabel *rtl = reinterpret_cast<RichTextLabel *>(self); - rtl->set_physics_process_internal(true); - rtl->_process_line_caches(); - rtl->set_physics_process_internal(false); - rtl->updating.store(false); - rtl->call_deferred(SNAME("queue_redraw")); +void RichTextLabel::_thread_function(void *p_userdata) { + _process_line_caches(); + updating.store(false); + call_deferred(SNAME("thread_end")); +} + +void RichTextLabel::_thread_end() { + set_physics_process_internal(false); + if (is_visible_in_tree()) { + queue_redraw(); + } } void RichTextLabel::_stop_thread() { if (threaded) { stop_thread.store(true); - thread.wait_to_finish(); + if (task != WorkerThreadPool::INVALID_TASK_ID) { + WorkerThreadPool::get_singleton()->wait_for_task_completion(task); + task = WorkerThreadPool::INVALID_TASK_ID; + } } } @@ -2787,7 +2796,8 @@ bool RichTextLabel::_validate_line_caches() { if (threaded) { updating.store(true); loaded.store(true); - thread.start(RichTextLabel::_thread_function, reinterpret_cast<void *>(this)); + task = WorkerThreadPool::get_singleton()->add_template_task(this, &RichTextLabel::_thread_function, nullptr, true, vformat("RichTextLabelShape:%x", (int64_t)get_instance_id())); + set_physics_process_internal(true); loading_started = OS::get_singleton()->get_ticks_msec(); return false; } else { @@ -5457,6 +5467,8 @@ void RichTextLabel::_bind_methods() { ClassDB::bind_method(D_METHOD("get_menu"), &RichTextLabel::get_menu); ClassDB::bind_method(D_METHOD("is_menu_visible"), &RichTextLabel::is_menu_visible); + ClassDB::bind_method(D_METHOD("_thread_end"), &RichTextLabel::_thread_end); + // Note: set "bbcode_enabled" first, to avoid unnecessary "text" resets. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bbcode_enabled"), "set_use_bbcode", "is_using_bbcode"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT), "set_text", "get_text"); diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h index 58b82d4672..fcbb91f67e 100644 --- a/scene/gui/rich_text_label.h +++ b/scene/gui/rich_text_label.h @@ -31,6 +31,7 @@ #ifndef RICH_TEXT_LABEL_H #define RICH_TEXT_LABEL_H +#include "core/object/worker_thread_pool.h" #include "rich_text_effect.h" #include "scene/gui/popup_menu.h" #include "scene/gui/scroll_bar.h" @@ -369,7 +370,7 @@ private: Item *current = nullptr; ItemFrame *current_frame = nullptr; - Thread thread; + WorkerThreadPool::TaskID task = WorkerThreadPool::INVALID_TASK_ID; Mutex data_mutex; bool threaded = false; std::atomic<bool> stop_thread; @@ -409,7 +410,8 @@ private: void _invalidate_current_line(ItemFrame *p_frame); - static void _thread_function(void *self); + void _thread_function(void *p_userdata); + void _thread_end(); void _stop_thread(); bool _validate_line_caches(); void _process_line_caches(); diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp index 1bba95f511..2e844269e3 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -667,7 +667,7 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_UNSHADED) { scene_state.ubo.ss_effects_flags = 0; - } else if (is_environment(p_render_data->environment)) { + } else if (p_render_data->reflection_probe.is_null() && is_environment(p_render_data->environment)) { scene_state.ubo.ssao_ao_affect = environment_get_ssao_ao_channel_affect(p_render_data->environment); scene_state.ubo.ssao_light_affect = environment_get_ssao_direct_light_affect(p_render_data->environment); uint32_t ss_flags = 0; @@ -1550,16 +1550,18 @@ void RenderForwardClustered::_process_sss(Ref<RenderSceneBuffersRD> p_render_buf void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) { RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); - Ref<RenderSceneBuffersRD> rb; + ERR_FAIL_NULL(p_render_data); + + Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers; + ERR_FAIL_COND(rb.is_null()); Ref<RenderBufferDataForwardClustered> rb_data; - if (p_render_data && p_render_data->render_buffers.is_valid()) { - rb = p_render_data->render_buffers; - if (rb->has_custom_data(RB_SCOPE_FORWARD_CLUSTERED)) { - // Our forward clustered custom data buffer will only be available when we're rendering our normal view. - // This will not be available when rendering reflection probes. - rb_data = rb->get_custom_data(RB_SCOPE_FORWARD_CLUSTERED); - } + if (rb->has_custom_data(RB_SCOPE_FORWARD_CLUSTERED)) { + // Our forward clustered custom data buffer will only be available when we're rendering our normal view. + // This will not be available when rendering reflection probes. + rb_data = rb->get_custom_data(RB_SCOPE_FORWARD_CLUSTERED); } + bool is_reflection_probe = p_render_data->reflection_probe.is_valid(); + static const int texture_multisamples[RS::VIEWPORT_MSAA_MAX] = { 1, 2, 4, 8 }; //first of all, make a new render pass @@ -1588,18 +1590,16 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co p_render_data->voxel_gi_count = 0; - if (rb.is_valid()) { - if (rb->has_custom_data(RB_SCOPE_SDFGI)) { - Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI); - if (sdfgi.is_valid()) { - sdfgi->update_cascades(); - sdfgi->pre_process_gi(p_render_data->scene_data->cam_transform, p_render_data); - sdfgi->update_light(); - } + if (rb->has_custom_data(RB_SCOPE_SDFGI)) { + Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI); + if (sdfgi.is_valid()) { + sdfgi->update_cascades(); + sdfgi->pre_process_gi(p_render_data->scene_data->cam_transform, p_render_data); + sdfgi->update_light(); } - - gi.setup_voxel_gi_instances(p_render_data, p_render_data->render_buffers, p_render_data->scene_data->cam_transform, *p_render_data->voxel_gi_instances, p_render_data->voxel_gi_count); } + + gi.setup_voxel_gi_instances(p_render_data, p_render_data->render_buffers, p_render_data->scene_data->cam_transform, *p_render_data->voxel_gi_instances, p_render_data->voxel_gi_count); } else { ERR_PRINT("No render buffer nor reflection atlas, bug"); //should never happen, will crash current_cluster_builder = nullptr; @@ -1618,7 +1618,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co // check if we need motion vectors if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS) { p_render_data->scene_data->calculate_motion_vectors = true; - } else if (rb.is_valid() && rb->get_use_taa()) { + } else if (!is_reflection_probe && rb->get_use_taa()) { p_render_data->scene_data->calculate_motion_vectors = true; } else { p_render_data->scene_data->calculate_motion_vectors = false; @@ -1641,9 +1641,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co bool using_sdfgi = false; bool using_voxelgi = false; bool reverse_cull = p_render_data->scene_data->cam_transform.basis.determinant() < 0; - bool using_ssil = p_render_data->environment.is_valid() && environment_get_ssil_enabled(p_render_data->environment); + bool using_ssil = !is_reflection_probe && p_render_data->environment.is_valid() && environment_get_ssil_enabled(p_render_data->environment); - if (p_render_data->reflection_probe.is_valid()) { + if (is_reflection_probe) { uint32_t resolution = light_storage->reflection_probe_instance_get_resolution(p_render_data->reflection_probe); screen_size.x = resolution; screen_size.y = resolution; @@ -1657,7 +1657,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co } reverse_cull = true; // for some reason our views are inverted - } else if (rb.is_valid()) { + } else { screen_size = rb->get_internal_size(); if (rb->get_use_taa() || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS) { @@ -1685,8 +1685,6 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co color_framebuffer = rb_data->get_color_pass_fb(color_pass_flags); color_only_framebuffer = rb_data->get_color_only_fb(); - } else { - ERR_FAIL(); //bug? } p_render_data->scene_data->emissive_exposure_normalization = -1.0; @@ -1695,7 +1693,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co _setup_lightmaps(p_render_data, *p_render_data->lightmaps, p_render_data->scene_data->cam_transform); _setup_voxelgis(*p_render_data->voxel_gi_instances); - _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false); + _setup_environment(p_render_data, is_reflection_probe, screen_size, !is_reflection_probe, p_default_bg_color, false); _update_render_base_uniform_set(); //may have changed due to the above (light buffer enlarged, as an example) @@ -1707,7 +1705,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co RD::get_singleton()->draw_command_end_label(); - if (rb.is_valid() && !p_render_data->reflection_probe.is_valid()) { + if (!is_reflection_probe) { if (using_voxelgi) { depth_pass_mode = PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI; } else if (p_render_data->environment.is_valid()) { @@ -1739,7 +1737,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co } } - bool using_sss = rb_data.is_valid() && scene_state.used_sss && ss_effects->sss_get_quality() != RS::SUB_SURFACE_SCATTERING_QUALITY_DISABLED; + bool using_sss = rb_data.is_valid() && !is_reflection_probe && scene_state.used_sss && ss_effects->sss_get_quality() != RS::SUB_SURFACE_SCATTERING_QUALITY_DISABLED; if (using_sss && !using_separate_specular) { using_separate_specular = true; @@ -1772,7 +1770,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co clear_color.r *= bg_energy_multiplier; clear_color.g *= bg_energy_multiplier; clear_color.b *= bg_energy_multiplier; - if ((rb.is_valid() && rb->has_custom_data(RB_SCOPE_FOG)) || environment_get_fog_enabled(p_render_data->environment)) { + if ((rb->has_custom_data(RB_SCOPE_FOG)) || environment_get_fog_enabled(p_render_data->environment)) { draw_sky_fog_only = true; RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear())); } @@ -1782,7 +1780,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co clear_color.r *= bg_energy_multiplier; clear_color.g *= bg_energy_multiplier; clear_color.b *= bg_energy_multiplier; - if ((rb.is_valid() && rb->has_custom_data(RB_SCOPE_FOG)) || environment_get_fog_enabled(p_render_data->environment)) { + if ((rb->has_custom_data(RB_SCOPE_FOG)) || environment_get_fog_enabled(p_render_data->environment)) { draw_sky_fog_only = true; RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear())); } @@ -1791,7 +1789,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co draw_sky = true; } break; case RS::ENV_BG_CANVAS: { - if (rb.is_valid()) { + if (!is_reflection_probe) { RID texture = RendererRD::TextureStorage::get_singleton()->render_target_get_rd_texture(rb->get_render_target()); copy_effects->copy_to_fb_rect(texture, color_only_framebuffer, Rect2i(), false, false, false, false, RID(), false, false, true); } @@ -1812,7 +1810,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co RD::get_singleton()->draw_command_begin_label("Setup Sky"); // Setup our sky render information for this frame/viewport - if (p_render_data->reflection_probe.is_valid()) { + if (is_reflection_probe) { Vector3 eye_offset; Projection correction; correction.set_depth_correction(true); @@ -1849,7 +1847,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co bool debug_sdfgi_probes = get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_SDFGI_PROBES; bool depth_pre_pass = bool(GLOBAL_GET("rendering/driver/depth_prepass/enable")) && depth_framebuffer.is_valid(); - bool using_ssao = depth_pre_pass && rb.is_valid() && p_render_data->environment.is_valid() && environment_get_ssao_enabled(p_render_data->environment); + bool using_ssao = depth_pre_pass && !is_reflection_probe && p_render_data->environment.is_valid() && environment_get_ssao_enabled(p_render_data->environment); bool continue_depth = false; if (depth_pre_pass) { //depth pre pass @@ -1881,7 +1879,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co _pre_resolve_render(p_render_data, using_sdfgi || using_voxelgi); } - if (rb.is_valid() && rb->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) { + if (rb->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) { RENDER_TIMESTAMP("Resolve Depth Pre-Pass (MSAA)"); RD::get_singleton()->draw_command_begin_label("Resolve Depth Pre-Pass (MSAA)"); if (depth_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS || depth_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI) { @@ -1915,7 +1913,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co p_render_data->scene_data->directional_light_count = p_render_data->directional_light_count; p_render_data->scene_data->opaque_prepass_threshold = 0.0f; - _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, rb.is_valid()); + _setup_environment(p_render_data, is_reflection_probe, screen_size, !is_reflection_probe, p_default_bg_color, true); RENDER_TIMESTAMP("Render Opaque Pass"); @@ -1996,7 +1994,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co RD::get_singleton()->draw_command_end_label(); } - if (rb.is_valid() && !can_continue_color && rb->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) { + if (!can_continue_color && rb->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) { // Handle views individual, might want to look at rewriting our resolve to do both layers in one pass. for (uint32_t v = 0; v < rb->get_view_count(); v++) { RD::get_singleton()->texture_resolve_multisample(rb_data->get_color_msaa(v), rb->get_internal_texture(v)); @@ -2008,7 +2006,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co } } - if (rb.is_valid() && !can_continue_depth && rb->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) { + if (!can_continue_depth && rb->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) { for (uint32_t v = 0; v < rb->get_view_count(); v++) { resolve_effects->resolve_depth(rb_data->get_depth_msaa(v), rb->get_depth_texture(v), rb->get_internal_size(), texture_multisamples[rb->get_msaa_3d()]); } @@ -2054,7 +2052,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_ALPHA, p_render_data, radiance_texture, true); - _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false); + _setup_environment(p_render_data, is_reflection_probe, screen_size, !is_reflection_probe, p_default_bg_color, false); { uint32_t transparent_color_pass_flags = (color_pass_flags | COLOR_PASS_FLAG_TRANSPARENT) & ~(COLOR_PASS_FLAG_SEPARATE_SPECULAR); diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp index 4065d253bb..7d9ca070b0 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -640,16 +640,18 @@ void RenderForwardMobile::_pre_opaque_render(RenderDataRD *p_render_data) { void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) { RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); - Ref<RenderSceneBuffersRD> rb; + ERR_FAIL_NULL(p_render_data); + + Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers; + ERR_FAIL_COND(rb.is_null()); + Ref<RenderBufferDataForwardMobile> rb_data; - if (p_render_data->render_buffers.is_valid()) { - rb = p_render_data->render_buffers; - if (rb->has_custom_data(RB_SCOPE_MOBILE)) { - // Our forward mobile custom data buffer will only be available when we're rendering our normal view. - // This will not be available when rendering reflection probes. - rb_data = rb->get_custom_data(RB_SCOPE_MOBILE); - } + if (rb->has_custom_data(RB_SCOPE_MOBILE)) { + // Our forward mobile custom data buffer will only be available when we're rendering our normal view. + // This will not be available when rendering reflection probes. + rb_data = rb->get_custom_data(RB_SCOPE_MOBILE); } + bool is_reflection_probe = p_render_data->reflection_probe.is_valid(); RENDER_TIMESTAMP("Prepare 3D Scene"); @@ -697,7 +699,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME] = p_render_data->instances->size(); } - if (p_render_data->reflection_probe.is_valid()) { + if (is_reflection_probe) { uint32_t resolution = light_storage->reflection_probe_instance_get_resolution(p_render_data->reflection_probe); screen_size.x = resolution; screen_size.y = resolution; @@ -754,7 +756,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color RD::get_singleton()->draw_command_begin_label("Render Setup"); _setup_lightmaps(p_render_data, *p_render_data->lightmaps, p_render_data->scene_data->cam_transform); - _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false); + _setup_environment(p_render_data, is_reflection_probe, screen_size, !is_reflection_probe, p_default_bg_color, false); _update_render_base_uniform_set(); //may have changed due to the above (light buffer enlarged, as an example) @@ -832,7 +834,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color RD::get_singleton()->draw_command_begin_label("Setup Sky"); // Setup our sky render information for this frame/viewport - if (p_render_data->reflection_probe.is_valid()) { + if (is_reflection_probe) { Vector3 eye_offset; Projection correction; correction.set_depth_correction(true); @@ -896,7 +898,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color p_render_data->scene_data->directional_light_count = p_render_data->directional_light_count; - _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, p_render_data->render_buffers.is_valid()); + _setup_environment(p_render_data, is_reflection_probe, screen_size, !is_reflection_probe, p_default_bg_color, p_render_data->render_buffers.is_valid()); if (using_subpass_transparent && using_subpass_post_process) { RENDER_TIMESTAMP("Render Opaque + Transparent + Tonemap"); @@ -1025,7 +1027,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color } // this may be needed if we re-introduced steps that change info, not sure which do so in the previous implementation - // _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false); + // _setup_environment(p_render_data, is_reflection_probe, screen_size, !is_reflection_probe, p_default_bg_color, false); RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(framebuffer); RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, spec_constant_base_flags, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count); @@ -1065,9 +1067,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color _disable_clear_request(p_render_data); } - if (rb.is_valid()) { - _render_buffers_debug_draw(rb, p_render_data->shadow_atlas, p_render_data->occluder_debug_tex); - } + _render_buffers_debug_draw(rb, p_render_data->shadow_atlas, p_render_data->occluder_debug_tex); } /* these are being called from RendererSceneRenderRD::_pre_opaque_render */ @@ -1924,7 +1924,6 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const } void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data, bool p_no_fog, const Size2i &p_screen_size, bool p_flip_y, const Color &p_default_bg_color, bool p_opaque_render_buffers, bool p_pancake_shadows, int p_index) { - Ref<RenderSceneBuffersRD> rd = p_render_data->render_buffers; RID env = is_environment(p_render_data->environment) ? p_render_data->environment : RID(); RID reflection_probe_instance = p_render_data->reflection_probe.is_valid() ? RendererRD::LightStorage::get_singleton()->reflection_probe_instance_get_probe(p_render_data->reflection_probe) : RID(); diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index 33f6ac0276..885ea18151 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -331,9 +331,13 @@ void RendererSceneRenderRD::_render_buffers_copy_depth_texture(const RenderDataR void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const RenderDataRD *p_render_data) { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + ERR_FAIL_NULL(p_render_data); + Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers; ERR_FAIL_COND(rb.is_null()); + ERR_FAIL_COND_MSG(p_render_data->reflection_probe.is_valid(), "Post processes should not be applied on reflection probes."); + // Glow, auto exposure and DoF (if enabled). Size2i internal_size = rb->get_internal_size(); @@ -928,11 +932,9 @@ void RendererSceneRenderRD::render_scene(const Ref<RenderSceneBuffers> &p_render RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); // getting this here now so we can direct call a bunch of things more easily - Ref<RenderSceneBuffersRD> rb; - if (p_render_buffers.is_valid()) { - rb = p_render_buffers; // cast it... - ERR_FAIL_COND(rb.is_null()); - } + ERR_FAIL_COND(p_render_buffers.is_null()); + Ref<RenderSceneBuffersRD> rb = p_render_buffers; + ERR_FAIL_COND(rb.is_null()); // setup scene data RenderSceneDataRD scene_data; diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp index 9011cdd98a..6f4bb115fc 100644 --- a/servers/rendering/renderer_scene_cull.cpp +++ b/servers/rendering/renderer_scene_cull.cpp @@ -2964,11 +2964,13 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c Scenario *scenario = scenario_owner.get_or_null(p_scenario); + ERR_FAIL_COND(p_render_buffers.is_null()); + render_pass++; scene_render->set_scene_pass(render_pass); - if (p_render_buffers.is_valid() && p_reflection_probe.is_null()) { + if (p_reflection_probe.is_null()) { //no rendering code here, this is only to set up what needs to be done, request regions, etc. scene_render->sdfgi_update(p_render_buffers, p_environment, p_camera_data->main_transform.origin); //update conditions for SDFGI (whether its used or not) } @@ -3050,7 +3052,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c { //sdfgi cull.sdfgi.region_count = 0; - if (p_render_buffers.is_valid() && p_reflection_probe.is_null()) { + if (p_reflection_probe.is_null()) { cull.sdfgi.cascade_light_count = 0; uint32_t prev_cascade = 0xFFFFFFFF; @@ -3279,7 +3281,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c } } - if (p_render_buffers.is_valid() && p_reflection_probe.is_null()) { + if (p_reflection_probe.is_null()) { sdfgi_update_data.directional_lights = &directional_lights; sdfgi_update_data.positional_light_instances = scenario->dynamic_lights.ptr(); sdfgi_update_data.positional_light_count = scenario->dynamic_lights.size(); diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index 7a4ac709f4..11a9303f11 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -8759,6 +8759,10 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f new_hint = ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE; --texture_uniforms; --texture_binding; + if (OS::get_singleton()->get_current_rendering_method() == "gl_compatibility") { + _set_error(RTR("'hint_normal_roughness_texture is not supported in gl_compatibility shaders.")); + return ERR_PARSE_ERROR; + } } break; case TK_HINT_DEPTH_TEXTURE: { new_hint = ShaderNode::Uniform::HINT_DEPTH_TEXTURE; |