How to get the splineobject of primitives?[SOLVED]
-
On 14/12/2016 at 08:23, xxxxxxxx wrote:
Hey,
I hope it´s a noobish question. I´d like to get the splineobject with tangents of a primitiv, for example circle.
This is what I already tried:import os import math import sys import c4d from c4d import plugins, utils, bitmaps, gui PLUGIN_ID = 123455589 class TEST(plugins.ObjectData) : def Init(self, node) : return True def GetVirtualObjects(self, op, hierarchyhelp) : child = op.GetDown() if not child: return None print child.GetCache() res = c4d.utils.SendModelingCommand( command = c4d.MCOMMAND_MAKEEDITABLE, list = [child.GetClone()], mode = c4d.MODELINGCOMMANDMODE_ALL, bc = c4d.BaseContainer(), doc = op.GetMain())[0] print res res = c4d.utils.SendModelingCommand( command = c4d.MCOMMAND_CURRENTSTATETOOBJECT, list = [child.GetClone()], mode = c4d.MODELINGCOMMANDMODE_ALL, bc = c4d.BaseContainer(), doc = op.GetMain())[0] print res, res.GetPointCount() print op.GetAndCheckHierarchyClone(hierarchyhelp,child,c4d.HIERARCHYCLONEFLAGS_ASSPLINE,False)["clone"] return None if __name__ == "__main__": dir, file = os.path.split(__file__) icon = bitmaps.BaseBitmap() icon.InitWith(os.path.join(dir, "res", "TEST.tif")) plugins.RegisterObjectPlugin(id=PLUGIN_ID, str="TEST2", g=TEST, description="TEST2", info=c4d.OBJECT_GENERATOR, icon=icon)
But
print child.GetCache()
(first print) returns <c4d.LineObject object called 'Circle' with ID 5137 at 0x0000000012661C70>,
print res
(second print) returns <dead c4d.SplineObject object at 0x0000000012661DB0>
print res
(third print) returns <c4d.SplineObject object called 'Circle/Spline' with ID 5101 at 0x0000000012661DF0> 68 (68 points means that all the intermediate points became points)
print op.GetAndCheckHierarchyClone(hierarchyhelp,child,c4d.HIERARCHYCLONEFLAGS_ASSPLINE,False)["clone"]
(last print) returns <c4d.BaseObject object called 'Circle/Circle' with ID 5181 at 0x0000000010B1E1F0>.
Any other ideas or THE solution?
Thx and greetings
rownn -
On 14/12/2016 at 16:08, xxxxxxxx wrote:
The best method that I've found is to use SendModelingCommand with Make Editable. Doesn't work in all cases, but that's your best shot if you want to maintain the original points.
-
On 14/12/2016 at 16:09, xxxxxxxx wrote:
You'll probably want to watch the progress on this thread:
https://developers.maxon.net/forum/topic/9791/13170_getvirtualobjects-v-getcontour-for-spline-gen&PID;=52510#52510 -
On 14/12/2016 at 16:16, xxxxxxxx wrote:
Try cloning the result you get after the MakeEditable, that should keep it alive.
"""Make Editable Inserts the "editable" version of the selected object. v0.0.1 by Donovan Keith """ import c4d from c4d import gui def MakeEditable(op) : if not op: return op_clone = op.GetClone() if not op_clone: return result_list = c4d.utils.SendModelingCommand( command = c4d.MCOMMAND_MAKEEDITABLE, list = [op_clone], mode = c4d.MODELINGCOMMANDMODE_ALL, bc = c4d.BaseContainer(), doc = op.GetDocument()) if not result_list: return result = result_list[0].GetClone() return result def main() : spline = MakeEditable(op) if not spline: return doc.StartUndo() doc.InsertObject(spline) doc.AddUndo(c4d.UNDOTYPE_NEW, spline) c4d.EventAdd() doc.EndUndo() if __name__=='__main__': main()
-
On 15/12/2016 at 01:29, xxxxxxxx wrote:
Hey Donovan,
thanks for your reply. I hope I got it, but its a bit strange.
This seems to work.clone = child.GetClone() res = c4d.utils.SendModelingCommand( command = c4d.MCOMMAND_MAKEEDITABLE, list = [clone], mode = c4d.MODELINGCOMMANDMODE_ALL, bc = c4d.BaseContainer(), doc = op.GetMain())[0].GetClone()
This seems to work, too. (Without cloning the result)
clone = child.GetClone() res = c4d.utils.SendModelingCommand( command = c4d.MCOMMAND_MAKEEDITABLE, list = [clone], mode = c4d.MODELINGCOMMANDMODE_ALL, bc = c4d.BaseContainer(), doc = op.GetMain())[0]
This doesnt work:
res = c4d.utils.SendModelingCommand( command = c4d.MCOMMAND_MAKEEDITABLE, list = [child.GetClone()], mode = c4d.MODELINGCOMMANDMODE_ALL, bc = c4d.BaseContainer(), doc = op.GetMain())[0].GetClone()
So it seems Ive to put the clone into a varaible before calling c4d.MCOMMAND_MAKEEDITABLE.
Thanks again and greetings
rownn -
On 15/12/2016 at 02:12, xxxxxxxx wrote:
Yeah, I think what's happening is that if you do .GetClone() in the function call SendModelingCommand() owns the clone. When SMC is done executing garbage collection kills the reference to the clone.
By making the clone and assigning it to a variable, you're ensuring that it will be "needed" by the calling function and that garbage collection won't delete it prematurely.
At least that's my best guess. I remember working through the exact same issue and it felt like voodoo as I was trying to figure out where I'd gone wrong.
-
On 15/12/2016 at 02:44, xxxxxxxx wrote:
Ok, cloning the result is nessesary if you wanne store the object ... makes sence.
-
On 15/12/2016 at 12:41, xxxxxxxx wrote:
Hi Rown, thanks for writing us.
With reference to your question, I suggest to use the GetRealSpline() method once you've checked the primitive type of the input object. This method basically returns for procedural curve generator the spline data (like points and tangents).
If beside querying for the spline data your intent is to use the child inside the GetVirtualObjects() I suggest to experiment with GetHierarchyClone() combined with GetAndCheckHierarchyClone() as shown in the short snippet below. At the moment the GetHierarchyClone() behaves a little bit differently than how it's implemented in C++ (we're working to fix it in future) but using it combined with GetAndCheckHierarchyClone() provides a viable alternativedef GetVirtualObjects(self, op, hh) : if op is None or hh is None: return None cloneDirty = False clone = None childDirty = -1 dirty = False child = op.GetDown() if not child: return None if not (child.IsInstanceOf(c4d.Ospline) or child.IsInstanceOf(c4d.Oline) or child.GetInfo()&c4d.OBJECT_SPLINE) : print ("Child object doesn't belong to spline/line primitive type") return None realSpline = child.GetRealSpline() if realSpline is not None: PrintSplineData(realSpline) resGHC = op.GetHierarchyClone(hh, child, c4d.HIERARCHYCLONEFLAGS_ASSPLINE) if resGHC is None: resGHC = op.GetAndCheckHierarchyClone(hh, child, c4d.HIERARCHYCLONEFLAGS_ASSPLINE, False) if resGHC is not None: cloneDirty = resGHC["dirty"] clone = resGHC["clone"] # it should return true only if the cloned object has been updated # but it seems that it returns true even if child has not changed dirty |= cloneDirty # add the dirty status of the operator data dirty |= op.IsDirty(c4d.DIRTYFLAGS_DATA) # recursively compute the child dirty status childDirty = RecursiveCheckDirty(child) child.Touch() # compare the dirtyness of local and member variable and accordingly update the generator's # dirty status and the member variable value dirty |= self._childDirty != childDirty self._childDirty = childDirty cache = op.GetCache() if not dirty and cache is not None: return cache return clone
Best, Riccardo
-
On 01/01/2017 at 06:18, xxxxxxxx wrote:
Hey KnickKnack,
sorry for my late reply.
I thank you for your hint to use GetRealSpline(), but I wasn´t able to understand all intensions in your code, so I have writting the following and it works for me.import os import math import sys import c4d from c4d import plugins, utils, bitmaps, gui PLUGIN_ID = 12345557 class ObjektDataTest(plugins.ObjectData) : def __init__(self) : self.child = None self.sourcePoints = [] def checkIsDirty(self, spline) : if spline: pnts = spline.GetAllPoints() else: pnts = [] if pnts != self.sourcePoints: self.sourcePoints = pnts return True else: return False def getSplineObject(self, child) : if child.CheckType(c4d.Oinstance) : if child[c4d.INSTANCEOBJECT_LINK].GetType() in self.acceptedTypes: realSpline = child[c4d.INSTANCEOBJECT_LINK].GetRealSpline() else: realSpline = child.GetRealSpline() if realSpline: return {'splineObject': realSpline, 'dirty': self.checkIsDirty(realSpline)} else: return {'splineObject': None, 'dirty': False} return {'splineObject': None, 'dirty': False} def GetVirtualObjects(self, op, hh) : if op is None or hh is None: return None child = op.GetDown() if not child:return None if not child[c4d.ID_BASEOBJECT_GENERATOR_FLAG]: return None if self.child != child: childNew = True else: childNew = False self.child = child gSO = self.getSplineObject(child) realSpline = gSO['splineObject'] if not realSpline: return None if op.GetCache() == None or child.IsDirty(c4d.DIRTYFLAGS_DATA) or child.IsDirty(c4d.DIRTYFLAGS_MATRIX) or gSO['dirty'] or op.IsDirty(c4d.DIRTYFLAGS_DATA) or childNew: print "DO STUFF", realSpline.GetPointCount() obj = realSpline.GetClone() else: obj = op.GetCache().GetClone() return obj if __name__ == "__main__": dir, file = os.path.split(__file__) icon = bitmaps.BaseBitmap() icon.InitWith(os.path.join(dir, "res", "ObjektDataTest.tif")) plugins.RegisterObjectPlugin(id=PLUGIN_ID, str="ObjektDataTest", g=ObjektDataTest, description="ObjektDataTest", icon=icon, info=c4d.OBJECT_GENERATOR)
Thx again and a happy new year!!
rownnEDIT: Have optimized the code