Populate Userdata via Python - Please Help!
-
On 08/06/2015 at 00:17, xxxxxxxx wrote:
Hello, as a beginner of C4D Python Scripting, I'm trying to find out how to populate & dynamically a userdata (dropdown - cycle ). When user add new object/spline under specific Null - I want it automatically be added to dropdown userdata. (I'm going to use it as a Python Node in my Xpresso Setup )
Here is my non-working terrible code;
What I want is;Search null (Profiles) - Get its children names
Populate Userdata as Dropdown (Userdata is located in "Options" null) like 01;Profile1 02;Profile2 03;Profile3
http://www.dropbox.com/s/9f5mwlosm6oy39v/modify_userdata.c4d?dl=0import c4d
from c4d import gui
from c4d import documentsdef GetChildren(node) :
global names
options = doc.SearchObject("Options") # This is where userdata located
profiles = doc.SearchObject("Profiles") # Get names of children from this null
userdata = options.GetUserDataContainer() #The master UD container
if options is None:
print "main controls not found"
return
count = len(profiles.GetChildren())
if (node.GetChildren() != []) :
for child in node.GetChildren() :
GetChildren(child)
names = []
names = child.GetName()
print names
print count
nextID = len(options.GetUserDataContainer()) - 1
bc = c4d.GetCustomDatatypeDefault(c4d.DTYPE_STRING)
cc = c4d.GetCustomDatatypeDefault(c4d.DTYPE_STRING)
bc[c4d.DESC_NAME] = 'Profiles'
bc[c4d.DESC_CUSTOMGUI] = c4d.CUSTOMGUI_CYCLE
#CUSTOMGUI_STRINGMULTI
options.SetUserDataContainer([c4d.ID_USERDATA, 1], bc)
def main() :
GetChildren(Object) -
On 08/06/2015 at 08:42, xxxxxxxx wrote:
Hi and welcome to the PluginCafe!
Thanks for the example scene.
What's you're missing is the initialization and the way to setup a user data container.
If you want a dropdown cycle, this is an integer parameter. So you've to retrieve an integer default container (DTYPE_LONG). Then set the parameter to use the CUSTOMGUI_CYCLE and initialize its values with DESC_CYCLE.
Also, you seem to try to recursively call GetChildren() for each child of the input object. I'm not sure this is really wanted.Note in your XPresso Python node, 'node' and 'profiles' variables references the same object. This could lead to problems if the input object is changed in the XPresso setup.
Here's how GetChildren() function would look like:
def GetChildren(node) : global names options = doc.SearchObject("Options") # This is where userdata located if options is None: print "main controls not found" return children = node.GetChildren() count = len(children) # Create and initialize user data container for an integer for the children bc = c4d.GetCustomDatatypeDefault(c4d.DTYPE_LONG) bc.SetString(c4d.DESC_NAME, node.GetName()) bc.SetInt32(c4d.DESC_CUSTOMGUI, c4d.CUSTOMGUI_CYCLE) bc.SetInt32(c4d.DESC_MIN, 0) bc.SetInt32(c4d.DESC_MAX, count-1) # Create a container for the dropdown cycle values cycle = c4d.BaseContainer() for index in range(0, count) : child = children[index] cycle.SetString(index, child.GetName()) # Set cycle values container bc.SetContainer(c4d.DESC_CYCLE, cycle) # Set container for children user data cycle parameter options.SetUserDataContainer([c4d.ID_USERDATA, 1], bc) names = ""
-
On 20/06/2015 at 12:49, xxxxxxxx wrote:
Hello,
Thanks for the answer, it worked:)But now I have realized that my specific userdata should be in another userdata group.
It changes default Userdata group automatically. But I could not find how to access another userdata group..
Really searched on net but could not find any info. As I said I'm just a beginner:)Again my scene;
https://www.dropbox.com/s/etmln6e7esvtnp1/modify_userdata_another_group.c4d?dl=0 -
On 17/07/2015 at 02:48, xxxxxxxx wrote:
Hi,
Sorry for the late reply.
To set the parent group for a user data assign DESC_PARENTGROUP. This value in the description container accepts a DescID and has to be setup like this:
parentGroup = c4d.DescID(c4d.DescLevel(c4d.ID_USERDATA), c4d.DescLevel(theGroupID, c4d.DTYPE_GROUP, 0)) bc.SetData(c4d.DESC_PARENTGROUP, parentGroup)
theGroupID is the ID number for the group (4 in your example scene).
-
On 17/07/2015 at 05:52, xxxxxxxx wrote:
Hi Yannick,
Thank you for your answer;
(Sorry If I am asking so many question, trying to learn...)What I am doing wrong? I've added your last strings but still it's not working.
Script By Yannick Puech
import c4d
from c4d import gui
from c4d import documentsdef GetChildren(Object) :
global names
options = doc.SearchObject("Options") # This is where userdata located
if options is None:
print "main controls not found"
return
children = Object.GetChildren()
count = len(children)
# Create and initialize user data container for an integer for the children
bc = c4d.GetCustomDatatypeDefault(c4d.DTYPE_LONG)
bc.SetString(c4d.DESC_NAME, Object.GetName())
bc.SetInt32(c4d.DESC_CUSTOMGUI, c4d.CUSTOMGUI_CYCLE)
bc.SetInt32(c4d.DESC_MIN, 0)
bc.SetInt32(c4d.DESC_MAX, count-1)
parentGroup = c4d.DescID(c4d.DescLevel(c4d.ID_USERDATA), c4d.DescLevel(4, c4d.DTYPE_GROUP, 0))
bc.SetData(c4d.DESC_PARENTGROUP, parentGroup)
# Create a container for the dropdown cycle values
cycle = c4d.BaseContainer()
for index in range(0, count) :
child = children[index]
cycle.SetString(index, child.GetName())
# Set cycle values container
bc.SetContainer(c4d.DESC_CYCLE, cycle)
# Set container for children user data cycle parameter
options.SetUserDataContainer([c4d.ID_USERDATA, 1], bc)
names = ""
def main() :
GetChildren(Object) -
On 17/07/2015 at 06:17, xxxxxxxx wrote:
Hi I think I've done finally:)
Thanks a lot Yannick, I have placed it inside Python Tag.
And if anyone intrested ;Script By Yannick Puech
import c4d
from c4d import gui
from c4d import documentsdef GetChildren() :
global names
profiles = doc.SearchObject("Profiles") # Null name contains children objects
options = doc.SearchObject("Options") # This is where userdata located
if options is None:
print "main controls not found"
return
children = profiles.GetChildren()
count = len(children)
# Create and initialize user data container for an integer for the children
bc = c4d.GetCustomDatatypeDefault(c4d.DTYPE_LONG)
bc.SetString(c4d.DESC_NAME, profiles.GetName())
bc.SetInt32(c4d.DESC_CUSTOMGUI, c4d.CUSTOMGUI_CYCLE)
bc.SetInt32(c4d.DESC_MIN, 0)
bc.SetInt32(c4d.DESC_MAX, count-1)
parentGroup = c4d.DescID(c4d.DescLevel(c4d.ID_USERDATA), c4d.DescLevel(4, c4d.DTYPE_GROUP, 0))# 4 is my secondary Group ID
bc.SetData(c4d.DESC_PARENTGROUP, parentGroup)
# Create a container for the dropdown cycle values
cycle = c4d.BaseContainer()
for index in range(0, count) :
child = children[index]
cycle.SetString(index, child.GetName())
# Set cycle values container
bc.SetContainer(c4d.DESC_CYCLE, cycle)
# Set container for children user data cycle parameter
options.SetUserDataContainer([c4d.ID_USERDATA, 1], bc)
names = ""
def main() :
GetChildren() -
On 17/07/2015 at 06:22, xxxxxxxx wrote:
Btw I've noticed that as I paste this code in my real project It deletes my current other options userdata.
Is there a way to add or modify directly without deleting or recreating other userdatas ?In my case my group ID is 2 and drop down list should be in userdata with ID 13 for example.
This is last step Yannick, please do me a favor last time:)))
Thanks a lot again.
-
On 17/07/2015 at 07:28, xxxxxxxx wrote:
To add a user data use BaseList2D.AddUserData().
To modify a user data retrieve its description container with BaseList2D.GetUserDataContainer() and set it back with BaseList2D.SetUserDataContainer(). -
On 17/07/2015 at 08:44, xxxxxxxx wrote:
I'm again confused, according to my previous example I tried to add getuserdatacontainer and setuserdatacontainer...But it's still not working...
(In this example my group ID is 1 and drop down cycle UD id is 13, I only need to modify it, it already exists...Sorry again as a beginner it's so confusing...)Script By Yannick Puech
import c4d
from c4d import gui
from c4d import documentsdef GetChildren() :
global names
profiles = doc.SearchObject("Profiles") # Null name contains children objects
options = doc.SearchObject("Options") # This is where userdata located
if options is None:
print "main controls not found"
return
children = profiles.GetChildren()
count = len(children)
# Create and initialize user data container for an integer for the children
bc = options.GetUserDataContainer()
bc = c4d.GetCustomDatatypeDefault(c4d.DTYPE_LONG)
bc.SetString(c4d.DESC_NAME, profiles.GetName())
bc.SetInt32(c4d.DESC_CUSTOMGUI, c4d.CUSTOMGUI_CYCLE)
bc.SetInt32(c4d.DESC_MIN, 0)
bc.SetInt32(c4d.DESC_MAX, count-1)
parentGroup = c4d.DescID(c4d.DescLevel(c4d.ID_USERDATA), c4d.DescLevel(1, c4d.DTYPE_GROUP, 0))
bc.SetData(c4d.DESC_PARENTGROUP, parentGroup)
cycle = c4d.BaseContainer()
for index in range(0, count) :
child = children[index]
cycle.SetString(index, child.GetName())
bc.SetContainer(c4d.DESC_CYCLE, cycle)
# Set container for children user data cycle parameter
options.SetUserDataContainer([c4d.ID_USERDATA,13], bc)
names = ""
def main() :
GetChildren()