summaryrefslogtreecommitdiff
path: root/scene/main
diff options
context:
space:
mode:
Diffstat (limited to 'scene/main')
-rw-r--r--scene/main/http_request.cpp56
-rw-r--r--scene/main/node.cpp14
-rw-r--r--scene/main/scene_tree.cpp2
-rw-r--r--scene/main/viewport.cpp81
-rw-r--r--scene/main/viewport.h8
5 files changed, 90 insertions, 71 deletions
diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp
index 65d210983e..4e91548d14 100644
--- a/scene/main/http_request.cpp
+++ b/scene/main/http_request.cpp
@@ -46,7 +46,7 @@ Error HTTPRequest::_parse_url(const String &p_url) {
request_sent = false;
got_response = false;
body_len = -1;
- body.resize(0);
+ body.clear();
downloaded.set(0);
redirections = 0;
@@ -86,9 +86,9 @@ String HTTPRequest::get_header_value(const PackedStringArray &p_headers, const S
String lowwer_case_header_name = p_header_name.to_lower();
for (int i = 0; i < p_headers.size(); i++) {
- if (p_headers[i].find(":", 0) >= 0) {
+ if (p_headers[i].find(":") > 0) {
Vector<String> parts = p_headers[i].split(":", false, 1);
- if (parts[0].strip_edges().to_lower() == lowwer_case_header_name) {
+ if (parts.size() > 1 && parts[0].strip_edges().to_lower() == lowwer_case_header_name) {
value = parts[1].strip_edges();
break;
}
@@ -99,7 +99,7 @@ String HTTPRequest::get_header_value(const PackedStringArray &p_headers, const S
}
Error HTTPRequest::request(const String &p_url, const Vector<String> &p_custom_headers, bool p_ssl_validate_domain, HTTPClient::Method p_method, const String &p_request_data) {
- // Copy the string into a raw buffer
+ // Copy the string into a raw buffer.
Vector<uint8_t> raw_data;
CharString charstr = p_request_data.utf8();
@@ -134,7 +134,7 @@ Error HTTPRequest::request_raw(const String &p_url, const Vector<String> &p_cust
headers = p_custom_headers;
if (accept_gzip) {
- // If the user has specified a different Accept-Encoding, don't overwrite it
+ // If the user has specified an Accept-Encoding header, don't overwrite it.
if (!has_header(headers, "Accept-Encoding")) {
headers.push_back("Accept-Encoding: gzip, deflate");
}
@@ -202,7 +202,7 @@ void HTTPRequest::cancel_request() {
file = nullptr;
}
client->close();
- body.resize(0);
+ body.clear();
got_response = false;
response_code = -1;
request_sent = false;
@@ -220,14 +220,14 @@ bool HTTPRequest::_handle_response(bool *ret_value) {
response_code = client->get_response_code();
List<String> rheaders;
client->get_response_headers(&rheaders);
- response_headers.resize(0);
+ response_headers.clear();
downloaded.set(0);
for (const String &E : rheaders) {
response_headers.push_back(E);
}
if (response_code == 301 || response_code == 302) {
- // Handle redirect
+ // Handle redirect.
if (max_redirects >= 0 && redirections >= max_redirects) {
call_deferred(SNAME("_request_done"), RESULT_REDIRECT_LIMIT_REACHED, response_code, response_headers, PackedByteArray());
@@ -244,12 +244,12 @@ bool HTTPRequest::_handle_response(bool *ret_value) {
}
if (!new_request.is_empty()) {
- // Process redirect
+ // Process redirect.
client->close();
- int new_redirs = redirections + 1; // Because _request() will clear it
+ int new_redirs = redirections + 1; // Because _request() will clear it.
Error err;
if (new_request.begins_with("http")) {
- // New url, request all again
+ // New url, new request.
_parse_url(new_request);
} else {
request_string = new_request;
@@ -260,7 +260,7 @@ bool HTTPRequest::_handle_response(bool *ret_value) {
request_sent = false;
got_response = false;
body_len = -1;
- body.resize(0);
+ body.clear();
downloaded.set(0);
redirections = new_redirs;
*ret_value = false;
@@ -276,11 +276,11 @@ bool HTTPRequest::_update_connection() {
switch (client->get_status()) {
case HTTPClient::STATUS_DISCONNECTED: {
call_deferred(SNAME("_request_done"), RESULT_CANT_CONNECT, 0, PackedStringArray(), PackedByteArray());
- return true; // End it, since it's doing something
+ return true; // End it, since it's disconnected.
} break;
case HTTPClient::STATUS_RESOLVING: {
client->poll();
- // Must wait
+ // Must wait.
return false;
} break;
case HTTPClient::STATUS_CANT_RESOLVE: {
@@ -290,9 +290,9 @@ bool HTTPRequest::_update_connection() {
} break;
case HTTPClient::STATUS_CONNECTING: {
client->poll();
- // Must wait
+ // Must wait.
return false;
- } break; // Connecting to IP
+ } break; // Connecting to IP.
case HTTPClient::STATUS_CANT_CONNECT: {
call_deferred(SNAME("_request_done"), RESULT_CANT_CONNECT, 0, PackedStringArray(), PackedByteArray());
return true;
@@ -301,7 +301,7 @@ bool HTTPRequest::_update_connection() {
case HTTPClient::STATUS_CONNECTED: {
if (request_sent) {
if (!got_response) {
- // No body
+ // No body.
bool ret_value;
@@ -313,16 +313,16 @@ bool HTTPRequest::_update_connection() {
return true;
}
if (body_len < 0) {
- // Chunked transfer is done
+ // Chunked transfer is done.
call_deferred(SNAME("_request_done"), RESULT_SUCCESS, response_code, response_headers, body);
return true;
}
call_deferred(SNAME("_request_done"), RESULT_CHUNKED_BODY_SIZE_MISMATCH, response_code, response_headers, PackedByteArray());
return true;
- // Request might have been done
+ // Request might have been done.
} else {
- // Did not request yet, do request
+ // Did not request yet, do request.
int size = request_data.size();
Error err = client->request(method, request_string, headers, size > 0 ? request_data.ptr() : nullptr, size);
@@ -334,13 +334,13 @@ bool HTTPRequest::_update_connection() {
request_sent = true;
return false;
}
- } break; // Connected: break requests only accepted here
+ } break; // Connected: break requests only accepted here.
case HTTPClient::STATUS_REQUESTING: {
- // Must wait, still requesting
+ // Must wait, still requesting.
client->poll();
return false;
- } break; // Request in progress
+ } break; // Request in progress.
case HTTPClient::STATUS_BODY: {
if (!got_response) {
bool ret_value;
@@ -411,7 +411,7 @@ bool HTTPRequest::_update_connection() {
return false;
- } break; // Request resulted in body: break which must be read
+ } break; // Request resulted in body: break which must be read.
case HTTPClient::STATUS_CONNECTION_ERROR: {
call_deferred(SNAME("_request_done"), RESULT_CONNECTION_ERROR, 0, PackedStringArray(), PackedByteArray());
return true;
@@ -428,7 +428,7 @@ bool HTTPRequest::_update_connection() {
void HTTPRequest::_request_done(int p_status, int p_code, const PackedStringArray &p_headers, const PackedByteArray &p_data) {
cancel_request();
- // Determine if the request body is compressed
+ // Determine if the request body is compressed.
bool is_compressed;
String content_encoding = get_header_value(p_headers, "Content-Encoding").to_lower();
Compression::Mode mode;
@@ -452,11 +452,11 @@ void HTTPRequest::_request_done(int p_status, int p_code, const PackedStringArra
} else if (result == -5) {
WARN_PRINT("Decompressed size of HTTP response body exceeded body_size_limit");
p_status = RESULT_BODY_SIZE_LIMIT_EXCEEDED;
- // Just return the raw data if we failed to decompress it
+ // Just return the raw data if we failed to decompress it.
} else {
WARN_PRINT("Failed to decompress HTTP response body");
p_status = RESULT_BODY_DECOMPRESS_FAILED;
- // Just return the raw data if we failed to decompress it
+ // Just return the raw data if we failed to decompress it.
}
}
@@ -471,7 +471,6 @@ void HTTPRequest::_notification(int p_what) {
bool done = _update_connection();
if (done) {
set_process_internal(false);
- // cancel_request(); called from _request done now
}
}
@@ -619,7 +618,6 @@ void HTTPRequest::_bind_methods() {
ADD_SIGNAL(MethodInfo("request_completed", PropertyInfo(Variant::INT, "result"), PropertyInfo(Variant::INT, "response_code"), PropertyInfo(Variant::PACKED_STRING_ARRAY, "headers"), PropertyInfo(Variant::PACKED_BYTE_ARRAY, "body")));
BIND_ENUM_CONSTANT(RESULT_SUCCESS);
- //BIND_ENUM_CONSTANT( RESULT_NO_BODY );
BIND_ENUM_CONSTANT(RESULT_CHUNKED_BODY_SIZE_MISMATCH);
BIND_ENUM_CONSTANT(RESULT_CANT_CONNECT);
BIND_ENUM_CONSTANT(RESULT_CANT_RESOLVE);
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index a2415442f8..2665a5695b 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -211,6 +211,12 @@ void Node::_propagate_enter_tree() {
data.tree->node_added(this);
+ if (data.parent) {
+ Variant c = this;
+ const Variant *cptr = &c;
+ data.parent->emit_signal(SNAME("child_entered_tree"), &cptr, 1);
+ }
+
data.blocked++;
//block while adding children
@@ -281,6 +287,12 @@ void Node::_propagate_exit_tree() {
data.tree->node_removed(this);
}
+ if (data.parent) {
+ Variant c = this;
+ const Variant *cptr = &c;
+ data.parent->emit_signal(SNAME("child_exited_tree"), &cptr, 1);
+ }
+
// exit groups
for (KeyValue<StringName, GroupData> &E : data.grouped) {
@@ -2865,6 +2877,8 @@ void Node::_bind_methods() {
ADD_SIGNAL(MethodInfo("tree_entered"));
ADD_SIGNAL(MethodInfo("tree_exiting"));
ADD_SIGNAL(MethodInfo("tree_exited"));
+ ADD_SIGNAL(MethodInfo("child_entered_tree", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT, "Node")));
+ ADD_SIGNAL(MethodInfo("child_exited_tree", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT, "Node")));
ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_name", "get_name");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "scene_file_path", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_scene_file_path", "get_scene_file_path");
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index 0c92dcae11..45f04b28b9 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -130,7 +130,7 @@ SceneTree::Group *SceneTree::add_to_group(const StringName &p_group, Node *p_nod
E = group_map.insert(p_group, Group());
}
- ERR_FAIL_COND_V_MSG(E->get().nodes.find(p_node) != -1, &E->get(), "Already in group: " + p_group + ".");
+ ERR_FAIL_COND_V_MSG(E->get().nodes.has(p_node), &E->get(), "Already in group: " + p_group + ".");
E->get().nodes.push_back(p_node);
//E->get().last_tree_version=0;
E->get().changed = true;
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 1244e0c028..09880ad6cf 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -492,20 +492,26 @@ void Viewport::_notification(int p_what) {
}
#endif // _3D_DISABLED
} break;
+ case NOTIFICATION_WM_MOUSE_ENTER: {
+ gui.mouse_in_window = true;
+ } break;
case NOTIFICATION_WM_MOUSE_EXIT: {
+ gui.mouse_in_window = false;
_drop_physics_mouseover();
-
- // Unlike on loss of focus (NOTIFICATION_WM_WINDOW_FOCUS_OUT), do not
- // drop the gui mouseover here, as a scrollbar may be dragged while the
- // mouse is outside the window (without the window having lost focus).
- // See bug #39634
+ _drop_mouse_over();
+ // When the mouse exits the window, we want to end mouse_over, but
+ // not mouse_focus, because, for example, we want to continue
+ // dragging a scrollbar even if the mouse has left the window.
} break;
case NOTIFICATION_WM_WINDOW_FOCUS_OUT: {
_drop_physics_mouseover();
-
if (gui.mouse_focus && !gui.forced_mouse_focus) {
_drop_mouse_focus();
}
+ // When the window focus changes, we want to end mouse_focus, but
+ // not the mouse_over. Note: The OS will trigger a separate mouse
+ // exit event if the change in focus results in the mouse exiting
+ // the window.
} break;
}
}
@@ -1447,8 +1453,6 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
if (mb.is_valid()) {
gui.key_event_accepted = false;
- Control *over = nullptr;
-
Point2 mpos = mb->get_position();
gui.last_mouse_pos = mpos;
if (mb->is_pressed()) {
@@ -1594,6 +1598,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
// it is different, rather than wait for it to be updated the next time the
// mouse is moved, notify the control so that it can e.g. drop the highlight.
// This code is duplicated from the mm.is_valid()-case further below.
+ Control *over = nullptr;
if (gui.mouse_focus) {
over = gui.mouse_focus;
} else {
@@ -1601,10 +1606,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
}
if (gui.mouse_focus_mask == MouseButton::NONE && over != gui.mouse_over) {
- if (gui.mouse_over) {
- _gui_call_notification(gui.mouse_over, Control::NOTIFICATION_MOUSE_EXIT);
- }
-
+ _drop_mouse_over();
_gui_cancel_tooltip();
if (over) {
@@ -1625,8 +1627,6 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
gui.last_mouse_pos = mpos;
- Control *over = nullptr;
-
// Drag & drop.
if (!gui.drag_attempted && gui.mouse_focus && (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) {
gui.drag_accum += mm->get_relative();
@@ -1674,29 +1674,23 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
}
}
- // These sections of code are reused in the mb.is_valid() case further up
- // for the purpose of notifying controls about potential changes in focus
- // when the mousebutton is released.
+ Control *over = nullptr;
if (gui.mouse_focus) {
over = gui.mouse_focus;
- } else {
+ } else if (gui.mouse_in_window) {
over = gui_find_control(mpos);
}
if (over != gui.mouse_over) {
- if (gui.mouse_over) {
- _gui_call_notification(gui.mouse_over, Control::NOTIFICATION_MOUSE_EXIT);
- }
-
+ _drop_mouse_over();
_gui_cancel_tooltip();
if (over) {
_gui_call_notification(over, Control::NOTIFICATION_MOUSE_ENTER);
+ gui.mouse_over = over;
}
}
- gui.mouse_over = over;
-
DisplayServer::CursorShape ds_cursor_shape = (DisplayServer::CursorShape)Input::get_singleton()->get_default_cursor_shape();
if (over) {
@@ -2098,7 +2092,7 @@ void Viewport::_gui_hide_control(Control *p_control) {
}
if (gui.key_focus == p_control) {
- _gui_remove_focus();
+ gui_release_focus();
}
if (gui.mouse_over == p_control) {
gui.mouse_over = nullptr;
@@ -2148,15 +2142,7 @@ Window *Viewport::get_base_window() const {
}
void Viewport::_gui_remove_focus_for_window(Node *p_window) {
if (get_base_window() == p_window) {
- _gui_remove_focus();
- }
-}
-
-void Viewport::_gui_remove_focus() {
- if (gui.key_focus) {
- Node *f = gui.key_focus;
- gui.key_focus = nullptr;
- f->notification(Control::NOTIFICATION_FOCUS_EXIT, true);
+ gui_release_focus();
}
}
@@ -2183,6 +2169,13 @@ void Viewport::_gui_accept_event() {
}
}
+void Viewport::_drop_mouse_over() {
+ if (gui.mouse_over) {
+ _gui_call_notification(gui.mouse_over, Control::NOTIFICATION_MOUSE_EXIT);
+ gui.mouse_over = nullptr;
+ }
+}
+
void Viewport::_drop_mouse_focus() {
Control *c = gui.mouse_focus;
MouseButton mask = gui.mouse_focus_mask;
@@ -2278,10 +2271,6 @@ void Viewport::_cleanup_mouseover_colliders(bool p_clean_all_frames, bool p_paus
}
}
-Control *Viewport::_gui_get_focus_owner() {
- return gui.key_focus;
-}
-
void Viewport::_gui_grab_click_focus(Control *p_control) {
gui.mouse_click_grabber = p_control;
call_deferred(SNAME("_post_gui_grab_click_focus"));
@@ -2797,6 +2786,19 @@ int Viewport::gui_get_canvas_sort_index() {
return gui.canvas_sort_index++;
}
+void Viewport::gui_release_focus() {
+ if (gui.key_focus) {
+ Control *f = gui.key_focus;
+ gui.key_focus = nullptr;
+ f->notification(Control::NOTIFICATION_FOCUS_EXIT, true);
+ f->update();
+ }
+}
+
+Control *Viewport::gui_get_focus_owner() {
+ return gui.key_focus;
+}
+
void Viewport::set_msaa(MSAA p_msaa) {
ERR_FAIL_INDEX(p_msaa, MSAA_MAX);
if (msaa == p_msaa) {
@@ -3590,6 +3592,9 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("gui_is_dragging"), &Viewport::gui_is_dragging);
ClassDB::bind_method(D_METHOD("gui_is_drag_successful"), &Viewport::gui_is_drag_successful);
+ ClassDB::bind_method(D_METHOD("gui_release_focus"), &Viewport::gui_release_focus);
+ ClassDB::bind_method(D_METHOD("gui_get_focus_owner"), &Viewport::gui_get_focus_owner);
+
ClassDB::bind_method(D_METHOD("set_disable_input", "disable"), &Viewport::set_disable_input);
ClassDB::bind_method(D_METHOD("is_input_disabled"), &Viewport::is_input_disabled);
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index a3127811f5..3a71745f44 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -335,6 +335,7 @@ private:
// info used when this is a window
bool forced_mouse_focus = false; //used for menu buttons
+ bool mouse_in_window = true;
bool key_event_accepted = false;
Control *mouse_focus = nullptr;
Control *last_mouse_focus = nullptr;
@@ -410,7 +411,6 @@ private:
Control *_gui_get_drag_preview();
void _gui_remove_focus_for_window(Node *p_window);
- void _gui_remove_focus();
void _gui_unfocus_control(Control *p_control);
bool _gui_control_has_focus(const Control *p_control);
void _gui_control_grab_focus(Control *p_control);
@@ -418,8 +418,6 @@ private:
void _post_gui_grab_click_focus();
void _gui_accept_event();
- Control *_gui_get_focus_owner();
-
bool _gui_drop(Control *p_at_control, Point2 p_at_pos, bool p_just_check);
friend class AudioListener2D;
@@ -433,6 +431,7 @@ private:
void _canvas_layer_add(CanvasLayer *p_canvas_layer);
void _canvas_layer_remove(CanvasLayer *p_canvas_layer);
+ void _drop_mouse_over();
void _drop_mouse_focus();
void _drop_physics_mouseover(bool p_paused_only = false);
@@ -557,6 +556,9 @@ public:
void gui_reset_canvas_sort_index();
int gui_get_canvas_sort_index();
+ void gui_release_focus();
+ Control *gui_get_focus_owner();
+
TypedArray<String> get_configuration_warnings() const override;
void set_debug_draw(DebugDraw p_debug_draw);