Tips and Tricks: Reading the SDK



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 11/04/2011 at 17:11, xxxxxxxx wrote:

    Since many people (besides me) have problems understanding how to read the SDK.
    Should we have a thread that has tips on how to read it?

    For example.
    This is something that I learned that's very important in getting the most out of the SDK:

    Many things in the Python SDK need to be created (instantiated) first before you can use the methods in that class.
    So to create an instance of a class. You look at the top of the SDK where it's say's something like this in grey:

    -class c4d.utils.Neighbor  
    -class c4d.bitmaps.BaseBitmap
    -class c4d.utils.SplineHelp

    Then you assign a variable to this class like this:
    nb = utils.Neighbor               #assigns a variable to the Neighbor class
    bmp = bitmaps.BaseBitmap  #assigns a variable to the Bitmap class
    sh = c4d.utils.SplineHelp()    #assigns a variable to the SplineHelp

    Once you've got a variable assigned to your class. You can then initialize it by using that variable with the init() function for that class. Like this:

    nb.Init(obj) #obj would be a variable that holds the object we're working on
    bmp.InitWith(path) #Path would be a variable that holds a file path
    length.Init(op,0)# Initializes the spline object(op) and the first spline segment

    Notice: We don't   use _Init()_
    Instead we look for the Init() function listed in the SDK under a particular class that has either nothing in it(). Or some parameters in it by default.

    Now that we have the class defined with a variable. And the class is instantiated using that variable. We can now use that to call to all of the many methods associated with each class in the SDK like this:

    nb.GetPointPolys(PointIndex) # Gets the neighboring polygons found in variable PointIndex
    bmp.GetSize() #Gets the pixel size of an image
    sh.GetSegmentLength(0)#Gets the length of the first segment

    Knowing how to create and initialize classes like this is crucial in using the C4D Python SDK.
    Because in many cases. You can't get access to all of the wonderful methods until you instantiate the class first.

    -ScottA



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 11/04/2011 at 21:40, xxxxxxxx wrote:

    Many things in the Python SDK need to be created (instantiated) first before you can use the methods in that class.
    So to create an instance of a class. You look at the top of the SDK where it's say's something like this in grey:

    Of course! You must see the difference between a module and a class.

    Once you've got a variable assigned to your class. You can then initialize it by using that variable with the init() function for that class. Like this:

    Not every class has got an own 'Init()' method. This is just for classes that need to be initialised with any values, that can be flushed, so that you can initialise them again.

    nb = utils.Neighbor               #assigns a variable to the Neighbor class
    bmp = bitmaps.BaseBitmap  #assigns a variable to the Bitmap class
    sh = c4d.utils.SplineHelp()    #assigns a variable to the SplineHelp

    In the first 2 lines you do *not* instantiate the classes 'Neighbour' and 'BaseBitmap', you assign the vonstructors new variables.

    That's the difference:

    from c4d import utils  
      
    neighbor_constructor = utils.Neighbor  
      
    neihgbor_instance = utils.Neighbor()  
    neihgbor_instance.Init(op)  
      
    neihgbor_instance.GetPointPolys(1)  
    neighbor_constructor.GetPointPolys(1)      #raises an error
    

    This is a very handy feature of Python:

    from c4d.gui import MessageDialog as MsgD  
    MsgD("Hi, I'm a MessageDialog !")
    
    import c4d  
    from c4d import BaseObject as BO  
    BO(c4d.Ocube)  
    """This is the same as: """  
    import c4d  
    BO = c4d.BaseObject  
    BO(c4d.Ocube)
    
    """You can also overload functions"""  
    import c4d  
      
    def do(userfunc,*userargs) :  
      op = c4d.BaseObject(c4d.Ocube)  
      userfunc(op,*userargs)  
      
    def myfunction(op,vec) :  
      op.SetAbsPos(vec)  
      
    def main() :  
      do(myfunction,c4d.Vector(0,300,700))  
      
    main()
    

    Cheers, Niklas



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 12/04/2011 at 11:05, xxxxxxxx wrote:

    This is a small tip. But trips up many people.
    Many things need to have a c4d. prefix to work. And it's easy to forget it.

    The Error you'll get for this is:
    NameError: global name "item" Not Defined     #  item is whatever you're working on at the time

    This is the same error you get if you forget to declare a variable. But most people spot that kind of mistake fairly easy.
    The missing c4d. prefix is a little bit more subtle and harder to spot.

    -ScottA



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 15/04/2011 at 08:50, xxxxxxxx wrote:

    I didn't see any examples of creating menus and sub menus in the SDK.
    So here is an entire plugin example that shows how to create them. And does some other common tasks.

      
    import os  
    import sys  
    import c4d  
    from c4d import plugins, utils, bitmaps, gui, documents  
      
    Plugin_ID=1000009 # Testing id ONLY!!!!!!!   
      
     #enums  
    MENU_ITEM1 = 1  
    MENU_ITEM2 = 2   
    MENU_ITEM3 = 3   
    MENU_ITEM4 = 4  
    RESET_BUTTON = 5     
       
       
    #---------------------------------------------------  
    #   MyDialog_Gui class --- where GUI items are added  
    #---------------------------------------------------  
      
    class MyDialog_Gui(gui.GeDialog) :  
       
     def CreateLayout(self) :  
       
     #This is the first menu code  
      self.MenuFlushAll();      
      self.MenuSubBegin("Menu1")              
      self.MenuAddString(MENU_ITEM1,"item1")  
      self.MenuAddString(MENU_ITEM2,"item2")  
      self.MenuAddSeparator()  
      self.MenuSubBegin("SubMenu1")  
      self.MenuAddCommand(1001153) # Creates an atom object                  
      self.MenuSubBegin("SubMenu2")  
      self.MenuAddCommand(1001154) # Creates a double circle object                      
      self.MenuSubEnd()  
      self.MenuSubEnd()  
      self.MenuSubEnd()  
      self.MenuFinished() #Ends the first menu & submenu list    
      
      #This is the second menu code   
      #Notice that we don't make another MenuFlushAll() function   
      self.MenuSubBegin("Menu2")              
      self.MenuAddString(MENU_ITEM3,"test1")  
      self.MenuAddString(MENU_ITEM4,"test2")  
      self.MenuAddSeparator()  
      self.MenuSubBegin("SubMenu1")  
      self.MenuAddCommand(5159) # Creates a Cube primitive                  
      self.MenuSubBegin("SubMenu2")  
      self.MenuAddCommand(5160) # Creates a Sphere primitive                      
      self.MenuSubEnd()  
      self.MenuSubEnd()  
      self.MenuSubEnd()  
      self.MenuFinished() #Ends the second menu & submenu list   
        
      self.GroupBeginInMenuLine() #Adds the Button to the menu area of the dialog window  
      self.AddButton(RESET_BUTTON, c4d.BFH_CENTER, 60, 10, name="Reset") #id, flags, width, height, caption   
      self.GroupEnd() #Ends the group formatting   
        
       
      self.GroupBegin(0, c4d.BFH_SCALEFIT|c4d.BFH_SCALEFIT, 1, 3, "Group Title",0) #id, flags, columns, rows, grouptext, groupflags  
      self.GroupBorder(c4d.BORDER_BLACK)  
      self.GroupBorderSpace(5, 20, 5, 20) #Left, top, Right, Bottom   
      self.SetTitle("myPythonDialog")    
      self.AddStaticText(4001,c4d.BFH_LEFT,50,10,"input",c4d.BORDER_NONE) #id, flags, height, width, text, borderstyle                                        
      self.AddEditText(4002,c4d.BFH_SCALEFIT,4,10,0) #id, flags, height, width, password     
      self.AddEditText(4003,c4d.BFH_SCALEFIT,2,10,0) #id, flags, height, width, password       
      self.AddButton(1001, c4d.BFH_CENTER, 100, 10, name="Execute X-Ray") #Puts the button in the menu bar  
        
      self.GroupEnd()  
      return True   
      
    #--------------------------------------------------------------------------  
    #    MyDialog_Gui method --- where gui items are set up with default values  
    #--------------------------------------------------------------------------   
       
     def InitValues(self) :  
    self.SetString(4002,"Waiting") #Sets the text inside of the field when the plugin opens  
    self.SetString(4003,"Waiting") #Sets the text inside of the field when the plugin opens  
    return True  
      
    #---------------------------------------------------------------------------------------------  
    #   MyDialog_Gui method --- Executes your code when GUI is used. Put your python code in here  
    #---------------------------------------------------------------------------------------------     
        
     def Command(self, id, msg) :  
    doc = documents.GetActiveDocument()   
    op = doc.GetActiveObject()   
    if id == 1001:  
      print "Button was pushed"  
      if not op:  
         gui.MessageDialog("Select an object first!")  
         return True  
      op[c4d.ID_BASEOBJECT_XRAY]=1  
      self.SetString(4002,"Button Worked!") #Sets the text inside of the field when the button is pushed  
      self.SetString(4003,"Congradulations!") #Sets the text inside of the field when the button is pushed  
      #gui.MessageDialog("Button was pushed") # Makes a pop up message appear whe the button is pushed  
        
    if id == RESET_BUTTON:     
      self.SetString(4002,"Waiting") #ReSets the text  
      self.SetString(4003,"Waiting") #ReSets the text     
      op[c4d.ID_BASEOBJECT_XRAY]=0 #Turns the Xray option off  
    c4d.EventAdd()  
      
    return True  
        
        
        
    #---------------------------------------------------------------  
    #   MyDialog_Main --- Where the plugin stuff happens--Don't edit  
    #---------------------------------------------------------------  
    class myDialog_Main(plugins.CommandData) :  
     dialog = None  
        
     def Execute(self, doc) :  
      # create the dialog  
      if self.dialog is None:  
         self.dialog = MyDialog_Gui()  
      return self.dialog.Open(dlgtype=c4d.DLG_TYPE_ASYNC, pluginid=Plugin_ID, defaultw=200, defaulth=150, xpos=-1, ypos=-1)  
            
     def RestoreLayout(self, sec_ref) :  
      # manage nonmodal dialog  
      if self.dialog is None:  
         self.dialog = MyDialog_Gui()  
      return self.dialog.Restore(pluginid=Plugin_ID, secret=sec_ref)  
       
      
    if __name__ == "__main__":  
     path, fn = os.path.split(__file__)  
     bmp = bitmaps.BaseBitmap()  
     bmp.InitWith(os.path.join(path, "res/icons/", "None"))  
     plugins.RegisterCommandPlugin(Plugin_ID, "myPythonDialog",0,None,"", myDialog_Main())  
    

    -ScottA



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 18/05/2011 at 10:25, xxxxxxxx wrote:

    Changing the display filter options is listed in the SDK under "BaseDocument".
    But I couldn't anything about the Selection filters. So here's how to manipulate those options with python.

    Here's a way to see which options are enabled:

    import c4d  
    from c4d import gui  
      
    def main() :  
     bc = doc.GetData()  
     sf = bc.GetLong(c4d.DOCUMENT_SELECTIONFILTER) #Get the filter bit mask  
     if not(sf & c4d.SELECTIONFILTERBIT_NULL) : print "Null Enabled"  
     if not(sf & c4d.SELECTIONFILTERBIT_POLYGON) : print "Polygon Enabled"  
     if not(sf & c4d.SELECTIONFILTERBIT_SPLINE) : print "Spline Enabled"  
     if not(sf & c4d.SELECTIONFILTERBIT_GENERATOR) : print "Generator Enabled"  
     if not(sf & c4d.SELECTIONFILTERBIT_HYPERNURBS) : print "HyperNurbs Enabled"  
     if not(sf & c4d.SELECTIONFILTERBIT_DEFORMER) : print "Deformer Enabled"  
     if not(sf & c4d.SELECTIONFILTERBIT_CAMERA) : print "Camera Enabled"  
     if not(sf & c4d.SELECTIONFILTERBIT_LIGHT) : print "Light Enabled"  
     if not(sf & c4d.SELECTIONFILTERBIT_SCENE) : print "Scene Enabled"  
     if not(sf & c4d.SELECTIONFILTERBIT_PARTICLE) : print "Particle Enabled"  
     if not(sf & c4d.SELECTIONFILTERBIT_JOINT) : print "Joint Enabled"  
       
    if __name__=='__main__':  
      main()
    

    These two scripts show how to turn one of the selections on or off:

    #This script turns the polygon option OFF  
      
    import c4d  
    from c4d import gui  
      
    def main() :  
     bc = doc.GetData()#Get the document's container  
     sf = bc.GetLong(c4d.DOCUMENT_SELECTIONFILTER) #Get the filter bit mask  
      
     if not(sf & c4d.SELECTIONFILTERBIT_POLYGON) : #If the option is ON  
      f = sf | c4d.SELECTIONFILTERBIT_POLYGON #Change the polygon option's Bit in memory only  
      bc.SetLong(c4d.DOCUMENT_SELECTIONFILTER, f) #Use the Bit info to change the container in memory only  
      doc.SetData(bc) #Execute the changes made to the container from memory  
     c4d.EventAdd()  
      
    if __name__=='__main__':  
      main()  
      
    ##################################################################################  
    ##################################################################################  
      
    #This script turns the polygon option ON  
      
    import c4d  
    from c4d import gui  
      
    def main() :  
     bc = doc.GetData()#Get the document's container  
     sf = bc.GetLong(c4d.DOCUMENT_SELECTIONFILTER) #Get the filter bit mask  
      
     if (sf & c4d.SELECTIONFILTERBIT_POLYGON) : #If the option is OFF  
      f = sf &~ c4d.SELECTIONFILTERBIT_POLYGON #Change the polygon option's Bit in memory only  
      bc.SetLong(c4d.DOCUMENT_SELECTIONFILTER, f) #Use the Bit info to change the container in memory only  
      doc.SetData(bc) #Execute the changes made to the container from memory  
     c4d.EventAdd()  
      
    if __name__=='__main__':  
      main()
    

    Credit goes to the guys in the C++ forum for helping me figure this one out.

    -ScottA


Log in to reply