diff --git a/doc/classes/Control.xml b/doc/classes/Control.xml index b9f3275dfee..08964cf21d6 100644 --- a/doc/classes/Control.xml +++ b/doc/classes/Control.xml @@ -780,67 +780,13 @@ - + + + - Forwards the handling of this control's drag and drop to [param target] object. - Forwarding can be implemented in the target object similar to the methods [method _get_drag_data], [method _can_drop_data], and [method _drop_data] but with two differences: - 1. The function name must be suffixed with [b]_fw[/b] - 2. The function must take an extra argument that is the control doing the forwarding - [codeblocks] - [gdscript] - # ThisControl.gd - extends Control - export(Control) var target_control - - func _ready(): - set_drag_forwarding(target_control) - - # TargetControl.gd - extends Control - - func _can_drop_data_fw(position, data, from_control): - return true - - func _drop_data_fw(position, data, from_control): - my_handle_data(data) # Your handler method. - - func _get_drag_data_fw(position, from_control): - set_drag_preview(my_preview) - return my_data() - [/gdscript] - [csharp] - // ThisControl.cs - public class ThisControl : Control - { - [Export] - public Control TargetControl { get; set; } - public override void _Ready() - { - SetDragForwarding(TargetControl); - } - } - - // TargetControl.cs - public class TargetControl : Control - { - public void CanDropDataFw(Vector2 position, object data, Control fromControl) - { - return true; - } - - public void DropDataFw(Vector2 position, object data, Control fromControl) - { - MyHandleData(data); // Your handler method. - } - - public void GetDragDataFw(Vector2 position, Control fromControl) - { - SetDragPreview(MyPreview); - return MyData(); - } - } - [/csharp] - [/codeblocks] + Forwards the handling of this control's [method _get_drag_data], [method _can_drop_data] and [method _drop_data] virtual functions to delegate callables. + For each argument, if not empty, the delegate callable is used, otherwise the local (virtual) function is used. + The function format for each callable should be exactly the same as the virtual functions described above. diff --git a/editor/action_map_editor.cpp b/editor/action_map_editor.cpp index 8e55f3a1c3e..712b11d7d72 100644 --- a/editor/action_map_editor.cpp +++ b/editor/action_map_editor.cpp @@ -578,7 +578,7 @@ ActionMapEditor::ActionMapEditor() { action_tree->connect("button_clicked", callable_mp(this, &ActionMapEditor::_tree_button_pressed)); main_vbox->add_child(action_tree); - action_tree->set_drag_forwarding(this); + action_tree->set_drag_forwarding_compat(this); // Adding event dialog event_config_dialog = memnew(InputEventConfigurationDialog); diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp index 76d70b09e64..6e701cb6bd4 100644 --- a/editor/create_dialog.cpp +++ b/editor/create_dialog.cpp @@ -754,7 +754,7 @@ CreateDialog::CreateDialog() { favorites->connect("cell_selected", callable_mp(this, &CreateDialog::_favorite_selected)); favorites->connect("item_activated", callable_mp(this, &CreateDialog::_favorite_activated)); favorites->add_theme_constant_override("draw_guides", 1); - favorites->set_drag_forwarding(this); + favorites->set_drag_forwarding_compat(this); fav_vb->add_margin_child(TTR("Favorites:"), favorites, true); VBoxContainer *rec_vb = memnew(VBoxContainer); diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp index 5296749c18a..7ef99d56abd 100644 --- a/editor/editor_audio_buses.cpp +++ b/editor/editor_audio_buses.cpp @@ -903,7 +903,7 @@ EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses, bool p_is_master) { effects->connect("item_edited", callable_mp(this, &EditorAudioBus::_effect_edited)); effects->connect("cell_selected", callable_mp(this, &EditorAudioBus::_effect_selected)); effects->set_edit_checkbox_cell_only_when_checkbox_is_pressed(true); - effects->set_drag_forwarding(this); + effects->set_drag_forwarding_compat(this); effects->connect("item_mouse_selected", callable_mp(this, &EditorAudioBus::_effect_rmb)); effects->set_allow_rmb_select(true); effects->set_focus_mode(FOCUS_CLICK); diff --git a/editor/editor_autoload_settings.cpp b/editor/editor_autoload_settings.cpp index db251c857ca..4001b849ffe 100644 --- a/editor/editor_autoload_settings.cpp +++ b/editor/editor_autoload_settings.cpp @@ -935,7 +935,7 @@ EditorAutoloadSettings::EditorAutoloadSettings() { tree->set_select_mode(Tree::SELECT_MULTI); tree->set_allow_reselect(true); - tree->set_drag_forwarding(this); + tree->set_drag_forwarding_compat(this); tree->set_columns(4); tree->set_column_titles_visible(true); diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index 54d43bbf442..12aa44891d8 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -2065,7 +2065,7 @@ void EditorInspectorArray::_setup() { ae.panel = memnew(PanelContainer); ae.panel->set_focus_mode(FOCUS_ALL); ae.panel->set_mouse_filter(MOUSE_FILTER_PASS); - ae.panel->set_drag_forwarding(this); + ae.panel->set_drag_forwarding_compat(this); ae.panel->set_meta("index", begin_array_index + i); ae.panel->set_tooltip_text(vformat(TTR("Element %d: %s%d*"), i, array_element_prefix, i)); ae.panel->connect("focus_entered", callable_mp((CanvasItem *)ae.panel, &PanelContainer::queue_redraw)); diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index 7aa050227d8..8ef394a59f2 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -569,7 +569,7 @@ EditorPropertyPath::EditorPropertyPath() { HBoxContainer *path_hb = memnew(HBoxContainer); add_child(path_hb); path = memnew(LineEdit); - path->set_drag_forwarding(this); + path->set_drag_forwarding_compat(this); path->set_structured_text_bidi_override(TextServer::STRUCTURED_TEXT_FILE); path_hb->add_child(path); path->connect("text_submitted", callable_mp(this, &EditorPropertyPath::_path_selected)); @@ -3686,7 +3686,7 @@ EditorPropertyNodePath::EditorPropertyNodePath() { assign->set_h_size_flags(SIZE_EXPAND_FILL); assign->set_clip_text(true); assign->connect("pressed", callable_mp(this, &EditorPropertyNodePath::_node_assign)); - assign->set_drag_forwarding(this); + assign->set_drag_forwarding_compat(this); hbc->add_child(assign); clear = memnew(Button); diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp index 10f46283e6d..ed667aa7c85 100644 --- a/editor/editor_properties_array_dict.cpp +++ b/editor/editor_properties_array_dict.cpp @@ -715,7 +715,7 @@ EditorPropertyArray::EditorPropertyArray() { edit->set_clip_text(true); edit->connect("pressed", callable_mp(this, &EditorPropertyArray::_edit_pressed)); edit->set_toggle_mode(true); - edit->set_drag_forwarding(this); + edit->set_drag_forwarding_compat(this); edit->connect("draw", callable_mp(this, &EditorPropertyArray::_button_draw)); add_child(edit); add_focusable(edit); diff --git a/editor/editor_resource_picker.cpp b/editor/editor_resource_picker.cpp index 94152dfd494..6b733e11f73 100644 --- a/editor/editor_resource_picker.cpp +++ b/editor/editor_resource_picker.cpp @@ -950,7 +950,7 @@ EditorResourcePicker::EditorResourcePicker(bool p_hide_assign_button_controls) { assign_button->set_flat(true); assign_button->set_h_size_flags(SIZE_EXPAND_FILL); assign_button->set_clip_text(true); - assign_button->set_drag_forwarding(this); + assign_button->set_drag_forwarding_compat(this); add_child(assign_button); assign_button->connect("pressed", callable_mp(this, &EditorResourcePicker::_resource_selected)); assign_button->connect("draw", callable_mp(this, &EditorResourcePicker::_button_draw)); diff --git a/editor/editor_settings_dialog.cpp b/editor/editor_settings_dialog.cpp index 5985af21cd1..2881302775f 100644 --- a/editor/editor_settings_dialog.cpp +++ b/editor/editor_settings_dialog.cpp @@ -793,7 +793,7 @@ EditorSettingsDialog::EditorSettingsDialog() { shortcuts->connect("item_activated", callable_mp(this, &EditorSettingsDialog::_shortcut_cell_double_clicked)); tab_shortcuts->add_child(shortcuts); - shortcuts->set_drag_forwarding(this); + shortcuts->set_drag_forwarding_compat(this); // Adding event dialog shortcut_editor = memnew(InputEventConfigurationDialog); diff --git a/editor/export/project_export.cpp b/editor/export/project_export.cpp index 3e06633cc89..df5d2dcd297 100644 --- a/editor/export/project_export.cpp +++ b/editor/export/project_export.cpp @@ -1023,7 +1023,7 @@ ProjectExportDialog::ProjectExportDialog() { mc->set_v_size_flags(Control::SIZE_EXPAND_FILL); presets = memnew(ItemList); // TODO: Must reimplement drag forwarding. - //presets->set_drag_forwarding(this); + //presets->set_drag_forwarding_compat(this); mc->add_child(presets); presets->connect("item_selected", callable_mp(this, &ProjectExportDialog::_edit_preset)); duplicate_preset = memnew(Button); diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index e66be6ce493..8306723f5cf 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -3116,7 +3116,7 @@ FileSystemDock::FileSystemDock() { tree = memnew(Tree); tree->set_hide_root(true); - tree->set_drag_forwarding(this); + tree->set_drag_forwarding_compat(this); tree->set_allow_rmb_select(true); tree->set_select_mode(Tree::SELECT_MULTI); tree->set_custom_minimum_size(Size2(0, 15 * EDSCALE)); @@ -3153,7 +3153,7 @@ FileSystemDock::FileSystemDock() { files = memnew(ItemList); files->set_v_size_flags(SIZE_EXPAND_FILL); files->set_select_mode(ItemList::SELECT_MULTI); - files->set_drag_forwarding(this); + files->set_drag_forwarding_compat(this); files->connect("item_clicked", callable_mp(this, &FileSystemDock::_file_list_item_clicked)); files->connect("gui_input", callable_mp(this, &FileSystemDock::_file_list_gui_input)); files->connect("multi_selected", callable_mp(this, &FileSystemDock::_file_multi_selected)); diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 942b6b51cf0..4fe1a6c0343 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -4921,7 +4921,7 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, int p c->add_child(viewport); surface = memnew(Control); - surface->set_drag_forwarding(this); + surface->set_drag_forwarding_compat(this); add_child(surface); surface->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); surface->set_clip_contents(true); diff --git a/editor/plugins/resource_preloader_editor_plugin.cpp b/editor/plugins/resource_preloader_editor_plugin.cpp index 27cad1cb7e1..2a5529e229d 100644 --- a/editor/plugins/resource_preloader_editor_plugin.cpp +++ b/editor/plugins/resource_preloader_editor_plugin.cpp @@ -379,7 +379,7 @@ ResourcePreloaderEditor::ResourcePreloaderEditor() { tree->set_column_expand(1, true); tree->set_v_size_flags(SIZE_EXPAND_FILL); - tree->set_drag_forwarding(this); + tree->set_drag_forwarding_compat(this); vbc->add_child(tree); dialog = memnew(AcceptDialog); diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index a23874ea053..caa42b677c4 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -3669,7 +3669,7 @@ ScriptEditor::ScriptEditor() { _sort_list_on_update = true; script_list->connect("item_clicked", callable_mp(this, &ScriptEditor::_script_list_clicked), CONNECT_DEFERRED); script_list->set_allow_rmb_select(true); - script_list->set_drag_forwarding(this); + script_list->set_drag_forwarding_compat(this); context_menu = memnew(PopupMenu); add_child(context_menu); diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index 9406701ade8..4d525cc5a96 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -2167,7 +2167,7 @@ ScriptTextEditor::ScriptTextEditor() { connection_info_dialog = memnew(ConnectionInfoDialog); - code_editor->get_text_editor()->set_drag_forwarding(this); + code_editor->get_text_editor()->set_drag_forwarding_compat(this); } ScriptTextEditor::~ScriptTextEditor() { diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp index da6a1ea0af5..a822584619d 100644 --- a/editor/plugins/shader_editor_plugin.cpp +++ b/editor/plugins/shader_editor_plugin.cpp @@ -451,7 +451,7 @@ ShaderEditorPlugin::ShaderEditorPlugin() { vb->add_child(shader_list); shader_list->connect("item_selected", callable_mp(this, &ShaderEditorPlugin::_shader_selected)); shader_list->connect("item_clicked", callable_mp(this, &ShaderEditorPlugin::_shader_list_clicked)); - shader_list->set_drag_forwarding(this); + shader_list->set_drag_forwarding_compat(this); main_split->add_child(vb); vb->set_custom_minimum_size(Size2(200, 300) * EDSCALE); diff --git a/editor/plugins/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp index 0c8fc08795b..956150ec698 100644 --- a/editor/plugins/skeleton_3d_editor_plugin.cpp +++ b/editor/plugins/skeleton_3d_editor_plugin.cpp @@ -813,7 +813,7 @@ void Skeleton3DEditor::create_editors() { joint_tree->set_v_size_flags(SIZE_EXPAND_FILL); joint_tree->set_h_size_flags(SIZE_EXPAND_FILL); joint_tree->set_allow_rmb_select(true); - joint_tree->set_drag_forwarding(this); + joint_tree->set_drag_forwarding_compat(this); s_con->add_child(joint_tree); pose_editor = memnew(BoneTransformEditor(skeleton)); diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp index 66892372cf2..7603a5e55d2 100644 --- a/editor/plugins/sprite_frames_editor_plugin.cpp +++ b/editor/plugins/sprite_frames_editor_plugin.cpp @@ -1408,7 +1408,7 @@ SpriteFramesEditor::SpriteFramesEditor() { frame_list->set_max_columns(0); frame_list->set_icon_mode(ItemList::ICON_MODE_TOP); frame_list->set_max_text_lines(2); - frame_list->set_drag_forwarding(this); + frame_list->set_drag_forwarding_compat(this); frame_list->connect("gui_input", callable_mp(this, &SpriteFramesEditor::_frame_list_gui_input)); frame_list->connect("item_selected", callable_mp(this, &SpriteFramesEditor::_frame_list_item_selected)); diff --git a/editor/plugins/text_editor.cpp b/editor/plugins/text_editor.cpp index f3f0542b9b2..ad5881c76f6 100644 --- a/editor/plugins/text_editor.cpp +++ b/editor/plugins/text_editor.cpp @@ -650,7 +650,7 @@ TextEditor::TextEditor() { goto_line_dialog = memnew(GotoLineDialog); add_child(goto_line_dialog); - code_editor->get_text_editor()->set_drag_forwarding(this); + code_editor->get_text_editor()->set_drag_forwarding_compat(this); } TextEditor::~TextEditor() { diff --git a/editor/plugins/tiles/tile_map_editor.cpp b/editor/plugins/tiles/tile_map_editor.cpp index e7dc5d825b4..dd4daa45b7c 100644 --- a/editor/plugins/tiles/tile_map_editor.cpp +++ b/editor/plugins/tiles/tile_map_editor.cpp @@ -2236,7 +2236,7 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() { scene_tiles_list = memnew(ItemList); scene_tiles_list->set_h_size_flags(Control::SIZE_EXPAND_FILL); scene_tiles_list->set_v_size_flags(Control::SIZE_EXPAND_FILL); - scene_tiles_list->set_drag_forwarding(this); + scene_tiles_list->set_drag_forwarding_compat(this); scene_tiles_list->set_select_mode(ItemList::SELECT_MULTI); scene_tiles_list->connect("multi_selected", callable_mp(this, &TileMapEditorTilesPlugin::_scenes_list_multi_selected)); scene_tiles_list->connect("empty_clicked", callable_mp(this, &TileMapEditorTilesPlugin::_scenes_list_lmb_empty_clicked)); diff --git a/editor/plugins/tiles/tile_set_editor.cpp b/editor/plugins/tiles/tile_set_editor.cpp index d269a7c0ecc..b44cb18dc71 100644 --- a/editor/plugins/tiles/tile_set_editor.cpp +++ b/editor/plugins/tiles/tile_set_editor.cpp @@ -728,7 +728,7 @@ TileSetEditor::TileSetEditor() { sources_list->add_user_signal(MethodInfo("sort_request")); sources_list->connect("sort_request", callable_mp(this, &TileSetEditor::_update_sources_list).bind(-1)); sources_list->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST); - sources_list->set_drag_forwarding(this); + sources_list->set_drag_forwarding_compat(this); split_container_left_side->add_child(sources_list); HBoxContainer *sources_bottom_actions = memnew(HBoxContainer); diff --git a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp index 5af338caa07..0ff87886265 100644 --- a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp +++ b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp @@ -509,7 +509,7 @@ TileSetScenesCollectionSourceEditor::TileSetScenesCollectionSourceEditor() { scene_tiles_list = memnew(ItemList); scene_tiles_list->set_h_size_flags(SIZE_EXPAND_FILL); scene_tiles_list->set_v_size_flags(SIZE_EXPAND_FILL); - scene_tiles_list->set_drag_forwarding(this); + scene_tiles_list->set_drag_forwarding_compat(this); scene_tiles_list->connect("item_selected", callable_mp(this, &TileSetScenesCollectionSourceEditor::_update_tile_inspector).unbind(1)); scene_tiles_list->connect("item_selected", callable_mp(this, &TileSetScenesCollectionSourceEditor::_update_action_buttons).unbind(1)); scene_tiles_list->connect("item_activated", callable_mp(this, &TileSetScenesCollectionSourceEditor::_scenes_list_item_activated)); diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index 4cf397ffd0b..46ec3bcdd10 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -4915,7 +4915,7 @@ VisualShaderEditor::VisualShaderEditor() { graph->set_h_size_flags(SIZE_EXPAND_FILL); graph->set_show_zoom_label(true); add_child(graph); - graph->set_drag_forwarding(this); + graph->set_drag_forwarding_compat(this); float graph_minimap_opacity = EDITOR_GET("editors/visual_editors/minimap_opacity"); graph->set_minimap_opacity(graph_minimap_opacity); float graph_lines_curvature = EDITOR_GET("editors/visual_editors/lines_curvature"); @@ -5146,7 +5146,7 @@ VisualShaderEditor::VisualShaderEditor() { members = memnew(Tree); members_vb->add_child(members); - members->set_drag_forwarding(this); + members->set_drag_forwarding_compat(this); members->set_h_size_flags(SIZE_EXPAND_FILL); members->set_v_size_flags(SIZE_EXPAND_FILL); members->set_hide_root(true); diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp index dad584ea921..2f50172f54a 100644 --- a/editor/scene_tree_editor.cpp +++ b/editor/scene_tree_editor.cpp @@ -1415,7 +1415,7 @@ SceneTreeEditor::SceneTreeEditor(bool p_label, bool p_can_rename, bool p_can_ope add_child(tree); - tree->set_drag_forwarding(this); + tree->set_drag_forwarding_compat(this); if (p_can_rename) { tree->set_allow_rmb_select(true); tree->connect("item_mouse_selected", callable_mp(this, &SceneTreeEditor::_rmb_select)); diff --git a/modules/multiplayer/editor/replication_editor.cpp b/modules/multiplayer/editor/replication_editor.cpp index dbf1eecf0ed..4ab41cfcb07 100644 --- a/modules/multiplayer/editor/replication_editor.cpp +++ b/modules/multiplayer/editor/replication_editor.cpp @@ -250,7 +250,7 @@ ReplicationEditor::ReplicationEditor() { tree->add_child(drop_label); drop_label->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); - tree->set_drag_forwarding(this); + tree->set_drag_forwarding_compat(this); } void ReplicationEditor::_bind_methods() { diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index 944363bcb0c..b5846cb6923 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -642,7 +642,7 @@ inline int ColorPicker::_get_preset_size() { void ColorPicker::_add_preset_button(int p_size, const Color &p_color) { ColorPresetButton *btn_preset_new = memnew(ColorPresetButton(p_color, p_size)); btn_preset_new->set_tooltip_text(vformat(RTR("Color: #%s\nLMB: Apply color\nRMB: Remove preset"), p_color.to_html(p_color.a < 1))); - btn_preset_new->set_drag_forwarding(this); + btn_preset_new->set_drag_forwarding_compat(this); btn_preset_new->set_button_group(preset_group); preset_container->add_child(btn_preset_new); btn_preset_new->set_pressed(true); diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 8460728448a..6e85ae5c0eb 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -1813,33 +1813,53 @@ bool Control::is_focus_owner_in_shortcut_context() const { // Drag and drop handling. -void Control::set_drag_forwarding(Object *p_target) { - if (p_target) { - data.drag_owner = p_target->get_instance_id(); +void Control::set_drag_forwarding_compat(Object *p_base) { + if (p_base != nullptr) { + data.forward_drag = Callable(p_base, "_get_drag_data_fw").bind(this); + data.forward_can_drop = Callable(p_base, "_can_drop_data_fw").bind(this); + data.forward_drop = Callable(p_base, "_drop_data_fw").bind(this); + } else { - data.drag_owner = ObjectID(); + data.forward_drag = Callable(); + data.forward_can_drop = Callable(); + data.forward_drop = Callable(); } } +void Control::set_drag_forwarding(const Callable &p_drag, const Callable &p_can_drop, const Callable &p_drop) { + data.forward_drag = p_drag; + data.forward_can_drop = p_can_drop; + data.forward_drop = p_drop; +} + Variant Control::get_drag_data(const Point2 &p_point) { - if (data.drag_owner.is_valid()) { - Object *obj = ObjectDB::get_instance(data.drag_owner); - if (obj) { - return obj->call("_get_drag_data_fw", p_point, this); + Variant ret; + if (data.forward_drag.is_valid()) { + Variant p = p_point; + const Variant *vp[1] = { &p }; + Callable::CallError ce; + data.forward_drag.callp((const Variant **)vp, 1, ret, ce); + if (ce.error != Callable::CallError::CALL_OK) { + ERR_FAIL_V_MSG(Variant(), "Error calling forwarded method from 'get_drag_data': " + Variant::get_callable_error_text(data.forward_drag, (const Variant **)vp, 1, ce) + "."); } + return ret; } - Variant dd; - GDVIRTUAL_CALL(_get_drag_data, p_point, dd); - return dd; + GDVIRTUAL_CALL(_get_drag_data, p_point, ret); + return ret; } bool Control::can_drop_data(const Point2 &p_point, const Variant &p_data) const { - if (data.drag_owner.is_valid()) { - Object *obj = ObjectDB::get_instance(data.drag_owner); - if (obj) { - return obj->call("_can_drop_data_fw", p_point, p_data, this); + if (data.forward_can_drop.is_valid()) { + Variant ret; + Variant p = p_point; + const Variant *vp[2] = { &p, &p_data }; + Callable::CallError ce; + data.forward_can_drop.callp((const Variant **)vp, 2, ret, ce); + if (ce.error != Callable::CallError::CALL_OK) { + ERR_FAIL_V_MSG(Variant(), "Error calling forwarded method from 'can_drop_data': " + Variant::get_callable_error_text(data.forward_can_drop, (const Variant **)vp, 2, ce) + "."); } + return ret; } bool ret = false; @@ -1848,12 +1868,16 @@ bool Control::can_drop_data(const Point2 &p_point, const Variant &p_data) const } void Control::drop_data(const Point2 &p_point, const Variant &p_data) { - if (data.drag_owner.is_valid()) { - Object *obj = ObjectDB::get_instance(data.drag_owner); - if (obj) { - obj->call("_drop_data_fw", p_point, p_data, this); - return; + if (data.forward_drop.is_valid()) { + Variant ret; + Variant p = p_point; + const Variant *vp[2] = { &p, &p_data }; + Callable::CallError ce; + data.forward_drop.callp((const Variant **)vp, 2, ret, ce); + if (ce.error != Callable::CallError::CALL_OK) { + ERR_FAIL_MSG("Error calling forwarded method from 'drop_data': " + Variant::get_callable_error_text(data.forward_drop, (const Variant **)vp, 2, ce) + "."); } + return; } GDVIRTUAL_CALL(_drop_data, p_point, p_data); @@ -3189,7 +3213,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_forwarding", "drag_func", "can_drop_func", "drop_func"), &Control::set_drag_forwarding); ClassDB::bind_method(D_METHOD("set_drag_preview", "control"), &Control::set_drag_preview); ClassDB::bind_method(D_METHOD("is_drag_successful"), &Control::is_drag_successful); diff --git a/scene/gui/control.h b/scene/gui/control.h index 9705dd62db6..52efe42bd56 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -168,7 +168,9 @@ private: Control *parent_control = nullptr; Window *parent_window = nullptr; CanvasItem *parent_canvas_item = nullptr; - ObjectID drag_owner; + Callable forward_drag; + Callable forward_can_drop; + Callable forward_drop; // Positioning and sizing. @@ -499,7 +501,8 @@ public: // Drag and drop handling. - virtual void set_drag_forwarding(Object *p_target); + virtual void set_drag_forwarding(const Callable &p_drag, const Callable &p_can_drop, const Callable &p_drop); + virtual void set_drag_forwarding_compat(Object *p_base); 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); diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp index cd1ebba5d1d..3457cfa94f8 100644 --- a/scene/gui/tab_container.cpp +++ b/scene/gui/tab_container.cpp @@ -975,7 +975,7 @@ void TabContainer::_bind_methods() { TabContainer::TabContainer() { tab_bar = memnew(TabBar); - tab_bar->set_drag_forwarding(this); + tab_bar->set_drag_forwarding_compat(this); add_child(tab_bar, false, INTERNAL_MODE_FRONT); tab_bar->set_anchors_and_offsets_preset(Control::PRESET_TOP_WIDE); tab_bar->connect("tab_changed", callable_mp(this, &TabContainer::_on_tab_changed));