diff --git a/doc/classes/SceneTree.xml b/doc/classes/SceneTree.xml index 970f5125cdb..3cd2ab09033 100644 --- a/doc/classes/SceneTree.xml +++ b/doc/classes/SceneTree.xml @@ -18,9 +18,9 @@ - Calls [code]method[/code] on each member of the given group. You can pass arguments to [code]method[/code] by specifying them at the end of the method call. This method is equivalent of calling [method call_group_flags] with [constant GROUP_CALL_DEFAULT] flag. + Calls [code]method[/code] on each member of the given group. You can pass arguments to [code]method[/code] by specifying them at the end of the method call. [b]Note:[/b] Due to design limitations, [method call_group] will fail silently if one of the arguments is [code]null[/code]. - [b]Note:[/b] [method call_group] will always call methods with an one-frame delay, in a way similar to [method Object.call_deferred]. To call methods immediately, use [method call_group_flags] with the [constant GROUP_CALL_REALTIME] flag. + [b]Note:[/b] [method call_group] will call methods immediately on all members at once, which can cause stuttering if an expensive method is called on lots of members. To wait for one frame after [method call_group] was called, use [method call_group_flags] with the [constant GROUP_CALL_DEFERRED] flag. @@ -30,11 +30,12 @@ Calls [code]method[/code] on each member of the given group, respecting the given [enum GroupCallFlags]. You can pass arguments to [code]method[/code] by specifying them at the end of the method call. - [b]Note:[/b] Due to design limitations, [method call_group_flags] will fail silently if one of the arguments is [code]null[/code]. [codeblock] - # Call the method immediately and in reverse order. - get_tree().call_group_flags(SceneTree.GROUP_CALL_REALTIME | SceneTree.GROUP_CALL_REVERSE, "bases", "destroy") + # Call the method in a deferred manner and in reverse order. + get_tree().call_group_flags(SceneTree.GROUP_CALL_DEFERRED | SceneTree.GROUP_CALL_REVERSE) [/codeblock] + [b]Note:[/b] Due to design limitations, [method call_group_flags] will fail silently if one of the arguments is [code]null[/code]. + [b]Note:[/b] Group call flags are used to control the method calling behavior. By default, methods will be called immediately in a way similar to [method call_group]. However, if the [constant GROUP_CALL_DEFERRED] flag is present in the [code]flags[/code] argument, methods will be called with a one-frame delay in a way similar to [method Object.set_deferred]. @@ -139,6 +140,7 @@ Sends the given notification to all members of the [code]group[/code]. + [b]Note:[/b] [method notify_group] will immediately notify all members at once, which can cause stuttering if an expensive method is called as a result of sending the notification lots of members. To wait for one frame, use [method notify_group_flags] with the [constant GROUP_CALL_DEFERRED] flag. @@ -148,6 +150,7 @@ Sends the given notification to all members of the [code]group[/code], respecting the given [enum GroupCallFlags]. + [b]Note:[/b] Group call flags are used to control the notification sending behavior. By default, notifications will be sent immediately in a way similar to [method notify_group]. However, if the [constant GROUP_CALL_DEFERRED] flag is present in the [code]flags[/code] argument, notifications will be sent with a one-frame delay in a way similar to using [code]Object.call_deferred("notification", ...)[/code]. @@ -189,6 +192,7 @@ Sets the given [code]property[/code] to [code]value[/code] on all members of the given group. + [b]Note:[/b] [method set_group] will set the property immediately on all members at once, which can cause stuttering if a property with an expensive setter is set on lots of members. To wait for one frame, use [method set_group_flags] with the [constant GROUP_CALL_DEFERRED] flag. @@ -199,6 +203,7 @@ Sets the given [code]property[/code] to [code]value[/code] on all members of the given group, respecting the given [enum GroupCallFlags]. + [b]Note:[/b] Group call flags are used to control the property setting behavior. By default, properties will be set immediately in a way similar to [method set_group]. However, if the [constant GROUP_CALL_DEFERRED] flag is present in the [code]flags[/code] argument, properties will be set with a one-frame delay in a way similar to [method Object.call_deferred]. @@ -297,8 +302,8 @@ Call a group in reverse scene order. - - Call a group immediately (calls are normally made on idle). + + Call a group with a one-frame delay (idle frame, not physics). Call a group only once even if the call is executed many times. diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp index efde8d8a2bc..f61dbc071d0 100644 --- a/scene/2d/camera_2d.cpp +++ b/scene/2d/camera_2d.cpp @@ -57,7 +57,7 @@ void Camera2D::_update_scroll() { Size2 screen_size = _get_camera_screen_size(); Point2 screen_offset = (anchor_mode == ANCHOR_MODE_DRAG_CENTER ? (screen_size * 0.5) : Point2()); - get_tree()->call_group_flags(SceneTree::GROUP_CALL_REALTIME, group_name, "_camera_moved", xform, screen_offset); + get_tree()->call_group(group_name, "_camera_moved", xform, screen_offset); }; } @@ -421,7 +421,7 @@ bool Camera2D::is_current() const { void Camera2D::make_current() { if (is_inside_tree()) { - get_tree()->call_group_flags(SceneTree::GROUP_CALL_REALTIME, group_name, "_make_current", this); + get_tree()->call_group(group_name, "_make_current", this); } else { current = true; } @@ -430,7 +430,7 @@ void Camera2D::make_current() { void Camera2D::clear_current() { if (is_inside_tree()) { - get_tree()->call_group_flags(SceneTree::GROUP_CALL_REALTIME, group_name, "_make_current", (Object *)nullptr); + get_tree()->call_group(group_name, "_make_current", (Object *)nullptr); } else { current = false; } diff --git a/scene/3d/camera_3d.cpp b/scene/3d/camera_3d.cpp index 4f05e803772..4c53776bbaf 100644 --- a/scene/3d/camera_3d.cpp +++ b/scene/3d/camera_3d.cpp @@ -217,8 +217,6 @@ void Camera3D::make_current() { } get_viewport()->_camera_3d_set(this); - - //get_scene()->call_group(SceneMainLoop::GROUP_CALL_REALTIME,camera_group,"_camera_make_current",this); } void Camera3D::clear_current(bool p_enable_next) { diff --git a/scene/3d/world_environment.cpp b/scene/3d/world_environment.cpp index f6386446281..fe9d9ae4dd1 100644 --- a/scene/3d/world_environment.cpp +++ b/scene/3d/world_environment.cpp @@ -71,7 +71,7 @@ void WorldEnvironment::_update_current_environment() { } else { get_viewport()->find_world_3d()->set_environment(Ref()); } - get_tree()->call_group("_world_environment_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()), "update_configuration_warnings"); + get_tree()->call_group_flags(SceneTree::GROUP_CALL_DEFERRED, "_world_environment_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()), "update_configuration_warnings"); } void WorldEnvironment::_update_current_camera_effects() { @@ -82,7 +82,7 @@ void WorldEnvironment::_update_current_camera_effects() { get_viewport()->find_world_3d()->set_camera_effects(Ref()); } - get_tree()->call_group("_world_camera_effects_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()), "update_configuration_warnings"); + get_tree()->call_group_flags(SceneTree::GROUP_CALL_DEFERRED, "_world_camera_effects_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()), "update_configuration_warnings"); } void WorldEnvironment::set_environment(const Ref &p_environment) { diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index a151d3cb330..9d80b3cc0f8 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -181,7 +181,7 @@ void SceneTree::_flush_ugc() { argptrs[i] = &E->get()[i]; } - call_group_flagsp(GROUP_CALL_REALTIME, E->key().group, E->key().call, argptrs, E->get().size()); + call_group_flagsp(GROUP_CALL_DEFAULT, E->key().group, E->key().call, argptrs, E->get().size()); unique_group_calls.erase(E); } @@ -220,7 +220,7 @@ void SceneTree::call_group_flagsp(uint32_t p_call_flags, const StringName &p_gro return; } - if (p_call_flags & GROUP_CALL_UNIQUE && !(p_call_flags & GROUP_CALL_REALTIME)) { + if (p_call_flags & GROUP_CALL_UNIQUE && p_call_flags & GROUP_CALL_DEFERRED) { ERR_FAIL_COND(ugc_locked); UGCall ug; @@ -254,7 +254,7 @@ void SceneTree::call_group_flagsp(uint32_t p_call_flags, const StringName &p_gro continue; } - if (p_call_flags & GROUP_CALL_REALTIME) { + if (!(p_call_flags & GROUP_CALL_DEFERRED)) { Callable::CallError ce; nodes[i]->callp(p_function, p_args, p_argcount, ce); } else { @@ -268,7 +268,7 @@ void SceneTree::call_group_flagsp(uint32_t p_call_flags, const StringName &p_gro continue; } - if (p_call_flags & GROUP_CALL_REALTIME) { + if (!(p_call_flags & GROUP_CALL_DEFERRED)) { Callable::CallError ce; nodes[i]->callp(p_function, p_args, p_argcount, ce); } else { @@ -307,7 +307,7 @@ void SceneTree::notify_group_flags(uint32_t p_call_flags, const StringName &p_gr continue; } - if (p_call_flags & GROUP_CALL_REALTIME) { + if (!(p_call_flags & GROUP_CALL_DEFERRED)) { nodes[i]->notification(p_notification); } else { MessageQueue::get_singleton()->push_notification(nodes[i], p_notification); @@ -320,7 +320,7 @@ void SceneTree::notify_group_flags(uint32_t p_call_flags, const StringName &p_gr continue; } - if (p_call_flags & GROUP_CALL_REALTIME) { + if (!(p_call_flags & GROUP_CALL_DEFERRED)) { nodes[i]->notification(p_notification); } else { MessageQueue::get_singleton()->push_notification(nodes[i], p_notification); @@ -358,7 +358,7 @@ void SceneTree::set_group_flags(uint32_t p_call_flags, const StringName &p_group continue; } - if (p_call_flags & GROUP_CALL_REALTIME) { + if (!(p_call_flags & GROUP_CALL_DEFERRED)) { nodes[i]->set(p_name, p_value); } else { MessageQueue::get_singleton()->push_set(nodes[i], p_name, p_value); @@ -371,7 +371,7 @@ void SceneTree::set_group_flags(uint32_t p_call_flags, const StringName &p_group continue; } - if (p_call_flags & GROUP_CALL_REALTIME) { + if (!(p_call_flags & GROUP_CALL_DEFERRED)) { nodes[i]->set(p_name, p_value); } else { MessageQueue::get_singleton()->push_set(nodes[i], p_name, p_value); @@ -390,7 +390,7 @@ void SceneTree::notify_group(const StringName &p_group, int p_notification) { } void SceneTree::set_group(const StringName &p_group, const String &p_name, const Variant &p_value) { - set_group_flags(0, p_group, p_name, p_value); + set_group_flags(GROUP_CALL_DEFAULT, p_group, p_name, p_value); } void SceneTree::initialize() { @@ -413,7 +413,7 @@ bool SceneTree::physics_process(double p_time) { emit_signal(SNAME("physics_frame")); _notify_group_pause(SNAME("physics_process_internal"), Node::NOTIFICATION_INTERNAL_PHYSICS_PROCESS); - call_group_flags(GROUP_CALL_REALTIME, SNAME("_picking_viewports"), SNAME("_process_picking")); + call_group(SNAME("_picking_viewports"), SNAME("_process_picking")); _notify_group_pause(SNAME("physics_process"), Node::NOTIFICATION_PHYSICS_PROCESS); _flush_ugc(); MessageQueue::get_singleton()->flush(); //small little hack @@ -944,7 +944,7 @@ void SceneTree::_call_group(const Variant **p_args, int p_argcount, Callable::Ca StringName group = *p_args[0]; StringName method = *p_args[1]; - call_group_flagsp(0, group, method, p_args + 2, p_argcount - 2); + call_group_flagsp(GROUP_CALL_DEFAULT, group, method, p_args + 2, p_argcount - 2); } int64_t SceneTree::get_frame() const { @@ -1277,7 +1277,7 @@ void SceneTree::_bind_methods() { BIND_ENUM_CONSTANT(GROUP_CALL_DEFAULT); BIND_ENUM_CONSTANT(GROUP_CALL_REVERSE); - BIND_ENUM_CONSTANT(GROUP_CALL_REALTIME); + BIND_ENUM_CONSTANT(GROUP_CALL_DEFERRED); BIND_ENUM_CONSTANT(GROUP_CALL_UNIQUE); } diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h index 9d7757e0a37..d633fb38d05 100644 --- a/scene/main/scene_tree.h +++ b/scene/main/scene_tree.h @@ -151,7 +151,6 @@ private: int collision_debug_contacts; void _change_scene(Node *p_to); - //void _call_group(uint32_t p_call_flags,const StringName& p_group,const StringName& p_function,const Variant& p_arg1,const Variant& p_arg2); List> timers; List> tweens; @@ -225,7 +224,7 @@ public: enum GroupCallFlags { GROUP_CALL_DEFAULT = 0, GROUP_CALL_REVERSE = 1, - GROUP_CALL_REALTIME = 2, + GROUP_CALL_DEFERRED = 2, GROUP_CALL_UNIQUE = 4, }; @@ -235,17 +234,20 @@ public: void notify_group_flags(uint32_t p_call_flags, const StringName &p_group, int p_notification); void set_group_flags(uint32_t p_call_flags, const StringName &p_group, const String &p_name, const Variant &p_value); + // `notify_group()` is immediate by default since Godot 4.0. void notify_group(const StringName &p_group, int p_notification); + // `set_group()` is immediate by default since Godot 4.0. void set_group(const StringName &p_group, const String &p_name, const Variant &p_value); template + // `call_group()` is immediate by default since Godot 4.0. void call_group(const StringName &p_group, const StringName &p_function, VarArgs... p_args) { Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported. const Variant *argptrs[sizeof...(p_args) + 1]; for (uint32_t i = 0; i < sizeof...(p_args); i++) { argptrs[i] = &args[i]; } - call_group_flagsp(0, p_group, p_function, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args)); + call_group_flagsp(GROUP_CALL_DEFAULT, p_group, p_function, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args)); } template diff --git a/scene/main/shader_globals_override.cpp b/scene/main/shader_globals_override.cpp index 7c689bd4365..ed08c45a01f 100644 --- a/scene/main/shader_globals_override.cpp +++ b/scene/main/shader_globals_override.cpp @@ -267,7 +267,7 @@ void ShaderGlobalsOverride::_notification(int p_what) { remove_from_group(SceneStringNames::get_singleton()->shader_overrides_group_active); remove_from_group(SceneStringNames::get_singleton()->shader_overrides_group); - get_tree()->call_group(SceneStringNames::get_singleton()->shader_overrides_group, "_activate"); //another may want to activate when this is removed + get_tree()->call_group_flags(SceneTree::GROUP_CALL_DEFERRED, SceneStringNames::get_singleton()->shader_overrides_group, "_activate"); //another may want to activate when this is removed active = false; } break; } diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index d7e58ed7077..e4037c28430 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -2186,7 +2186,7 @@ void Viewport::_gui_control_grab_focus(Control *p_control) { // No need for change. return; } - get_tree()->call_group_flags(SceneTree::GROUP_CALL_REALTIME, "_viewports", "_gui_remove_focus_for_window", (Node *)get_base_window()); + get_tree()->call_group("_viewports", "_gui_remove_focus_for_window", (Node *)get_base_window()); gui.key_focus = p_control; emit_signal(SNAME("gui_focus_changed"), p_control); p_control->notification(Control::NOTIFICATION_FOCUS_ENTER); diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index 16fce5e08aa..27e15909402 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -84,7 +84,7 @@ void Material::inspect_native_shader_code() { SceneTree *st = Object::cast_to(OS::get_singleton()->get_main_loop()); RID shader = get_shader_rid(); if (st && shader.is_valid()) { - st->call_group("_native_shader_source_visualizer", "_inspect_shader", shader); + st->call_group_flags(SceneTree::GROUP_CALL_DEFERRED, "_native_shader_source_visualizer", "_inspect_shader", shader); } }