PySide6からビューポートへのドラッグ&ドロップがUE5.7で動作しなくなった(5.6では動作)

PySide6で作成したカスタムツールから、ビューポートへのドラッグ&ドロップでアセットを配置する機能が、

UE5.7以降で正常に動作しなくなりました。

## 再現手順

添付のPythonスクリプトを実行すると、問題を確認できます。

1. スクリプトを実行してウィンドウを表示

2. リスト内のアセット(Cube, Cone)を選択

3. ビューポートにドラッグ&ドロップを試みる

質問したい内容は以下のとおりです。

  1. UE5.7でドラッグ&ドロップの仕様が変更されましたか?
  2. 外部Qtウィジェットからのドロップを受け付けるための新しい方法はありますか?
  3. 使用すべき正しいMIMEタイプやフォーマットはありますか?
  4. この問題は既知のバグでしょうか?修正予定はありますか?

よろしくお願いします。

import unreal
import sys
from PySide6.QtWidgets import QWidget, QVBoxLayout, QListWidget, QListWidgetItem, QLabel
from PySide6.QtCore import Qt, QMimeData
from PySide6.QtGui import QDrag
from PySide6.QtWidgets import QApplication
 
 
class SimpleDragDropWidget(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("UE D&D Sample (UE5.6で動作)")
        self.setGeometry(200, 200, 400, 300)
        
        # 常に最前面に表示
        self.setWindowFlags(Qt.Window | Qt.WindowStaysOnTopHint)
        
        layout = QVBoxLayout()
        
        # 説明ラベル
        info = QLabel("リスト内のアセットをビューポートにD&Dしてください")
        layout.addWidget(info)
        
        # アセットリスト
        self.list_widget = QListWidget()
        self.list_widget.setDragEnabled(True)
        self.list_widget.setSelectionMode(QListWidget.SingleSelection)
        
        test_assets = [
            '/Engine/BasicShapes/Cube.Cube',
            '/Engine/BasicShapes/Cone.Cone'
        ]
        
        for asset_path in test_assets:
            item = QListWidgetItem(asset_path)
            item.setData(Qt.UserRole, asset_path)  # アセットパスを保存
            self.list_widget.addItem(item)
        
        # カスタムリストウィジェットに差し替え
        self.list_widget.startDrag = lambda actions: self.custom_start_drag(self.list_widget, actions)
        
        layout.addWidget(self.list_widget)
        self.setLayout(layout)
    
    def custom_start_drag(self, list_widget, supported_actions):
        current_item = list_widget.currentItem()
        if not current_item:
            return
        
        asset_path = current_item.data(Qt.UserRole)
        
        # MIMEデータにアセットパスを設定
        mime_data = QMimeData()
        mime_data.setText(asset_path)  # シンプルにテキストとして設定
        
        # ドラッグオブジェクト作成
        drag = QDrag(list_widget)
        drag.setMimeData(mime_data)
        
        # ドラッグ実行
        result = drag.exec(Qt.CopyAction | Qt.MoveAction)
        
        if result == Qt.CopyAction:
            print(f"[成功] UEにドロップ完了: {asset_path}")
        else:
            print(f"[キャンセル] D&Dがキャンセルされました")
 
 
def run_sample():
    global sample_widget
    app = None
    if not QApplication.instance():
        app = QApplication(sys.argv)    
    sample_widget = SimpleDragDropWidget()
    sample_widget.show()
    return sample_widget
 
 
if __name__ == "__main__":
    widget = run_sample()

[Attachment Removed]

再現用のスクリプトのご用意ありがとうございます。問題を再現することが出来ました。

本件を​ UE-364137 Drag and drop does not work from a window created with PySide としてバグ登録いたしました。

UE5.7ではドラッグを行った際にIgnoreActionがUE側から帰ってきてしまっておりドラッグアンドドロップが無効化されています​。

原因としてはドラッグ中に内部のカーソル情報が更新されないことによって、

FSlateApplication::OnDragOver関数内でResult = EDropEffect::Copyが処理されないことによって発生しています。

WindowsCursor.cppのGetPosition関数をUE5.6相当に修正することで改善が見られました。​

FVector2D FWindowsCursor::GetPosition() const
{
	POINT OutCursorPos;
//	if (!FWindowsApplication::StaticGetCursorPosition(OutCursorPos))  //この行をコメントアウトしてUE5.6互換の動作にする
	{
		::GetCursorPos(&OutCursorPos);
	}
 
	return FVector2D(OutCursorPos.x, OutCursorPos.y);
}

​こちらを適用して改善がみられるか確認していただけますでしょうか。

[Attachment Removed]

意図通りの動作を得られました!

大変助かりました。ありがとうございます。本件クローズでお願いします!

[Attachment Removed]