1. import c4d
  2. from c4d import gui
  3. #Welcome to the world of Python
  4. #Unique id numbers for each of the GUI elements
  5. BACKGROUND = 1000
  6. BACKGROUND_COLOR = 1001
  7. GROUP_OPTIONS = 10000
  8. OPTION_COLOR = 10001
  9. OPTION_AO = 10002
  10. GROUP_BUTTONS = 20000
  11. BUTTON_OK = 20001
  12. BUTTON_CANCEL = 20002
  13. OPTION_WIDTH = 20003
  14. OPTION_HIGHT = 20004
  15. #This class defines the dialogue that pops up to request user options
  16. class OptionsDialog(gui.GeDialog):
  17. #Add all the items we want to show in the dialogue box
  18. def CreateLayout(self):
  19. #Bake cehck box
  20. self.GroupBegin(GROUP_OPTIONS, c4d.BFH_SCALE|c4d.BFH_LEFT, 1, 2)
  21. self.AddCheckbox(OPTION_COLOR, c4d.BFH_LEFT, 0,0, name="Color")
  22. self.AddCheckbox(OPTION_AO, c4d.BFH_LEFT, 0,0, name="AO")
  23. self.GroupEnd()
  24. #BG color
  25. self.AddStaticText(BACKGROUND, c4d.BFH_LEFT, name="Background Color")
  26. self.AddColorField(BACKGROUND_COLOR, c4d.BFH_SCALEFIT, 80, 12)
  27. #Group name
  28. self.GroupBegin(10000, c4d.BFH_SCALEFIT, 1, title = 'Texture size')
  29. self.GroupBorder(c4d.BORDER_GROUP_IN)
  30. self.GroupBorderSpace(20, 5, 20, 5)
  31. #Arrow numbers
  32. self.AddEditNumberArrows(OPTION_WIDTH, c4d.BFH_SCALEFIT, 50, 0)
  33. self.AddEditNumberArrows(OPTION_HIGHT, c4d.BFH_SCALEFIT, 50, 0)
  34. #Buttons - an OK and a CANCEL button
  35. self.GroupBegin(GROUP_OPTIONS, c4d.BFH_CENTER, 2, 1)
  36. self.AddButton(BUTTON_OK, c4d.BFH_SCALE, name="Set")
  37. self.AddButton(BUTTON_CANCEL, c4d.BFH_SCALE, name="Cancel")
  38. self.GroupEnd()
  39. return True
  40. #This is where we react to user input (eg button clicks)
  41. def Command(self, id, msg):
  42. if id==BUTTON_CANCEL:
  43. #The user has clicked the 'Cancel' button
  44. self.ok = False
  45. self.Close()
  46. elif id==BUTTON_OK:
  47. #The user has clicked the 'OK' button
  48. self.ok = True
  49. #Save the checkbox values so that the rest of the script can access them
  50. self.option_color = self.GetBool(OPTION_COLOR)
  51. self.option_AO = self.GetBool(OPTION_AO)
  52. self.option_BG = self.GetColorField(BACKGROUND_COLOR)['color'] # GetColorField returns a dictionary. The actual vector of the color is an item with the key 'color'
  53. self.option_width = self.GetInt32(OPTION_WIDTH) # the field in the BakeTexture tag expects integers, not floats ;)
  54. self.option_hight = self.GetInt32(OPTION_HIGHT)
  55. self.Close()
  56. return True
  57. #This is where the action happens
  58. def main():
  59. #Open the options dialogue to let users choose their options
  60. optionsdialog = OptionsDialog()
  61. optionsdialog.Open(c4d.DLG_TYPE_MODAL, defaultw=300, defaulth=50)
  62. #Quit if the user has clicked cancel
  63. if not optionsdialog.ok:
  64. return
  65. #create tag
  66. def tool():
  67. return plugins.FindPlugin(doc.GetAction(), c4d.PLUGINTYPE_TOOL)
  68. def object():
  69. return doc.GetActiveObject()
  70. def tag():
  71. return doc.GetActiveTag()
  72. def renderdata():
  73. return doc.GetActiveRenderData()
  74. def prefs(id):
  75. return plugins.FindPlugin(id, c4d.PLUGINTYPE_PREFS)
  76. # c4d.CallCommand(100004788, 50005) # you should avoid using CallCommand if where you can.
  77. tag = doc.GetActiveObject().MakeTag(c4d.Tbaketexture) # this creates the tag and applies it to the active object
  78. tag[c4d.BAKETEXTURE_CHANNEL_COLOR] = optionsdialog.option_color # you don't need () around the variables
  79. tag[c4d.BAKETEXTURE_CHANNEL_AO] = optionsdialog.option_AO
  80. tag[c4d.BAKETEXTURE_WIDTH] = optionsdialog.option_width
  81. tag[c4d.BAKETEXTURE_HEIGHT] = optionsdialog.option_hight
  82. tag[c4d.BAKETEXTURE_BACKGROUND] = optionsdialog.option_BG
  83. c4d.EventAdd()
  84. if __name__=='__main__':
  85. main()
  1. import c4d
  2. def main():
  3. doc.StartUndo()
  4. # Flags
  5. # 0 GETACTIVEOBJECTFLAGS_0
  6. # 1 GETACTIVEOBJECTFLAGS_CHILDREN
  7. # 2 GETACTIVEOBJECTFLAGS_SELECTIONORDER
  8. objs = doc.GetActiveObjects(1)
  9. if not objs:
  10. print("No objects selected.")
  11. return
  12. for i in objs:
  13. tag = i.MakeTag(c4d.Texpresso)
  14. doc.AddUndo(c4d.UNDOTYPE_NEW, tag)
  15. c4d.EventAdd()
  16. doc.EndUndo()
  17. if __name__=='__main__':
  18. main()

image.png

  1. # For each selected open spline (line), turns it into a thick
  2. # closed spline (polygon) along the path of the original line.
  3. # No additional chamfer points are added, so very sharp corners will
  4. # look funny - resulting spline will have twice as many points.
  5. # Alternatively can also fold the spline back on itself in place
  6. # without duplicating the first or last line.
  7. import c4d
  8. from c4d import gui
  9. import math
  10. # Unique id numbers for each of the GUI elements
  11. LBL_USAGE = 1000
  12. LBL_INFO1 = 1001
  13. LBL_INFO2 = 1002
  14. GROUP_OPTS = 10000
  15. NUMEDIT_THICKNESS = 10001
  16. CHK_CLOSE_SPLINE = 10003
  17. CHK_MAKE_COPY = 10004
  18. CMB_ACTION = 20000
  19. CMB_ACTION_EXPAND = 20001
  20. CMB_ACTION_REVERSE = 20002
  21. class OptionsDialog(gui.GeDialog):
  22. """ Dialog for expanding a open spline.
  23. """
  24. def CreateLayout(self):
  25. self.SetTitle('Expand Open Spline')
  26. self.AddMultiLineEditText(LBL_USAGE, c4d.BFH_SCALEFIT, inith=40, initw=500,
  27. style=c4d.DR_MULTILINE_READONLY)
  28. self.SetString(LBL_USAGE,
  29. "USAGE: For any selected open splines, makes them\n"
  30. " thick closed polygons of specified thickness")
  31. # Dropdown and thickness option:
  32. self.GroupBegin(GROUP_OPTS, c4d.BFH_SCALEFIT, 2, 2)
  33. self.AddStaticText(LBL_INFO1, c4d.BFH_LEFT, name='Action: ')
  34. self.AddComboBox(CMB_ACTION, c4d.BFH_SCALEFIT)
  35. self.AddChild(CMB_ACTION, CMB_ACTION_EXPAND, "expand spline in XZ")
  36. self.AddChild(CMB_ACTION, CMB_ACTION_REVERSE, "reverse on itself")
  37. self.SetInt32(CMB_ACTION, CMB_ACTION_EXPAND) # Set default action.
  38. self.AddStaticText(LBL_INFO2, c4d.BFH_LEFT, name='Thickness: ')
  39. self.AddEditNumber(NUMEDIT_THICKNESS, c4d.BFH_SCALEFIT)
  40. self.SetReal(NUMEDIT_THICKNESS, 10)
  41. self.GroupEnd()
  42. self.AddSeparatorH(c4d.BFH_SCALE);
  43. # Checkbox options:
  44. self.AddCheckbox(CHK_CLOSE_SPLINE, c4d.BFH_SCALEFIT,
  45. initw=1, inith=1, name="close spline when done")
  46. self.SetBool(CHK_CLOSE_SPLINE, True)
  47. self.AddCheckbox(CHK_MAKE_COPY, c4d.BFH_SCALEFIT,
  48. initw=1, inith=1, name="make new copy")
  49. self.SetBool(CHK_MAKE_COPY, True)
  50. self.AddSeparatorH(c4d.BFH_SCALE);
  51. # Buttons - an Ok and Cancel button:
  52. self.AddDlgGroup(c4d.DLG_OK|c4d.DLG_CANCEL);
  53. self.ok = False
  54. return True
  55. # React to user's input:
  56. def Command(self, id, msg):
  57. if id==c4d.DLG_CANCEL:
  58. self.Close()
  59. elif id==c4d.DLG_OK:
  60. self.ok = True
  61. action = self.GetInt32(CMB_ACTION)
  62. self.option_action_expand = action == CMB_ACTION_EXPAND
  63. self.option_action_reverse = action == CMB_ACTION_REVERSE
  64. self.option_thickness = self.GetReal(NUMEDIT_THICKNESS)
  65. self.option_close_spline = self.GetBool(CHK_CLOSE_SPLINE)
  66. self.option_make_copy = self.GetBool(CHK_MAKE_COPY)
  67. self.Close()
  68. return True
  69. def get_yaw(start_pt, end_pt):
  70. """Determines the azimuth from the given start to end point.
  71. Rotation is around XZ where -X = 0
  72. Args:
  73. start_pt: c4d.Vector representing start point.
  74. end_pt: c4d.Vector representing end point.
  75. Returns:
  76. yaw angle in degrees.
  77. """
  78. rad = math.atan2(end_pt.z - start_pt.z, end_pt.x - start_pt.x)
  79. return math.degrees(rad)
  80. def angle_formed_by_three_points_xy(pt1, pt2, pt3):
  81. """Determines the theta (in degrees) between 3 connected points.
  82. pt3 o
  83. /
  84. / theta
  85. pt2 o---------o pt1
  86. Args:
  87. pt1: c4d.Vector representing point before middle point.
  88. pt2: c4d.Vector representing middle point.
  89. pt3: c4d.Vector representing point after middle point.
  90. Returns:
  91. angle between 0 and 360.
  92. """
  93. line1_yaw = get_yaw(pt1, pt2)
  94. line2_yaw = get_yaw(pt3, pt2)
  95. return (line2_yaw - line1_yaw) % 360.0
  96. def get_point_rel_to_end_xy(start_pt, end_pt, dist_offset, rel_angle):
  97. """Get a point 'dist_offset' from 'end_pt' at an angle relative to the line.
  98. Example: if dist_offset=2 and rel_angle=90:
  99. o <-- the point returned would be here
  100. start_pt o-----------o end_pt
  101. Args:
  102. start_pt: c4d.Vector representing start point.
  103. end_pt: c4d.Vector representing end point.
  104. dist_offset: Numeric distance to offset away from end_pt.
  105. rel_angle: Angle relative from the direction of the line to use in
  106. displacing the returned point. 0 is straight (in direction of line).
  107. Returns:
  108. angle between 0 and 360.
  109. """
  110. yaw = get_yaw(start_pt, end_pt)
  111. theta = math.radians(yaw + rel_angle)
  112. offset_x = dist_offset * math.cos(theta)
  113. offset_z = dist_offset * math.sin(theta)
  114. return c4d.Vector(offset_x + end_pt.x, end_pt.y, offset_z + end_pt.z)
  115. def get_chamfer_point_xy(pt1, pt2, pt3, offset):
  116. """Get a chamfer on the outside of a point connected to two other points.
  117. - - - o <-- chamfer point
  118. thickness / (for this case would be 45 degress offset)
  119. /
  120. pt1 o-------o pt2
  121. |
  122. |
  123. o pt3
  124. Args:
  125. pt1: c4d.Vector representing point before middle point.
  126. pt2: c4d.Vector representing middle point.
  127. pt3: c4d.Vector representing point after middle point.
  128. offset: Numerical value representing thickness to base
  129. offset on. A sharper turn will mean further offset.
  130. Returns:
  131. c4d.Vector representing chamfer point.
  132. """
  133. if pt1 == pt2:
  134. return get_point_rel_to_end_xy(
  135. pt3, pt2, offset, -90)
  136. if pt2 == pt3:
  137. return get_point_rel_to_end_xy(
  138. pt1, pt2, offset, 90)
  139. angle_at_curr = 360 - angle_formed_by_three_points_xy(pt1, pt2, pt3)
  140. angle_inset = angle_at_curr / 2.0
  141. rad = math.sin(math.radians(angle_inset)) # Radians
  142. dist_from_corner = offset
  143. if rad != 0:
  144. dist_from_corner = offset / rad
  145. return get_point_rel_to_end_xy(
  146. pt1, pt2, dist_from_corner, 180.0-angle_inset)
  147. def expand_spline_xz(spline, thickness):
  148. """Takes a 'spline' object, and expands it by 'thickness' in XZ.
  149. Args:
  150. spline: Open spline object to expand.
  151. thickness: Number representing thickness/diameter of final line.
  152. Returns:
  153. number of points added.
  154. """
  155. if (spline == None or not spline.CheckType(c4d.Ospline) or
  156. spline.GetPointCount() < 2):
  157. return 0;
  158. len_orig = spline.GetPointCount()
  159. len_new = len_orig * 2
  160. new_spline = spline
  161. new_spline.ResizeObject(len_new)
  162. for i in range(0,len_orig):
  163. p_prev = spline.GetPoint(i) # Previous point.
  164. p_curr = spline.GetPoint(i) # Current point.
  165. p_next = spline.GetPoint(i) # Next point.
  166. if i > 0:
  167. p_prev = spline.GetPoint(i-1)
  168. if i < len_orig-1:
  169. p_next = spline.GetPoint(i+1)
  170. p_mid_cw = get_chamfer_point_xy(p_prev, p_curr, p_next, thickness / 2.0)
  171. p_mid_ccw = get_chamfer_point_xy(p_next, p_curr, p_prev, thickness / 2.0)
  172. new_spline.SetPoint(i, p_mid_cw)
  173. new_spline.SetPoint(len_new-i-1, p_mid_ccw)
  174. doc.AddUndo(c4d.UNDOTYPE_CHANGE, spline)
  175. spline = new_spline
  176. return len_new - len_orig;
  177. def fold_spline_on_itself(spline):
  178. """Takes a 'spline' object, and appends points which backtrack to the first.
  179. If the origional spline has points at positions: A,B,C,D
  180. The new spline append s(len*2-2) points and becomes: A,B,C,D,C,B
  181. Neither the last or first point are not repeated.
  182. Args:
  183. spline: Spline object to fold back on itself by appending.
  184. Returns:
  185. number of points added.
  186. """
  187. if (spline == None or not spline.CheckType(c4d.Ospline) or
  188. spline.GetPointCount() < 3):
  189. return 0;
  190. len_orig = spline.GetPointCount()
  191. len_new = (len_orig) * 2 - 2
  192. doc.AddUndo(c4d.UNDOTYPE_CHANGE, spline)
  193. spline.ResizeObject(len_new)
  194. for i in range(1, len_orig-1):
  195. e = len_new - i # Working back from last point.
  196. point = spline.GetPoint(i)
  197. new_point = c4d.Vector(point.x, point.y, point.z)
  198. spline.SetPoint(e, new_point)
  199. return len_new - len_orig;
  200. def main():
  201. # Get the selected objects, including children.
  202. selection = doc.GetActiveObjects(c4d.GETACTIVEOBJECTFLAGS_CHILDREN)
  203. if len(selection) <= 0:
  204. gui.MessageDialog('Must select spline object(s)!')
  205. return
  206. # Open the options dialogue to let users choose their options.
  207. dlg = OptionsDialog()
  208. dlg.Open(c4d.DLG_TYPE_MODAL, defaultw=300, defaulth=50)
  209. if not dlg.ok:
  210. return
  211. doc.StartUndo() # Start undo block.
  212. num_splines_changed = 0
  213. for i in range(0,len(selection)):
  214. spline = selection[i]
  215. if not spline.CheckType(c4d.Ospline) or spline.GetPointCount() < 2:
  216. continue
  217. num_splines_changed += 1
  218. # Make copy if needed:
  219. if dlg.option_make_copy:
  220. new_spline = spline.GetClone()
  221. doc.InsertObject(new_spline, pred=spline)
  222. doc.AddUndo(c4d.UNDOTYPE_NEW, new_spline)
  223. spline = new_spline
  224. # Apply chosen action:
  225. points_added = 0
  226. if dlg.option_action_expand:
  227. points_added = expand_spline_xz(spline, dlg.option_thickness)
  228. elif dlg.option_action_reverse:
  229. points_added = fold_spline_on_itself(spline)
  230. # Close spline:
  231. if dlg.option_close_spline:
  232. spline[c4d.SPLINEOBJECT_CLOSED] = True
  233. doc.EndUndo() # End undo block.
  234. c4d.EventAdd() # Update C4D to see changes.
  235. gui.MessageDialog(str(num_splines_changed) + ' splines changed')
  236. if __name__=='__main__':
  237. main()





自定义图标案例

image.png

  1. import c4d,os
  2. from c4d import gui,bitmaps
  3. MY_BITMAP_BUTTON = 1003
  4. class MyDialog(c4d.gui.GeDialog):
  5. def CreateLayout(self):
  6. self.SetTitle("My Python Dialog")
  7. self.GroupBegin(0, c4d.BFH_SCALEFIT|c4d.BFH_SCALEFIT, 1, 1, "Bitmap Example",0)
  8. bc = c4d.BaseContainer() ######Create a new container to store the button image
  9. bc.SetLong(c4d.BITMAPBUTTON_BORDER, c4d.BORDER_OUT) #Sets the border to look like a button
  10. bc.SetLong(c4d.BITMAPBUTTON_ICONID1, c4d.RESOURCEIMAGE_MOVE) #####Sets Button Icon
  11. bc.SetBool(c4d.BITMAPBUTTON_BUTTON, True) #<---Does Not animate in R13!?
  12. self.myBitButton=self.AddCustomGui(MY_BITMAP_BUTTON, c4d.CUSTOMGUI_BITMAPBUTTON, "My Button", c4d.BFH_CENTER | c4d.BFV_CENTER, 50, 50, bc)
  13. self.GroupEnd()
  14. return True
  15. #Do something when the button is pressed
  16. def Command(self, id, msg=None):
  17. if id==MY_BITMAP_BUTTON:
  18. print "Hello"
  19. return True
  20. if __name__=='__main__':
  21. dlg = MyDialog()
  22. dlg.Open(c4d.DLG_TYPE_ASYNC, defaultw=100, defaulth=100)

坐标相关

  1. import c4d
  2. def main():
  3. #创建物体
  4. obj1 = c4d.BaseObject(5160)
  5. doc.InsertObject(obj1) #导入到文档
  6. return
  7. #常用标签
  8. print "所有标签", op.GetTags() #所有标签
  9. print "点总数", op.GetTagDataCount(c4d.Tpoint) #点总数
  10. print "面总数", op.GetTagDataCount(c4d.Tpolygon) #面总数
  11. print "第一个标签", op.GetFirstTag() #第一个标签
  12. print "最后一个标签", op.GetLastTag() #最后一个标签
  13. op.MakeTag(5612) #平滑标签
  14. op.MakeTag(5637) #合成标签
  15. op.MakeTag(5629) #保护标签
  16. op.MakeTag(5676) #目标标签
  17. op.MakeTag(1019364) #约束标签
  18. op.MakeTag(1019561) #IK标签
  19. op.MakeTag(1001149) #XPresso标签
  20. op.KillTag(5612) #删除标签
  21. #文档
  22. doc = c4d.documents.GetActiveDocument()
  23. print "当前文档名称:", doc.GetDocumentName() #当前文档名称
  24. print "当前文档路径:", doc.GetDocumentPath() #当前文档路径
  25. print "顶级对象集合:", doc.GetObjects() #顶级对象集合
  26. return
  27. print "当前选中对象:", doc.GetActiveObject() #当前选中的单个对象(多个为None
  28. #名称
  29. print "对象名称:", op.GetName() #对象名称
  30. print "对象类型名称:", op.GetTypeName() #对象类型
  31. #层级
  32. #点
  33. print "隐藏点的集合:", op.GetPointH() #隐藏点的集合
  34. print "所选点的集合:", op.GetPointS() #所选点的集合
  35. print "点的位置集合:", op.GetAllPoints() #所有点的位置集合
  36. print "第n个点的位置:", op.GetPoint(1) #第n个点的位置
  37. print "顶点数量:", op.GetPointCount() #点的总数量
  38. print "更改后点的数量:", op.ResizeObject(5) #更改对象点的数量
  39. #位置
  40. #print "GetAbsPos:", op.GetAbsPos()
  41. print "GetMgn:", op.GetMgn()
  42. print "GetMg:", op.GetMg()
  43. print "GetMp:", op.GetMp()
  44. print "GetMln:", op.GetMln()
  45. print "GetMl:", op.GetMl()
  46. print "GetUpMg:", op.GetUpMg()
  47. print "GetRelMl:", op.GetRelMl()
  48. print "GetRelMln:", op.GetRelMln()
  49. if __name__=='__main__':
  50. main()
  51. c4d.EventAdd()#刷新界面

监测键盘被按下

image.png
https://developers.maxon.net/docs/Cinema4DPythonSDK/html/misc/inputevents.html

  1. import c4d
  2. def main():
  3. # Check all keys
  4. bc =c4d.BaseContainer()
  5. if c4d.gui.GetInputState(c4d.BFM_INPUT_KEYBOARD,c4d.BFM_INPUT_CHANNEL,bc):
  6. print "Qualifier Bitwise:",bc[c4d.BFM_INPUT_QUALIFIER]
  7. if bc[c4d.BFM_INPUT_QUALIFIER] & c4d.QSHIFT:
  8. print "SHIFT PRESSED"
  9. if bc[c4d.BFM_INPUT_QUALIFIER] & c4d.QCTRL:
  10. print "CONTROL PRESSED"
  11. if bc[c4d.BFM_INPUT_QUALIFIER] & c4d.QALT:
  12. print "ALT PRESSED"
  13. # Execute main()
  14. if __name__=='__main__':
  15. main()