Message for link set

On 07/05/2015 at 19:14, xxxxxxxx wrote:

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

I have a bit of code where I check if a link has been...or perhaps is about to be set and I use that link to setup other links:

	switch (msg.GetId())
			if (msg.GetInt32(BFM_DRAG_FINISHED)) {
				Int32 activeTab;
				GetInt32(IDC_TAB_1, activeTab); //Get current active tab
				for(maxon::HashMap<UInt, objEntry>::Iterator i = _objTable.Begin(); i != _objTable.End(); ++i) {
					Bool bFound = false;
					Int32 guiID = 0;
					if(activeTab == IDC_GRP_TAB1) {
						guiID = i.GetValue().GetsObjID();
						bFound = CheckDropArea(guiID, msg, TRUE, TRUE);
					else if(activeTab == IDC_GRP_TAB2) {
						guiID = i.GetValue().GettObjID();
						bFound = CheckDropArea(guiID, msg, TRUE, TRUE);
					if(bFound) {
						//GePrint("Object dragged to: " + String::IntToString(guiID));
						void* obj = nullptr;
						Int32 type = 0;
						GetDragObject(msg, &type, &obj);
						if((type == DRAGTYPE_ATOMARRAY) && (((AtomArray* )obj)->GetCount() == 1) && ((AtomArray* )obj)->GetIndex(0)) {
							AutoFillObj(guiID, (BaseObject* )((AtomArray* )obj)->GetIndex(0));

Thing is, the LinkBoxGui's update but when I use these objects later I find that they don't actually exist. It's as if when I call SetLink in my AutoFillObj function the Gui's get updated but the links aren't propagated. Also when I use the picker (pickwhip, selection thingy) for the link box's to pick an object the  BFM_DRAGRECEIVE event doesn't run. Obviously because it's not a drag and drop. I think I can fix this if I knew what event in general happens when a link is set in a LinkBoxGui.

On 07/05/2015 at 23:31, xxxxxxxx wrote:


Never filter BFM_DRAGRECEIVE nor check BFM_DRAG_FINISHED for gadgets in a dialog: this is automatically handled by Cinema.

To dynamically check the objects that can be accepted for a link gadget in a dialog, listen for MSG_DESCRIPTION_CHECKDRAGANDDROP in GeDialog::Message(). See LINK documentation.
To be notified after an object has been set for a link in a dialog, listen for BFM_ACTION in GeDialog::Message(). See BFM_ACTION documentation.

On 08/05/2015 at 14:49, xxxxxxxx wrote:

Cool cool, so I got that and it's great that the code is shorter and more clean, but when I set links in my auto fill function they still don't work later in the program:

	switch (msg.GetId())
        case BFM_ACTION:
            Int32 guiID = msg.GetInt32(BFM_ACTION_ID);
            GePrint("Action performed on GuiID: " + String::IntToString(msg.GetInt32(BFM_ACTION_ID)));
			LinkBoxGui* linkGui = (LinkBoxGui* )FindCustomGui(guiID, CUSTOMGUI_LINKBOX);
				AutoFillObj(guiID, (BaseObject * )linkGui->GetLink(GetActiveDocument()));
	return GeDialog::Message(msg, result);
void someDialog::AutoFillObj(Int32 guiID, BaseObject* dropObj)
	BaseDocument* doc = GetActiveDocument();
	Bool bCharFound = false;
	Bool bNumFound = false;
	Int32 charPos = -1;
	String sName = dropObj->GetName();
	String rootObjName;
	String aObjName;
	String bObjName;
	//GePrint("Object dropped is: " + sName);
	// let's check and see if 'a' is at the beginning of the name, if not we will check for 'alpha'
	bCharFound = sName.Left(1) == "a";
	charPos = 1;
	if(!bCharFound && sName.GetLength() > 4) {
		bCharFound = sName.Left(4) == "Alpha;
		charPos = 4;
	// let's parse the string if we found a l or Left and then see if a number is on the end
	if(bCharFound) {
		rootObjName = sName.SubStr(charPos, sName.GetLength()-1);
		bNumFound = sName.Right(1) == "1";
		if(bNumFound) rootObjName = rootObjName.SubStr(0,rootObjName.GetLength()-1);
		// so now we know there's a prefix and maybe a number, we have the root name of the object
		// so we'll rebuild the name depending on if there's numbers or not, and SetLinks 
		// automatically for the user
		//GePrint("Found an a or Alpha." ); //debug
		if(guiID > 2999 && guiID < 4000) {
			//GePrint("Name with prefix/postfix removed: " + rootObjName); //debug
				for(int i = 0; i < 3; i++) {
					if(i > 0) {
						if(charPos == 1)
							aObjName = "a" + rootObjName + String::IntToString(i+1);
						else if(charPos == 4)
							aObjName = "Alpha" + rootObjName + String::IntToString(i+1);
						BaseObject* aObj = doc->SearchObject(aObjName);
						LinkBoxGui* aObjLink = (LinkBoxGui* )FindCustomGui(guiID + i, CUSTOMGUI_LINKBOX);
						if(leftObj) aObjLink->SetLink(leftObj);
					if(charPos == 1)
						rightObjName = "r" + rootObjName + String::IntToString(i+1);
					else if(charPos == 4)
						rightObjName = "Right" + rootObjName + String::IntToString(i+1);
					BaseObject* bObj = doc->SearchObject(bObjName);
					LinkBoxGui* bObjLink = (LinkBoxGui* )FindCustomGui(guiID + 1000 + i, CUSTOMGUI_LINKBOX);
					if(rightObj) bObjLink->SetLink(rightObj);
			else {
				if(charPos == 1)
					bObjName = "b" + rootObjName;
				else if(charPos == 4)
					bObjName = "Beta" + rootObjName;
				BaseObject* bObj = doc->SearchObject(bObjName);
				LinkBoxGui* bObjLink = (LinkBoxGui* )FindCustomGui(guiID + 1000, CUSTOMGUI_LINKBOX);
				if(rightObj) bObjLink->SetLink(bObj);

Is this an issue with something being dirty or me not running some event or message after these SetLinks? Basically only the objects I manually drag into Linkbox's have links, the ones I'm auto filling for the user don't seem to be used later on even though the GUI updates in Cinema showing that the links are there.

On 11/05/2015 at 09:10, xxxxxxxx wrote:

It's hard to tell without being able to debug such piece of code.
But EventAdd() should be definitely called after the link is set so that Cinema is notified  to update the active document.