• Add Additional Script Path?

    General Talk r25 python
    3
    0 Votes
    3 Posts
    613 Views
    B
    @m_adam Thanks for the response. Modifying the environment varialbles works for my use case. Closing the thread now.
  • Replace "Shape Node"?

    Cinema 4D SDK 2023 python
    4
    0 Votes
    4 Posts
    609 Views
    B
    @ferdinand Thanks for the outlining the limitation. For options Yep the replace command does not carry over the connection so that's a no go. I just went with the python route. Works as expected. Basically, I just deleted all the points of the spline object through the resize object. Then rebuild it again with the reference. No problem so far. RE: scene nodes. Uhm I really find the nodes implementation clunky at the moment and this is coming from a user who uses Houdini. No plans in implementing it at all in my workflow.And the pyro being implemented as a tag and not as a scene nodes set-up tells a lot that they are not confident in that workflow. Too convoluted for what it is trying to achieve and doesn't use "attributes" like what Houdini and Blender can. I find it as a "toy" at the moment rather than an actual production tool. Anyway, will close this thread for now.
  • 0 Votes
    5 Posts
    1k Views
    K
    Hi @ferdinand, Thank you for the detailed explanation and the code. It works perfectly and the problem is solved!
  • Actively Link Hair Guides to a Spline or Alembic?

    Cinema 4D SDK r25 python
    3
    0 Votes
    3 Posts
    696 Views
    B
    Hi @ferdinand Thanks for the response and heads up on the crashes. RE: you want to control hair guide vertices programmatically Yep yep you are right on this part. Basically, have a geometric hair animated and simulated for preview. But rendered on the actual hair object. This is the workflow for other DCC, and the more logical one. This way you separate the hair source and hair generation. It's easier to debug. Anyhow, for looking at your python example, this should get me by on my current use case. Thanks for your illustration as always! Will close thread now.
  • Copy Assets to new Location

    Cinema 4D SDK python
    3
    0 Votes
    3 Posts
    627 Views
    C
    Hi ferdinand, I am very sorry for my lack of reading the Guidelines properly. But still, very huge thanks to you for the explanation anyway. This already helped me. I will try things out and will probably come back here with some code.
  • Asset Browser: Add Watch Folder

    Cinema 4D SDK python
    4
    0 Votes
    4 Posts
    1k Views
    a_blockA
    Thanks, Ferdinand. I'll take a closer look as soon as I find the time.
  • Make Node Callbacks Optional?

    Cinema 4D SDK python
    3
    0 Votes
    3 Posts
    363 Views
    B
    @ferdinand Thanks as always for the explanation. The illustration code works for my use case. Will close now thread
  • C4D 2023 Script Manager Doesn't Update?

    General Talk python
    3
    0 Votes
    3 Posts
    684 Views
    B
    @m_adam Thanks for the confirmation. Will close the thread for now.
  • Node Method IsValid() Throws ValueError

    Cinema 4D SDK python r25
    5
    0 Votes
    5 Posts
    501 Views
    B
    @m_adam Gotcha. Thanks for the heads up!
  • How to Modify the Axis of a Point Object?

    Cinema 4D SDK python
    7
    0 Votes
    7 Posts
    3k Views
    ferdinandF
    Hey @delizade, The script works for anything that is a c4d.PointObject, i.e., editable polygon and spline objects. But not for generators, e.g., the Cube object or the Circle spline, as you cannot edit their points and therefore have no control over the placement of their "axis" in relation to their vertices. When you want to set the transform of any BaseObject, e.g., a PointObject, a generator, or a null object, you must simply set either its local or global matrix. But this will not keep vertices 'in place' as generators and a null object have no vertices one could edit, and the vertices of PointObject instances must be corrected manually to achieve the 'move the axis idea'. But you can of course just set the global or local matrix (a.k.a. transform) of a BaseObject. Find an example below. For more detailled information, I would recommend having a look at the Matrix Manual. Cheers, Ferdinand The result, the two cubes are not at the same location because combining two transforms is not commutative, i.e., the order matters. A * B is not always the same as B * A for matrices: [image: 1669892200687-8392f997-7526-4a6d-b00b-e020d7669c59-image.png] The code: """Demonstrates the basic concept of transformations as realized by Cinema 4D. """ import c4d def main() -> None: """Constructs two transforms and applies them in the global coordinate system to two cube objects. """ # Construct a transform that translates by 500 units on the y-axis and one that rotates by # 45° on the x-axis. move: c4d.Matrix = c4d.utils.MatrixMove(c4d.Vector(0, 500, 0)) rotate: c4d.Matrix = c4d.utils.MatrixRotX(c4d.utils.DegToRad(45)) # Combine both transforms into a singular one by multiplying them. Note that matrix # multiplication, combining transforms, is not commutative. I.e., the order matters opposed # to numbers; move * rotate is not the same as rotate * move. tMoveRotate: c4d.Matrix = move * rotate tRotateMove: c4d.Matrix = rotate * move # Allocate two cube objects. cubeMoveRotate: c4d.BaseObject = c4d.BaseObject(c4d.Ocube) cubeRotateMove: c4d.BaseObject = c4d.BaseObject(c4d.Ocube) if None in (cubeMoveRotate, cubeRotateMove): raise MemoryError("Could not allocate cube object.") # And set their global matrix, i.e., the absolute transform in the global coordinate system. cubeMoveRotate.SetMg(tMoveRotate) cubeRotateMove.SetMg(tRotateMove) # Name both null objects, set their display color, insert them into the active document, and # push an update event. cubeMoveRotate.SetName("Cube: Move -> Rotate") cubeRotateMove.SetName("Cube: Rotate -> Move") cubeMoveRotate[c4d.ID_BASEOBJECT_USECOLOR] = c4d.ID_BASEOBJECT_USECOLOR_ALWAYS cubeRotateMove[c4d.ID_BASEOBJECT_USECOLOR] = c4d.ID_BASEOBJECT_USECOLOR_ALWAYS cubeMoveRotate[c4d.ID_BASEOBJECT_COLOR] = c4d.Vector(1, 0, 0) cubeRotateMove[c4d.ID_BASEOBJECT_COLOR] = c4d.Vector(0, 0, 1) doc.InsertObject(cubeMoveRotate) doc.InsertObject(cubeRotateMove) c4d.EventAdd() if __name__ == '__main__': main()
  • Drag and Drop from GeUserArea in Python

    Cinema 4D SDK python
    3
    0 Votes
    3 Posts
    880 Views
    a_blockA
    Hi Maxime, that's a bummer. Just a few additions: is done by calling HandleMouseDrag. Your code is paused until the drag operation ended Yes, no objection. But it should be said, during this "pause" one does still receive messages, among them BFM_DRAGRECEIVE_START and BFM_DRAGRECEIVE. Just not BFM_DRAGEND. Which makes me think, if only the receiver would not "consume" this message, it could already work... From a pure implementation point of view, it also does make sense since it would make no sense if each drag operation have to support all possible managers I wouldn't want it differently. But I still think, the initiator of an action deserves result information. after all these years, I'm still wondering, what's this obsession with not delivering feedback to a caller. Yes, I'm looking at you CallCommand()... Finally it is not possible to drag objects directly to the viewport I didn't even consider, drag and drop could work differently for materials and objects, or objects not working at all. So, thanks for the info and avoiding even more headache on my end. I guess, we are back to the drawing board then. Anyway, greetings to the team. Cheers, Andreas
  • Custom GUI Linkbox checking for Accepted types?

    Cinema 4D SDK r23 python
    3
    0 Votes
    3 Posts
    944 Views
    CairynC
    @ferdinand Thanks for the reply! Ah, of course, I should have considered that Command is actually the last message I get for that operation. This Message stuff totally got me on the wrong track. Naturally, resetting the link and thereby cancelling and reverting the user's drag or pick operation is not as nice as showing a "stop sign" mouse pointer during the operation. Since the ACCEPT clause in a Resource allows setting accepted types, I wonder why there is no API functionality allowing the same. It's not even in the C++ implementation. I suppose people should use external resources anyway, but seeing stuff in the API makes functionality clearer to me at least. Regarding PyCapsule, no, I didn't happen across that previously, I just took code from some other thread on this forum to get into the message. I was lazy and looked for PyCapsule in the Cinema 4D API doc, and assumed it undocumented when it wasn't found. Totally my fault, I should have checked the web too. Never program in an unfamiliar scope past midnight! Nice code btw.
  • Swap Out Joint Axis Rotation?

    Cinema 4D SDK r25 python
    7
    0 Votes
    7 Posts
    668 Views
    B
    @manuel Interesting. Thanks for the heads up. It works now as expected. Closing the thread.
  • MatrixToHPB Not Giving the Global Rotation?

    Cinema 4D SDK r25 python
    3
    1
    0 Votes
    3 Posts
    379 Views
    ferdinandF
    Hello @bentraje, thank you for reaching out to us. There is nothing much left to add for us here. All angle values are represented internally in radians in Cinema 4D, only the UI does convert to degrees. Except for displaying angle values in UIs, I would however recommend to embrace the unit of radians in code rather than converting in and out of it. There is no computional downside to always doing the conversions, e.g., theta: float = c4d.utils.DegToRad(90). But writing something like theta: float = math.pi * .5 forces oneself to understand the intimate relation between a trigangle and the unit circle, i.e., the circle or trigonometric functions. Understanding radians and why it is a useful unit is then an emergent property of that understanding of trigonometry. Cheers, Ferdinand
  • Load Save Weights Command from Weight Manager?

    Cinema 4D SDK r25 python
    3
    1
    0 Votes
    3 Posts
    466 Views
    B
    @manuel Gotcha. Thanks for the confirmation. Closing this thread now.
  • Building menus with C4DPL_BUILDMENU in S26+

    Cinema 4D SDK s26 python
    4
    0 Votes
    4 Posts
    2k Views
    ferdinandF
    Hello @alexandre-dj, I know all menus in C4D have their own id, so this should be an easy check. That is only true on a relatively abstract level. There are string symbols, e.g., IDS_EDITOR_PLUGINS for menu resources, but there is no strict namespace management or anything else on might associate with statements such as 'all menus in C4D have their own id'. Also note that all menu entries in a menu container are stored under the integer IDs MENURESOURCE_COMMAND and MENURESOURCE_SUBMENU as shown in my example above. So, when you have a menu with ten commands and four sub-menus, all fourteen items are stored under these two IDs. This works because BaseContainer is actually not a hash map as one might think, and can store more than one value under a key. Long story short - traversing and modifying menus is not ultra complicated but I would also not label it as 'easy' ; which is why I did provide the example in my previous posting. When firing c4d.gui.GetMenuResource("M_EDITOR") to Get the whole menu of Cinema 4D (as you mention in your code here) I get a different address every time: >>> c4d.gui.GetMenuResource("M_EDITOR") <c4d.BaseContainer object at 0x000001B406C86580> >>> c4d.gui.GetMenuResource("M_EDITOR") <c4d.BaseContainer object at 0x000001B406CA6A40> >>> c4d.gui.GetMenuResource("M_EDITOR") <c4d.BaseContainer object at 0x000001B406C88C80> You are calling here the Python layer for returning a Python object representation of the C++ object that represents the menu. Cinema 4D is still a C++ application and the menu exists in your memory with the layout defined by the C++ type BaseContainer. That type has memory-wise nothing to do with its Python counter part c4d.BaseContainer. So, the Python layer must create that Python data on the fly, as otherwise the memory-footprint of Cinema 4D would double (actually more, because Python data is not exactly sparse data) and synchronizing both data layers would bring Cinema 4D to a crawl. TLDR; you retrieve the same data expressed as a different memory object because 'that is how Python works'. So when I use c4d.gui.SearchMenuResource(main_menu_ressource, my_custom_menu) to check if my custom menu is part of the main menu, this always return False, as the address of the main_menu object changes. Why your call fails here, depends a bit on what you are passing. The first argument should be the string symbol inside a sub menu, and the second item is the sub menu. When you store a reference to a sub-menu from a previous call to GetMenuResource, this might not work when SearchPluginMenuResource searches by identity instead of equality, i.e., it expects that container to be at a certain memory location (have not tried though). There is also c4d.gui.SearchPluginMenuResource(identifier='IDS_EDITOR_PLUGINS'), which should be sufficient to find anything that does not produce a name collision. I personally would just write my own stuff as demonstrated above, since I can then search however I want to. Cheers, Ferdinand
  • Crash when converting objects in bulk

    Cinema 4D SDK r23 python
    5
    0 Votes
    5 Posts
    1k Views
    ManuelM
    You can also filter your objects. Using GetInfo for example, you can check if the current object is a generator or not. If you make a generator editable, the generator will/should handle the children itself. The only exception are primitives. Primitives are generators but they do not care about their children. Cheers, Manuel
  • Python Module not found on upgrade

    Cinema 4D SDK
    4
    0 Votes
    4 Posts
    996 Views
    FSSF
    Thanks alot Ferdinand. I investigated some further and added the classes to the plugins list: _plugins = [ "Tools", "Recipe", The error was also caused, by the executables having different libraries. Meaning, we call once cinema 4d.exe, which uses the {prefs}/python39/libs folder. The second part of the plugin is executed using the classic Commandline.exe and uses the {prefs}_x/python39/libs folder. Im a idiot, but a stubborn one. Have a great day. Topic can be locked now.
  • Using AddCustomGui for primitive controls

    Cinema 4D SDK python r23
    4
    0 Votes
    4 Posts
    1k Views
    J
    Hello @Cairyn , without further questions or postings, we will consider this topic as solved by Friday 11th of august 2023 and flag it accordingly. Thank you for your understanding, Maxon SDK Group