• 0 Votes
    2 Posts
    436 Views
    i_mazlovI
    Hi @heytraile, Please have a look at our Support Procedures: How to Ask Question section. Usually it is very helpful if one provides a relevant code snippet, demonstrating the issue. This helps to reduce the room for any misinterpretations of your original question. Regarding the issue you're describing, the "null" being logged to the console is often a symptom of an implementation issue within a function that overrides the base implementation. Specifically, if a function (such as Message() or RestoreLayout()) is expected to return a particular type (e.g., bool), but instead returns None or a mismatched type, it can result in unexpected behavior and the "null" log. Cheers, Ilia
  • Issue Retrieving Alpha Layer from a Layer in MultipassBitmap

    windows c++ 2024
    2
    0 Votes
    2 Posts
    364 Views
    ferdinandF
    Hello @T1001, Thank your for reaching out to us and for splitting your questions into multiple topics. But let's put this topic on hold here until we have asked your other question (which I set as the main question). Cheers, Ferdinand
  • Python - How to insert knots in c4d.Gradient

    python
    3
    0 Votes
    3 Posts
    459 Views
    V
    Thank you very much, @i_mazlov! This is what I needed!
  • Syntax highlight in VS Code under MacOS

    python macos
    4
    0 Votes
    4 Posts
    827 Views
    ferdinandF
    I would heavily recommend using the extension, as it will automatically curate the paths for you. I.e., when you use the extension and connect to a Cinema 4D instance, it will make sure that the dummy modules of that Cinema 4D version are on the search paths. But when you really do not want to use it, you can also just edit your config so that the dummy module paths are discoverable for auto complete and the linter. [image: 1731583351292-2a76cd6c-35aa-451f-82db-02b03694e72d-image.png] What you will need in any case, is the Python and Pylance extension for VS Code, as they are the extensions which make use of these settings. When you install the connector, they will be installed automatically as a dependency. [image: 1731583415824-0b5d77af-5f23-4203-9a0a-276b8eafc62e-image.png] Cheers, Ferdinand
  • C++ Import Custom Extension With Modal

    windows c++ 2024
    2
    0 Votes
    2 Posts
    347 Views
    i_mazlovI
    Hi @RyanTheDev, 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 Please elaborate on your question, there's no good reference or solution you can get without providing the context. What is a "custom file type"? do you mean you've implemented BaseSceneLoader plugin? When you try to open dialog? Is it happening on main thread? What's the code that does this? What does it mean "keeps failing" - does it give you error instead? You can also have a look at SCENEFILTER::DIALOGSALLOWED flag, if it's applicable in your case. Cheers, Ilia
  • Python - Set Take render state

    python
    4
    1
    0 Votes
    4 Posts
    603 Views
    J
    @ferdinand Okay I will do it in the future. Thanks for the code snippet, always helps to learn!
  • OpenUSD (pxr) library in c4d python

    python 2024
    17
    0 Votes
    17 Posts
    6k Views
    i_mazlovI
    Hi @llealloo, please excuse the delayed answers. To the best of my knowledge in the near future there're no plans for integrating usd python bindings into c4d python system. By the way, with the 2025.0 release internal usd library was properly updated to OpenUSD 24.08, so we expect the double loading usd issue to be solved under OSX. Cheers, Ilia
  • UserArea drag and drop example?

    windows 2024 python
    6
    0 Votes
    6 Posts
    2k Views
    K
    I tried using a timer to solve this problem, but I still want to know if there is a more direct way import c4d import threading from c4d.gui import GeUserArea, GeDialog GADGET_ID_GEUSERAREA = 10000 class DropArea(GeUserArea): def __init__(self): # Used to store all objects involved in the drag-and-drop operation self.currentDragObjects = [] # Flag to indicate whether a drag operation is in progress self.isDragging = False # Define a timer to delay the handling of the drag completion self.dragTimer = None def Message(self, msg, result): # Handle drag-and-drop messages if msg.GetId() == c4d.BFM_DRAGRECEIVE: # Check if the drag was lost or canceled if msg.GetInt32(c4d.BFM_DRAG_LOST) or msg.GetInt32(c4d.BFM_DRAG_ESC): self.isDragging = False return self.SetDragDestination(c4d.MOUSE_FORBIDDEN) # If the drag just started, clear the previous object list if not self.isDragging: self.currentDragObjects = [] # Initialize the storage list self.isDragging = True # Mark the beginning of the drag # Verify if it is a valid drop area if not self.CheckDropArea(msg, True, True): return self.SetDragDestination(c4d.MOUSE_FORBIDDEN) # Get the dragged file object dragInfo = self.GetDragObject(msg) if dragInfo is not None: dragObject = dragInfo['object'] # Check if the object already exists in the list to avoid duplicates if dragObject not in self.currentDragObjects: self.currentDragObjects.append(dragObject) # Reset the timer to delay the handling of drag completion if self.dragTimer is not None: self.dragTimer.cancel() # Set a short timer (e.g., 0.2 seconds) to determine if the drag operation is complete self.dragTimer = threading.Timer(0.2, self._finalize_drag) self.dragTimer.start() # Set the mouse cursor to a valid state return self.SetDragDestination(c4d.MOUSE_MOVE) # Call the base class Message() method to handle other messages return c4d.gui.GeUserArea.Message(self, msg, result) def _finalize_drag(self): # Delayed execution to ensure all dragged objects have been received self.isDragging = False if self.currentDragObjects: # Print all dropped files print(f"Dropped files: {self.currentDragObjects}") # Additional logic can be executed here, e.g., handling file paths or other content # Clear the object list for the next drag-and-drop operation self.currentDragObjects = [] # Redraw the user area (if UI update is needed) self.Redraw() class ExampleDialog(GeDialog): geUserArea = DropArea() def CreateLayout(self): self.SetTitle("Drag Area") if self.GroupBegin(0, c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, cols=1, rows=0, title="", groupflags=0, initw=100, inith=100): self.GroupBorderSpace(8, 8, 8, 8) self.GroupSpace(2, 2) # Add the user area gadget self.AddUserArea(GADGET_ID_GEUSERAREA, c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, 200, 200) # Attach the user area to the gadget self.AttachUserArea(self.geUserArea, GADGET_ID_GEUSERAREA) self.GroupEnd() return True if __name__ == "__main__": global dlg dlg = ExampleDialog() dlg.Open(dlgtype=c4d.DLG_TYPE_ASYNC, defaultw=200, defaulth=200)
  • How to set the active documents preview image

    windows python
    2
    0 Votes
    2 Posts
    395 Views
    ferdinandF
    Hey @MMayrh, Thank you for reaching out to us. This is not how this parameter works. The parameter DOCUMENT_PREVIEW_IMAGE is of data type BitmapButtonStruct, not of BaseBitmap. [image: 1731082043337-54c636b2-05c8-4e3a-af41-9edf7e80bd24-image.png] The documentation is a bit misleading here. This is not the document preview bitmap, but sort of the preview bitmap delegate. I.e., an entity that is used to retrieve a preview bitmap (for a document in this case). A BitmapButtonStruct wraps a node, an ID, and a dirty flag. [image: 1731082143508-3e4681a7-7db6-45b7-a1da-5279cc028cf2-image.png] This parameter does not make too much sense in the Python API, here is what the C++ API does when the parameter is access for a document: [image: 1731082401202-459e7ff6-a8fe-4abf-ae35-adc803c17170-image.png] I.e., it returns itself (the doc), the ID of the parameter (DOCUMENT_PREVIEW_IMAGE) and the dirty state of its internal current preview bitmap as the BitmapButtonStruct bbs. What you could technically try, is implement a node, e.g., an object, and then set that object as the preview provider for a document. Your node would for that have to implement MSG_DESCRIPTION_GETBITMAP, because that is what effectively will be called. But that is all very theoretical, DOCUMENT_PREVIEW_IMAGE is largely unused in our code base, and I do not see any implemnation for the SetParameter part. So, the document will likely just ignore you trying to overwrite its preview provider. There could be some base implemenation kicking in, but I doubt it. But what you definitely cannot do, is just set there a bitmap to overwrite the preview image of the document (assuming that was what you wanted to do). That would also not make too much sense since a document is constantly recalculating its preview image. So, on the next update that image would be gone (if it would work like that). Cheers, Ferdinand
  • How to Swap location in Object Manager

    c++ s26 windows
    3
    2
    0 Votes
    3 Posts
    662 Views
    P
    @ferdinand Thank you very much for your reply
  • TempUVHandle always None! Why?

    r21 python windows
    3
    0 Votes
    3 Posts
    661 Views
    ThomasBT
    @i_mazlov Thank you very much for the hint with the texture view and for the helpful links. The second thread I have already read, but was not able to find the solution so far. I study these examples. Thank you.
  • Finding duplicate materials - Octane Render

    python r19
    17
    0 Votes
    17 Posts
    3k Views
    John_DoJ
    Hi, sorry for bringing back up this topic but the Compare() method still gives weird results in 2024.5.1. [image: 1730828935913-cinema_4d_d5fwj9o4rq.gif] Comparing a material duplicated with Ctrl-Drag returns sometimes True, sometimes False Comparing a material against a copy-pasted version (in the same scene) always returns False Comparing two identical materials both copy-pasted together in one-go in another scene always returns False, even if True was returned in the original scene. Please note that I'm using Corona Materials here but results are the same with the Standard Material.
  • Monitoring object parameter changes

    c++
    8
    0 Votes
    8 Posts
    1k Views
    M
    Thanks you!
  • Change settings of XCode project generated by project tool

    c++ macos
    3
    0 Votes
    3 Posts
    609 Views
    B
    Thank you, @f8bet00net. Yeah, I remember I had gone though this with you before. But recently, we found there is a way to customize TreatSpecificWarningsAsErrors settings in projectdefinition.txt for MSVCBase.props for windows VS projects. So I asked this question again just to double confirm if we could do similar things for MacOS XCode settings. Thanks for confirming this is not possible on MacOS.
  • How to obtain the color of each ball in each frame

    s26 windows c++
    2
    3
    0 Votes
    2 Posts
    525 Views
    ferdinandF
    Hello @pchg, Thank you for reaching out to us. Please note that we normally expect question to be accompanied by code. It is also still unanswered in which context you want to do this: As an effector, as a Script Manager script, etc. Cheers, Ferdinand Result [image: 1730718564670-347fc2f0-a0cd-4583-816b-b3e38fda2280-image.png] Code """Reads out the particle data of a MoGraph Cloner object. Must be run as a Script Manager script in Cinema 4D with a MoGraph Cloner object selected. """ import c4d doc: c4d.documents.BaseDocument # The currently active document. op: c4d.BaseObject | None # The primary selected object in `doc`. Can be `None`. def main() -> None: """Called by Cinema 4D when the script is being executed. """ if not op or not op.CheckType(c4d.Omgcloner): raise ValueError("Please select a MoGraph Cloner object.") # Get the particle data from the cloner object. data: c4d.modules.mograph.MoData = c4d.modules.mograph.GeGetMoData(op) if data is None: return # Get the transform and color data for the particles. matrices: list[c4d.Matrix] = data.GetArray(c4d.MODATA_MATRIX) colors: list[c4d.Vector] = data.GetArray(c4d.MODATA_COLOR) # Iterate over all particle data and do something with it. If we were in an effector, we could # also write back data. Technically, we could also write back data here, but it would be volatile. for i in range(data.GetCount()): matrix: c4d.Matrix = matrices[i] color: c4d.Vector = colors[i] print(f"Particle {i} at {matrix.off} with color {color}") if __name__ == '__main__': main() And here is the 2024.0.0 effector full control mode default code which more or less is very similar but also writes data. """Realizes an effector that attracts MoGraph particles spherically around its origin. Add the example to a Matrix object to understand its effect. In Full Control mode we can realize a true attraction force as we have full control over the particle values. Compare this example to Parameter Control mode to understand the difference. """ import c4d op: c4d.BaseObject # The Python Effector object containing this code. gen: c4d.BaseObject # The MoGraph Generator executing `op`. doc: c4d.documents.BaseDocument # The document `op` and `gen`are contained in. def main() -> bool: """Called by Cinema 4D to evaluate the effector. """ # Get the particle data for the effector #op. Get out when either the data cannot be retrieved. data: c4d.modules.mograph.MoData = c4d.modules.mograph.GeGetMoData(op) if data is None: return 1.0 # The transform of both the generator and the effector, the transforms of all particles, and # finally the position of the effector as if it would live in the coordinate system of the # generator. mgGen: c4d.Matrix = gen.GetMg() mgEff: c4d.Matrix = op.GetMg() matrices: list[c4d.Matrix] = data.GetArray(c4d.MODATA_MATRIX) q: c4d.Vector = ~mgGen * mgEff.off # For each particle compute a weight `w` for how much the particle should be attracted to the # attraction point `q`, and then blend the particle position between the attraction point and # its own position `p`. for i in range(data.GetCount()) : p: c4d.Vector = matrices[i].off w: float = c4d.utils.RangeMap((mgGen * ~mgEff * p).GetLength(), 0., 100., 0., 1., True) ** 3. matrices[i].off = c4d.utils.MixVec(q, p, w) # Write the new data back. data.SetArray(c4d.MODATA_MATRIX, matrices, op[c4d.FIELDS].HasContent()) return True
  • How to modify the index

    s26 c++ windows
    4
    1
    0 Votes
    4 Posts
    752 Views
    P
    @ferdinand Thank you for your reply
  • FontData BaseContainer IDs

    python r20
    4
    0 Votes
    4 Posts
    857 Views
    S
    @m_adam I still don't understand how to get the id of parameters? How do I know that this parameter has id 500?
  • Natvis settings not working?

    windows c++
    5
    0 Votes
    5 Posts
    861 Views
    ferdinandF
    Hey @bojidar, well, we do not write these object views (the natvis for MSVC and the Python scripts for Xcode) for public usage but for internal usage. That we hand them out to third parties is just a courtesy. When we are looking at maxon::GraphNode, <Type Name="maxon::GraphNode"> <DisplayString Condition="_mem[0] != 0">{((maxon::NodePath*)&amp;_mem[0]),na}</DisplayString> <!-- Root will have empty path and valid graph --> <DisplayString Condition="_mem[0] == 0 &amp;&amp; _graph._object != 0">Root</DisplayString> <DisplayString Condition="_mem[0] == 0">nullptr</DisplayString> <Expand> <Item Name="Path">(((maxon::NodePath*)&amp;_mem[0])),na</Item> <Item Name="Kind" Condition="_mem[0] != 0 &amp;&amp; _graph._object != 0">(maxon::NODE_KIND)((((nodes.module.xdl64!maxon::nodes::NodePathImpl::CountAndKind*) &amp; (*(nodes.module.xdl64!maxon::nodes::NodePathImpl**) &amp; _mem[0])->_path))->kind &amp; 0xFF)</Item> <Item Name="Kind" Condition="_mem[0] == 0 &amp;&amp; _graph._object != 0">maxon::NODE_KIND::NONE</Item> <Item Name="Info">((nodes.module.xdl64!maxon::nodes::NodesGraphModelImpl::Info*)this->_mem),na</Item> <Item Name="Graph">(this->_graph)</Item> <Item Name="Graph Storage">(this->_mem)</Item> </Expand> </Type> then there are indeed quite a few references to the implementation (which means that this cannot work in the public API). You could rip these out to make it work, but would then be left with only a small subset of the debug attributes. But that would be up to you. In general, you can expect the Cinema API to be more conservative and almost all object views working there, while the Maxon API is generally more internal in nature. Cheers, Ferdinand
  • Bake animation in the background

    python
    2
    0 Votes
    2 Posts
    502 Views
    i_mazlovI
    Hi @brian-michael, I've forked your posting in a dedicated thread. For your following postings please stick to our guidelines, which you can find in the Support Procedures, namely: Singular Subject: From all this follows that a topic must have a singular and sparse subject tied to a specific problem especially when it comes to N-years-old threads Regarding your question, please share more context on what specifically you're trying to do, because depending on that you can end up in a completely different ways of approaching your goal. For example, if you'd like to bake animation in a "read-only manner" (just take the object transformations and store/send them somewhere), then the suggested approach would be to clone document and process it in a separate C4DThread. You can check Ferdinand's code example on the exact same topic in application to rendering document: RenderDocument/PythonCallBack : how to display progress prints during the render. However, with such approach you're limited to not being able to modify original document (because you'd use the cloned document instead of the active one). Cheers, Ilia
  • Detect error-causing nodes in XPresso

    python
    4
    1
    0 Votes
    4 Posts
    717 Views
    K
    Hi @i_mazlov , Unfortunately, the python node approach is not effective for my use case, so I may have to emulate the error conditions on my own for each node. In any case, thank you for your answer.