Making Py. Feature Interoperate w/ Part Design Features

Need help, or want to share a macro? Post here!
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
Post Reply
User avatar
KurtF
Posts: 161
Joined: Fri Mar 04, 2022 7:36 pm
Location: North Carolina, US
Contact:

Making Py. Feature Interoperate w/ Part Design Features

Post by KurtF »

Hello FC professionals. I have a macro generating threads using FeatureAdditivePython when a PD Body is active. It works great, fusing itself to the basefeature, and behaving almost exactly like any other PD Geo. Primitive placed in a body the same way.

Except my macro doesn't know how to raise the PD Attach dialog during feature creation, like a PD primitive does. Also, the thread feature generates "getEditDialog() not implemented" error when dbl-clicked.

Is the PD attachment dialog (used when adding a PD geo. primitive) exposed to Python coders? And if not, can it be?

I can't find info anywhere on the getEditDialog error. Nor could I produce results by trying to implement that in my object class and my VP class (method isn't called). Is there a method for setting the EditDialog for my FeatureAdditivePython object, so that when it's dbl-clicked, it raises the PD attach dialog?

There's over 450 lines of code, so I'll only show the part related to packaging my feature:

Code: Select all

### Tail End of my PDThreadShaft.execute() Method, threadbody contains the result of Part.fuse(x) or Part.common(x) ###

        if hasattr(fp, "BaseFeature") and fp.BaseFeature != None:		# Implied Active PDBody when invoked.
            threadbody.transformShape(fp.Placement.toMatrix(), True)		# now threadbody moved twice; basef moved once
            full_shape = fp.BaseFeature.Shape.fuse(threadbody,0.001)	# fuse fails if tolerance <= 0.0008 (or if removeSplitter() applied first)
            full_shape.transformShape(fp.Placement.inverse().toMatrix(), True)	# now fused shape put back
            fp.Shape = Part.makeSolid(full_shape).removeSplitter()
        else:	# no base feature
            fp.Shape = Part.makeSolid(threadbody).removeSplitter()

        #It is the shape used for copying in pattern features
        if fp.TypeId != "Part::FeaturePython":
            threadbody.transformShape(fp.Placement.inverse().toMatrix(), True)
            fp.AddSubShape = Part.makeSolid(threadbody)


### Main Method ###
	activebody = FreeCADGui.ActiveDocument.ActiveView.getActiveObject("pdbody")
	if activebody:
		# Store shape in new PartDesign::FeatureAdditivePython object
		FreeCAD.ActiveDocument.openTransaction("Make Thread Shaft")
		a = FreeCAD.ActiveDocument.addObject("PartDesign::FeatureAdditivePython", "ThreadExt", None, None, False)
		FreeCAD.ActiveDocument.commitTransaction()
		PDThreadShaft(a, speclist)			# Build Thread object
		PDThreadShaftVP(a.ViewObject)		# Build View Provider
		activebody.addObject(a)
#		a.MapMode = 'FlatFace'
#		a.Support = [(FreeCAD.ActiveDocument.getObject('XY_Plane001'),'')]
	else:
		FreeCAD.ActiveDocument.openTransaction("Make Thread Shaft")
		a = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "ThreadExt", None, None, False)
		FreeCAD.ActiveDocument.commitTransaction()
		PDThreadShaft(a, speclist)			# Build Thread object
		PDThreadShaftVP(a.ViewObject)		# Build View Provider
		a.setEditorMode('Placement', 0) #non-readonly non-hidden
Last edited by KurtF on Tue May 17, 2022 4:00 pm, edited 1 time in total.
May whatever Higher Power you believe in bless the Ukrainians. They are a decent people who never hurt anybody.
wmayer
Founder
Posts: 20243
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: getEditDialog Not Implemented with PD::FeatureAdditivePython

Post by wmayer »

Except my macro doesn't know how to raise the PD Attach dialog during feature creation, like a PD primitive does.
This is a way to show the attachment dialog:

Code: Select all

from AttachmentEditor import Commands

obj=App.ActiveDocument.addObject("PartDesign::FeatureAdditivePython", "Object")
Commands.editAttachment(obj)
Also, the thread feature generates "getEditDialog() not implemented" error when dbl-clicked.
To make this working you have to implement a proxy view provider that implements the setEdit function. Inside there you call Commands.editAttachment.
User avatar
KurtF
Posts: 161
Joined: Fri Mar 04, 2022 7:36 pm
Location: North Carolina, US
Contact:

Re: getEditDialog Not Implemented with PD::FeatureAdditivePython

Post by KurtF »

Awesome. Thanks, Mr. Meyer. AttachmentEditor part sounds straightforward, and I need to go off and learn more about what a Proxy class really does, then I'll tackle the second part of your suggestion.

Hopefully, when I get through this project, I'll have a nice set of class templates to share for scripted objects which integrate seamlessly into PDWB when a body is active; else integrate seamlessly into Part WB.

Btw- I've been snooping around in your TemplatePyMod directory on Git. Thanks for that!
May whatever Higher Power you believe in bless the Ukrainians. They are a decent people who never hurt anybody.
User avatar
KurtF
Posts: 161
Joined: Fri Mar 04, 2022 7:36 pm
Location: North Carolina, US
Contact:

Making Py. Feature Interoperate w/ Part Design Features

Post by KurtF »

I've changed the title of this post because my original question is specific to the larger problem I'm still trying to solve. I'm writing my first FC macro, which builds a solid, and I want to make sure mine is a good, little FC solid: behaving like and interoperating with all the other FC solids. In short: "works and plays well with others". So I'm looking for a good FC Psychiatrist. :-)

This is easy to accomplish for Part WB objects; but seems more mysterious for PD objects. When my macro runs with a PD Body activated,
it needs to:

* Package the Shape in FeatureAdditivePython object (allows interoperability with array functions).
* Launch Attach dialog just like adding at PD Primitive does to attach shape to basefeature.
* Fuses itself to existing Body base feature and becomes new Tip.
* Enter attach dialog when Shape is dbl-clicked, just like a PD Primitive.

Thanks to wmeyer's help above, I got the 2nd bullet working, though there is one small glitch. When my code runs editAttachent(), while inside the attachment dialog, I cannot select the base feature or it's faces to attach to. Yet when adding a PD Primitive, it's attachment dialog allows selection of the base feature to attach to.

Code: Select all

	if activebody:
		FreeCAD.ActiveDocument.openTransaction("Make Thread Shaft")
		a = FreeCAD.ActiveDocument.addObject("PartDesign::FeatureAdditivePython", "ThreadExt", None, None, False)
		FreeCAD.ActiveDocument.commitTransaction()
		PDThreadShaft(a, speclist)			# Build Thread object
		PDThreadShaftVP(a.ViewObject)		# Build View Provider
		activebody.addObject(a)
		Commands.editAttachment(a)		# Attach dialog
I never had trouble with the 3rd bullet, but the 4th bullet is still out of my reach. I don't yet know how to follow wmayer's advice on this (how to implement proxy VP).

I'm about to go snooping through FC code on my hard drive in search of "official" PartDesign Primitive handling samples. But if anyone help me out on the glitch and the 4th bullet, I'd be grateful.

EDIT: I just remembered I can see what PD Primitives are doing in the Py Console. I'm pouring through that output now (adding PD Primitive to Active Body Basefeature).
May whatever Higher Power you believe in bless the Ukrainians. They are a decent people who never hurt anybody.
User avatar
KurtF
Posts: 161
Joined: Fri Mar 04, 2022 7:36 pm
Location: North Carolina, US
Contact:

Re: Making Py. Feature Interoperate w/ Part Design Features

Post by KurtF »

After some more research, I made more progress following wmayer's advice, adding this to my VP:

Code: Select all

	def setEdit(self, vp, mode):
#					callback_Cancel=None, callback_Apply=None)
		Commands.editAttachment(self)		# Attach dialog
Now on dbl-click, it's asking me to implement getEditorMode in my VP, which I will research and attempt to apply.

But in my research last night, I discovered this macro, which fits my quest for compatibility perfectly. It is a macro designed specifically to package a Python feature into a fully interoperable PD Body member solid. Clearly, my objective wasn't gonna be achieved with a few added code snippets. Here is that macro: https://wiki.freecad.org/Macro_PDWrapper

The original guidance I was following is inadequate to it's stated goal, and should probably be updated (like with a link to the 'majic pd macro'). That guidance is here: https://wiki.freecad.org/Scripted_objec ... ed_objects

It seems that when you package a python feature with Part::FeaturePython, you inherit all the properties and methods necessary for working well with Part WB. But if you attempt compatibility with PD WB, and package the python feature with PartDesign::FeatureAdditivePython, you don't inherit much, and need to add an additional 1,542 lines of code (from macro) in order to equal the compatibility of Part::FeauterPython.

But I have 2 problems with this macro: one is adding 1,542 lines of code to a 550 line program which works great as a Part WB object. Other problem is duplication of code which is intimately tied to internal code. If FC Developer team decides to change the internals of PD features, maybe macro code will break.

Would it be useful, and would it promote improved Part Design integration and reduced help requests from scripters, if the PartDesign::FeatureXxxxxx object shells included all the mappings being made by the macro?
May whatever Higher Power you believe in bless the Ukrainians. They are a decent people who never hurt anybody.
Post Reply