Notifications
Clear all

[Closed] [sdk] 'Storing' a controller

What would be the best way to save a controller selection? A users picks one using the TrackViewPickDlg() and I end up with a IControl which is the picked controller. Now I want to save that selection in the scene, as an AppDataChunk for example but that only saves strings. I probably could find ‘a’ path to the controller but that is not very pretty. And controllers don’t have handles like nodes do. Any ideas?

4 Replies

they have anim handles but they are not save safe so no use to you anyway also appdata is any binary data you just need to allocate with MaxAlloc() (also not much help). Your best bet is use the a IParamBlock2 type TYPE_REFTARG_TAB in a parameter block

then set and get with

virtual BOOL  SetValue (ParamID id, TimeValue t, ReferenceTarget *v, int tabIndex=0)=0
  virtual BOOL  GetValue (ParamID id, TimeValue t, ReferenceTarget *&v, Interval &ivalid, int tabIndex=0)=0

there also an example of appdata being used to store on an Animatable in \maxsdk\samples\utilities\appdata.cpp not exactly what you want but not to much work knock it into shape…
say to add a simple selected tag to each control selected.

something (untested) like

bool SetControlPicked(Control* cntrl, BOOL picked)
 {
 	int* ptr = static_cast<int*>(MAX_malloc(sizeof(int)));
 	if(!ptr)
 		return false;
 		
 	*ptr = picked;
 	cntrl->RemoveAppDataChunk(MY_CLASS_ID, MY_SUPERCLASS_ID, MY_PICK_ID); 
 	cntrl->AddAppDataChunk(MY_CLASS_ID, MY_SUPERCLASS_ID, MY_PICK_ID, sizeof(int), ptr);
 	return true;
 }
 
 BOOL GetControlPicked(Control* cntrl)		
 {
 	AppDataChunk* appdata = cntrl->GetAppDataChunk(MY_CLASS_ID, MY_SUPERCLASS_ID, MY_PICK_ID); 
 	return appdata ? *static_cast<int*>(appdata->data) : FALSE;
 }	

Cheers, this looks like it could work!

how you might handle enumerating or clearing a “tag” after a file is loaded

much the same just made just moved it up a class or 2
bool SetControlPicked(Animatable* anim, BOOL picked)
    {
    	int* ptr = static_cast<int*>(MAX_malloc(sizeof(int)));
    	if(!ptr)
    		return false;
    		
    	*ptr = picked;
    	anim->RemoveAppDataChunk(MY_CLASS_ID, MY_SUPERCLASS_ID, MY_PICK_ID); 
    	anim->AddAppDataChunk(MY_CLASS_ID, MY_SUPERCLASS_ID, MY_PICK_ID, sizeof(int), ptr);
    	return true;
    }
    
    BOOL GetControlPicked(Animatable *anim)		
    {
    	AppDataChunk* appdata = anim->GetAppDataChunk(MY_CLASS_ID, MY_SUPERCLASS_ID, MY_PICK_ID); 
    	return appdata ? *static_cast<int*>(appdata->data) : FALSE;
    }	
enumerator classes
class ClearAllPickedCntrls : public Animatable::EnumAnimList
    {
    public:
    
    	bool  proc(Animatable *anim)
    	{
    		anim->RemoveAppDataChunk(MY_CLASS_ID, MY_SUPERCLASS_ID, MY_PICK_ID); 
    		return true;
    	}
    };
    
    class enumPickedCntrl : public Animatable::EnumAnimList
    {
    public:
    	Tab<Animatable*> cntrls;
    
    	bool  proc(Animatable *anim)
    	{
    		if(GetControlPicked(anim))
    			cntrls.Append(1,&anim);
    		return true;
    	}
    };
usage where ip is pointer to the max interface...
enumPickedCntrl enumerator;
    ClearAllPickedCntrls clearPicked;
    
    Animatable* root = ip->GetScenePointer();
    root->EnumerateAllAnimatables(enumerator); // collect all the "tagged" controls
    int nctrl = enumerator.cntrls.Count();   //  in the cntrls tab
    root->EnumerateAllAnimatables(clearPicked);

the clearPicked enumeration is probably overkill having already collected the relevant Controls