color (lx_color.hpp)

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


ILxColorModel

modo supports an extensible set of color models that define how the color picker is displayed. Each color model can have 1, 3 or 4 components. They are represented by the ILxColorModel interface. We internally support the RGB color model, but other models can be defined as needed by plug-ins.

(1) SDK: Declarations
 #define LXu_COLORMODEL          "67d3d952-4ab0-49e5-8f9e-6c889b00f253"
 #define LXa_COLORMODEL          "colormodel"

It should be noted that color models should be "stateless". This means that everything you need to compute the values for a given method should be derived from the arguments provided. This ensures that a single color model instance can be safely used across color picker views, and avoids unforeseen complications from storing state in your object.

For speed, floats are used instead of doubles in all methods. It is important to keep this conversion in mind, as many other parts of the nexus architecture use doubles for colors. Be sure to double-check the datatype when passing float/double pointers to avoid crashes.

Color models can have 1, 3 or 4 components. Examples, include color temperature (1), RGB/HSV/LAB (3) and CMYK (4). Models with 2 or more than 4 components are not currently supported. This method must be implemented.

(2) SDK: ILxColorModel interface
         LXxMETHOD( int,
 NumComponents) (
         LXtObjectID               self);

Each component can have its own datatype. For example, the Hue component of HSV is in degrees. More generic units, like the components of RGB, can use the "color1" datatype to have their units determined by the current color system. This must be a floating point datatype. If not implemented, color1 is assumed.

(3) SDK: ILxColorModel interface
         LXxMETHOD( LxResult,
 ComponentType) (
         LXtObjectID               self,
         unsigned                  component,
         const char              **type);

Each component can also have its own min/max range. For example, Hue ranges from 0 to 360. If not implemented, we default to 0.0 to 1.0.

(4) SDK: ILxColorModel interface
         LXxMETHOD( LxResult,
 ComponentRange) (
         LXtObjectID               self,
         unsigned                  component,
         float                    *min,
         float                    *max);

The main job of a color model is to convert between RGB and a vector in the model's space. These functions facilitate this. The vector is assumed to have NumComponents() number of elements. The output vectors will already be allocated and simply need to be populated by the server.

(5) SDK: ILxColorModel interface
         LXxMETHOD( LxResult,
 ToRGB) (
         LXtObjectID               self,
         const float              *vector,
         float                    *rgb);
 
         LXxMETHOD( LxResult,
 FromRGB) (
         LXtObjectID               self,
         const float              *rgb,
         float                    *vector);

By default, the color picker draws a rectangular image depecting a 2D slices through the color space (or a 1D slice in the case of single-component modes). It also will draw one or two horizontal strips representing the remaining axes for three and four component modes.

The server can define it's own version of the 2D slice by implementing this method. An ILxImageID is provided to the caller, who is then responsible for filling the image with a representation of the space given two numbered axes. Note that this image may not initially be empty, and should be completely drawn by the server. The image will be RGBA32, and you should clear the alpha for areas of the image that do not have contents. vec[xAxis] and vec[yAxis] will be undefined, but the remaining vec elements will be set from the current color. If this method is not implemented, a default slice image is computed directly by the color picker.

(6) SDK: ILxColorModel interface
         LXxMETHOD( LxResult,
 DrawSlice) (
         LXtObjectID               self,
         LXtObjectID               image,
         unsigned                  xAxis,
         unsigned                  yAxis,
         const float              *vec);

This second function is called to mark the current color in the image, or as close as it can get. The image will already be filled with a slice returned by a previous call to DrawSlace(), and the server should simply draw a marker at the position identified by vec. If this method is not implemented, a default marker will be drawn by the color picker itself. The current fstops are also provided so that the image can be drawn with the correct exposure.

The "down vector" is also provided to the slice. This is the color that was current at the time the mouse button went down, and may be different than the current color provided by vec. If no mouse buttons are down, this is the same as vec.

Most clients will simply use vec to draw their marker. Clients that do advanced drawing (such as the swatches in the HSV color model) will use downVec as well, updating the original downVec themselves during their FromSlicePos() call. See FromSlicePos() for more information.

(7) SDK: ILxColorModel interface
         LXxMETHOD( LxResult,
 DrawSliceMarker) (
         LXtObjectID               self,
         LXtObjectID               image,
         unsigned                  xAxis,
         unsigned                  yAxis,
         const float              *downVec,
         const float              *vec);

This method is called to ask the color model if it needs to redraw the slice when the current color has changed. If it does not need to, we will simply ask for a new marker to be drawn. If this returns LXe_FALSE, we redraw the slice; if it returns LXe_TRUE or any other success code, we reuse the existing slice and ask for a new marker to be drawn over it (the marker is always drawn fresh). If not implemented, we will only redraw if a component of the vector other than the xAxis or yAxis have changed; otherwise, we reuse the slice. This is only called if you drew the slice yourself in the first palce, and only if it is possible for the slice to be reused (because the image size or colorspace didn't change, for example).

(8) SDK: ILxColorModel interface
         LXxMETHOD( LxResult,
 CanSliceBeReused) (
         LXtObjectID               self,
         unsigned                  xAxis,
         unsigned                  yAxis,
         const float              *oldVec,
         const float              *newVec);

The server doesn't need to draw the marker itself, in which case it needs to be able to convert the color vector into an XY coordinate within the slice image for us. This only needs to be implemented if the server is drawing the image but not the marker position itself. imgX and imgY are expected to be coordinates with the image defined by imgW and imgH.

(9) SDK: ILxColorModel interface
         LXxMETHOD( LxResult,
 ToSlicePos) (
         LXtObjectID               self,
         unsigned                  xAxis,
         unsigned                  yAxis,
         unsigned                  imgW,
         unsigned                  imgH,
         const float              *vec,
         unsigned                 *imgX,
         unsigned                 *imgY);

This reciprocal method gets a color vector given an XY coordinate in the slice image itself. Again the XY coordinates range from zero to imgW and imgH, and the xAxis and yAxis of the vector provided should be set to the values represented by those coordinates. The remaining components do not need to be set.

This function is usually called when the users is clicking and dragging over the color picker. The downVec represents the color at the time the mouse button went down. This value is initialized when the mouse button goes down, and is not changed by the color picker until the next time the button goes down. This allows you to use it as a kind of scratch area, letting you change the color between calls to FromSlicePos(). An example of where this is useful is the HSV color model, which shows both a color wheel and a series of swatches. Clicking on a swatch would always use the downVec to compute a new vec. Meanwhile, clicking on the wheel should update downVec in case the user drags from the wheel over to the swatch.

(10) SDK: ILxColorModel interface
         LXxMETHOD( LxResult,
 FromSlicePos) (
         LXtObjectID               self,
         unsigned                  xAxis,
         unsigned                  yAxis,
         unsigned                  imgW,
         unsigned                  imgH,
         unsigned                  imgX,
         unsigned                  imgY,
         float                    *downVec,
         float                    *vec );

This method is used in 3D color models to get a "clean" color vector in the model's space that the color picker will use as the basis for draw drawing the horizontal strip. The given component index in the vetor will be incremented through the component's range and passed to the ToRGB() method to draw the strip, so the vector should represent useful colors for the full range of the component. For example, the Hue channel of an HSV model this might return a vector of 0.0,1.0,1.0, while for value it might return 0.0,0.0,0.0. Meanwhile, an RGB color model would also present 0.0,0.0,0.0 for all of its components.

The vector passed to the method is initialized with the current color if dynamic is true. If false, a vector set to all zeros is passed in. The dynamic flag allows the client to decide if it wants to set all of the components of the vector itself (when dynamic is off), or to set only some components and leave the others alone (when dynamic is on). This allows the saturation of HSV to be set to set the value to 1 but leave the hue alone, causing the strip to reflect the current hue at different saturation levels.

If this method isn't implemented, the vector provided is used directly as the base.

(11) SDK: ILxColorModel interface
         LXxMETHOD( LxResult,
 StripBaseVector) (
         LXtObjectID               self,
         unsigned                  axis,
         int                       dynamic,
         float                    *vec );

The server is assumed to have a message table in the form of "colormodel.<serverName>", where "<serverName>" is the name of the server. It is expected to have the following messages:

Model
The username of the color model itself. Just a simple string like "RGB", "HSV", "CMYK", "Color Temperature", etc.
Component1Short
Component2Short
Component3Short
Component4Short
The short label for the individual components. These are usually single characters, such as 'R', 'G', 'B', etc. These may be concatenated by the color picker to create longer strings, like "RGB", so keep them short and standard.
Component1Long
Component2Long
Component3Long
Component4Long
The long name for the individual components. These are usually full words, like "Red", "Green" and "Blue", and are commonly used as the labels for the controls in forms.

ILxColor

ILxColor defines a color, and is primarily used as a source for drag and drop operations that represent a color. The object contains the RGB color (which may be HDR), as well as an optional color model named and the color in that model's space. An optional alpha is also supported.

(12) SDK: Declarations
 #define LXu_COLOR               "7c084df3-adb6-48ee-92d3-032d90efea05"
 #define LXa_COLOR               "color"

These return the RGB and alpha components. The color argument must be a three element float array, which will be filled in with the color.

(13) SDK: ILxColor interface
         LXxMETHOD( LxResult,
 Color) (
         LXtObjectID               self,
         float                    *color);

Alpha is optional. If not implemented, it is assumed to be 1.0.

(14) SDK: ILxColor interface
         LXxMETHOD( LxResult,
 Alpha) (
         LXtObjectID               self,
         float                    *alpha);

This returns the optional color model name, and a the color in the model's model's space. These may not be implemented, in which case the raw RGB values should be used.

(15) SDK: ILxColor interface
         LXxMETHOD( LxResult,
 ColorModel) (
         LXtObjectID               self,
         const char              **model);

A color model can contain up to four components, and thus a four element float array must be provided, which will be filled in with the vector.

(16) SDK: ILxColor interface
         LXxMETHOD( LxResult,
 ColorInModelSpace) (
         LXtObjectID               self,
         float                    *vec);

Individual components within a color model can support value presets when their control is shown in the UI. Each component can have its own value preset cookie. The format is "<index>:<cookie> <index:cookie>" etc.

(17) SDK: Declarations
 #define LXsCOLORMODEL_VALUEPRESET       "colorModelValuePresetCookieTag"

(18) User Class: Color method

Empty Color Python user class.

(19) PY: Color method
 pass