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. HerrMay
    3. Topics
    H
    • Profile
    • Following 0
    • Followers 0
    • Topics 20
    • Posts 62
    • Best 7
    • Controversial 0
    • Groups 0

    Topics created by HerrMay

    • H

      Discrepancy with point positions of Circle Spline Primitive

      Cinema 4D SDK
      • windows s26 python • • HerrMay
      3
      0
      Votes
      3
      Posts
      660
      Views

      H

      Hi @ferdinand,

      thanks for taking the time to clarify that 🙂

      Okay, I see. So one can view this "behavoiur" as intended since it is the result of the math behind how the circle spline is calculated?

      Still I wonder why the circle spline primitive with 1 intermediate point, i.e. with four control points doesn't appear like the n-side spline with 8 sides? Wouldn't it be "cleaner" that way?

      Regading the true values - I am well aware that the repr of c4d.Vector rounds in the GUI. It was only that those values were quite off compared to the values of the points of the n-side spline. That's why my initial question arose. 😉

      Interesting and good to know that rotating points via sine and cosine is slow and no good option. Thank you for that insight. May I ask why that is? I mean why is c4d.utils.MatrixRotZ better? What does that function do differently in terms of performance? In the end it has to do the math as well, does it not?

      Sorry for constantly asking all this stupid questions. It is only that I want to understand these things thoroughly. 😄

      Thanks for your time,
      Sebastian

    • H

      How to evenly distribute objects of different 'width'

      Cinema 4D SDK
      • python s26 windows • • HerrMay
      6
      0
      Votes
      6
      Posts
      2.0k
      Views

      i_mazlovI

      Hi @gsmetzer,

      please have a look at the related thread (How to get the bounding box for the whole scene) where your issue was explained in details by @ferdinand

      @ferdinand said in How to get the bounding box for the whole scene:

      a BaseObject will also not include its descendants in its bounding box computation

      So, one must carry out such computations oneself

      Cheers,
      Ilia

    • H

      Why do I have to hit Undo twice after performing SendModelingCommand 'Weld'?

      Cinema 4D SDK
      • windows s26 python • • HerrMay
      3
      0
      Votes
      3
      Posts
      581
      Views

      H

      Hi @ferdinand,

      ah okay I see. Some part of me already suspected it could be a bug. Thanks for taking the time to look into it. 🙂

      Regarding the scope of question. You are absolutely right. And while I understand that it can make answering branching questions hard, it is sometimes not that easy to split things up. But all good, no offense taken. 🙂

      One last thing, I know you guys are not here to develop solutions or come up with algorithms. Still, I was wondering if a possible solution could be to move the selected points to a custom vector position and afterwards simply send an "Optimize" modeling command?

      Cheers,
      Sebastian

    • H

      Why doesn't c4d.Vector.GetAngle throw an error for the null vector?

      Cinema 4D SDK
      • python s26 • • HerrMay
      2
      0
      Votes
      2
      Posts
      421
      Views

      ferdinandF

      Hello Herr May,

      Thank you for reaching out to us. I am not quite sure why you think it should do that.

      The angle between two vectors u and v is defined as:

      theta(u, v) = arccosine(~u * ~v)

      I.e., the arccosine of the dot product of the two normalized vectors. This is due to the so called circle functions, specifically this identity:

      26ea0c5e-9de3-4885-bc15-34b4ee3342da-image.png

      Under the hood, GetAngle does exactly what I declared above (just in a bit more efficient manner, as calculating the normalized vector is much more expensive than this little trick):

      123bbf8a-568b-49a5-9ff3-2bac41f61339-image.png

      As you can see, the correct solution to the arccosine of the dot product of the null vector with itself is 0.5 π, i.e., the value you got :

      ebfd4607-e872-42ef-898c-d3a2de4d8dd8-image.png

      You could now argue if that is a sensible result for a method that is called 'GetAngle' and if it should throw an error on getting an input vector or being called on a vector with the length zero. But you have also to keep in mind that the C++ backend is used by people who will know the identity pi_half = arccosine(~(0, 0, 0) * ~(0, 0, 0)) and might want to make use of it.

      Cheers,
      Ferdinand

    • H

      Dynamically changing custom icon of TagData Plugin

      Cinema 4D SDK
      • python s26 windows • • HerrMay
      6
      1
      Votes
      6
      Posts
      1.0k
      Views

      ferdinandF

      Hello @HerrMay,

      Thank you for the updated information. I had a look at your problem, and I could reproduce it, but it is primarily a problem of your code as suspected.

      I document below how I analyzed this problem not as a passive aggressive expression of "look how easy that is!". But to give an insight on how to approach such debugging task. The core rule is here to question one's own assumptions and assure that things are indeed how we think they are.

      Debugging

      So, when one follows your steps, one indeed ends up with something like this:

      8fdef1aa-1a5e-43d8-8cdb-42b480fd4f0d-image.png

      Your assumption here was that the icon handling is bugged on our side. For that to be true, the tag on Null.2 would have to be IDC_ACTIVE_ON but with the icon handling failing and Cinemas 4D rendering it as disabled.

      So, I checked the value with this code:

      # Set custom icon for node. if id == c4d.MSG_GETCUSTOMICON: host: c4d.BaseObject = tag.GetObject() isFirst: bool = host.GetUp() == None and host.GetPred() == None if isFirst: print(f"TOP: {host.GetName() = }, {tag[IDC_ACTIVE] = }") else: print(f"OTHER: {host.GetName() = }, {tag[IDC_ACTIVE] = }") icon = self.PLUGIN_ICON_INACTIVE if tag[IDC_ACTIVE] == IDC_ACTIVE_OFF else self.PLUGIN_ICON_ACTIVE data["bmp"] = icon data["w"] = icon.GetBw() data["h"] = icon.GetBh() data["filled"] = True

      Which will print this when you add the tags:

      baebed6a-fdc0-4d53-8214-1d6b2011cad8-image.png

      So, the topmost tag is indeed inactive and the icon rendering is correct. The question is now: 'Why is that tag inactive because we initialize all tags as node[IDC_ACTIVE] = IDC_ACTIVE_ON ?' The likely culprit is just a few lines above, as we toggle there the active state of our tag.

      # Handle double click on tag. if id == c4d.MSG_EDIT: if tag[IDC_ACTIVE] == IDC_ACTIVE_OFF: tag[IDC_ACTIVE] = IDC_ACTIVE_ON else: tag[IDC_ACTIVE] = IDC_ACTIVE_OFF

      And indeed, when we comment out these lines, we end up with this when creating multiple new tags.

      ebddd8e2-ff78-47f3-a4ca-40cbd26ac047-image.png

      Moreover, when we revert our change of commenting out that code and test our assumption 'only happens for multi-object selections', we can see that this does not hold true:

      e5f2a8dd-2ebd-4555-8188-d769b84895e3-image.png

      We can now check our own comment:

      # Handle double click on tag. if id == c4d.MSG_EDIT: ...

      and check MSG_EDIT:

      de39ee11-81d9-4e68-a2a6-a4c4dd182b84-image.png

      The documentation says, "for example". So, the event does not capture a double click, but double clicking a BaseObject to edit its name is one example of an edit event. Adding a tag to an object apparently also emits MSG_EDIT to the tag, and when you have a multi-selection, MSG_EDIT is only emitted to the first element in the selection.

      Conclusion

      That behavior of MSG_EDIT in regard to tags and multi-selections is of course quite odd, but I would not consider it to be a bug, as an edit event is not really defined for tags in the first place. And while I understand what you want to do here, I would also say that what you do in MSG_EDIT is a violation of the UX principles of Cinema 4D. Double clicking a tag should not edit a random parameter in it. We strive for Cinema 4D having a seamless UX-experience for users including plugins. So, we rather not support it when plugin authors are trying to break these UX rules.

      But I will nevertheless talk with my colleagues about the subject and if we want to consider this behavior of MSG_EDIT to be a bug.

      Cheers,
      Ferdinand

    • H

      Nesting Pivot object causes parent to shoot up into space

      Cinema 4D SDK
      • • • HerrMay
      6
      0
      Votes
      6
      Posts
      775
      Views

      ferdinandF

      Hey @HerrMay,

      Great to hear that you solved your problem.

      Cheers,
      Ferdinand

    • H

      How to add custom menu to take manager

      Cinema 4D SDK
      • • • HerrMay
      3
      0
      Votes
      3
      Posts
      540
      Views

      H

      Hi @i_mazlov,

      thank you for your reply. 🙂

      Yes, I thought as much. Too bad the take manager menu is not publicy exposed.

      And while I understand that Maxon as well as the community are not big fans of every plugin messing around with menu insertions, it still is a pitty.

      One can e.g. insert plugins into the menu of the material manager as done so by "CV-Swim".

      IMHO it should pose no problem when done carefully with UX in mind while doing so. Especially when one "only" appends entries to a menu.

      Nethertheless thank you for confirmation.

      Cheers,
      Sebastian

    • H

      How can I add an offset to the global matrix of an object that is rotated?

      Cinema 4D SDK
      • python sdk s26 • • HerrMay
      4
      0
      Votes
      4
      Posts
      665
      Views

      ferdinandF

      Hello @HerrMay,

      Is the multiplication of a matrix with a vector (mg.off = mg * p) essentially the same what mg * c4d.utils.MatrixMove(vec) does?

      No, mg * p multiplies a matrix by a vector which will yield the transformed vector p'. mg * c4d.utils.MatrixMove(vec) on the other hand multiplies two matrices, yielding the combined transform of them, a new matrix.

      What would be equivalent to mg * p is mg * c4d.utils.MatrixMove(p) * c4d.Vetcor(0, 0, 0). Please note that the whole subject is also out of scope of support as declared in the forum guidelines. I understand that the subject is a common barrier for the more on the artist-sided leaning users of ours, and I help where I can, but we cannot teach you vector math, linear algebra, or however you want to label this subject.

      Find below a short code example.

      Cheers,
      Ferdinand

      Output:

      M = Matrix(v1: (1, 0, 0); v2: (0, 1, 0); v3: (0, 0, 1); off: (0, 100, 0)) p = Vector(100, 0, 0) M * p = Vector(100, 100, 0) M * c4d.utils.MatrixMove(c4d.Vector(100, 0, 0)) = Matrix(v1: (1, 0, 0); v2: (0, 1, 0); v3: (0, 0, 1); off: (100, 100, 0)) M * c4d.Vector(100, 0, 0) = Vector(100, 100, 0) N * c4d.Vector( 0, 0, 0) = Vector(100, 100, 0) M * c4d.utils.MatrixMove(p) * c4d.Vector(0, 0, 0) = Vector(100, 100, 0)

      Code:

      import c4d # Let us assume #M to be the global matrix/transform of some object #op. View it as a tool to # transform a point in global space into the local coordinate system of #op. M: c4d.Matrix = c4d.Matrix(off=c4d.Vector(0, 100, 0)) # The matrix #M now has this form: # # | v1 1 0 0 | # The "x-axis" of the coordinate system defined by #M. # | v2 0 1 0 | # The "y-axis" of the coordinate system defined by #M. # | v3 0 0 1 | # The "z-axis" of the coordinate system defined by #M. # ---------------------- # | off 0 100 0 | # The origin of the coordinate system defined by #M. # # I.e., #M has the standard orientation and scale and only translates all things by 100 units # on the y-axis. So, the object #op would have the Euler angles (0°, 0°, 0°), the scale (1, 1, 1) # and the position (0, 100, 0) in world coordinates. # Define a vector #p to transform and print both #M and #p. p: c4d.Vector = c4d.Vector(100, 0, 0) print(f"{M = }") print(f"{p = }") # Transforming a point #p by a matrix #M will yield a point #q that is in the same relation to #M # as #p is to the global frame. q: c4d.Vector = M * p # #q will be the vector (100, 100, 0) because , (100, 100, 0) and #M are the same relation as #p # and the identity matrix are, a.k.a., the world frame. In a less technical way, (0, 100, 0) is the # origin of the coordinate system defined by #M. And to express #p in a manner as if #M would be # its coordinate system, we have to add (0, 100, 0), because that is the new origin. For orientation # and scale it works more or less the same, I would recommend having a look at the Matrix manual or # Wikipedia article on the subject. print (f"{M * p = }") # We can construct new transforms in many ways (again, Matrix Manual :)), one of them is by # combining multiple transforms via matrix multiplication. # We "add" the translation transform (100, 0, 0) to #M. Note that matrix multiplication is not # commutative, i.e., "M * N = N * M" does not always hold true. In this case it would because only # translations are involved. N: c4d.Matrix = M * c4d.utils.MatrixMove(c4d.Vector(100, 0, 0)) print(f"{M * c4d.utils.MatrixMove(c4d.Vector(100, 0, 0)) = }") # To get the same point as #q when multiplying a point #r with #N, we must pick the null-vector # because the origin of #N is already at where M * (100, 0, 0) is. print (f"{M * c4d.Vector(100, 0, 0) = }") print (f"{N * c4d.Vector( 0, 0, 0) = }") # We can also do it in one operation: print (f"{M * c4d.utils.MatrixMove(p) * c4d.Vector(0, 0, 0) = }")
    • H

      Is it possible to intercept rendering to modify the document that is about to render?

      Cinema 4D SDK
      • python s26 windows sdk • • HerrMay
      4
      0
      Votes
      4
      Posts
      582
      Views

      M

      Hello @HerrMay,

      without further questions or postings, we will consider this topic as solved by Monday 05/06/2023 and flag it accordingly.

      Thank you for your understanding,
      Maxime.

    • H

      Un-commenting Message function of python tag results in RuntimeError

      Cinema 4D SDK
      • s26 python windows • • HerrMay
      3
      0
      Votes
      3
      Posts
      373
      Views

      H

      Hi @m_adam,

      alrighty, good to know that this will be looked into and eventually get fixed.

      Yes, I remember I returned True in the past. In the python tag as well as in the TagData equivalent. As returning super didn't work.

      Thanks for the information anyway. 🙂

      Cheers,
      Sebastian

    • H

      How to find out if document is rendering from a python tag

      Cinema 4D SDK
      • s26 python sdk windows • • HerrMay
      3
      0
      Votes
      3
      Posts
      585
      Views

      H

      Hi @m_adam,

      thanks for the explanation and your example code. That will absolutely suffice my needs. 🤗

      Good to know though that additional information may be available in the future.

      Cheers,
      Sebastian

    • H

      How to be sure if an object is a generator/modifier?

      Cinema 4D SDK
      • s26 r20 python sdk • • HerrMay
      3
      0
      Votes
      3
      Posts
      979
      Views

      H

      Hello @ferdinand,

      alright I see. I already thought that you would teach me once again that the naive thought I put up here would'nt hold up to the real world. 😄 😄 😄

      Thanks for the explanation and the example you provided. I guess that will do just fine. As always much appreciated! 🙂

      Cheers,
      Sebastian

    • H

      How to draw on spline points from spline returned by Object Data

      Cinema 4D SDK
      • • • HerrMay
      4
      0
      Votes
      4
      Posts
      633
      Views

      ferdinandF

      Hello @HerrMay,

      Funny enough DrawPoints seems to internally use the "same points" to draw, one gets to see when one edits the points of a polygon object. 😄 In S26 the points are round (thats probably why I was thinking of circles) while in R20 they are squares. No question here, just an observation.

      As you can see, in the script I retrieve the cache of the object we are going to draw.

      # Get the cache of the object representing the plugin in the object manager, i.e., more or # less what we returned in GetContour, Cinema 4D has however exhausted the cache for us, and # the cache is not a SplineObject but a LineObject (i.e, the cache of a SplineObject). cache: c4d.LineObject = op.GetDeformCache() or op.GetCache() if not isinstance(cache, c4d.LineObject): return c4d.DRAWRESULT_O

      This not only enables us to deal with splines affected by a deformer correctly, but also and more importantly with spline generators as for example the Circle spline generator.

      Such generators do not have any control points one could retrieve, their cache will always contain LineObject instances and not SplineObject instances (when they have been implemented correctly). This is also what I was referring to in my comment, because OffsetYSpline returns a SplineObject as its cache in GetContour, but Cinema 4D will 'exhaust' that cache for us by returning the cache of the cache, the LineObject.

      A LineObject represents a SplineObject over its current interpolation settings.

      What is actually weird though is that the color gradient you used here to color the points doesn't work in R20. The points are simply drawn black there. Possibly a Python 2/3 issue caused by integer/float division differences? 🤷

      Yes, this is Python 3 code. In Python 2 integers divide by default as integers. Simply wrap one of the numbers into a float, e.g., f: float = float(i)/float(count).

      Allow one follow up question. How can I draw only the control points of the spline? In your example you use a circle primitive which has - when made editable - exactly four points making up the shape via tangents. Where as the drawn points using the intermediate points of the circle as well.

      You can use BaseObject.GetRealSpline to get the underlying editable spline object for a spline. So, when you would replace the section quoted above with this:

      cache: c4d.SplineObject = op.GetRealSpline() if not isinstance(cache, c4d.SplineObject): return c4d.DRAWRESULT_OK

      You would now draw the control points of the SplineObject representing the spline generator rather than the vertices of its underlying LineObject. The problem in this case is that the plugin you have chosen is calling 'Current State to Object' (CSTO) on the input object which it is cloning and returning offset-ed (see line 130 in your code listing). CSTO is of course just replacing an object with its cache state. So, when you put a circle spline below the offset spline, it will still be drawn as in the LineObject cache version because the cache and the BaseObject.GetRealSpline representation are in this case identical.

      Cheers,
      Ferdinand

    • H

      How to "permanently" store data?

      Cinema 4D SDK
      • • • HerrMay
      4
      0
      Votes
      4
      Posts
      548
      Views

      ferdinandF

      Hello @herrmay,

      Yes, it can be a bit cumbersome to write a whole abstraction layer, but most of the time it is avoidable to do that in the first place. In your case it should be pretty simple.

      Iterate over all layers you want to save to disk. Get the MAXON_CREATOR_ID UUID of each layer and its data container. Write the UUID and the data container to disk using JSON or HyperFile, I would recommend the latter as it will be less work. You only must convert the UUID bytes to a string, put the string into the file, then the data container and you are done. If you want to, you could also store all layer data in one file per document, or just have one giant file for all documents. Later load these hyper file fragments back and do what you want with the data. When you need the original node, traverse the layers in the active document for a node with the stored UUID. You could also make things fancier and search in all open documents or even store the document path in your serialized data and load that document.

      Saving things in the document container is a possibility too, you should make sure though to use a plugin ID for that.

      Cheers,
      Ferdinand

    • H

      Treeview does not refresh

      Cinema 4D SDK
      • r20 python • • HerrMay
      5
      0
      Votes
      5
      Posts
      1.1k
      Views

      H

      Hello @ferdinand,

      sorry for coming back this late. Work kept me quite busy. 🙄 😄

      @ferdinand so, I had a play with your code example. It works like a charm and also seems to have a lot of potential for all kinds of update/dirty checking issues.

      Thanks again @ferdinand for your help, the effort you always put into answering our questions and the eloborate examples you come up with!

      Cheers,
      Sebastian

    • H

      Cinema crashes renaming items in a TreeView

      Bugs
      • r20 s26 python windows macos • • HerrMay
      11
      0
      Votes
      11
      Posts
      2.3k
      Views

      ferdinandF

      Hello @HerrMay,

      Thank you for your reply, and please excuse that I have overlooked it.

      Maybe a little bit off topic but since we're already talking Treeviews. There seems to be a bug too when it comes to multi-selecting objects in the Treeview. At least when using c4ds native BaseList2D objects.

      Without wanting to be rude, that statement is too vague to make a bug report out of it. The thread is quite old and therefore not the most reliable source of information, geared towards C++, and from what I see, not even conclusive in the assessment if there is a bug or not. I see there a user claiming that there is a bug, and another user, probably a Maxon employee, being skeptical about it.

      We are happy to file bugs, but we need a reproducible case. And just as a heads up, us filing a bug does not necessarily mean that we will fix soon or at all. I understand that this can be disheartening, but we must prioritize where our bug fixing efforts are most needed, which can lead to minor bugs being pushed for a long time.

      I have closed this thread due to its age, please feel free to open a new thread when you want to discuss that other bug. The thread is still be tracked due to its to_fix tag.

      Cheers,
      Ferdinand

    • H

      How to Add Child Shaders to a Fusion Shader?

      Cinema 4D SDK
      • python r20 • • HerrMay
      6
      0
      Votes
      6
      Posts
      1.6k
      Views

      H

      Hello @ferdinand,

      when trying out your function to traverse shaders I noticed that for two materials in the scene it yields for the first material all the shaders of itself but also all the shaders of the second material. For second material it works like expected and yields only the shaders of itself.

      After fiddling around a bit with some other code of you from this post I think I ended up with a function that is yielding all the shaders from a material iteratively.

      Find the code below. Maybe this will help others. 🙂

      Cheers,
      Sebastian

      def iter_shaders(node): """Credit belongs to Ferdinand from the Plugincafe. I added only the part with the material and First Shader checking. Yields all descendants of ``node`` in a truly iterative fashion. The passed node itself is yielded as the first node and the node graph is being traversed in depth first fashion. This will not fail even on the most complex scenes due to truly hierarchical iteration. The lookup table to do this, is here solved with a dictionary which yields favorable look-up times in especially larger scenes but results in a more convoluted code. The look-up could also be solved with a list and then searching in the form ``if node in lookupTable`` in it, resulting in cleaner code but worse runtime metrics due to the difference in lookup times between list and dict collections. """ if not node: return # The lookup dictionary and a terminal node which is required due to the # fact that this is truly iterative, and we otherwise would leak into the # ancestors and siblings of the input node. The terminal node could be # set to a different node, for example ``node.GetUp()`` to also include # siblings of the passed in node. visisted = {} terminator = node while node: if isinstance(node, c4d.Material) and not node.GetFirstShader(): break if isinstance(node, c4d.Material) and node.GetFirstShader(): node = node.GetFirstShader() # C4DAtom is not natively hashable, i.e., cannot be stored as a key # in a dict, so we have to hash them by their unique id. node_uuid = node.FindUniqueID(c4d.MAXON_CREATOR_ID) if not node_uuid: raise RuntimeError("Could not retrieve UUID for {}.".format(node)) # Yield the node when it has not been encountered before. if not visisted.get(bytes(node_uuid)): yield node visisted[bytes(node_uuid)] = True # Attempt to get the first child of the node and hash it. child = node.GetDown() if child: child_uuid = child.FindUniqueID(c4d.MAXON_CREATOR_ID) if not child_uuid: raise RuntimeError("Could not retrieve UUID for {}.".format(child)) # Walk the graph in a depth first fashion. if child and not visisted.get(bytes(child_uuid)): node = child elif node == terminator: break elif node.GetNext(): node = node.GetNext() else: node = node.GetUp()
    • H

      Unique Material per Object Plugin instance?

      Cinema 4D SDK
      • r20 python macos • • HerrMay
      4
      0
      Votes
      4
      Posts
      858
      Views

      H

      Hi Guys,

      as I'm pretty sure I found a way to achieve what I'm after I thought I update this thread. Maybe this will help others as well. 😉

      After taking some time to make NodeData.CopyTo() work, I ended up not getting it to work at all.

      So I thought about how I could achieve what I'm after a different way. Long story short, I ended up implementing a MessageData plugin as some kind of watchdog for a document. Since its CoreMessage runs on the main thread I can happily insert and delete materials as much as I wish to. (At least I'm hoping so 😬 😁)

      Tl; dr
      The idea behind this goes as follows. I have a timer running and in addition to that I listen for c4d.EVMSG_CHANGE and do some checking to see if the scene needs to update. In my case it's comparing the amount of a specific object against the amount of "specific" materials. If there's a difference I use that difference to delete or insert materials until there's no difference. Once there's no difference I can assign the materials to the objects and let each object control its own material.

      To distinguish between materials responsible for my plugin and the ones that aren't I make sure to put a unique plugin id inside the base container of the material I can then check for.

      Here's a code snippet of that MessageData:

      class Watchdog(c4d.plugins.MessageData): PLUGIN_ID = "Use your own unique one" PLUGIN_NAME = "A MessageData plugin." PLUGIN_INFO = 0 def __init__(self): self._time = 1000 def GetTimer(self): return self._time def SetTimer(self, time): self._time = time @property def should_execute(self): is_mainthread = c4d.threading.GeIsMainThread() check_running = ( bool(c4d.CheckIsRunning(c4d.CHECKISRUNNING_EDITORRENDERING)), bool(c4d.CheckIsRunning(c4d.CHECKISRUNNING_EXTERNALRENDERING)), bool(c4d.CheckIsRunning(c4d.CHECKISRUNNING_INTERACTIVERENDERING)), bool(c4d.CheckIsRunning(c4d.CHECKISRUNNING_ANIMATIONRUNNING)), bool(c4d.CheckIsRunning(c4d.CHECKISRUNNING_VIEWDRAWING)) ) is_running = any(item is True for item in check_running) return is_mainthread and not is_running def CoreMessage(self, mid, mdata): if not self.should_execute: return False doc = c4d.documents.GetActiveDocument() # SceneHandler is a custom class I delegate the whole creation and comparing stuff to. objs, mats = ..., ... scene = SceneHandler(objs, mats) # Check for a change and start the timer again. But only if the scene should update. Otherwise the timer would run all the time. if mid == c4d.EVMSG_CHANGE: if scene.should_update: self.SetTimer(1000) # If we get a timer event we update the scene as long as it shouldn't update anymore. We can then stop the timer. if mid == c4d.MSG_TIMER: if not scene.should_update: self.SetTimer(0) scene.update(doc) return True

      Maybe this will help others. Since I found a solution for my problem this thread can be marked solved.

      Cheers,
      Sebastian

    • H

      Blank appearing dropdown cycle

      Cinema 4D SDK
      • python macos • • HerrMay
      5
      0
      Votes
      5
      Posts
      873
      Views

      H

      @m_adam alrighty got it working. 😃
      Thanks again. You can close this thread if you like.

      Cheers,
      Sebastian

    • H

      Dialog Plugin with Progress Bar or SetStatusBar

      Cinema 4D SDK
      • python • • HerrMay
      12
      0
      Votes
      12
      Posts
      1.8k
      Views

      ferdinandF

      Hello @HerrMay,

      thank you for your reply. Please note that we prefer users to flag topics as solved, as doing it ourselves always comes with the danger of erroneously flagging a posting as solved. Please refer to our Forum Guidelines - Forum Feature: Ask as Question in case you do not know how to do this.

      Cheers,
      Ferdinand