DragDropHandler.cpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. // Copyright 2017-2021 marynate. All Rights Reserved.
  2. #include "DragDropHandler.h"
  3. #include "ExtContentBrowserUtils.h"
  4. #include "Layout/WidgetPath.h"
  5. #include "Framework/Application/MenuStack.h"
  6. #include "Framework/Application/SlateApplication.h"
  7. #include "Textures/SlateIcon.h"
  8. #include "Framework/Commands/UIAction.h"
  9. #include "Framework/MultiBox/MultiBoxBuilder.h"
  10. #include "EditorStyleSet.h"
  11. #include "DragAndDrop/AssetDragDropOp.h"
  12. #define LOCTEXT_NAMESPACE "ExtContentBrowser"
  13. bool DragDropHandler::ValidateDragDropOnAssetFolder(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent, const FString& TargetPath, bool& OutIsKnownDragOperation)
  14. {
  15. OutIsKnownDragOperation = false;
  16. TSharedPtr<FDragDropOperation> Operation = DragDropEvent.GetOperation();
  17. if (!Operation.IsValid())
  18. {
  19. return false;
  20. }
  21. bool bIsValidDrag = false;
  22. TOptional<EMouseCursor::Type> NewDragCursor;
  23. const bool bIsAssetPath = !ExtContentBrowserUtils::IsClassPath(TargetPath);
  24. if (Operation->IsOfType<FAssetDragDropOp>())
  25. {
  26. TSharedPtr<FAssetDragDropOp> DragDropOp = StaticCastSharedPtr<FAssetDragDropOp>(Operation);
  27. const TArray<FAssetData>& DroppedAssets = DragDropOp->GetAssets();
  28. const TArray<FString>& DroppedAssetPaths = DragDropOp->GetAssetPaths();
  29. OutIsKnownDragOperation = true;
  30. int32 NumAssetItems, NumClassItems;
  31. ExtContentBrowserUtils::CountItemTypes(DroppedAssets, NumAssetItems, NumClassItems);
  32. int32 NumAssetPaths, NumClassPaths;
  33. ExtContentBrowserUtils::CountPathTypes(DroppedAssetPaths, NumAssetPaths, NumClassPaths);
  34. if (DroppedAssetPaths.Num() == 1 && DroppedAssetPaths[0] == TargetPath)
  35. {
  36. DragDropOp->SetToolTip(LOCTEXT("OnDragFoldersOverFolder_CannotSelfDrop", "Cannot move or copy a folder onto itself"), FAppStyle::GetBrush(TEXT("Graph.ConnectorFeedback.Error")));
  37. }
  38. else if (bIsAssetPath)
  39. {
  40. const int32 TotalAssetDropItems = NumAssetItems + NumAssetPaths;
  41. const int32 TotalClassDropItems = NumClassItems + NumClassPaths;
  42. if (TotalAssetDropItems > 0)
  43. {
  44. bIsValidDrag = true;
  45. const FText FirstItemText = DroppedAssets.Num() > 0 ? FText::FromName(DroppedAssets[0].AssetName) : FText::FromString(DroppedAssetPaths[0]);
  46. const FText MoveOrCopyText = (TotalAssetDropItems > 1)
  47. ? FText::Format(LOCTEXT("OnDragAssetsOverFolder_MultipleAssetItems", "Move or copy '{0}' and {1} {1}|plural(one=other,other=others)"), FirstItemText, TotalAssetDropItems - 1)
  48. : FText::Format(LOCTEXT("OnDragAssetsOverFolder_SingularAssetItems", "Move or copy '{0}'"), FirstItemText);
  49. if (TotalClassDropItems > 0)
  50. {
  51. DragDropOp->SetToolTip(FText::Format(LOCTEXT("OnDragAssetsOverFolder_AssetAndClassItems", "{0}\n\n{1} C++ {1}|plural(one=item,other=items) will be ignored as they cannot be moved or copied"), MoveOrCopyText, NumClassItems), FAppStyle::GetBrush(TEXT("Graph.ConnectorFeedback.OKWarn")));
  52. }
  53. else
  54. {
  55. DragDropOp->SetToolTip(MoveOrCopyText, FAppStyle::GetBrush(TEXT("Graph.ConnectorFeedback.OK")));
  56. }
  57. }
  58. else if (TotalClassDropItems > 0)
  59. {
  60. DragDropOp->SetToolTip(LOCTEXT("OnDragAssetsOverFolder_OnlyClassItems", "C++ items cannot be moved or copied"), FAppStyle::GetBrush(TEXT("Graph.ConnectorFeedback.Error")));
  61. }
  62. }
  63. else
  64. {
  65. DragDropOp->SetToolTip(FText::Format(LOCTEXT("OnDragAssetsOverFolder_InvalidFolder", "'{0}' is not a valid place to drop assets or folders"), FText::FromString(TargetPath)), FAppStyle::GetBrush(TEXT("Graph.ConnectorFeedback.Error")));
  66. }
  67. }
  68. else if (Operation->IsOfType<FExternalDragOperation>())
  69. {
  70. TSharedPtr<FExternalDragOperation> DragDropOp = StaticCastSharedPtr<FExternalDragOperation>(Operation);
  71. OutIsKnownDragOperation = true;
  72. bIsValidDrag = DragDropOp->HasFiles() && bIsAssetPath;
  73. }
  74. // Set the default slashed circle if this drag is invalid and a drag operation hasn't set NewDragCursor to something custom
  75. if (!bIsValidDrag && !NewDragCursor.IsSet())
  76. {
  77. NewDragCursor = EMouseCursor::SlashedCircle;
  78. }
  79. Operation->SetCursorOverride(NewDragCursor);
  80. return bIsValidDrag;
  81. }
  82. void DragDropHandler::HandleDropOnAssetFolder(const TSharedRef<SWidget>& ParentWidget, const TArray<FAssetData>& AssetList, const TArray<FString>& AssetPaths, const FString& TargetPath, const FText& TargetDisplayName, FExecuteCopyOrMove CopyActionHandler, FExecuteCopyOrMove MoveActionHandler, FExecuteCopyOrMove AdvancedCopyActionHandler)
  83. {
  84. // Remove any classes from the asset list
  85. TArray<FAssetData> FinalAssetList = AssetList;
  86. FinalAssetList.RemoveAll([](const FAssetData& AssetData)
  87. {
  88. return AssetData.AssetClassPath == FTopLevelAssetPath(TEXT("/Script/CoreUObject"), NAME_Class);
  89. });
  90. // Remove any class paths from the list
  91. TArray<FString> FinalAssetPaths = AssetPaths;
  92. FinalAssetPaths.RemoveAll([](const FString& AssetPath)
  93. {
  94. return ExtContentBrowserUtils::IsClassPath(AssetPath);
  95. });
  96. FMenuBuilder MenuBuilder(/*bInShouldCloseWindowAfterMenuSelection=*/true, nullptr);
  97. const FText MoveCopyHeaderString = FText::Format(LOCTEXT("AssetViewDropMenuHeading", "Move/Copy to {0}"), TargetDisplayName);
  98. MenuBuilder.BeginSection("PathAssetMoveCopy", MoveCopyHeaderString);
  99. {
  100. MenuBuilder.AddMenuEntry(
  101. LOCTEXT("DragDropMove", "Move Here"),
  102. LOCTEXT("DragDropMoveTooltip", "Move the dragged items to this folder, preserving the structure of any copied folders."),
  103. FSlateIcon(),
  104. FUIAction(FExecuteAction::CreateLambda([=]() { MoveActionHandler.ExecuteIfBound(FinalAssetList, FinalAssetPaths, TargetPath); }))
  105. );
  106. MenuBuilder.AddMenuEntry(
  107. LOCTEXT("DragDropCopy", "Copy Here"),
  108. LOCTEXT("DragDropCopyTooltip", "Copy the dragged items to this folder, preserving the structure of any copied folders."),
  109. FSlateIcon(),
  110. FUIAction(FExecuteAction::CreateLambda([=]() { CopyActionHandler.ExecuteIfBound(FinalAssetList, FinalAssetPaths, TargetPath); }))
  111. );
  112. MenuBuilder.AddMenuEntry(
  113. LOCTEXT("DragDropAdvancedCopy", "Advanced Copy Here"),
  114. LOCTEXT("DragDropAdvancedCopyTooltip", "Copy the dragged items and any specified dependencies to this folder, afterwards fixing up any dependencies on copied files to the new files."),
  115. FSlateIcon(),
  116. FUIAction(FExecuteAction::CreateLambda([=]() { AdvancedCopyActionHandler.ExecuteIfBound(FinalAssetList, FinalAssetPaths, TargetPath); }))
  117. );
  118. }
  119. MenuBuilder.EndSection();
  120. FSlateApplication::Get().PushMenu(
  121. ParentWidget,
  122. FWidgetPath(),
  123. MenuBuilder.MakeWidget(),
  124. FSlateApplication::Get().GetCursorPos(),
  125. FPopupTransitionEffect(FPopupTransitionEffect::ContextMenu)
  126. );
  127. }
  128. void DragDropHandler::HandleDropOnAssetFolderOfContentBrowser(const TSharedRef<SWidget>& ParentWidget, const TArray<FExtAssetData>& AssetList, const TArray<FString>& AssetPaths, const FString& TargetPath, const FText& TargetDisplayName, FExecuteDropToImport ImportActionHandler, FExecuteDropToImport ImportFlatActionHandler)
  129. {
  130. // Remove any classes from the asset list
  131. TArray<FExtAssetData> FinalAssetList = AssetList;
  132. FinalAssetList.RemoveAll([](const FExtAssetData& AssetData)
  133. {
  134. //return AssetData.AssetClass == NAME_Class;
  135. return !AssetData.IsValid();
  136. });
  137. // Remove any class paths from the list
  138. TArray<FString> FinalAssetPaths = AssetPaths;
  139. #if ECB_LEGACY
  140. FinalAssetPaths.RemoveAll([](const FString& AssetPath)
  141. {
  142. return ExtContentBrowserUtils::IsClassPath(AssetPath);
  143. });
  144. #endif
  145. FMenuBuilder MenuBuilder(/*bInShouldCloseWindowAfterMenuSelection=*/true, nullptr);
  146. const FText FlatImportHeaderString = FText::Format(LOCTEXT("ExtAssetViewDropMenuHeadingFlatImport", "Flat Import to {0}"), TargetDisplayName);
  147. MenuBuilder.BeginSection("AssetFlatImport", FlatImportHeaderString);
  148. {
  149. MenuBuilder.AddMenuEntry(
  150. LOCTEXT("DragDropFlatImport", "Flat Import to Current Folder"),
  151. LOCTEXT("DragDropFlatImportTooltip", "Import selected uassets and collect all dependencies to current folder."),
  152. FSlateIcon(),
  153. FUIAction(FExecuteAction::CreateLambda([=]() { ImportFlatActionHandler.ExecuteIfBound(FinalAssetList, FinalAssetPaths, TargetPath); }))
  154. );
  155. }
  156. MenuBuilder.EndSection();
  157. const FText NormalImportHeaderString = FText::Format(LOCTEXT("ExtAssetViewDropMenuHeadingImport", "Import to Project"), TargetDisplayName);
  158. MenuBuilder.BeginSection("AssetImport", NormalImportHeaderString);
  159. {
  160. MenuBuilder.AddMenuEntry(
  161. LOCTEXT("DragDropImport", "Import to Current Project"),
  162. LOCTEXT("DragDropImportTooltip", "Import selected uassets to current project, keeping original asset paths."),
  163. FSlateIcon(),
  164. FUIAction(FExecuteAction::CreateLambda([=]() { ImportActionHandler.ExecuteIfBound(FinalAssetList, FinalAssetPaths, TargetPath); }))
  165. );
  166. }
  167. MenuBuilder.EndSection();
  168. FSlateApplication::Get().PushMenu(
  169. ParentWidget,
  170. FWidgetPath(),
  171. MenuBuilder.MakeWidget(),
  172. FSlateApplication::Get().GetCursorPos(),
  173. FPopupTransitionEffect(FPopupTransitionEffect::ContextMenu)
  174. );
  175. }
  176. #undef LOCTEXT_NAMESPACE