Call button of BaseObject

On 26/01/2017 at 12:01, xxxxxxxx wrote:

User Information:
Cinema 4D Version:   R15 
Platform:   Windows  ;   
Language(s) :     C++  ;

---------
Hello,

I am translating a Python script to C++, but I don't find how to perform the CallButton.

Python :

        defMaillage = c4d.BaseObject(1024543) # Ocameshdeformer  
      inex = c4d.InExcludeData()  
      inex.InsertObject(peau, 1)  
      defMaillage[c4d.ID_CA_MESH_DEFORMER_OBJECT_CAGE_INCLUDE] = inex  
      defMaillage[c4d.ID_CA_MESH_DEFORMER_OBJECT_EXTERNAL] = c4d.ID_CA_MESH_DEFORMER_OBJECT_EXTERNAL_SURFACE  
      doc.InsertObject(peau)  
      defMaillage.InsertUnder(soi.obj)  
      c4d.CallButton(defMaillage, c4d.ID_CA_MESH_DEFORMER_OBJECT_INITIAL)

C++ :

    BaseObject* defMaillage = BaseObject::Alloc(1024543); //Ocameshdeformer  
  BaseContainer* bc = defMaillage->GetDataInstance();  
  InExcludeData* inex = (InExcludeData* )bc->GetCustomDataType(ID_CA_MESH_DEFORMER_OBJECT_CAGE_INCLUDE, CUSTOMDATATYPE_INEXCLUDE_LIST);  
  inex->InsertObject(_peau, 1);  
  bc->SetInt32(ID_CA_MESH_DEFORMER_OBJECT_EXTERNAL, ID_CA_MESH_DEFORMER_OBJECT_EXTERNAL_SURFACE);  
  _doc->InsertObject(_peau, nullptr, nullptr);  
  defMaillage->InsertUnder(_obj);  
// CallButton ?

How can we simulate the click to the button action ?

By the way, the InExcludeData* inex is null here, I don't know why. : /

Thanks,

César

On 27/01/2017 at 07:11, xxxxxxxx wrote:

Hi César,

basically CallButton() in Python is just a convenience function wrapping some messages.

In most cases it will be enough to send a MSG_DESCRIPTION_COMMAND, like so:

	DescriptionCommand dc;
	dc.id = DescID(DescLevel(id, DTYPE_BUTTON, op->GetType()));
	op->Message(MSG_DESCRIPTION_COMMAND, (void* )&dc);

In special cases (and it doesn't hurt to do it all the time, so does CallButton internally as well) a few more messages are needed:

	DescriptionCheckUpdate dcu;
	dcu.doc = GetActiveDocument();  // NOTE: this depends, in NodeData derived plugins NEVER use GetActiveDocument(), in CommandData it's fine though
	dcu.descid = &dc.id;
	dcu.drawflags = 0;
	op->Message(MSG_DESCRIPTION_CHECKUPDATE, (void* )&dcu);
	op->Message(MSG_DESCRIPTION_USERINTERACTION_END);
	op->Message(MSG_TOOL_RESTART);

For the nullptr question: For some reason the InExcludeList of the Mesh Deformer (opposed to other objects I checked) is uninitialized.
So if you get a nullptr, you need to initialize it with default data first. Like so:

	if (!inex)
	{
		// Init InExcludeList with default data 
		bc->SetData(ID_CA_MESH_DEFORMER_OBJECT_CAGE_INCLUDE, GeData(CUSTOMDATATYPE_INEXCLUDE_LIST, DEFAULTVALUE));
		inex = (InExcludeData* )bc->GetCustomDataType(ID_CA_MESH_DEFORMER_OBJECT_CAGE_INCLUDE, CUSTOMDATATYPE_INEXCLUDE_LIST);
	}
	if (!inex)
		return false; // something went wrong, error
  
	// go on with your code here...

On 27/01/2017 at 10:27, xxxxxxxx wrote:

Thanks, it works very well !