App::FeaturePython discussion

Have some feature requests, feedback, cool stuff to share, or want to know where FreeCAD is going? This is the place.
Forum rules
Be nice to others! Read the FreeCAD code of conduct!
Post Reply
jacknotreally
Posts: 75
Joined: Mon Dec 14, 2009 9:49 am

App::FeaturePython discussion

Post by jacknotreally »

after working a while with "App::FeaturePython" i found it would be helpful
to have a feature derived from "Part::Feature".
The "App::FeaturePython" as now, has no automatic representation of itself like a "Part::Feature".

I would prefer a "App::FeaturePython" with a default viewprovider like that in "Part::Feature" and a default Shape-Property that´s
represent its geometry (and being visible at default).
That would help in dealing with Shape-constructions that don´t use any special coin objetcs.

Jack - not really
wmayer
Founder
Posts: 20243
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: App::FeaturePython discussion

Post by wmayer »

Yes, this makes much sense. I have it already on my todo list for some time but until now didn't find the latter to implement it. I have submitted an issue on the Mantis tracker to myself (https://sourceforge.net/apps/mantisbt/f ... .php?id=41)
wmayer
Founder
Posts: 20243
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: App::FeaturePython discussion

Post by wmayer »

Hi,

I have added the new class Part::FeaturePython which inherits from App::FeaturePython and has its own shape property. The associated view provider class does the update of the view representation so that inside your Python code you don't have to worry about this anymore.

Here a fully working example:

Code: Select all


import FreeCAD, FreeCADGui, Part
from pivy import coin

class PartFeature:
	def __init__(self, obj):
		obj.Proxy = self

class Box(PartFeature):
	def __init__(self, obj):
		PartFeature.__init__(self, obj)
		''' Add some custom properties to our box feature '''
		obj.addProperty("App::PropertyLength","Length","Box","Length of the box").Length=1.0
		obj.addProperty("App::PropertyLength","Width","Box","Width of the box").Width=1.0
		obj.addProperty("App::PropertyLength","Height","Box", "Height of the box").Height=1.0

	def onChanged(self, fp, prop):
		''' Print the name of the property that has changed '''
		FreeCAD.Console.PrintMessage("Change property: " + str(prop) + "\n")
		if prop == "Length" or prop == "Width" or prop == "Height":
			fp.Shape = Part.makeBox(fp.Length,fp.Width,fp.Height)

	def execute(self, fp):
		''' Print a short message when doing a recomputation, this method is mandatory '''
		FreeCAD.Console.PrintMessage("Recompute Python Box feature\n")
		fp.Shape = Part.makeBox(fp.Length,fp.Width,fp.Height)

class ViewProviderBox:
	def __init__(self, obj):
		''' Set this object to the proxy object of the actual view provider '''
		obj.Proxy = self

	def attach(self, obj):
		''' Setup the scene sub-graph of the view provider, this method is mandatory '''
		return

	def updateData(self, fp, prop):
		''' If a property of the handled feature has changed we have the chance to handle this here '''
		return

	def getDisplayModes(self,obj):
		''' Return a list of display modes. '''
		modes=[]
		return modes

	def getDefaultDisplayMode(self):
		''' Return the name of the default display mode. It must be defined in getDisplayModes. '''
		return "Shaded"

	def setDisplayMode(self,mode):
		''' Map the display mode defined in attach with those defined in getDisplayModes.
		Since they have the same names nothing needs to be done. This method is optinal.
		'''
		return mode

	def onChanged(self, vp, prop):
		''' Print the name of the property that has changed '''
		FreeCAD.Console.PrintMessage("Change property: " + str(prop) + "\n")

	def getIcon(self):
		''' Return the icon in XMP format which will appear in the tree view. This method is optional
		and if not defined a default icon is shown.
		'''
		return """
			/* XPM */
			static const char * ViewProviderBox_xpm[] = {
			"16 16 6 1",
			" 	c None",
			".	c #141010",
			"+	c #615BD2",
			"@	c #C39D55",
			"#	c #000000",
			"$	c #57C355",
			"        ........",
			"   ......++..+..",
			"   .@@@@.++..++.",
			"   .@@@@.++..++.",
			"   .@@  .++++++.",
			"  ..@@  .++..++.",
			"###@@@@ .++..++.",
			"##$.@@$#.++++++.",
			"#$#$.$$$........",
			"#$$#######      ",
			"#$$#$$$$$#      ",
			"#$$#$$$$$#      ",
			"#$$#$$$$$#      ",
			" #$#$$$$$#      ",
			"  ##$$$$$#      ",
			"   #######      "};
			"""

	def __getstate__(self):
		''' When saving the document this object gets stored using Python's cPickle module.
		Since we have some un-pickable here -- the Coin stuff -- we must define this method
		to return a tuple of all pickable objects or None.
		'''
		return None

	def __setstate__(self,state):
		''' When restoring the pickled object from document we have the chance to set some
		internals here. Since no data were pickled nothing needs to be done here.
		'''
		return None


def makeBox():
	FreeCAD.newDocument()
	a=FreeCAD.ActiveDocument.addObject("Part::FeaturePython","Box")
	Box(a)
	ViewProviderBox(a.ViewObject)
Post Reply