diff options
Diffstat (limited to 'scene')
| -rw-r--r-- | scene/3d/physics_body_3d.cpp | 2 | ||||
| -rw-r--r-- | scene/animation/animation_player.cpp | 63 | ||||
| -rw-r--r-- | scene/animation/animation_tree.cpp | 56 | ||||
| -rw-r--r-- | scene/debugger/scene_debugger.cpp | 33 | ||||
| -rw-r--r-- | scene/debugger/scene_debugger.h | 4 | ||||
| -rw-r--r-- | scene/gui/control.cpp | 35 | ||||
| -rw-r--r-- | scene/gui/tab_bar.cpp | 81 | ||||
| -rw-r--r-- | scene/gui/tab_bar.h | 6 | ||||
| -rw-r--r-- | scene/gui/tree.cpp | 2 | ||||
| -rw-r--r-- | scene/main/node.cpp | 68 | ||||
| -rw-r--r-- | scene/main/node.h | 28 | ||||
| -rw-r--r-- | scene/main/scene_tree.cpp | 50 | ||||
| -rw-r--r-- | scene/main/scene_tree.h | 23 | ||||
| -rw-r--r-- | scene/main/viewport.cpp | 4 | ||||
| -rw-r--r-- | scene/main/window.cpp | 12 | ||||
| -rw-r--r-- | scene/main/window.h | 2 | ||||
| -rw-r--r-- | scene/multiplayer/scene_rpc_interface.cpp | 6 |
17 files changed, 225 insertions, 250 deletions
diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp index c1f5ab1d32..47baa9e023 100644 --- a/scene/3d/physics_body_3d.cpp +++ b/scene/3d/physics_body_3d.cpp @@ -1425,7 +1425,7 @@ void CharacterBody3D::_move_and_slide_grounded(double p_delta, bool p_was_on_flo const PhysicsServer3D::MotionCollision &collision = result.collisions[0]; Vector3 slide_motion = result.remainder.slide(collision.normal); - if (collision_state.floor && !collision_state.wall) { + if (collision_state.floor && !collision_state.wall && !motion_slide_up.is_equal_approx(Vector3())) { // Slide using the intersection between the motion plane and the floor plane, // in order to keep the direction intact. real_t motion_length = slide_motion.length(); diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index e243915c13..402418e5a9 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -401,6 +401,22 @@ void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim, Node *p_root_ov } } +static void _call_object(Object *p_object, const StringName &p_method, const Vector<Variant> &p_params, bool p_deferred) { + // Separate function to use alloca() more efficiently + const Variant **argptrs = (const Variant **)alloca(sizeof(const Variant **) * p_params.size()); + const Variant *args = p_params.ptr(); + uint32_t argcount = p_params.size(); + for (uint32_t i = 0; i < argcount; i++) { + argptrs[i] = &args[i]; + } + if (p_deferred) { + MessageQueue::get_singleton()->push_callp(p_object, p_method, argptrs, argcount); + } else { + Callable::CallError ce; + p_object->callp(p_method, argptrs, argcount, ce); + } +} + void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double p_time, double p_delta, float p_interp, bool p_is_current, bool p_seeked, bool p_started, int p_pingponged) { _ensure_node_caches(p_anim); ERR_FAIL_COND(p_anim->node_cache.size() != p_anim->animation->get_track_count()); @@ -677,41 +693,14 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double StringName method = a->method_track_get_name(i, E); Vector<Variant> params = a->method_track_get_params(i, E); - int s = params.size(); - - ERR_CONTINUE(s > VARIANT_ARG_MAX); #ifdef DEBUG_ENABLED if (!nc->node->has_method(method)) { ERR_PRINT("Invalid method call '" + method + "'. '" + a->get_name() + "' at node '" + get_path() + "'."); } #endif - static_assert(VARIANT_ARG_MAX == 8, "This code needs to be updated if VARIANT_ARG_MAX != 8"); if (can_call) { - if (method_call_mode == ANIMATION_METHOD_CALL_DEFERRED) { - MessageQueue::get_singleton()->push_call( - nc->node, - method, - s >= 1 ? params[0] : Variant(), - s >= 2 ? params[1] : Variant(), - s >= 3 ? params[2] : Variant(), - s >= 4 ? params[3] : Variant(), - s >= 5 ? params[4] : Variant(), - s >= 6 ? params[5] : Variant(), - s >= 7 ? params[6] : Variant(), - s >= 8 ? params[7] : Variant()); - } else { - nc->node->call( - method, - s >= 1 ? params[0] : Variant(), - s >= 2 ? params[1] : Variant(), - s >= 3 ? params[2] : Variant(), - s >= 4 ? params[3] : Variant(), - s >= 5 ? params[4] : Variant(), - s >= 6 ? params[5] : Variant(), - s >= 7 ? params[6] : Variant(), - s >= 8 ? params[7] : Variant()); - } + _call_object(nc->node, method, params, method_call_mode == ANIMATION_METHOD_CALL_DEFERRED); } } @@ -754,7 +743,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double Ref<AudioStream> stream = a->audio_track_get_key_stream(i, idx); if (!stream.is_valid()) { - nc->node->call("stop"); + nc->node->call(SNAME("stop")); nc->audio_playing = false; playing_caches.erase(nc); } else { @@ -764,14 +753,14 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double float len = stream->get_length(); if (start_ofs > len - end_ofs) { - nc->node->call("stop"); + nc->node->call(SNAME("stop")); nc->audio_playing = false; playing_caches.erase(nc); continue; } - nc->node->call("set_stream", stream); - nc->node->call("play", start_ofs); + nc->node->call(SNAME("set_stream"), stream); + nc->node->call(SNAME("play"), start_ofs); nc->audio_playing = true; playing_caches.insert(nc); @@ -793,7 +782,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double Ref<AudioStream> stream = a->audio_track_get_key_stream(i, idx); if (!stream.is_valid()) { - nc->node->call("stop"); + nc->node->call(SNAME("stop")); nc->audio_playing = false; playing_caches.erase(nc); } else { @@ -801,8 +790,8 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double float end_ofs = a->audio_track_get_key_end_offset(i, idx); float len = stream->get_length(); - nc->node->call("set_stream", stream); - nc->node->call("play", start_ofs); + nc->node->call(SNAME("set_stream"), stream); + nc->node->call(SNAME("play"), start_ofs); nc->audio_playing = true; playing_caches.insert(nc); @@ -833,7 +822,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double if (stop) { //time to stop - nc->node->call("stop"); + nc->node->call(SNAME("stop")); nc->audio_playing = false; playing_caches.erase(nc); } @@ -1544,7 +1533,7 @@ void AnimationPlayer::_animation_changed() { void AnimationPlayer::_stop_playing_caches() { for (Set<TrackNodeCache *>::Element *E = playing_caches.front(); E; E = E->next()) { if (E->get()->node && E->get()->audio_playing) { - E->get()->node->call("stop"); + E->get()->node->call(SNAME("stop")); } if (E->get()->node && E->get()->animation_playing) { AnimationPlayer *player = Object::cast_to<AnimationPlayer>(E->get()->node); diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp index a50618182d..e0e94d8632 100644 --- a/scene/animation/animation_tree.cpp +++ b/scene/animation/animation_tree.cpp @@ -490,7 +490,7 @@ void AnimationTree::set_active(bool p_active) { if (!active && is_inside_tree()) { for (Set<TrackCache *>::Element *E = playing_caches.front(); E; E = E->next()) { if (ObjectDB::get_instance(E->get()->object_id)) { - E->get()->object->call("stop"); + E->get()->object->call(SNAME("stop")); } } @@ -796,6 +796,21 @@ void AnimationTree::_clear_caches() { cache_valid = false; } +static void _call_object(Object *p_object, const StringName &p_method, const Vector<Variant> &p_params, bool p_deferred) { + // Separate function to use alloca() more efficiently + const Variant **argptrs = (const Variant **)alloca(sizeof(const Variant **) * p_params.size()); + const Variant *args = p_params.ptr(); + uint32_t argcount = p_params.size(); + for (uint32_t i = 0; i < argcount; i++) { + argptrs[i] = &args[i]; + } + if (p_deferred) { + MessageQueue::get_singleton()->push_callp(p_object, p_method, argptrs, argcount); + } else { + Callable::CallError ce; + p_object->callp(p_method, argptrs, argcount, ce); + } +} void AnimationTree::_process_graph(double p_delta) { _update_properties(); //if properties need updating, update them @@ -1286,25 +1301,10 @@ void AnimationTree::_process_graph(double p_delta) { for (int &F : indices) { StringName method = a->method_track_get_name(i, F); Vector<Variant> params = a->method_track_get_params(i, F); - - int s = params.size(); - - static_assert(VARIANT_ARG_MAX == 8, "This code needs to be updated if VARIANT_ARG_MAX != 8"); - ERR_CONTINUE(s > VARIANT_ARG_MAX); if (can_call) { - t->object->call_deferred( - method, - s >= 1 ? params[0] : Variant(), - s >= 2 ? params[1] : Variant(), - s >= 3 ? params[2] : Variant(), - s >= 4 ? params[3] : Variant(), - s >= 5 ? params[4] : Variant(), - s >= 6 ? params[5] : Variant(), - s >= 7 ? params[6] : Variant(), - s >= 8 ? params[7] : Variant()); + _call_object(t->object, method, params, true); } } - } break; case Animation::TYPE_BEZIER: { TrackCacheBezier *t = static_cast<TrackCacheBezier *>(track); @@ -1331,7 +1331,7 @@ void AnimationTree::_process_graph(double p_delta) { Ref<AudioStream> stream = a->audio_track_get_key_stream(i, idx); if (!stream.is_valid()) { - t->object->call("stop"); + t->object->call(SNAME("stop")); t->playing = false; playing_caches.erase(t); } else { @@ -1341,14 +1341,14 @@ void AnimationTree::_process_graph(double p_delta) { double len = stream->get_length(); if (start_ofs > len - end_ofs) { - t->object->call("stop"); + t->object->call(SNAME("stop")); t->playing = false; playing_caches.erase(t); continue; } - t->object->call("set_stream", stream); - t->object->call("play", start_ofs); + t->object->call(SNAME("set_stream"), stream); + t->object->call(SNAME("play"), start_ofs); t->playing = true; playing_caches.insert(t); @@ -1370,7 +1370,7 @@ void AnimationTree::_process_graph(double p_delta) { Ref<AudioStream> stream = a->audio_track_get_key_stream(i, idx); if (!stream.is_valid()) { - t->object->call("stop"); + t->object->call(SNAME("stop")); t->playing = false; playing_caches.erase(t); } else { @@ -1378,8 +1378,8 @@ void AnimationTree::_process_graph(double p_delta) { double end_ofs = a->audio_track_get_key_end_offset(i, idx); double len = stream->get_length(); - t->object->call("set_stream", stream); - t->object->call("play", start_ofs); + t->object->call(SNAME("set_stream"), stream); + t->object->call(SNAME("play"), start_ofs); t->playing = true; playing_caches.insert(t); @@ -1416,7 +1416,7 @@ void AnimationTree::_process_graph(double p_delta) { if (stop) { //time to stop - t->object->call("stop"); + t->object->call(SNAME("stop")); t->playing = false; playing_caches.erase(t); } @@ -1424,10 +1424,10 @@ void AnimationTree::_process_graph(double p_delta) { } real_t db = Math::linear2db(MAX(blend, 0.00001)); - if (t->object->has_method("set_unit_db")) { - t->object->call("set_unit_db", db); + if (t->object->has_method(SNAME("set_unit_db"))) { + t->object->call(SNAME("set_unit_db"), db); } else { - t->object->call("set_volume_db", db); + t->object->call(SNAME("set_volume_db"), db); } } break; case Animation::TYPE_ANIMATION: { diff --git a/scene/debugger/scene_debugger.cpp b/scene/debugger/scene_debugger.cpp index e5b81f9d8d..ac0d017a23 100644 --- a/scene/debugger/scene_debugger.cpp +++ b/scene/debugger/scene_debugger.cpp @@ -34,6 +34,7 @@ #include "core/debugger/engine_profiler.h" #include "core/io/marshalls.h" #include "core/object/script_language.h" +#include "core/templates/local_vector.h" #include "scene/main/scene_tree.h" #include "scene/main/window.h" #include "scene/resources/packed_scene.h" @@ -236,12 +237,28 @@ Error SceneDebugger::parse_message(void *p_user, const String &p_msg, const Arra live_editor->_res_set_func(p_args[0], p_args[1], p_args[2]); } else if (p_msg == "live_node_call") { - ERR_FAIL_COND_V(p_args.size() < 10, ERR_INVALID_DATA); - live_editor->_node_call_func(p_args[0], p_args[1], p_args[2], p_args[3], p_args[4], p_args[5], p_args[6], p_args[7], p_args[8], p_args[9]); + LocalVector<Variant> args; + LocalVector<Variant *> argptrs; + args.resize(p_args.size() - 2); + argptrs.resize(args.size()); + for (uint32_t i = 0; i < args.size(); i++) { + args[i] = p_args[i + 2]; + argptrs[i] = &args[i]; + } + live_editor->_node_call_func(p_args[0], p_args[1], (const Variant **)argptrs.ptr(), argptrs.size()); } else if (p_msg == "live_res_call") { ERR_FAIL_COND_V(p_args.size() < 10, ERR_INVALID_DATA); - live_editor->_res_call_func(p_args[0], p_args[1], p_args[2], p_args[3], p_args[4], p_args[5], p_args[6], p_args[7], p_args[8], p_args[9]); + + LocalVector<Variant> args; + LocalVector<Variant *> argptrs; + args.resize(p_args.size() - 2); + argptrs.resize(args.size()); + for (uint32_t i = 0; i < args.size(); i++) { + args[i] = p_args[i + 2]; + argptrs[i] = &args[i]; + } + live_editor->_res_call_func(p_args[0], p_args[1], (const Variant **)argptrs.ptr(), argptrs.size()); } else if (p_msg == "live_create_node") { ERR_FAIL_COND_V(p_args.size() < 3, ERR_INVALID_DATA); @@ -636,7 +653,7 @@ void LiveEditor::_node_set_res_func(int p_id, const StringName &p_prop, const St _node_set_func(p_id, p_prop, r); } -void LiveEditor::_node_call_func(int p_id, const StringName &p_method, VARIANT_ARG_DECLARE) { +void LiveEditor::_node_call_func(int p_id, const StringName &p_method, const Variant **p_args, int p_argcount) { SceneTree *scene_tree = SceneTree::get_singleton(); if (!scene_tree) { return; @@ -668,7 +685,8 @@ void LiveEditor::_node_call_func(int p_id, const StringName &p_method, VARIANT_A } Node *n2 = n->get_node(np); - n2->call(p_method, VARIANT_ARG_PASS); + Callable::CallError ce; + n2->callp(p_method, p_args, p_argcount, ce); } } @@ -699,7 +717,7 @@ void LiveEditor::_res_set_res_func(int p_id, const StringName &p_prop, const Str _res_set_func(p_id, p_prop, r); } -void LiveEditor::_res_call_func(int p_id, const StringName &p_method, VARIANT_ARG_DECLARE) { +void LiveEditor::_res_call_func(int p_id, const StringName &p_method, const Variant **p_args, int p_argcount) { if (!live_edit_resource_cache.has(p_id)) { return; } @@ -715,7 +733,8 @@ void LiveEditor::_res_call_func(int p_id, const StringName &p_method, VARIANT_AR return; } - r->call(p_method, VARIANT_ARG_PASS); + Callable::CallError ce; + r->callp(p_method, p_args, p_argcount, ce); } void LiveEditor::_root_func(const NodePath &p_scene_path, const String &p_scene_from) { diff --git a/scene/debugger/scene_debugger.h b/scene/debugger/scene_debugger.h index dd0a17c2dc..29d7da7d11 100644 --- a/scene/debugger/scene_debugger.h +++ b/scene/debugger/scene_debugger.h @@ -148,10 +148,10 @@ private: void _node_set_func(int p_id, const StringName &p_prop, const Variant &p_value); void _node_set_res_func(int p_id, const StringName &p_prop, const String &p_value); - void _node_call_func(int p_id, const StringName &p_method, VARIANT_ARG_DECLARE); + void _node_call_func(int p_id, const StringName &p_method, const Variant **p_args, int p_argcount); void _res_set_func(int p_id, const StringName &p_prop, const Variant &p_value); void _res_set_res_func(int p_id, const StringName &p_prop, const String &p_value); - void _res_call_func(int p_id, const StringName &p_method, VARIANT_ARG_DECLARE); + void _res_call_func(int p_id, const StringName &p_method, const Variant **p_args, int p_argcount); void _root_func(const NodePath &p_scene_path, const String &p_scene_from); void _create_node_func(const NodePath &p_parent, const String &p_type, const String &p_name); diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 3c712a89bb..2866a5ad6c 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -190,10 +190,10 @@ String Control::properties_managed_by_container[] = { "anchor_top", "anchor_right", "anchor_bottom", - "rect_position", - "rect_rotation", - "rect_scale", - "rect_size" + "position", + "rotation", + "scale", + "size" }; void Control::accept_event() { @@ -490,7 +490,7 @@ void Control::_validate_property(PropertyInfo &property) const { } else if (Object::cast_to<Container>(parent_node)) { // If the parent is a container, display only container-related properties. if (property.name.begins_with("anchor_") || property.name.begins_with("offset_") || property.name.begins_with("grow_") || property.name == "anchors_preset" || - (property.name.begins_with("rect_") && property.name != "rect_min_size" && property.name != "rect_clip_content" && property.name != "rect_global_position")) { + property.name == "position" || property.name == "rotation" || property.name == "scale" || property.name == "size" || property.name == "pivot_offset") { property.usage ^= PROPERTY_USAGE_EDITOR; } else if (property.name == "layout_mode") { @@ -2663,6 +2663,11 @@ void Control::set_default_cursor_shape(CursorShape p_shape) { ERR_FAIL_INDEX(int(p_shape), CURSOR_MAX); data.default_cursor = p_shape; + + if (!is_inside_tree()) { + return; + } + get_viewport()->get_base_window()->update_mouse_cursor_shape(); } Control::CursorShape Control::get_default_cursor_shape() const { @@ -3342,8 +3347,8 @@ void Control::_bind_methods() { ClassDB::bind_method(D_METHOD("is_auto_translating"), &Control::is_auto_translating); ADD_GROUP("Layout", ""); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "rect_clip_content"), "set_clip_contents", "is_clipping_contents"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "rect_min_size"), "set_custom_minimum_size", "get_custom_minimum_size"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_contents"), "set_clip_contents", "is_clipping_contents"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "minimum_size"), "set_custom_minimum_size", "get_custom_minimum_size"); ADD_PROPERTY(PropertyInfo(Variant::INT, "layout_direction", PROPERTY_HINT_ENUM, "Inherited,Locale,Left-to-Right,Right-to-Left"), "set_layout_direction", "get_layout_direction"); ADD_PROPERTY(PropertyInfo(Variant::INT, "layout_mode", PROPERTY_HINT_ENUM, "Position,Anchors,Container,Uncontrolled", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_layout_mode", "_get_layout_mode"); ADD_PROPERTY_DEFAULT("layout_mode", LayoutMode::LAYOUT_MODE_POSITION); @@ -3372,15 +3377,13 @@ void Control::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "grow_horizontal", PROPERTY_HINT_ENUM, "Left,Right,Both"), "set_h_grow_direction", "get_h_grow_direction"); ADD_PROPERTY(PropertyInfo(Variant::INT, "grow_vertical", PROPERTY_HINT_ENUM, "Top,Bottom,Both"), "set_v_grow_direction", "get_v_grow_direction"); - ADD_SUBGROUP("Rectangle", "rect_"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "rect_position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "_set_position", "get_position"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "rect_global_position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "_set_global_position", "get_global_position"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "rect_size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "_set_size", "get_size"); - - ADD_SUBGROUP("Transform", "rect_"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rect_rotation", PROPERTY_HINT_RANGE, "-360,360,0.1,or_lesser,or_greater,radians"), "set_rotation", "get_rotation"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "rect_scale"), "set_scale", "get_scale"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "rect_pivot_offset"), "set_pivot_offset", "get_pivot_offset"); + ADD_SUBGROUP("Transform", ""); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "_set_size", "get_size"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "_set_position", "get_position"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "global_position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "_set_global_position", "get_global_position"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rotation", PROPERTY_HINT_RANGE, "-360,360,0.1,or_lesser,or_greater,radians"), "set_rotation", "get_rotation"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "scale"), "set_scale", "get_scale"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "pivot_offset"), "set_pivot_offset", "get_pivot_offset"); ADD_SUBGROUP("Container Sizing", "size_flags_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "size_flags_horizontal", PROPERTY_HINT_FLAGS, "Fill:1,Expand:2,Shrink Center:4,Shrink End:8"), "set_h_size_flags", "get_h_size_flags"); diff --git a/scene/gui/tab_bar.cpp b/scene/gui/tab_bar.cpp index 2f5df9b756..af314b9545 100644 --- a/scene/gui/tab_bar.cpp +++ b/scene/gui/tab_bar.cpp @@ -827,78 +827,52 @@ void TabBar::_update_cache() { int limit_minus_buttons = limit - incr->get_width() - decr->get_width(); int w = 0; - int mw = 0; - int size_fixed = 0; - int count_resize = 0; + + max_drawn_tab = tabs.size() - 1; for (int i = 0; i < tabs.size(); i++) { - tabs.write[i].size_text = Math::ceil(tabs[i].text_buf->get_size().x); tabs.write[i].text_buf->set_width(-1); - - tabs.write[i].ofs_cache = 0; + tabs.write[i].size_text = Math::ceil(tabs[i].text_buf->get_size().x); tabs.write[i].size_cache = get_tab_width(i); - if (!tabs[i].hidden) { - mw += tabs[i].size_cache; + if (max_width > 0 && tabs[i].size_cache > max_width) { + int size_textless = tabs[i].size_cache - tabs[i].size_text; + int mw = MAX(size_textless, max_width); - if (tabs[i].size_cache <= min_width || i == current) { - size_fixed += tabs[i].size_cache; - } else { - count_resize++; - } + tabs.write[i].size_text = MAX(mw - size_textless, 1); + tabs.write[i].text_buf->set_width(tabs[i].size_text); + tabs.write[i].size_cache = size_textless + tabs[i].size_text; } - } - - int m_width = min_width; - if (count_resize > 0) { - m_width = MAX((limit_minus_buttons - size_fixed) / count_resize, min_width); - } - - for (int i = offset; i < tabs.size(); i++) { - if (tabs[i].hidden) { - tabs.write[i].ofs_cache = w; - max_drawn_tab = i; + if (i < offset || i > max_drawn_tab) { + tabs.write[i].ofs_cache = 0; continue; } - int lsize = tabs[i].size_cache; - int slen = tabs[i].size_text; + tabs.write[i].ofs_cache = w; - // FIXME: This is completely broken. - if (min_width > 0 && (mw > limit || (offset > 0 && mw > limit_minus_buttons)) && i != current && lsize > m_width) { - slen = MAX(m_width - tabs[i].size_cache + tabs[i].size_text, 1); - lsize = m_width; + if (tabs[i].hidden) { + continue; } - tabs.write[i].ofs_cache = w; - tabs.write[i].size_cache = lsize; - tabs.write[i].size_text = slen; - tabs.write[i].text_buf->set_width(slen); - - w += lsize; - max_drawn_tab = i; + w += tabs[i].size_cache; // Check if all tabs would fit inside the area. if (clip_tabs && i > offset && (w > limit || (offset > 0 && w > limit_minus_buttons))) { tabs.write[i].ofs_cache = 0; - tabs.write[i].text_buf->set_width(-1); w -= tabs[i].size_cache; - max_drawn_tab--; + max_drawn_tab = i - 1; while (w > limit_minus_buttons && max_drawn_tab > offset) { tabs.write[max_drawn_tab].ofs_cache = 0; if (!tabs[max_drawn_tab].hidden) { - tabs.write[max_drawn_tab].text_buf->set_width(-1); w -= tabs[max_drawn_tab].size_cache; } max_drawn_tab--; } - - break; } } @@ -938,12 +912,11 @@ void TabBar::_on_mouse_exited() { void TabBar::add_tab(const String &p_str, const Ref<Texture2D> &p_icon) { Tab t; t.text = p_str; - t.xl_text = atr(p_str); t.text_buf->set_direction(is_layout_rtl() ? TextServer::DIRECTION_RTL : TextServer::DIRECTION_LTR); - t.text_buf->add_string(t.xl_text, get_theme_font(SNAME("font")), get_theme_font_size(SNAME("font_size")), Dictionary(), TranslationServer::get_singleton()->get_tool_locale()); t.icon = p_icon; tabs.push_back(t); + _shape(tabs.size() - 1); _update_cache(); if (scroll_to_selected) { ensure_tab_visible(current); @@ -1379,8 +1352,21 @@ TabBar::CloseButtonDisplayPolicy TabBar::get_tab_close_display_policy() const { return cb_displaypolicy; } -void TabBar::set_min_width(int p_width) { - min_width = p_width; +void TabBar::set_max_tab_width(int p_width) { + ERR_FAIL_COND(p_width < 0); + max_width = p_width; + + _update_cache(); + _ensure_no_over_offset(); + if (scroll_to_selected) { + ensure_tab_visible(current); + } + update(); + update_minimum_size(); +} + +int TabBar::get_max_tab_width() const { + return max_width; } void TabBar::set_scrolling_enabled(bool p_enabled) { @@ -1515,6 +1501,8 @@ void TabBar::_bind_methods() { ClassDB::bind_method(D_METHOD("move_tab", "from", "to"), &TabBar::move_tab); ClassDB::bind_method(D_METHOD("set_tab_close_display_policy", "policy"), &TabBar::set_tab_close_display_policy); ClassDB::bind_method(D_METHOD("get_tab_close_display_policy"), &TabBar::get_tab_close_display_policy); + ClassDB::bind_method(D_METHOD("set_max_tab_width", "width"), &TabBar::set_max_tab_width); + ClassDB::bind_method(D_METHOD("get_max_tab_width"), &TabBar::get_max_tab_width); ClassDB::bind_method(D_METHOD("set_scrolling_enabled", "enabled"), &TabBar::set_scrolling_enabled); ClassDB::bind_method(D_METHOD("get_scrolling_enabled"), &TabBar::get_scrolling_enabled); ClassDB::bind_method(D_METHOD("set_drag_to_rearrange_enabled", "enabled"), &TabBar::set_drag_to_rearrange_enabled); @@ -1539,6 +1527,7 @@ void TabBar::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "tab_alignment", PROPERTY_HINT_ENUM, "Left,Center,Right"), "set_tab_alignment", "get_tab_alignment"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_tabs"), "set_clip_tabs", "get_clip_tabs"); ADD_PROPERTY(PropertyInfo(Variant::INT, "tab_close_display_policy", PROPERTY_HINT_ENUM, "Show Never,Show Active Only,Show Always"), "set_tab_close_display_policy", "get_tab_close_display_policy"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "max_tab_width", PROPERTY_HINT_RANGE, "0,99999,1"), "set_max_tab_width", "get_max_tab_width"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scrolling_enabled"), "set_scrolling_enabled", "get_scrolling_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "drag_to_rearrange_enabled"), "set_drag_to_rearrange_enabled", "get_drag_to_rearrange_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "tabs_rearrange_group"), "set_tabs_rearrange_group", "get_tabs_rearrange_group"); diff --git a/scene/gui/tab_bar.h b/scene/gui/tab_bar.h index 82ae8bce3f..0f2184aca7 100644 --- a/scene/gui/tab_bar.h +++ b/scene/gui/tab_bar.h @@ -98,7 +98,7 @@ private: CloseButtonDisplayPolicy cb_displaypolicy = CLOSE_BUTTON_SHOW_NEVER; int hover = -1; // Hovered tab. - int min_width = 0; + int max_width = 0; bool scrolling_enabled = true; bool drag_to_rearrange_enabled = false; bool scroll_to_selected = true; @@ -198,7 +198,9 @@ public: bool get_select_with_rmb() const; void ensure_tab_visible(int p_idx); - void set_min_width(int p_width); + + void set_max_tab_width(int p_width); + int get_max_tab_width() const; Rect2 get_tab_rect(int p_tab) const; Size2 get_minimum_size() const override; diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 5afc37061b..ff8d2b88b1 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -1186,7 +1186,7 @@ void recursive_call_aux(TreeItem *p_item, const StringName &p_method, const Vari if (!p_item) { return; } - p_item->call(p_method, p_args, p_argcount, r_error); + p_item->callp(p_method, p_args, p_argcount, r_error); TreeItem *c = p_item->get_first_child(); while (c) { recursive_call_aux(c, p_method, p_args, p_argcount, r_error); diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 211667ce38..208bbe4d72 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -211,7 +211,7 @@ void Node::_propagate_enter_tree() { if (data.parent) { Variant c = this; const Variant *cptr = &c; - data.parent->emit_signal(SNAME("child_entered_tree"), &cptr, 1); + data.parent->emit_signalp(SNAME("child_entered_tree"), &cptr, 1); } data.blocked++; @@ -287,7 +287,7 @@ void Node::_propagate_exit_tree() { if (data.parent) { Variant c = this; const Variant *cptr = &c; - data.parent->emit_signal(SNAME("child_exited_tree"), &cptr, 1); + data.parent->emit_signalp(SNAME("child_exited_tree"), &cptr, 1); } // exit groups @@ -582,34 +582,6 @@ uint16_t Node::rpc_config(const StringName &p_method, Multiplayer::RPCMode p_rpc /***** RPC FUNCTIONS ********/ -void Node::rpc(const StringName &p_method, VARIANT_ARG_DECLARE) { - VARIANT_ARGPTRS; - - int argc = 0; - for (int i = 0; i < VARIANT_ARG_MAX; i++) { - if (argptr[i]->get_type() == Variant::NIL) { - break; - } - argc++; - } - - rpcp(0, p_method, argptr, argc); -} - -void Node::rpc_id(int p_peer_id, const StringName &p_method, VARIANT_ARG_DECLARE) { - VARIANT_ARGPTRS; - - int argc = 0; - for (int i = 0; i < VARIANT_ARG_MAX; i++) { - if (argptr[i]->get_type() == Variant::NIL) { - break; - } - argc++; - } - - rpcp(p_peer_id, p_method, argptr, argc); -} - Variant Node::_rpc_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { if (p_argcount < 1) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; @@ -2389,42 +2361,6 @@ void Node::_replace_connections_target(Node *p_new_target) { } } -Vector<Variant> Node::make_binds(VARIANT_ARG_DECLARE) { - Vector<Variant> ret; - - if (p_arg1.get_type() == Variant::NIL) { - return ret; - } else { - ret.push_back(p_arg1); - } - - if (p_arg2.get_type() == Variant::NIL) { - return ret; - } else { - ret.push_back(p_arg2); - } - - if (p_arg3.get_type() == Variant::NIL) { - return ret; - } else { - ret.push_back(p_arg3); - } - - if (p_arg4.get_type() == Variant::NIL) { - return ret; - } else { - ret.push_back(p_arg4); - } - - if (p_arg5.get_type() == Variant::NIL) { - return ret; - } else { - ret.push_back(p_arg5); - } - - return ret; -} - bool Node::has_node_and_resource(const NodePath &p_path) const { if (!has_node(p_path)) { return false; diff --git a/scene/main/node.h b/scene/main/node.h index 8e49f871a7..f5fbcf6587 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -420,7 +420,11 @@ public: void set_scene_instance_load_placeholder(bool p_enable); bool get_scene_instance_load_placeholder() const; - static Vector<Variant> make_binds(VARIANT_ARG_LIST); + template <typename... VarArgs> + Vector<Variant> make_binds(VarArgs... p_args) { + Vector<Variant> binds = { p_args... }; + return binds; + } void replace_by(Node *p_node, bool p_keep_data = false); @@ -472,8 +476,26 @@ public: uint16_t rpc_config(const StringName &p_method, Multiplayer::RPCMode p_rpc_mode, bool p_call_local = false, Multiplayer::TransferMode p_transfer_mode = Multiplayer::TRANSFER_MODE_RELIABLE, int p_channel = 0); // config a local method for RPC Vector<Multiplayer::RPCConfig> get_node_rpc_methods() const; - void rpc(const StringName &p_method, VARIANT_ARG_LIST); // RPC, honors RPCMode, TransferMode, channel - void rpc_id(int p_peer_id, const StringName &p_method, VARIANT_ARG_LIST); // RPC to specific peer(s), honors RPCMode, TransferMode, channel + template <typename... VarArgs> + void rpc(const StringName &p_method, 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]; + } + rpcp(0, p_method, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args)); + } + + template <typename... VarArgs> + void rpc_id(int p_peer_id, const StringName &p_method, 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]; + } + rpcp(p_peer_id, p_method, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args)); + } + void rpcp(int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount); Ref<MultiplayerAPI> get_multiplayer() const; diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index d1e8b477a6..c497718eda 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -175,13 +175,13 @@ void SceneTree::_flush_ugc() { while (unique_group_calls.size()) { Map<UGCall, Vector<Variant>>::Element *E = unique_group_calls.front(); - Variant v[VARIANT_ARG_MAX]; + const Variant **argptrs = (const Variant **)alloca(E->get().size() * sizeof(Variant *)); + for (int i = 0; i < E->get().size(); i++) { - v[i] = E->get()[i]; + argptrs[i] = &E->get()[i]; } - static_assert(VARIANT_ARG_MAX == 8, "This code needs to be updated if VARIANT_ARG_MAX != 8"); - call_group_flags(GROUP_CALL_REALTIME, E->key().group, E->key().call, v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]); + call_group_flagsp(GROUP_CALL_REALTIME, E->key().group, E->key().call, argptrs, E->get().size()); unique_group_calls.erase(E); } @@ -210,7 +210,7 @@ void SceneTree::_update_group_order(Group &g, bool p_use_priority) { g.changed = false; } -void SceneTree::call_group_flags(uint32_t p_call_flags, const StringName &p_group, const StringName &p_function, VARIANT_ARG_DECLARE) { +void SceneTree::call_group_flagsp(uint32_t p_call_flags, const StringName &p_group, const StringName &p_function, const Variant **p_args, int p_argcount) { Map<StringName, Group>::Element *E = group_map.find(p_group); if (!E) { return; @@ -231,14 +231,9 @@ void SceneTree::call_group_flags(uint32_t p_call_flags, const StringName &p_grou return; } - VARIANT_ARGPTRS; - Vector<Variant> args; - for (int i = 0; i < VARIANT_ARG_MAX; i++) { - if (argptr[i]->get_type() == Variant::NIL) { - break; - } - args.push_back(*argptr[i]); + for (int i = 0; i < p_argcount; i++) { + args.push_back(*p_args[i]); } unique_group_calls[ug] = args; @@ -260,9 +255,10 @@ void SceneTree::call_group_flags(uint32_t p_call_flags, const StringName &p_grou } if (p_call_flags & GROUP_CALL_REALTIME) { - nodes[i]->call(p_function, VARIANT_ARG_PASS); + Callable::CallError ce; + nodes[i]->callp(p_function, p_args, p_argcount, ce); } else { - MessageQueue::get_singleton()->push_call(nodes[i], p_function, VARIANT_ARG_PASS); + MessageQueue::get_singleton()->push_callp(nodes[i], p_function, p_args, p_argcount); } } @@ -273,9 +269,10 @@ void SceneTree::call_group_flags(uint32_t p_call_flags, const StringName &p_grou } if (p_call_flags & GROUP_CALL_REALTIME) { - nodes[i]->call(p_function, VARIANT_ARG_PASS); + Callable::CallError ce; + nodes[i]->callp(p_function, p_args, p_argcount, ce); } else { - MessageQueue::get_singleton()->push_call(nodes[i], p_function, VARIANT_ARG_PASS); + MessageQueue::get_singleton()->push_callp(nodes[i], p_function, p_args, p_argcount); } } } @@ -388,10 +385,6 @@ void SceneTree::set_group_flags(uint32_t p_call_flags, const StringName &p_group } } -void SceneTree::call_group(const StringName &p_group, const StringName &p_function, VARIANT_ARG_DECLARE) { - call_group_flags(0, p_group, p_function, VARIANT_ARG_PASS); -} - void SceneTree::notify_group(const StringName &p_group, int p_notification) { notify_group_flags(0, p_group, p_notification); } @@ -930,14 +923,8 @@ Variant SceneTree::_call_group_flags(const Variant **p_args, int p_argcount, Cal int flags = *p_args[0]; StringName group = *p_args[1]; StringName method = *p_args[2]; - Variant v[VARIANT_ARG_MAX]; - - for (int i = 0; i < MIN(p_argcount - 3, 5); i++) { - v[i] = *p_args[i + 3]; - } - static_assert(VARIANT_ARG_MAX == 8, "This code needs to be updated if VARIANT_ARG_MAX != 8"); - call_group_flags(flags, group, method, v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]); + call_group_flagsp(flags, group, method, p_args + 3, p_argcount - 3); return Variant(); } @@ -950,14 +937,8 @@ Variant SceneTree::_call_group(const Variant **p_args, int p_argcount, Callable: StringName group = *p_args[0]; StringName method = *p_args[1]; - Variant v[VARIANT_ARG_MAX]; - - for (int i = 0; i < MIN(p_argcount - 2, 5); i++) { - v[i] = *p_args[i + 2]; - } - static_assert(VARIANT_ARG_MAX == 8, "This code needs to be updated if VARIANT_ARG_MAX != 8"); - call_group_flags(0, group, method, v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]); + call_group_flagsp(0, group, method, p_args + 2, p_argcount - 2); return Variant(); } @@ -1087,6 +1068,7 @@ void SceneTree::_change_scene(Node *p_to) { if (p_to) { current_scene = p_to; root->add_child(p_to); + root->update_mouse_cursor_shape(); } } diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h index 5f7c1729e8..6197e52fc1 100644 --- a/scene/main/scene_tree.h +++ b/scene/main/scene_tree.h @@ -229,14 +229,33 @@ public: _FORCE_INLINE_ Window *get_root() const { return root; } - void call_group_flags(uint32_t p_call_flags, const StringName &p_group, const StringName &p_function, VARIANT_ARG_LIST); + void call_group_flagsp(uint32_t p_call_flags, const StringName &p_group, const StringName &p_function, const Variant **p_args, int p_argcount); 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); - void call_group(const StringName &p_group, const StringName &p_function, VARIANT_ARG_LIST); void notify_group(const StringName &p_group, int p_notification); void set_group(const StringName &p_group, const String &p_name, const Variant &p_value); + template <typename... VarArgs> + 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)); + } + + template <typename... VarArgs> + void call_group_flags(uint32_t p_flags, 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(p_flags, p_group, p_function, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args)); + } + void flush_transform_notifications(); virtual void initialize() override; diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index de6aa2b139..0082e7b061 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -1551,7 +1551,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { gui.drag_preview_id = ObjectID(); } _propagate_viewport_notification(this, NOTIFICATION_DRAG_END); - // Change mouse accordingly. + get_base_window()->update_mouse_cursor_shape(); } _gui_cancel_tooltip(); @@ -1572,7 +1572,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { gui.dragging = false; gui.drag_mouse_over = nullptr; _propagate_viewport_notification(this, NOTIFICATION_DRAG_END); - // Change mouse accordingly. + get_base_window()->update_mouse_cursor_shape(); } gui.mouse_focus_mask &= ~mouse_button_to_mask(mb->get_button_index()); // Remove from mask. diff --git a/scene/main/window.cpp b/scene/main/window.cpp index 6837fcae21..a1124274d8 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -378,6 +378,18 @@ void Window::_event_callback(DisplayServer::WindowEvent p_event) { } } +void Window::update_mouse_cursor_shape() { + // The default shape is set in Viewport::_gui_input_event. To instantly + // see the shape in the viewport we need to trigger a mouse motion event. + Ref<InputEventMouseMotion> mm; + Vector2 pos = get_mouse_position(); + Transform2D xform = get_global_canvas_transform().affine_inverse(); + mm.instantiate(); + mm->set_position(pos); + mm->set_global_position(xform.xform(pos)); + push_input(mm); +} + void Window::show() { set_visible(true); } diff --git a/scene/main/window.h b/scene/main/window.h index 3d8e337b4a..27a02b837f 100644 --- a/scene/main/window.h +++ b/scene/main/window.h @@ -205,6 +205,8 @@ public: void set_visible(bool p_visible); bool is_visible() const; + void update_mouse_cursor_shape(); + void show(); void hide(); diff --git a/scene/multiplayer/scene_rpc_interface.cpp b/scene/multiplayer/scene_rpc_interface.cpp index 2239a5d81c..84700a82f3 100644 --- a/scene/multiplayer/scene_rpc_interface.cpp +++ b/scene/multiplayer/scene_rpc_interface.cpp @@ -278,7 +278,7 @@ void SceneRPCInterface::_process_rpc(Node *p_node, const uint16_t p_rpc_method_i Callable::CallError ce; - p_node->call(config.name, (const Variant **)argp.ptr(), argc, ce); + p_node->callp(config.name, (const Variant **)argp.ptr(), argc, ce); if (ce.error != Callable::CallError::CALL_OK) { String error = Variant::get_call_error_text(p_node, config.name, (const Variant **)argp.ptr(), argc, ce); error = "RPC - " + error; @@ -480,7 +480,7 @@ void SceneRPCInterface::rpcp(Object *p_obj, int p_peer_id, const StringName &p_m Callable::CallError ce; multiplayer->set_remote_sender_override(peer->get_unique_id()); - node->call(p_method, p_arg, p_argcount, ce); + node->callp(p_method, p_arg, p_argcount, ce); multiplayer->set_remote_sender_override(0); if (ce.error != Callable::CallError::CALL_OK) { @@ -496,7 +496,7 @@ void SceneRPCInterface::rpcp(Object *p_obj, int p_peer_id, const StringName &p_m ce.error = Callable::CallError::CALL_OK; multiplayer->set_remote_sender_override(peer->get_unique_id()); - node->get_script_instance()->call(p_method, p_arg, p_argcount, ce); + node->get_script_instance()->callp(p_method, p_arg, p_argcount, ce); multiplayer->set_remote_sender_override(0); if (ce.error != Callable::CallError::CALL_OK) { |