@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.
Posts made by ThomasB
-
RE: TempUVHandle always None! Why?
-
TempUVHandle always None! Why?
Hi,
I am not able to get the TempUVHandle from an active UVWTag in R21.
It returns always "None".
In the following script I created a simple plane in a TempDoc and took the cache and inserted it into the TempDoc. It already has a UVW-Tag, then I have set the object active and so the UVWTag....My Code:
import c4d def main(): temp = c4d.documents.BaseDocument() plane = c4d.BaseObject(c4d.Oplane) temp.InsertObject(plane) temp.ExecutePasses(bt=None, animation=False, expressions=False, caches=True, flags=c4d.BUILDFLAGS_NONE) plane_cache = plane.GetCache().GetClone() if plane_cache is None: raise Exception("no cache") temp.InsertObject(plane_cache) uvw_tag = plane_cache.GetTag(c4d.Tuvw) temp.SetActiveTag(uvw_tag) temp.SetActiveObject(plane_cache) handle = c4d.modules.bodypaint.GetActiveUVSet(temp, c4d.GETACTIVEUVSET_UVWS) print(handle) # Execute main() if __name__=='__main__': main()
-
RE: Dynamically adding parameters in tag plugin - description is not refreshing
@ferdinand
Thanks a lot Ferdinand for your time and effort. It is always admirable how carefully and thoroughly you answer many questions.
At first it was often difficult to understand and follow your code examples...now it is a little easier.
Thanks for that.I found out that the following method also does the job:
c4d.SendCoreMessage(c4d.COREMSG_CINEMA, c4d.BaseContainer(c4d.COREMSG_CINEMA_FORCE_AM_UPDATE), 0)
Sorry for the second question about why this
buttonDesc[c4d.DESC_FITH] = True buttonDesc[c4d.DESC_SCALEH] = True
in the GetDDescription method are not working. I thought this is a follow-up question.
I will open another topic for that. -
Dynamically adding parameters in tag plugin - description is not refreshing
Hi, in my object plugin it worked fine but in my tag plugin the description cannot be updated after clicking a button which in this example should add a new button.
so when I click the button it adds a new id to the member variable self.id_list, and then I iter through this list in my GetDDescription() method
It just shows the added Button if I click on the Object which holds the tag and select again the tag.
Do I have to send a message? I read the GitHubExample but it is a example with an ObjectPlugin.import c4d from c4d import bitmaps, gui, plugins # Just a test ID PLUGIN_ID = 1110101 PY_ADD_TRACK = 10000 #The Plugin Class class Audioworkstation(plugins.TagData): def __init__(self): self.id_list = [] def Init(self, node): return True def GetDDescription(self, op, description, flags): if not description.LoadDescription(op.GetType()): return False singleID = description.GetSingleDescID() # id_counter = 1 for desc_id in reversed(self.id_list): measure_object_hide = c4d.DescID(c4d.DescLevel(desc_id + 2, c4d.DTYPE_BUTTON, op.GetType())) if not singleID or measure_object_hide.IsPartOf(singleID)[0]: bc_measure_object_hide = c4d.GetCustomDataTypeDefault(c4d.DTYPE_BUTTON) bc_measure_object_hide[c4d.DESC_NAME] = "DELETE" bc_measure_object_hide[c4d.DESC_CUSTOMGUI] = c4d.CUSTOMGUI_BUTTON # id_counter += 1 if not description.SetParameter(measure_object_hide, bc_measure_object_hide, c4d.DescID(c4d.DescLevel( c4d.ID_TAGPROPERTIES))): return False return True, flags | c4d.DESCFLAGS_DESC_LOADED def Execute(self, tag, doc, op, bt, priority, flags): return c4d.EXECUTIONRESULT_OK def Message(self, node, type, data): if type == c4d.MSG_DESCRIPTION_COMMAND: if data["id"][0].id == PY_ADD_TRACK: last_id = None if self.id_list: last_id = self.id_list[-1] new_id = last_id + 100 self.id_list.append(new_id) else: new_id = 10100 self.id_list.append(new_id) node.Message(c4d.MSG_CHANGE) return True # main if __name__ == "__main__": bmp = bitmaps.BaseBitmap() dir, file = os.path.split(__file__) fn = os.path.join(dir, "res", "icon.tif") bmp.InitWith(fn) c4d.plugins.RegisterTagPlugin(id=PLUGIN_ID, str="C4D-Audioworkstation", info=c4d.TAG_EXPRESSION | c4d.TAG_VISIBLE, description="audioworkstation", g=Audioworkstation, icon=bmp)
edit by @ferdinand:
@ThomasB said:
I have also problems to scale the button so that it fits the attribute manager:
so this doesn't work in the GetDDescription Example above:
bc_measure_object_hide[c4d.DESC_SCALEH] = True bc_measure_object_hide[c4d.DESC_FITH] = True
-
RE: 2024.4.0 crashes when setting key-values
@ferdinand
this is really odd, because I have a Button in my plugin which simply creates keyframes for specific description parameters of the plugin, similar as it is in the PoseMorph Tag when you create keyframes for all sliders at once. And here it works without crashing:
Maybe this helps you.
The code of writing the keyframes is pretty the same, the only difference is that I set here keyframes for the description Id's instead of the user-datas...hmthis is just a snippet:
PY_STRENGTH_A_MANUAL = 10051 PY_STRENGTH_E_MANUAL = 10052 PY_STRENGTH_I_MANUAL = 10053 PY_STRENGTH_O_MANUAL = 10054 PY_STRENGTH_U_MANUAL = 10055 PY_STRENGTH_F_MANUAL = 10056 PY_STRENGTH_W_MANUAL = 10057 PY_STRENGTH_SH_MANUAL = 10058 PY_STRENGTH_OTHERS_MANUAL = 10059 PY_STRENGTH_CLOSED_MANUAL = 10060 id_list = [PY_STRENGTH_A_MANUAL, PY_STRENGTH_E_MANUAL, PY_STRENGTH_I_MANUAL, PY_STRENGTH_O_MANUAL, PY_STRENGTH_U_MANUAL, PY_STRENGTH_F_MANUAL, PY_STRENGTH_W_MANUAL, PY_STRENGTH_SH_MANUAL, PY_STRENGTH_OTHERS_MANUAL, PY_STRENGTH_CLOSED_MANUAL ] #========Plugin==================== def Message(self, node, type, data): if data["id"][0].id == PY_RECORD_MANUAL: time = node.GetObject().GetDocument().GetTime() node.GetDocument().AddUndo(c4d.UNDOTYPE_CHANGE, node) if c4d.threading.GeIsMainThread(): for ide in id_list: track = node.FindCTrack(ide) if not track: track = c4d.CTrack(node, ide) node.InsertTrackSorted(track) curve = track.GetCurve(c4d.CCURVE_CURVE, True) keydata = curve.AddKey(time) if keydata is None: raise RuntimeError("Could not add key frame.") key = keydata["key"] key.SetValue(curve, node[ide]) key[c4d.ID_CKEY_PRESET] = 2 # c4d.ID_CKEY_PRESET_AUTO_OVERSHOOTWEIGHTED c4d.EventAdd()
-
2024.4.0 crashes when setting key-values
Hello,
I'm just a bit stumped. In previous versions of C4D this approach, writing keys worked perfectly.
Normally the routine is executed by a plugin in the message method, but I was able to change the example into a script and that's where the error occurs.Here I have the script and the required scene with the object.
bake_test.zipThe script should simply write keys with values into the user data, usually the user datas are animated and they are a lot more, so in the plugin it has to filter the right ones
After detailed debugging, I'm sure the error happens in the third last line with key.SetValue(curve, value)import c4d doc: c4d.documents.BaseDocument # The currently active document. op: c4d.BaseObject | None # The primary selected opect in `doc`. Can be `None`. def bake(): strength_list = { "AA": 1, "EE": 1, "IY": 1, "OW": 1, "UW": 1, "F": 1, "W": 1, "SH": 1, "T": 1, "M": 1 } after_list = [] # ================================================= user_list = ["AA", "EE", "IY", "OW", "UW", "F", "W", "SH", "T", "M"] parameter_list = [] for ide, bc in op.GetUserDataContainer(): if bc[c4d.DESC_NAME] in user_list: parameter_list.append(ide) after_list.append(bc[c4d.DESC_NAME]) if not parameter_list: # if no userdatas added c4d.gui.MessageDialog("Missing User Datas!\n\nClick 'Add User-Data'") return True doc.AddUndo(c4d.UNDOTYPE_CHANGE, op) c4d.StatusSetSpin() # start = node[PY_BAKE_START] # end = node[PY_BAKE_END] for frame in range(0, 90): time = c4d.BaseTime(frame, doc.GetFps()) doc.SetTime(time) doc.ExecutePasses(None, True, True, True, c4d.BUILDFLAGS_NONE) # False True False for ide in parameter_list: track = op.FindCTrack(ide) if track is None: track = c4d.CTrack(op, ide) op.InsertTrackSorted(track) curve = track.GetCurve() keyData = curve.AddKey(time) if keyData is None: raise RuntimeError("Could not add key frame.") key = keyData["key"] key.SetValue(curve, op[ide]) key[c4d.ID_CKEY_PRESET] = 2 # c4d.ID_CKEY_PRESET_AUTO_OVERSHOOTWEIGHTED c4d.StatusClear() def main() -> None: """Called by Cinema 4D when the script is being executed. """ bake() if __name__ == '__main__': main()
Cheers
-
Snapping to a specific position of an object plugin's object chain
An Object plugin returns an object chain with certain objects.
But now I need a point at a very specific position of the object where other objects created in Cinema 4D can snap to it.I have or rather wanted to solve this by creating an internal polygon object that is placed in the object chain with a point, for example. I then made the point visually visible using the Draw method
ObjectData.Draw(self, op, drawpass, bd, bh)
However, the snapping does not work properly. If you're too close, nothing will snap. If the snapping radius is too small, nothing works.
Am I completely on the wrong track or should I approach the whole thing differently? Sometimes there's just a lack of new things, and I can't always find everything in the Github examples...sometimes I have to laugh at myself, how stupid I want to start a spedific approach....Regards
-
RE: How do I get the cache of a cloner in an ObjectData Plugin
@ferdinand
oh man thanks I forgot thisBaseDocument.ExecutePasses(bt=None, animation=False, expressions=False, caches=True, flags=c4d.BUILDFLAGS_NONE)
I tried that before but it seems I have set the caches parameter wrong.
Thank you very much.... -
How do I get the cache of a cloner in an ObjectData Plugin
Hi, sorry for this as always dumb question.
I was trying to get the Cache of a cloner object in the GetVirtualObjects(self, op, hh) method.
First I tried it in the python generator, there was already a cloner in the scene and in the python generator I returned the cache so to say, but this approach doesn´t work out in an object plugin.
Even if I create a temp_doc. The returned cache is always None.
But converting the cloner with a ModelingCommand is not the best way, if the cloner produces for instance a million clones.This method works in a python generator when the clone is already in the scene
cloner = op.GetDown() return cloner.GetCache().GetClone()
But creating a cloner and returning its cache doesn`t work.
cloner = c4d.BaseObject(1018544) c4d.BaseObject(c4d.Ocube).InsertUnder(cloner) return cloner.GetCache().GetClone()
Is there a way to get the cache in a plugin?
Sweep, Extrude, other Generators, Deformers and parametric objects work perfectly. -
RE: Boole Object causes version 2024 to freeze
@ferdinand
Hello Ferdinand,
Thank you very much first of all.
yes, you're right, I worked extremely sloppily with the SMC method, of course I'll take the threading into account and also work with a Temp Document.Regarding the problem itself, I can only say that reinstalling CINEMA 4D solved our problem.
Cheers
-
Boole Object causes version 2024 to freeze
Hi,
for demonstration purposes, I have an extremely stripped down version (1200 LOC) of my plugin (6000 LOC) here.
Unfortunately it was not possible to insert the whole Pyp file here because the post can only be a maximum of 32767 characters long. That's why I only have sent the classes and functions that are not so important are without code.- Condition: the window bars must be activated. Error with Boole happens in the method
def bar_cutter(op, obj, bars, fixed=False)
Description:
Of course, it is not technically perfect and in this version it is more of a prototype. I was able to narrow down the error to the Bars_Cutter() function. That's why I only included the bar_cutter method.
- In this function I read specific points from the created frame and create a spline, which I throw into an Extrude and then convert to a polygon object. this extrude is used to cut the window bars.
- I then create a Boole object and throw the previously created bars together with the extrude into the Boole object.
Normally I also create a polygon object from the Boole object with SendModelingCommand() but to prove that the error comes from the Boole, I insert the Boole object directly under the window frames.
Problem:
The problem now is this. If you reduce the arch height of this arched window, the polygons will now intersect. The following usually happens (R23-2023). The bars then simply disappear. And the glass is no longer displayed correctly either. That's actually OK. The user immediately knows that something is intersected. (Watch Video)
And in version 23-2023.2 this works, as can be seen in the video.
But in version 2024 when the polygons intersect, Cinema 4d freezes.I have a short video to watch here.
-
RE: Object Plugin - Generator Objects - Hiding the child objects in Editor View
@m_adam
Thank you very much Maxime.
But there is one more thing I would like to know.
Why don't the highlighted links work? I am always referred to this site. -
RE: Python: Detect Plugins
@m_adam
Sorry, little question, what does the python extenstion "pype" mean? -
RE: Object Plugin - Generator Objects - Hiding the child objects in Editor View
@CJtheTiger
thanks
But that doesn't seem to work because if, for example, I create an object plug-in that returns a cube in the GetVirtualObjects() method and I assign 2 objects to this plug-in in the Object Manager, then I still see the child objects in the editor window.Do I have to set a parameter or a flag somewhere to specify the ObjectPlugin somehow?
-
RE: OpenUSD (pxr) library in c4d python
@llealloo
That wasn't a one-way ticket recommendation, but just to test whether the problem still exists...I can't even get the usd library installed. pip shows me errors even via venv in pycharm as well as with their .whl files.
Back to your proplem:
- Maybe it doesn't work properly because the USD module needs some dependencies that are not installed or some modules are not supported in C4D python...to my knowledge not all modules of the standard library are supported in c4d python
-
Object Plugin - Generator Objects - Hiding the child objects in Editor View
Hi,
Happy New YearI have an internal development question.
How does this work, for example with Generators such as the Boole Object or Spline-Mask, when two objects are under the Bool-Object as childs, but these are no longer visible in their original form in the Editor View? But only the newly created object. They have to be hidden somehow but they are still visible in the Object Manager.
- How does this work exactly?
- Does this happen when registering the plugin with the method and specifying the info argument and type
plugins.RegisterObjectPlugin(info=type))
- Or do they have to be saved in a variable and deleted somehow or is there a Function to make them invisible?
Just to get the idea?
-
RE: OpenUSD (pxr) library in c4d python
@llealloo
Your link is not working, with the folder example in your first post.
Have you tried to place it into a separate folder in your res-folder or directly into your plugin folder and write the path into to the sys-path?
That's just a few lines of code:Folder structure:
- plugin folder.
-
- res folder
-
- your module
-
- plugin.pyp
import os import sys # if the module is placed directly into the plugin folder - add the folder to the python search path folder = os.path.dirname(__file__) # your plugin folder if folder not in sys.path: sys.path.insert(0, folder) import yourmodule
But I would paste the module into the res-folder
Folder structure:
- plugin folder.
-
- res folder
-
-
- your module
-
-
- plugin.pyp
import os import sys # add the res folder to the python search path folder = os.path.join(os.path.dirname(__file__), "res") # res folder if folder not in sys.path: sys.path.insert(0, folder) import yourmodule
-
RE: How to create python plugin in 2024?
Yes, download the SDK and study the examples.
I wrote my own software that allows me to simply select the type of plugin I want to create, enter the plugin ID and the plugin name. The program then creates the folder structure, all files with the correct content and the correct name automatically...that was the first thing I did because it is always extremely tedious.
This then takes 10 seconds and I have a finished blueprint. Then I can start programming straight away.
I usually make the Gui first using UserData to roughly create the design and then I write it down in the resfile in no time at all. It's relatively quick and even fun and you gradually grow into it, it emerges little by little.....Basically it wouldn't be a problem to write a script that writes the UserData interface into a Res, header and string file, I already have an idea for that... That would actually be easy to do.
I'll get to it when I'm done with my update... and then maybe make it available to the community... However, a similar one is already there, but I can't remember where.Greetings
Tom -
RE: How to access the BaseContainer of an Command-Dialog
This is a command, and you can c4d.CallCommand it, but that is all the control you have.
thank you Ferdiand,
-
RE: How to access the BaseContainer of an Command-Dialog
@ferdinand
Thanks Ferdinand, but I meant the command bake objects in the timeline where you can bake the animations. For the upcoming dialog I wanted to automate the process so I need to access the dialog parameters to set it, as the user needs to set the parameters and click the button and then delete some keys, I wanted to automate this with just one click.But thank you, I will have a look at the py-texture_baker_r18.pyp.