Understood and works like a charm!
Many thanks guys
Understood and works like a charm!
Many thanks guys
Hi @Cairyn and @ferdinand
Many thanks for your input.
It definitely works if you enable the Camera Dependent flag as Cairyn mentioned.
I'm just trying to figure out how to enable it.
tag[c4d.EXPRESSION_PRIORITY].SetPriorityValue(c4d.PRIORITYVALUE_CAMERADEPENDENT, True) perhaps?
This is not working, so not sure if I should do it via SetParameter.
@ferdinand Cheers for your screenshare and code. Unfortunately, it still happens with your code. If you look through the camera and pan around does the target stays fixed for you?
P.S. What do you use for your screen share gifs, please?
Thank you both!
@fwilleke80 Hi Frank,
Yes, apologies for the low-quality video. Think Google Drive may be compressing it somehow.
Not sure if you noticed, but on the Camera named Script_Target_Tag, I can pan in the viewport and the aim moves with it. Once I click anywhere it jumps back to the targeted Null/Cube.
While when added the target tag manually, it's always aimed at the targeted Null/Cube.
Hope this makes sense.
Let me know if not and will do another comparison video.
Thank you in advance,
We recently moved from Cinema R19 to R21 and manage to do the changes to our libraries.
One of the things I noticed is that when creating a target tag for a camera
cam.MakeTag(c4d.Ttargetexpression) does not work correctly when assigning a target, as the camera just moves and jumps around the viewport.
Added screen share below of a camera with added scripted target tag and a camera with added manual target tag.
Am I missing something really obvious with the change between Cinema versions, please?
Thank you all in advance,
Thank you for your time and help!
Will get it sorted with your pointers above.
All the best!
I just found what perhaps is the issue...
The world-container. It seems that it runs without freezing if the data is not saved and load from the world container.
Quiet odd, but perhaps as you said, it corrupted it somehow?
Just need to find a way to storing data outside of the document.
Many thanks for your valid points and I appreciate what you are saying :).
I've made the changes to use a
GeDialog instead for the menu and it works.
Here's are my results, based on your proposals:
ShowPopupDialog(), as any code after this does not run. Then again it may be something associated with it.
GetTimer()function is not doing anything, so definitely good idea.
The undo-block is for something I wrote in between, but for simplification removed it to pinpoint the culprit.
The world-container is definitely a good point. I'm not sure if I should be using it to store data. I think the reasoning behind it was to keep data accessible between loading and unloading of documents, which is mainly what this plugin is doing.
Would you recommend perhaps a different container to store the data?
What I found most weird is that works perfectly fine with R19, so perhaps as you pointed out on 2, Cinema needs reinstalling.
It's all learning and I think I know a bit more about it now and even if I cannot find the solution for this, I already have another way of dealing with it. Not elegant, but works with no issues :).
Thank you very much for your help and time!
Thank you for your tips!
Unfortunately removing the other plugins does not make a difference, from what I can understand.
I've also run the general popup dialog and it works fine with no freezing.
Not sure what to do about this except perhaps change the
c4d.gui.ShowPopupDialog to a
and create a simple menu. Any thoughts?
Thank you in advance!
Yes, it freezes with the code I provided.
I've also tried the way that you mention above by running the
c4d.SpecialEventAdd(1055684) and the same happens, as per my video below.
Let me know if you need any other information.
Cinema R21.207 Build RB303831.
Windows 10 1809
I'm calling the
SpecialEventAdd on an SceneLoaderPlugin.
# Import modules import c4d plugin_ID = 1055684 class AOLoader(c4d.plugins.SceneLoaderData): """ Class for the SceneLoaderData plugin. """ def Identify(self, node, name, probe, size): """ Identifies if the format of the custom file captured meets the plugins requirements. :param node: BaseContainer for instance. :param name: Path and file name of the instance. :param probe: The data from the instance. :param size: The data size of the instance. :return: True if meets object requirements. """ file_name = name.lower() if not file_name.endswith('.ao'): return False return True @staticmethod def clean_path_str(txt, chr_lst): """ This method removes specific characters in a path. :param txt: The string to replace character. :param chr_lst: The characters list to be replaced. :return: Returns the path with removed c characters. """ for c in chr_lst: txt = txt.replace(c, '') return txt def read_lines(self, data_file): """ Iterates throught the data until finds the line with path for .c4d asset. :param data_file: The file data returned by Identify method. :return: The path string, not formatted. """ with open(data_file, 'rU') as data: ds_file = data.read().splitlines() paths = "" for line in ds_file: if ".c4d" in line: remove_chrs = self.clean_path_str(line, [')', '"']) paths += remove_chrs.replace("\\\\", "\\") return paths def Load(self, node, name, doc, filterflags, error, bt): """ Loads the data into the active document. In this case, we do not load or merge the file, but send a message to CoreMessage when it is catched with a SpecialEventAdd. The WorldContainer will save the path to be used later. :param node: BaseContainer for the instance. :param name: Path and file name of the instance. :param doc: The active document. :param filterflags: Flags to filter objects to load. :param error: Errors brought by Identify Method. :param bt: The BaseThread for the document. :return: Returns a c4d.FILEERROR_USERBREAK to capture the message. """ paths = self.read_lines(name) world_container = c4d.GetWorldContainerInstance() world_container.SetString(plugin_ID, paths) c4d.SpecialEventAdd(plugin_ID) return c4d.FILEERROR_USERBREAK if __name__ == "__main__": c4d.plugins.RegisterSceneLoaderPlugin(id=plugin_ID, str="AO Loader", g=AOLoader, info=c4d.PLUGINFLAG_SCENELOADER_MERGEORIGINAL, description="")
It's passing the data correctly, so perhaps the call needs to be done somewhere else?
Thank you in advance!
Hope you are well in these crazy times!
I'm having trouble understanding how
ShowPopupDialog currently works in R21, if caught by MessageData plugin's
CoreMessage. It keeps freezing Cinema, could be thread related (which I don't know a lot of)?
I manage to get the data across externally fine but when creating the menu it freezes immediately after
c4d.gui.ShowPopupDialog is called.
# Import modules import os import c4d from c4d import documents plugin_ID = 1055685 plugin_ID_loader = 1055684 MENU_ADD_ASSETS = c4d.FIRST_POPUP_ID MENU_ADD_MATERIALS = c4d.FIRST_POPUP_ID + 1 MENU_REPLACE_ASSETS = c4d.FIRST_POPUP_ID + 2 MENU_REPLACE_MATERIALS = c4d.FIRST_POPUP_ID + 3 MENU_REPLACE_TAG = c4d.FIRST_POPUP_ID + 4 class AOMessage(c4d.plugins.MessageData): """ Class for the MessageData plugin. """ def GetTimer(self): """ Called to return a time in milliseconds to receive timer messages (MSG_TIMER) with that interval in CoreMessage. This method is queried again after each message.. :return: The time in miliseconds. """ return 0 def CoreMessage(self, id, bc): """ Called to receive core messages. :param id: The id of the messages received. :param bc: The BaseContainer objects with message data. :return: True if Message is received. """ if id == plugin_ID_loader: world_container = c4d.GetWorldContainerInstance() doc = documents.GetActiveDocument() paths_str = world_container.GetString(plugin_ID_loader) paths_lst = paths_str.split(', ') active_objs = doc.GetActiveObjects(c4d.GETACTIVEOBJECTFLAGS_0) active_mat = doc.GetActiveMaterial() doc.StartUndo() # Dialog for importing assets menu = c4d.BaseContainer() if active_objs or active_mat: menu.InsData(MENU_REPLACE_ASSETS, 'Replace Asset(s)') menu.InsData(MENU_REPLACE_MATERIALS, 'Replace Material(s)') menu.InsData(MENU_REPLACE_TAG, 'Replace Texture Tag(s)') else: menu.InsData(MENU_ADD_ASSETS, 'Add Asset(s)') menu.InsData(MENU_ADD_MATERIALS, 'Add Material(s)') result = c4d.gui.ShowPopupDialog(cd=None, bc=menu, x=c4d.MOUSEPOS, y=c4d.MOUSEPOS) doc.EndUndo() world_container.RemoveData(plugin_ID_loader) print("Finished") return True if __name__ == "__main__": c4d.plugins.RegisterMessagePlugin(id=plugin_ID, str="AO Message", info=0, dat=AOMessage())
It works perfectly in R19, so I'm not sure what changed since then.
Apologies if this as been asked before.
Thank you very much for your help in advance!
Not to worry! I understand!
Thanks for your help!
I am somehow even more confused than before, lol. You want the geometry in the screenshot to be subdivided, right? And the geometry is somehow procedurally generated by a Xpresso rig?
I'm sorry if it made it more confusing!
The Xpresso just connects the userdata to the generator object. So the subdivisions are controlled by changing the object's number of segments.
I do not quite understand why you cannot just implement that choice of subdivision in that rig? Doing it after the fact seems incredible cumbersome because this is probably not a static polygon mesh, but some kind of generator object that your rig produces there.
That's correct! Which leads me to think that having a poly object in the first place is probably the best way.
I am also just seeing now that you are asking also for a unsubdiving feature in your first post, which is quite a can of worms for an arbitrary mesh. I would go for your LOD-thingy if you see there a solution, because it is probably the fastest solution for you.
Yes, that's what I currently testing. I agree as that being the best way to switch from different resolutions.
Hopefully, this will work.
Will keep you posted!
Does your setup react to the global Level of Detail controls?
I'm afraid not! It's all done by changing the number of segments for the objects.
If not, could you use a local LOD object with differently subdivided children?
I'm currently exploring this. I think I will be able to do that. Need to make sure it it does not break with the rest of setup
Will keep you posted!
Thank you very much for your help and apologies for the slow reply (been off a few days)!
You are absolutely right, my question is too broad.
Had a few days to think about other options and perhaps I'm overthinking this.
Nevertheless, I will share with you the specifics.
So this is the current rig:
You have a dynamic change of shapes that supports all the parameters that you see in the image.
It does lack the secondary controls needed to shape it as we want and this is a big point as I currently can't create the nuances with Xpresso.
A possible solution would be to use three poly objects with different levels of subdivisions that are controlled with the same rig. Keep some elements procedural, as the bevel and bend deformers and connected all by Xpresso.
This would give us the benefit of accessing the point information and deformed it manually for animation as we need.
Also as @zipit said, this can also be a potential design, if rest fails
And last but not least, a Python Tag doesn't seem to be the right choice for this kind of tool in the first place, due to its constant execution. A script manager script, a Python Generator Object or a fitting plugin type would be much appropriate choices.
I understand that this is a design question and not API, so please delete if it's inappropriate.
Will come back with some results!
Thank you all again for your time!
Hi @Cairyn ,
Thank you very much for that!
Good to know from someone with more experience than myself.
We have a rig that already works with procedural objects, which is great. But at the moment if we want to have flexibility with it, I need to be able to control specific points/polygons of the objects to give animation the flexibility they need. I'm just trying to get a solution that takes aspects of both procedural and polygon objects, thus my question.
Have to think in a different way for now!
I'm trying to understand how to add and remove edge loops from a polygon object, by using a slider in User Data and a Python Tag.
Like replicating the segments change with a Procedural Cube, for example.
Not completely sure how I would start this, to be honest.
Would be very grateful for any direction, please.
Thank you all in advance!
Thank you for giving me some time to check this out.
So after a bit of testing and changing the code to work with Cinema I cannot replicate the issue. As you mention it seems to be related to Pyblish.
I did find interesting that when running the code in Cinema without Pyblish you can't see the active frame running through the timeline, while you do see it when running through Pyblish. Perhaps that's the correlation with the crash.
I will close this as solve, for the fact that it does not crash in the Cinema context.
Thank you Manuel!
I appreciate it!
Apologies for this, as due to current circumstances I'm inundated in solving other issues.
Can we revisit this please?
Thank you in advance and apologies!