User data Preset [SOLVED]

On 27/01/2017 at 15:34, xxxxxxxx wrote:

I am trying to set up a User Data preset. So far, I have some radio buttons. The user chooses a preset. He then makes some changes. I want him to be able to click on a button and the data is transferred to a User Preset. Here is what I have:

import c4d
import collections

Type = collections.namedtuple('Type', 'name value_id presets')
Preset = collections.namedtuple('Preset', 'name group_id')

Container = [
    Type('Spritz! v2', 13, {
        0: Preset('Classic Beer', 21),
        1: Preset('Cool Pop', 216),
        2: Preset('Dew', 244),
        3: Preset('Fridge', 272),
        4: Preset('Summer', 440),
        5: Preset('Mountain', 1),
        6: Preset('Cooler', 300),
        7: Preset('Picnic', 328),
        8: Preset('Heat Wave', 356),
        9: Preset('Drive-in', 384),
        10: Preset('User Preset 1', 480),
        11: Preset('User Preset 2', 541),
        12: Preset('User Preset 3', 574),
        13: Preset('User Preset 4', 607),
        }),
    ]

Ids = {
    'on_off_switch': 184,
    'bake_button': 432,
    }

def get_selected_type(rig) :
    return Container[0]

def update_parameters(rig) :

obj = doc.SearchObject('Spritz!')

=============================================================================

Internals start here

=============================================================================

g = {
    'dcount': None,

# Automatically computed from the Container data. Contains
    # the IDs of the groups that are hidden except if they're selected
    # by their preset value.
    'group_ids': None,
    }

def update_visibility(rig) :
    build_caches()

selected_type = get_selected_type(rig)
    preset_value = rig[c4d.ID_USERDATA, selected_type.value_id]
    selected_preset = selected_type.presets[preset_value]
    
    print (preset_value)

for desc_id, desc_bc in rig.GetUserDataContainer() :
        elem_id = desc_id[1].id
        if elem_id not in g['group_ids']:
            continue

# Update the parameter to its new hidden status if it doesn't correspend.
         
        hidden = (elem_id != selected_preset.group_id)
        if bool(desc_bc[c4d.DESC_HIDE]) ^ hidden:
            desc_bc[c4d.DESC_HIDE] = hidden
            rig.SetUserDataContainer(desc_id, desc_bc)

def build_caches() :
    #Updates caches in g if they're not already built.

if g['group_ids'] is None:
        g['group_ids'] = group_ids = set()
        for type_ in Container:
            for preset in type_.presets.itervalues() :
                group_ids.add(preset.group_id)

def main() :
    rig = op.GetObject()
    # Check if the data on the rig has changed. If it hasn't, we can
    # stop here already.
    dcount = rig.GetDirty(c4d.DIRTYFLAGS_DATA)
    if dcount == g.get('dcount') :
        return
    g['dcount'] = dcount

update_parameters(rig)
    update_visibility(rig)
    
   
def user_presets() :
   
    Set_UP1 = 537
    Set_UP2 = 536
    Set_UP3 = 539
    Set_UP4 = 540
    
    #Classic Beer
    Classic_Beer_MASTER_Coalesce = rig[c4d.ID_USERDATA, 196]
    Classic_Beer_Coalesce_Amount = rig[c4d.ID_USERDATA, 197]
    Classic_Beer_BIG_and_SMALL_Random_Scale = rig[c4d.ID_USERDATA, 198]
    Classic_Beer_Mesh_Density = rig[c4d.ID_USERDATA, 199]
    
    Classic_Beer_BIG_Drops = rig[c4d.ID_USERDATA, 201]
    Classic_Beer_BIG_Count = rig[c4d.ID_USERDATA, 202]
    Classic_Beer_BIG_Size = rig[c4d.ID_USERDATA, 203]
    Classic_Beer_Random_Seed_BIG = rig[c4d.ID_USERDATA, 204]
     
    Classic_Beer_SMALL_Drops = rig[c4d.ID_USERDATA, 206]
    Classic_Beer_SMALL_Count = rig[c4d.ID_USERDATA, 207]
    Classic_Beer_SMALL_Size = rig[c4d.ID_USERDATA, 208]
    Classic_Beer_Random_Seed_SMALL = rig[c4d.ID_USERDATA, 209]
    
    Classic_Beer_MICRO_Drops = rig[c4d.ID_USERDATA, 211]
    Classic_Beer_MICRO_Coalesce_Amount = rig[c4d.ID_USERDATA, 214]
    Classic_Beer_MICRO_Count = rig[c4d.ID_USERDATA, 212]
    Classic_Beer_MICRO_Size = rig[c4d.ID_USERDATA, 213]
    Classic_Beer_Random_Seed_MICRO = rig[c4d.ID_USERDATA, 215]
    
    Classic_Beer_MIST = rig[c4d.ID_USERDATA, 190]
    Classic_Beer_MIST_Amount = rig[c4d.ID_USERDATA, 191]
    Classic_Beer_MIST_Droplet_Size = rig[c4d.ID_USERDATA, 192]
    Classic_Beer_Random_Seed_MIST = rig[c4d.ID_USERDATA, 193]
    Classic_Beer_Random_Scale_MIST = rig[c4d.ID_USERDATA, 194]
    
    #User Preset 1
    UP1_MASTER_Coalesce = rig[c4d.ID_USERDATA, 507]
    UP1_Coalesce_Amount = rig[c4d.ID_USERDATA, 508]
    UP1_BIG_and_SMALL_Random_Scale = rig[c4d.ID_USERDATA, 509]
    UP1r_Mesh_Density = rig[c4d.ID_USERDATA, 510]
    
    UP1_BIG_Drops = rig[c4d.ID_USERDATA, 512]
    UP1_BIG_Count = rig[c4d.ID_USERDATA, 513]
    UP1_BIG_Size = rig[c4d.ID_USERDATA, 514]
    UP1_Random_Seed_BIG = rig[c4d.ID_USERDATA, 515]
     
    UP1_SMALL_Drops = rig[c4d.ID_USERDATA, 517]
    UP1_SMALL_Count = rig[c4d.ID_USERDATA, 518]
    UP1_SMALL_Size = rig[c4d.ID_USERDATA, 519]
    UP1_Random_Seed_SMALL = rig[c4d.ID_USERDATA, 520]
    
    UP1_MICRO_Drops = rig[c4d.ID_USERDATA, 523]
    UP1_MICRO_Coalesce_Amount = rig[c4d.ID_USERDATA, 5214]
    UP1_MICRO_Count = rig[c4d.ID_USERDATA, 525]
    UP1_MICRO_Size = rig[c4d.ID_USERDATA, 526]
    UP1_Random_Seed_MICRO = rig[c4d.ID_USERDATA, 527]
    
    UP1_MIST = rig[c4d.ID_USERDATA, 531]
    UP1_MIST_Amount = rig[c4d.ID_USERDATA, 532]
    UP1_MIST_Droplet_Size = rig[c4d.ID_USERDATA, 533]
    UP1_Random_Seed_MIST = rig[c4d.ID_USERDATA, 534]
    UP1_Random_Scale_MIST = rig[c4d.ID_USERDATA, 535]
    
    if rig[c4d.ID_USERDATA, Set_UP1] == 1: #resets User Preset 1 button
        if preset_value == 0:
            UP1_MASTER_Coalesce = Classic_Beer_MASTER_Coalesce
            UP1_Coalesce_Amount = Classic_Beer_Coalesce_Amount
            UP1_BIG_and_SMALL_Random_Scale = Classic_Beer_BIG_and_SMALL_Random_Scale
            UP1_Mesh_Density = Classic_Beer_Mesh_Density
    
            UP1_BIG_Drops = Classic_Beer_BIG_Drops
            UP1_BIG_Count = Classic_Beer_BIG_Count
            UP1_BIG_Size = Classic_Beer_BIG_Size
            UP1_Random_Seed_BIG = Classic_Beer_Random_Seed_BIG
     
            UP1_SMALL_Drops = Classic_Beer_SMALL_Drops
            UP1_SMALL_Count = Classic_Beer_SMALL_Count
            UP1_SMALL_Size = Classic_Beer_SMALL_Size
            UP1_Random_Seed_SMALL = Classic_Beer_Random_Seed_SMALL
    
            UP1_MICRO_Drops = Classic_Beer_MICRO_Drops
            UP1_MICRO_Coalesce_Amount = Classic_Beer_MICRO_Coalesce_Amount
            UP1_MICRO_Count = Classic_Beer_MICRO_Count
            UP1_MICRO_Size = Classic_Beer_MICRO_Size
            UP1_Random_Seed_MICRO = Classic_Beer_Random_Seed_MICRO
    
            UP1_MIST = Classic_Beer_MIST
            UP1_MIST_Amount = Classic_Beer_MIST_Amount
            UP1_MIST_Droplet_Size = Classic_Beer_MIST_Droplet_Size
            UP1_Random_Seed_MIST = Classic_Beer_Random_Seed_MIST
            UP1_Random_Scale_MIST = Classic_Beer_Random_Scale_MIST
        
            rig[c4d.ID_USERDATA, Set_UP1] = 0

The radio button selector shows and hides the controls for its specific preset nicely (probably because Niklas wrote the code :)
 But then, it all goes to hell. Can anyone help? Thanks.

On 29/01/2017 at 04:23, xxxxxxxx wrote:

Simplifying the problem:

import c4d
import collections

def main() :
    rig = op.GetObject()
    
    Set_UP1 = 537
    preset_value = rig[c4d.ID_USERDATA, 13]
    
    #Classic Beer
    Classic_Beer_MASTER_Coalesce = rig[c4d.ID_USERDATA, 196]
    Classic_Beer_Coalesce_Amount = rig[c4d.ID_USERDATA, 197]

#User Preset 1
    UP1_MASTER_Coalesce = rig[c4d.ID_USERDATA, 507]
    UP1_Coalesce_Amount = rig[c4d.ID_USERDATA, 508]

if rig[c4d.ID_USERDATA, Set_UP1]:
        rig[c4d.ID_USERDATA, Set_UP1] = 0 #resets User Preset 1 button
        
        if preset_value == 0:
            print (preset_value)
            UP1_MASTER_Coalesce = Classic_Beer_MASTER_Coalesce
            UP1_Coalesce_Amount = 3

The Set_UP1 switch resets itself but I can't get the UP1 values to change. Any help? Thanks.

On 29/01/2017 at 09:25, xxxxxxxx wrote:

If your other code is correct. One, or possibly both, of these should fix the updating problem.
Try the SendCoreMessage() first.

op.SetUserDataContainer(descId, container)

c4d.SendCoreMessage(c4d.COREMSG_CINEMA, c4d.BaseContainer(c4d.COREMSG_CINEMA_FORCE_AM_UPDATE))

-ScottA

On 30/01/2017 at 05:18, xxxxxxxx wrote:

Neither of these work. Do you have any other ideas? I get no errors when I compile and nothing untoward is showing up in the console.

On 30/01/2017 at 05:39, xxxxxxxx wrote:

It looks like there is a problem defining user data as a variable.

Classic_Beer_Coalesce_Amount = rig[c4d.ID_USERDATA, 197]
UP1_Coalesce_Amount = rig[c4d.ID_USERDATA, 508]

C4D doesn't like this for some reason.

UP1_Coalesce_Amount = Classic_Beer_Coalesce_Amount
doesn't work but
rig[c4d.ID_USERDATA, 508] = rig[c4d.ID_USERDATA, 197]
does work. Any ideas?

On 30/01/2017 at 06:02, xxxxxxxx wrote:

It's just how python work.

For exemple

Classic_Beer_Coalesce_Amount = rig[c4d.ID_USERDATA, 197] 

the variable class_beer_coalesce_amount is egal to the value of rig[user_id]. so we can simpify as class_beer_coalesce_amount = 10 (I take 10 just as an exemple)

So by doing

UP1_Coalesce_Amount = Classic_Beer_Coalesce_Amount

You tell my first variable who store a value of 10 for exemple is now egal to my second variable who is egal to 20. But that only change variable value not the user id.

In you second exemple

rig[c4d.ID_USERDATA, 508] = rig[c4d.ID_USERDATA, 197]

For a better understanding is similar to

bc = rig.GetDataInstance()
bc.SetData(508, bc.GetData(197))

A good read https://jeffknupp.com/blog/2012/11/13/is-python-callbyvalue-or-callbyreference-neither/

Hope it's help you

Btw in future please use [ code] and [ /code] for posting code in the forum ;)

On 30/01/2017 at 06:13, xxxxxxxx wrote:

Thanks! [ code]! So that's how you get it to look like that in the posts! :)

On 30/01/2017 at 06:24, xxxxxxxx wrote:

[ code]

bc = rig.GetDataInstance()

bc.SetData(508, bc.GetData(197))

[ /code]

doesn't work. Do you have another suggestion?

On 30/01/2017 at 06:42, xxxxxxxx wrote:

If you want a switch here is an exemple with container and another one which is more efficient (since we dont have to iterate the list)

import c4d
  
def switch_user_data(obj, first, second) :
    #Set first value to the second value
    list_ud = obj.GetUserDataContainer()
    buffer_first = None
    buffer_second = None
    
    for descId, bc in list_ud:
        buffer_id = descId[1].id
        if buffer_id == first:
            buffer_first = obj[c4d.ID_USERDATA, buffer_id] #store the value
        elif buffer_id == second:
            buffer_second = obj[c4d.ID_USERDATA, buffer_id] #store the value
        
    #Check if we find our user data
    if buffer_first is not None and buffer_second is not None:
        obj[c4d.ID_USERDATA, first] = buffer_second
        obj[c4d.ID_USERDATA, second] = buffer_first
        c4d.EventAdd()
        
  
def efficient_switch(obj, first, second) :
    try:
        buffer_first = obj[c4d.ID_USERDATA, first]
        obj[c4d.ID_USERDATA, first] = obj[c4d.ID_USERDATA, second]
        obj[c4d.ID_USERDATA, second] = buffer_first
        c4d.EventAdd()
    except:
        print "error can't switch"
  
def main() :
    obj = doc.GetFirstObject()
  
    efficient_switch(obj, 1, 5)
    switch_user_data(obj, 1, 2)
  
if __name__=='__main__':
    main()

On 30/01/2017 at 06:49, xxxxxxxx wrote:

Thanks! :)