diff options
Diffstat (limited to 'scene/main')
-rw-r--r-- | scene/main/canvas_item.cpp | 37 | ||||
-rw-r--r-- | scene/main/canvas_item.h | 7 | ||||
-rw-r--r-- | scene/main/http_request.cpp | 21 | ||||
-rw-r--r-- | scene/main/http_request.h | 8 | ||||
-rw-r--r-- | scene/main/multiplayer_api.cpp | 18 | ||||
-rw-r--r-- | scene/main/multiplayer_api.h | 8 | ||||
-rw-r--r-- | scene/main/multiplayer_peer.cpp | 2 | ||||
-rw-r--r-- | scene/main/node.cpp | 26 | ||||
-rw-r--r-- | scene/main/node.h | 1 | ||||
-rw-r--r-- | scene/main/viewport.cpp | 161 | ||||
-rw-r--r-- | scene/main/viewport.h | 18 | ||||
-rw-r--r-- | scene/main/window.cpp | 105 | ||||
-rw-r--r-- | scene/main/window.h | 6 |
13 files changed, 269 insertions, 149 deletions
diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp index 7b0554442c..0ea8f6c5f1 100644 --- a/scene/main/canvas_item.cpp +++ b/scene/main/canvas_item.cpp @@ -154,17 +154,7 @@ Transform2D CanvasItem::get_global_transform_with_canvas() const { Transform2D CanvasItem::get_screen_transform() const { ERR_FAIL_COND_V(!is_inside_tree(), Transform2D()); - Transform2D xform = get_global_transform_with_canvas(); - - Window *w = Object::cast_to<Window>(get_viewport()); - if (w && !w->is_embedding_subwindows()) { - Transform2D s; - s.set_origin(w->get_position()); - - xform = s * xform; - } - - return xform; + return get_viewport()->get_popup_base_transform() * get_global_transform_with_canvas(); } Transform2D CanvasItem::get_global_transform() const { @@ -195,7 +185,7 @@ void CanvasItem::_top_level_raise_self() { } void CanvasItem::_enter_canvas() { - // Resolves to nullptr if the node is toplevel. + // Resolves to nullptr if the node is top_level. CanvasItem *parent_item = get_parent_item(); if (parent_item) { @@ -410,11 +400,28 @@ void CanvasItem::set_as_top_level(bool p_top_level) { _exit_canvas(); top_level = p_top_level; + _top_level_changed(); _enter_canvas(); _notify_transform(); } +void CanvasItem::_top_level_changed() { + // Inform children that top_level status has changed on a parent. + int children = get_child_count(); + for (int i = 0; i < children; i++) { + CanvasItem *child = Object::cast_to<CanvasItem>(get_child(i)); + if (child) { + child->_top_level_changed_on_parent(); + } + } +} + +void CanvasItem::_top_level_changed_on_parent() { + // Inform children that top_level status has changed on a parent. + _top_level_changed(); +} + bool CanvasItem::is_set_as_top_level() const { return top_level; } @@ -927,6 +934,12 @@ void CanvasItem::force_update_transform() { notification(NOTIFICATION_TRANSFORM_CHANGED); } +void CanvasItem::_validate_property(PropertyInfo &p_property) const { + if (hide_clip_children && p_property.name == "clip_children") { + p_property.usage = PROPERTY_USAGE_NONE; + } +} + void CanvasItem::_bind_methods() { ClassDB::bind_method(D_METHOD("_top_level_raise_self"), &CanvasItem::_top_level_raise_self); diff --git a/scene/main/canvas_item.h b/scene/main/canvas_item.h index 644fe856ec..2fa1d56667 100644 --- a/scene/main/canvas_item.h +++ b/scene/main/canvas_item.h @@ -106,6 +106,7 @@ private: bool use_parent_material = false; bool notify_local_transform = false; bool notify_transform = false; + bool hide_clip_children = false; ClipChildrenMode clip_children_mode = CLIP_CHILDREN_DISABLED; @@ -124,6 +125,9 @@ private: void _propagate_visibility_changed(bool p_parent_visible_in_tree); void _handle_visibility_change(bool p_visible); + virtual void _top_level_changed(); + virtual void _top_level_changed_on_parent(); + void _redraw_callback(); void _enter_canvas(); @@ -155,6 +159,9 @@ protected: void _notification(int p_what); static void _bind_methods(); + void _validate_property(PropertyInfo &p_property) const; + + _FORCE_INLINE_ void set_hide_clip_children(bool p_value) { hide_clip_children = p_value; } GDVIRTUAL0(_draw) public: diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp index 46ba7e67eb..0d53f740db 100644 --- a/scene/main/http_request.cpp +++ b/scene/main/http_request.cpp @@ -33,7 +33,7 @@ #include "scene/main/timer.h" Error HTTPRequest::_request() { - return client->connect_to_host(url, port, use_tls, validate_tls); + return client->connect_to_host(url, port, use_tls ? tls_options : nullptr); } Error HTTPRequest::_parse_url(const String &p_url) { @@ -96,7 +96,7 @@ String HTTPRequest::get_header_value(const PackedStringArray &p_headers, const S return value; } -Error HTTPRequest::request(const String &p_url, const Vector<String> &p_custom_headers, bool p_tls_validate_domain, HTTPClient::Method p_method, const String &p_request_data) { +Error HTTPRequest::request(const String &p_url, const Vector<String> &p_custom_headers, HTTPClient::Method p_method, const String &p_request_data) { // Copy the string into a raw buffer. Vector<uint8_t> raw_data; @@ -108,10 +108,10 @@ Error HTTPRequest::request(const String &p_url, const Vector<String> &p_custom_h memcpy(w, charstr.ptr(), len); } - return request_raw(p_url, p_custom_headers, p_tls_validate_domain, p_method, raw_data); + return request_raw(p_url, p_custom_headers, p_method, raw_data); } -Error HTTPRequest::request_raw(const String &p_url, const Vector<String> &p_custom_headers, bool p_tls_validate_domain, HTTPClient::Method p_method, const Vector<uint8_t> &p_request_data_raw) { +Error HTTPRequest::request_raw(const String &p_url, const Vector<String> &p_custom_headers, HTTPClient::Method p_method, const Vector<uint8_t> &p_request_data_raw) { ERR_FAIL_COND_V(!is_inside_tree(), ERR_UNCONFIGURED); ERR_FAIL_COND_V_MSG(requesting, ERR_BUSY, "HTTPRequest is processing a request. Wait for completion or cancel it before attempting a new one."); @@ -127,8 +127,6 @@ Error HTTPRequest::request_raw(const String &p_url, const Vector<String> &p_cust return err; } - validate_tls = p_tls_validate_domain; - headers = p_custom_headers; if (accept_gzip) { @@ -590,10 +588,16 @@ void HTTPRequest::_timeout() { _defer_done(RESULT_TIMEOUT, 0, PackedStringArray(), PackedByteArray()); } +void HTTPRequest::set_tls_options(const Ref<TLSOptions> &p_options) { + ERR_FAIL_COND(p_options.is_null() || p_options->is_server()); + tls_options = p_options; +} + void HTTPRequest::_bind_methods() { - ClassDB::bind_method(D_METHOD("request", "url", "custom_headers", "tls_validate_domain", "method", "request_data"), &HTTPRequest::request, DEFVAL(PackedStringArray()), DEFVAL(true), DEFVAL(HTTPClient::METHOD_GET), DEFVAL(String())); - ClassDB::bind_method(D_METHOD("request_raw", "url", "custom_headers", "tls_validate_domain", "method", "request_data_raw"), &HTTPRequest::request_raw, DEFVAL(PackedStringArray()), DEFVAL(true), DEFVAL(HTTPClient::METHOD_GET), DEFVAL(PackedByteArray())); + ClassDB::bind_method(D_METHOD("request", "url", "custom_headers", "method", "request_data"), &HTTPRequest::request, DEFVAL(PackedStringArray()), DEFVAL(HTTPClient::METHOD_GET), DEFVAL(String())); + ClassDB::bind_method(D_METHOD("request_raw", "url", "custom_headers", "method", "request_data_raw"), &HTTPRequest::request_raw, DEFVAL(PackedStringArray()), DEFVAL(HTTPClient::METHOD_GET), DEFVAL(PackedByteArray())); ClassDB::bind_method(D_METHOD("cancel_request"), &HTTPRequest::cancel_request); + ClassDB::bind_method(D_METHOD("set_tls_options", "client_options"), &HTTPRequest::set_tls_options); ClassDB::bind_method(D_METHOD("get_http_client_status"), &HTTPRequest::get_http_client_status); @@ -654,6 +658,7 @@ void HTTPRequest::_bind_methods() { HTTPRequest::HTTPRequest() { client = Ref<HTTPClient>(HTTPClient::create()); + tls_options = TLSOptions::client(); timer = memnew(Timer); timer->set_one_shot(true); timer->connect("timeout", callable_mp(this, &HTTPRequest::_timeout)); diff --git a/scene/main/http_request.h b/scene/main/http_request.h index add4e9538d..9a91171eaf 100644 --- a/scene/main/http_request.h +++ b/scene/main/http_request.h @@ -68,8 +68,8 @@ private: String url; int port = 80; Vector<String> headers; - bool validate_tls = false; bool use_tls = false; + Ref<TLSOptions> tls_options; HTTPClient::Method method; Vector<uint8_t> request_data; @@ -125,8 +125,8 @@ protected: static void _bind_methods(); public: - Error request(const String &p_url, const Vector<String> &p_custom_headers = Vector<String>(), bool p_tls_validate_domain = true, HTTPClient::Method p_method = HTTPClient::METHOD_GET, const String &p_request_data = ""); //connects to a full url and perform request - Error request_raw(const String &p_url, const Vector<String> &p_custom_headers = Vector<String>(), bool p_tls_validate_domain = true, HTTPClient::Method p_method = HTTPClient::METHOD_GET, const Vector<uint8_t> &p_request_data_raw = Vector<uint8_t>()); //connects to a full url and perform request + Error request(const String &p_url, const Vector<String> &p_custom_headers = Vector<String>(), HTTPClient::Method p_method = HTTPClient::METHOD_GET, const String &p_request_data = ""); //connects to a full url and perform request + Error request_raw(const String &p_url, const Vector<String> &p_custom_headers = Vector<String>(), HTTPClient::Method p_method = HTTPClient::METHOD_GET, const Vector<uint8_t> &p_request_data_raw = Vector<uint8_t>()); //connects to a full url and perform request void cancel_request(); HTTPClient::Status get_http_client_status() const; @@ -161,6 +161,8 @@ public: void set_http_proxy(const String &p_host, int p_port); void set_https_proxy(const String &p_host, int p_port); + void set_tls_options(const Ref<TLSOptions> &p_options); + HTTPRequest(); }; diff --git a/scene/main/multiplayer_api.cpp b/scene/main/multiplayer_api.cpp index e36cbc4414..950eb2809c 100644 --- a/scene/main/multiplayer_api.cpp +++ b/scene/main/multiplayer_api.cpp @@ -135,7 +135,7 @@ Error MultiplayerAPI::encode_and_compress_variant(const Variant &p_variant, uint return err; } if (r_buffer) { - // The first byte is not used by the marshalling, so store the type + // The first byte is not used by the marshaling, so store the type // so we know how to decompress and decode this variant. r_buffer[0] = p_variant.get_type(); } @@ -329,9 +329,9 @@ void MultiplayerAPI::_bind_methods() { /// MultiplayerAPIExtension Error MultiplayerAPIExtension::poll() { - int err = OK; + Error err = OK; GDVIRTUAL_CALL(_poll, err); - return (Error)err; + return err; } void MultiplayerAPIExtension::set_multiplayer_peer(const Ref<MultiplayerPeer> &p_peer) { @@ -364,9 +364,9 @@ Error MultiplayerAPIExtension::rpcp(Object *p_obj, int p_peer_id, const StringNa for (int i = 0; i < p_argcount; i++) { args.push_back(*p_arg[i]); } - int ret = FAILED; + Error ret = FAILED; GDVIRTUAL_CALL(_rpc, p_peer_id, p_obj, p_method, args, ret); - return (Error)ret; + return ret; } int MultiplayerAPIExtension::get_remote_sender_id() { @@ -376,15 +376,15 @@ int MultiplayerAPIExtension::get_remote_sender_id() { } Error MultiplayerAPIExtension::object_configuration_add(Object *p_object, Variant p_config) { - int err = ERR_UNAVAILABLE; + Error err = ERR_UNAVAILABLE; GDVIRTUAL_CALL(_object_configuration_add, p_object, p_config, err); - return (Error)err; + return err; } Error MultiplayerAPIExtension::object_configuration_remove(Object *p_object, Variant p_config) { - int err = ERR_UNAVAILABLE; + Error err = ERR_UNAVAILABLE; GDVIRTUAL_CALL(_object_configuration_remove, p_object, p_config, err); - return (Error)err; + return err; } void MultiplayerAPIExtension::_bind_methods() { diff --git a/scene/main/multiplayer_api.h b/scene/main/multiplayer_api.h index 0b107ee50b..a578e6f2f1 100644 --- a/scene/main/multiplayer_api.h +++ b/scene/main/multiplayer_api.h @@ -101,15 +101,15 @@ public: virtual Error object_configuration_remove(Object *p_object, Variant p_config) override; // Extensions - GDVIRTUAL0R(int, _poll); + GDVIRTUAL0R(Error, _poll); GDVIRTUAL1(_set_multiplayer_peer, Ref<MultiplayerPeer>); GDVIRTUAL0R(Ref<MultiplayerPeer>, _get_multiplayer_peer); GDVIRTUAL0RC(int, _get_unique_id); GDVIRTUAL0RC(PackedInt32Array, _get_peer_ids); - GDVIRTUAL4R(int, _rpc, int, Object *, StringName, Array); + GDVIRTUAL4R(Error, _rpc, int, Object *, StringName, Array); GDVIRTUAL0RC(int, _get_remote_sender_id); - GDVIRTUAL2R(int, _object_configuration_add, Object *, Variant); - GDVIRTUAL2R(int, _object_configuration_remove, Object *, Variant); + GDVIRTUAL2R(Error, _object_configuration_add, Object *, Variant); + GDVIRTUAL2R(Error, _object_configuration_remove, Object *, Variant); }; #endif // MULTIPLAYER_API_H diff --git a/scene/main/multiplayer_peer.cpp b/scene/main/multiplayer_peer.cpp index 83555966d7..f3e56a1455 100644 --- a/scene/main/multiplayer_peer.cpp +++ b/scene/main/multiplayer_peer.cpp @@ -163,7 +163,7 @@ Error MultiplayerPeerExtension::put_packet(const uint8_t *p_buffer, int p_buffer if (!GDVIRTUAL_CALL(_put_packet_script, a, err)) { return FAILED; } - return (Error)err; + return err; } WARN_PRINT_ONCE("MultiplayerPeerExtension::_put_packet_native is unimplemented!"); return FAILED; diff --git a/scene/main/node.cpp b/scene/main/node.cpp index def91c424c..52c1df8110 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -946,7 +946,7 @@ String Node::validate_child_name(Node *p_child) { #endif String Node::adjust_name_casing(const String &p_name) { - switch (GLOBAL_GET("editor/node_naming/name_casing").operator int()) { + switch (GLOBAL_GET("editor/naming/node_name_casing").operator int()) { case NAME_CASING_PASCAL_CASE: return p_name.to_pascal_case(); case NAME_CASING_CAMEL_CASE: @@ -1987,7 +1987,16 @@ String Node::get_scene_file_path() const { } void Node::set_editor_description(const String &p_editor_description) { + if (data.editor_description == p_editor_description) { + return; + } + data.editor_description = p_editor_description; + + if (Engine::get_singleton()->is_editor_hint() && is_inside_tree()) { + // Update tree so the tooltip in the Scene tree dock is also updated in the editor. + get_tree()->tree_changed(); + } } String Node::get_editor_description() const { @@ -2126,13 +2135,13 @@ Node *Node::_duplicate(int p_flags, HashMap<const Node *, Node *> *r_duplimap) c } else if ((p_flags & DUPLICATE_USE_INSTANTIATION) && !get_scene_file_path().is_empty()) { Ref<PackedScene> res = ResourceLoader::load(get_scene_file_path()); ERR_FAIL_COND_V(res.is_null(), nullptr); - PackedScene::GenEditState ges = PackedScene::GEN_EDIT_STATE_DISABLED; + PackedScene::GenEditState edit_state = PackedScene::GEN_EDIT_STATE_DISABLED; #ifdef TOOLS_ENABLED if (p_flags & DUPLICATE_FROM_EDITOR) { - ges = PackedScene::GEN_EDIT_STATE_INSTANCE; + edit_state = PackedScene::GEN_EDIT_STATE_INSTANCE; } #endif - node = res->instantiate(ges); + node = res->instantiate(edit_state); ERR_FAIL_COND_V(!node, nullptr); node->set_scene_instance_load_placeholder(get_scene_instance_load_placeholder()); @@ -2213,7 +2222,7 @@ Node *Node::_duplicate(int p_flags, HashMap<const Node *, Node *> *r_duplimap) c Variant value = N->get()->get(name).duplicate(true); - if (E.usage & PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE) { + if (E.usage & PROPERTY_USAGE_ALWAYS_DUPLICATE) { Resource *res = Object::cast_to<Resource>(value); if (res) { // Duplicate only if it's a resource current_node->set(name, res->duplicate()); @@ -2799,8 +2808,8 @@ void Node::unhandled_key_input(const Ref<InputEvent> &p_key_event) { } void Node::_bind_methods() { - GLOBAL_DEF(PropertyInfo(Variant::INT, "editor/node_naming/name_num_separator", PROPERTY_HINT_ENUM, "None,Space,Underscore,Dash"), 0); - GLOBAL_DEF(PropertyInfo(Variant::INT, "editor/node_naming/name_casing", PROPERTY_HINT_ENUM, "PascalCase,camelCase,snake_case"), NAME_CASING_PASCAL_CASE); + GLOBAL_DEF(PropertyInfo(Variant::INT, "editor/naming/node_name_num_separator", PROPERTY_HINT_ENUM, "None,Space,Underscore,Dash"), 0); + GLOBAL_DEF(PropertyInfo(Variant::INT, "editor/naming/node_name_casing", PROPERTY_HINT_ENUM, "PascalCase,camelCase,snake_case"), NAME_CASING_PASCAL_CASE); ClassDB::bind_static_method("Node", D_METHOD("print_orphan_nodes"), &Node::print_orphan_nodes); ClassDB::bind_method(D_METHOD("add_sibling", "sibling", "force_readable_name"), &Node::add_sibling, DEFVAL(false)); @@ -2947,6 +2956,7 @@ void Node::_bind_methods() { BIND_CONSTANT(NOTIFICATION_POST_ENTER_TREE); BIND_CONSTANT(NOTIFICATION_DISABLED); BIND_CONSTANT(NOTIFICATION_ENABLED); + BIND_CONSTANT(NOTIFICATION_NODE_RECACHE_REQUESTED); BIND_CONSTANT(NOTIFICATION_EDITOR_PRE_SAVE); BIND_CONSTANT(NOTIFICATION_EDITOR_POST_SAVE); @@ -3021,7 +3031,7 @@ void Node::_bind_methods() { } String Node::_get_name_num_separator() { - switch (GLOBAL_GET("editor/node_naming/name_num_separator").operator int()) { + switch (GLOBAL_GET("editor/naming/node_name_num_separator").operator int()) { case 0: return ""; case 1: diff --git a/scene/main/node.h b/scene/main/node.h index dbdcca6170..493578bc5b 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -270,6 +270,7 @@ public: NOTIFICATION_POST_ENTER_TREE = 27, NOTIFICATION_DISABLED = 28, NOTIFICATION_ENABLED = 29, + NOTIFICATION_NODE_RECACHE_REQUESTED = 30, //keep these linked to node NOTIFICATION_WM_MOUSE_ENTER = 1002, diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 07bcf45899..28521c5bbe 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -524,7 +524,12 @@ void Viewport::_process_picking() { if (!physics_object_picking) { return; } - if (to_screen_rect != Rect2i() && Input::get_singleton()->get_mouse_mode() == Input::MOUSE_MODE_CAPTURED) { + if (Object::cast_to<Window>(this) && Input::get_singleton()->get_mouse_mode() == Input::MOUSE_MODE_CAPTURED) { + return; + } + if (!gui.mouse_in_viewport) { + // Clear picking events if mouse has left viewport. + physics_picking_events.clear(); return; } @@ -704,25 +709,15 @@ void Viewport::_process_picking() { } #ifndef _3D_DISABLED - bool captured = false; - + CollisionObject3D *capture_object = nullptr; if (physics_object_capture.is_valid()) { - CollisionObject3D *co = Object::cast_to<CollisionObject3D>(ObjectDB::get_instance(physics_object_capture)); - if (co && camera_3d) { - _collision_object_3d_input_event(co, camera_3d, ev, Vector3(), Vector3(), 0); - captured = true; - if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT && !mb->is_pressed()) { - physics_object_capture = ObjectID(); - } - - } else { + capture_object = Object::cast_to<CollisionObject3D>(ObjectDB::get_instance(physics_object_capture)); + if (!capture_object || !camera_3d || (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT && !mb->is_pressed())) { physics_object_capture = ObjectID(); } } - if (captured) { - // None. - } else if (pos == last_pos) { + if (pos == last_pos) { if (last_id.is_valid()) { if (ObjectDB::get_instance(last_id) && last_object) { // Good, exists. @@ -748,13 +743,12 @@ void Viewport::_process_picking() { bool col = space->intersect_ray(ray_params, result); ObjectID new_collider; - if (col) { - CollisionObject3D *co = Object::cast_to<CollisionObject3D>(result.collider); - if (co && co->can_process()) { - _collision_object_3d_input_event(co, camera_3d, ev, result.position, result.normal, result.shape); + CollisionObject3D *co = col ? Object::cast_to<CollisionObject3D>(result.collider) : nullptr; + if (co && co->can_process()) { + new_collider = result.collider_id; + if (!capture_object) { last_object = co; last_id = result.collider_id; - new_collider = last_id; if (co->get_capture_input_on_drag() && mb.is_valid() && mb->get_button_index() == MouseButton::LEFT && mb->is_pressed()) { physics_object_capture = last_id; } @@ -763,21 +757,24 @@ void Viewport::_process_picking() { if (is_mouse && new_collider != physics_object_over) { if (physics_object_over.is_valid()) { - CollisionObject3D *co = Object::cast_to<CollisionObject3D>(ObjectDB::get_instance(physics_object_over)); - if (co) { - co->_mouse_exit(); + CollisionObject3D *previous_co = Object::cast_to<CollisionObject3D>(ObjectDB::get_instance(physics_object_over)); + if (previous_co) { + previous_co->_mouse_exit(); } } if (new_collider.is_valid()) { - CollisionObject3D *co = Object::cast_to<CollisionObject3D>(ObjectDB::get_instance(new_collider)); - if (co) { - co->_mouse_enter(); - } + DEV_ASSERT(co); + co->_mouse_enter(); } physics_object_over = new_collider; } + if (capture_object) { + _collision_object_3d_input_event(capture_object, camera_3d, ev, result.position, result.normal, result.shape); + } else if (new_collider.is_valid()) { + _collision_object_3d_input_event(co, camera_3d, ev, result.position, result.normal, result.shape); + } } last_pos = pos; @@ -799,16 +796,21 @@ void Viewport::update_canvas_items() { _update_canvas_items(this); } -void Viewport::_set_size(const Size2i &p_size, const Size2i &p_size_2d_override, const Rect2i &p_to_screen_rect, const Transform2D &p_stretch_transform, bool p_allocated) { - if (size == p_size && size_allocated == p_allocated && stretch_transform == p_stretch_transform && p_size_2d_override == size_2d_override && to_screen_rect == p_to_screen_rect) { +void Viewport::_set_size(const Size2i &p_size, const Size2i &p_size_2d_override, bool p_allocated) { + Transform2D stretch_transform_new = Transform2D(); + if (is_size_2d_override_stretch_enabled() && p_size_2d_override.width > 0 && p_size_2d_override.height > 0) { + Size2 scale = Size2(p_size) / Size2(p_size_2d_override); + stretch_transform_new.scale(scale); + } + + if (size == p_size && size_allocated == p_allocated && stretch_transform == stretch_transform_new && p_size_2d_override == size_2d_override) { return; } size = p_size; size_allocated = p_allocated; size_2d_override = p_size_2d_override; - stretch_transform = p_stretch_transform; - to_screen_rect = p_to_screen_rect; + stretch_transform = stretch_transform_new; #ifndef _3D_DISABLED if (!use_xr) { @@ -1053,6 +1055,29 @@ Transform2D Viewport::get_final_transform() const { return stretch_transform * global_canvas_transform; } +void Viewport::assign_next_enabled_camera_2d(const StringName &p_camera_group) { + List<Node *> camera_list; + get_tree()->get_nodes_in_group(p_camera_group, &camera_list); + + Camera2D *new_camera = nullptr; + for (Node *E : camera_list) { + Camera2D *cam = Object::cast_to<Camera2D>(E); + if (!cam) { + continue; // Non-camera node (e.g. ParallaxBackground). + } + + if (cam->is_enabled()) { + new_camera = cam; + break; + } + } + + _camera_2d_set(new_camera); + if (!camera_2d) { + set_canvas_transform(Transform2D()); + } +} + void Viewport::_update_canvas_items(Node *p_node) { if (p_node != this) { Window *w = Object::cast_to<Window>(p_node); @@ -1117,23 +1142,12 @@ Viewport::PositionalShadowAtlasQuadrantSubdiv Viewport::get_positional_shadow_at return positional_shadow_atlas_quadrant_subdiv[p_quadrant]; } -Transform2D Viewport::_get_input_pre_xform() const { - Transform2D pre_xf; - - if (to_screen_rect.size.x != 0 && to_screen_rect.size.y != 0) { - pre_xf.columns[2] = -to_screen_rect.position; - pre_xf.scale(Vector2(size) / to_screen_rect.size); - } - - return pre_xf; -} - Ref<InputEvent> Viewport::_make_input_local(const Ref<InputEvent> &ev) { if (ev.is_null()) { return ev; // No transformation defined for null event } - Transform2D ai = get_final_transform().affine_inverse() * _get_input_pre_xform(); + Transform2D ai = get_final_transform().affine_inverse(); return ev->xformed_by(ai); } @@ -1795,9 +1809,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { if (w->is_embedded()) { embedder = w->_get_embedder(); - Transform2D ai = (get_final_transform().affine_inverse() * _get_input_pre_xform()).affine_inverse(); - - viewport_pos = ai.xform(mpos) + w->get_position(); // To parent coords. + viewport_pos = get_final_transform().xform(mpos) + w->get_position(); // To parent coords. } } } @@ -1847,7 +1859,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { if (viewport_under) { if (viewport_under != this) { - Transform2D ai = (viewport_under->get_final_transform().affine_inverse() * viewport_under->_get_input_pre_xform()); + Transform2D ai = viewport_under->get_final_transform().affine_inverse(); viewport_pos = ai.xform(viewport_pos); } // Find control under at position. @@ -2853,7 +2865,7 @@ bool Viewport::get_physics_object_picking() { } Vector2 Viewport::get_camera_coords(const Vector2 &p_viewport_coords) const { - Transform2D xf = get_final_transform(); + Transform2D xf = stretch_transform * global_canvas_transform; return xf.xform(p_viewport_coords); } @@ -3245,7 +3257,7 @@ Viewport::SDFScale Viewport::get_sdf_scale() const { } Transform2D Viewport::get_screen_transform() const { - return _get_input_pre_xform().affine_inverse() * get_final_transform(); + return get_final_transform(); } void Viewport::set_canvas_cull_mask(uint32_t p_canvas_cull_mask) { @@ -4108,9 +4120,26 @@ Viewport::~Viewport() { ///////////////////////////////// void SubViewport::set_size(const Size2i &p_size) { - _set_size(p_size, _get_size_2d_override(), Rect2i(), _stretch_transform(), true); + _internal_set_size(p_size); +} + +void SubViewport::set_size_force(const Size2i &p_size) { + // Use only for setting the size from the parent SubViewportContainer with enabled stretch mode. + // Don't expose function to scripting. + _internal_set_size(p_size, true); +} +void SubViewport::_internal_set_size(const Size2i &p_size, bool p_force) { SubViewportContainer *c = Object::cast_to<SubViewportContainer>(get_parent()); + if (!p_force && c && c->is_stretch_enabled()) { +#ifdef DEBUG_ENABLED + WARN_PRINT("Can't change the size of a `SubViewport` with a `SubViewportContainer` parent that has `stretch` enabled. Set `SubViewportContainer.stretch` to `false` to allow changing the size manually."); +#endif // DEBUG_ENABLED + return; + } + + _set_size(p_size, _get_size_2d_override(), true); + if (c) { c->update_minimum_size(); } @@ -4121,7 +4150,7 @@ Size2i SubViewport::get_size() const { } void SubViewport::set_size_2d_override(const Size2i &p_size) { - _set_size(_get_size(), p_size, Rect2i(), _stretch_transform(), true); + _set_size(_get_size(), p_size, true); } Size2i SubViewport::get_size_2d_override() const { @@ -4134,7 +4163,7 @@ void SubViewport::set_size_2d_override_stretch(bool p_enable) { } size_2d_override_stretch = p_enable; - _set_size(_get_size(), _get_size_2d_override(), Rect2i(), _stretch_transform(), true); + _set_size(_get_size(), _get_size_2d_override(), true); } bool SubViewport::is_size_2d_override_stretch_enabled() const { @@ -4163,17 +4192,6 @@ DisplayServer::WindowID SubViewport::get_window_id() const { return DisplayServer::INVALID_WINDOW_ID; } -Transform2D SubViewport::_stretch_transform() { - Transform2D transform; - Size2i view_size_2d_override = _get_size_2d_override(); - if (size_2d_override_stretch && view_size_2d_override.width > 0 && view_size_2d_override.height > 0) { - Size2 scale = Size2(_get_size()) / Size2(view_size_2d_override); - transform.scale(scale); - } - - return transform; -} - Transform2D SubViewport::get_screen_transform() const { Transform2D container_transform; SubViewportContainer *c = Object::cast_to<SubViewportContainer>(get_parent()); @@ -4185,7 +4203,22 @@ Transform2D SubViewport::get_screen_transform() const { } else { WARN_PRINT_ONCE("SubViewport is not a child of a SubViewportContainer. get_screen_transform doesn't return the actual screen position."); } - return container_transform * Viewport::get_screen_transform(); + return container_transform * get_final_transform(); +} + +Transform2D SubViewport::get_popup_base_transform() const { + if (is_embedding_subwindows()) { + return Transform2D(); + } + SubViewportContainer *c = Object::cast_to<SubViewportContainer>(get_parent()); + if (!c) { + return get_final_transform(); + } + Transform2D container_transform; + if (c->is_stretch_enabled()) { + container_transform.scale(Vector2(c->get_stretch_shrink(), c->get_stretch_shrink())); + } + return c->get_screen_transform() * container_transform * get_final_transform(); } void SubViewport::_notification(int p_what) { diff --git a/scene/main/viewport.h b/scene/main/viewport.h index 603e92b071..2142aaaaef 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -275,7 +275,6 @@ private: Ref<World2D> world_2d; - Rect2i to_screen_rect; StringName input_group; StringName gui_input_group; StringName shortcut_input_group; @@ -408,8 +407,6 @@ private: void _perform_drop(Control *p_control = nullptr, Point2 p_pos = Point2()); void _gui_cleanup_internal_state(Ref<InputEvent> p_event); - _FORCE_INLINE_ Transform2D _get_input_pre_xform() const; - Ref<InputEvent> _make_input_local(const Ref<InputEvent> &ev); friend class Control; @@ -471,7 +468,7 @@ private: uint64_t event_count = 0; protected: - void _set_size(const Size2i &p_size, const Size2i &p_size_2d_override, const Rect2i &p_to_screen_rect, const Transform2D &p_stretch_transform, bool p_allocated); + void _set_size(const Size2i &p_size, const Size2i &p_size_2d_override, bool p_allocated); Size2i _get_size() const; Size2i _get_size_2d_override() const; @@ -510,7 +507,8 @@ public: void set_global_canvas_transform(const Transform2D &p_transform); Transform2D get_global_canvas_transform() const; - Transform2D get_final_transform() const; + virtual Transform2D get_final_transform() const; + void assign_next_enabled_camera_2d(const StringName &p_camera_group); void gui_set_root_order_dirty(); @@ -648,7 +646,10 @@ public: void set_canvas_cull_mask_bit(uint32_t p_layer, bool p_enable); bool get_canvas_cull_mask_bit(uint32_t p_layer) const; + virtual bool is_size_2d_override_stretch_enabled() const { return true; } + virtual Transform2D get_screen_transform() const; + virtual Transform2D get_popup_base_transform() const { return Transform2D(); } #ifndef _3D_DISABLED bool use_xr = false; @@ -752,21 +753,23 @@ private: ClearMode clear_mode = CLEAR_MODE_ALWAYS; bool size_2d_override_stretch = false; + void _internal_set_size(const Size2i &p_size, bool p_force = false); + protected: static void _bind_methods(); virtual DisplayServer::WindowID get_window_id() const override; - Transform2D _stretch_transform(); void _notification(int p_what); public: void set_size(const Size2i &p_size); Size2i get_size() const; + void set_size_force(const Size2i &p_size); void set_size_2d_override(const Size2i &p_size); Size2i get_size_2d_override() const; void set_size_2d_override_stretch(bool p_enable); - bool is_size_2d_override_stretch_enabled() const; + bool is_size_2d_override_stretch_enabled() const override; void set_update_mode(UpdateMode p_mode); UpdateMode get_update_mode() const; @@ -775,6 +778,7 @@ public: ClearMode get_clear_mode() const; virtual Transform2D get_screen_transform() const override; + virtual Transform2D get_popup_base_transform() const override; SubViewport(); ~SubViewport(); diff --git a/scene/main/window.cpp b/scene/main/window.cpp index 2c6599d849..33946246b0 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -663,18 +663,18 @@ void Window::set_visible(bool p_visible) { return; } - visible = p_visible; - if (!is_inside_tree()) { + visible = p_visible; return; } - if (updating_child_controls) { - _update_child_controls(); - } - ERR_FAIL_COND_MSG(get_parent() == nullptr, "Can't change visibility of main window."); + visible = p_visible; + + // Stop any queued resizing, as the window will be resized right now. + updating_child_controls = false; + Viewport *embedder_vp = _get_embedder(); if (!embedder_vp) { @@ -833,7 +833,7 @@ bool Window::is_visible() const { } void Window::_update_window_size() { - // Force window to respect size limitations of rendering server + // Force window to respect size limitations of rendering server. RenderingServer *rendering_server = RenderingServer::get_singleton(); if (rendering_server) { Size2i max_window_size = rendering_server->get_maximum_viewport_size(); @@ -905,16 +905,13 @@ void Window::_update_viewport_size() { Size2i final_size; Size2i final_size_override; Rect2i attach_to_screen_rect(Point2i(), size); - Transform2D stretch_transform_new; float font_oversampling = 1.0; + window_transform = Transform2D(); if (content_scale_mode == CONTENT_SCALE_MODE_DISABLED || content_scale_size.x == 0 || content_scale_size.y == 0) { font_oversampling = content_scale_factor; final_size = size; final_size_override = Size2(size) / content_scale_factor; - - stretch_transform_new = Transform2D(); - stretch_transform_new.scale(Size2(content_scale_factor, content_scale_factor)); } else { //actual screen video mode Size2 video_mode = size; @@ -990,20 +987,24 @@ void Window::_update_viewport_size() { attach_to_screen_rect = Rect2(margin, screen_size); font_oversampling = (screen_size.x / viewport_size.x) * content_scale_factor; - Size2 scale = Vector2(screen_size) / Vector2(final_size_override); - stretch_transform_new.scale(scale); - + window_transform.translate_local(margin); } break; case CONTENT_SCALE_MODE_VIEWPORT: { final_size = (viewport_size / content_scale_factor).floor(); attach_to_screen_rect = Rect2(margin, screen_size); + window_transform.translate_local(margin); + if (final_size.x != 0 && final_size.y != 0) { + Transform2D scale_transform; + scale_transform.scale(Vector2(attach_to_screen_rect.size) / Vector2(final_size)); + window_transform *= scale_transform; + } } break; } } bool allocate = is_inside_tree() && visible && (window_id != DisplayServer::INVALID_WINDOW_ID || embedder != nullptr); - _set_size(final_size, final_size_override, attach_to_screen_rect, stretch_transform_new, allocate); + _set_size(final_size, final_size_override, allocate); if (window_id != DisplayServer::INVALID_WINDOW_ID) { RenderingServer::get_singleton()->viewport_attach_to_screen(get_viewport_rid(), attach_to_screen_rect, window_id); @@ -1130,6 +1131,7 @@ void Window::_notification(int p_what) { case NOTIFICATION_READY: { if (wrap_controls) { + // Finish any resizing immediately so it doesn't interfere on stuff overriding _ready(). _update_child_controls(); } } break; @@ -1138,9 +1140,7 @@ void Window::_notification(int p_what) { _invalidate_theme_cache(); _update_theme_item_cache(); - if (embedder) { - embedder->_sub_window_update(this); - } else if (window_id != DisplayServer::INVALID_WINDOW_ID) { + if (!embedder && window_id != DisplayServer::INVALID_WINDOW_ID) { String tr_title = atr(title); #ifdef DEBUG_ENABLED if (window_id == DisplayServer::MAIN_WINDOW_ID) { @@ -1152,8 +1152,6 @@ void Window::_notification(int p_what) { #endif DisplayServer::get_singleton()->window_set_title(tr_title, window_id); } - - child_controls_changed(); } break; case NOTIFICATION_EXIT_TREE: { @@ -1254,8 +1252,13 @@ Vector<Vector2> Window::get_mouse_passthrough_polygon() const { void Window::set_wrap_controls(bool p_enable) { wrap_controls = p_enable; - if (wrap_controls) { - child_controls_changed(); + + if (!is_inside_tree()) { + return; + } + + if (updating_child_controls) { + _update_child_controls(); } else { _update_window_size(); } @@ -1282,23 +1285,23 @@ Size2 Window::_get_contents_minimum_size() const { return max; } -void Window::_update_child_controls() { - if (!updating_child_controls) { +void Window::child_controls_changed() { + if (!is_inside_tree() || !visible || updating_child_controls) { return; } - _update_window_size(); - - updating_child_controls = false; + updating_child_controls = true; + call_deferred(SNAME("_update_child_controls")); } -void Window::child_controls_changed() { - if (!is_inside_tree() || !visible || updating_child_controls) { +void Window::_update_child_controls() { + if (!updating_child_controls) { return; } - updating_child_controls = true; - call_deferred(SNAME("_update_child_controls")); + _update_window_size(); + + updating_child_controls = false; } bool Window::_can_consume_input_events() const { @@ -1647,7 +1650,24 @@ void Window::_invalidate_theme_cache() { void Window::_update_theme_item_cache() { // Request an update on the next frame to reflect theme changes. // Updating without a delay can cause a lot of lag. - child_controls_changed(); + if (!wrap_controls) { + updating_embedded_window = true; + call_deferred(SNAME("_update_embedded_window")); + } else { + child_controls_changed(); + } +} + +void Window::_update_embedded_window() { + if (!updating_embedded_window) { + return; + } + + if (embedder) { + embedder->_sub_window_update(this); + }; + + updating_embedded_window = false; } void Window::set_theme_type_variation(const StringName &p_theme_type) { @@ -2095,13 +2115,30 @@ bool Window::is_auto_translating() const { return auto_translate; } +Transform2D Window::get_final_transform() const { + return window_transform * stretch_transform * global_canvas_transform; +} + Transform2D Window::get_screen_transform() const { Transform2D embedder_transform; if (_get_embedder()) { embedder_transform.translate_local(get_position()); embedder_transform = _get_embedder()->get_screen_transform() * embedder_transform; } - return embedder_transform * Viewport::get_screen_transform(); + return embedder_transform * get_final_transform(); +} + +Transform2D Window::get_popup_base_transform() const { + if (is_embedding_subwindows()) { + return Transform2D(); + } + Transform2D popup_base_transform; + popup_base_transform.set_origin(get_position()); + popup_base_transform *= get_final_transform(); + if (_get_embedder()) { + return _get_embedder()->get_popup_base_transform() * popup_base_transform; + } + return popup_base_transform; } void Window::_bind_methods() { @@ -2188,6 +2225,7 @@ void Window::_bind_methods() { ClassDB::bind_method(D_METHOD("child_controls_changed"), &Window::child_controls_changed); ClassDB::bind_method(D_METHOD("_update_child_controls"), &Window::_update_child_controls); + ClassDB::bind_method(D_METHOD("_update_embedded_window"), &Window::_update_embedded_window); ClassDB::bind_method(D_METHOD("set_theme", "theme"), &Window::set_theme); ClassDB::bind_method(D_METHOD("get_theme"), &Window::get_theme); @@ -2303,6 +2341,7 @@ void Window::_bind_methods() { ADD_SIGNAL(MethodInfo("visibility_changed")); ADD_SIGNAL(MethodInfo("about_to_popup")); ADD_SIGNAL(MethodInfo("theme_changed")); + ADD_SIGNAL(MethodInfo("dpi_changed")); ADD_SIGNAL(MethodInfo("titlebar_changed")); BIND_CONSTANT(NOTIFICATION_VISIBILITY_CHANGED); diff --git a/scene/main/window.h b/scene/main/window.h index e9c217f973..9861fefc68 100644 --- a/scene/main/window.h +++ b/scene/main/window.h @@ -116,6 +116,7 @@ private: bool exclusive = false; bool wrap_controls = false; bool updating_child_controls = false; + bool updating_embedded_window = false; bool clamp_to_embedder = false; LayoutDirection layout_dir = LAYOUT_DIRECTION_INHERITED; @@ -123,6 +124,7 @@ private: bool auto_translate = true; void _update_child_controls(); + void _update_embedded_window(); Size2i content_scale_size; ContentScaleMode content_scale_mode = CONTENT_SCALE_MODE_DISABLED; @@ -171,6 +173,8 @@ private: Viewport *embedder = nullptr; + Transform2D window_transform; + friend class Viewport; //friend back, can call the methods below void _window_input(const Ref<InputEvent> &p_ev); @@ -372,7 +376,9 @@ public: // + virtual Transform2D get_final_transform() const override; virtual Transform2D get_screen_transform() const override; + virtual Transform2D get_popup_base_transform() const override; Rect2i get_parent_rect() const; virtual DisplayServer::WindowID get_window_id() const override; |