Game Development Community

TGB 1.7.4 Drag and Drop Images and OS X

by Lin Chear · in Torque Game Builder · 01/08/2009 (9:37 pm) · 8 replies

I'm having a curious issue with TGB 1.7.4 on OS X (10.5.4-10.5.5).

According to the documentation, I should be able to drag an image and drop it onto the "Static Sprites" panel and have it loaded into TGB. This behaviour seems to work fine under Windows (Vista).

However, when I try to do the same thing on my Mac, it does not work. The only way I can import assets is to load them one at a time.

I've tried rebuilding and debugging it but gave up after about an hour.

Is anyone else having this issue with TGB / OS X?
A work around is to import the assets on a Windows machine and same the project and reload in OSX.
Thanks,

#1
01/08/2009 (11:57 pm)
So... I looked deeper into this and if I'm correct, dragDrop.ed.cs is the torque script responsible for adding dropped files into (jpg, bmp, png) onto the static sprite panel.

Specifically:
function T2DProject::onDropFile( %this, %filePath )
{
// Check imagemap extension
%fileExt = fileExt( %filePath );
if( (%fileExt $= ".png") || (%fileExt $= ".jpg") || (%fileExt $= ".bmp") )
%this.onDropImageFile(%filePath);

else if (%fileExt $= ".zip")
%this.onDropZipFile(%filePath);
}

I did a grep on "onDropFile" and found:

engine/source/platformWin32/winWindow.cc:762: if( !Con::isFunction( "onDropBegin") || !Con::isFunction("onDropFile")
engine/source/platformWin32/winWindow.cc:808: Con::executef( 2, "onDropFile", StringTable->insert((const char*)pszTheBuffer) );
tgb/tools/editorClasses/scripts/input/dragDropEvents.ed.cs:18:function onDropFile( %filePath )
Binary file tgb/tools/editorClasses/scripts/input/dragDropEvents.ed.cs.edso matches
tgb/tools/levelEditor/core/dragDrop.ed.cs:13:function T2DProject::onDropFile( %this, %filePath )
Binary file tgb/tools/levelEditor/core/dragDrop.ed.cs.edso matches

The only reference is winWindow.cc, which is the Windows window handler...
The macCarbWindow.cc doesn't reference "onDropFile", which explains why the Windows version works and the OS X version does not.

So my question, is this feature REALLY supported in OS X? Or do I somehow have a funky version... I've downloaded, uninstalled, reinstalled many times, and nothing changes.
#2
01/09/2009 (12:25 pm)
I responded to your support request as well. Drag and drop is not currently functioning in the 1.7.4 version of TGB. It should be fixed in the next version, I believe.
#3
01/09/2009 (1:49 pm)
Update: I hacked my copy of TGB to support Drag and Drop.

Basically it installs a drag receiver, listens for drag receive events. The receiver then looks up the OS X pasteboard and grabs the file information from there.

I'll paste my hack code in here in hopes it helps the GG team add this into the next release. I'm completely new to Carbon/OS X, so don't mind the code. Fix it up as you see fit.

Summary:

//in macCarbEvents.cc
//I installed a Drag Receive handler in MacCarbonInstallCarbonEventHandlers():

static DragReceiveHandlerUPP dragReceiveHandlerUPP = NULL;
dragReceiveHandlerUPP = NewDragReceiveHandlerUPP(_DragReceiveHandler);
OSErr err = InstallReceiveHandler(dragReceiveHandlerUPP, platState.appWindow, NULL);


// And created a DragReceiveHandler function:

OSErr _DragReceiveHandler( WindowRef inWindow, void *inUserData, DragRef inDrag )
{
OSStatus err = noErr;
PasteboardRef pasteboard;
TXNObject txnObject = (TXNObject)inUserData;

err = GetDragPasteboard( inDrag, &pasteboard );
require_noerr( err, CantGetDragPasteboard );

err = GetDataFromPasteboard( pasteboard, txnObject );

CantGetDragPasteboard:

HideDragHilite( inDrag );

return err;
}

// And created a function to grab data from the pasteboard:
OSStatus GetDataFromPasteboard( PasteboardRef inPasteboard, TXNObject inTXNObject )

{

OSStatus err = noErr;
PasteboardSyncFlags syncFlags;
ItemCount itemCount;

syncFlags = PasteboardSynchronize( inPasteboard );// 1

/* require_action( syncFlags & kPasteboardModified, PasteboardOutOfSync,
err = badPasteboardSyncErr );

*/
err = PasteboardGetItemCount( inPasteboard, &itemCount );// 2
require_noerr( err, CantGetPasteboardItemCount );

if( !Con::isFunction( "onDropBegin") || !Con::isFunction("onDropFile")
|| !Con::isFunction("onDropEnd") )
return err;

if (itemCount == 0)
return err;

Con::executef( 2, "onDropBegin", Con::getIntArg( itemCount ) );

for( UInt32 itemIndex = 1; itemIndex <= itemCount; itemIndex++ )
{
PasteboardItemID itemID;
CFArrayRef flavorTypeArray;
CFIndex flavorCount;

err = PasteboardGetItemIdentifier( inPasteboard, itemIndex, &itemID );// 3
require_noerr( err, CantGetPasteboardItemIdentifier );

err = PasteboardCopyItemFlavors( inPasteboard, itemID, &flavorTypeArray );// 4
require_noerr( err, CantCopyPasteboardItemFlavors );
flavorCount = CFArrayGetCount( flavorTypeArray );// 5

for( CFIndex flavorIndex = 0; flavorIndex < flavorCount; flavorIndex++ )
{
CFStringRef flavorType;
CFDataRef flavorData;
CFIndex flavorDataSize;
char flavorText[256];
char pathOnly[256];
flavorType = (CFStringRef)CFArrayGetValueAtIndex( flavorTypeArray,
flavorIndex );

if (UTTypeConformsTo(flavorType, CFSTR("public.file-url")))
{
err = PasteboardCopyItemFlavorData( inPasteboard, itemID,flavorType, &flavorData );
require_noerr( err, CantCopyFlavorData );

flavorDataSize = CFDataGetLength( flavorData );
flavorDataSize = (flavorDataSize<254) ? flavorDataSize : 254;

for( short dataIndex = 0; dataIndex <= flavorDataSize; dataIndex++ )// 9
{
char byte = *(CFDataGetBytePtr( flavorData ) + dataIndex);
flavorText[dataIndex] = byte;
}

flavorText[flavorDataSize] = '\0';
flavorText[flavorDataSize+1] = '\n';

// Ewwww
int count = 0;
int sl = 0;
for(int sc = 0; sc < strlen(flavorText); sc++) {
if (flavorText[sc] == '/') {
count++;
}
if (count >= 3) {
pathOnly[sl] = flavorText[sc];
sl++;
}
}

pathOnly[sl] = NULL;

// Notify Drop
if (Platform::isFile( (const char*)pathOnly ))
{
// The timeout for waiting for files (ms).
U32 timeout = 5000;

// Need to make sure the file is copyable. When ganking images from Firefox, it
// isn't necessarily since Firefox insists on redownloading the file instead of
// using the local copy.
U32 time = Platform::getRealMilliseconds() + timeout;

Con::executef( 2, "onDropFile", StringTable->insert((const char*)pathOnly) );
}

CFRelease (flavorData);
}

CantCopyFlavorData:
;
}
CFRelease (flavorTypeArray);

CantCopyPasteboardItemFlavors:
CantGetPasteboardItemIdentifier:
;

}

Con::executef( 2, "onDropEnd", Con::getIntArg( itemCount ) );

CantGetPasteboardItemCount:

PasteboardOutOfSync:

return err;

}
#4
01/09/2009 (1:50 pm)
Very cool. I'll sit down and work with this a bit tonight!
#5
03/10/2009 (8:20 pm)
Any update on this - drag and drop to add art to a project would be very useful on Mac
#6
03/20/2009 (8:10 am)
We haven't released an update to the engine yet. For the time being, people with Pro can use Lin's solution.
#7
05/03/2011 (6:25 pm)
Hi, Lin can your share your macCarbEvents.cc file, i copy and paste you code but give-me some errors.
It´s important have this working.
I think with your solutions, the team from garagegames go to fix this.
Best Regards
#8
05/13/2011 (1:51 am)
Hi,
I add the code in file MacCarbEvents.cc and i have successful compiled and working good drag and drop in Mac OSX.
Thanks.

Best Regards.