Yes,
If you don´t know how to start a D&D, here is a short example of my Inventory System:
This Drag Detected should be located in your OnMouseButtonDown Function Override of your UI Slots / Card / Icon…etc.
Edit:
You see, i don´t use hardcoded Key bindings here… I just ask for Keys of the Player Input Settings (ProjectPreferences Input). “Select” is my LeftMouse per Default… but can be Changed via User Settings at any Time.
Here, in the OnDragDetected Function override, you create a Widget as Placeholder, that is automatically attached to your Cursor.
Important:
As DragOperation Class, you need to create yourself a custom one, that holds the Class of the Actor you want to spawn, as exposed Variables.
Like my Quantity, Index, SourceType and Name. See:
You now want to call yozur PlayerController and switch on a Bool, called “SpawnDragEnable” and set a Class Reference called “SpawnActorClass”.
Best in a Function of the PlayerController
Back to your OnDragDetected of your Widget, right after you set the Drag Operation, just call that Function in your Player Controller.
The class should be the Actor class, you want to Spawn later.
Since you want a Tick in your PlayerController, you simply add a Bool to check the true state of SpawnDragEnable, and spawn the Actor you want. In my following Screenshot, i spawn this actor one time only and just replace it on a grid. I set an Actor reference as Variable for that:
Nvm the Tick Graph… i use to put the Tick Events in a standalone Graph of the BPs.
So… you now want to get the Mouse Position in your Viewport. Here is my little function for that:
This allows you to get the Mouse Position in Viewport, scaled by the Viewport Scale if wanted. Since you by default want it scaled, just set the Default Value of the Input “scaled” as true.
Set this function as “Pure”, since it needs no Execution Input.
Drag thet function into your Tick.
You now want to define the Gridposition, based on the Cursor Position.
Since the Mouse is workin inside the Viewport and not the World, convert the Viewport Location to World Location. first.
Use the “DeprojectScreenToWorld” for that.
You now got the World Location under your Cursor. whats next?
Tiling!
Here is a simple pseudo Math for that… you, so i think, can convert it to BP Nodes:
// Get the Tile Position floored
xPos = floor(Mouse.x / TileSize.x);
yPos = floor(Mouse.y / TileSize.y);
// Multiply this by TileSize again, to get World Location
xPos = xPos * TileSize.x;
yPos = yPos * TileSize.y;
// Now add an offset to place the Actor in the Center of the Tile.
Offset = Vector2(TileSize.x/2, TileSize.y/2);
xPos = xPos += Offset.x;
yPos = yPos += Offset.y;
After that, xPos and yPos are your Actor Location in the World. Before that, store the Location in a Variable (StoredLocation here)
F.e.:
Last Step… you want to place the actor fixed in the world.
In your Widget, add an override of the OnDrop Event.
Call your PlayerController again.
In your Player Controller, add a function to actually place this Actor on the Grid… call it from your Widget:
That is all… just a small example… perhaps needs some tweaking…
Edit:
If OnDrop is not working… perhaps cause you not drop on a Widget… Try OnDragCancelled