summaryrefslogtreecommitdiff
path: root/scene/main
diff options
context:
space:
mode:
Diffstat (limited to 'scene/main')
-rw-r--r--scene/main/canvas_layer.cpp4
-rw-r--r--scene/main/http_request.cpp20
-rw-r--r--scene/main/node.cpp50
-rw-r--r--scene/main/node.h9
-rw-r--r--scene/main/scene_tree.cpp53
-rw-r--r--scene/main/scene_tree.h3
-rw-r--r--scene/main/viewport.cpp126
-rw-r--r--scene/main/viewport.h9
8 files changed, 180 insertions, 94 deletions
diff --git a/scene/main/canvas_layer.cpp b/scene/main/canvas_layer.cpp
index 8414210952..a2e890e7a7 100644
--- a/scene/main/canvas_layer.cpp
+++ b/scene/main/canvas_layer.cpp
@@ -248,12 +248,10 @@ void CanvasLayer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_custom_viewport"), &CanvasLayer::get_custom_viewport);
ClassDB::bind_method(D_METHOD("get_canvas"), &CanvasLayer::get_canvas);
- //ClassDB::bind_method(D_METHOD("get_viewport"),&CanvasLayer::get_viewport);
ADD_PROPERTY(PropertyInfo(Variant::INT, "layer", PROPERTY_HINT_RANGE, "-128,128,1"), "set_layer", "get_layer");
- //ADD_PROPERTY( PropertyInfo(Variant::MATRIX32,"transform",PROPERTY_HINT_RANGE),"set_transform","get_transform") ;
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset"), "set_offset", "get_offset");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "rotation_degrees", PROPERTY_HINT_RANGE, "-1440,1440,0.1", PROPERTY_USAGE_EDITOR), "set_rotation_degrees", "get_rotation_degrees");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "rotation_degrees", PROPERTY_HINT_RANGE, "-1080,1080,0.1,or_lesser,or_greater", PROPERTY_USAGE_EDITOR), "set_rotation_degrees", "get_rotation_degrees");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "rotation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_rotation", "get_rotation");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "scale"), "set_scale", "get_scale");
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "transform"), "set_transform", "get_transform");
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 4dc7b03685..e30f58e012 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
@@ -725,6 +725,17 @@ const Map<StringName, MultiplayerAPI::RPCMode>::Element *Node::get_node_rset_mod
return data.rpc_properties.find(p_property);
}
+bool Node::can_process_notification(int p_what) const {
+ switch (p_what) {
+ case NOTIFICATION_PHYSICS_PROCESS: return data.physics_process;
+ case NOTIFICATION_PROCESS: return data.idle_process;
+ case NOTIFICATION_INTERNAL_PROCESS: return data.idle_process_internal;
+ case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: return data.physics_process_internal;
+ }
+
+ return true;
+}
+
bool Node::can_process() const {
ERR_FAIL_COND_V(!is_inside_tree(), false);
@@ -809,6 +820,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)
@@ -1895,7 +1922,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;
}
@@ -1934,8 +1961,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 {
@@ -2054,9 +2082,7 @@ void Node::_duplicate_and_reown(Node *p_new_parent, const Map<Node *, Node *> &p
} else {
Object *obj = ClassDB::instance(get_class());
- if (!obj) {
- print_line("could not duplicate: " + String(get_class()));
- }
+ ERR_EXPLAIN("Node: Could not duplicate: " + String(get_class()));
ERR_FAIL_COND(!obj);
node = Object::cast_to<Node>(obj);
if (!node)
@@ -2151,9 +2177,7 @@ Node *Node::duplicate_and_reown(const Map<Node *, Node *> &p_reown_map) const {
Node *node = NULL;
Object *obj = ClassDB::instance(get_class());
- if (!obj) {
- print_line("could not duplicate: " + String(get_class()));
- }
+ ERR_EXPLAIN("Node: Could not duplicate: " + String(get_class()));
ERR_FAIL_COND_V(!obj, NULL);
node = Object::cast_to<Node>(obj);
if (!node)
@@ -2444,7 +2468,7 @@ static void _Node_debug_sn(Object *p_obj) {
path = n->get_name();
else
path = String(p->get_name()) + "/" + p->get_path_to(n);
- print_line(itos(p_obj->get_instance_id()) + "- Stray Node: " + path + " (Type: " + n->get_class() + ")");
+ print_line(itos(p_obj->get_instance_id()) + " - Stray Node: " + path + " (Type: " + n->get_class() + ")");
}
void Node::_print_stray_nodes() {
@@ -2527,6 +2551,9 @@ void Node::clear_internal_tree_resource_paths() {
String Node::get_configuration_warning() const {
+ if (get_script_instance() && get_script_instance()->has_method("_get_configuration_warning")) {
+ return get_script_instance()->call("_get_configuration_warning");
+ }
return String();
}
@@ -2607,6 +2634,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);
@@ -2734,6 +2762,7 @@ void Node::_bind_methods() {
BIND_VMETHOD(MethodInfo("_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent")));
BIND_VMETHOD(MethodInfo("_unhandled_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent")));
BIND_VMETHOD(MethodInfo("_unhandled_key_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEventKey")));
+ BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_configuration_warning"));
//ClassDB::bind_method(D_METHOD("get_child",&Node::get_child,PH("index")));
//ClassDB::bind_method(D_METHOD("get_node",&Node::get_node,PH("path")));
@@ -2758,6 +2787,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..f3422618ce 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->data.process_priority == p_a->data.process_priority ? p_b->is_greater_than(p_a) : p_b->data.process_priority > p_a->data.process_priority; }
+ };
+
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;
@@ -319,6 +325,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;
@@ -355,6 +363,7 @@ public:
void set_pause_mode(PauseMode p_mode);
PauseMode get_pause_mode() const;
bool can_process() const;
+ bool can_process_notification(int p_what) const;
void request_ready();
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index 8d6e57b335..11268cc5c6 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,18 +171,23 @@ 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;
if (g.nodes.empty())
return;
- Node **nodes = &g.nodes[0];
+ Node **nodes = g.nodes.ptrw();
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;
}
@@ -216,7 +227,7 @@ void SceneTree::call_group_flags(uint32_t p_call_flags, const StringName &p_grou
_update_group_order(g);
Vector<Node *> nodes_copy = g.nodes;
- Node **nodes = &nodes_copy[0];
+ Node **nodes = nodes_copy.ptrw();
int node_count = nodes_copy.size();
call_lock++;
@@ -271,7 +282,7 @@ void SceneTree::notify_group_flags(uint32_t p_call_flags, const StringName &p_gr
_update_group_order(g);
Vector<Node *> nodes_copy = g.nodes;
- Node **nodes = &nodes_copy[0];
+ Node **nodes = nodes_copy.ptrw();
int node_count = nodes_copy.size();
call_lock++;
@@ -320,7 +331,7 @@ void SceneTree::set_group_flags(uint32_t p_call_flags, const StringName &p_group
_update_group_order(g);
Vector<Node *> nodes_copy = g.nodes;
- Node **nodes = &nodes_copy[0];
+ Node **nodes = nodes_copy.ptrw();
int node_count = nodes_copy.size();
call_lock++;
@@ -498,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;
@@ -656,6 +668,11 @@ void SceneTree::_notification(int p_notification) {
#endif
} break;
+ case NOTIFICATION_CRASH: {
+
+ get_root()->propagate_notification(p_notification);
+ } break;
+
default:
break;
};
@@ -878,7 +895,7 @@ void SceneTree::_call_input_pause(const StringName &p_group, const StringName &p
Vector<Node *> nodes_copy = g.nodes;
int node_count = nodes_copy.size();
- Node **nodes = &nodes_copy[0];
+ Node **nodes = nodes_copy.ptrw();
Variant arg = p_input;
const Variant *v[1] = { &arg };
@@ -915,14 +932,14 @@ 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.
Vector<Node *> nodes_copy = g.nodes;
int node_count = nodes_copy.size();
- Node **nodes = &nodes_copy[0];
+ Node **nodes = nodes_copy.ptrw();
call_lock++;
@@ -934,6 +951,8 @@ void SceneTree::_notify_group_pause(const StringName &p_group, int p_notificatio
if (!n->can_process())
continue;
+ if (!n->can_process_notification(p_notification))
+ continue;
n->notification(p_notification);
//ERR_FAIL_COND(node_count != g.nodes.size());
@@ -1112,7 +1131,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;
@@ -1176,8 +1195,6 @@ void SceneTree::_update_root_rect() {
VisualServer::get_singleton()->black_bars_set_margins(0, 0, 0, 0);
}
- //print_line("VP SIZE: "+viewport_size+" OFFSET: "+offset+" = "+(offset*2+viewport_size));
- //print_line("SS: "+video_mode);
switch (stretch_mode) {
case STRETCH_MODE_2D: {
@@ -1845,10 +1862,10 @@ void SceneTree::_bind_methods() {
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")));
- ADD_SIGNAL(MethodInfo("node_removed", PropertyInfo(Variant::OBJECT, "node")));
+ ADD_SIGNAL(MethodInfo("node_added", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
+ ADD_SIGNAL(MethodInfo("node_removed", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
ADD_SIGNAL(MethodInfo("screen_resized"));
- ADD_SIGNAL(MethodInfo("node_configuration_warning_changed", PropertyInfo(Variant::OBJECT, "node")));
+ ADD_SIGNAL(MethodInfo("node_configuration_warning_changed", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
ADD_SIGNAL(MethodInfo("idle_frame"));
ADD_SIGNAL(MethodInfo("physics_frame"));
@@ -2004,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 aa8d78b1e1..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);
@@ -204,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);
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 1236aea2dd..d1b3eb9d9a 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -41,7 +41,10 @@
#include "scene/3d/spatial.h"
#include "scene/gui/control.h"
#include "scene/gui/label.h"
+#include "scene/gui/menu_button.h"
#include "scene/gui/panel.h"
+#include "scene/gui/panel_container.h"
+#include "scene/gui/popup_menu.h"
#include "scene/main/timer.h"
#include "scene/resources/mesh.h"
#include "scene/scene_string_names.h"
@@ -144,7 +147,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 +169,9 @@ ViewportTexture::~ViewportTexture() {
/////////////////////////////////////
-class TooltipPanel : public Panel {
+class TooltipPanel : public PanelContainer {
- GDCLASS(TooltipPanel, Panel)
+ GDCLASS(TooltipPanel, PanelContainer)
public:
TooltipPanel(){};
};
@@ -182,6 +185,7 @@ public:
Viewport::GUI::GUI() {
+ dragging = false;
mouse_focus = NULL;
mouse_click_grabber = NULL;
mouse_focus_button = -1;
@@ -441,7 +445,7 @@ void Viewport::_notification(int p_what) {
Vector2 point = get_canvas_transform().affine_inverse().xform(pos);
Physics2DDirectSpaceState::ShapeResult res[64];
- int rc = ss2d->intersect_point(point, res, 64, Set<RID>(), 0xFFFFFFFF, true);
+ int rc = ss2d->intersect_point(point, res, 64, Set<RID>(), 0xFFFFFFFF, true, true, true);
for (int i = 0; i < rc; i++) {
if (res[i].collider_id && res[i].collider) {
@@ -524,7 +528,7 @@ void Viewport::_notification(int p_what) {
PhysicsDirectSpaceState *space = PhysicsServer::get_singleton()->space_get_direct_state(find_world()->get_space());
if (space) {
- bool col = space->intersect_ray(from, from + dir * 10000, result, Set<RID>(), 0xFFFFFFFF, true);
+ bool col = space->intersect_ray(from, from + dir * 10000, result, Set<RID>(), 0xFFFFFFFF, true, true, true);
ObjectID new_collider = 0;
if (col) {
@@ -560,7 +564,7 @@ void Viewport::_notification(int p_what) {
PhysicsDirectSpaceState *space = PhysicsServer::get_singleton()->space_get_direct_state(find_world()->get_space());
if (space) {
- bool col = space->intersect_ray(from, from + dir * 10000, result, Set<RID>(), 0xFFFFFFFF, true);
+ bool col = space->intersect_ray(from, from + dir * 10000, result, Set<RID>(), 0xFFFFFFFF, true, true, true);
ObjectID new_collider = 0;
if (col) {
CollisionObject *co = Object::cast_to<CollisionObject>(result.collider);
@@ -626,7 +630,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,10 +1309,11 @@ 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) {
+String Viewport::_gui_get_tooltip(Control *p_control, const Vector2 &p_pos, Control **r_which) {
Vector2 pos = p_pos;
String tooltip;
@@ -1317,6 +1322,10 @@ String Viewport::_gui_get_tooltip(Control *p_control, const Vector2 &p_pos) {
tooltip = p_control->get_tooltip(pos);
+ if (r_which) {
+ *r_which = p_control;
+ }
+
if (tooltip != String())
break;
pos = p_control->get_transform().xform(pos);
@@ -1338,41 +1347,49 @@ void Viewport::_gui_show_tooltip() {
return;
}
- String tooltip = _gui_get_tooltip(gui.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)
@@ -1404,6 +1421,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;
@@ -1488,12 +1507,6 @@ Control *Viewport::_gui_find_control_at_pos(CanvasItem *p_node, const Point2 &p_
if (Object::cast_to<Viewport>(p_node))
return NULL;
- Control *c = Object::cast_to<Control>(p_node);
-
- if (c) {
- //print_line("at "+String(c->get_path())+" POS "+c->get_position()+" bt "+p_xform);
- }
-
//subwindows first!!
if (!p_node->is_visible()) {
@@ -1506,6 +1519,8 @@ Control *Viewport::_gui_find_control_at_pos(CanvasItem *p_node, const Point2 &p_
if (matrix.basis_determinant() == 0.0f)
return NULL;
+ Control *c = Object::cast_to<Control>(p_node);
+
if (!c || !c->clips_input() || c->has_point(matrix.affine_inverse().xform(p_global))) {
for (int i = p_node->get_child_count() - 1; i >= 0; i--) {
@@ -1636,7 +1651,6 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
*/
gui.mouse_focus = _gui_find_control(pos);
- //print_line("has mf "+itos(gui.mouse_focus!=NULL));
gui.mouse_focus_button = mb->get_button_index();
if (!gui.mouse_focus) {
@@ -1665,11 +1679,6 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
arr.push_back(gui.mouse_focus->get_class());
ScriptDebugger::get_singleton()->send_message("click_ctrl", arr);
}
-
-/*if (bool(GLOBAL_DEF("debug/print_clicked_control",false))) {
-
- print_line(String(gui.mouse_focus->get_path())+" - "+pos);
- }*/
#endif
if (mb->get_button_index() == BUTTON_LEFT) { //assign focus
@@ -1710,6 +1719,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
}
gui.drag_data = Variant();
+ gui.dragging = false;
if (gui.drag_preview) {
memdelete(gui.drag_preview);
@@ -1739,6 +1749,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
}
gui.drag_data = Variant();
+ gui.dragging = false;
_propagate_viewport_notification(this, NOTIFICATION_DRAG_END);
//change mouse accordingly
}
@@ -1801,10 +1812,13 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
Control *control = Object::cast_to<Control>(ci);
if (control) {
+ gui.dragging = true;
gui.drag_data = control->get_drag_data(control->get_global_transform_with_canvas().affine_inverse().xform(mpos) - gui.drag_accum);
if (gui.drag_data.get_type() != Variant::NIL) {
gui.mouse_focus = NULL;
+ } else {
+ gui.dragging = false;
}
if (control->data.mouse_filter == Control::MOUSE_FILTER_STOP)
@@ -1838,8 +1852,32 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
if (gui.drag_data.get_type() == Variant::NIL && over && !gui.modal_stack.empty()) {
Control *top = gui.modal_stack.back()->get();
+
if (over != top && !top->is_a_parent_of(over)) {
- over = NULL; //nothing can be found outside the modal stack
+
+ PopupMenu *popup_menu = Object::cast_to<PopupMenu>(top);
+ MenuButton *popup_menu_parent = NULL;
+ MenuButton *menu_button = Object::cast_to<MenuButton>(over);
+
+ if (popup_menu)
+ popup_menu_parent = Object::cast_to<MenuButton>(popup_menu->get_parent());
+
+ // If the mouse is over a menu button, this menu will open automatically
+ // if there is already a pop-up menu open at the same hierarchical level.
+ if (popup_menu_parent && menu_button &&
+ popup_menu_parent->get_icon().is_null() &&
+ menu_button->get_icon().is_null() &&
+ (popup_menu->get_parent()->get_parent()->is_a_parent_of(menu_button) ||
+ menu_button->get_parent()->is_a_parent_of(popup_menu))) {
+
+ popup_menu->notification(Control::NOTIFICATION_MODAL_CLOSE);
+ popup_menu->_modal_stack_remove();
+ popup_menu->hide();
+
+ menu_button->pressed();
+ } else {
+ over = NULL; //nothing can be found outside the modal stack
+ }
}
}
@@ -1889,13 +1927,18 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
bool is_tooltip_shown = false;
if (gui.tooltip_popup) {
- if (can_tooltip) {
+ 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();
}
@@ -2215,6 +2258,7 @@ void Viewport::_gui_force_drag(Control *p_base, const Variant &p_data, Control *
ERR_EXPLAIN("Drag data must be a value");
ERR_FAIL_COND(p_data.get_type() == Variant::NIL);
+ gui.dragging = true;
gui.drag_data = p_data;
gui.mouse_focus = NULL;
@@ -2654,6 +2698,9 @@ bool Viewport::is_snap_controls_to_pixels_enabled() const {
return snap_controls_to_pixels;
}
+bool Viewport::gui_is_dragging() const {
+ return gui.dragging;
+}
void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_use_arvr", "use"), &Viewport::set_use_arvr);
@@ -2740,6 +2787,7 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("gui_has_modal_stack"), &Viewport::gui_has_modal_stack);
ClassDB::bind_method(D_METHOD("gui_get_drag_data"), &Viewport::gui_get_drag_data);
+ ClassDB::bind_method(D_METHOD("gui_is_dragging"), &Viewport::gui_is_dragging);
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 3000398540..450f235b79 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -31,11 +31,11 @@
#ifndef VIEWPORT_H
#define VIEWPORT_H
-#include "math_2d.h"
#include "scene/main/node.h"
#include "scene/resources/texture.h"
#include "scene/resources/world_2d.h"
#include "servers/visual_server.h"
+#include "transform_2d.h"
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
@@ -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;
@@ -274,6 +274,7 @@ private:
bool roots_order_dirty;
List<Control *> roots;
int canvas_sort_index; //for sorting items with canvas as root
+ bool dragging;
GUI();
} gui;
@@ -312,7 +313,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);
+ String _gui_get_tooltip(Control *p_control, const Vector2 &p_pos, Control **r_which = NULL);
void _gui_cancel_tooltip();
void _gui_show_tooltip();
@@ -474,6 +475,8 @@ public:
void _subwindow_visibility_changed();
+ bool gui_is_dragging() const;
+
Viewport();
~Viewport();
};