Skip to content

Commit

Permalink
Allow drag_preview to be handled by a different viewport than its parent
Browse files Browse the repository at this point in the history
  • Loading branch information
MinusKube committed Aug 27, 2022
1 parent cfcdd57 commit 0321946
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 10 deletions.
4 changes: 4 additions & 0 deletions doc/classes/Control.xml
Original file line number Diff line number Diff line change
Expand Up @@ -336,9 +336,11 @@
<return type="void" />
<param index="0" name="data" type="Variant" />
<param index="1" name="preview" type="Control" />
<param index="2" name="parent" type="Control" default="null" />
<description>
Forces drag and bypasses [method _get_drag_data] and [method set_drag_preview] by passing [param data] and [param preview]. Drag will start even if the mouse is neither over nor pressed on this control.
The methods [method _can_drop_data] and [method _drop_data] must be implemented on controls that want to receive drop data.
The [param parent] parameter defines which control will be used to determine preview's parent, or defaults to [code]this[/code] if left null.
</description>
</method>
<method name="get_anchor" qualifiers="const">
Expand Down Expand Up @@ -844,6 +846,7 @@
<method name="set_drag_preview">
<return type="void" />
<param index="0" name="control" type="Control" />
<param index="1" name="parent" type="Control" default="null" />
<description>
Shows the given control at the mouse pointer. A good time to call this method is in [method _get_drag_data]. The control must not be in the scene tree. You should not free the control, and you should not keep a reference to the control beyond the duration of the drag. It will be deleted automatically after the drag has ended.
[codeblocks]
Expand Down Expand Up @@ -873,6 +876,7 @@
}
[/csharp]
[/codeblocks]
The [param parent] parameter defines which control will be used to determine preview's parent, or defaults to [code]this[/code] if left null.
</description>
</method>
<method name="set_end">
Expand Down
2 changes: 1 addition & 1 deletion editor/plugins/visual_shader_editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4474,7 +4474,7 @@ Variant VisualShaderEditor::get_drag_data_fw(const Point2 &p_point, Control *p_f

Label *label = memnew(Label);
label->set_text(it->get_text(0));
set_drag_preview(label);
members->set_drag_preview(label, this);
return d;
}
return Variant();
Expand Down
21 changes: 15 additions & 6 deletions scene/gui/control.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1810,17 +1810,26 @@ void Control::drop_data(const Point2 &p_point, const Variant &p_data) {
GDVIRTUAL_CALL(_drop_data, p_point, p_data);
}

void Control::force_drag(const Variant &p_data, Control *p_control) {
void Control::force_drag(const Variant &p_data, Control *p_control, Control *p_parent) {
ERR_FAIL_COND(!is_inside_tree());
ERR_FAIL_COND(p_data.get_type() == Variant::NIL);

get_viewport()->_gui_force_drag(this, p_data, p_control);
if (p_parent == nullptr) {
p_parent = this;
}

get_viewport()->_gui_force_drag(p_parent, p_data, p_control);
}

void Control::set_drag_preview(Control *p_control) {
void Control::set_drag_preview(Control *p_control, Control *p_parent) {
ERR_FAIL_COND(!is_inside_tree());
ERR_FAIL_COND(!get_viewport()->gui_is_dragging());
get_viewport()->_gui_set_drag_preview(this, p_control);

if (p_parent == nullptr) {
p_parent = this;
}

get_viewport()->_gui_set_drag_preview(p_parent, p_control);
}

bool Control::is_drag_successful() const {
Expand Down Expand Up @@ -3423,7 +3432,7 @@ void Control::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_focus_previous", "previous"), &Control::set_focus_previous);
ClassDB::bind_method(D_METHOD("get_focus_previous"), &Control::get_focus_previous);

ClassDB::bind_method(D_METHOD("force_drag", "data", "preview"), &Control::force_drag);
ClassDB::bind_method(D_METHOD("force_drag", "data", "preview", "parent"), &Control::force_drag, DEFVAL((Control *)nullptr));

ClassDB::bind_method(D_METHOD("set_mouse_filter", "filter"), &Control::set_mouse_filter);
ClassDB::bind_method(D_METHOD("get_mouse_filter"), &Control::get_mouse_filter);
Expand All @@ -3437,7 +3446,7 @@ void Control::_bind_methods() {
ClassDB::bind_method(D_METHOD("grab_click_focus"), &Control::grab_click_focus);

ClassDB::bind_method(D_METHOD("set_drag_forwarding", "target"), &Control::set_drag_forwarding);
ClassDB::bind_method(D_METHOD("set_drag_preview", "control"), &Control::set_drag_preview);
ClassDB::bind_method(D_METHOD("set_drag_preview", "control", "parent"), &Control::set_drag_preview, DEFVAL((Control *)nullptr));
ClassDB::bind_method(D_METHOD("is_drag_successful"), &Control::is_drag_successful);

ClassDB::bind_method(D_METHOD("warp_mouse", "position"), &Control::warp_mouse);
Expand Down
4 changes: 2 additions & 2 deletions scene/gui/control.h
Original file line number Diff line number Diff line change
Expand Up @@ -501,8 +501,8 @@ class Control : public CanvasItem {
virtual Variant get_drag_data(const Point2 &p_point);
virtual bool can_drop_data(const Point2 &p_point, const Variant &p_data) const;
virtual void drop_data(const Point2 &p_point, const Variant &p_data);
void set_drag_preview(Control *p_control);
void force_drag(const Variant &p_data, Control *p_control);
void set_drag_preview(Control *p_control, Control *p_parent = nullptr);
void force_drag(const Variant &p_data, Control *p_control, Control *p_parent = nullptr);
bool is_drag_successful() const;

// Focus.
Expand Down
9 changes: 8 additions & 1 deletion scene/main/viewport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1779,7 +1779,14 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {

Control *drag_preview = _gui_get_drag_preview();
if (drag_preview) {
drag_preview->set_position(mpos);
// The viewport which started the drag takes care of the preview position,
// even if it's owned by another viewport. So, we need to convert the mouse
// position according to the target viewport.

Point2i this_position = get_base_window()->get_position();
Point2i owner_position = drag_preview->get_viewport()->get_base_window()->get_position();

drag_preview->set_position(mpos + this_position - owner_position);
}

gui.drag_mouse_over = over;
Expand Down

0 comments on commit 0321946

Please sign in to comment.