Insert new obj after selected objs in OM [SOLVED]



  • On 17/01/2015 at 00:11, xxxxxxxx wrote:

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

    ---------
    Hi guys,

    In the prefs, there's an option to set where new objects are inserted. [Top, Previous, Next, Parent, Child, Root]
    But I want to move my plugin Object to a specific spot in the Object Manager on creation.
    _<_img src="http://www.genemagtoto.com/c4d/insert_issue.png" height="216" width="482" border="0" /_>_

    Basically I want my plugin object to be inserted after all selected objects, as it's a generator that reads the selected objects and I want to avoid priority issues.

    The problem is, C4D's insertion does not work when multiple objects are selected. Instead, the object is placed at the very top of the OM list.

    There's no document in my object's Init() method, so I can't do it there.
    I'm trying to do it in Message() via MSG_MENUPREPARE, but C4D locks up when I try calling node->InsertAfter(LastSelectedObject) in it.

    Any way of doing it?



  • On 17/01/2015 at 06:02, xxxxxxxx wrote:

    If you are letting the user create the object from the plugins menu, you probably will not have any control about its insertion since C4D does that using its defaults.  To circumvent that, you could hide your plugin in the menu (see RegisterObjectPlugin()), create a CommandData plugin and create/insert your object in its Execute() method.  The code below assumes that you don't want your object inserted at the root.  For only root insertion, you will need to traverse up to the root parent of the last selected object and insert it using that root parent as the predecessor.

    Bool Execute(BaseDocument* doc)
    {
    	AutoAlloc<AtomArray> aarray;
    	if (!aarray)
    		return FALSE;
    	BaseObject*	myPluginObj =	BaseObject::Alloc(myPlugin_ID);
    	if (!myPluginObj)
    		return FALSE;
    	doc->GetActiveObjects(*aarray, GETACTIVEOBJECTFLAGS_SELECTIONORDER);
    	LONG last =	aarray->GetCount()-1L;
    	doc->StartUndo();
    	// Consider case where there are no selected objects!
    	if (last < 0L)
    		doc->InsertObject(myPluginObj, NULL, NULL);
    	else
    		doc->InsertObject(myPluginObj, NULL, aarray[last]);
    	doc->AddUndo(UNDOTYPE_NEW, myPluginObj);
    	doc->EndUndo();
    	myPluginObj->Message(MSG_UPDATE);
    	EventAdd();
    	return TRUE;
    }
    


  • On 17/01/2015 at 17:58, xxxxxxxx wrote:

    Aye, I already have a function for getting the root, and that root's position in the OM.

      
    void CrawlUpCount(GeListNode *&root, Int64 &rootct, BaseList2D *obj){  
      GeListNode    *temp = static_cast<GeListNode*>(obj),  
                  *temp2 = temp;  
      rootct = 0;  
      
      for(temp; temp; temp = temp->GetUp()){  
          temp2 = temp;  
      }  
      root = temp2;//obj's root object  
      for(temp = temp2 ; temp; temp = temp->GetPred()){  
          temp2 = temp;  
          ++rootct;//root object's OM position  
      }  
    }  
    

    I just loop through all the selections, get the root with the highest "om index" and insert my object after that.

    I guess I'll keep the original plugin entry visible as well, in case people can't get used to the insertion point I'm trying to achieve.

    Thanks Robert!

    -gene



  • On 19/01/2015 at 14:41, xxxxxxxx wrote:

    Note: I reduced the topic name to fit in the [SOLVED] tag to help others know.

    Joey Gaspe
    SDK Support Engineer


Log in to reply