Solved Update in UD link does not update object in Volume Builder Object List

I am trying to automatically update the object list in a Volume Builder. I am using a User Data link. When I drop a new object in the UD link field, the object in the Volume Builder list does not update. Is there a way to do this? Below is the code I am using:

import c4d
from c4d.modules import volume
import pprint
from c4d import documents
from c4d import utils


Bake_Button = 240

obj = op.GetObject()
#obj = doc.SearchObject("Spritz 4.0")
UD = obj.GetUserDataContainer()

bottle = obj[c4d.ID_USERDATA,5]
set_bottle = 242
delete_bottle = 243

document = op.GetDocument()
settings = c4d.BaseContainer()
selected = doc.GetActiveObjects(0)
taglist = doc.GetActiveTags()

presets = obj[c4d.ID_USERDATA,13]
drop_name = obj[c4d.ID_USERDATA,197]




def set_delete_UD_object():

    vol_build = doc.SearchObject("VB Drops")
    vol_build_drip_1 = doc.SearchObject("VB Drip 1")

    if obj[c4d.ID_USERDATA, set_bottle] == 1:
        vol_build.AddSceneObject(bottle, index = 0)
        vol_build.SetBoolMode(0, 2)
        vol_build_drip_1.AddSceneObject(bottle, index = 0)
        vol_build_drip_1.SetBoolMode(0, 2)

        obj[c4d.ID_USERDATA, set_bottle] = False
        for descId, container in UD: # SET Object hide
            if descId[1].id == 266:
                container[c4d.DESC_HIDE] = True
                obj.SetUserDataContainer(descId, container)

        for descId, container in UD: # DELETE Object show
            if descId[1].id == 267:
                container[c4d.DESC_HIDE] = False
                obj.SetUserDataContainer(descId, container)


    if obj[c4d.ID_USERDATA, delete_bottle] == 1:
            vol_build.RemoveObject(0)
            vol_build_drip_1.RemoveObject(0)

            obj[c4d.ID_USERDATA, delete_bottle] = False
            for descId, container in UD: # SET Object show
                if descId[1].id == 267:
                    container[c4d.DESC_HIDE] = True
                    obj.SetUserDataContainer(descId, container)

            for descId, container in UD: # DELETE Object hide
                if descId[1].id == 266:
                    container[c4d.DESC_HIDE] = False
                    obj.SetUserDataContainer(descId, container)

def main():

    set_delete_UD_object()

Hi @Swinn no worries, but please make sure to use Q&A functionality :wink:.

According to your description, I made my own setup, with a Null which gets a userData link. Then I attach a python script to this Null object.
I also created a Volume Builder called Volume Builder. Using the following code it's working as expected.

import c4d
from c4d.modules import volume

def main():
    # Get the host object and the linked obj from the user data
    obj = op.GetObject()
    linkedObj = obj[c4d.ID_USERDATA,1]
    if not linkedObj: return

    # Get the volume builder
    vBuilder = doc.SearchObject("Volume Builder")
    if not vBuilder and not vBuilder.CheckType(c4d.Ovolumebuilder): return

    # Check if our object is not already in the list
    allowedObj = [linkedObj] # Maybe you got some other object you don't want to delete
    alreadyIn = False
    for i in xrange(0, vBuilder.GetListEntryCount()):
        o = vBuilder.GetInputObject(i)

        # If is not in our list of allowed objects we remove it
        if o not in allowedObj:
            vBuilder.RemoveObject(i)
        
        # If our linked object is already in the list
        if o == linkedObj:
            alreadyIn = True
        
    # Only add if the object is not already in the list
    if not alreadyIn:
        vBuilder.AddSceneObject(linkedObj)
        vBuilder.SetBoolMode(0, 2)

Maybe you can try to reduce your code. Moreover, it looks like you are adding and deleting the bottle at the same time.

Additionally, I would not recommend you to define variables in global space of the script but rather in local space of your function.

if you have any question, please me know!
Cheers,
Maxime.

This is starting to work but it now adds 2 user data objects. As well, do I need to add an event to get a refresh? Also, I am trying to move the linked user data object to the top of the hierarchy but it doesn't want to go there. And finally, MIST Cloner and SMALL DROPS Cloner keep switching places.

import c4d
from c4d.modules import volume

def main():
    # Get the host object and the linked obj from the user data
    obj = op.GetObject()
    linkedObj = obj[c4d.ID_USERDATA,5]
    if not linkedObj: return

    # Get the volume builder
    vBuilder = doc.SearchObject("VB Drops")
    if not vBuilder and not vBuilder.CheckType(c4d.Ovolumebuilder): return

    # Check if our object is not already in the list
    allowedObj = [linkedObj] # Maybe you got some other object you don't want to delete
    alreadyIn = False
    for i in xrange(0, vBuilder.GetListEntryCount()):
        o = vBuilder.GetInputObject(i)

        # If is not in our list of allowed objects we remove it
        if o not in allowedObj:
            vBuilder.RemoveObject(i)

        # If our linked object is already in the list
        if o == linkedObj:
            alreadyIn = True

    # Only add if the object is not already in the list
    if not alreadyIn:
        vBuilder.AddSceneObject(linkedObj, index = 0)
        vBuilder.SetBoolMode(0, 2)

I have added index = 0 to your code but it doesn't seem to work.

0_1539033606921_CINEMA 4DScreenSnapz008.jpg

0_1539033625748_CINEMA 4DScreenSnapz009.jpg

Hi @Swinn, if you add another object through another UserData link, then you have to properly insert it, and keep track of it inside the volume builder as well and handle the "refresh" yourself as I demonstrated in my previous example.
Since you are doing it for more than one object, in my previous example I used a variable called alreadyIn, to keep track of my object. But it was a very simple example.
If you are switching to multiple objects, it may be worth making a data structure where you hold the objects, and if these are already inserted or not, in order to be able to track your objects properly.

In the end this is probably more an algorithmic problem, and not that much API related. Thus we as the SDK Team can only give advice and suggest a direction.

Moreover, in your code, I don't see any link to the new UserData link. And you are still deleting 'BIG DROPS CLONER' and all others custom cloners you have in your image. Are you sure you use the same code than the one you posted?

Furthermore vBuilder.AddSceneObject(linkedObj, index = 0) respects the order, with index parameter set to zero linkedObj will be correctly inserted at the top of the list.

Cheers,
Maxime!

@m_adam Cool. Thank-you for your time and patience. :relaxed: