• Catch - 'c4d.BaseDraw' is not alive

    Cinema 4D SDK
    2
    0 Votes
    2 Posts
    540 Views
    ferdinandF
    Hey @mogh, Thank you for reaching out to us. The idea of a node, a c4d.C4DAtom not being alive means that the Python layer cannot find the C++ C4DAtom which the Python layer c4d.C4DAtom was referencing, usually because something has been reallocated in the background while someone was long-term storing a c4d.C4DAtom instance. We talked about it here in more detail. Sometimes you then must write elaborate interfaces which recapture the same thing over their UUID, e.g., get hold of the same shader once its Python reference has gone bad. But that does not seem necessary here since you are interested only in the active viewport of the active document. It is in this case also not only the case that the viewport could have been reallocated, but also what is the active viewport could have changed (although that will likely cause viewports to be reallocated). So, when you want to modify the active base draw, in fact any node, make sure to get a fresh reference when possible. doc: c4d.document.BaseDocument = c4d.documents.GetActiveDocument() bd: c4d.BaseDraw = doc.GetActiveBaseDraw() self.AddCheckbox(ID_SAVEFRAME, flags=c4d.BFH_LEFT, initw=270, inith=0, name="Show Save Frame") self.SetBool(ID_SAVEFRAME, bd[c4d.BASEDRAW_DATA_SHOWSAFEFRAME]) If you need access to the active viewport of the active document very often, you could make it a property with some mild caching. import c4d import typing class Foo: """Provides cached access to the active document and active viewport. """ def __init__(self) -> None: self._activeDocument: typing.Optional[c4d.documents.BaseDocument] = None self._activeViewport: typing.Optional[c4d.BaseDraw] = None @property def ActiveDocument(self) -> c4d.documents.BaseDocument: """Returns the active document. """ if self._activeDocument is None or not self._activeDocument.IsAlive(): self._activeDocument = c4d.documents.GetActiveDocument() return self._activeDocument @property def ActiveBaseDraw(self) -> c4d.BaseDraw: """Returns the active viewport in the active document. """ if self._activeViewport is None or not self._activeViewport.IsAlive(): self._activeViewport = self.ActiveDocument.GetActiveBaseDraw() return self._activeViewport def Bar(self) -> None: """Makes use of the #ActiveBaseDraw property. """ self.ActiveBaseDraw[c4d.BASEDRAW_DATA_TEXTURES] = True Although this also suffers from the problem that what is the active viewport could have changed. Caching anything that is "active" is a bad idea as what is active can change. Active entities should always be retrieved when required unless one can guarantee that they cannot change (by being in a modal dialog for example). Cheers, Ferdinand
  • 0 Votes
    5 Posts
    536 Views
    DunhouD
    @ferdinand Thanks for your help. I did search on web and find the Unicode string, and Chinese characters is so much complicated ,when most user use Chinese for the GUI language, Maybe sometime the translation of the world "在队列中" witch means "in the queue" in English has changed ( I belive now Chinese translation is response to IHDT so it won't randomly changed). That is not a big problem but maybe a little "uniform" with the "ID" And the "brief moment" is I don't sure why does it happend. In another word ,I think the initializing render process can be also called "rendering" . so it is a bit of counterintuitive for me , maybe I should add an additional check to make sure the spying will not break while the brief. Cheers~
  • How to make Python Field react to camera?

    Cinema 4D SDK python 2023
    8
    0 Votes
    8 Posts
    1k Views
    M
    Hello @wuzelwazel, without further questions or postings, we will consider this topic as solved by Friday 02/06/2023 and flag it accordingly. Thank you for your understanding, Maxime.
  • Dialog Menu

    Cinema 4D SDK python
    6
    0 Votes
    6 Posts
    1k Views
    J
    Creating an instance for each subdialog solved the issue thank you so much.
  • 0 Votes
    3 Posts
    505 Views
    gheyretG
    @manuel Cool ! Thank you ~
  • How to implement a license check on a python plugin?

    Cinema 4D SDK python
    5
    0 Votes
    5 Posts
    992 Views
    ThomasBT
    @manuel Hi Manuel, I just wanted to let you know that I have decided on your suggestion and have decided on a license system with serial numbers that are automatically created and delivered upon purchase and in combination with a kind of license server that controls the licenses..... thank you for the hints
  • TreeView for ObjectData plugin

    Cinema 4D SDK python r23
    2
    0 Votes
    2 Posts
    476 Views
    M
    Hi Mike this is unfortunately not possible, even in C++ for more info please look at Info for ITEMTREE/customgui_itemtree. Cheers, Maxime.
  • Button Hover -> Helptext - searching for example

    Moved Cinema 4D SDK
    5
    0 Votes
    5 Posts
    777 Views
    M
    I use CreateLayout ... no description file ... but as I wrote probably a little bit to cryptic I am fine for now. Thanks for the reply Manuel. Cheers mogh
  • 0 Votes
    4 Posts
    751 Views
    ferdinandF
    Hey @mogh, just to clarify: I found that bit of the documentation before you pointed it out, but in my mind I could not link "needs a document" to "the object has to be present" ... Well, the documentation clearly states it: doc (Optional[c4d.documents.BaseDocument]) – The document for the operation. Should be set if possible. Must be set for MCOMMAND_JOIN, MCOMMAND_MAKEEDITABLE, MCOMMAND_CURRENTSTATETOOBJECT and MCOMMAND_SPLINE_PROJECT. If you set the document, the objects which you pass to this function have to be in the same document. So pay attention that you use one send_modeling_command per document for objects. But that could be more visible. I'll see if I can rework the function documentation a bit to make that important information more prominent. Cheers, Ferdinand
  • C4D Threading in python doesn't work as expect .

    Cinema 4D SDK sdk python 2023
    9
    0 Votes
    9 Posts
    2k Views
    DunhouD
    @ferdinand thanks for your generoso help. I already send you an email with an zip file , and some notes in the front of the codes. Have a good day!
  • How to get the bounding box for the whole scene

    Cinema 4D SDK python
    5
    0 Votes
    5 Posts
    3k Views
    ferdinandF
    Hey @mogh, Thank you for pointing out that problem. No, there is no Vector(0, 0, 0) being added, there was simply a small bug in my code. self.min: c4d.Vector = c4d.Vector(sys.float_info.max) self.max: c4d.Vector = c4d.Vector(sys.float_info.min) float_info.min is 2.2250738585072014e-308, i.e., the smallest representable increment of the float type, not the lower representable boundary. So, the code did initialize the max-value boundary as ~(0, 0, 0) which then caused values to be discarded which should not be discared. I of course meant here the following: self.min: c4d.Vector = c4d.Vector(sys.float_info.max) self.max: c4d.Vector = c4d.Vector(-sys.float_info.max) Fixing this should fix your problems. I have updated my original posting to not mislead future readers. Cheers, Ferdinand
  • Subprocess can't detect system installed utilities

    General Talk r23 python
    3
    0 Votes
    3 Posts
    752 Views
    mikeudinM
    Thank you @ferdinand !
  • Trying to programmatically create vertex color tag

    Cinema 4D SDK
    2
    0 Votes
    2 Posts
    704 Views
    ferdinandF
    Hello @zauhar, thank you for reaching out to us. Your code does look mostly fine and is working for me. The line op = Default makes little sense and you are of course missing things like imports, a context guard and a main function. Not all of them are absolutely necessary, but it is strongly advised to use them all, especially for novice users. Find a code example below. Vertex colors are also not automatically rendered as the diffuse color in Cinema 4D, one must use a VertexMap shader for that. Please consult the user manual or end-user support for end-user questions, we cannot deliver such support here. Cheers, Ferdinand The result for two polygon objects, the color of a vertex depends on its position in global space. [image: 1676539052471-0e9b3117-e70a-4495-8001-cbe0a6b0a2e4-image.png] Code """Creates vertex-color tag on the currently selected polygon object and makes it the active tag. Must be run as a Script Manager scrip with a polygon object selected. The color of each vertex will depend on its position in global space. """ import c4d import typing GRADIENT_MIN: float = -200.0 # The lower boundary of the gradient. GRADIENT_MAX: float = 200.0 # The upper boundary of the gradient. op: typing.Optional[c4d.BaseObject] # The active object, can be `None`. def main() -> None: """Runs the example. """ # Check that there is indeed a selected object and that it is a polygon object. if not isinstance(op, c4d.PolygonObject): raise TypeError("Please select a polygon object.") # Get its point count and allocate a vertex color tag with that count. count: int = op.GetPointCount() tag: c4d.VertexColorTag = c4d.VertexColorTag(count) if not isinstance(tag, c4d.VertexColorTag): raise MemoryError("Could not allocate tag.") # We are going to make it a little bit more exciting and write a gradient based on the global # coordinate y-component of a vertex. # Set the tag to defining colors only once per vertex instead of having N colors per vertex, # where N is the number of polygons attached to it. tag.SetPerPointMode(True) # Get the global matrix of the polygon object and all its points in global space. mg: c4d.Matrix = op.GetMg() globalPoints: list[c4d.Vector] = [mg * p for p in op.GetAllPoints()] # Define a callable with which we can get the gradient color of a point over its index. GetGradientColor = lambda i : c4d.Vector4d( c4d.utils.RangeMap(globalPoints[i].y, GRADIENT_MIN, GRADIENT_MAX, 0, 1, True), 0, 0, 1) # Get the data pointer of the tag and start writing data. dataW: object = tag.GetDataAddressW() for i in range(count): c4d.VertexColorTag.SetPoint(dataW, None, None, i, GetGradientColor(i)) # Insert the tag into the selected object, make it the active tag, and push an update event. op.InsertTag(tag) tag.SetBit(c4d.BIT_ACTIVE) c4d.EventAdd() if __name__ == "__main__": main()
  • List All Nodes With No Filter?

    Cinema 4D SDK python 2023
    3
    0 Votes
    3 Posts
    645 Views
    B
    RE: Yes, GraphModelHelper.ListAllNodes requires at least one attribute to be set in the data dictionary. Gotcha. Thanks for the clarification. Anyway, the suggested alternative (i.e. write a separate iterator) still works as expected. Same as before.
  • 0 Votes
    26 Posts
    19k Views
    M
    Hello @ThomasB , without further questions or postings, we will consider this topic as solved by Friday 02/06/2023 and flag it accordingly. Thank you for your understanding, Maxime.
  • 0 Votes
    4 Posts
    2k Views
    ferdinandF
    Hello @Tng, Please excuse the very long waiting time, I simply overlooked the question in your answer. One question regarding Assets from the asset browser, in the case of a random machine that is rendering via command-line, is the Asset stored in the Project File or will it be downloaded if's missing ? Assets will be automatically downloaded when they are accessed and not already localized. The type maxon.Url hides all that complexity away with its different URL schemes. The Asset API manual provides an example for how to manually download an asset. But doing that is not possible in the Python API, here one must always rely on the automated asset access mechanisms. Assets can be stored in project files (via BaseDocument.GetSceneRepository) but are usually not, and instead reside in the user preferences directory bound user preferences repository. Once a remote asset has been accessed, a copy of its primary data, e.g., the texture, the model, etc., resides as a cache in the user preferences of that Cinema 4D installation. That cache will only be updated when the primary or secondary (i.e., metadata) of that asset change. Cheers, Ferdinand PS: I have closed this thread due to its age. Please feel free to reopen it when you have more questions.
  • Relative File Path Not Recognize by Plug-in?

    Cinema 4D SDK 2023 python
    5
    0 Votes
    5 Posts
    1k Views
    ferdinandF
    Hello @bentraje, Yes, the Python variant of GeGetPluginPath is not that useful as it just calls the C++ implementation which will then return the Python module path because the Python module is the C++ plugin which is calling GeGetPluginPath in that case. I will make the function description a bit more clear about that and also add a little example snippet for the module attribute __file__. And as what I would consider a fun fact: The __file__ attribute of modules is one of the many things where the language Python took inspiration from C/C++. In C++, __FILE__ is the macro which refers to the source file it is referenced in. I used this for example recently in the C++ Color Management examples to load an ICC file which is located next to a source file. But since users are usually not in the habit of compiling their C++ code themselves, or if they do, then want to move the resulting binary to a different place, __FILE__ is much less useful than __file__ as C++ there is a difference between the source and the executable. Cheers, Ferdinand
  • 0 Votes
    3 Posts
    553 Views
    mikeudinM
    Thank you @ferdinand ! Will chek it!
  • Change Bodypaint Active Channel Color

    Cinema 4D SDK python
    3
    1
    0 Votes
    3 Posts
    513 Views
    A
    Hi @m_adam. Thanks for the information! I needed this feature to generate UV texture, where polygon selection tags colorizes the texture with different colors. And since "Fill Layer, Fill Polygons and Outline Polygons" commands uses color from current "Channel Color" I needed option to change the color with a script. [image: 1675761996302-g89cotievo.png] c4d.CallCommand(170150) # Fill Layer c4d.CallCommand(170151) # Fill Polygons c4d.CallCommand(170152) # Outline Polygons But if this is not possible, one workaround that come to mind is to use "UV to Mesh" Scene Nodes Deformer/Capsule and render actual mesh with aligned camera. Cheers, Arttu