Create workbench
This commit is contained in:
parent
866a20dd71
commit
caca713d8d
369
Gui/Resources/icons/Assembly_Move.svg
Normal file
369
Gui/Resources/icons/Assembly_Move.svg
Normal file
|
@ -0,0 +1,369 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="64px"
|
||||
height="64px"
|
||||
id="svg2963"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.48.5 r10040"
|
||||
sodipodi:docname="Draft_Move.svg"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape"
|
||||
version="1.1">
|
||||
<defs
|
||||
id="defs2965">
|
||||
<linearGradient
|
||||
id="linearGradient3354">
|
||||
<stop
|
||||
style="stop-color:#2157c7;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop3356" />
|
||||
<stop
|
||||
style="stop-color:#6daaff;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop3358" />
|
||||
</linearGradient>
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 32 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="64 : 32 : 1"
|
||||
inkscape:persp3d-origin="32 : 21.333333 : 1"
|
||||
id="perspective2971" />
|
||||
<linearGradient
|
||||
gradientTransform="matrix(0,-1.4500001,1.4705882,0,-15.05882,91.45)"
|
||||
y2="36.079998"
|
||||
x2="21.689653"
|
||||
y1="29.279999"
|
||||
x1="56.172409"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient3036"
|
||||
xlink:href="#linearGradient3895"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
id="linearGradient3895">
|
||||
<stop
|
||||
style="stop-color:#729fcf;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop3897" />
|
||||
<stop
|
||||
style="stop-color:#204a87;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop3899" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
y2="36.079998"
|
||||
x2="21.689653"
|
||||
y1="29.279999"
|
||||
x1="56.172409"
|
||||
gradientTransform="matrix(0,-0.58000003,0.58823527,0,13.176471,38.379999)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient3918-3"
|
||||
xlink:href="#linearGradient3895-6"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
id="linearGradient3895-6">
|
||||
<stop
|
||||
style="stop-color:#729fcf;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop3897-7" />
|
||||
<stop
|
||||
style="stop-color:#204a87;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop3899-5" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
y2="36.079998"
|
||||
x2="21.689653"
|
||||
y1="29.279999"
|
||||
x1="56.172409"
|
||||
gradientTransform="matrix(0.58000003,0,0,0.58823527,25.620001,13.176471)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient3029-6"
|
||||
xlink:href="#linearGradient3895-6-2"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
id="linearGradient3895-6-2">
|
||||
<stop
|
||||
style="stop-color:#729fcf;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop3897-7-9" />
|
||||
<stop
|
||||
style="stop-color:#204a87;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop3899-5-1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
y2="36.079998"
|
||||
x2="21.689653"
|
||||
y1="29.279999"
|
||||
x1="56.172409"
|
||||
gradientTransform="matrix(0,-0.58000003,0.58823527,0,13.176471,38.379999)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient3918-0"
|
||||
xlink:href="#linearGradient3895-9"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
id="linearGradient3895-9">
|
||||
<stop
|
||||
style="stop-color:#729fcf;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop3897-3" />
|
||||
<stop
|
||||
style="stop-color:#204a87;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop3899-6" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3895"
|
||||
id="linearGradient3154"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0,-0.58000003,0.58823527,0,13.176471,38.379999)"
|
||||
x1="45.482754"
|
||||
y1="11.599999"
|
||||
x2="-23.482759"
|
||||
y2="52.400002" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3895-6-2"
|
||||
id="linearGradient3156"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(-0.58000003,0,0,0.58823527,38.379999,13.176471)"
|
||||
x1="31.689651"
|
||||
y1="-2.0000007"
|
||||
x2="-9.6896563"
|
||||
y2="66" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3895-6"
|
||||
id="linearGradient3158"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.58000003,0,0,0.58823527,25.620001,13.176471)"
|
||||
x1="-9.6896563"
|
||||
y1="-2.0000007"
|
||||
x2="31.689651"
|
||||
y2="66" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3895-9"
|
||||
id="linearGradient3160"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0,0.58000003,0.58823527,0,13.176471,25.620001)"
|
||||
x1="-23.482759"
|
||||
y1="11.599999"
|
||||
x2="45.482754"
|
||||
y2="52.400002" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3895-9"
|
||||
id="linearGradient3936"
|
||||
x1="20"
|
||||
y1="12"
|
||||
x2="44"
|
||||
y2="52"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3895-9"
|
||||
id="linearGradient3944"
|
||||
x1="20"
|
||||
y1="12"
|
||||
x2="44"
|
||||
y2="52"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="10.193662"
|
||||
inkscape:cx="21.49082"
|
||||
inkscape:cy="36.860521"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:window-width="1600"
|
||||
inkscape:window-height="837"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:snap-global="true"
|
||||
inkscape:window-maximized="1">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid3009"
|
||||
empspacing="2"
|
||||
visible="true"
|
||||
enabled="true"
|
||||
snapvisiblegridlinesonly="true" />
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid3011"
|
||||
empspacing="2"
|
||||
visible="true"
|
||||
enabled="true"
|
||||
snapvisiblegridlinesonly="true"
|
||||
spacingx="16px"
|
||||
spacingy="16px"
|
||||
empcolor="#ff0000"
|
||||
empopacity="0.25098039"
|
||||
color="#ff0000"
|
||||
opacity="0.1254902" />
|
||||
</sodipodi:namedview>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer">
|
||||
<rect
|
||||
style="fill:url(#linearGradient3936);fill-opacity:1;stroke:none"
|
||||
id="rect3126"
|
||||
width="12"
|
||||
height="6"
|
||||
x="26"
|
||||
y="29" />
|
||||
<rect
|
||||
style="fill:url(#linearGradient3944);fill-opacity:1;stroke:none"
|
||||
id="rect3126-2"
|
||||
width="6"
|
||||
height="11.999999"
|
||||
x="29"
|
||||
y="26" />
|
||||
<g
|
||||
id="g4351"
|
||||
inkscape:export-filename="/home/yorik/Documents/Lab/Draft/icons/move.png"
|
||||
inkscape:export-xdpi="6.5591564"
|
||||
inkscape:export-ydpi="6.5591564"
|
||||
transform="matrix(0.1378133,0,0,0.1378133,-221.39699,-138.35275)" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:url(#linearGradient3154);fill-opacity:1;fill-rule:evenodd;stroke:#0b1521;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 37,28 0,-15 6,0 -11,-10 -11,10 6,0 0,15"
|
||||
id="path3343"
|
||||
sodipodi:nodetypes="ccccccc"
|
||||
inkscape:export-filename="/home/yorik/Documents/Lab/Draft/icons/changeprop.png"
|
||||
inkscape:export-xdpi="4.1683898"
|
||||
inkscape:export-ydpi="4.1683898" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:none;stroke:#729fcf;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="M 35,29 35,11 37.831259,11 32,5.7026937 26.168741,11 29,11 29,29"
|
||||
id="path3343-2"
|
||||
sodipodi:nodetypes="ccccccc"
|
||||
inkscape:export-filename="/home/yorik/Documents/Lab/Draft/icons/changeprop.png"
|
||||
inkscape:export-xdpi="4.1683898"
|
||||
inkscape:export-ydpi="4.1683898" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:url(#linearGradient3158);fill-opacity:1;fill-rule:evenodd;stroke:#0b1521;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 37,37 14,0 0,6 10,-11 -10,-11 0,6 -14,0"
|
||||
id="path3343-3"
|
||||
sodipodi:nodetypes="ccccccc"
|
||||
inkscape:export-filename="/home/yorik/Documents/Lab/Draft/icons/changeprop.png"
|
||||
inkscape:export-xdpi="4.1683898"
|
||||
inkscape:export-ydpi="4.1683898" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:none;stroke:#729fcf;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 35,35 18,0 0,2.831259 L 58.297306,32 53,26.168741 53,29 34,29"
|
||||
id="path3343-2-5"
|
||||
sodipodi:nodetypes="ccccccc"
|
||||
inkscape:export-filename="/home/yorik/Documents/Lab/Draft/icons/changeprop.png"
|
||||
inkscape:export-xdpi="4.1683898"
|
||||
inkscape:export-ydpi="4.1683898" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:url(#linearGradient3156);fill-opacity:1;fill-rule:evenodd;stroke:#0b1521;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 27,37 -14,0 0,6 -10,-11 10,-11 0,6 14,0"
|
||||
id="path3343-3-2"
|
||||
sodipodi:nodetypes="ccccccc"
|
||||
inkscape:export-filename="/home/yorik/Documents/Lab/Draft/icons/changeprop.png"
|
||||
inkscape:export-xdpi="4.1683898"
|
||||
inkscape:export-ydpi="4.1683898" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:none;stroke:#729fcf;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="M 29,35 11,35 11,37.831259 5.702694,32 11,26.168741 11,29 30,29"
|
||||
id="path3343-2-5-7"
|
||||
sodipodi:nodetypes="ccccccc"
|
||||
inkscape:export-filename="/home/yorik/Documents/Lab/Draft/icons/changeprop.png"
|
||||
inkscape:export-xdpi="4.1683898"
|
||||
inkscape:export-ydpi="4.1683898" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:url(#linearGradient3160);fill-opacity:1;fill-rule:evenodd;stroke:#0b1521;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 37,36 0,15 6,0 -11,10 -11,-10 6,0 0,-15"
|
||||
id="path3343-0"
|
||||
sodipodi:nodetypes="ccccccc"
|
||||
inkscape:export-filename="/home/yorik/Documents/Lab/Draft/icons/changeprop.png"
|
||||
inkscape:export-xdpi="4.1683898"
|
||||
inkscape:export-ydpi="4.1683898" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:none;stroke:#729fcf;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 35,34 0,19 2.831259,0 L 32,58.297306 26.168741,53 29,53 29,34"
|
||||
id="path3343-2-6"
|
||||
sodipodi:nodetypes="ccccccc"
|
||||
inkscape:export-filename="/home/yorik/Documents/Lab/Draft/icons/changeprop.png"
|
||||
inkscape:export-xdpi="4.1683898"
|
||||
inkscape:export-ydpi="4.1683898" />
|
||||
</g>
|
||||
<metadata
|
||||
id="metadata5006">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title>Draft_Move</dc:title>
|
||||
<cc:license
|
||||
rdf:resource="" />
|
||||
<dc:date>Mon Oct 10 13:44:52 2011 +0000</dc:date>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>[wmayer]</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:rights>
|
||||
<cc:Agent>
|
||||
<dc:title>FreeCAD LGPL2+</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:rights>
|
||||
<dc:publisher>
|
||||
<cc:Agent>
|
||||
<dc:title>FreeCAD</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:publisher>
|
||||
<dc:identifier>FreeCAD/src/Mod/Draft/Resources/icons/Draft_Move.svg</dc:identifier>
|
||||
<dc:relation>http://www.freecadweb.org/wiki/index.php?title=Artwork</dc:relation>
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title>[agryson] Alexander Gryson</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
<dc:subject>
|
||||
<rdf:Bag>
|
||||
<rdf:li>arrow</rdf:li>
|
||||
<rdf:li>move</rdf:li>
|
||||
<rdf:li>arrows</rdf:li>
|
||||
<rdf:li>compass</rdf:li>
|
||||
<rdf:li>cross</rdf:li>
|
||||
</rdf:Bag>
|
||||
</dc:subject>
|
||||
<dc:description>Four equally sized arrow heads at 90° to eachother, all joined at the tail</dc:description>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
</svg>
|
After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
27
InitGui.py
Normal file
27
InitGui.py
Normal file
|
@ -0,0 +1,27 @@
|
|||
import FreeCAD, FreeCADGui
|
||||
|
||||
class Assembly3Workbench(FreeCADGui.Workbench):
|
||||
import asm3
|
||||
MenuText = 'Assembly 3'
|
||||
Icon = asm3.utils.addIconToFCAD('AssemblyWorkbench.svg')
|
||||
|
||||
def Activated(self):
|
||||
import asm3
|
||||
asm3.constraint.Observer.attach()
|
||||
|
||||
def Deactivated(self):
|
||||
import asm3
|
||||
asm3.constraint.Observer.detach()
|
||||
|
||||
def Initialize(self):
|
||||
import asm3
|
||||
cmds = asm3.gui.AsmCmdType.getInfo().TypeNames
|
||||
asm3.utils.logger.debug(cmds)
|
||||
self.appendToolbar('asm3',cmds)
|
||||
self.appendMenu('&Assembly3', cmds)
|
||||
self.appendToolbar('asm3 Constraint',
|
||||
asm3.constraint.Constraint.CommandList)
|
||||
# FreeCADGui.addPreferencePage(
|
||||
# ':/assembly3/ui/assembly3_prefs.ui','Assembly3')
|
||||
|
||||
FreeCADGui.addWorkbench(Assembly3Workbench)
|
|
@ -1,5 +1,5 @@
|
|||
import FreeCAD, FreeCADGui, Part
|
||||
from asm3 import utils,assembly,solver,constraint,system
|
||||
from asm3 import proxy,utils,assembly,solver,constraint,system,gui
|
||||
from asm3.utils import logger
|
||||
from asm3.assembly import Assembly,AsmConstraint
|
||||
try:
|
||||
|
|
74
assembly.py
74
assembly.py
|
@ -121,6 +121,7 @@ class AsmPartGroup(AsmGroup):
|
|||
obj = parent.Document.addObject("App::FeaturePython",name,
|
||||
AsmPartGroup(parent),None,True)
|
||||
ViewProviderAsmPartGroup(obj.ViewObject)
|
||||
obj.purgeTouched()
|
||||
return obj
|
||||
|
||||
|
||||
|
@ -130,6 +131,11 @@ class ViewProviderAsmPartGroup(ViewProviderAsmBase):
|
|||
def onDelete(self,_obj,_subs):
|
||||
return False
|
||||
|
||||
def canDropObject(self,obj):
|
||||
return isTypeOf(obj,Assembly) or not isTypeOf(obj,AsmBase)
|
||||
|
||||
def canDropObjects(self):
|
||||
return True
|
||||
|
||||
class AsmElement(AsmBase):
|
||||
def __init__(self,parent):
|
||||
|
@ -373,7 +379,7 @@ class AsmElementLink(AsmBase):
|
|||
if not ret:
|
||||
# It is from a non assembly child part, then use our own element
|
||||
# group as the holder for elements
|
||||
ret = [Assembly.Selection(assembly.obj,owner,subname)]
|
||||
ret = [Assembly.Info(assembly.obj,owner,subname)]
|
||||
|
||||
if not isTypeOf(ret[-1].Object,AsmPartGroup):
|
||||
raise RuntimeError('Invalid element link ' + subname)
|
||||
|
@ -436,7 +442,8 @@ class AsmElementLink(AsmBase):
|
|||
if not isTypeOf(part,Assembly,True) and \
|
||||
not Constraint.isDisabled(self.parent.obj) and \
|
||||
not Constraint.isLocked(self.parent.obj):
|
||||
getter = getattr(part.getLinkedObject(True),'getLinkExtProperty')
|
||||
getter = getattr(part.getLinkedObject(True),
|
||||
'getLinkExtProperty',None)
|
||||
|
||||
# special treatment of link array (i.e. when ElementCount!=0), we
|
||||
# allow the array element to be moveable by the solver
|
||||
|
@ -543,6 +550,7 @@ class ViewProviderAsmElementLink(ViewProviderAsmBase):
|
|||
class AsmConstraint(AsmGroup):
|
||||
|
||||
def __init__(self,parent):
|
||||
self._initializing = True
|
||||
self.elements = None
|
||||
self.parent = getProxy(parent,AsmConstraintGroup)
|
||||
super(AsmConstraint,self).__init__()
|
||||
|
@ -585,8 +593,10 @@ class AsmConstraint(AsmGroup):
|
|||
obj.recompute()
|
||||
|
||||
def execute(self,_obj):
|
||||
self.checkSupport()
|
||||
self.getElements(True)
|
||||
if not getattr(self,'_initializing',False) and\
|
||||
getattr(self,'parent',None):
|
||||
self.checkSupport()
|
||||
self.getElements(True)
|
||||
return False
|
||||
|
||||
def getElements(self,refresh=False):
|
||||
|
@ -691,6 +701,8 @@ class AsmConstraint(AsmGroup):
|
|||
|
||||
for e in selection.Elements:
|
||||
AsmElementLink.make(AsmElementLink.MakeInfo(cstr,*e))
|
||||
cstr.Proxy._initializing = False
|
||||
cstr.recompute()
|
||||
return cstr
|
||||
|
||||
|
||||
|
@ -727,6 +739,7 @@ class AsmConstraintGroup(AsmGroup):
|
|||
obj = parent.Document.addObject("App::FeaturePython",name,
|
||||
AsmConstraintGroup(parent),None,True)
|
||||
ViewProviderAsmConstraintGroup(obj.ViewObject)
|
||||
obj.purgeTouched()
|
||||
return obj
|
||||
|
||||
|
||||
|
@ -750,6 +763,7 @@ class AsmElementGroup(AsmGroup):
|
|||
obj = parent.Document.addObject("App::FeaturePython",name,
|
||||
AsmElementGroup(parent),None,True)
|
||||
ViewProviderAsmElementGroup(obj.ViewObject)
|
||||
obj.purgeTouched()
|
||||
return obj
|
||||
|
||||
|
||||
|
@ -797,17 +811,23 @@ class Assembly(AsmGroup):
|
|||
System.touch(obj)
|
||||
return False # return False to call LinkBaseExtension::execute()
|
||||
|
||||
def onSolverChanged(self):
|
||||
def onSolverChanged(self,setup=False):
|
||||
for obj in self.getConstraintGroup().Group:
|
||||
# setup==True usually means we are restoring, so try to restore the
|
||||
# non-touched state if possible, since recompute() below will touch
|
||||
# the constraint object
|
||||
touched = not setup or 'Touched' in obj.State
|
||||
obj.recompute()
|
||||
if not touched:
|
||||
obj.purgeTouched()
|
||||
|
||||
def buildShape(self):
|
||||
import Part
|
||||
obj = self.obj
|
||||
if not obj.BuildShape:
|
||||
obj.Shape.nullify()
|
||||
if obj.BuildShape == BuildShapeNone:
|
||||
obj.Shape = Part.Shape()
|
||||
return
|
||||
|
||||
import Part
|
||||
shape = []
|
||||
partGroup = self.getPartGroup(obj)
|
||||
group = partGroup.Group
|
||||
|
@ -855,7 +875,8 @@ class Assembly(AsmGroup):
|
|||
# all groups exist. The order of the group is important to make sure
|
||||
# correct rendering and picking behavior
|
||||
self.getPartGroup(True)
|
||||
self.onSolverChanged()
|
||||
|
||||
self.onSolverChanged(True)
|
||||
|
||||
def onChanged(self, obj, prop):
|
||||
if prop == 'BuildShape':
|
||||
|
@ -958,10 +979,28 @@ class Assembly(AsmGroup):
|
|||
"Part::FeaturePython",name,Assembly(),None,True)
|
||||
ViewProviderAssembly(obj.ViewObject)
|
||||
obj.Visibility = True
|
||||
obj.purgeTouched()
|
||||
return obj
|
||||
|
||||
Info = namedtuple('AssemblyInfo',('Assembly','Object','Subname'))
|
||||
|
||||
@staticmethod
|
||||
def find(sels=None):
|
||||
'Find all assembly objects among the current selection'
|
||||
objs = set()
|
||||
if sels is None:
|
||||
sels = FreeCADGui.Selection.getSelectionEx('',False)
|
||||
for sel in sels:
|
||||
if not sel.SubElementNames:
|
||||
if isTypeOf(sel.Object,Assembly):
|
||||
objs.add(sel.Object)
|
||||
continue
|
||||
for subname in sel.SubElementNames:
|
||||
ret = Assembly.findChild(sel.Object,subname,recursive=True)
|
||||
if ret:
|
||||
objs.add(ret[-1].Assembly)
|
||||
return tuple(objs)
|
||||
|
||||
@staticmethod
|
||||
def findChild(obj,subname,childType=None,
|
||||
recursive=False,relativeToChild=True):
|
||||
|
@ -991,7 +1030,7 @@ class Assembly(AsmGroup):
|
|||
if isTypeOf(obj,Assembly,True):
|
||||
assembly = obj
|
||||
subs = subname if isinstance(subname,list) else subname.split('.')
|
||||
for i,name in enumerate(subs[:-2]):
|
||||
for i,name in enumerate(subs[:-1]):
|
||||
obj = obj.getSubObject(name+'.',1)
|
||||
if not obj:
|
||||
raise RuntimeError('Cannot find sub object {}'.format(name))
|
||||
|
@ -1043,12 +1082,21 @@ class ViewProviderAssembly(ViewProviderAsmGroup):
|
|||
def canDragObjects(self):
|
||||
return False
|
||||
|
||||
def canDropObject(self,_child):
|
||||
return False
|
||||
@property
|
||||
def PartGroup(self):
|
||||
return self.ViewObject.Object.Proxy.getPartGroup()
|
||||
|
||||
def canDropObject(self,obj):
|
||||
self.PartGroup.ViewObject.canDropObject(obj)
|
||||
|
||||
def canDropObjects(self):
|
||||
return False
|
||||
return True
|
||||
|
||||
def dropObjectEx(self,_vobj,obj,owner,subname):
|
||||
self.PartGroup.ViewObject.dropObject(obj,owner,subname)
|
||||
|
||||
def getIcon(self):
|
||||
return System.getIcon(self.ViewObject.Object)
|
||||
|
||||
|
||||
|
||||
|
|
124
constraint.py
124
constraint.py
|
@ -145,14 +145,83 @@ def _a(solver,partInfo,subname,shape):
|
|||
return _c(solver,partInfo,subname,shape,True)
|
||||
|
||||
|
||||
class ConstraintCommand:
|
||||
def __init__(self,tp):
|
||||
self.tp = tp
|
||||
|
||||
def GetResources(self):
|
||||
return self.tp.GetResources()
|
||||
|
||||
def Activated(self):
|
||||
from asm3.assembly import AsmConstraint
|
||||
AsmConstraint.make(self.tp._id)
|
||||
|
||||
def IsActive(self):
|
||||
return FreeCADGui.ActiveDocument and self.tp._active
|
||||
|
||||
class SelectionObserver:
|
||||
def __init__(self):
|
||||
self._attached = False
|
||||
|
||||
def onChanged(self):
|
||||
from asm3.assembly import AsmConstraint
|
||||
for cls in Constraint._cmdTypes:
|
||||
try:
|
||||
AsmConstraint.getSelection()
|
||||
except Exception as e:
|
||||
logger.trace('selection "{}" exception: {}'.format(
|
||||
cls.getName(),e.message),frame=1)
|
||||
cls._active = False
|
||||
else:
|
||||
cls._active = True
|
||||
|
||||
def addSelection(self,*_args):
|
||||
self.onChanged()
|
||||
|
||||
def removeSelection(self,*_args):
|
||||
self.onChanged()
|
||||
|
||||
def setSelection(self,*_args):
|
||||
self.onChanged()
|
||||
|
||||
def clearSelection(self,*_args):
|
||||
logger.trace('selection cleared')
|
||||
for cls in Constraint._cmdTypes:
|
||||
cls._active = False
|
||||
|
||||
def attach(self):
|
||||
if not self._attached:
|
||||
FreeCADGui.Selection.addObserver(self)
|
||||
self._attached = True
|
||||
self.onChanged()
|
||||
|
||||
def detach(self):
|
||||
if self._attached:
|
||||
FreeCADGui.Selection.removeObserver(self)
|
||||
self._attached = False
|
||||
self.clearSelection('')
|
||||
|
||||
Observer = SelectionObserver()
|
||||
|
||||
class Constraint(ProxyType):
|
||||
'constraint meta class'
|
||||
|
||||
_typeID = '_ConstraintType'
|
||||
_typeEnum = 'ConstraintType'
|
||||
|
||||
_disabled = 'Disabled'
|
||||
|
||||
CommandList = []
|
||||
_cmdTypes = []
|
||||
|
||||
def register(cls):
|
||||
super(Constraint,cls).register()
|
||||
if cls._menuItem:
|
||||
name = 'asm3Add'+cls.getName()
|
||||
mcs = cls.__class__
|
||||
mcs.CommandList.append(name)
|
||||
mcs._cmdTypes.append(cls)
|
||||
FreeCADGui.addCommand(name,ConstraintCommand(cls))
|
||||
|
||||
@classmethod
|
||||
def attach(mcs,obj,checkType=True):
|
||||
if checkType:
|
||||
|
@ -220,8 +289,12 @@ class Base(with_metaclass(Constraint,object)):
|
|||
_props = []
|
||||
_iconName = 'Assembly_ConstraintGeneral.svg'
|
||||
|
||||
_menuText = 'Add a "{}" constraint'
|
||||
_active = False
|
||||
_menuItem = False
|
||||
|
||||
def __init__(self,_obj):
|
||||
self._supported = True
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def getPropertyInfoList(cls):
|
||||
|
@ -295,10 +368,29 @@ class Base(with_metaclass(Constraint,object)):
|
|||
else:
|
||||
logger.warn('{} no constraint func'.format(cstrName(obj)))
|
||||
|
||||
@classmethod
|
||||
def getMenuText(cls):
|
||||
return cls._menuText.format(cls.getName())
|
||||
|
||||
@classmethod
|
||||
def getToolTip(cls):
|
||||
tooltip = getattr(cls,'_tooltip',None)
|
||||
if not tooltip:
|
||||
return cls.getMenuText()
|
||||
return tooltip.format(cls.getName())
|
||||
|
||||
@classmethod
|
||||
def GetResources(cls):
|
||||
return {'Pixmap':utils.addIconToFCAD(cls._iconName,_iconPath),
|
||||
'MenuText':cls.getMenuText(),
|
||||
'ToolTip':cls.getToolTip()}
|
||||
|
||||
|
||||
class Locked(Base):
|
||||
_id = 0
|
||||
_iconName = 'Assembly_ConstraintLock.svg'
|
||||
_menuItem = True
|
||||
_tooltip = 'Add a "{}" constraint to fix part(s)'
|
||||
|
||||
@classmethod
|
||||
def prepare(cls,obj,solver):
|
||||
|
@ -309,6 +401,7 @@ class Locked(Base):
|
|||
def check(cls,_group):
|
||||
pass
|
||||
|
||||
|
||||
class BaseMulti(Base):
|
||||
_id = -1
|
||||
_entityDef = (_wa,)
|
||||
|
@ -414,23 +507,36 @@ class PlaneCoincident(BaseCascade):
|
|||
_id = 35
|
||||
_iconName = 'Assembly_ConstraintCoincidence.svg'
|
||||
_props = ['Cascade','Offset']
|
||||
_menuItem = True
|
||||
_tooltip = \
|
||||
'Add a "{}" constraint to conincide planes of two or more parts.\n'\
|
||||
'The planes are coincided at their centers with an optional distance.'
|
||||
|
||||
|
||||
class PlaneAlignment(BaseCascade):
|
||||
_id = 37
|
||||
_iconName = 'Assembly_ConstraintAlignment.svg'
|
||||
_props = ['Cascade','Offset']
|
||||
_menuItem = True
|
||||
_tooltip = 'Add a "{}" constraint to rotate planes of two or more parts\n'\
|
||||
'into the same orientation'
|
||||
|
||||
|
||||
class AxialAlignment(BaseMulti):
|
||||
_id = 36
|
||||
_iconName = 'Assembly_ConstraintAxial.svg'
|
||||
_menuItem = True
|
||||
_tooltip = 'Add a "{}" constraint to align planes of two or more parts.\n'\
|
||||
'The planes are aligned at the direction of their surface normal axis.'
|
||||
|
||||
|
||||
class SameOrientation(BaseMulti):
|
||||
_id = 2
|
||||
_entityDef = (_n,)
|
||||
_iconName = 'Assembly_ConstraintOrientation.svg'
|
||||
_menuItem = True
|
||||
_tooltip = 'Add a "{}" constraint to align planes of two or more parts.\n'\
|
||||
'The planes are aligned to have the same orientation (i.e. rotation)'
|
||||
|
||||
|
||||
class Angle(Base):
|
||||
|
@ -439,6 +545,9 @@ class Angle(Base):
|
|||
_workplane = True
|
||||
_props = ["Angle","Supplement"]
|
||||
_iconName = 'Assembly_ConstraintAngle.svg'
|
||||
_menuItem = True
|
||||
_tooltip = 'Add a "{}" constraint to set the angle of planes or linear\n'\
|
||||
'edges of two parts.'
|
||||
|
||||
|
||||
class Perpendicular(Base):
|
||||
|
@ -446,19 +555,28 @@ class Perpendicular(Base):
|
|||
_entityDef = (_ln,_ln)
|
||||
_workplane = True
|
||||
_iconName = 'Assembly_ConstraintPerpendicular.svg'
|
||||
_menuItem = True
|
||||
_tooltip = 'Add a "{}" constraint to make planes or linear edges of two\n'\
|
||||
'parts perpendicular.'
|
||||
|
||||
|
||||
class Parallel(Base):
|
||||
_id = 29
|
||||
_id = -1
|
||||
_entityDef = (_ln,_ln)
|
||||
_workplane = True
|
||||
_iconName = 'Assembly_ConstraintParallel.svg'
|
||||
_menuItem = True
|
||||
_tooltip = 'Add a "{}" constraint to make planes or linear edges of two\n'\
|
||||
'parts parallel.'
|
||||
|
||||
|
||||
class MultiParallel(BaseMulti):
|
||||
_id = 291
|
||||
_entityDef = (_ln,)
|
||||
_iconName = 'Assembly_ConstraintMultiParallel.svg'
|
||||
_menuItem = True
|
||||
_tooltip = 'Add a "{}" constraint to make planes or linear edges of two\n'\
|
||||
'or more parts parallel.'
|
||||
|
||||
|
||||
class PointsCoincident(Base):
|
||||
|
|
67
gui.py
Normal file
67
gui.py
Normal file
|
@ -0,0 +1,67 @@
|
|||
from future.utils import with_metaclass
|
||||
import FreeCAD, FreeCADGui
|
||||
from asm3.utils import logger,objName,addIconToFCAD
|
||||
from asm3.assembly import Assembly,AsmConstraint
|
||||
from asm3.proxy import ProxyType
|
||||
|
||||
class AsmCmdType(ProxyType):
|
||||
def register(cls):
|
||||
super(AsmCmdType,cls).register()
|
||||
if cls._id >= 0:
|
||||
FreeCADGui.addCommand(cls.getName(),cls())
|
||||
|
||||
class AsmCmdBase(with_metaclass(AsmCmdType,object)):
|
||||
_id = -1
|
||||
_active = True
|
||||
|
||||
@classmethod
|
||||
def getName(cls):
|
||||
return 'asm3'+cls.__name__[3:]
|
||||
|
||||
@classmethod
|
||||
def GetResources(cls):
|
||||
return {
|
||||
'Pixmap':addIconToFCAD(cls._iconName),
|
||||
'MenuText':cls.getMenuText(),
|
||||
'ToolTip':cls.getToolTip()
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def getMenuText(cls):
|
||||
return cls._menuText
|
||||
|
||||
@classmethod
|
||||
def getToolTip(cls):
|
||||
return getattr(cls,'_tooltip',cls.getMenuText())
|
||||
|
||||
@classmethod
|
||||
def IsActive(cls):
|
||||
if FreeCAD.ActiveDocument and cls._active:
|
||||
return True
|
||||
|
||||
class AsmCmdNew(AsmCmdBase):
|
||||
_id = 0
|
||||
_menuText = 'Create a new assembly'
|
||||
_iconName = 'Assembly_New_Assembly.svg'
|
||||
|
||||
def Activated(self):
|
||||
Assembly.make()
|
||||
|
||||
class AsmCmdSolve(AsmCmdBase):
|
||||
_id = 1
|
||||
_menuText = 'Solve the constraints of assembly(s)'
|
||||
_iconName = 'AssemblyWorkbench.svg'
|
||||
|
||||
def Activated(self):
|
||||
import asm3.solver as solver
|
||||
solver.solve()
|
||||
|
||||
|
||||
class AsmCmdMove(AsmCmdBase):
|
||||
_id = 2
|
||||
_menuText = 'Move assembly'
|
||||
_iconName = 'Assembly_Move.svg'
|
||||
|
||||
def Activated(self):
|
||||
pass
|
||||
|
27
proxy.py
27
proxy.py
|
@ -9,6 +9,8 @@ def propGetValue(self,obj):
|
|||
return getattr(getattr(obj,self.Name),'Value')
|
||||
|
||||
class PropertyInfo(object):
|
||||
'For holding information to create dynamic properties'
|
||||
|
||||
def __init__(self,host,name,tp,doc='', enum=None,
|
||||
getter=propGet,group='Base',internal=False,duplicate=False):
|
||||
self.Name = name
|
||||
|
@ -21,9 +23,15 @@ class PropertyInfo(object):
|
|||
self.Key = host.addPropertyInfo(self,duplicate)
|
||||
|
||||
class ProxyType(type):
|
||||
'''
|
||||
Meta class for managing other "proxy" like classes whose instances can be
|
||||
dynamically attached to or detached from FCAD FeaturePython Proxy objects.
|
||||
In other word, it is meant for managing proxies of Proxies
|
||||
'''
|
||||
|
||||
_typeID = '_ProxyType'
|
||||
_typeEnum = 'ProxyType'
|
||||
_typeGroup = 'Base'
|
||||
_propGroup = 'Base'
|
||||
_proxyName = '_proxy'
|
||||
_registry = {}
|
||||
|
||||
|
@ -48,7 +56,7 @@ class ProxyType(type):
|
|||
for tp in info.Types:
|
||||
tp._idx = -1
|
||||
mcs.getInfo().Types.append(tp)
|
||||
mcs.register(tp)
|
||||
tp.register()
|
||||
|
||||
@classmethod
|
||||
def getType(mcs,tp):
|
||||
|
@ -99,8 +107,6 @@ class ProxyType(type):
|
|||
obj.addProperty(prop.Type,prop.Name,prop.Group,prop.Doc)
|
||||
if prop.Enum:
|
||||
setattr(obj,prop.Name,prop.Enum)
|
||||
else:
|
||||
obj.setPropertyStatus(prop.Name,'-Hidden')
|
||||
|
||||
setattr(obj.Proxy,mcs._proxyName,cls(obj))
|
||||
obj.ViewObject.signalChangeIcon()
|
||||
|
@ -114,7 +120,6 @@ class ProxyType(type):
|
|||
proxy.__class__.__name__))
|
||||
for key in proxy.getPropertyInfoList():
|
||||
prop = mcs.getPropertyInfo(key)
|
||||
# obj.setPropertyStatus(prop.Name,'Hidden')
|
||||
obj.removeProperty(prop.Name)
|
||||
callback = getattr(proxy,'onDetach',None)
|
||||
if callback:
|
||||
|
@ -143,14 +148,14 @@ class ProxyType(type):
|
|||
if checkType:
|
||||
if mcs._typeID not in obj.PropertiesList:
|
||||
obj.addProperty("App::PropertyInteger",
|
||||
mcs._typeID,mcs._typeGroup,'',0,False,True)
|
||||
mcs._typeID,mcs._propGroup,'',0,False,True)
|
||||
mcs.setDefaultTypeID(obj)
|
||||
|
||||
if mcs._typeEnum not in obj.PropertiesList:
|
||||
logger.debug('type enum {}, {}'.format(mcs._typeEnum,
|
||||
mcs._typeGroup))
|
||||
mcs._propGroup))
|
||||
obj.addProperty("App::PropertyEnumeration",
|
||||
mcs._typeEnum,mcs._typeGroup,'',2)
|
||||
mcs._typeEnum,mcs._propGroup,'',2)
|
||||
mcs.setTypeName(obj,info.TypeNames)
|
||||
|
||||
idx = 0
|
||||
|
@ -179,10 +184,9 @@ class ProxyType(type):
|
|||
cls._idx = -1
|
||||
mcs = cls.__class__
|
||||
mcs.getInfo().Types.append(cls)
|
||||
mcs.register(cls)
|
||||
cls.register()
|
||||
|
||||
@classmethod
|
||||
def register(mcs,cls):
|
||||
def register(cls):
|
||||
'''
|
||||
Register a class to this meta class
|
||||
|
||||
|
@ -193,6 +197,7 @@ class ProxyType(type):
|
|||
'''
|
||||
if cls._id < 0:
|
||||
return
|
||||
mcs = cls.__class__
|
||||
info = mcs.getInfo()
|
||||
if cls._id in info.TypeMap:
|
||||
raise RuntimeError('Duplicate {} type id {}'.format(
|
||||
|
|
31
solver.py
31
solver.py
|
@ -22,15 +22,10 @@ class Solver(object):
|
|||
self.system = System.getSystem(assembly)
|
||||
cstrs = assembly.Proxy.getConstraints()
|
||||
if not cstrs:
|
||||
self.system.log('no constraint found in assembly '
|
||||
logger.warn('no constraint found in assembly '
|
||||
'{}'.format(objName(assembly)))
|
||||
return
|
||||
|
||||
parts = assembly.Proxy.getPartGroup().Group
|
||||
if len(parts)<=1:
|
||||
self.system.log('not enough parts in {}'.format(objName(assembly)))
|
||||
return
|
||||
|
||||
self._fixedGroup = 2
|
||||
self.group = 1 # the solving group
|
||||
self._partMap = {}
|
||||
|
@ -41,16 +36,24 @@ class Solver(object):
|
|||
|
||||
self.system.GroupHandle = self._fixedGroup
|
||||
|
||||
firstPart = None
|
||||
firstPartName = None
|
||||
for cstr in cstrs:
|
||||
if Constraint.isLocked(cstr):
|
||||
Constraint.prepare(cstr,self)
|
||||
elif not Constraint.isDisabled(cstr) and \
|
||||
System.isConstraintSupported(
|
||||
assembly,Constraint.getTypeName(cstr)):
|
||||
if not firstPart:
|
||||
elements = cstr.Proxy.getElements()
|
||||
if elements:
|
||||
info = elements[0].Proxy.getInfo()
|
||||
firstPart = info.Part
|
||||
firstPartName = info.PartName
|
||||
self._cstrs.append(cstr)
|
||||
if not self._fixedParts:
|
||||
self.system.log('lock first part {}'.format(objName(parts[0])))
|
||||
self._fixedParts.add(parts[0])
|
||||
self.system.log('lock first part {}'.format(firstPartName))
|
||||
self._fixedParts.add(firstPart)
|
||||
|
||||
for cstr in self._cstrs:
|
||||
self.system.log('preparing {}'.format(cstrName(cstr)))
|
||||
|
@ -162,9 +165,17 @@ class Solver(object):
|
|||
self._partMap[info.Part] = partInfo
|
||||
return partInfo
|
||||
|
||||
def solve(objs=None,recursive=True,reportFailed=True,recompute=True):
|
||||
def solve(objs=None,recursive=None,reportFailed=True,recompute=True):
|
||||
if not objs:
|
||||
objs = FreeCAD.ActiveDocument.Objects
|
||||
sels = FreeCADGui.Selection.getSelectionEx('',False)
|
||||
if len(sels):
|
||||
objs = asm.Assembly.find()
|
||||
if not objs:
|
||||
raise RuntimeError('No assembly found in selection')
|
||||
else:
|
||||
objs = FreeCAD.ActiveDocument.Objects
|
||||
if recursive is None:
|
||||
recursive = True
|
||||
elif not isinstance(objs,(list,tuple)):
|
||||
objs = [objs]
|
||||
|
||||
|
|
|
@ -14,12 +14,12 @@ class _AlgoType(ProxyType):
|
|||
|
||||
_typeID = '_AlgorithmType'
|
||||
_typeEnum = 'AlgorithmType'
|
||||
_typeGroup = 'SolverAlgorithm'
|
||||
_propGroup = 'SolverAlgorithm'
|
||||
_proxyName = '_algo'
|
||||
|
||||
def _makeProp(name,doc='',tp='App::PropertyFloat',group=None):
|
||||
if not group:
|
||||
group = _AlgoType._typeGroup
|
||||
group = _AlgoType._propGroup
|
||||
info = PropertyInfo(_AlgoType,name,tp,doc,duplicate=True,group=group)
|
||||
return info.Key
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ class System(ProxyType):
|
|||
|
||||
_typeID = '_SolverType'
|
||||
_typeEnum = 'SolverType'
|
||||
_typeGroup = 'Solver'
|
||||
_propGroup = 'Solver'
|
||||
_iconName = 'Assembly_Assembly_Tree.svg'
|
||||
|
||||
@classmethod
|
||||
|
|
21
utils.py
21
utils.py
|
@ -5,6 +5,11 @@ Most of the functions are borrowed directly from assembly2lib.py or lib3D.py in
|
|||
assembly2
|
||||
'''
|
||||
|
||||
import FreeCAD, FreeCADGui, Part
|
||||
import numpy as np
|
||||
from asm3.FCADLogger import FCADLogger
|
||||
logger = FCADLogger('asm3')
|
||||
|
||||
import sys, os
|
||||
modulePath = os.path.dirname(os.path.realpath(__file__))
|
||||
|
||||
|
@ -29,12 +34,16 @@ def getIcon(obj,disabled=False,path=None):
|
|||
obj._iconDisabled = QIcon(pixmap)
|
||||
return obj._iconDisabled
|
||||
|
||||
|
||||
import FreeCAD, FreeCADGui, Part
|
||||
import numpy as np
|
||||
|
||||
import asm3.FCADLogger
|
||||
logger = asm3.FCADLogger.FCADLogger('assembly3')
|
||||
def addIconToFCAD(iconFile,path=None):
|
||||
iconName = ':asm3/icons/' + iconFile
|
||||
if not path:
|
||||
path = iconPath
|
||||
try:
|
||||
path = os.path.join(path,iconFile)
|
||||
FreeCADGui.addIcon(iconName,path)
|
||||
except AssertionError:
|
||||
pass
|
||||
return iconName
|
||||
|
||||
def objName(obj):
|
||||
if obj.Label == obj.Name:
|
||||
|
|
Loading…
Reference in New Issue
Block a user