Game Development Community

Drag and drop built in to 1.7.1 woot

by Dave Young · in Torque Game Engine Advanced · 09/22/2008 (4:51 am) · 7 replies

I just about *always* use a heavily modified resource-based guiDragDropbutton control in my projects, for inventories, skills, stores, etc etc.

Imagine my pleasant surprise when looking through the new codebase to find that there is a very nice script based dragdrop and very flexible drag and drop solution now built right in. Maybe I missed it on some release notes or something, but I thought I would share a little bit about it. It looks like it's been in TGB for some time. It's used in the gui editor to make new gui controls but you can use it in your game to do TONS of handy gameplay functions.

The name of the GUI control is:
GuiDragAndDropControl

(You can find a nice working implementation in tools/guiEditor/gui/guiEditor.ed.cs.)

Basically, if your control implements these SCRIPT callbacks:
function MyControl::onControlDragged(%this, %payload, %position)
{
}

function MyControl::onControlDragEnter(%this, %payload, %position)
{
}

function MyControl::onControlDragExit(%this, %payload, %position)
{
}

function MyControl::onControlDropped(%this, %payload, %position)
{
}

It can respond to the drag event as a drop target as it happens. To make a drop source, you only need to make sure the control extends onMouseDragged with the appropriate script callback. Here's an example of a simple use which turns any control into a drag source, displaying a copy of the bitmap that was on the button as it is dragged

function guiBitmapButtonCtrl::onMouseDragged(%this)
{
  
   %position = %this.getGlobalPosition();
   %cursorpos = Canvas.getCursorPos();
   
    %payload = new GuiBitmapCtrl() {
            profile = "GuiDefaultProfile";
            horizSizing = "width";
            vertSizing = "height";
            position = "0 0";
            extent = "32 32";
            minExtent = "8 8";
            visible = "1";
            helpTag = "0";
            bitmap = %this.getBitmap();
            wrap = "0";
         };
      
   %xOffset = getWord(%payload.extent, 0) /2;
   %yOffset = getWord(%payload.extent, 1) / 2;
   
   // position where the drag will start, to prevent visible jumping. Down and to the right also
   %xPos = getWord(%cursorpos, 0) + 32; //%xOffset;
   %yPos = getWord(%cursorpos, 1) + 32; //%yOffset;
   
   //Now create the drag and drop control which will be deleted when mouse is up, delivering its payload
   %dragCtrl = new GuiDragAndDropControl() {
      canSaveDynamicFields = "0";
      Profile = "GuiDefaultProfile";
      HorizSizing = "right";
      VertSizing = "bottom";
      Position = %xPos SPC %yPos;
      extent = %payload.extent;
      MinExtent = "32 32";
      canSave = "1";
      Visible = "1";
      hovertime = "1000";
      deleteOnMouseUp = true;
   };

   %dragCtrl.add(%payload);
   Canvas.getContent().add(%dragCtrl);

   //We want the new dragdrop to be offset from the cursor   
   %dragCtrl.startDragging(%xOffset -32, %yOffset - 32);
}

To register this on my playgui, I just implemented the previously mentioned callbacks. I wanted drag and drop to give the mousedrag events to playgui so it could keep track of the current mouse over object as well, so I adjusted void GuiDragAndDropControl::onMouseDragged(const GuiEvent& event) to pump the onMouseDragged event to the current playgui. Now I can drag and drop onto an ingame inworld object as well as any GUI control.

Because the payload can be anything, you can set whatever dynamic fields you need in script to tell it that it's an inventory item, or a skill, or a healing potion.. whatever your needs are.

Just another little TGEA gem the GG boys cooked up for us, thanks!!

#1
09/22/2008 (7:32 am)
Thanks for posting this Dave.
#2
09/22/2008 (8:43 am)
Actually i think that new control along with many others came from the TGB tools team in developing the level builder. They added alot of new cool controls and features.
#3
09/22/2008 (9:14 am)
Definitely they did Tom! I'm uncovering more and more, I don't have a TGB background so I'm just now seeing the extra guiControls and finding application for others as well.
#4
08/30/2009 (1:17 am)
Any chance you can post a tutorial on this? I have tried it and still not getting it to work. I am trying to get a GuiObjectView as a source to drag a DTS object to the ingame world. I am happy to help however I can.

One issue is the GuiObjectView uses the mouse down to move the camera around inside the control.
#5
08/03/2010 (1:43 am)
Ok, what a pain in the butt to get working.... Just for others.. so they don't have to pull their hair out like I did, here is a complete gui .


//--- OBJECT WRITE BEGIN ---
%guiContent = new GuiControl(DragDropGui) {
position = "0 0";
extent = "1024 768";
minExtent = "8 8";
horizSizing = "right";
vertSizing = "bottom";
profile = "GuiDefaultProfile";
visible = "1";
active = "1";
tooltipProfile = "GuiToolTipProfile";
hovertime = "1000";
isContainer = "1";
canSave = "1";
canSaveDynamicFields = "1";
helpTag = "0";

new GuiBitmapCtrl(background) {
bitmap = "art/gui/inv/stone_back";
wrap = "0";
position = "156 84";
extent = "620 460";
minExtent = "8 2";
horizSizing = "right";
vertSizing = "bottom";
profile = "GuiDefaultProfile";
visible = "1";
active = "1";
tooltipProfile = "GuiToolTipProfile";
hovertime = "1000";
isContainer = "0";
canSave = "1";
canSaveDynamicFields = "0";
};
new GuiBitmapCtrl() {
bitmap = "art/gui/inv/tile.png";
wrap = "0";
position = "231 140";
extent = "64 64";
minExtent = "8 2";
horizSizing = "right";
vertSizing = "bottom";
profile = "GuiDefaultProfile";
visible = "1";
active = "1";
command = "DragDropGui::StartDrag (%this);";
tooltipProfile = "GuiToolTipProfile";
hovertime = "1000";
isContainer = "0";
canSave = "1";
canSaveDynamicFields = "0";
};
new GuiBitmapCtrl() {
bitmap = "art/gui/inv/tile.png";
wrap = "0";
position = "560 143";
extent = "64 64";
minExtent = "8 2";
horizSizing = "right";
vertSizing = "bottom";
profile = "GuiDefaultProfile";
visible = "1";
active = "1";
tooltipProfile = "GuiToolTipProfile";
hovertime = "1000";
isContainer = "0";
canSave = "1";
canSaveDynamicFields = "0";
};
new GuiBitmapButtonCtrl(droptarget) {
bitmapMode = "Stretched";
autoFitExtents = "0";
groupNum = "-1";
buttonType = "PushButton";
useMouseEvents = "1";
position = "565 149";
extent = "55 52";
minExtent = "8 2";
horizSizing = "right";
vertSizing = "bottom";
profile = "GuiDefaultProfile";
visible = "1";
active = "1";
tooltipProfile = "GuiToolTipProfile";
hovertime = "1000";
isContainer = "0";
canSave = "1";
canSaveDynamicFields = "0";
};
#6
08/03/2010 (1:45 am)
new GuiBitmapButtonCtrl(Source) {
bitmap = "art/gui/inv/knife.png";
bitmapMode = "Stretched";
autoFitExtents = "0";
groupNum = "-1";
buttonType = "PushButton";
useMouseEvents = "1";
position = "238 146";
extent = "49 50";
minExtent = "8 2";
horizSizing = "right";
vertSizing = "bottom";
profile = "GuiDefaultProfile";
visible = "1";
active = "1";
tooltipProfile = "GuiToolTipProfile";
hovertime = "1000";
isContainer = "0";
canSave = "1";
canSaveDynamicFields = "0";
};
};
//--- OBJECT WRITE END ---

function DragDropGui::StartDrag (%this)
{
echo("1");
}
function droptarget::onControlDragged(%this,%payload,%position)
{
echo("2");
}
function droptarget::onControlDragEntered(%this,%payload,%position)
{
echo("3");
}
function droptarget::onControlDragExit(%this,%payload,%position)
{
echo("4");
}
function droptarget::onControlDropped(%this,%payload,%position)
{
%this.bitmap=%payload.bitmap;
echo("5");
}

function Source::onMouseDragged(%this)
{
echo ("dragged");
echo ("bitmap = " @ %this.bitmap);
%position = %this.getGlobalPosition();
%cursorpos = Canvas.getCursorPos();

%payload = new GuiBitmapCtrl() {
profile = "GuiDefaultProfile";
horizSizing = "width";
vertSizing = "height";
position = "0 0";
extent = "32 32";
minExtent = "8 8";
visible = "1";
helpTag = "0";
bitmap = %this.bitmap;
wrap = "0";
};

%xOffset = getWord(%payload.extent, 0) /2;
%yOffset = getWord(%payload.extent, 1) / 2;

// position where the drag will start, to prevent visible jumping. Down and to the right also
%xPos = getWord(%cursorpos, 0) + 32; //%xOffset;
%yPos = getWord(%cursorpos, 1) + 32; //%yOffset;

//Now create the drag and drop control which will be deleted when mouse is up, delivering its payload
%dragCtrl = new GuiDragAndDropControl() {
canSaveDynamicFields = "0";
Profile = "GuiDefaultProfile";
HorizSizing = "right";
VertSizing = "bottom";
Position = %xPos SPC %yPos;
extent = %payload.extent;
MinExtent = "32 32";
canSave = "1";
Visible = "1";
hovertime = "1000";
deleteOnMouseUp = true;
};

%dragCtrl.add(%payload);
Canvas.getContent().add(%dragCtrl);

//We want the new dragdrop to be offset from the cursor
%dragCtrl.startDragging(%xOffset -32, %yOffset - 32);
}
#7
01/12/2012 (1:27 pm)
Thank you for sharing this!!!

Vince I'm trying your script in TGB , I cant get drag work (no errors in console) , the rest seem to be working. Knife icon changes onMouseEnter and onMouseDown but dragging doesnt work.
What gives?