It works like a charm!
Thanks a lot!
It works like a charm!
Thanks a lot!
Hi,
How can I add a button to an object with python?
I'm trying to add a button to a Null Object
, but only get a button userdata without button itself. Here is the code:
import c4d
def main():
null_object = c4d.BaseObject(c4d.Onull)
ud_btn_bc = c4d.GetCustomDatatypeDefault(c4d.DTYPE_BUTTON)
ud_btn_bc.SetString(c4d.DESC_NAME, "Click")
ud_btn_bc.SetString(c4d.DESC_SHORT_NAME, "click")
null_object.AddUserData(ud_btn_bc)
doc.InsertObject(null_object)
c4d.EventAdd()
if __name__ == "__main__":
main()
It seems that creating a button user data from GUI is different from Python. But I don't know how to do it correctly in Python.
Thanks!
Thank you @ferdinand for the detailed answer and code.
I will do more reading in the sdk document.
Thanks again @cairyn!
I will use the method your introduced, and keep this topic open, hoping someone could make this more clearly.
Thanks @cairyn! When i read c4d.IsCommandChecked(id), it says Forbidden to call in expressions (Python generator, tag, XPresso node, etc.)
. Is it safe to use this in a Interaction Tag?
Hi,
How can I get and set Move Tool's XYZ Axis Lock state? when I click the buttons, the Script Log
display as:
c4d.CallCommand(12153) # X-Axis / Pitch
c4d.CallCommand(12154) # Y-Axis / Heading
c4d.CallCommand(12155) # Z-Axis / Bank
I append an Interaction Tag
on a object, when I select this object, I want it automaticly change to Move Tool and lock the Y axis and Z axis,
when I deselect the object, it restore the original axis lock state, then change back to last active tool.
Here is the code I put in the tag:
import c4d
from c4d import gui
def onSelect():
#Code for what happens when the object gets selected goes here
global last_tool
last_tool = doc.GetAction() # store the active tool
c4d.CallCommand(c4d.ID_MODELING_MOVE) # change to Move Tool
gui.ActiveObjectManager_SetObject( # change Attribute Manager to Object Mode
c4d.ACTIVEOBJECTMODE_OBJECT, op, c4d.ACTIVEOBJECTMANAGER_SETOBJECTS_OPEN)
# TODO: Get Move Tool current axis lock state, then change the state
def onDeselect():
#Code for what happens when the object gets unselected goes here
# TODO: Restore Move Tool's last axis lock state
doc.SetAction(last_tool) # restore the last active tool
#def onHighlight():
#Code for what happens when the object gets highlighted goes here
#def onUnhighlight():
#Code for what happens when the object gets unhighlighted goes here
by the way, what is the difference between "onSelect" and "onHighlight"?
Thanks!
@s_bach thank you for your answer! I think I have the same question as mike do, so it has been solved now. Thank you again!
Hi, @m_adam
Thank you for your kindness and the inspiring answer! It's a GREAT Christmas present for me!
So sorry asking XPresso
related questions in this forum.
The problem I faced is a little bit complex than this: I need sample Effector
s' total Output Strength
s in the position from a Polygon Object
's Point
s, and store the result into a Vertex Color Map
attached for further use.
This problem bothers me for months, and I didn't find any clue until your post. I have never think about using Python Node
with global variable
in XPresso Network
can keep the data as I need and do the magic!
From the bottom of my heart, I want to say THANK YOU.
The answer you give not only solve this problem, but also inspire me re-thinking of ObjectList Node
and Python Node
, and how these nodes executed in an XPresso Network
.
Just let me THANK YOU AGAIN!
Best wishes for you to have a wonderful holiday!
Hi,
I have a Null Object
with an In-/Exclusion Userdata
attached. In In-/Exclusion Userdata
some Mograph Effector
have been added. I want to use Sample Node
to get all Strength
of Mograph Effector
, then add output Strength
together. How can I do?
Here is the snapshot of the scene.
The problem I meet is that I can't use Python
to sample the output of a Mograph Effector
(Sample Node With Python), and I haven't found a way to cumulate output of an Object List Node
.
Thanks!
Hi @r_gigante,
Thank you for replying. I'd like to know more about this topic: if I only know the Control Point Index
from PointObject.GetPoint(id)
of a spline, how could I get the Spline Position
of this point?
Hi, here is a thread from the old forum: Sample Node With Python.
I don't know if there will be any solution for now.
hi @passion3d,
There is no actual n-gon in the underlying layer of Cinema 4D.
Adjacent polygons use hidden edge
to create n-gon-like shape(s).
Following code creates a 5-side polygon object:
import c4d, math
from c4d import utils
#Welcome to the world of Python
def main():
pointCount = 5
polygonCount = math.ceil(pointCount/4.0) # caculate minimum needed polygon number
polyObj = c4d.BaseObject(c4d.Opolygon) # create an empty polygon object
polyObj.ResizeObject(pcnt=pointCount, vcnt=polygonCount) # resize object to have 5 points, 2 polygons
# manually set all point position
polyObj.SetPoint(id=0, pos=c4d.Vector(200,0,-200))
polyObj.SetPoint(id=1, pos=c4d.Vector(-200,0,-200))
polyObj.SetPoint(id=2, pos=c4d.Vector(-200,0,200))
polyObj.SetPoint(id=3, pos=c4d.Vector(200,0,200))
polyObj.SetPoint(id=4, pos=c4d.Vector(300,0,0))
# associate points into polygons
polygon0 = c4d.CPolygon(t_a=0, t_b=1, t_c=2, t_d=3)
polygon1 = c4d.CPolygon(t_a=0, t_b=3, t_c=4)
# set polygon in polygon object
polyObj.SetPolygon(id=0, polygon=polygon0)
polyObj.SetPolygon(id=1, polygon=polygon1)
# set hidden edge
nbr = utils.Neighbor()
nbr.Init(op=polyObj, bs=None) # create Neighor counting all polygon in
edge = c4d.BaseSelect()
edge.Select(num=3) # set selection, which is the id of the edge to be hidden
polyObj.SetSelectedEdges(e=nbr, pSel=edge, ltype=c4d.EDGESELECTIONTYPE_HIDDEN) # hide the edge
polyObj.Message(c4d.MSG_UPDATE)
doc.InsertObject(polyObj)
c4d.EventAdd()
if __name__=='__main__':
main()
Hi @cmpxchg8b and @a_block ,
I don't know much about matrix, but here is what I found.
If the point with arrow
should rotate to aim, then all the possible position of the point must lay on the sphere surface
which sphere's center is the parent object.
And one point and a vector can form a line in space.
So the question becomes a line-sphere intersection problem.
After solving the equations, we can get 2 points: original point
and transformed point(s)
.
After that, we can find the transform matrix between 2 points.
btw, please read the How to Post Questions, Q&A New Functionality.
I think it's better to move this question into Cinema 4D Development category
Hi @bonsak,
Try use op.GetObject().GetDeformCache().GetPointCount()
in a Python Tag
on the Polygon Object
.
Here you can get more information: GetDeformCache().
@s_bach, thank you, I'll start to do some hard reading!
[I have so many questions in this thread. So first, please let me thank you for taking time! ]
Hi,
I want to access user data in a more "procedural way". Here is the code after I do lots of searching on the Python (and C++) SDK document:
import c4d
from c4d import gui
#Welcome to the world of Python
def main():
obj = doc.GetActiveObject()
objBc = obj.GetData()
userdataList = obj.GetUserDataContainer()
userdata = userdataList[0]
userdataBc = userdata[1]
DescIDList = userdata[0]
id0 = DescIDList[0].id
id1 = DescIDList[1].id
print(objBc[id0][id1])
if __name__=='__main__':
main()
After this, I really want to know how the data of a BaseObject
organized and stored. And I make a picture:
I don't know if this reveals some of the data structure of BaseObject
.
And I have some doubts in or out of the picture:
[In the picture] After I search in the BaseContainer
of BaseObject
, I don't find anything data related to a Userdata
: long name
, short name
, min/max value/default value
, etc.
Where is the BaseContainer
of all these data stored?
[In the picture] Is DescID
is similar to UUID
of a BaseContainer
? And where are they stored?
[In the picture] What is CreatorId
of DescLevel
? I only find 0
in this field.
[Out the picture] As for now, is there any easier way to get a textual form
of DescLevel.id
and DescLevel.dtype
? Comparing and searching in branches of *.h
files is not friendly for us without C++ experience.
[Off topic] The name index
in sample code of BaseContainer.__iter__()
in Python SDK Document
is confusing. Especially that all other function documents refer the same thing as id
on the same page.
[Off topic] Is there any articles that have more detail about the foundation concepts for cinema 4d coding?
Here I find some pages in Python SDK Document
:
Cookbook, Plugin Structure, Introduction into the GUI of Cinema 4D.
But they are lack of details and relation with other document.
Also, some foundation concepts only have few introduction paragraphs:
BaseList2D
,BaseContainer
, etc.
I don't mean to complain, but it's frustrating after spending hours and hours searching in the SDK and the Internet but only get some obscure results. I hope the document could be more friendly to new developers.
Thanks a lot!
@c4ds, don’t worry! Every steps (even the off-road one) make some progress, right? I appreciate the way you focusing on the problem solving, which I believe is also the wonderful thing of this forum: we do our best to solving the problem itself, discussing about the better/more accurate answers rather than “who is right, who is wrong”. Last but not least, thank you for taking time to reply!
Hi @bentraje,
Here is the code that can do:
import c4d
def AddLongDataType(obj):
if obj is None: return
bc = c4d.GetCustomDataTypeDefault(c4d.DTYPE_LONG) # Create default container
bc[c4d.DESC_NAME] = "Test" # Rename the entry
element = obj.AddUserData(bc) # Add userdata container
obj[element] = 30 # Assign a value
c4d.EventAdd() # Update
def main():
obj = doc.GetActiveObject() # Here you get selected/active object from scene
AddLongDataType(obj) # Call the AddLongDataType function to add user data to selected object
if __name__=='__main__': # The "actual" place that code start to execute
main() # Call "main" function, start the processing
@s_bach, thank you very much! Now I see the whole picture!