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.SplineHelpThen 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 SplineHelpOnce 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 segmentNotice: 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 segmentKnowing 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 SplineHelpIn 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 timeThis 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