CSTO on a Cloner
-
On 05/11/2017 at 07:20, xxxxxxxx wrote:
I have a ObjectPlugin where I want to use a cloner.
But CSTO returns a Null with only one child under it (and not 2 as I expected).Input objA = Cube, objB = Cloner with a cube and a count of 2.
So, I expect a Null with 2 children.It does not help if I use a Clone or not.
Here the test code.def GetVirtualObjects(self, op, hierarchyhelp) : doc = c4d.documents.GetActiveDocument() if op.GetDown() is None or op.GetDown().GetNext() is None: return c4d.BaseObject(c4d.Onull) res = op.GetAndCheckHierarchyClone(hierarchyhelp, op.GetDown(), c4d.HIERARCHYCLONEFLAGS_0, True) if res['dirty'] == False: return res['clone'] objA = res['clone'].GetDown() objB = objA.GetNext() objList = c4d.utils.SendModelingCommand( command = c4d.MCOMMAND_CURRENTSTATETOOBJECT, list = [objB], #using objB.GetClone() does not help mode = c4d.MODELINGCOMMANDMODE_ALL, doc = doc) if objList == False: #print "Error Current State to object MoGraph!" return None print "CSTOMoGraph: ", objB print "objList[0]: ", objList[0] print objList[0].GetChildren() #print all children return c4d.BaseObject(c4d.Onull)
-
On 05/11/2017 at 07:47, xxxxxxxx wrote:
objB.GetCache() seems to return all children!
But apparently GetVirtualObjects() makes life harder.
Using the script manager I get the result I expected, but within GetVirtualObjects() objB.GetCache() returns None?
Script
import c4d from c4d import gui #Welcome to the world of Python def main() : obj = op.GetCache() print obj.GetChildren() if __name__=='__main__': main()
Test code
def GetVirtualObjects(self, op, hierarchyhelp) : doc = c4d.documents.GetActiveDocument() if op.GetDown() is None or op.GetDown().GetNext() is None: return c4d.BaseObject(c4d.Onull) res = op.GetAndCheckHierarchyClone(hierarchyhelp, op.GetDown(), c4d.HIERARCHYCLONEFLAGS_0, True) if res['dirty'] == False: return res['clone'] objA = res['clone'].GetDown() objB = objA.GetNext() objCache = objB.GetCache() print "objCache: ", objCache print "CSTOMoGraph: ", objB print objCache.GetChildren() return c4d.BaseObject(c4d.Onull)
-
On 05/11/2017 at 08:48, xxxxxxxx wrote:
Or do I have to use GeGetMoData() to get all the children?
-
On 07/11/2017 at 00:29, xxxxxxxx wrote:
Solved it using a new doc.
-
On 07/11/2017 at 03:22, xxxxxxxx wrote:
Ok, I am using a new doc to do the csto for a MoGraph cloner.
That works, but the materials - attached to the children of the cloner - are not included.
Of course that is because I use a new doc without any materials.
But then the question is then, how to get the materials back?Even if I use a doc.GetClone() for the new doc, it does not work.
-Pim
-
On 07/11/2017 at 05:46, xxxxxxxx wrote:
Hi Pim,
I'm terribly sorry for letting you alone with this for so long.
First of all, even if it may not be the cause of your issues, it is so important, I must not forget: Never ever use GetActiveDocument() in a NodeData (or derived thereof) plugin! Never!
Reason:
Functions like Execute(), GetVirtualObjects() and alike get called during scene execution. But a scene/document does not only get executed, while the user is working with it in the editor, but also for example when rendering. But in the later case the scene is most likely not the active document (but at least a clone thereof). So by using GetActiveDocument() in a NodeData plugin you will end up in a situation, where you are working with the wrong document. Maybe not immediately, but once for sure. And even then you might not even notice, because the active scene and the one being rendered might be identical or identical enough for this not to cause immediate issues. But then one day it will cause problems and the issue then will be pretty hard to track down as things suddenly without warning start acting weird. So please, do not use GetActiveDocument() here, instead use op.GetDocument().Ok, forgive me for writing so much about this, but it's really important. I will see, that we improve our documentation in this regard.
Now, back to your original issue.
No, you don't need to use GeGetMoData().
In the end you are dealing with caches of objects and if evaluated properly, these caches do finally contain the polygonal representation of a more or less complex object (-hierarchy). Just to visualize a more complex situation (and the one you are describing is not that different), see the notes and image on GetCache() and GetDeformCache(). This just to get a better understanding, in your case you don't need to iterate the caches yourself.
Good news is, GetAndCheckHierarchyClone() takes care of this. It iterates the hierarchy of your input objects, takes care of dependency lists, retrieves clones(!) of the involved caches and also marks your input objects correctly as control objects.
The important part for you: It retrieves clones of the involved caches. Meaning, you get a polygonal representation of the inputs.
No need to do an extra "Current State to Object" via SendModelingCommand(), as you do in your first post.
And also no need to try to get the cache of the returned cache objects as you do in your second post via objB.GetCache(). objB is already (part of) the cache.The thing is, GetAndCheckHierarchyClone() returns the cache, but you need to be aware that the cache may be a bit more complex, i.E. is a hierarchy of objects. In case of your MoGraph Cloner example as second input object, objB will be a Null object parenting the polygonal representations of the cube clones.
So your code snippets are actually correct until the assignment of objA and objB. objB then being the Null object, where in the original object hierarchy the cloner was located. And objB.GetDown() will be the first cube.
Also worth knowing that you can use GetType(), CheckType(), IsInstanceOf() or even GetName() to get an idea of what got returned to you in such situations.
-
On 07/11/2017 at 07:25, xxxxxxxx wrote:
Thanks for the detailed answer, I am beginning to see the light.
However, for me it does not return the polygonal representations of the cube clones, but the objects itself.
Here the console output:
objB: <c4d.BaseObject object called 'Cloner/Cloner' with ID 1018544 at 0x0000016A9C11DB30>
[<c4d.BaseObject object called 'Cube/Cube' with ID 5159 at 0x0000016A9C11D9D0>, <c4d.BaseObject object called 'Cylinder/Cylinder' with ID 5170 at 0x0000016A9C11D8B0>]This is the hierarchy:
- objectplugin
- cube
- MoGraph Cloner
- cube
- cylinderdef GetVirtualObjects(self, op, hierarchyhelp) : doc = op.GetDocument() #not needed here if op.GetDown() is None or op.GetDown().GetNext() is None: return c4d.BaseObject(c4d.Onull) res = op.GetAndCheckHierarchyClone(hierarchyhelp, op.GetDown(), c4d.HIERARCHYCLONEFLAGS_0, True) if res['dirty'] == False: return res['clone'] objA = res['clone'].GetDown() objB = objA.GetNext() print "objB: ", objB print objB.GetChildren() #print all children return c4d.BaseObject(c4d.Onull)
-
On 07/11/2017 at 08:19, xxxxxxxx wrote:
Ah, sorry!!!
I overlooked your flags. Please pass c4d.HIERARCHYCLONEFLAGS_ASPOLY to GetAndCheckHierarchyClone(). -
On 07/11/2017 at 08:35, xxxxxxxx wrote:
Thank you!