• Drag & Drop Undo

    Cinema 4D SDK r20 sdk c++
    5
    0 Votes
    5 Posts
    1k Views
    J
    Thanks for the response. I figured that something like this would be the case, will have to look into the options you mentioned. John Terenece
  • MessageDialog in NodeData plugin

    Cinema 4D SDK python r23 r20 2023
    2
    0 Votes
    2 Posts
    641 Views
    ferdinandF
    Hey @mikeudin, Thank you for reaching out to us. In short, there is no good answer to your question. There is no guarantee that anything will ever run on the main thread. You must always check yourself with c4d.threading.GeIsMainThread. Scene computations, e.g., ObjectData.GetContour is run in parallel off-main-thread and is therefore subject to access restriction to avoid access violations, i.e., crashes. There is no "hack" for this. The essence is that you cannot have both the benefits of sequentialism (can use shared resources) and parallelism (is fast). There are of course data structures which allow you to handle a singular resource from multiple threads, but doing this always entails lining up multiple users in a line, each waiting for users ahead in the line to be done, i.e., hidden sequentialism. In Python this might be hard to grasp because Python itself mostly ignores the concept of parallelism and we only experience here the side effects of the parallelism of the underlying C++ Cinema 4D API. There is also the problem that your request does not make too much sense for me on a practical level. Imagine having a plugin MySpline which opens an error dialog once its GetContour method strays from the right path. A user now edits one hundred instances of MySpline at once and triggers the error. Cinema 4D sometimes executes passes two or three times in a row to resolve dependency problems. This would then mean that you would open three hundred error dialogs for one user interaction (if that would be technically possible in the first place). In general, no node should open any form of dialogs on its own. Opening a dialog after a button press in the description of a node via NodeData.Message is okay. When you are hell-bent on doing this, you could do this: Add a field to your plugin, e.g., self._error: str = "". When you are in your GetContour and an error happens, instead of raising it, simply write it to _error. Implement any NodeData method which often runs on the main thread. NodeData.Message is a good candidate. On each execution of it, check if _error has content and if you are on the main thread. If so, display the message and then null _error. You will still need some kind of throttling so that the user is not spammed with the same error over and over again. I.e., you need an "only-new-errors" mechanism. It is up to you to implement that. An alternative approach could go via core messages. But that is also non-ideal because setting off a c4d.SpecialEventAdd will work from a non main thread but will cause the global core message lock to engage, which is of course a bad thing to happen and exactly the "no-hack" problem I described under (4). You could also try using c4d.StatusSetText and the other status functions. While not officially supported, they will work from non-main-thread environments. But there is no guarantee and we do not officially support this. Cheers, Ferdinand
  • 0 Votes
    5 Posts
    1k Views
    D
    @ferdinand Thanks for your comprehensive explanation. I really appreciate that. Cheers
  • Active Controls

    Cinema 4D SDK sdk r20 c++
    5
    1
    0 Votes
    5 Posts
    982 Views
    J
    Thanks for the response. That's what I figured would be the case.
  • FieldLayer Plugin Globals

    Cinema 4D SDK r20 sdk c++
    3
    0 Votes
    3 Posts
    694 Views
    J
    Thanks for the response, that seems to have solved the problem.
  • 0 Votes
    3 Posts
    1k 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
  • FieldList Enable Clamping

    Cinema 4D SDK r20 sdk c++
    5
    0 Votes
    5 Posts
    1k Views
    J
    Thanks, that was exactly what I was looking for. John Terenece
  • Quicktab SDK Example

    Cinema 4D SDK r20 2023 python sdk
    9
    1
    0 Votes
    9 Posts
    2k Views
    M
    While rethinking about it last night, it may not be that slow if on user interaction you just flush the main group and re-attach already existing dialog. So you need to modify your `def _DrawQuickTabGroup(self)`` method like so to only display visible dialog: def _DrawQuickTabGroup(self, onlyVisible=True): """ Creates and draws all the SubDialog for each tab, take care it does not hide these according to a selection state. Returns: True if success otherwise False. """ # Checks if the quicktab is defined if self._quickTab is None: return False activeIds, activeNames = self.GetActiveTabs() # Flush the content of the group that holds all ours SubDialogs self.LayoutFlushGroup(ID_MAINGROUP) #self.GroupBorderSpace(left=5, top=5, right=5, bottom=5) # Iterates over the number of tab to create and attach the correct SubDialog for tabId, (tabName, tabGui) in enumerate(self._tabList.items()): toDisplay = tabId in activeIds if not toDisplay: continue self.AddSubDialog(ID_QUICKTAB_BASE_GROUP + tabId, c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, 0, 0) self.AttachSubDialog(tabGui, ID_QUICKTAB_BASE_GROUP + tabId) self.LayoutChanged(ID_MAINGROUP) return True Then in the Command message instead of calling DisplayCorrectGroup you should call _DrawQuickTabGroup like so: def Command(self, id, msg): if id == ID_QUICKTAB_BAR and self._quickTab: self._DrawQuickTabGroup() return True Regarding your question and classic Tab, find an example in Remove a GeDialog Tab Group but as you can see this is also not possible to remove a tab without redrawing everything . Cheers, Maxime.
  • Removing IsolateObjects document

    Cinema 4D SDK r23 r25 c++ 2023 r20
    3
    0 Votes
    3 Posts
    696 Views
    ManuelM
    hi, yes, KillDocument is not necessary in that case. Cheers, Manuel
  • Treeview does not refresh

    Cinema 4D SDK r20 python
    5
    0 Votes
    5 Posts
    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
  • Cinema crashes renaming items in a TreeView

    Moved Bugs r20 s26 python windows macos
    11
    0 Votes
    11 Posts
    2k 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
  • How to Add Child Shaders to a Fusion Shader?

    Cinema 4D SDK python r20
    6
    1
    0 Votes
    6 Posts
    2k 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()
  • Compiling for R20... linker error in maxon::String

    Cinema 4D SDK r20 r25 c++
    5
    0 Votes
    5 Posts
    926 Views
    M
    Hello @fwilleke80 , without further questions or postings, we will consider this topic as solved by Thursday 01/06/2023 and flag it accordingly. Thank you for your understanding, Maxime.
  • update error?

    Cinema 4D SDK r20 python
    10
    0 Votes
    10 Posts
    2k Views
    JH23J
    I want to finish with this in case someone reads it. Years ago, I asked about the outdated methods when using these techniques. I tried to adjust the depth of the IK spline controls with the actual length of the spline itself. Today, I understand my mistake, as I was trying something that didn’t make logical sense. At the time, I thought it was the best option for what I was looking for. In short, this was never a problem, and the low response time is normal because the length depends on the depth of the controls. I thought there would be a solution, but choosing this path was not useful. In conclusion, what eventually satisfied my requirements was directly referencing the angles of the controls, meaning identifying how oriented each control is to another. I took this angle and used it as a factor to multiply by the depth. This model is much more logical and doesn’t have any flaws. At the time, I couldn’t think of a direct solution, but I didn’t want to leave this post like that. Thanks anyway, Ferdinand, for trying to help me. Cheers JH
  • DragDrop Model from UserArea into Viewport or Object Manager

    Moved Bugs c++ r20 s26 sdk
    2
    0 Votes
    2 Posts
    959 Views
    M
    Hi Kent, so far for the moment the viewport drop operation are more related to scene management rather than scene creation. By that I means except for an asset being loaded which create new elements (scene, object, material, etc...) other drag command are just here to act on the active object. So regarding drag operation for file, only DRAGTYPE_FILENAME_IMAGE is allowed and an object should be selected, then a texture tag will be applied to this object and a new material with the texture will be automatically assigned. DRAGTYPE_FILENAME_SCENE is not supported. For DRAGTYPE_ATOMARRAY it is only allowed for some particular categories, like layers to be applied on the active object or even materials for the same condition, so in any case the layer/material should already be part of the scene. So for the moment the only workaround would be to create your own temporary asset and pass this asset to be inserted into the document. For more information about the asset API I let you read Asset API - Handbook but this is S26.0+ only. Cheers, Maxime.
  • Detect CTRL + RightMouseButton in SceneHook

    Cinema 4D SDK c++ r20
    8
    0 Votes
    8 Posts
    2k Views
    ManuelM
    The workaround is to have your scenehook priority over 2k. Remember this priority is reversed, the lowest, the latest to be called so you can delete what have been done by other scenehook. (if you are using the draw function) The function will call scenehook beginning at LIMIT<Int32>::MAX to 2000 included. This bug was introduced more than 10 years ago after fixing another issue. The code is old and would need a session of refactoring. Cheers, Manuel
  • maxon::Url 206 partial content

    Cinema 4D SDK c++ r20 s26
    7
    0 Votes
    7 Posts
    1k Views
    ferdinandF
    Hey @kbar, sure, no pressure and that all sounds reasonable, I was just offering options. And to be clear here: I am not optimistic for this being user fixable. But you never know for sure until you have tried. Cheers, Ferdinand
  • Limit On the Number Of Takes

    Cinema 4D SDK c++ r20 sdk
    4
    0 Votes
    4 Posts
    870 Views
    J
    @m_magalhaes Thanks for the response. Might be able to use your idea as potential solution. John Terenece
  • GeDialog Update

    Cinema 4D SDK r20 c++ sdk
    4
    0 Votes
    4 Posts
    884 Views
    fwilleke80F
    I would recommend against changing anything in the scene from within GetVirtualObjects(). Rather do it in Execute(). Cheers, Frank
  • BaseTake AddTake

    Cinema 4D SDK c++ r20 sdk
    4
    1 Votes
    4 Posts
    1k Views
    J
    Thanks for the response Ferdinand, I thought that that would be the case. John Terenece