Complete Replica of a Native Objects UI?
-
-
Hey @bentraje,
Thank you for reaching out to us. The answer to this depends on what you mean by complete replica here.
- You can simply copy the GUI elements manually in the GUI with
User Interface > Copy User Data Interface
. I assume you are aware of this, and this is not what you mean. Find an example below. - To dynamically show a node inside another node you need a
DescriptionCustomGui
. You can use this element in dialogs directly. For descriptions (e.g. user data) you must either use aBaseLink
as a standin or implement you ownCustomGui
which then uses theDescriptionCustomGui
. The latter is only possible in C++.
Cheers,
FerdinandCopying a set of GUI elements manually:
- You can simply copy the GUI elements manually in the GUI with
-
Hi @ferdinand
Thanks for the response.
Yep theUser Interface > Copy User Data Interface
is a handy workflow.
That's what I am looking but in python.Something like.
user_data_ui = obj_a.copy_user_data_interface() obj_b.paste_user_data_interface()
Is there such an existing API for this?
===
RE: dynamically show a node
I want it to be dynamic but not always.
I just want to replicate the user data once.Here's an illustration to the problem
- Suppose I have 10 area lights. If I want to change all their intensity, I have to select all of them and change them by hand.
Not as paintful since I can just assign a selection object. - The limitation of #1 is it assumes all light intesity are the same. How about I change them relatively? Like changing the intensity by 125% than their current value? In this case #1 would fail
This is why I'm trying to create dialog where it replicates the UI of the selected object. Then as I input the value it changes on the relevant objects (i.e. if the selected object is a light it will change the other lights based on a criteria).
Logic wise I can by with that.It just the replica of UI I'm troubled with. I don't want to hand code the UI for each object type hehe
- Suppose I have 10 area lights. If I want to change all their intensity, I have to select all of them and change them by hand.
-
Hi, @bentraje
For each parameter input box, formula expressions are supported in c4d,x
: represents the parameter's current value. If you want to change the intensity by 125% than their current value for each light, you can select all of them and simply inputx * 1.25
.
The document for Expanded Formula Entry by Multiple Selections is here:
-
Hello @bentraje,
Is there such an existing API for this?
user_data_ui = obj_a.copy_user_data_interface() obj_b.paste_user_data_interface()
It depends on what you would call an API. But there are no high-level functions akin to
Copy/SaveGui
in your example. But there is of coursec4d.C4DAtom.GetDescription
and the fact that you can iterate over such description, getting the data container, the "GUI", yielded for a parameter in the node. You could then add each of these description containers as a user data paramater container in your node you want to copy to. Instead of callingc4d.GetCustomDataTypeDefault
to get a data type default container and then modifying it, you would use a source node parameter data container yielded by its description to callc4d.BaseList2D.AddUserData
.Adding the tangible parameters itself would be no problem with that. The problem are parameters of type
DTYPE_GROUP
. They are also yielded with the description, but you would have to remap them, as elements refer to their parent group overDESC_PARENTGROUP
. So when you add the parameterFoo
which in the source node was in a group with the ID1000, DTYPE_GROUP, 0
you would have first to add the group to the target node as a user data parameter which will give you a new ID. And then for all parameters which reference that group inDESC_PARENTGROUP
, replace the reference with the new ID. I do not have the time to write an example right now, if you need help with this, you would have to wait until the new year.Alternatively, you could also ignore groups, i.e., ignore all parameters of type
DTYPE_GROUP
and simply flush all group references. All in all, this can probably get a bit tricky, and you might be better off with the manual approach lined out by @iplai .Cheers,
Ferdinand -
There is a third-party module to serialize and deserialize the user data of any
BaseList2D
object in python dict format. Here's an example:c4d.ID_USERDATA: { (c4d.ID_USERDATA, 1): { c4d.DTYPE_: c4d.DTYPE_REAL, c4d.DESC_NAME: 'Data', c4d.DESC_SHORT_NAME: 'Data', c4d.DESC_MIN: 0, c4d.DESC_MAX: 1, c4d.DESC_STEP: 0.01, c4d.DESC_UNIT: c4d.DESC_UNIT_PERCENT, c4d.DESC_CUSTOMGUI: c4d.CUSTOMGUI_REAL, c4d.DESC_PARENTGROUP: (700, 5, 0), }, (c4d.ID_USERDATA, 2): { c4d.DTYPE_: c4d.DTYPE_GROUP, c4d.DESC_NAME: 'Group', c4d.DESC_SHORT_NAME: 'Group', c4d.DESC_ANIMATE: c4d.DESC_ANIMATE_OFF, c4d.DESC_COLUMNS: 1, c4d.DESC_TITLEBAR: 1, c4d.DESC_DEFAULT: 1, c4d.DESC_PARENTGROUP: (), }, (c4d.ID_USERDATA, 3): { c4d.DTYPE_: c4d.DTYPE_LONG, c4d.DESC_NAME: 'Data', c4d.DESC_SHORT_NAME: 'Data', c4d.DESC_UNIT: c4d.DESC_UNIT_INT, c4d.DESC_CUSTOMGUI: c4d.CUSTOMGUI_LONGSLIDER, c4d.DESC_MIN: 0, c4d.DESC_MAX: 100, c4d.DESC_STEP: 1, c4d.DESC_PARENTGROUP: ((700, 5, 0), (2, 1, 0)), }, }
The module is not fully tested, but it's enough for me for my daily scripting work. The processing of parameters is implemented in a way described by @ferdinand . Sort of like the.res
file used by plugins developing, the json data defines the details of a parameter. If you feel like it, you can implement it yourself by refering to following functions:
DumpParams
DumpParamDetails
DumpUserDataDetails
LoadUserData
...
Considering sometimes there's a huge amount of parameters, I spent a lot of time to judge and handle dirty parameters, namely the parameter has been changed, there is still no perfect way. If you don't care whether the parameter is dirty, problem goes easier. Maybe do some filters by restrictingDescLevel.creator
to a specific value etc. -
Thanks for providing details especially the third party API. Seems like a handy utility library I'll see what I can do with it.
-