Method Groups for Class Control

The methods in this class are grouped below.

(Links go to the Control Class Reference page.)

New Methods in Max8
Control::BaseClone(ReferenceTarget *from, ReferenceTarget *to, RemapDir &remap)
Get / Set Value Methods
Control::GetValue(TimeValue t, void *val, Interval &valid, GetSetMethod method=CTRL_ABSOLUTE)=0
Control::SetValue(TimeValue t, void *val, int commit=1, GetSetMethod method=CTRL_ABSOLUTE)=0
Control::GetLocalTMComponents(TimeValue t, TMComponentsArg& cmpts, Matrix3Indirect& parentMatrix)
Post Clone Notification
Control::PostCloneNode()
Undo / Redo methods
Controllers, like objects and modifiers, need to be able to undo and redo themselves. Whenever a controller is about to modify its data, it checks the state of the global Hold object to see if it is holding. If so it must register a RestoreObject with the hold (see the Advanced Topics section eUndo/Redo). Controllers also support another type of undo and redo through two methods: CommitValue() and RestoreValue().
The purpose of this 'inner' hold and restore buffer is not to hold and restore the entire state of the controller, but to hold and restore the value of the controller at a single instant in time. When SetValue() is called on a controller with the commit parameter equal to zero, the controller records the new value, but does not necessarily modify any data. For example, a keyframe controller doesn't actually generate a new key -- it just updates a cache it maintains. Then, if the controller is asked to evaluate itself at the exact same TimeValue for which the controller was just set, it can just return the cached value.
The RestoreValue() method will simply throw out the temporary value whereas the CommitValue() method will cause the value to be actually committed (a key generated in the case of a keyframe controller).
The purpose of this inner hold and restore is for iterative procedures that need to set values many times at a single TimeValue and don't want to incur the overhead of things like recalculating the tangents at adjacent keys. Some examples of these types of procedures are inverse kinematics and collision detection.
Control::CommitValue(TimeValue t)
Control::RestoreValue(TimeValue t)
New Controller Assignment
Control::Copy(Control *from)=0
Control::IsReplaceable()
Lookat Controller methods
The following two methods work with lookat controllers. If the controller is not a lookat controller, these methods should be ignored.
Control::GetTarget()
Control::SetTarget(INode *targ)
Sub-Controllers
Control::GetPositionController()
Control::GetRotationController()
Control::GetScaleController()
Control::GetRollController()
Control::SetPositionController(Control *c)
Control::SetRotationController(Control *c)
Control::SetScaleController(Control *c)
Control::SetRollController(Control *c)
Control::GetXController()
Control::GetYController()
Control::GetZController()
Transform Controller methods
Control::ChangeParents(TimeValue t,const Matrix3& oldP, const Matrix3& newP,const Matrix3& tm)
Control::PinNodeChanged(RefMessage message,Interval changeInt, PartID &partID)
Control::NodeIKParamsChanged()
Control::InheritsParentTransform()
Control::GetInheritanceFlags()
Control::SetInheritanceFlags(DWORD f, BOOL keepPos)
IsLeaf / IsKeyable / IsColor
Control::IsLeaf()
Control::IsKeyable()
Control::IsColorController()
Ease / Mulitplier Curve and ORT methods
The following methods involve ease and multiplier curves. See the sample code after the methods GetValue() and SetValue() to see how these methods are used.
Control::CanApplyEaseMultCurves()
Control::ApplyEase(TimeValue t,Interval &valid)
Control::AppendEaseCurve(Control *cont)
Control::NumEaseCurves()
Control::DeleteEaseCurve(int i)
Control::GetMultVal(TimeValue t,Interval &valid)
Control::AppendMultCurve(Control *cont)
Control::NumMultCurves()
Control::DeleteMultCurve(int i)
Range Type for Controller
When a user brings up the track view and sets the out of range types for the controller the following two methods are called.
Control::GetORT(int type)
Control::SetORT(int ort,int type)
Control::EnableORTs(BOOL enable)
The methods below are used with Inverse Kinematics
The following is an overview of the control flow of the system calling these IK methods on the controller during IK calculations:
First the system calls EnumIKParams() once to get the number of IK parameters (degrees of freedom) from the plug-in. This lets the system know how many parameters the controller has. This happens only once when the entire chain is set up. For example during interactive IK, when the user presses the mouse button down the chain is set up. In applied IK when the user presses the Apply IK button the chain is set up.
Next the IK task is defined. For example, if the user is doing interactive IK they press the mouse button down and the IK chain is set up. Next they move the mouse a few pixels. This results in a delta for the end effector. This defines the task for the end effector. The end effector wants to move some delta or rotate some amount. This has defined a task to be solved.
In order to solve the task the system must iterate towards a solution.
To do this it first needs to compute the derivatives of all the parameters. The system calls CompDerivs() on the controller. The controller computes the derivative and tells the system by calling methods on the IKDeriv argument passed to the method. It provides its derivative for each of the parameters.
Next the system uses this derivative information to formulate a change in the parameter that will get closer to the solution. The system then computes an amount to change the parameter and then calls IncIKParams(). The delta passed to this method is the amount of change it wants in the parameter. The controller then applies this change (perhaps not all of it due to constraints it might have) and returns the amount that was applied.
This has completed a single iteration. All the parameters have been adjusted a bit and hopefully we have move closer to a solution. At this point the system calls CompDerivs() again because just moving the parameters a small amount may have actually changed the derivative. The cycle begins again.
When the IK solver has reached its solution the IK task is finished. Below are the methods that must be implemented to participate in this process.
Control::EnumIKParams(IKEnumCallback &callback)
Control::CompDeriv(TimeValue t,Matrix3& ptm, IKDeriv& derivs,DWORD flags)
Control::IncIKParam(TimeValue t,int index,float delta)
Control::ClearIKParam(Interval iv,int index)
Control::InitIKJoints(InitJointData *posData,InitJointData *rotData)
Control::InitIKJoints2(InitJointData2 *posData, InitJointData2 *rotData)
Control::GetIKJoints(InitJointData *posData,InitJointData *rotData)
Control::GetIKJoints2(InitJointData2 *posData, InitJointData2 *rotData)
Control::GetDOFParams(TimeValue t, Matrix3 &ptm, DOFParams &dofs, BOOL nodeSel)
Control::CreateLockKey(TimeValue t, int which)
Control::MirrorIKConstraints(int axis, int which, BOOL pasteMirror=FALSE)
Control::TerminateIK()
Control::NodeIKParamsChanged()
Control::TMInvalidated()
Control::OKToBindToNode(INode *node)
Control::PreventNodeDeletion()
Control::EvalVisibility(TimeValue t, View &view, Box3 pbox, Interval &valid)
Control::VisibleInViewports()
Control::CanInstanceController()
Control::CloneControl(Control *ctrl,RemapDir &remap)
Not in Class Control
The following functions are not part of class Control but are provided for use. These functions are for use by Position or Rotation controllers. Position controllers would use the Point3 versions and Rotation controllers would use the Quat versions.
 
void QuatEnumIKParams(Control *cont,IKEnumCallback &callback);
 
BOOL QuatCompDeriv(Control *cont,TimeValue t,Matrix3& ptm, IKDeriv& derivs,DWORD flags);
 
float QuatIncIKParam(Control *cont,TimeValue t,int index,float delta);
 
void QuatBeginIKParams(Control *cont,IObjParam *ip, ULONG flags, Animatable *prev);
 
void Point3EnumIKParams(Control *cont,IKEnumCallback &callback);
 
BOOL Point3CompDeriv(Control *cont,TimeValue t,Matrix3& ptm, IKDeriv& derivs,DWORD flags);
 
float Point3IncIKParam(Control *cont,TimeValue t,int index,float delta);
 
void Point3BeginIKParams(Control *cont,IObjParam *ip, ULONG flags,Animatable *prev);
The methods below deal with copying and pasting IK parameters in the Hierarchy branch.
Control::CanCopyIKParams(int which)
Control::CopyIKParams(int which)
Control::CanPasteIKParams(IKClipObject *co,int which)
Control::PasteIKParams(IKClipObject *co,int which)
Controllers that want to have a gizmo (apparatus) available in the scene will implement these methods
Control::Display(TimeValue t, INode* inode,  ViewExp *vpt, int flags)
Control::HitTest(TimeValue t, INode* inode, int type,  int crossing, int flags, IPoint2 *p, ViewExp *vpt)
Control::GetWorldBoundBox(TimeValue t,INode* inode,  ViewExp *vpt, Box3& box)
Control::ActivateSubobjSel(int level, XFormModes& modes)
Control::SelectSubComponent(CtrlHitRecord *hitRec,  BOOL selected, BOOL all, BOOL invert=FALSE)
Control::ClearSelection(int selLevel)
Control::SubObjectIndex(CtrlHitRecord *hitRec)
Control::SelectAll(int selLevel)
Control::InvertSelection(int selLevel)
Reference Coordinate System Definition
When the user is in a sub-object selection level, the system needs to get the reference coordinate system definition from the current controller being edited so that it can display the axis.
Two methods allows the system to do this:
Control::GetSubObjectCenters(SubObjAxisCallback *cb, TimeValue t,INode *node)
Control::GetSubObjectTMs(SubObjAxisCallback *cb, TimeValue t,INode *node)
Modify sub-object apparatuses
Control::SubMove(TimeValue t, Matrix3& partm, Matrix3& tmAxis, Point3& val, BOOL localOrigin=FALSE )
Control::SubRotate(TimeValue t, Matrix3& partm, Matrix3& tmAxis, Quat& val, BOOL localOrigin=FALSE ){}
Control::SubScale(TimeValue t, Matrix3& partm, Matrix3& tmAxis, Point3& val, BOOL localOrigin=FALSE)
Control::RescaleTime(Interval oseg, Interval nseg)
Control::GetDrawPixelStep()
Control::GetExtentTimeStep()
Load / Save
Control::Save(ISave *isave)
Control::Load(ILoad *iload)
These are implemented to handle ease curves
If a controller is a leaf controller, then it MUST NOT BY DEFINITION have any sub-controllers or references. If it is a leaf controller, then these are implemented to handle the ease curve list. If it is NOT a leaf controller, then these can be overridden.
 
From ReferenceMaker. See this class for details on these methods.
int NumRefs()
RefTargetHandle GetReference(int i)
void SetReference(int i, RefTargetHandle rtarg)
 
From Animatable. See this class for details on these methods.
int NumSubs()
Animatable* SubAnim(int i)
TSTR SubAnimName(int i)
 
Default implementations of some Animatable methods:
void* GetInterface(ULONG id)
int PaintFCurves(ParamDimensionBase *dim,
 HDC hdc, Rect& rcGraph, Rect& rcPaint,
 float tzoom, int tscroll, float vzoom, int vscroll, DWORD flags )
int GetFCurveExtents(ParamDimensionBase *dim,
 float &min, float &max, DWORD flags)