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://plugincafe.maxon.net/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 alternative

    def 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!!
    rownn

    EDIT: Have optimized the code


Log in to reply