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. ROMAN
    3. Topics
    • Profile
    • Following 0
    • Followers 0
    • Topics 11
    • Posts 26
    • Best 0
    • Controversial 0
    • Groups 0

    Topics created by ROMAN

    • ROMANR

      Selected object to selected layer

      Cinema 4D SDK
      • python r25 • • ROMAN
      5
      0
      Votes
      5
      Posts
      1.2k
      Views

      ferdinandF

      Hello @ROMAN,

      without any further questions and other postings, we will consider this topic as solved and flag it as such by Friday, 17/06/2022.

      Thank you for your understanding,
      Ferdinand

    • ROMANR

      Layers checker

      Cinema 4D SDK
      • python s24 sdk • • ROMAN
      4
      0
      Votes
      4
      Posts
      910
      Views

      ROMANR

      @mogh I didn't know about this function 🤦
      @ferdinand Thank you a lot for your detailed response. I will chek posts which you recommended

    • ROMANR

      How to Center the Axis of Objects

      Cinema 4D SDK
      • python r21 • • ROMAN
      4
      0
      Votes
      4
      Posts
      2.3k
      Views

      ferdinandF

      Hello @roman,

      I have forked this topic since this a new question. Please refer to the Forum Guidelines for details on forum procedures.

      The error message AttributeError: 'NoneType' object has no attribute 'GetAllPoints'. likely stems from you having no object selected when trying to run the script you posted. This is because the script simply assumes that op is populated, i.e., some kind of BaseObject, and even further it assumes that it is not only a BaseObject but also a PointObject. Both assumptions can prove false, as the user can have no selection, then op is None, or a selection which is not a PointObject, e.g., some parametric object.

      Your code will also not work for what you wanted to do regarding the last thread, as this new code only applies to a singular object. Your code is also a bit complicated for my taste, it could be done more cleanly like this:

      # Get the origin of the bounding box of the object, i.e., where # the axis should be. origin = node.GetMp() # The global matrix of the object. mg = node.GetMg() # The delta between where the axis is and where it should be delta = c4d.Matrix(off=origin) # Move all points by the inverse of that delta. node.SetAllPoints([(p * ~delta) for p in node.GetAllPoints()]) # Set the new node position node.SetMg(mg * delta)

      I have provided an example solution in the context of your last topic. The major insight here is that you have to do things then in two steps. First you go over all selcted objects to set their layers and try to move their axis. And after that you can calaculate the position of the null. Please also note that:

      Moving the axis of an object can be quite the can of worms when you start touching orientation or scale, as you then also have to update tangent tags, normal tags and other data. The provided code is an example and might still contain bugs you must fix yourself. We cannot provide full solutions.

      Cheers,
      Ferdinand

      The result:
      origin.gif

      The test scene:
      test_scene.c4d

      The code:

      import c4d def main(): """ """ # Start an undo stack item. doc.StartUndo() # Add a new top-level layer newLayer = c4d.documents.LayerObject() layerRoot = doc.GetLayerObjectRoot() newLayer.InsertUnder(layerRoot) doc.AddUndo(c4d.UNDOTYPE_NEWOBJ, newLayer) # Let the user name the new layer newName = c4d.gui.RenameDialog(newLayer.GetName()) newLayer[c4d.ID_BASELIST_NAME] = newName # Get the selected objects. selectedObjects = doc.GetActiveObjects(c4d.GETACTIVEOBJECTFLAGS_NONE) # Iterate over the selected objects to change their layer and the layer # of the attached materials and optionally center their axis. for node in selectedObjects: # Attempt to center the axis for editable objects. if isinstance(node, c4d.PointObject): # Get the origin of the bounding box of the object, i.e., where # the axis should be. origin = node.GetMp() # The global matrix of the object. mg = node.GetMg() # The delta between where the axis is and where it should be delta = c4d.Matrix(off=origin) # Move all points by the inverse that delta. doc.AddUndo(c4d.UNDOTYPE_CHANGE, node) node.SetAllPoints([(p * ~delta) for p in node.GetAllPoints()]) # Move the object by that delta. node.SetMg(mg * delta) # Set the layer of the current node. doc.AddUndo(c4d.UNDOTYPE_CHANGE, node) node[c4d.ID_LAYER_LINK] = newLayer # Get all materials attached with material tags to the node. isTex = lambda node: node.IsInstanceOf(c4d.Ttexture) for material in [t.GetMaterial() for t in node.GetTags() if isTex(t)]: doc.AddUndo(c4d.UNDOTYPE_CHANGE, material) material[c4d.ID_LAYER_LINK] = newLayer # Compute the mean global offset for all objects in the selection. meanOffset = (sum((n.GetMg().off for n in selectedObjects)) * (1. / len(selectedObjects))) # Create a null object at that offset to parent the selected objects to. newLayerNull = c4d.BaseObject(c4d.Onull) newLayerNull[c4d.ID_LAYER_LINK] = newLayer newLayerNull[c4d.ID_BASELIST_NAME] = newName newLayerNull.SetMg(c4d.Matrix(off=meanOffset)) doc.InsertObject(newLayerNull) doc.AddUndo(c4d.UNDOTYPE_NEWOBJ, newLayerNull) # Loop again over all selected objects to parent them to the new null # object. for node in selectedObjects: # Get the global matrix of the node and then remove it from the scene. mg = node.GetMg() doc.AddUndo(c4d.UNDOTYPE_CHANGE, node) node.Remove() # Attach the node to its new parent and set its global matrix to the # stored value. node.InsertUnder(newLayerNull) node.SetMg(mg) # Close the undo item and push an update event to Cinema 4D. doc.EndUndo() c4d.EventAdd() if __name__ == '__main__': main()
    • ROMANR

      How to fix the bug of objects position in script

      Cinema 4D SDK
      • python r21 • • ROMAN
      2
      0
      Votes
      2
      Posts
      633
      Views

      ferdinandF

      Hello @roman,

      Thank you for reaching out to us. R21 has left the SDK support cycle, which primarily means we will not debug again such versions anymore and also do not fix bugs for it anymore. I have provided below a solution for your problem which has been tested with R25 because of that, but it should run fine in R21.

      Your problem primarily is rooted in you simply reparenting the objects. Objects store their transformation - their position, scale and orientation - as a matrix relative to their parent. So, when you have the objects a, b, c with the local positions (0, 100, 0), (0, 50, 0), (0, 0, 0) and b being parented to a, then the effective global position of b is (0, 100, 0) + (0, 50, 0) = (0, 150, 0). When you then parent b to c, its position will change from (0, 150, 0) to (0, 50, 0) since c only contributes the null vector to the position of its children. The same principle applies to the scale and orientation stored in the local transform matrix of an object. You were also missing some undo-steps, at least I assumed you did not skip them intentionally.

      The topic is also covered in the Python API Matrix Manual.

      Cheers,
      Ferdinand

      The result:
      reparent.gif

      The script:

      """Moves the selected objects to a new layer and parent object. Your problem primarily is rooted in you simply reparenting the objects. Objects store their transformation - their position, scale and orientation - as a matrix relative to their parent. So, when you have the objects `a, b, c` with the local positions `(0, 100, 0), (0, 50, 0), (0, 0, 0)` and `b` being parented to `a`, then the effective global position of `b` is `(0, 100, 0) + (0, 50, 0) = (0, 150, 0)`. When you then parent `b` to `c`, its position will change from `(0, 150, 0)` to `(0, 50, 0)` since `c` only contributes the null vector to the position of its children. The same principle applies to the scale and orientation stored in the local transform matrix of an object. You were also missing some undo-steps, at least I assumed you did not skip them intentionally. """ import c4d def main(): """Entry point. """ # Start an undo stack item. doc.StartUndo() # Add a new top-level layer newLayer = c4d.documents.LayerObject() layerRoot = doc.GetLayerObjectRoot() newLayer.InsertUnder(layerRoot) doc.AddUndo(c4d.UNDOTYPE_NEWOBJ, newLayer) # Let the user name the new layer newName = c4d.gui.RenameDialog(newLayer.GetName()) newLayer [c4d.ID_BASELIST_NAME] = newName # Create a null object to parent the objects moved to the new layer to. newLayerNull = c4d.BaseObject(c4d.Onull) newLayerNull [c4d.ID_LAYER_LINK] = newLayer newLayerNull [c4d.ID_BASELIST_NAME] = newName doc.InsertObject(newLayerNull) doc.AddUndo(c4d.UNDOTYPE_NEWOBJ, newLayerNull) # Iterate over the selected objects and attach them both to the new layer # and layer null-object. for item in doc.GetActiveObjects(c4d.GETACTIVEOBJECTFLAGS_NONE): # Set the layer of the current item, detach it from its previous # parent and store its global matrix. doc.AddUndo(c4d.UNDOTYPE_CHANGE, item) item [c4d.ID_LAYER_LINK] = newLayer itemMg = item.GetMg() item.Remove() # Attach the object to the null and set its global matrix to the old # value. item.SetMg(itemMg) item.InsertUnder(newLayerNull) # Get all materials attached with material tags to the item. isTex = lambda item: item.IsInstanceOf(c4d.Ttexture) for material in [t.GetMaterial() for t in item.GetTags() if isTex(t)]: doc.AddUndo(c4d.UNDOTYPE_CHANGE, material) material[c4d.ID_LAYER_LINK] = newLayer # Close the undo item and push an update event to Cinema 4D. doc.EndUndo() c4d.EventAdd() if __name__ == '__main__': main()
    • ROMANR

      Get port id of xpresso node

      Cinema 4D SDK
      • python s24 • • ROMAN
      6
      0
      Votes
      6
      Posts
      1.1k
      Views

      kbarK

      Was just searching for something related and came across this post and thought I would also point out my site that also displays all the data from the resource files.

      https://plugins4d.com/Description/Nodes

      Here is the page for GVSpline: https://plugins4d.com/Description/Node?containerName=GVspline

      It is similar to the documentation now supplied in the official maxon docs.

    • ROMANR

      Xpresso set port for all nodes

      Cinema 4D SDK
      • python • • ROMAN
      3
      0
      Votes
      3
      Posts
      552
      Views

      ROMANR

      @m_magalhaes Thank you for answer!

    • ROMANR

      Insert scene under object

      Cinema 4D SDK
      • python • • ROMAN
      5
      0
      Votes
      5
      Posts
      799
      Views

      ROMANR

      Mike, thank you a lot!

    • ROMANR

      Set up selected user data value

      Cinema 4D SDK
      • • • ROMAN
      3
      0
      Votes
      3
      Posts
      452
      Views

      ROMANR

      @ferdinand Sorry for the late reply. Yes you understood me correctly. Will this be fixed in new c4d versions?

    • ROMANR

      Add user data to HUD by python

      Cinema 4D SDK
      • • • ROMAN
      3
      0
      Votes
      3
      Posts
      512
      Views

      ROMANR

      It’s too bad, but thank you for your answer Manuel.

    • ROMANR

      Layer Selection Python

      Cinema 4D SDK
      • python r21 • • ROMAN
      11
      0
      Votes
      11
      Posts
      1.5k
      Views

      ROMANR

      @cairyn Thank you again. I will check your patreon

    • ROMANR

      Log in annotation tag (python)

      General Talk
      • • • ROMAN
      10
      0
      Votes
      10
      Posts
      1.4k
      Views

      ferdinandF

      Hello @ROMAN,

      without any further questions or replies, we will consider this topic as solved by Monday and flag it accordingly.

      Thank you for your understanding,
      Ferdinand