[Closed] Select FFD Control Point
I’m trying to write a script that selects FFD control points instead of using manual selection. I am able to access the points and set/get their positions, but it’s unclear to me how I can use the script to select them by index instead of manually selecting in the editor. For example I want to select ffd.control_point_1 but I get an error.
MAXScript reference:
There are two special considerations when accessing FFD control points. First, you can only access control points that have ALREADY been animated by hand, or by using the animateVertex() or the animateAll() MAXScript functions
I already call animateAll() in the script, I am able to access the control points from script but my question is how do I select them in the editor using code
oh, I missed that from your post.
I don’t know if maxscript method to select control points exists
but here’s what we can do about it
that’s what is going on under the hood when control points selection happens
void FFDMod::SelectSubComponent(
HitRecord *hitRec,
BOOL selected,
BOOL all,
BOOL invert)
{
int level = ip ? ip->GetSubObjectLevel() : SEL_LATTICE;
if (level==SEL_LATTICE) return;
if (theHold.Holding()) theHold.Put(new SelRestore(this));
while (hitRec) {
BOOL state = selected;
if (invert) state = !sel[hitRec->hitInfo];
if (state) sel.Set(hitRec->hitInfo); <-- this is what we need to emulate
else sel.Clear(hitRec->hitInfo);
if (!all) break;
hitRec = hitRec->Next();
}
NotifyDependents(FOREVER, PART_SELECT, REFMSG_CHANGE);
}
let’s emulate it using c# sdk
delete objects
gc()
t = Teapot()
ffd = FFD4x4x4()
addModifier t ffd
g = (dotNetClass "Autodesk.Max.GlobalInterface").Instance
hitRecord = g.HitRecord.create()
animatable = g.animatable.getanimbyhandle (dotNetObject "System.UIntPtr" (getHandleByAnim ffd))
select t
max modify mode
subObjectLevel = 1
-- .SelectSubComponent <Autodesk.Max.IHitRecord> hitRec <System.Boolean>selected <System.Boolean>all <System.Boolean>invert
for i = 0 to 27 do
(
hitRecord.HitInfo = i
animatable.SelectSubComponent hitRecord true false false
)
redrawViews()
as a bonus you don’t have to use animateAll to move/rotate/scale control points
(
tm = $.objecttransform
mod_tm = inverse (getModContextTM $ $.modifiers[1])
_tm = tm * mod_tm
-- .<Autodesk.Max.IMatrix3> Create <Autodesk.Max.IPoint3>U <Autodesk.Max.IPoint3>V <Autodesk.Max.IPoint3>N <Autodesk.Max.IPoint3>T
modtm = g.matrix3.create (g.point3.create _tm[1][1] _tm[1][2] _tm[1][3]) (g.point3.create _tm[2][1] _tm[2][2] _tm[2][3]) (g.point3.create _tm[3][1] _tm[3][2] _tm[3][3]) (g.point3.create _tm[4][1] _tm[4][2] _tm[4][3])
tm = g.Matrix3.create()
tm.IdentityMatrix()
pt = g.point3.create 0 0 10 -- offset
animatable.move (currentTime as integer) modtm tm pt false
redrawViews()
)