Drag and Drop Sample

One of the major features of the 0.98 release is the inclusion of drag and drop. Basically, this allows you to drag an Item into the 3D space where the IMML can decide to do something with it.

To try drag and drop out for yourself, first download generic-drag-drop-sample.imml (right-click, save as) and open in the Player.

Next, you’ll need to expand the Items list. Do so by clicking on this icon:

By default you are presented with the list of Items of type Video and Document that the currently logged in account has access to (these can be further restricted by the hosting server’s group ACL).

In this case as we are opening the file directly, it will default to showing the most recently published Items without filtering and should look similar to this:

Click to select one of the items from the list (in my example, I’ve chosen “VastPark Logo”) and drag it onto the 3D view. The large rectangle in the centre of the screen will change colour to blue indicating it is a drop target.

Next, drop the Item onto the blue rectangle, which will cause it to change colour to green. Shortly the VastPark logo will appear on it.

How does this work?

Behind the scenes is a plugin (called MetaforikAdapter) which currently supports adapting Items of type “Document” and “Video” to a Model or Primitive element. The code to do this is quite simple.

First, reference the Plugin:

<Plugin Enabled="True" Source="http://id.vastpark.com/VastParkWS/get.vpws?name=MetaforikAdapter&amp;publisher=craigomatic&amp;domain=vastpark&amp;context=park" Name="MetaforikAdapter">
    <Element Name="InvalidRequestHandler" />
    <Parameter Key="InvalidRequestEvent" Value="InvalidRequestHandler" />    
  <Script Name="InvalidRequestHandler">
    function main(obj, args)
      scene.ui:writeline('invalid request')          

Next, handle the appropriate events on the elements you want to be able to drop on. Alternatively, this can be at the document level:
<Trigger Event="DragDrop" Target="OnDragDrop" />
<Trigger Event="DragEnter" Target="OnDragEnter" />
<Trigger Event="DragLeave" Target="OnDragLeave" />

In you script for the drop, pass the Item along with the element you want to adapt it to into the load method on the plugin. You may choose to inspect the Item before the drop to give user feedback as is done in the sample IMML.

<Script Name="OnDragDrop">
    function main(obj, args)            
      --args.data contains the Item which was dragged in
      --load returns a controller object
      c = metaforikadapter:load(args.data, obj)      
      scene.ui:writeline('item name: '..c.item.name)
      scene.ui:writeline('id: '..c.id)
      scene.ui:writeline('is first: '..tostring(c.isfirst))
      scene.ui:writeline('is last: '..tostring(c.islast))
      scene.ui:writeline('total pages: '..tostring(c.pages))
      scene.ui:writeline('current page: '..tostring(c.currentpage))
<Script Name="OnDragEnter">
    function main(obj, args)
        scene.ui:writeline('drag enter on: '..obj.name..' of type: '..args.data.assets[0].type)     
<Script Name="OnDragLeave">
    function main(obj, args)
      scene.ui:writeline('drag leave on: '..obj.name)

Working with elements other than Document or Video

One thing to be aware of is that you don’t necessarily have to use the MetaforikAdapter plugin to benefit from drag and drop. If you want to allow for models or sounds to be dropped in, you can use the item.updateuri as the source for the element and add it into the scene, like this:

<Script Name="OnDragDrop">
    function main(obj, args)    
      item = args.data
      if(item.assets[0].type == 'Model') then       
          m = model()
          m.source = args.data.updateuri

Final Note

That’s really all there is to it, you may want to craft different UI depending on the state of the controller properties in the MetaforikAdapter plugin sample, ie: to handle a multi-page document differently to a video or single page document, or in the model example to only allow certain users to drop models into a specific region of your space.


Comments are closed.