envelope (lx_envelope.hpp)

From The Foundry MODO SDK wiki
(Redirected from ILxGradientFilter (index))
Jump to: navigation, search
There are security restrictions on this page


Contents

Envelopes

Envelopes are an abstract data type that represents a time-varying signal. They are constructed from a series of curves interpolating keyframes using a variety of different shapes. The envelope API provides methods for managing, evaluating and altering envelopes.

The envelope interface is split into two parts. The ILxEnvelope controls the gross attributes of the envelope and permits evaluation for any input value. This can also spawn a key iterator which allows the keys to be walked in sequence, searched, queried and modified.

(1) SDK: Declarations
 #define LXu_ENVELOPE            "E39EB451-6C35-47F4-8A7D-FF96671C0DEF"
 #define LXu_KEYFRAME            "D1D0261F-22CF-4E5D-822E-76B5DEC98AE4"

Envelope

The IsInt() method returns 1 for integer-valued type envelopes, 0 otherwise.

(2) SDK: ILxEnvelope interface
         LXxMETHOD( unsigned,
 IsInt) (
         LXtObjectID              self);

This method allocates a new keyframe enumerator, allowing multiple clients to query the same envelope.

(3) SDK: ILxEnvelope interface
         LXxMETHOD( LxResult,
 Enumerator) (
         LXtObjectID              self,
         void                   **ppvObj);

These two methods allow the envelope to be evaluated. The input value is given as "time" although it is any independent parameter. the correct method must be called based on the envelopes numeric type.

(4) SDK: ILxEnvelope interface
         LXxMETHOD( LxResult,
 EvaluateF) (
         LXtObjectID              self,
         double                   time,
         double                  *value);
 
         LXxMETHOD( LxResult,
 EvaluateI) (
         LXtObjectID              self,
         double                   time,
         int                     *value);

The end behaviors determine what value the envelope takes outside the range of keyframes.

RESET
A default value, or may be just zero.
CONSTANT
The value of the first or last keyframe. For first or last keys set to "Auto" or "Auto Flat" the slopes of the keys will be adjusted to provide a smooth interpolation to or from the behavior.
REPEAT
The values in the keyframe range repeating continuously.
OSCILLATE
Like repeat, but the values run forwards and backward alternately. For first or last keys set to "Auto" or "Auto Flat" the slopes of the keys will be adjusted to provide a smooth interpolation to or from the behavior.
OFFSETREPEAT
Like repeat, but the values are offset in each cycle by the difference between the first and last keyframes. For first or last keys set to "Auto" or "Auto Flat" the slopes of the keys will be adjusted to provide a smooth interpolation to or from the behavior.
LINEAR
Linear interpolation from the slope at the nearest keyframe.
NONE
Indicates that the envelope does not exist before or after the explicit keyframe range. This isbe used by motion evaluation code to decide whether to use the envelope for a channel or to look up the parent envelope or default value.
CONSTANT_KEEP_SLOPE
As for constant except that the slopes of the first or last keys are not changed.
OSCILLATE_KEEP_SLOPE
As for oscillate except that the slopes of the first or last keys are not changed.
OFFSETREPEAT_KEEP_SLOPE
As for offset repeat except that the slopes of the first or last keys are not changed.

(5) SDK: Types
 typedef unsigned        LXtEndBehavior;
 
 #define LXiENV_RESET                    0
 #define LXiENV_CONSTANT                 1
 #define LXiENV_REPEAT                   2
 #define LXiENV_OSCILLATE                3
 #define LXiENV_OFFSETREPEAT             4
 #define LXiENV_LINEAR                   5
 #define LXiENV_NONE                     6
 #define LXiENV_CONSTANT_KEEP_SLOPE      LXiENV_NONE
 #define LXiENV_OSCILLATE_KEEP_SLOPE     7
 #define LXiENV_OFFSETREPEAT_KEEP_SLOPE  8

The envelopes end behavior is read and set with these methods. The side can be IN or OUT to select the behavior for times prior to the first key frame or the behavior after the last keyframe, respectively. The behavior for both can be set by specifying BOTH.

(6) SDK: ILxEnvelope interface
         LXxMETHOD( unsigned int,
 EndBehavior) (
         LXtObjectID              self,
         unsigned int             side);
 
         LXxMETHOD( LxResult,
 SetEndBehavior) (
         LXtObjectID              self,
         unsigned int             behavior,
         unsigned int             side);

(7) SDK: Declarations
 #define LXiENVSIDE_IN                   1
 #define LXiENVSIDE_OUT                  2
 #define LXiENVSIDE_BOTH                 3

For envelopes which can be edited this removes all the keys.

(8) SDK: ILxEnvelope interface
         LXxMETHOD( LxResult,
 Clear) (
         LXtObjectID              self);

(9) SDK: Declarations

(10) SDK: ILxEnvelope interface
         LXxMETHOD( unsigned int,
 Interpolation) (
         LXtObjectID              self);

(11) SDK: ILxEnvelope interface
         LXxMETHOD( LxResult,
 SetInterpolation) (
         LXtObjectID              self,
         unsigned int             type);

Envelope User Class

The user class for envelopes adds a method to spawn an enumerator directly to a keyframe user object. It returns true for success.

(12) User Class: Envelope method
         bool
 GetKeyframe (
         CLxLoc_Keyframe         *key)
 {
         LXtObjectID              obj;
 
         if (LXx_OK (Enumerator (&obj)))
                 return key->take (obj);
 
         clear ();
         return false;
 }

It also adds alternate methods for evaluating the envelope at a given time.

(13) User Class: Envelope method
         int
 IntValue (
         double                   time)
 {
         int                      val = 0;
 
         EvaluateI (time, &val);
         return val;
 }
 
         double
 Value (
         double                   time)
 {
         double                   val = 0.0;
 
         EvaluateF (time, &val);
         return val;
 }

Empty Envelope Python user class.

(14) PY: Envelope method
 pass

Keyframe Traversal

The keyframe interface has a state which is a current key, so it acts as an iterator. The next four methods set the current key based on its position in the sequence, or relative to the current key. They return LXe_NOTFOUND on errors.

(15) SDK: ILxKeyframe interface
         LXxMETHOD( LxResult,
 First) (
         LXtObjectID              self);
 
         LXxMETHOD( LxResult,
 Last) (
         LXtObjectID              self);
 
         LXxMETHOD( LxResult,
 Next) (
         LXtObjectID              self);
 
         LXxMETHOD( LxResult,
 Previous) (
         LXtObjectID              self);

Find() selects a key at or near the current time. If side is IN then the key prior or equal to the time will become current. OUT gets the key after the given time. For BOTH the key must be exactly at the requested time.

(16) SDK: ILxKeyframe interface
         LXxMETHOD( LxResult,
 Find) (
         LXtObjectID              self,
         double                   time,
         unsigned int             side);

Keyframe Values

The time (or other independent parameter) of the key can be read with this method.

(17) SDK: ILxKeyframe interface
         LXxMETHOD( LxResult,
 GetTime) (
         LXtObjectID              self,
         double                  *time);

This method returns flags for which attributes of the key are broken and are different for the incoming and outgoing sides of the key. If the value of the key itself is broken, the side flag indicates which side of the key controls the value exactly at the given time.

(18) SDK: ILxKeyframe interface
         LXxMETHOD( LxResult,
 GetBroken) (
         LXtObjectID              self,
         unsigned int            *breaks,
         unsigned int            *side);

(19) SDK: Declarations
 #define LXfKEYBREAK_VALUE               (1<<0)
 #define LXfKEYBREAK_SLOPE               (1<<1)
 #define LXfKEYBREAK_WEIGHT              (1<<2)

Read the value of the key as a float or int for either side of the key. For unbroken keys this will be the same.

(20) SDK: ILxKeyframe interface
         LXxMETHOD( LxResult,
 GetValueF) (
         LXtObjectID              self,
         double                  *value,
         unsigned int             side);
 
         LXxMETHOD( LxResult,
 GetValueI) (
         LXtObjectID              self,
         int                     *value,
         unsigned int             side);

The slope type, slope and weight may likewise be read for the current key.

(21) SDK: ILxKeyframe interface
         LXxMETHOD( LxResult,
 GetSlopeType) (
         LXtObjectID              self,
         LXtSlopeType            *type,
         unsigned int            *weighted,
         unsigned int             side);
 
         LXxMETHOD( LxResult,
 GetSlope) (
         LXtObjectID              self,
         double                  *slope,
         unsigned int             side);
 
         LXxMETHOD( LxResult,
 GetWeight) (
         LXtObjectID              self,
         double                  *weight,
         unsigned int             side);

The slope can have one of the following values.

LXiSLOPE_DIRECT
the slope of the tangent is set based on the value stored in the key.
LXiSLOPE_AUTO
the slope of the tangent is calculated automatically with regard to surrounding keys. This is similar to the slope adjustments made by TCB curves.
LXiSLOPE_LINEAR_IN
the slope of the tangent is calculated to align with the previous key's value.
LXiSLOPE_LINEAR_OUT
the slope of the tangent is calculated to align with the next key's value.
LXiSLOPE_FLAT
the slope of the tangent is set to zero.
LXiSLOPE_AUTOFLAT
the same as auto but if a neighboring key has the same value as the key the slope is set to zero.
LXiSLOPE_STEPPED
Maintains the value of the previous key between pairs of keys.

(22) SDK: Types
 typedef unsigned        LXtSlopeType;
 
 #define LXiSLOPE_DIRECT         0
 #define LXiSLOPE_AUTO           1
 #define LXiSLOPE_LINEAR_IN      2
 #define LXiSLOPE_LINEAR_OUT     3
 #define LXiSLOPE_FLAT           4
 #define LXiSLOPE_AUTOFLAT       5
 #define LXiSLOPE_STEPPED        6

The SlopeType() method also returns an optional weighted flag, which is true if the weight is set manually rather than being computed automatically.

Keyframe Modification

This alters the time (or independent parameter) of the key, potentially changing its relative position in the sequence of keys.

(23) SDK: ILxKeyframe interface
         LXxMETHOD( LxResult,
 SetTime) (
         LXtObjectID              self,
         double                   time);

These methods allow the various parameters of the keyframe to be set. Breaking and unbreaking are controlled implicitly with the 'side' parameter. Setting the side to IN or OUT will break the parameter and only affect the specified side. Setting the side to BOTH will unbreak the parameter. The last side set when breaking the value will be the controlling side for the key.

(24) SDK: ILxKeyframe interface
         LXxMETHOD( LxResult,
 SetValueF) (
         LXtObjectID              self,
         double                   value,
         unsigned int             side);
 
         LXxMETHOD( LxResult,
 SetValueI) (
         LXtObjectID              self,
         int                      value,
         unsigned int             side);
 
         LXxMETHOD( LxResult,
 SetSlope) (
         LXtObjectID              self,
         double                   slope,
         unsigned int             side);
 
         LXxMETHOD( LxResult,
 SetSlopeType) (
         LXtObjectID              self,
         LXtSlopeType             type,
         unsigned int             side);

This will set the weight for the key unless 'reset' is true, in which case the weight will be set back to automatic.

(25) SDK: ILxKeyframe interface
         LXxMETHOD( LxResult,
 SetWeight) (
         LXtObjectID              self,
         double                   weight,
         unsigned int             reset,
         unsigned int             side);

Adding and Removing Keys

These methods allow keys to be created at the given time (or other independent parameter) and value.

(26) SDK: ILxKeyframe interface
         LXxMETHOD( LxResult,
 AddF) (
         LXtObjectID              self,
         double                   time,
         double                   value);
 
         LXxMETHOD( LxResult,
 AddI) (
         LXtObjectID              self,
         double                   time,
         int                      value);

This deletes the current key.

(27) SDK: ILxKeyframe interface
         LXxMETHOD( LxResult,
 Delete) (
         LXtObjectID              self);

Keyframe User Class

The keyframe user class has a special constructor that takes an envelope user object, from which the enumerator is extracted.

(28) User Class: Keyframe method
 CLxUser_Keyframe (
         CLxLoc_Envelope         &env)
 {
         LXtObjectID              obj;
 
         _init ();
         if (env.test () && LXx_OK (env.Enumerator (&obj)))
                 take (obj);
 }

There is also a function to set the enumerator given any COM object. The method will clear the enumerator and return false if the object does not present an ILxEnvelope interface.

(29) User Class: Keyframe method
         bool
 fromEnvObject (
         ILxUnknownID             obj)
 {
         CLxLoc_Envelope          env (obj);
         LXtObjectID              enObj;
 
         if (env.test () && LXx_OK (env.Enumerator (&enObj)))
                 return take (enObj);
 
         clear ();
         return false;
 }

Easier method for getting the time (or independent parameter) of the key. This should be fine as long as you know there is a valid current key.

(30) User Class: Keyframe method
         double
 Time ()
 {
         double                   time = 0.0;
 
         GetTime (&time);
         return time;
 }

Alternate methods for reading the value in the 90% case of an unbroken key.

(31) User Class: Keyframe method
         LxResult
 Value (
         double                  *val)
 {
         return GetValueF (val, LXiENVSIDE_IN);
 }
 
         double
 Value ()
 {
         double                   val = 0.0;
 
         GetValueF (&val, LXiENVSIDE_IN);
         return val;
 }
 
         LxResult
 Value (
         int                     *val)
 {
         return GetValueI (val, LXiENVSIDE_IN);
 }
 
         int
 IntValue ()
 {
         int                      val = 0;
 
         GetValueI (&val, LXiENVSIDE_IN);
         return val;
 }

The breaking and controlling side can be read independently.

(32) User Class: Keyframe method
         unsigned int
 Broken ()
 {
         unsigned int             flags = 0;
 
         GetBroken (&flags, 0);
         return flags;
 }
 
         unsigned int
 ActiveSide ()
 {
         unsigned int             flags, side = LXiENVSIDE_BOTH;
 
         GetBroken (&flags, &side);
         return side;
 }

The other key attributes can be read without error checking, although sidedness tends to be important for these so that is provided.

(33) User Class: Keyframe method
         double
 Slope (
         unsigned int             side)
 {
         double                   val = 0.0;
 
         GetSlope (&val, side);
         return val;
 }
 
         LXtSlopeType
 SlopeType (
         unsigned int             side)
 {
         LXtSlopeType             val = LXiSLOPE_DIRECT;
 
         GetSlopeType (&val, 0, side);
         return val;
 }
 
         bool
 Weighted (
         unsigned int             side)
 {
         LXtSlopeType             val;
         unsigned int             test;
 
         GetSlopeType (&val, &test, side);
         return (test != 0);
 }
 
         double
 Weight (
         unsigned int             side)
 {
         double                   val = 0.0;
 
         GetWeight (&val, side);
         return val;
 }

Empty Keyframe Python user class.

(34) PY: Keyframe method
 pass

Gradient Stacks

This is needed to have an object to evaluate in the SDK context.

(35) SDK: Declarations
 #define LXu_GRADIENTFILTER      "ACCD7C33-D246-4FE5-ABA0-079F225BBB34"

(36) SDK: ILxGradientFilter interface
         LXxMETHOD( double,
 Evaluate) (
         LXtObjectID              self,
         double                   inVal);
 
     LXxMETHOD( LxResult,
 AddRef) (
     LXtObjectID          self);
 
     LXxMETHOD( LxResult,
 Release) (
           LXtObjectID            self);

(37) User Class: GradientFilter method

Empty GradientFilter Python user class.

(38) PY: GradientFilter method
 pass