Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login
    1. Maxon Developers Forum
    2. bentraje
    3. Best
    B
    • Profile
    • Following 0
    • Followers 1
    • Topics 241
    • Posts 738
    • Best 17
    • Controversial 0
    • Groups 0

    Best posts made by bentraje

    • RE: LINK EFFECTORS TO CLONERS

      Hi,

      Not quite directly a revision of your code but this should help you get started.

      import c4d
      from c4d import gui
      
      # Main function
      def main():
          cloner = doc.SearchObject("Cloner") # Assuming there is already a Cloner Mograph Object 
          plain_effector = doc.SearchObject("Plain")# Assuming there is already a Plain Effector Object 
      
          effector_list = c4d.InExcludeData()
          effector_list.InsertObject(plain_effector, 1)
      
          cloner[c4d.ID_MG_MOTIONGENERATOR_EFFECTORLIST] = effector_list
          c4d.EventAdd()
      
      
      # Execute main()
      if __name__=='__main__':
          main()
      
      posted in Cinema 4D SDK
      B
      bentraje
    • RE: How to detect a new light and pram change?

      @Dunhou
      I fork that redshift light manager last time.
      https://github.com/bentraje/c4d_redshift_light_lister

      I just change the minimum for it to work on the latest C4D versions.
      It works on C4D 2023, last time I check, and on RS 3.5, but not all parameters are fully supported since I didn't refactor that much.

      2002c62c-f3a1-4565-9dd7-4136add8ceba-image.png

      posted in Cinema 4D SDK
      B
      bentraje
    • RE: requirenments for building Cinema 4D extension

      Cinema4D can accommodate plug-ins written in C++ or Python. However, it only accept scripts written in Python.

      posted in General Talk
      B
      bentraje
    • RE: Developing .obj sequence exporter for selected objects

      Probably not that helpful but there is an existing script for the C4D OBJ Sequence Exporter
      https://richh.co/c4d-native-obj-sequence-export-no-plugins/

      posted in Cinema 4D SDK
      B
      bentraje
    • RE: Disable a tag from Python

      Hi @blieque

      You can do is the Basic>Enable Checkbox in every object.
      If you drag it to the console, the parameter is [c4d.ID_BASEOBJECT_GENERATOR_FLAG]

      posted in Cinema 4D SDK
      B
      bentraje
    • RE: Modify the Default Untitled Python Script

      Thanks Adam for the confirmation.
      I'll just send it for Maxon Suggestion for now.

      Thanks!

      posted in Cinema 4D SDK
      B
      bentraje
    • RE: Get/Fetch Node from an Existing Xpresso Tag

      Thanks @m_adam. Works as expected.
      My bad, I was looking at the documentation hierarchy erroneously (i.e c4d > modules > graphview > GvNode)

      Just a note: I think the if Multiply: line is supposed to be if isMultiply:.

      Thanks again. Have a great day ahead!

      posted in Cinema 4D SDK
      B
      bentraje
    • RE: Get the Button GadgetID Directly Under the Mouse?

      Hi @m_adam

      Thanks for the patience. Your suggestions and reminders works are greatly appreciated.

      I guess the confusion stems mainly on my part because I posted slightly two different codes. You were responding to my initial post but I was thinking with the code from the succeeding post(the one in the rar file). Totally my bad.

      Anyhow, here is the working code (using the initial post) which works as I expected:

      import c4d
      
      class ColorButton(object):
      
          def __init__(self):
              self.width = None
              self.height = None
              self.color = None
              self.color = None
              self.btn_id = None
              self.menu_list = None
      
      
          def create(self, dlg, w, h, color, btn_id):
      
              self.width = w
              self.height = h
              self.color = color
              self.btn_id = btn_id
      
              bmp_color = c4d.bitmaps.BaseBitmap()
              bmp_color.Init(w, h)
      
              for y in xrange(w):
                  for x in xrange(h):
                      bmp_color.SetPixel(x, y, color[0], color[1], color[2])
      
              bcBitmapButton = c4d.BaseContainer()
              bcBitmapButton[c4d.BITMAPBUTTON_BUTTON] = True
      
              bmp_btn = dlg.AddCustomGui(self.btn_id, c4d.CUSTOMGUI_BITMAPBUTTON, "", c4d.BFH_CENTER | c4d.BFV_CENTER, w, h, bcBitmapButton)
      
              bmp_btn.SetImage(bmp_color, True)
      
          def create_menu(self):
      
              self.menu = c4d.BaseContainer()
      
              for menu_item in self.menu_list: 
                  counter = 0
                  IDM_MENU = c4d.FIRST_POPUP_ID + counter
                  self.menu.InsData(IDM_MENU, menu_item)
      
                  counter += 1
      
      class MyDialog(c4d.gui.GeDialog):
      
          def __init__(self):
              self.btn_id_list = []
              self.class_btn_id_dict = {}
      
          def CreateLayout(self):
      
              red_button = ColorButton()
              red_button.create(self, w=50,h=50,color=(255,0,0), btn_id=6000)
              red_button.menu_list = ['Menu1', 'Menu2', 'Menu3']
              self.btn_id_list.append(red_button.btn_id)
              self.class_btn_id_dict[6000] = red_button
      
              blue_button = ColorButton()
              blue_button.create(self, w=50,h=50,color=(0,0,255), btn_id=7000)
              blue_button.menu_list = ['Menu4', 'Menu5', 'Menu6', 'Menu7']
              self.btn_id_list.append(blue_button.btn_id)
              self.class_btn_id_dict[7000] = blue_button
      
      
              green_button = ColorButton()
              green_button.create(self, w=50,h=50,color=(0,255,0), btn_id=8000)
              green_button.menu_list = ['Menu8', 'Menu9']
              self.btn_id_list.append(green_button.btn_id)
              self.class_btn_id_dict[8000] = green_button
      
              return True
      
          def IsPositionOnGadget(self, gadgetId, x, y):
              # Be sure that the windows is opened,
              # in our case since we call it in BFM_INTERACTSTART it's ok
              buttonData = self.GetItemDim(gadgetId)
              
              if not buttonData["x"] < x < buttonData["x"] + buttonData["w"]:
                  return False
      
              if not buttonData["y"] < y < buttonData["y"] + buttonData["h"]:
                  return False
      
              return True
          
          def function_to_determine_gadgetId_under_mouse_cursor(self, x, y):
              for gadgetId in self.btn_id_list:
                  if self.IsPositionOnGadget(gadgetId, x, y):
                      return gadgetId
                  
          def Message(self, msg, result):
              if msg.GetId() == c4d.BFM_ADJUSTSIZE:
                self._x = msg[3] # Retrieve Y size of the GeDialog
                self._y = msg[4] # Retrieve Y size of the GeDialog
      
              # We are on the main thread here
              elif msg.GetId() == c4d.BFM_INTERACTSTART:
                  c4d.StopAllThreads()
      
                  state = c4d.BaseContainer()
                  self.GetInputState(c4d.BFM_INPUT_MOUSE, c4d.BFM_INPUT_MOUSERIGHT, state)
      
                  if state.GetInt32(c4d.BFM_INPUT_VALUE) == True:
      
                      x = state.GetInt32(c4d.BFM_INPUT_X)
                      y = state.GetInt32(c4d.BFM_INPUT_Y)
                      g2l  = self.Global2Local() 
                      x += g2l['x']  
                      y += g2l['y']
      
                      gadgetId = self.function_to_determine_gadgetId_under_mouse_cursor(x=x,y=y)
      
                      if gadgetId in self.btn_id_list:
      
                           if self.IsPositionOnGadget(gadgetId=gadgetId, x=x, y=y):
      
                                button_class = self.class_btn_id_dict[gadgetId] 
                                button_class.create_menu()
      
      
                                l2s = self.Local2Screen()
                                print str(x+l2s['x']) + " :: " + str(y+l2s['y'])
                                self.KillEvents()
                                res = c4d.gui.ShowPopupDialog(cd=self, bc=button_class.menu, x=x+l2s['x'], y=y+l2s['y'])
                                return True
      
              return c4d.gui.GeDialog.Message(self, msg, result)
      
      if __name__ == "__main__":
          dlg = MyDialog()
          dlg.Open(dlgtype=c4d.DLG_TYPE_ASYNC, pluginid=20304050)
      
      posted in Cinema 4D SDK
      B
      bentraje
    • RE: Content Browser Like Navigation?

      @r_gigante

      Thanks for the reference.
      For anyone trying to achieve the same,
      here is a sample file.
      https://www.dropbox.com/sh/z1lzyphp8qnt9kw/AAB2P5gNo16IHafgc6xPEsy4a?dl=0

      Thanks again for @zipit for the help.

      posted in Cinema 4D SDK
      B
      bentraje
    • RE: Copy, Paste, Flip X a Pose Morph Target?

      @m_magalhaes @zipit

      I managed to flip the mesh (not necessarily a pose morph target since I'd have to know the API).
      Anyhow, here is a demo of it working:
      https://www.dropbox.com/s/bh4p26s4m9qwljw/c4d272_flip_miror_mesh.mp4?dl=0

      Here is wip script. It only works if the x-axis is dead set on 0.
      Also, it is slow since it has to loop within a loop.

      import c4d
      from c4d import gui
      
      
      # Main function
      def main():
          neutral_geo = doc.SearchObject('neutral_geo')
          posed_geo = doc.SearchObject('posed_geo')
          neutral_world_matrix = neutral_geo.GetMg()
          posed_world_matrix = posed_geo.GetMg()
          
          neut_lcl_pnts = neutral_geo.GetAllPoints()
          neut_gbl_pnts = [point * neutral_world_matrix for point in neut_lcl_pnts]
          
          posed_lcl_pnts = posed_geo.GetAllPoints()
          posed_gbl_pnts = [point * posed_world_matrix for point in posed_lcl_pnts]
              
          match_pnts = []
          left_pnts = []
          right_pnts = []
          
          for idx, point in enumerate(neut_gbl_pnts):
              if point[0] == 0.0: # ignore points at the world x axis
                  continue
              
              if point[0] > 0.0:
                  left_pnts.append((idx,point))
              
              if point[0] < 0.0:
                  right_pnts.append((idx,point))
                  
          
          for left in left_pnts:
              for right in right_pnts:
                  if left[1][1] == right[1][1]: # check if Y pos match
                      if left[1][2] == right[1][2]: # check if Z pos match
                         if left[1][0] == -1 * (right[1][0]):# check if X pos are inverse
                             match_pnts.append((left[0],right[0]))
              
              
          for pnt in match_pnts:
              
              reversed_left = posed_lcl_pnts[pnt[1]]
              reversed_left[0] = reversed_left[0] * -1
              reversed_right = posed_lcl_pnts[pnt[0]]
              reversed_right[0] = reversed_right[0] * -1
              
              
              posed_geo.SetPoint(pnt[0], reversed_left)
              posed_geo.SetPoint(pnt[1], reversed_right)
              
          posed_geo.Message(c4d.MSG_UPDATE)
           
          c4d.EventAdd()
      
      # Execute main()
      if __name__=='__main__':
          main()
      
      posted in Cinema 4D SDK
      B
      bentraje
    • RE: SetAllPoints() Not Working On An Object With Skin/Bind

      @m_adam

      Thanks for the response.

      RE: without enabling the Post Deformers option.
      It seems like so. I initially thought I could reverse engineer it by getting the point's skin influence (its joint and its weight) and in a way factor it with the intended world vector. However, I gave up since I realize point can have several joints and several weight. Haha

      Don't get me wrong, enabling the post deformer works as expected.
      The problem comes because of its inherent nature
      "calculate the points position of the morph after they are deformed by a Deformer."

      It presupposes that the (near) last deformation comes from the pose morph.
      For example, Squash/Stretch>Bulge>Bend>Twist>Pose Morph.
      However, there are cases where the intended deformation is
      Pose Morph>Squash/Stretch>Bulge>Bend>Twist.

      So having the post deformer off while still getting the world position desired gives a bit of flexibility.

      Anyhow, thanks again for the help.
      I'll just use the post deformer for now and see where I get stuck.

      Have a great day ahead!

      posted in Cinema 4D SDK
      B
      bentraje
    • RE: Can I now script creation of Node Materials (R21.1, S22, R23, S24) ?

      Any updates on this one?

      posted in Cinema 4D SDK
      B
      bentraje
    • Change the ColorSpace of Redshift Texture Node?

      Hi,

      I can access the colorspace port through
      port = texture_node.GetInputs().FindChild("com.redshift3d.redshift4c4d.nodes.core.texturesampler.tspace_id")

      With the inspector enabled, it shows it accepts a string. I tried the following
      port..SetDefaultValue(maxon.String("sRGB"))
      port.SetDefaultValue("sRGB")

      But it doesn't change the values nor does it error out.

      Is there a way around this?

      f72b3611-7f4c-4b75-b4d9-9d6609c3dea8-image.png

      posted in Cinema 4D SDK r25 python
      B
      bentraje
    • RE: GetMg() doesn't update on objects affected with Align to Spline Tag?

      @i_mazlov

      Gotcha. Thanks. Works as expected.

      posted in Cinema 4D SDK
      B
      bentraje
    • RE: Get All Nodes inside an Xpresso Tag?

      Ah my bad. It's just the same for objects in object manager.
      Here is the code for reference:

      import c4d 
      
      def GetAllNodes(gvNode=None, nodeList=None):
              if nodeList is None:
                  nodeList = list()
                  gvNode = nodemaster.GetRoot()
      
              while gvNode:
                  nodeList.append(gvNode)
                  GetAllNodes(gvNode.GetDown(), nodeList)
                  gvNode = gvNode.GetNext()
      
              if len(nodeList) > 1: 
                  nodeList = nodeList[1:] # Remove the Xgroup
                  
              return nodeList
      
      geo_obj = doc.SearchObject("Cube")
      exp_tag = geo_obj.GetTag(1001149) #Get Expresso
      nodemaster = exp_tag.GetNodeMaster()
      node_list = GetAllNodes()
      
      posted in Cinema 4D SDK
      B
      bentraje
    • RE: Get the Neighboring Keys from a Selected Key?

      Hi @ferdinand

      Apologies for the late response.

      RE: You should show me how you access that key.
      My bad. But it's on the previous thread you answered by manually selecting a keyframe and storign it in a variable.
      https://developers.maxon.net/forum/topic/15344/get-selected-keyframes/3

      RE: I just showed you above how to operate with percentage values in Cinema 4D.
      My bad. I missed it. I was looking immediately at the declaration.

      keyA: c4d.CKey
      keyB: c4d.CKey
      

      which I only want one key to be declared.

      ===

      In summary, the GetNext() and GetPred() solved the problem in getting the Neighboring Keys from a Selected Key.

      posted in Cinema 4D SDK
      B
      bentraje
    • RE: GetCache Does Not Work Inside the Python Generator

      @ferdinand

      Thanks for the response. Your code works without the program freezing up (although I think it's GeGetCurrentThread instead of GetCurrentThread()). Other than that, it works as expected.

      Ah. I didn't think to just pass objects from different documents.

      I was thinking of something like this:

      1. All in the same document. Create a dummy object in the same document. In this way, the cache is already created because it now exist.
      2. Clone it. Store the data.
      3. Delete the dummy object in the same document.

      The problem was that in #3, the generator no longer has access to that object for some reason. So it keeps creating a dummy object lol

      Anyway, enough for my excuses. Sorry for the trouble and thanks again for your patience.

      posted in Cinema 4D SDK
      B
      bentraje