Ver código fonte

Adjust SubViewportContainer event handling

Change SubViewportContainer, so that it processes events with a position property no longer in 'input', but in 'gui_input'.
This fixes the issue, that Nodes within its SubViewport receive MouseButton events before other Control-Nodes.
Markus Sauermann 3 anos atrás
pai
commit
56ddf89fac

+ 34 - 7
scene/gui/subviewport_container.cpp

@@ -180,24 +180,51 @@ void SubViewportContainer::input(const Ref<InputEvent> &p_event) {
 		return;
 	}
 
-	Transform2D xform = get_global_transform_with_canvas();
+	if (_is_propagated_in_gui_input(p_event)) {
+		return;
+	}
 
-	if (stretch) {
-		Transform2D scale_xf;
-		scale_xf.scale(Vector2(shrink, shrink));
-		xform *= scale_xf;
+	_send_event_to_viewports(p_event);
+}
+
+void SubViewportContainer::gui_input(const Ref<InputEvent> &p_event) {
+	ERR_FAIL_COND(p_event.is_null());
+
+	if (Engine::get_singleton()->is_editor_hint()) {
+		return;
 	}
 
-	Ref<InputEvent> ev = p_event->xformed_by(xform.affine_inverse());
+	if (!_is_propagated_in_gui_input(p_event)) {
+		return;
+	}
 
+	if (stretch && shrink > 1) {
+		Transform2D xform;
+		xform.scale(Vector2(1, 1) / shrink);
+		_send_event_to_viewports(p_event->xformed_by(xform));
+	} else {
+		_send_event_to_viewports(p_event);
+	}
+}
+
+void SubViewportContainer::_send_event_to_viewports(const Ref<InputEvent> &p_event) {
 	for (int i = 0; i < get_child_count(); i++) {
 		SubViewport *c = Object::cast_to<SubViewport>(get_child(i));
 		if (!c || c->is_input_disabled()) {
 			continue;
 		}
 
-		c->push_input(ev);
+		c->push_input(p_event);
+	}
+}
+
+bool SubViewportContainer::_is_propagated_in_gui_input(const Ref<InputEvent> &p_event) {
+	// Propagation of events with a position property happen in gui_input
+	// Propagation of other events happen in input
+	if (Object::cast_to<InputEventMouse>(*p_event) || Object::cast_to<InputEventScreenDrag>(*p_event) || Object::cast_to<InputEventScreenTouch>(*p_event) || Object::cast_to<InputEventGesture>(*p_event)) {
+		return true;
 	}
+	return false;
 }
 
 void SubViewportContainer::unhandled_input(const Ref<InputEvent> &p_event) {

+ 3 - 0
scene/gui/subviewport_container.h

@@ -39,6 +39,8 @@ class SubViewportContainer : public Container {
 	bool stretch = false;
 	int shrink = 1;
 	void _notify_viewports(int p_notification);
+	bool _is_propagated_in_gui_input(const Ref<InputEvent> &p_event);
+	void _send_event_to_viewports(const Ref<InputEvent> &p_event);
 
 protected:
 	void _notification(int p_what);
@@ -49,6 +51,7 @@ public:
 	bool is_stretch_enabled() const;
 
 	virtual void input(const Ref<InputEvent> &p_event) override;
+	virtual void gui_input(const Ref<InputEvent> &p_event) override;
 	virtual void unhandled_input(const Ref<InputEvent> &p_event) override;
 	void set_stretch_shrink(int p_shrink);
 	int get_stretch_shrink() const;