SOLVED merge BaceCointainer from one object to another.

Hello PluginCafe! 🙂

I have an object generator plugin which already has its own Base Container based on .res file.

I need to create a new tab directly from .pyp file which will contain attributes of another object. As I know, this task should be accomplished via GetDDescription.

I tried 2 different methods to import BaseContainer of null object into my plugin.

this is the first attempt. But the problem is that it completely overrode the existing container.

    def GetDDescription(self, node, description, flags):

        if not description.LoadDescription(c4d.Onull): return False

        return (True, flags | c4d.DESCFLAGS_DESC_LOADED)

Then I tried another method but seems like it does not work.

    def GetDDescription(self, node, description, flags):

        data = node.GetDataInstance()
        nullData = c4d.BaseObject(node.GetType()).GetData()
        if not description.LoadDescription(node.GetType()): return False

        return (True, flags | c4d.DESCFLAGS_DESC_LOADED)

Also, it is worth mentioning that when the null shape is set to 'Dot' other parameters are ghosted and I need to import this feature as well. Nut without manually ghosting them from via GetDEnabling.

It is worth mentioning that I know how to INCLUDE desc data from other objects via .res file but with this method, I will have to manually define cases in which, parameters will be ghosted.

hello @merkvilson,
sorry for the delay but i have to do some research, there's no "one function" solution.

I'm still searching in fact, I didn't found any solutions that satisfy your request, here's what i found so far. Depending on what you are trying to achieve, this could be "enough"

Some clue
1 - Merging Descriptions
One simple way could be create a tab and iterate through the description of the target and add the fields like so.

#after loading the description in GetDDescription
   child = node.GetDown()

        if child:

            # add a group to received the data
            gid = c4d.DescID(c4d.DescLevel(6000, c4d.DTYPE_GROUP, node.GetType()))
            if not singleid or not cid.IsPartOf(singleid):
                bc = c4d.GetCustomDataTypeDefault(c4d.DTYPE_GROUP)
                bc[c4d.DESC_NAME] = child.GetName()
                if not description.SetParameter(gid, bc, 0):
                    raise ValueError("error adding a tab group in the object")

            # get the description of a null object.
            nullDescription = child.GetDescription(c4d.DESCFLAGS_DESC_NONE)
            for bc, id, groupid in nullDescription:
                # the descLevel.creator can be used to filter the data (to not copy coordinate and thigs like that)
                if id[0].creator == child.GetType():
                    desclvl = id[0]
                    # offset the id far away so it will not collide with the one on the object itself.
           += 6000
                    # desclvl.creator = child.GetType() # maybe a good idea.
                    if not description.SetParameter(id, bc, gid):
                        raise ValueError("error adding a tab group in the object")

you can add everything of course and you will have to check if it's a group with

if id[0].dtype == c4d.DTYPE_GROUP:

and add the fields back to the groups.

2 - One solution maybe, adding a BaseLink and once open, it will show the parameters of the object.

3 - Some Ideas
If you merge the descriptions, you could be interesting into this function : TranslateDescID
We don't have any example on how to use it at the moment.

About reproducing the Enabling / Disabling state i didn't found anything yet without reproduce the way GetDEnabling is working.


Thanks, Manuel! 🙂

Don't spend more time on this. I already know about "brute force" methods, so I probably will use it in my code.

I'm making a free, open-source spline object plugin which will contain spline object properties.

Its Angle, Number, and Maximum Length values are ghosted according to the Interpolation Points value. I do not want to mislead people and use complicated snippets in my code, but if this is the only way, then I will INCLUDE spline data in the .res file which can be ghosted directly from .pyp file via GetDEnabling

    def GetDEnabling(self, node, id, t_data, flags, itemdesc):

        spline_type = node[c4d.SPLINEOBJECT_INTERPOLATION]

        if   spline_type == 0: ghost1,ghost2,ghost3 = False, False, False
        elif spline_type == 1: ghost1,ghost2,ghost3 = True , False, False
        elif spline_type == 2: ghost1,ghost2,ghost3 = True , False, False
        elif spline_type == 3: ghost1,ghost2,ghost3 = False, True , False
        elif spline_type == 4: ghost1,ghost2,ghost3 = False, True , True

        if id[0].id == c4d.SPLINEOBJECT_SUB:            return ghost1
        if id[0].id == c4d.SPLINEOBJECT_ANGLE:          return ghost2
        if id[0].id == c4d.SPLINEOBJECT_MAXIMUMLENGTH:  return ghost3

        return True

yea, sometime a direct approach is better.

By the way, and for those who are reading this post, you can use the ids found in Ospline.h
(i'm pretty sure you found them but just in case)