Drop (lx-drop.hpp)

From The Foundry MODO SDK wiki
Revision as of 21:01, 19 February 2018 by LuxSDKBot (Talk | contribs) (Header Documentation)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search
There are security restrictions on this page

ILxDrop Interface

ILxDrop allows servers to provide arbtirary behaviors when a drag and drop operation matches a specific combination of source and destination COM interfaces. If the user has chosen one of these behaviors (often from a popover that appears when the user hovers the mouse during a drag and drop operation), ILxDrop is asked to perform it.

(1) SDK: LXu_DROP, etc. defines
 #define LXu_DROP                "ca3c0d04-5ebe-40a7-bb1a-d38488c7967d"
 #define LXa_DROP                "drop"

Source Type Server Tag

An ILxDrop server can recognize only one kind of source, although the details of that source may be varied. For example, a LXsDROPSOURCE_FILES may represent the path to one or more presets, images, scenes or any other kind of file.

The specific source type supported by a server is indicated through server tags.

 #define LXsDROP_SOURCETYPE              "drop.sourceType"

Here are some common source types. The ones ending in "S" are plurals, and thus are usually an ILxValueArray containing one or more entries. The ones without an "S" suffix are usually represented as single objects, not arrays of objects.

FILES An ILxValueArray object with the FILEPATH ExoType, which contains strings representing the paths for each file being dropped (even if it's only one file). These always represent real files or directories as absolute paths in local format.
FILES_SYNTH An ILxValueArray object with the FILEPATH ExoType, which contains strings representing the paths for each file being dropped (even if it's only one file). Unlike FILES, which only ever includes real files on disk, FILES_SYNTH can include both real files and synthetic files (those starting with the path volume "[servername]:" as described in the dir cache docs). Paths are always absoluete and in local format for file system paths, and neutral format for synthetic paths.
COLOR An ILxColor object, which contains the RGB color, the alternate color model (if any) and the color in that model's space as a string (if any).
ITEMS An ILxValueArray object with the ITEM ExoType.
CHANNELS An ILxValueArray object with the CHANNEL ExoType.
COMMANDS An ILxValueArray of strings representing commands.
FORMCONTROLS An ILxValueArray of strings representing form controls and sheets.

A note about FILES and FILES_SYNTH: Since drop servers can support only a single drop source, you only need to support FILES or FILES_SYNTH. If the actual drag source is FILES_SYNTH and you only support FILES, the array you get will contain only non-synthetic paths. This makes it easy to add synthetic support, while also avoiding ssues with legacy servers that predate FILES_SYNTH.

(3) SDK: LXsDROPSOURCE_FILES, etc. defines
 #define LXsDROPSOURCE_FILES             "files"
 #define LXsDROPSOURCE_FILES_SYNTH       "filesAndSynthetics"
 #define LXsDROPSOURCE_COLOR             "color"
 #define LXsDROPSOURCE_ITEMS             "items"
 #define LXsDROPSOURCE_CHANNELS          "channels"
 #define LXsDROPSOURCE_COMMANDS          "commands"
 #define LXsDROPSOURCE_FORMCONTROLS      "formcontrols"

Action Names Tag

The user can prioritize which drop actions are associated with which modifier key combinations through the Drop Mapping viewport. The list of available actions for this view is read from the LXsDROP_ACTIONS server tag. All actions that may appear in the dropover should be included in this tag, as only actions exposed in this way can be associated with modifier keys. Although actions not in the tag may still appear in the dropover, they will never have modifier keys associated with them and can never be the deafult drop action, so you really should always include them so that the user can make that decision themselves.

 #define LXsDROP_ACTIONNAMES     "drop.actions"

The format of the string is the action index, an '@', and a message table entry representing the name to be displayed in the Drop Mappings view. Multiple action/message pairs can be provided by separating them by spaces, and one should be added for each action that your server supports. These strings are only shown in the Drop Mappings UI, so they should be obvious enough to anyone who is trying to order the actions relative to each other. The serevr's username is automatically prefixed to the action name in the Drop Mappings UI, so you only need to provide the username for the action itself here.

"1@myAction1 2@myAction2"

The messages are looked up in a table named after the drop server. Note that the server name should also be defined in this table as normal, as the server name is displayed with the action in the Drop Mappings preferences.

(5) SDK: Drop Action Names Message Table Axample
 <hash type="Table" key="myDropServer.en_US">
   <hash type-"T" key="Name">My Serevr Name</hash>                   <!-- Standard way to name a server -->
   <hash type="T" key="myAction1">Action 1</hash>
   <hash type="T" key="myAction2">Action 2</hash>


When the user begins a drag and drop operation, each of the ILxDrop servers that match the source type (based on their server tags) are instanced. The Recognize() method is then called on each with the source data. This allows the server to perform expensive operations like scanning file headers only once, rather than doing so on every drag step. Servers that do not reognize the source are then freed.

While dragging, the ActionList() method is called with the previously recognized source and a destination representing the current drop location. This gives the server a chance to add any behaviors it can support for this combination to the action list, which in turn is presented to the user through a hover popover.

When a drop occurs, the Drop() method is called with the same source and the destination so that the user can apply the source object to the target using the destination's methods. Drop() is only called if the server is handling the drop.

Once the drop has completed (through this server or another) or the user has aborted, the server is freed.


The Recognize() method is called soon after the server is instanced. It is only called once per drag and drop cycle, and is used to perform any possibly expensive setup and verification of the source, such as scanning file headers. This information can be cached in your server for use in ActionList(), Preview() and Drop(), rather than recomputing state in those functions.

If the source was recognized, this should return LXe_OK. Any failure code will be treated as though the source was not recognized, and the server will not be called any more for this drag and drop cycle.

(6) SDK: Drop::Recognize
         LXxMETHOD( LxResult,
 Recognize) (
         LXtObjectID               self,
         LXtObjectID               source);

ActionList() is where you add your actions to the dropover. This method is called frequently (ie: when dragging the mouse around the screen), and should be fast. It is provided with thtrr COM objects: the source data being dragged, the destination, and an ILxAddDropAction object with which you can add your actions to the dropover.

The destination may contain arbitrary interfaces depending on what is under the mouse, included interfaces that your server doesn't support. It is best to check the destination interfaces first before doing anything else so that you can exit quickly if you can't support drops here.

The source will be of the type the server indicated in its tags, but it may contain additional interfaces, and should be queried as appropriate before trying to use it.

If the server can find interfaces that it supports on both the source and destination objects, it should call ILxAddDropAction::AddAction() on the provided object for each drop action it would like to register. An arbitrary number of actions can be registered, but the action codes must match those defined by the server's ACTIONNAMES server tag.

(7) SDK: Drop::ActionList
         LXxMETHOD( LxResult,
 ActionList) (
         LXtObjectID               self,
         LXtObjectID               source,
         LXtObjectID               dest,
         LXtObjectID               addDropAction);

901 introduces the Preview() method. Some targets provide objects that can be used by the server to drop the mark point. This can be as simple changing the location fo a drop marker drawn by the target (say, changing whre the drop marker is drawn in a tree view), to complete custom drawing by the server in a GL view (say, to draw a bounding box representation of a mesh preset in the 3D view).

If an action in your server is the best match for the current mouse/modifier combo and the target provides a destination interface (as determiend by which modifier keys are down and the Drop Mappings set up in the prefernces), your Preview() method will be called.

If you return LXe_NOTIMPL, the target will do its own default drawing. Otherwise, you are expected to do your own drawing with the draw object provided. The exact interfaces available are determined by the target, so you will have to query for the ones you want to see if they are available.

The draw object is expected to have the ILxDropPreviewDefault interface, which may allow you to force the default drawing in addition to your own drawing, athough in some case default drawing and custom drawing are mutually exclusive (such as in tree panes).

(8) SDK: Drop::Preview
         LXxMETHOD( LxResult,
 Preview) (
         LXtObjectID               self,
         LXtObjectID               source,
         LXtObjectID               dest,
         int                       action,
         LXtObjectID               draw);

The Drop() method is called to actually perform the drop itself. The server is expected to take apply the source object using information obtained through the destination's interfaces. The specific action to apply is provided through the action argument, and is one of those that was added by the Recognize() method's

(9) SDK: Drop::Drop
         LXxMETHOD( LxResult,
 Drop) (
         LXtObjectID               self,
         LXtObjectID               source,
         LXtObjectID               dest,
         int                       action);

Empty Drop Python user class.

(10) SDK: empty Drop User Class

(11) PY: empty Drop user class

ILxDrop1 (Legacy Interface)

This interface was retired in modo 901, and was replaced with an updated one that adds new methods.

(12) SDK: LXu_DROP1 define
 #define LXu_DROP1               "abea8de3-d821-4437-88b3-05f20276ffeb"

(13) SDK: Drop1::Recognize, etc.
         LXxMETHOD( LxResult,
 Recognize) (
         LXtObjectID               self,
         LXtObjectID               source);
         LXxMETHOD( LxResult,
 ActionList) (
         LXtObjectID               self,
         LXtObjectID               source,
         LXtObjectID               dest,
         LXtObjectID               addDropAction);
         LXxMETHOD( LxResult,
 Drop) (
         LXtObjectID               self,
         LXtObjectID               source,
         LXtObjectID               dest,
         int                       action);


An object with this interface is used by ILxDrop to add new behaviors to the action list.

(14) SDK: LXu_ADDDROPACTION, etc. defines
 #define LXu_ADDDROPACTION       "05C3FF8F-5C3C-4463-AF6E-439C52621DCA"
 #define LXa_ADDDROPACTION       "adddropaction"

This method is called during by ILxDrop servers during their ActionList() method to add new behaviors to drop hover popover. The ILxDrop server should call this once for each action it wishes to add.

Actions are identified by a server-specific action code (which can be anything the server desires, but is expected to match those in the ACTIONNAMES tag), as well as a label in the form of a "@table@message" message string for display in the hover popover. This label can also be a dynamically generated string, thus allowing for things like "Move 3 Files" that provide more useful information to the user about what the drop will do.

(15) SDK: AddDropAction::AddAction
         LXxMETHOD(  LxResult,
 AddAction) (
         LXtObjectID              self,
         int                      action,
         const char              *message);

This method can be used to obtain a "peek" at the destination object to more accurately determine which actions to add to the list. This only works when inside the ILxDrop server's ActionList() method, and is somewhat redundant since that method is passed the destination anyway. Although this is a peek, the caller is still responsible for freeing the returned object.

(16) SDK: AddDropAction::Peek
         LXxMETHOD(  LxResult,
 Peek) (
         LXtObjectID               self,
         void                    **ppvObj);

Empty AddDropAction Python user class.

(17) SDK: empty AddDropAction User Class

(18) PY: empty AddDropAction user class


An object with this interface (and others) is passed to ILxDrop::Preview() so that clients can ask the view to draw a default drop marker.

(19) SDK: LXu_DROPPREVIEWDEFAULT, etc. defines
 #define LXu_DROPPREVIEWDEFAULT  "f3823495-d23f-448f-a5dd-16a1761445a0"
 #define LXa_DROPPREVIEWDEFAULT  "droppreviewdefault"

Calling this method tells the target to draw its default drop marker. You can call this instead of or in addition to your own drawing. Rreturning LXe_NOTIMPL from your ILxDrop::Preview() will also trigger default drawing.

(20) SDK: DropPreviewDefault::Draw
         LXxMETHOD(  LxResult,
 Draw) (
         LXtObjectID              self);

Empty DropPreviewDefault Python user class.

(21) SDK: empty DropPreviewDefault User Class

(22) PY: empty DropPreviewDefault user class

ILxDropService Interface

The global ILxDropService provides a way for clients that don't have direct access to the ILxDrop server to access the destination and source objects. This is primarily for scripts associated with drop servers. For example, a script embedded in a preset can be launched by the ILxDrop server, and the script can determine what to do based on the destination object.

Note that all of these are only gauranteed to be implemented for an actual drop, and not necessarily during a drag.

(23) SDK: LXu_DROPSERVICE, etc. defines
 #define LXu_DROPSERVICE "44345a07-014c-4deb-aba8-8a3147bba212"
 #define LXa_DROPSERVICE "dropservice"

As with all globals, the first method gets the ILxScriptQueryID interface for the system. However, it is not implemented for ILxDropService.

(24) SDK: DropService::ScriptQuery
         LXxMETHOD(  LxResult,
 ScriptQuery) (
         LXtObjectID              self,
         void                   **ppvObj);

This returns the current destination object, failing if there is none. The object must be released when no longer needed.

(25) SDK: DropService::Destination
         LXxMETHOD(  LxResult,
 Destination) (
         LXtObjectID               self,
         void                    **ppvObj);

This returns the current source type and source object. While a source can expose multiple source types and objects, this is the specific source type (as an LXsDROPSOURCE_ define) and object representing the drop in progress. The object must be released when no longer needed.

(26) SDK: DropService::Source
         LXxMETHOD(  LxResult,
 Source) (
         LXtObjectID               self,
         const char              **sourceType,
         void                    **ppvObj);

During a drop, this returns the name of the drop server and the action code of the server. Scripts associated with the drop server can use knowledge of that server's action codes to perform specific drop actions (add vs. replace, say).

(27) SDK: DropService::Action
         LXxMETHOD(  LxResult,
 Action) (
         LXtObjectID               self,
         const char              **serverName,
         int                      *actionCode);

Empty Drop service user classes.

(28) SDK: empty DropService User Class

(29) PY: empty Service.Drop user class