summaryrefslogtreecommitdiff
path: root/scene/main
diff options
context:
space:
mode:
Diffstat (limited to 'scene/main')
-rw-r--r--scene/main/http_request.cpp20
-rw-r--r--scene/main/node.cpp34
-rw-r--r--scene/main/node.h9
-rw-r--r--scene/main/scene_tree.cpp47
-rw-r--r--scene/main/scene_tree.h6
-rw-r--r--scene/main/viewport.cpp116
-rw-r--r--scene/main/viewport.h3
7 files changed, 175 insertions, 60 deletions
diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp
index ae21775c55..4750e05633 100644
--- a/scene/main/http_request.cpp
+++ b/scene/main/http_request.cpp
@@ -30,8 +30,6 @@
#include "http_request.h"
-#include "version.h"
-
void HTTPRequest::_redirect_request(const String &p_new_url) {
}
@@ -106,28 +104,10 @@ Error HTTPRequest::request(const String &p_url, const Vector<String> &p_custom_h
validate_ssl = p_ssl_validate_domain;
- bool has_user_agent = false;
- bool has_accept = false;
headers = p_custom_headers;
request_data = p_request_data;
- for (int i = 0; i < headers.size(); i++) {
-
- if (headers[i].findn("user-agent:") == 0)
- has_user_agent = true;
- if (headers[i].findn("Accept:") == 0)
- has_accept = true;
- }
-
- if (!has_user_agent) {
- headers.push_back("User-Agent: GodotEngine/" + String(VERSION_FULL_BUILD) + " (" + OS::get_singleton()->get_name() + ")");
- }
-
- if (!has_accept) {
- headers.push_back("Accept: */*");
- }
-
requesting = true;
if (use_threads) {
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index ffb8acc687..b7b26d1c55 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -240,7 +240,7 @@ void Node::_propagate_enter_tree() {
void Node::_propagate_exit_tree() {
-//block while removing children
+ //block while removing children
#ifdef DEBUG_ENABLED
@@ -809,6 +809,22 @@ bool Node::is_processing_internal() const {
return data.idle_process_internal;
}
+void Node::set_process_priority(int p_priority) {
+ data.process_priority = p_priority;
+
+ if (is_processing())
+ data.tree->make_group_changed("idle_process");
+
+ if (is_processing_internal())
+ data.tree->make_group_changed("idle_process_internal");
+
+ if (is_physics_processing())
+ data.tree->make_group_changed("physics_process");
+
+ if (is_physics_processing_internal())
+ data.tree->make_group_changed("physics_process_internal");
+}
+
void Node::set_process_input(bool p_enable) {
if (p_enable == data.input)
@@ -1095,6 +1111,10 @@ void Node::add_child(Node *p_child, bool p_legible_unique_name) {
}
void Node::add_child_below_node(Node *p_node, Node *p_child, bool p_legible_unique_name) {
+
+ ERR_FAIL_NULL(p_node);
+ ERR_FAIL_NULL(p_child);
+
add_child(p_child, p_legible_unique_name);
if (is_a_parent_of(p_node)) {
@@ -1384,6 +1404,11 @@ bool Node::is_greater_than(const Node *p_node) const {
return res;
}
+bool Node::has_priority_higher_than(const Node *p_node) const {
+ ERR_FAIL_NULL_V(p_node, false);
+ return data.process_priority > p_node->data.process_priority;
+}
+
void Node::get_owned_by(Node *p_by, List<Node *> *p_owned) {
if (data.owner == p_by)
@@ -1891,7 +1916,7 @@ Node *Node::_duplicate(int p_flags, Map<const Node *, Node *> *r_duplimap) const
// Skip nodes not really belonging to the instanced hierarchy; they'll be processed normally later
// but remember non-instanced nodes that are hidden below instanced ones
if (descendant->data.owner != this) {
- if (descendant->get_parent() && descendant->get_parent() != this && descendant->get_parent()->data.owner == this)
+ if (descendant->get_parent() && descendant->get_parent() != this && descendant->get_parent()->data.owner == this && descendant->data.owner != descendant->get_parent())
hidden_roots.push_back(descendant);
continue;
}
@@ -1930,8 +1955,9 @@ Node *Node::_duplicate(int p_flags, Map<const Node *, Node *> *r_duplimap) const
if (E->get().usage & PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE) {
Resource *res = Object::cast_to<Resource>(value);
- if (res) // Duplicate only if it's a resource
+ if (res) { // Duplicate only if it's a resource
current_node->set(name, res->duplicate());
+ }
} else {
@@ -2603,6 +2629,7 @@ void Node::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_physics_processing"), &Node::is_physics_processing);
ClassDB::bind_method(D_METHOD("get_process_delta_time"), &Node::get_process_delta_time);
ClassDB::bind_method(D_METHOD("set_process", "enable"), &Node::set_process);
+ ClassDB::bind_method(D_METHOD("set_process_priority", "priority"), &Node::set_process_priority);
ClassDB::bind_method(D_METHOD("is_processing"), &Node::is_processing);
ClassDB::bind_method(D_METHOD("set_process_input", "enable"), &Node::set_process_input);
ClassDB::bind_method(D_METHOD("is_processing_input"), &Node::is_processing_input);
@@ -2754,6 +2781,7 @@ Node::Node() {
data.tree = NULL;
data.physics_process = false;
data.idle_process = false;
+ data.process_priority = 0;
data.physics_process_internal = false;
data.idle_process_internal = false;
data.inside_tree = false;
diff --git a/scene/main/node.h b/scene/main/node.h
index 341349de79..4b8f584ba7 100644
--- a/scene/main/node.h
+++ b/scene/main/node.h
@@ -70,6 +70,11 @@ public:
bool operator()(const Node *p_a, const Node *p_b) const { return p_b->is_greater_than(p_a); }
};
+ struct ComparatorWithPriority {
+
+ bool operator()(const Node *p_a, const Node *p_b) const { return p_b->has_priority_higher_than(p_a) || p_b->is_greater_than(p_a); }
+ };
+
private:
struct GroupData {
@@ -118,6 +123,7 @@ private:
//should move all the stuff below to bits
bool physics_process;
bool idle_process;
+ int process_priority;
bool physics_process_internal;
bool idle_process_internal;
@@ -259,6 +265,7 @@ public:
bool is_a_parent_of(const Node *p_node) const;
bool is_greater_than(const Node *p_node) const;
+ bool has_priority_higher_than(const Node *p_node) const;
NodePath get_path() const;
NodePath get_path_to(const Node *p_node) const;
@@ -319,6 +326,8 @@ public:
void set_process_internal(bool p_idle_process_internal);
bool is_processing_internal() const;
+ void set_process_priority(int p_priority);
+
void set_process_input(bool p_enable);
bool is_processing_input() const;
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index 607dbebf6c..3424c4edac 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -132,6 +132,12 @@ void SceneTree::remove_from_group(const StringName &p_group, Node *p_node) {
group_map.erase(E);
}
+void SceneTree::make_group_changed(const StringName &p_group) {
+ Map<StringName, Group>::Element *E = group_map.find(p_group);
+ if (E)
+ E->get().changed = true;
+}
+
void SceneTree::flush_transform_notifications() {
SelfList<Node> *n = xform_change_list.first();
@@ -165,7 +171,7 @@ void SceneTree::_flush_ugc() {
ugc_locked = false;
}
-void SceneTree::_update_group_order(Group &g) {
+void SceneTree::_update_group_order(Group &g, bool p_use_priority) {
if (!g.changed)
return;
@@ -175,8 +181,13 @@ void SceneTree::_update_group_order(Group &g) {
Node **nodes = &g.nodes[0];
int node_count = g.nodes.size();
- SortArray<Node *, Node::Comparator> node_sort;
- node_sort.sort(nodes, node_count);
+ if (p_use_priority) {
+ SortArray<Node *, Node::ComparatorWithPriority> node_sort;
+ node_sort.sort(nodes, node_count);
+ } else {
+ SortArray<Node *, Node::Comparator> node_sort;
+ node_sort.sort(nodes, node_count);
+ }
g.changed = false;
}
@@ -485,7 +496,9 @@ bool SceneTree::idle(float p_time) {
idle_process_time = p_time;
- multiplayer->poll();
+ if (multiplayer_poll) {
+ multiplayer->poll();
+ }
emit_signal("idle_frame");
@@ -496,7 +509,8 @@ bool SceneTree::idle(float p_time) {
_notify_group_pause("idle_process_internal", Node::NOTIFICATION_INTERNAL_PROCESS);
_notify_group_pause("idle_process", Node::NOTIFICATION_PROCESS);
- Size2 win_size = Size2(OS::get_singleton()->get_video_mode().width, OS::get_singleton()->get_video_mode().height);
+ Size2 win_size = Size2(OS::get_singleton()->get_window_size().width, OS::get_singleton()->get_window_size().height);
+
if (win_size != last_screen_size) {
last_screen_size = win_size;
@@ -654,6 +668,11 @@ void SceneTree::_notification(int p_notification) {
#endif
} break;
+ case NOTIFICATION_CRASH: {
+
+ get_root()->propagate_notification(p_notification);
+ } break;
+
default:
break;
};
@@ -913,7 +932,7 @@ void SceneTree::_notify_group_pause(const StringName &p_group, int p_notificatio
if (g.nodes.empty())
return;
- _update_group_order(g);
+ _update_group_order(g, p_notification == Node::NOTIFICATION_PROCESS || p_notification == Node::NOTIFICATION_INTERNAL_PROCESS || p_notification == Node::NOTIFICATION_PHYSICS_PROCESS || p_notification == Node::NOTIFICATION_INTERNAL_PHYSICS_PROCESS);
//copy, so copy on write happens in case something is removed from process while being called
//performance is not lost because only if something is added/removed the vector is copied.
@@ -1110,7 +1129,7 @@ void SceneTree::_update_root_rect() {
}
//actual screen video mode
- Size2 video_mode = Size2(OS::get_singleton()->get_video_mode().width, OS::get_singleton()->get_video_mode().height);
+ Size2 video_mode = Size2(OS::get_singleton()->get_window_size().width, OS::get_singleton()->get_window_size().height);
Size2 desired_res = stretch_min;
Size2 viewport_size;
@@ -1672,6 +1691,14 @@ Ref<MultiplayerAPI> SceneTree::get_multiplayer() const {
return multiplayer;
}
+void SceneTree::set_multiplayer_poll_enabled(bool p_enabled) {
+ multiplayer_poll = p_enabled;
+}
+
+bool SceneTree::is_multiplayer_poll_enabled() const {
+ return multiplayer_poll;
+}
+
void SceneTree::set_multiplayer(Ref<MultiplayerAPI> p_multiplayer) {
ERR_FAIL_COND(!p_multiplayer.is_valid());
@@ -1802,6 +1829,8 @@ void SceneTree::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_multiplayer", "multiplayer"), &SceneTree::set_multiplayer);
ClassDB::bind_method(D_METHOD("get_multiplayer"), &SceneTree::get_multiplayer);
+ ClassDB::bind_method(D_METHOD("set_multiplayer_poll_enabled", "enabled"), &SceneTree::set_multiplayer_poll_enabled);
+ ClassDB::bind_method(D_METHOD("is_multiplayer_poll_enabled"), &SceneTree::is_multiplayer_poll_enabled);
ClassDB::bind_method(D_METHOD("set_network_peer", "peer"), &SceneTree::set_network_peer);
ClassDB::bind_method(D_METHOD("get_network_peer"), &SceneTree::get_network_peer);
ClassDB::bind_method(D_METHOD("is_network_server"), &SceneTree::is_network_server);
@@ -1830,6 +1859,7 @@ void SceneTree::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "network_peer", PROPERTY_HINT_RESOURCE_TYPE, "NetworkedMultiplayerPeer", 0), "set_network_peer", "get_network_peer");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "root", PROPERTY_HINT_RESOURCE_TYPE, "Node", 0), "", "get_root");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "multiplayer", PROPERTY_HINT_RESOURCE_TYPE, "MultiplayerAPI", 0), "set_multiplayer", "get_multiplayer");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "multiplayer_poll"), "set_multiplayer_poll_enabled", "is_multiplayer_poll_enabled");
ADD_SIGNAL(MethodInfo("tree_changed"));
ADD_SIGNAL(MethodInfo("node_added", PropertyInfo(Variant::OBJECT, "node")));
@@ -1934,6 +1964,7 @@ SceneTree::SceneTree() {
root->set_world(Ref<World>(memnew(World)));
// Initialize network state
+ multiplayer_poll = true;
set_multiplayer(Ref<MultiplayerAPI>(memnew(MultiplayerAPI)));
//root->set_world_2d( Ref<World2D>( memnew( World2D )));
@@ -1990,7 +2021,7 @@ SceneTree::SceneTree() {
stretch_aspect = STRETCH_ASPECT_IGNORE;
stretch_shrink = 1;
- last_screen_size = Size2(OS::get_singleton()->get_video_mode().width, OS::get_singleton()->get_video_mode().height);
+ last_screen_size = Size2(OS::get_singleton()->get_window_size().width, OS::get_singleton()->get_window_size().height);
_update_root_rect();
if (ScriptDebugger::get_singleton()) {
diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h
index 6e0156546e..11201097d4 100644
--- a/scene/main/scene_tree.h
+++ b/scene/main/scene_tree.h
@@ -161,7 +161,7 @@ private:
bool ugc_locked;
void _flush_ugc();
- _FORCE_INLINE_ void _update_group_order(Group &g);
+ _FORCE_INLINE_ void _update_group_order(Group &g, bool p_use_priority = false);
void _update_listener();
Array _get_nodes_in_group(const StringName &p_group);
@@ -186,6 +186,7 @@ private:
///network///
Ref<MultiplayerAPI> multiplayer;
+ bool multiplayer_poll;
void _network_peer_connected(int p_id);
void _network_peer_disconnected(int p_id);
@@ -203,6 +204,7 @@ private:
Group *add_to_group(const StringName &p_group, Node *p_node);
void remove_from_group(const StringName &p_group, Node *p_node);
+ void make_group_changed(const StringName &p_group);
void _notify_group_pause(const StringName &p_group, int p_notification);
void _call_input_pause(const StringName &p_group, const StringName &p_method, const Ref<InputEvent> &p_input);
@@ -411,6 +413,8 @@ public:
//network API
Ref<MultiplayerAPI> get_multiplayer() const;
+ void set_multiplayer_poll_enabled(bool p_enabled);
+ bool is_multiplayer_poll_enabled() const;
void set_multiplayer(Ref<MultiplayerAPI> p_multiplayer);
void set_network_peer(const Ref<NetworkedMultiplayerPeer> &p_network_peer);
Ref<NetworkedMultiplayerPeer> get_network_peer() const;
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index ca9be9823a..9013d276c7 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -41,7 +41,7 @@
#include "scene/3d/spatial.h"
#include "scene/gui/control.h"
#include "scene/gui/label.h"
-#include "scene/gui/panel.h"
+#include "scene/gui/panel_container.h"
#include "scene/main/timer.h"
#include "scene/resources/mesh.h"
#include "scene/scene_string_names.h"
@@ -144,7 +144,7 @@ void ViewportTexture::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_viewport_path_in_scene", "path"), &ViewportTexture::set_viewport_path_in_scene);
ClassDB::bind_method(D_METHOD("get_viewport_path_in_scene"), &ViewportTexture::get_viewport_path_in_scene);
- ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "viewport_path"), "set_viewport_path_in_scene", "get_viewport_path_in_scene");
+ ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "viewport_path", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Viewport"), "set_viewport_path_in_scene", "get_viewport_path_in_scene");
}
ViewportTexture::ViewportTexture() {
@@ -166,9 +166,9 @@ ViewportTexture::~ViewportTexture() {
/////////////////////////////////////
-class TooltipPanel : public Panel {
+class TooltipPanel : public PanelContainer {
- GDCLASS(TooltipPanel, Panel)
+ GDCLASS(TooltipPanel, PanelContainer)
public:
TooltipPanel(){};
};
@@ -626,7 +626,7 @@ Rect2 Viewport::get_visible_rect() const {
if (size == Size2()) {
- r = Rect2(Point2(), Size2(OS::get_singleton()->get_video_mode().width, OS::get_singleton()->get_video_mode().height));
+ r = Rect2(Point2(), Size2(OS::get_singleton()->get_window_size().width, OS::get_singleton()->get_window_size().height));
} else {
r = Rect2(Point2(), size);
@@ -1305,50 +1305,87 @@ void Viewport::_gui_cancel_tooltip() {
if (gui.tooltip_popup) {
gui.tooltip_popup->queue_delete();
gui.tooltip_popup = NULL;
+ gui.tooltip_label = NULL;
}
}
+String Viewport::_gui_get_tooltip(Control *p_control, const Vector2 &p_pos, Control **r_which) {
+
+ Vector2 pos = p_pos;
+ String tooltip;
+
+ while (p_control) {
+
+ tooltip = p_control->get_tooltip(pos);
+
+ if (r_which) {
+ *r_which = p_control;
+ }
+
+ if (tooltip != String())
+ break;
+ pos = p_control->get_transform().xform(pos);
+
+ if (p_control->data.mouse_filter == Control::MOUSE_FILTER_STOP)
+ break;
+ if (p_control->is_set_as_toplevel())
+ break;
+
+ p_control = p_control->get_parent_control();
+ }
+
+ return tooltip;
+}
+
void Viewport::_gui_show_tooltip() {
if (!gui.tooltip) {
return;
}
- String tooltip = gui.tooltip->get_tooltip(gui.tooltip->get_global_transform().xform_inv(gui.tooltip_pos));
+ Control *which = NULL;
+ String tooltip = _gui_get_tooltip(gui.tooltip, gui.tooltip->get_global_transform().xform_inv(gui.tooltip_pos), &which);
if (tooltip.length() == 0)
return; // bye
if (gui.tooltip_popup) {
memdelete(gui.tooltip_popup);
gui.tooltip_popup = NULL;
+ gui.tooltip_label = NULL;
}
- if (!gui.tooltip) {
+ if (!which) {
return;
}
- Control *rp = gui.tooltip->get_root_parent_control();
+ Control *rp = which; //->get_root_parent_control();
if (!rp)
return;
- gui.tooltip_popup = memnew(TooltipPanel);
+ gui.tooltip_popup = which->make_custom_tooltip(tooltip);
+
+ if (!gui.tooltip_popup) {
+ gui.tooltip_popup = memnew(TooltipPanel);
+
+ gui.tooltip_label = memnew(TooltipLabel);
+ gui.tooltip_popup->add_child(gui.tooltip_label);
+
+ Ref<StyleBox> ttp = gui.tooltip_label->get_stylebox("panel", "TooltipPanel");
+
+ gui.tooltip_label->set_anchor_and_margin(MARGIN_LEFT, Control::ANCHOR_BEGIN, ttp->get_margin(MARGIN_LEFT));
+ gui.tooltip_label->set_anchor_and_margin(MARGIN_TOP, Control::ANCHOR_BEGIN, ttp->get_margin(MARGIN_TOP));
+ gui.tooltip_label->set_anchor_and_margin(MARGIN_RIGHT, Control::ANCHOR_END, -ttp->get_margin(MARGIN_RIGHT));
+ gui.tooltip_label->set_anchor_and_margin(MARGIN_BOTTOM, Control::ANCHOR_END, -ttp->get_margin(MARGIN_BOTTOM));
+ gui.tooltip_label->set_text(tooltip.strip_edges());
+ }
rp->add_child(gui.tooltip_popup);
gui.tooltip_popup->force_parent_owned();
- gui.tooltip_label = memnew(TooltipLabel);
- gui.tooltip_popup->add_child(gui.tooltip_label);
gui.tooltip_popup->set_as_toplevel(true);
- gui.tooltip_popup->hide();
-
- Ref<StyleBox> ttp = gui.tooltip_label->get_stylebox("panel", "TooltipPanel");
+ //gui.tooltip_popup->hide();
- gui.tooltip_label->set_anchor_and_margin(MARGIN_LEFT, Control::ANCHOR_BEGIN, ttp->get_margin(MARGIN_LEFT));
- gui.tooltip_label->set_anchor_and_margin(MARGIN_TOP, Control::ANCHOR_BEGIN, ttp->get_margin(MARGIN_TOP));
- gui.tooltip_label->set_anchor_and_margin(MARGIN_RIGHT, Control::ANCHOR_END, -ttp->get_margin(MARGIN_RIGHT));
- gui.tooltip_label->set_anchor_and_margin(MARGIN_BOTTOM, Control::ANCHOR_END, -ttp->get_margin(MARGIN_BOTTOM));
- gui.tooltip_label->set_text(tooltip.strip_edges());
- Rect2 r(gui.tooltip_pos + Point2(10, 10), gui.tooltip_label->get_minimum_size() + ttp->get_minimum_size());
- Rect2 vr = gui.tooltip_label->get_viewport_rect();
+ Rect2 r(gui.tooltip_pos + Point2(10, 10), gui.tooltip_popup->get_minimum_size());
+ Rect2 vr = gui.tooltip_popup->get_viewport_rect();
if (r.size.x + r.position.x > vr.size.x)
r.position.x = vr.size.x - r.size.x;
else if (r.position.x < 0)
@@ -1380,6 +1417,8 @@ void Viewport::_gui_call_input(Control *p_control, const Ref<InputEvent> &p_inpu
mb->get_button_index() == BUTTON_WHEEL_UP ||
mb->get_button_index() == BUTTON_WHEEL_LEFT ||
mb->get_button_index() == BUTTON_WHEEL_RIGHT));
+ Ref<InputEventPanGesture> pn = p_input;
+ cant_stop_me_now = pn.is_valid() || cant_stop_me_now;
bool ismouse = ev.is_valid() || Object::cast_to<InputEventMouseMotion>(*p_input) != NULL;
@@ -1388,12 +1427,14 @@ void Viewport::_gui_call_input(Control *p_control, const Ref<InputEvent> &p_inpu
Control *control = Object::cast_to<Control>(ci);
if (control) {
- control->call_multilevel(SceneStringNames::get_singleton()->_gui_input, ev);
+
+ control->emit_signal(SceneStringNames::get_singleton()->gui_input, ev); //signal should be first, so it's possible to override an event (and then accept it)
if (gui.key_event_accepted)
break;
if (!control->is_inside_tree())
break;
- control->emit_signal(SceneStringNames::get_singleton()->gui_input, ev);
+ control->call_multilevel(SceneStringNames::get_singleton()->_gui_input, ev);
+
if (!control->is_inside_tree() || control->is_set_as_toplevel())
break;
if (gui.key_event_accepted)
@@ -1863,13 +1904,18 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
bool is_tooltip_shown = false;
if (gui.tooltip_popup) {
- if (can_tooltip) {
- String tooltip = over->get_tooltip(gui.tooltip->get_global_transform().xform_inv(mpos));
+ if (can_tooltip && gui.tooltip) {
+ String tooltip = _gui_get_tooltip(over, gui.tooltip->get_global_transform().xform_inv(mpos));
if (tooltip.length() == 0)
_gui_cancel_tooltip();
- else if (tooltip == gui.tooltip_label->get_text())
+ else if (gui.tooltip_label) {
+ if (tooltip == gui.tooltip_label->get_text()) {
+ is_tooltip_shown = true;
+ }
+ } else if (tooltip == String(gui.tooltip_popup->call("get_tooltip_text"))) {
is_tooltip_shown = true;
+ }
} else
_gui_cancel_tooltip();
}
@@ -1886,7 +1932,23 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
mm->set_position(pos);
- Control::CursorShape cursor_shape = over->get_cursor_shape(pos);
+ Control::CursorShape cursor_shape = Control::CURSOR_ARROW;
+ {
+ Control *c = over;
+ Vector2 cpos = pos;
+ while (c) {
+ cursor_shape = c->get_cursor_shape(cpos);
+ cpos = c->get_transform().xform(cpos);
+ if (cursor_shape != Control::CURSOR_ARROW)
+ break;
+ if (c->data.mouse_filter == Control::MOUSE_FILTER_STOP)
+ break;
+ if (c->is_set_as_toplevel())
+ break;
+ c = c->get_parent_control();
+ }
+ }
+
OS::get_singleton()->set_cursor_shape((OS::CursorShape)cursor_shape);
if (over->can_process()) {
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index c1ef58de69..e717d27069 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -255,7 +255,7 @@ private:
Control *key_focus;
Control *mouse_over;
Control *tooltip;
- Panel *tooltip_popup;
+ Control *tooltip_popup;
Label *tooltip_label;
Point2 tooltip_pos;
Point2 last_mouse_pos;
@@ -312,6 +312,7 @@ private:
void _gui_remove_root_control(List<Control *>::Element *RI);
void _gui_remove_subwindow_control(List<Control *>::Element *SI);
+ String _gui_get_tooltip(Control *p_control, const Vector2 &p_pos, Control **r_which = NULL);
void _gui_cancel_tooltip();
void _gui_show_tooltip();