Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush Python API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    How to get the splineobject of primitives?[SOLVED]

    Scheduled Pinned Locked Moved PYTHON Development
    9 Posts 0 Posters 845 Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • H Offline
      Helper
      last edited by

      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

      1 Reply Last reply Reply Quote 0
      • H Offline
        Helper
        last edited by

        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.

        1 Reply Last reply Reply Quote 0
        • H Offline
          Helper
          last edited by

          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

          1 Reply Last reply Reply Quote 0
          • H Offline
            Helper
            last edited by

            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()   
            
            1 Reply Last reply Reply Quote 0
            • H Offline
              Helper
              last edited by

              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

              1 Reply Last reply Reply Quote 0
              • H Offline
                Helper
                last edited by

                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.

                1 Reply Last reply Reply Quote 0
                • H Offline
                  Helper
                  last edited by

                  On 15/12/2016 at 02:44, xxxxxxxx wrote:

                  Ok, cloning the result is nessesary if you wanne store the object ... makes sence.

                  1 Reply Last reply Reply Quote 0
                  • H Offline
                    Helper
                    last edited by

                    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

                    1 Reply Last reply Reply Quote 0
                    • H Offline
                      Helper
                      last edited by

                      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

                      1 Reply Last reply Reply Quote 0
                      • First post
                        Last post