• Setting XRef options via python?

    6
    0 Votes
    6 Posts
    1k Views
    P
    @ferdinand ok I will open another thread for this
  • TexBox CustomGUI for Python?

    13
    0 Votes
    13 Posts
    2k Views
    ferdinandF
    Yes, please create a new thread. And, no, TexBoxCustomGui has not been ported to Python. You might also want to look at this thread. Cheers, Ferdinand
  • Python: Cinema exit event

    Locked python
    4
    0 Votes
    4 Posts
    651 Views
    ferdinandF
    I think this can be closed
  • How to hide an object's native attributes

    windows 2024 python
    3
    1
    0 Votes
    3 Posts
    621 Views
    O
    @i_mazlov Thank you
  • How to SetKeyframeSelection for Subfield

    2024 python
    5
    1
    0 Votes
    5 Posts
    826 Views
    F
    Thanks again.@i_mazlov I haven't studied C++ yet, but I'm glad to know that it's achievable with C++.
  • Export RSproxy with Python

    python
    4
    0 Votes
    4 Posts
    813 Views
    R
    Great, thank you both very much. That helped a lot and I got the export working!
  • How to Undo Switching Between Modes?

    windows 2024 python
    10
    0 Votes
    10 Posts
    2k Views
    B
    @ferdinand said in How to Undo Switching Between Modes?: Well, just move the code which switches the mode to the end of your code when it is only cosmetic anyways. As I said above, a sensible way to use SetMode is when you want to leave the user in a state where he or she can continue working right away. But you can then just run all your code, check if everything went fine and then set your code. Otherwise you never set the mode, and therefore also have nothing to revert. It's a matter of workflow. It's not simply for checking the code that it's working properly. It's about a workflow. The workflow in the example is Select some mesh components, run the command. It generates something for you and switches the mode for you. If you selected the wrong components, you'd undo and try it again. But the undo won't put you back in the component mode. The issue is that that part of the command is not undoable so it's does hinder the workflow just a bit. I'm not necessarily advocating that it should be undoable or anything like that, just explaining the reasoning in this example and the value if it were undoable.
  • How to simulate "Cappucino" behavior?

    windows python 2024
    5
    0 Votes
    5 Posts
    918 Views
    ferdinandF
    PS: I would test this on heavy scenes with a lot of animations, to see if you get at least one data point for each frame (or whatever value you would consider acceptable).
  • 0 Votes
    8 Posts
    1k Views
    i_mazlovI
    Hi @hoffwerr , Please check our Support Procedures about consolidating consequent answers in a single posting. Please also do not duplicate your threads! I assume this question was answered in your second thread: GetChildren into an InExcludeData. Cheers, Ilia
  • 0 Votes
    4 Posts
    828 Views
    i_mazlovI
    Hi @justinleduc , Great to hear your issue was resolved! Special thanks on sharing your solution with the community! Regarding compiling issues you had: Error C2440: <function-style-cast>: cannot convert from AutoAlloc<ColorProfile> to GeData The AutoAlloc wrapper is just a convenient wrapper for a raw pointer. Hence, to fix your issue you just had to dereference the pointer: CheckState(colorProfile); settings.SetData(BAKE_TEX_COLORPROFILE, GeData(*colorProfile)); Cheers, Ilia
  • Can I convert a BaseBitmap into a Image file in memory?

    windows python 2024
    3
    0 Votes
    3 Posts
    509 Views
    DunhouD
    Hey @ferdinand , oops, I have an impression of this topic and tried to recall it, but I couldn't find any keywords in my mind at the time. I must have gone crazy. And the key is the GetData(), I have no concept of file composition and did not realize that what is returned here is the data required for an image file. Thank you very much. Cheers~ DunHou
  • Python Api: Document Events

    python
    8
    0 Votes
    8 Posts
    1k Views
    ferdinandF
    Hey @paulgolter, yes, this is okay. What you should not do, is traverse the whole scene graph, i.e., every object, shader, material, scene hook, track, curve, key etc that are to be found in a scene; just to get hold of all cube objects for example. For performance critical operations, we should always only traverse what we really need . But you just traverse the objects which is totally fine. I personally would avoid recursion, passing around a list, and not using an iterator, as this all makes things slower. Especially recursion/function calls are not cheap in Python. For the next major release we added some premade scene traversal functions in Python. I have attached one of the functions which will be exposed below. But your function is probably fine too, this is all very nitpicky. You do not use full recursion which is the most important thing. Everything else is probably nerd-talk. Cheers, Ferdinand def IterateTree(node: c4d.GeListNode | None, yieldSiblings: bool = False, rewindToFirstSibling: bool = False, rewindToRoot: bool = False) -> typing.Iterator[c4d.GeListNode]: """Yields nodes that are hierarchically related to `node`. .. note:: This function walks a node tree in a purely iterative manner, which makes it fast and robust for medium to large trees. For small trees (<= 100 nodes) `RecurseTree` is slightly faster. This function is usually the faster and safer choice compared to `RecurseTree` as the performance gain for large trees is significant while the loss for small trees is negligible. .. note:: To also yield non-hierarchical relationships, use `RecurseGraph` instead. :param node: The root node to start iterating from. :type node: c4d.GeListNode or None :param yieldSiblings: Whether to yield the next siblings of the current node, defaults to `False`. :type yieldSiblings: bool, optional :param rewindToFirstSibling: Whether to rewind the node to its first sibling before the iteration is carried out, defaults to `False`. :type rewindToFirstSibling: bool, optional :param rewindToRoot: Whether to rewind the node to its root before the iteration is carried out, defaults to `False`. :type rewindToRoot: bool, optional :return: An iterator that yields the descendants of the passed `node`. :rtype: typing.Iterator[c4d.GeListNode] :raises RuntimeError: If the UUID of a node could not be retrieved. :Example: .. code-block:: python import c4d from mxutils import CheckType, IterateTree # For the object tree: # # A # |___B # | |___C # | |___D # | | |___E # | |___F # G # Find the object named "D" in the scene. d: c4d.BaseObject = CheckType(doc.FindObject("D")) # Will yield D and E. for node in IterateTree(d): print (node) # Will yield D, E, and F. But not C as we start out at D and #yieldSiblings only looks # downwards, at next siblings and not previous ones. for node in IterateTree(d, yieldSiblings=True): print (node) # Will yield C, D, E, and F. Because we rewind to the first sibling of D - which is C. for node in IterateTree(d, yieldSiblings=True, rewindToFirstSibling=True): print (node) # Will yield A, B, C, D, E, and F. But not G, as we do not yield siblings. for node in IterNodeTree(d, rewindToRoot=True): print (node) # Will always yield the whole tree, no matter where we start. for node in IterateTree(d, True, True, True): print (node) """ def iter(node: c4d.GeListNode) -> typing.Iterator[c4d.GeListNode]: """Iterates over the descendants of the passed `node`. """ # The visited nodes and the node to stop iteration at. visited: dict[bytes, c4d.GeListNode] = {} terminal: c4d.GeListNode = node # Walking a tree iteratively is faster for medium to large trees than a recursive or # semi-recursive traversal. See: https://developers.maxon.net/forum/topic/13684 while node: # We could use GeListNode.__hash__ here, but it turns out that it is much slower than # doing it manually with MAXON_CREATOR_ID (sic!). Probably because of the overhead of # __hash__ hashing the UUID into an integer? nodeUuid: bytes = bytes(node.FindUniqueID(c4d.MAXON_CREATOR_ID)) if nodeUuid is None: raise RuntimeError(f"Could not retrieve UUID for {node}.") # Yield the node when it has not been encountered before. if visited.get(nodeUuid) is None: yield node visited[nodeUuid] = True # Walk the graph in a depth first fashion. getDown: c4d.GeListNode | None = node.GetDown() getNext: c4d.GeListNode | None = node.GetNext() getDownUuid: bytes | None = getDown.FindUniqueID(c4d.MAXON_CREATOR_ID) if getDown else None if getDown and getDownUuid is None: raise RuntimeError(f"Could not retrieve UUID for {getDown}.") if getDown and visited.get(bytes(getDownUuid)) is None: node = getDown elif node == terminal: break elif getNext: node = getNext else: node = node.GetUp() # --- End of iter() ---------------------------------------------------------------------------- if not isinstance(node, c4d.GeListNode): return # Set the starting node. # if rewindToRoot: # node = GetRootNode(node) # if rewindToFirstSibling: # node = GetFirstSiblingNode(node) # Traverse the hierarchy. while node: yield from iter(node) if not yieldSiblings: return node = node.GetNext()
  • How to change the value here using python

    2024 python
    8
    1
    0 Votes
    8 Posts
    1k Views
    F
    @ferdinand Thanks so much for such a detailed response. Learned a lot. My problem is solved. Thank you very much.
  • Hide the illumination group in node materials

    c++
    2
    0 Votes
    2 Posts
    505 Views
    ferdinandF
    Hey @bojidar, Thank you for reaching out to us. I assume you are talking about NodeMaterial cases, i.e., a material realized by the Nodes API. [image: 1722273375699-a78c9ce8-3a6c-4903-8428-625e0f8add14-image.png] Something like a NodeMaterial does not actually exist under the hood. A NodeMaterial is just a modified Material (i.e., the type Mmaterial) where pretty much everything except for the Viewport (and previously Illumination) tab is being hidden. This is done by us overriding GetDDescription in Material. By default not the whole illumination tab is hidden, but only everything below the check box "Portal" (don't ask me why). I just had a look: And for Redshift we recently added a section in Material::GetDescription where we check for a material being part of the Redshift node space and then hide the full tab. Since third parties do not own/overwrite Material, their node material then looks different, without them being able to change that (here at the example of V-Ray): [image: 1722273065911-e03ce790-eb53-43dc-a604-ddfe5a7bace6-image.png] For me it looks a bit like that we unintentionally left that group there. Maybe physical render node materials were/are still using that? But at least I do not see a reason why light portals and polygon lights must be standardized in this manner (we hide that group except for physical). I would recommend reaching out to us with a mail and the request to remove that "feature", i.e., make this more a program management than a programming thing. I cannot guarantee that we will do this, as there might be some special material management reasons why this has been done, but the starting point would be to have a PM discussion. Cheers, Ferdinand
  • 0 Votes
    3 Posts
    504 Views
    kangddanK
    @ferdinand Thank you !
  • How to scale all objects in a scene at once?

    2
    0 Votes
    2 Posts
    605 Views
    ferdinandF
    Hello @j_vogel, Welcome to the Maxon developers forum and its community, it is great to have you with us! Getting Started Before creating your next postings, we would recommend making yourself accustomed with our forum and support procedures. You did not do anything wrong, we point all new users to these rules. Forum Overview: Provides a broad overview of the fundamental structure and rules of this forum, such as the purpose of the different sub-forums or the fact that we will ban users who engage in hate speech or harassment. Support Procedures: Provides a more in detail overview of how we provide technical support for APIs here. This topic will tell you how to ask good questions and limits of our technical support. Forum Features: Provides an overview of the technical features of this forum, such as Markdown markup or file uploads. It is strongly recommended to read the first two topics carefully, especially the section Support Procedures: Asking Questions. About your First Question As lined out above, please follow our support procedures. Thread necromancy usually leads to problems, at least when that much time has passed, I have forked this thread. Please also follow our rules about Support Procedures: Asking Questions, in short, we do not answer "please implement this or that for me". The parameter DOCUMENT_DOCUNIT in a document is just something that is added to things like the coordinate manager, to set the unit and a multiplier for the numbers shown there. It will not scale the actual geometries (as it otherwise would be destructive) and therefore does not affect the view port. To scale all elements in the scene, you must scale all elements . You can use the command which we implemented for that, what is talked about above and which can be invoked with the button in the document scale settings. But you then have to use its UI, which is I guess not what you want. So, you would have write something like that yourself. But there is currently no premade scene traversal in Python which can be a bit daunting for beginners (will change with the next major release). Carrying out the scaling itself is not that hard, although this complexity can also vary based on the content. Since I know you have beta access: You can also pick the latest beta build, the traversal stuff is already in there. Cheers, Ferdinand Code """Demonstrates how to scale all objects in a scene by a given factor. """ import c4d SCALE_FACTOR: c4d.Vector = c4d.Vector(2) # Scale factor for the objects, we pick a uniform scale of 2. doc: c4d.documents.BaseDocument # The currently active document. def IterateTree(node: c4d.GeListNode, yieldSiblings: bool = False) -> c4d.GeListNode: """Iterates over all descendants of the given #node and optionally its next siblings. In the next major release, there will be (finally) built-in scene traversal functions in Python. The one to pick for this case would be `mxutils.IterateTree`. Its signature is compatible with what I did here. """ def iterate(node: c4d.GeListNode) -> c4d.GeListNode: if not node: return yield node for child in node.GetChildren(): yield from iterate(child) while node: yield from iterate(node) node = node.GetNext() if yieldSiblings else None def main() -> None: """Called by Cinema 4D when the script is being executed. """ # Iterate over all objects in the document and scale them. for node in IterateTree(doc.GetFirstObject(), yieldSiblings=True): node.SetMl(node.GetMl() * c4d.utils.MatrixScale(SCALE_FACTOR)) c4d.EventAdd() if __name__ == '__main__': main() edit: you should of course use the local and not global matrix, as you otherwise will scale things multiple times.
  • Importing pythonapi from ctypes freezes C4D

    s24 macos python
    7
    0 Votes
    7 Posts
    1k Views
    ferdinandF
    Hey @lasselauch, We are not able to reproduce this crash on an Intel, M1, or M3 MacBook with 2024.4.0. Please provide and submit a crash report when this is still a problem for you. I would also recommend reinstalling Cinema 4D to rule out that your installation was damaged. Cheers, Ferdinand
  • Adding image to GeDialog - Python Plugin/Script

    python
    8
    0 Votes
    8 Posts
    1k Views
    DunhouD
    @ferdinand fine for that, like I think, this is not perfect solution for this, thanks for your confirm! Cheers~ DunHou
  • Transform coordinates of a polygon's points

    5
    0 Votes
    5 Posts
    1k Views
    i_mazlovI
    Hi @SmetK, Please note that we have a great Matrix Manual with code samples. You can also check our github repository for the geometry examples, e.g. the Polygon Object example. For your further questions I kindly encourage you to create new thread and shape your posting according to how it's described in our Support Procedures: Asking Question. Cheers, Ilia
  • Importing/loading sound file to scene via Python

    python 2024 windows
    4
    1
    0 Votes
    4 Posts
    667 Views
    i_mazlovI
    Hi @ezeuz, Great to hear you've figured it out and thanks for sharing the solution with the community! Cheers, Ilia