Skip to content

Commit 41448eb

Browse files
committed
feat(ui): drag-and-drop assets/files into the chat input
1 parent dc2f701 commit 41448eb

2 files changed

Lines changed: 85 additions & 0 deletions

File tree

unreal/HaybaMCPToolkit/Source/HaybaMCPToolkit/Private/HaybaMCPChatPanel.cpp

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@
3131
#include "Widgets/Notifications/SNotificationList.h"
3232

3333
#include "HAL/PlatformApplicationMisc.h"
34+
#include "DragAndDrop/AssetDragDropOp.h"
35+
#include "Input/DragAndDrop.h" // FExternalDragOperation (SlateCore)
36+
#include "AssetRegistry/AssetData.h"
3437
#include "Json.h"
3538
#include "JsonUtilities.h"
3639
#include "Editor.h"
@@ -478,6 +481,78 @@ FReply SHaybaMCPChatPanel::OnPromptCardClicked(FString Prompt)
478481
return FReply::Handled();
479482
}
480483

484+
// ── Drag-and-drop into the input (assets + external files) ────────────────
485+
486+
bool SHaybaMCPChatPanel::AppendToInput(const FString& Addition)
487+
{
488+
if (!InputBox.IsValid() || Addition.IsEmpty()) return false;
489+
490+
FString Existing = InputBox->GetText().ToString();
491+
// Space-separate from prior content; if the box already ends in whitespace
492+
// (or is empty) don't inject a redundant leading space.
493+
if (!Existing.IsEmpty() && !FChar::IsWhitespace(Existing[Existing.Len() - 1]))
494+
{
495+
Existing += TEXT(" ");
496+
}
497+
Existing += Addition;
498+
499+
InputBox->SetText(FText::FromString(Existing));
500+
if (FSlateApplication::IsInitialized())
501+
{
502+
FSlateApplication::Get().SetKeyboardFocus(InputBox);
503+
}
504+
return true;
505+
}
506+
507+
FReply SHaybaMCPChatPanel::OnDragOver(const FGeometry& /*MyGeometry*/, const FDragDropEvent& DragDropEvent)
508+
{
509+
// Show the droppable cursor for payloads we know how to consume.
510+
if (DragDropEvent.GetOperationAs<FAssetDragDropOp>().IsValid() ||
511+
DragDropEvent.GetOperationAs<FExternalDragOperation>().IsValid())
512+
{
513+
return FReply::Handled();
514+
}
515+
return FReply::Unhandled();
516+
}
517+
518+
FReply SHaybaMCPChatPanel::OnDrop(const FGeometry& /*MyGeometry*/, const FDragDropEvent& DragDropEvent)
519+
{
520+
TArray<FString> Refs;
521+
522+
// 1) Content Browser assets — append each asset's object path
523+
// (e.g. /Game/Path/Asset.Asset) so the reference is unambiguous.
524+
if (TSharedPtr<FAssetDragDropOp> AssetOp = DragDropEvent.GetOperationAs<FAssetDragDropOp>())
525+
{
526+
for (const FAssetData& Asset : AssetOp->GetAssets())
527+
{
528+
const FString ObjectPath = Asset.GetObjectPathString();
529+
if (!ObjectPath.IsEmpty()) Refs.Add(ObjectPath);
530+
}
531+
}
532+
// 2) External files dragged from the OS file explorer.
533+
else if (TSharedPtr<FExternalDragOperation> ExtOp = DragDropEvent.GetOperationAs<FExternalDragOperation>())
534+
{
535+
if (ExtOp->HasFiles())
536+
{
537+
for (const FString& File : ExtOp->GetFiles())
538+
{
539+
if (!File.IsEmpty()) Refs.Add(File);
540+
}
541+
}
542+
}
543+
544+
if (Refs.Num() == 0) return FReply::Unhandled();
545+
546+
const bool bAppended = AppendToInput(FString::Join(Refs, TEXT(" ")));
547+
if (bAppended)
548+
{
549+
Toast(FText::Format(
550+
LOCTEXT("DropAppended", "Added {0} reference(s) to the message."),
551+
FText::AsNumber(Refs.Num())));
552+
}
553+
return FReply::Handled();
554+
}
555+
481556
// ── Message row (Q5-a flat + Q12-c copy on hover + right-click) ──────────
482557

483558
TSharedRef<SWidget> SHaybaMCPChatPanel::BuildMessageRow(const FHaybaMCPChatMessage& Msg, int32 MessageIndex)

unreal/HaybaMCPToolkit/Source/HaybaMCPToolkit/Private/HaybaMCPChatPanel.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,17 @@ class SHaybaMCPChatPanel : public SCompoundWidget
4141
// cannot touch freed Slate widgets.
4242
virtual ~SHaybaMCPChatPanel() override;
4343

44+
// ── Drag-and-drop into the chat input ────────────────────────────────────
45+
// Accept Content Browser assets (FAssetDragDropOp) and external files
46+
// (FExternalDragOperation); on drop, append their paths to InputBox.
47+
virtual FReply OnDragOver(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent) override;
48+
virtual FReply OnDrop(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent) override;
49+
4450
private:
51+
// Append `Addition` to InputBox, space-separating from any existing text,
52+
// then focus the input. Returns true if anything was appended.
53+
bool AppendToInput(const FString& Addition);
54+
4555
FHaybaMCPModule* Module = nullptr;
4656
SHaybaMCPMainPanel* MainPanel = nullptr;
4757

0 commit comments

Comments
 (0)