toolui (lx_toolui.hpp)

From The Foundry MODO SDK wiki
Jump to: navigation, search
There are security restrictions on this page


Tool Event Processing

3D view input events are split into separate packets for tool vector consumption. These packets are set at the beginning of the pipeline after each 3D input event and are processed down the line by the set of tools present in the stack. This makes it possible to have constraint tools like construction planes or vertex snapping.

Tool events are processed separately from the tool apply itself. This means that there are two distinct tool vectors: one for event processing and one for apply. Eventually these two vectors could be just one, but since the tool system is a two step process, it seems natural to use two different vectors.

View Packet

The 'type' is the viewport type on the mouse down event position. 'viewProjection' is the AGLViewType() one of the LXiVIEWv_xxx

(1) SDK: LXpToolViewEvent struct
 struct st_Viewport      *vport;
 struct st_AGLView       *view;
 unsigned                 flags;
 unsigned                 type;
 unsigned                 vportType;
 unsigned                 viewProjection;

(2) SDK: Declarations
 #define LXsP_TOOL_VIEW_EVENT    "ToolViewEvent"
 #define LXi_VIEWTYPE_3D         0
 #define LXi_VIEWTYPE_UV         1
 #define LXi_VIEWTYPE_2D         2

3D Packet

The 3D event packet has four sets of coordinates: v0 is the down event position and dv is the vector for from v0 to the current 3D event as it is updated during move events. The read-only rv0 and rdv vectors are the raw vectors fed into the event pipeline, untouched by other tools.

This packet is only valid in the context of a stroke list. Primary 3D event information should be calculated using the EventTranslation object.

(3) SDK: LXpTool3DEvent struct
 LXtVector                v0, dv;
 LXtVector                rv0, rdv;

(4) SDK: Declarations
 #define LXsP_TOOL_3D_EVENT      "Tool3DEvent"

Screen Packet

(5) SDK: LXpToolScreenEvent struct
 int              px, py;
 int              cx, cy;
 float            fpx, fpy;
 float            fcx, fcy;

(6) SDK: Declarations
 #define LXsP_TOOL_SCREEN_EVENT  "ToolScreenEvent"

Input Packet

(7) SDK: LXpToolInputEvent struct
 int              mode;
 int              input;
 int              count;
 int              part;
 int              type;
 int              haul;

There are different input event types corresponding to the cases in which the event function may be called. NONE is included to allow the filter method to determine if it's being called as part of drawing.

(8) SDK: Declarations
 #define LXiTIE_TYPE_NONE        0
 #define LXiTIE_TYPE_DOWN        1
 #define LXiTIE_TYPE_MOVE        2
 #define LXiTIE_TYPE_UP  3

The inputs are classified as I0 and I1 which by default maps to the left and right mouse buttons for the normal input patterns. For the CURVE input pattern we have a different set of possible input events. Any event which has no effect for a tool should revert to EDIT.

(9) SDK: Declarations

The 'haul' flag is raised when automatic attribute hauling is happening.

(10) SDK: Declarations
 #define LXsP_TOOL_INPUT_EVENT   "ToolInputEvent"

Tablet Packet

Tools which can do something useful with tablets can request the tablet event packet. This is the information from the tablet device about the current event (or the event along the stroke). The packet will contain default values if the input comes from a mouse or from some other device that does not support all the inputs. You can also see if the tablet even exists and if the tablet is in use or not (if not in use, default mouse values will be set for the other parameters)

(11) SDK: LXpToolTabletEvent struct
 int                      exists;
 int                      inUse;
 double                   normal;
 double                   tangent;
 double                   tilt[2];
 double                   twist;

This is the pressure normal to the pen tip. Defaults to 1.0.
This is the tangent pressure, as controlled by the airbrush wheel on stylii that support this. Defaults to 0.0.
These are the angles in radians of the pen tip relative to the tablet. tilt[0] is the azimuth of the pen relative to the tablet measured clockwise. Defaults to 0.0, which is a pen with the tip pointing "up" the tablet. tilt[1] is the angle of deviation of the pen from vertical. Defaults to 0.0.
Twist of the pen around its own axis in radians. Defaults to 0.0.

(12) SDK: Declarations
 #define LXsP_TOOL_TABLET_EVENT  "ToolTabletEvent"

Color Packet

Tools can work with colors, the color packet can be used to set the foreground and background colors which can be shared by tools in the pipe.

(13) SDK: LXpToolColor struct
 float            fg[4];
 float            bg[4];

(14) SDK: Declarations
 #define LXsP_TOOL_COLOR         "ToolColor"

Ray Casting

To allow clients to do raycasting on the mesh, we add an object packet containing a tracing interface. The object itself encodes all the information about the view mapping and active geometry.

(15) SDK: ILxRaycastPacket interface
         LXxMETHOD(  int,
 HitPolygon) (
         LXtObjectID              self,
         LXtObjectID              toolVector,
         unsigned                 layer,
         float                    x,
         float                    y,
         LXtHitPolygon           *hit);
         LXxMETHOD(  int,
 HitEdge) (
         LXtObjectID              self,
         LXtObjectID              toolVector,
         unsigned                 layer,
         float                    x,
         float                    y,
         LXtHitEdge              *hit);
         LXxMETHOD(  int,
 HitVertex) (
         LXtObjectID              self,
         LXtObjectID              toolVector,
         unsigned                 layer,
         float                    x,
         float                    y,
         LXtHitVertex            *hit);
         LXxMETHOD(  int,
 HitItem) (
         LXtObjectID              self,
         LXtObjectID              toolVector,
         float                    x,
         float                    y,
         LXtHitItem              *hit);

(16) SDK: Declarations
 #define LXf_LAYER_ACTIVE            0x01
 #define LXf_LAYER_INACTIVE          0x02

These methods perform ray casting looking for an element of the given type. If none is found under the screen coord.s given, it returns 0. The different 'hit' types encode information gleaned from the hit. All have the element ID and 3D position. Polygons have a normal (the interpolated normal from the limit surface) and UV coordinates for the selected UV map. Edges have the fraction from the A to B vertex for the edge. The 'nrm' member of the HitItem structure is only set if the item is a surface item, in which case the 'isMesh' member will be set to true.

'layer' select the layers to be processed: ACTIVE is all current meshes; INACTIVE is all visible but inactive meshes.

!!!N.B. the use of opaque LXtPolygonID type pointers may be limiting compared to delivering an ILxMesh and LXtMeshPolyInfo, or the mesh and ID, given that a lookup method is added to the mesh.

(17) SDK: LXtHitPolygon struct
 LXtPolygonID             pol;
 LXtVector                pos;
 LXtVector                nrm;
 float                    uv[2];
 float                    cosine;
 float                    disp;
 LXtObjectID              item;
 void                    *mbin;

(18) SDK: LXtHitEdge struct
 LXtEdgeID                edge;
 LXtVector                pos;
 float                    t;

(19) SDK: LXtHitVertex struct
 LXtPointID               vrt;
 LXtVector                pos;

(20) SDK: LXpToolHitEvent struct
 LXtHitPolygon            hit;
 float                    dist;

(21) SDK: LXtHitItem struct
 LXtObjectID              item;
 LXtVector                pos;
 LXtVector                nrm;
 int                      isMesh;

(22) SDK: Declarations
 #define LXu_RAYCASTPACKET               "4AC0C624-15EE-4BB1-91EB-CDF9395A9193"

(23) SDK: Declarations
 #define LXsP_TOOL_RAYCAST               "ToolRaycast"

(24) User Class: RaycastPacket method

Empty RaycastPacket Python user class.

(25) PY: RaycastPacket method

ILxRaycastPacket1 (Legacy Interface)

This interface was retired in modo 701, and was replaced with an updated one that adds a few more methods.

(26) SDK: Declarations
 #define LXu_RAYCASTPACKET1              "D622B573-2638-4A47-AD91-6BC7A6D2D30B"

(27) SDK: ILxRaycastPacket1 interface
         LXxMETHOD(  int,
 HitPolygon) (
         LXtObjectID              self,
         LXtObjectID              toolVector,
         float                    x,
         float                    y,
         LXtHitPolygon           *hit);
         LXxMETHOD(  int,
 HitEdge) (
         LXtObjectID              self,
         LXtObjectID              toolVector,
         float                    x,
         float                    y,
         LXtHitEdge              *hit);
         LXxMETHOD(  int,
 HitVertex) (
         LXtObjectID              self,
         LXtObjectID              toolVector,
         float                    x,
         float                    y,
         LXtHitVertex            *hit);
         LXxMETHOD(  int,
 HitItem) (
         LXtObjectID              self,
         LXtObjectID              toolVector,
         float                    x,
         float                    y,
         LXtHitItem              *hit);

Hit Packet

When a tool asks for this in its vector type, the 3D view traces the polygon under the mouse at each event, filling in the hit info in the packet. The 'dist' is the distance from the default eye 'pos' for the event ray. If there is no hit, hit.pol will be NULL.

(28) SDK: Declarations
 #define LXsP_TOOL_HIT_EVENT     "ToolHitEvent"

Stroke Packet Interface

The stroke packet is a tool input packet provided by the vp3d tool input handling code. It is an object packet, containing an ILxVectorList object. A subset of the normal tool packets are stored in the stroke vector list. It can contain the following packet types:

(29) Stroke Packet Subtypes

The stroke vector is just built up by appending the packets for the current event to the list. Which packets are included is determined by the ones requested by the tool normally. Generally the ones which may be found in the stroke are those whose values change on each mouse move. Any packets which are fixed should stay fixed while those which change for each move event are appended to the vector list as the mouse input traces out a stroke.

(30) SDK: Declarations
 typedef ILxVectorList           ILxStrokePacket;
 typedef ILxVectorListID         ILxStrokePacketID;

(31) SDK: Declarations
 #define LXsP_TOOL_STROKE_EVENT  "ToolStrokeEvent"

Paint Target Packet

The paint target is the image that is being edited (read only), the (xc,yc) coordinates of the paint operation (usually the brush center) and the (xp,yp) coordinates of the pixel (usually the brush's pixel coordinates in the image). This packet is used by most paint tools to know what the current paint position is. 'projMode' is enabled when projection painting is used. 'projWidth\Height' are set with the current pane size used for projection painting.

(32) SDK: LXpToolPaintTarget struct
 ILxImageID               image;
 int                      projMode, projWidth, projHeight;
 int                      xc, yc;
 int                      xp, yp;
 float                    fxp, fyp;

(33) SDK: Declarations
 #define LXsP_TOOL_PAINT_TARGET  "ToolPaintTarget"

Paint Stroke Packet

The paint stroke packets holds the information about the current stroke with the 'start' and 'end' points in pixel coordinates (note that we use floats because positions are interpolated). 'length' is the stroke length in pixels (between 'start' and 'end'). 'total' is the total stroke length since mouse DOWN. 'current' is the position on the stroke for the current paint operation. 'align' is true if the brush is aligned to the stroke.

(34) SDK: Declarations
 #define LXsP_TOOL_PAINT_STROKE  "ToolPaintStroke"

(35) SDK: LXpToolPaintStroke struct
 float            start[2], end[2];
 float            length;
 float            total;
 float            current;
 int              align, colorEval;

Paint Brush Packet

The paint brush is an object packet that can be used by paint tools. Paint brushes can be 2D or 3D or both, thus we provide a set of methods to compute values in 2D and 3D.

This method returns brush flags, these indicate what type of brush (2D and\or 3D).

(36) SDK: Declarations
 #define LXfPAINTBRUSH_2D                0x01
 #define LXfPAINTBRUSH_3D                0x02
 #define LXfPAINTBRUSH_3D_RGBA           0x04

This method returns the brush size in screen space (the size is expressed in pixels).
This method sets the brush bounding box given the brush center in 3D space and the size multiplier. Returns 0 if the brush is not 3D.
This method returns a brush as a bitmap. The arguments are the toolvector, the size multiplier and the brush to set. The brush returned can be of any size though the size should be set according to the multiplier. So if the tool ise set to have a 20 pixel size and the multiplier comes in as 0.5 then the brush size should be 10. This function returns 0 in case of failure.
For 3D brushes, this method returns the brush 'falloff' at the given position in space. If the brush also defines the volume color, then 'rgba' will be set with that color. 'wpos' is the wordl position 'bpos' is the position in brush space. 'rad' is the brush radius.

(37) SDK: ILxPaintBrushPacket interface
         LXxMETHOD(  int,
 Flags) (
         LXtObjectID              self);
         LXxMETHOD(  float,
 Size) (
         LXtObjectID              self);
         LXxMETHOD(  int,
 BBox) (
         LXtObjectID              self,
         LXtObjectID              toolVector,
         const LXtVector          center,
         double                   size,
         LXtBBox                 *bbox);
         LXxMETHOD(  int,
 Eval2D) (
         LXtObjectID              self,
         LXtObjectID              toolVector,
         float                    multiplier,
         LXtPaintBrush           *brush);
         LXxMETHOD(  double,
 Eval3D) (
         LXtObjectID              self,
         LXtObjectID              toolVector,
         const LXtVector          center,
         const LXtVector          wpos,
         const LXtVector          bpos,
         double                   rad,
         float                   *rgba);

The paint brush is a very simple structure with a width and a height, a pointer to the weight values and an optional pointer to color values.

Specifies how pixels are transferred from the brush to the canvas.
Painting usually uses brush stepping to speedup painting. This is sometimes not desirable though, for example when the brush is very smooth and painting on the bump channel because steps become very visible. With the stepFlags the brush can activate stepping in the bump channel. 'roller' should be set for 'roller' brushes.

(38) SDK: LXtPaintBrush struct
 int              width, height;
 float           *wgt;
 float           *rgb;
 float            rotation;
 int              mode;
 int              flags;

(39) SDK: Declarations
 #define LXiPAINTMODE_SET        0
 #define LXiPAINTMODE_ADD        1
 #define LXiPAINTMODE_MAX        2

(40) SDK: Declarations
 #define LXfPAINTSTEP_BUMP       0x01
 #define LXfPAINT_ROLLER         0x02
 #define LXfPAINT_STAMP          0x04
 #define LXfPAINT_NOROT          0x08

(41) SDK: Declarations
 #define LXu_PAINTBRUSHPACKET            "9283C21E-77FC-402D-B22A-7B26285888C4"
 #define LXa_PAINTBRUSHPACKET            "PaintBrushPacket"

(42) SDK: Declarations
 #define LXsP_TOOL_PAINT_BRUSH           "ToolPaintBrush"

(43) User Class: PaintBrushPacket method

Empty PaintBrushPacket Python user class.

(44) PY: PaintBrushPacket method

Paint Ink Packet

The paint ink is an object packet that can be used by paint tools. It mostly consists of a method used to obtain a color at a given position.

This method returns the ink flags. By default the color is the same for the entire brush. There is a flag that tells if the ink should be evaluated for each pixel and another one if the ink requires 3D parameters (which may require interpolating costly geometric parameters).

(45) SDK: Declarations
 #define LXf_PAINT_INK_PERPIXEL          0x01
 #define LXf_PAINT_INK_3D                0x02
 #define LXf_PAINT_INK_STAMP             0x04
 #define LXf_PAINT_INK_REPLACE           0x08

This method returns a color with alpha. The arguments are the toolvector, the mode and the color itself as a float vector. The 'mode' specifies which paint color should be used in combination with the ink color. 'raw' means that the color returned is the raw image color, other modes multiply the selected color with the pixel image color.
This method returns a stamp brush used to override the tool vector brush.

(46) SDK: ILxPaintInkPacket interface
         LXxMETHOD(  int,
 Flags) (
         LXtObjectID              self,
         LXtObjectID              toolVector);
         LXxMETHOD(  int,
 Color) (
         LXtObjectID              self,
         LXtObjectID              toolVector,
         int                      flags,
         LXtColorRGBA             rgba);
         LXxMETHOD(  int,
 Stamp) (
         LXtObjectID      self,
         LXtPaintBrush   *brush);

(47) SDK: Declarations
 #define LXu_PAINTINKPACKET              "340EE412-232D-4619-974D-7E59C7B39353"
 #define LXa_PAINTINKPACKET              "PaintInkPacket"

(48) SDK: Declarations
 #define LXsP_TOOL_PAINT_INK             "ToolPaintInk"

(49) User Class: PaintInkPacket method

Empty PaintInkPacket Python user class.

(50) PY: PaintInkPacket method

Paint Nozzle Packet

The paint nozzle is an object packet that can be used by paint tools.

This method returns true if a paint operation should happen for the given paint target.
This method returns a position used to paint a brush. The arguments are the toolvector, the image, the brush size and the jittered brush position in the image. The base paint position can be read from the paint target.
The is the main method which sets the strength, size and rotation values.

(51) SDK: ILxPaintNozzlePacket interface
         LXxMETHOD(  int,
 Paint) (
         LXtObjectID      self,
         LXtObjectID              toolVector,
         float            brushSize);
         LXxMETHOD(  int,
 Jitter) (
         LXtObjectID      self,
         LXtObjectID              toolVector,
         float            brushSize,
         int                     *xj,
         int                     *yj);
         LXxMETHOD(  int,
 Nozzle) (
         LXtObjectID      self,
         LXtObjectID              toolVector,
         float           *strength,
         float           *size,
         float           *rotation);

(52) SDK: Declarations
 #define LXu_PAINTNOZZLEPACKET           "F0BB49ED-0BBB-448a-8339-F69F78E95048"
 #define LXa_PAINTNOZZLEPACKET           "PaintNozzlePacket"

(53) SDK: Declarations
 #define LXsP_TOOL_PAINT_NOZZLE          "ToolPaintNozzle"

(54) User Class: PaintNozzlePacket method

Empty PaintNozzlePacket Python user class.

(55) PY: PaintNozzlePacket method

Profile Packet

The profile packet set the profile destination object of the selected profile preset.

(56) SDK: LXpToolProfile struct
 LXtObjectID              xobj;
 int                      dimension;

(57) SDK: Declarations
 #define LXsP_TOOL_PROFILE       "toolProfile"

Image Content Preset Packet

(58) SDK: LXpToolImage struct
 char                    *path;
 int                      flags;

(59) SDK: Declarations
 #define LXsP_TOOL_IMAGE         "toolImage"

Snapped Element Packet

The Snapped Element packet set the informations when element snap tool made an element snapped. This is a packet to communicate element snap tools and the downstream tools.

(60) SDK: LXpToolSnapElement struct
 LXtMeshID                mesh;
 LXtMeshMapID             vmap;
 LXtID4                   type;
 LXtPolygonID             pol;
 LXtPointID               vrt0, vrt1;
 LXtVector                pos;
 double                   cx, cy;
 double                   dist;
 struct st_AGLView       *view;

(61) SDK: Declarations
 #define LXsP_TOOL_SNAPELEMENT   "toolSnapElement"

Subject Packet

The default ScanAllocate function just allocates the equivalent function on the Layer Service.

(62) PRIV: Functions
         static LxResult
 DefaultSub_ScanAllocate (
         LXtObjectID               self,
         unsigned                  flags,
         void                    **ppvObj)
         ILxLayerServiceID        lyr_svc = NULL;
         lyr_svc = GlobalService (GUIDLookup (LXu_LAYERSERVICE));
         if (!lyr_svc)
                 return LXe_FAILED;
         return lyr_svc[0]->ScanAllocate (lyr_svc, flags, ppvObj);

The default Type function just queries the global selection state.

(63) PRIV: Functions
         static ID4
 DefaultSub_Type (
         LXtObjectID              self)
         ID4                      selTypes[] = {ID_VERX, ID_EDGE, ID_POLY, ID_NULL};
         return SelTopmostType (selTypes);

(64) Startup: Register COM interfaces
         static ILxSubject2Packet         vtSubj;
         vtSubj.ScanAllocate = DefaultSub_ScanAllocate;
         vtSubj.Type = DefaultSub_Type;
         XCOMDefineObject ("def.subject2", NULL);
         XCOMAddInterface ("def.subject2", GUIDLookup (LXu_SUBJECT2PACKET), &vtSubj);

(65) SDK: Declarations
 #define LXsP_TOOL_SUBJECT2      "tool.subject2"

Item Replacements

The '' command supports item type replacement. This allows us to create controls for channels on items that aren't selected, provided they have some relationship to the selected items. The format for this is ' itemtype(replace)$channelname', where 'replace' is the name of an ItemReplacement server.

(66) SDK: Declarations
 #define LXu_ITEMREPLACEMENT             "3C256C60-DDE0-4347-82BB-10BF6E3AE887"
 #define LXa_ITEMREPLACEMENT             "itemreplacement"

The server is given an ItemCollection object with the selected items matching the initial type. The server should return a new collection to replace the selected items.

(67) SDK: ILxItemReplacement interface
         LXxMETHOD( LxResult,
 ReplaceItems) (
         LXtObjectID              self,
         LXtObjectID              current,
         LXtObjectID              replacement);

Given an item type name, this method should return the types of items that would be used to replace it. It can be a list of type names separated by white space.

(68) SDK: ILxItemReplacement interface
         LXxMETHOD( LxResult,
 Types) (
         LXtObjectID              self,
         const char              *curType,
         const char             **repTypes);

The replacement can also define additional notifiers for an using the replacement. This can be useful for updating controls if graphs change that define the redirection. Notifiers are given by a string containing the notifier name and args.

(69) SDK: ILxItemReplacement interface
         LXxMETHOD( LxResult,
 NotifierCount) (
         LXtObjectID              self,
         const char              *itemType,
         const char              *channelName,
         unsigned                *count);
         LXxMETHOD( LxResult,
 NotifierByIndex) (
         LXtObjectID              self,
         const char              *itemType,
         const char              *channelName,
         unsigned                 index,
         char                    *buf,
         unsigned                 len);