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)