Added stock creation.

This commit is contained in:
Markus Lampert
2017-09-02 14:50:29 -07:00
committed by wmayer
parent f4ee27458f
commit b778882f76
5 changed files with 633 additions and 94 deletions

View File

@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>400</width>
<height>608</height>
<height>924</height>
</rect>
</property>
<property name="windowTitle">
@@ -24,7 +24,7 @@
<item>
<widget class="QToolBox" name="tbGeneral">
<property name="currentIndex">
<number>0</number>
<number>1</number>
</property>
<widget class="QWidget" name="page">
<property name="geometry">
@@ -226,67 +226,184 @@
<x>0</x>
<y>0</y>
<width>378</width>
<height>403</height>
<height>719</height>
</rect>
</property>
<attribute name="label">
<string>Layout</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_5">
<layout class="QVBoxLayout" name="verticalLayout_7">
<item>
<widget class="QGroupBox" name="stockGroup">
<property name="title">
<string>Stock</string>
</property>
<layout class="QGridLayout" name="gridLayout_8">
<item row="1" column="1">
<widget class="QLabel" name="stockExtXLabel">
<property name="text">
<string>Ext. X</string>
<layout class="QVBoxLayout" name="verticalLayout_5">
<property name="spacing">
<number>0</number>
</property>
<item>
<widget class="QComboBox" name="stock">
<property name="currentIndex">
<number>2</number>
</property>
<item>
<property name="text">
<string>Create Box</string>
</property>
</item>
<item>
<property name="text">
<string>Create Cylinder</string>
</property>
</item>
<item>
<property name="text">
<string>Extend Base Bound Box</string>
</property>
</item>
<item>
<property name="text">
<string>Use Existing</string>
</property>
</item>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="stockExtYLabel">
<property name="text">
<string>Ext. Y</string>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>6</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QFrame" name="stockFromExisting">
<layout class="QGridLayout" name="gridLayout_8">
<item row="0" column="1">
<widget class="QComboBox" name="stockExisting"/>
</item>
</layout>
</widget>
</item>
<item row="1" column="4">
<widget class="Gui::InputField" name="stockExtXPlus">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<widget class="QFrame" name="stockFromBase">
<layout class="QGridLayout" name="gridLayout_9">
<item row="1" column="3">
<widget class="Gui::InputField" name="stockExtYpos"/>
</item>
<item row="0" column="1">
<widget class="QLabel" name="stockExtXLabel">
<property name="text">
<string>Ext. X</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="Gui::InputField" name="stockExtXpos">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="stockExtYLabel">
<property name="text">
<string>Ext. Y</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="Gui::InputField" name="stockExtXneg"/>
</item>
<item row="2" column="1">
<widget class="QLabel" name="stockExtZLabel">
<property name="text">
<string>Ext. Z</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="Gui::InputField" name="stockExtZneg"/>
</item>
<item row="2" column="3">
<widget class="Gui::InputField" name="stockExtZpos"/>
</item>
<item row="1" column="2">
<widget class="Gui::InputField" name="stockExtYneg"/>
</item>
</layout>
</widget>
</item>
<item row="1" column="3">
<widget class="Gui::InputField" name="stockExtXMinus"/>
</item>
<item row="3" column="1">
<widget class="QLabel" name="stockExtZLabel">
<property name="text">
<string>Ext. Z</string>
</property>
<item>
<widget class="QFrame" name="stockCreateCylinder">
<layout class="QGridLayout" name="gridLayout_10">
<item row="0" column="2">
<widget class="Gui::InputField" name="stockCylinderRadius"/>
</item>
<item row="1" column="2">
<widget class="Gui::InputField" name="stockCylinderHeight"/>
</item>
<item row="0" column="1">
<widget class="QLabel" name="stockCylinderRadiusLabel">
<property name="text">
<string>Radius</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="stockCylinderHeightLabel">
<property name="text">
<string>Height</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="3" column="3">
<widget class="Gui::InputField" name="stockExtZMinus"/>
</item>
<item row="2" column="3">
<widget class="Gui::InputField" name="stockExtYMinus"/>
</item>
<item row="2" column="4">
<widget class="Gui::InputField" name="stockExtYPlus"/>
</item>
<item row="3" column="4">
<widget class="Gui::InputField" name="stockExtZPlus"/>
</item>
<item row="0" column="1" colspan="4">
<widget class="QComboBox" name="comboBox"/>
<item>
<widget class="QFrame" name="stockCreateBox">
<layout class="QGridLayout" name="gridLayout_11">
<item row="0" column="1">
<widget class="QLabel" name="stockBoxLengthLabel">
<property name="text">
<string>Length</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="stockBoxWidthLabel">
<property name="text">
<string>Width</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="Gui::InputField" name="stockBoxLength"/>
</item>
<item row="2" column="2">
<widget class="Gui::InputField" name="stockBoxHeight"/>
</item>
<item row="1" column="2">
<widget class="Gui::InputField" name="stockBoxWidth"/>
</item>
<item row="2" column="1">
<widget class="QLabel" name="stockBoxHeightLabel">
<property name="text">
<string>Height</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
@@ -612,7 +729,7 @@
<item>
<widget class="QToolBox" name="toolBox_2">
<property name="currentIndex">
<number>1</number>
<number>0</number>
</property>
<widget class="QWidget" name="page_9">
<property name="geometry">
@@ -862,6 +979,63 @@
<header>Gui/InputField.h</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>infoLabel</tabstop>
<tabstop>infoModel</tabstop>
<tabstop>infoMaterial</tabstop>
<tabstop>stock</tabstop>
<tabstop>stockExisting</tabstop>
<tabstop>stockExtXneg</tabstop>
<tabstop>stockExtXpos</tabstop>
<tabstop>stockExtYneg</tabstop>
<tabstop>stockExtYpos</tabstop>
<tabstop>stockExtZneg</tabstop>
<tabstop>stockExtZpos</tabstop>
<tabstop>stockCylinderRadius</tabstop>
<tabstop>stockCylinderHeight</tabstop>
<tabstop>stockBoxLength</tabstop>
<tabstop>stockBoxWidth</tabstop>
<tabstop>stockBoxHeight</tabstop>
<tabstop>orientXAxis</tabstop>
<tabstop>orientYAxis</tabstop>
<tabstop>orientZAxis</tabstop>
<tabstop>setOrigin</tabstop>
<tabstop>moveToOrigin</tabstop>
<tabstop>centerInStock</tabstop>
<tabstop>centerInStockXY</tabstop>
<tabstop>postProcessorOutputFile</tabstop>
<tabstop>postProcessorSetOutputFile</tabstop>
<tabstop>postProcessor</tabstop>
<tabstop>postProcessorArguments</tabstop>
<tabstop>templateDefaultValues</tabstop>
<tabstop>templatePostProcessor</tabstop>
<tabstop>buttonBox</tabstop>
<tabstop>templateGeneral</tabstop>
<tabstop>templateMaterial</tabstop>
<tabstop>templateSetup</tabstop>
<tabstop>templateStock</tabstop>
<tabstop>templateOperations</tabstop>
<tabstop>templateTools</tabstop>
<tabstop>toolControllerList</tabstop>
<tabstop>toolControllerEdit</tabstop>
<tabstop>toolControllerAdd</tabstop>
<tabstop>toolControllerDelete</tabstop>
<tabstop>activeToolController</tabstop>
<tabstop>operationsList</tabstop>
<tabstop>operationEdit</tabstop>
<tabstop>operationDelete</tabstop>
<tabstop>groupBox_5</tabstop>
<tabstop>defaultSafeHeight</tabstop>
<tabstop>defaultClearanceHeight</tabstop>
<tabstop>groupBox_6</tabstop>
<tabstop>defaultStepDown</tabstop>
<tabstop>groupBox</tabstop>
<tabstop>lineEdit</tabstop>
<tabstop>lineEdit_2</tabstop>
<tabstop>groupBox_7</tabstop>
<tabstop>defaultMillingOp</tabstop>
<tabstop>defaultToolCompensation</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

View File

@@ -27,6 +27,7 @@ import Draft
import FreeCAD
import PathScripts.PathIconViewProvider as PathIconViewProvider
import PathScripts.PathLog as PathLog
import PathScripts.PathStock as PathStock
import PathScripts.PathToolController as PathToolController
import PathScripts.PathUtil as PathUtil
import xml.etree.ElementTree as xml
@@ -58,6 +59,24 @@ class JobTemplate:
Description = 'desc'
ToolController = 'ToolController'
def isResourceClone(obj, propName, resourceName):
'''isResourceClone(obj, propName, resourceName) ... Return True if the given property of obj is a clone of type resourceName.'''
if hasattr(obj, propName):
propLink = getattr(obj, propName)
if hasattr(propLink, 'PathResource') and resourceName == propLink.PathResource:
return True
return False
def createResourceClone(obj, orig, name, icon):
clone = Draft.clone(orig)
clone.Label = "%s-%s" % (name, orig.Label)
clone.addProperty('App::PropertyString', 'PathResource')
clone.PathResource = name
if clone.ViewObject:
PathIconViewProvider.ViewProvider(clone.ViewObject, icon)
clone.ViewObject.Visibility = False
return clone
class ObjectJob:
def __init__(self, obj, base, template = None):
@@ -91,10 +110,14 @@ class ObjectJob:
obj.setEditorMode('Operations', 2) # hide
obj.setEditorMode('Placement', 2)
self.createResourceClone(obj, base, 'Base')
obj.Base = createResourceClone(obj, base, 'Base', 'BaseGeometry')
obj.Proxy = self
self.assignTemplate(obj, template)
if not obj.Stock:
obj.Stock = PathStock.CreateFromBase(obj)
if obj.Stock.ViewObject:
obj.Stock.ViewObject.Visibility = False
def onDelete(self, obj, arg2=None):
'''Called by the view provider, there doesn't seem to be a callback on the obj itself.'''
@@ -115,36 +138,18 @@ class ObjectJob:
doc.removeObject(obj.Stock.Name)
obj.Stock = None
def isResourceClone(self, obj, propName, resourceName):
if hasattr(obj, propName):
propLink = getattr(obj, propName)
if hasattr(propLink, 'PathResource') and resourceName == propLink.PathResource:
return True
return False
def createResourceClone(self, obj, orig, name):
clone = Draft.clone(orig)
clone.Label = "%s-%s" % (name, orig.Label)
clone.addProperty('App::PropertyString', 'PathResource')
clone.PathResource = name
if clone.ViewObject:
PathIconViewProvider.ViewProvider(clone.ViewObject, 'BaseGeometry')
clone.ViewObject.Visibility = False
setattr(obj, name, clone)
def fixupResourceClone(self, obj, name):
if not self.isResourceClone(obj, name, name):
def fixupResourceClone(self, obj, name, icon):
if not isResourceClone(obj, name, name):
orig = getattr(obj, name)
if orig:
self.createResourceClone(obj, orig, name)
setattr(obj, name, createResourceClone(obj, orig, name, icon))
def onDocumentRestored(self, obj):
self.fixupResourceClone(obj, 'Base')
self.fixupResourceClone(obj, 'Stock')
self.fixupResourceClone(obj, 'Base', 'BaseGeometry')
def baseObject(self, obj):
'''Return the base object, not its clone.'''
if self.isResourceClone(obj, 'Base', 'Base'):
if isResourceClone(obj, 'Base', 'Base'):
return obj.Base.Objects[0]
return obj.Base

View File

@@ -28,8 +28,10 @@ import FreeCAD
import FreeCADGui
import PathScripts.PathJob as PathJob
import PathScripts.PathLog as PathLog
import PathScripts.PathStock as PathStock
import PathScripts.PathToolController as PathToolController
import PathScripts.PathToolLibraryManager as PathToolLibraryManager
import PathScripts.PathUtil as PathUtil
import math
import sys
@@ -104,6 +106,223 @@ class ViewProvider:
self.obj.Proxy.onDelete(self.obj, arg2)
return True
class StockEdit(object):
def __init__(self, obj, form):
self.obj = obj
self.form = form
self.setupUi(obj)
def activate(self, obj, select = False):
PathLog.track(obj.Label, select)
def showHide(widget, activeWidget):
if widget == activeWidget:
widget.show()
else:
widget.hide()
if select:
self.form.stock.setCurrentIndex(self.Index)
editor = self.editorFrame()
showHide(self.form.stockFromExisting, editor)
showHide(self.form.stockFromBase, editor)
showHide(self.form.stockCreateBox, editor)
showHide(self.form.stockCreateCylinder, editor)
self.setFields(obj)
def setStock(self, obj, stock):
if obj.Stock:
obj.Document.removeObject(self.obj.Stock.Name)
obj.Stock = stock
def setLengthField(self, widget, prop):
widget.setText(FreeCAD.Units.Quantity(prop.Value, FreeCAD.Units.Length).UserString)
class StockFromBaseBoundBoxEdit(StockEdit):
Index = 2
StockType = 'FromBase'
@classmethod
def IsStock(cls, obj):
return hasattr(obj.Stock, 'ExtXneg') and hasattr(obj.Stock, 'ExtZpos')
def editorFrame(self):
return self.form.stockFromBase
def getFields(self, obj, fields = ['xneg', 'xpos', 'yneg', 'ypos', 'zneg', 'zpos']):
PathLog.track(obj.Label, fields)
if self.IsStock(obj):
if 'xneg' in fields:
obj.Stock.ExtXneg = FreeCAD.Units.Quantity(self.form.stockExtXneg.text())
if 'xpos' in fields:
obj.Stock.ExtXpos = FreeCAD.Units.Quantity(self.form.stockExtXpos.text())
if 'yneg' in fields:
obj.Stock.ExtYneg = FreeCAD.Units.Quantity(self.form.stockExtYneg.text())
if 'ypos' in fields:
obj.Stock.ExtYpos = FreeCAD.Units.Quantity(self.form.stockExtYpos.text())
if 'zneg' in fields:
obj.Stock.ExtZneg = FreeCAD.Units.Quantity(self.form.stockExtZneg.text())
if 'zpos' in fields:
obj.Stock.ExtZpos = FreeCAD.Units.Quantity(self.form.stockExtZpos.text())
else:
PathLog.error(translate('PathJob', 'Stock not from Base bound box!'))
def setFields(self, obj):
if not self.IsStock(obj):
self.setStock(obj, PathStock.CreateFromBase(obj))
self.setLengthField(self.form.stockExtXneg, obj.Stock.ExtXneg)
self.setLengthField(self.form.stockExtXpos, obj.Stock.ExtXpos)
self.setLengthField(self.form.stockExtYneg, obj.Stock.ExtYneg)
self.setLengthField(self.form.stockExtYpos, obj.Stock.ExtYpos)
self.setLengthField(self.form.stockExtZneg, obj.Stock.ExtZneg)
self.setLengthField(self.form.stockExtZpos, obj.Stock.ExtZpos)
def setupUi(self, obj):
self.setFields(obj)
self.checkXpos()
self.checkYpos()
self.checkZpos()
self.form.stockExtXneg.editingFinished.connect(self.updateXpos)
self.form.stockExtYneg.editingFinished.connect(self.updateYpos)
self.form.stockExtZneg.editingFinished.connect(self.updateZpos)
self.form.stockExtXpos.editingFinished.connect(self.checkXpos)
self.form.stockExtYpos.editingFinished.connect(self.checkYpos)
self.form.stockExtZpos.editingFinished.connect(self.checkZpos)
def checkXpos(self):
self.trackXpos = self.form.stockExtXneg.text() == self.form.stockExtXpos.text()
self.getFields(self.obj, ['xpos'])
def checkYpos(self):
self.trackYpos = self.form.stockExtYneg.text() == self.form.stockExtYpos.text()
self.getFields(self.obj, ['ypos'])
def checkZpos(self):
self.trackZpos = self.form.stockExtZneg.text() == self.form.stockExtZpos.text()
self.getFields(self.obj, ['zpos'])
def updateXpos(self):
fields = ['xneg']
if self.trackXpos:
self.form.stockExtXpos.setText(self.form.stockExtXneg.text())
fields.append('xpos')
self.getFields(self.obj, fields)
def updateYpos(self):
fields = ['yneg']
if self.trackYpos:
self.form.stockExtYpos.setText(self.form.stockExtYneg.text())
fields.append('ypos')
self.getFields(self.obj, fields)
def updateZpos(self):
fields = ['zneg']
if self.trackZpos:
self.form.stockExtZpos.setText(self.form.stockExtZneg.text())
fields.append('zpos')
self.getFields(self.obj, fields)
class StockCreateBoxEdit(StockEdit):
Index = 0
StockType = 'CreateBox'
@classmethod
def IsStock(cls, obj):
return hasattr(obj.Stock, 'Length') and hasattr(obj.Stock, 'Width') and hasattr(obj.Stock, 'Height') and not StockFromBaseBoundBoxEdit.IsStock(obj)
def editorFrame(self):
return self.form.stockCreateBox
def getFields(self, obj, fields = ['length', 'widht', 'height']):
if self.IsStock(obj):
if 'length' in fields:
obj.Stock.Length = FreeCAD.Units.Quantity(self.form.stockBoxLength.text())
if 'width' in fields:
obj.Stock.Width = FreeCAD.Units.Quantity(self.form.stockBoxWidth.text())
if 'height' in fields:
obj.Stock.Height = FreeCAD.Units.Quantity(self.form.stockBoxHeight.text())
else:
PathLog.error(translate('PathJob', 'Stock not a box!'))
def setFields(self, obj):
if not self.IsStock(obj):
self.setStock(obj, PathStock.CreateBox(obj))
self.setLengthField(self.form.stockBoxLength, obj.Stock.Length)
self.setLengthField(self.form.stockBoxWidth, obj.Stock.Width)
self.setLengthField(self.form.stockBoxHeight, obj.Stock.Height)
def setupUi(self, obj):
self.setFields(obj)
self.form.stockBoxLength.editingFinished.connect(lambda: self.getFields(obj, ['length']))
self.form.stockBoxWidth.editingFinished.connect(lambda: self.getFields(obj, ['width']))
self.form.stockBoxHeight.editingFinished.connect(lambda: self.getFields(obj, ['height']))
class StockCreateCylinderEdit(StockEdit):
Index = 1
@classmethod
def IsStock(cls, obj):
return hasattr(obj.Stock, 'Radius') and hasattr(obj.Stock, 'Height')
def editorFrame(self):
return self.form.stockCreateCylinder
def getFields(self, obj, fields = ['radius', 'height']):
if self.IsStock(obj):
if 'radius' in fields:
obj.Stock.Radius = FreeCAD.Units.Quantity(self.form.stockCylinderRadius.text())
if 'height' in fields:
obj.Stock.Height = FreeCAD.Units.Quantity(self.form.stockCylinderHeight.text())
else:
PathLog.error(translate('PathJob', 'Stock not a cylinder!'))
def setFields(self, obj):
if not self.IsStock(obj):
self.setStock(obj, PathStock.CreateCylinder(obj))
self.setLengthField(self.form.stockCylinderRadius, obj.Stock.Radius)
self.setLengthField(self.form.stockCylinderHeight, obj.Stock.Height)
def setupUi(self, obj):
self.setFields(obj)
self.form.stockCylinderRadius.editingFinished.connect(lambda: self.getFields(obj, ['radius']))
self.form.stockCylinderHeight.editingFinished.connect(lambda: self.getFields(obj, ['height']))
class StockFromExistingEdit(StockEdit):
Index = 3
def IsStock(cls, obj):
return PathJob.isResourceClone(obj, 'Stock', 'Stock')
def editorFrame(self):
return self.form.stockFromExisting
def getFields(self, obj):
stock = self.form.stockExisting.itemData(self.form.stockExisting.currentIndex())
if not (hasattr(obj.Stock, 'Objects') and len(obj.Stock.Objects) == 1 and obj.Stock.Objects[0] == stock):
if stock:
stock = PathJob.createResourceClone(obj, stock, 'Stock', 'Stock')
stock.ViewObject.Visibility = True
PathStock.SetupStockObject(stock, False)
stock.Proxy.execute(stock)
self.setStock(obj, stock)
def setFields(self, obj):
candidates = [o for o in obj.Document.Objects if PathUtil.isSolid(o)]
candidates.remove(obj.Base)
if PathJob.isResourceClone(obj, 'Stock', 'Stock'):
candidates.remove(obj.Stock)
stockName = obj.Stock.Label if obj.Stock else None
self.form.stockExisting.clear()
index = -1
for i, c in enumerate(candidates):
self.form.stockExisting.addItem(c.Label, c)
if c.Label == stockName:
index = i
self.form.stockExisting.setCurrentIndex(index if index != -1 else 0)
if not self.IsStock(obj):
self.getFields(obj)
def setupUi(self, obj):
self.setFields(obj)
self.form.stockExisting.currentIndexChanged.connect(lambda: self.getFields(obj))
class TaskPanel:
DataObject = QtCore.Qt.ItemDataRole.UserRole
DataProperty = QtCore.Qt.ItemDataRole.UserRole + 1
@@ -144,6 +363,17 @@ class TaskPanel:
self.baseVisibility = self.obj.Base.ViewObject.Visibility
self.baseObjectSaveVisibility(self.obj)
self.stockVisibility = False
if self.obj.Stock and self.obj.Stock.ViewObject:
self.stockVisibility = self.obj.Stock.ViewObject.Visibility
self.obj.Stock.ViewObject.Visibility = True
self.stockFromBase = None
self.stockFromExisting = None
self.stockCreateBox = None
self.stockCreateCylinder = None
self.stockEdit = None
def baseObjectViewObject(self, obj):
base = obj.Proxy.baseObject(obj)
body = base.getParentGeoFeatureGroup()
@@ -165,6 +395,8 @@ class TaskPanel:
if self.obj.Base and self.obj.Base.ViewObject:
self.obj.Base.ViewObject.Visibility = self.baseVisibility
self.baseObjectRestoreVisibility(self.obj)
if self.obj.Stock and self.obj.Stock.ViewObject:
self.obj.Stock.ViewObject.Visibility = self.stockVisibility
def accept(self, resetEdit=True):
PathLog.track()
@@ -222,8 +454,8 @@ class TaskPanel:
self.baseObjectSaveVisibility(self.obj)
self.updateTooltips()
self.obj.Proxy.execute(self.obj)
self.stockEdit.getFields(self.obj)
self.obj.Proxy.execute(self.obj)
def selectComboBoxText(self, widget, text):
index = widget.findText(text, QtCore.Qt.MatchFixedString)
@@ -316,6 +548,8 @@ class TaskPanel:
self.form.infoModel.setCurrentIndex(baseindex)
self.updateToolController()
self.stockEdit.setFields(self.obj)
def setPostProcessorOutputFile(self):
filename = QtGui.QFileDialog.getSaveFileName(self.form, translate("Path_Job", "Select Output File"), None, translate("Path_Job", "All Files (*.*)"))
@@ -501,7 +735,58 @@ class TaskPanel:
self.form.orientGroup.setEnabled(False)
self.form.alignGroup.setEnabled(False)
def updateStockEditor(self, index):
PathLog.track(self.obj.Label, index)
def setupFromBaseEdit():
PathLog.track()
if not self.stockFromBase:
self.stockFromBase = StockFromBaseBoundBoxEdit(self.obj, self.form)
self.stockEdit = self.stockFromBase
def setupCreateBoxEdit():
PathLog.track()
if not self.stockCreateBox:
self.stockCreateBox = StockCreateBoxEdit(self.obj, self.form)
self.stockEdit = self.stockCreateBox
def setupCreateCylinderEdit():
PathLog.track()
if not self.stockCreateCylinder:
self.stockCreateCylinder = StockCreateCylinderEdit(self.obj, self.form)
self.stockEdit = self.stockCreateCylinder
def setupFromExisting():
PathLog.track()
if not self.stockFromExisting:
self.stockFromExisting = StockFromExistingEdit(self.obj, self.form)
self.stockEdit = self.stockFromExisting
if index == -1:
PathLog.track('wtf')
if self.obj.Stock is None or StockFromBaseBoundBoxEdit.IsStock(self.obj):
setupFromBaseEdit()
elif StockCreateBoxEdit.IsStock(self.obj):
setupCreateBoxEdit()
elif StockCreateCylinderEdit.IsStock(self.obj):
setupCreateCylinderEdit()
elif StockFromExistingEdit.IsStock(self.obj):
setupFromExisting()
else:
PathLog.error(translate('PathJob', "Unsupported stock object %s") % self.obj.Stock.Label)
else:
PathLog.track(self.obj.Label, index)
if index == StockFromBaseBoundBoxEdit.Index:
setupFromBaseEdit()
elif index == StockCreateBoxEdit.Index:
setupCreateBoxEdit()
elif index == StockCreateCylinderEdit.Index:
setupCreateCylinderEdit()
elif index == StockFromExistingEdit.Index:
setupFromExisting()
else:
PathLog.error(translate('PathJob', "Unsupported stock type %s (%d)") % (self.form.stock.currentText(), index))
self.stockEdit.activate(self.obj, index == -1)
def setupUi(self):
self.updateStockEditor(-1)
self.setFields()
# Info
@@ -528,10 +813,11 @@ class TaskPanel:
self.toolControllerSelect()
# Stock, Orientation and Alignment
self.form.stockGroup.hide()
self.form.centerInStock.hide()
self.form.centerInStockXY.hide()
self.form.stock.currentIndexChanged.connect(self.updateStockEditor)
self.form.orientXAxis.clicked.connect(lambda: self.orientSelected(FreeCAD.Vector(1, 0, 0)))
self.form.orientYAxis.clicked.connect(lambda: self.orientSelected(FreeCAD.Vector(0, 1, 0)))
self.form.orientZAxis.clicked.connect(lambda: self.orientSelected(FreeCAD.Vector(0, 0, 1)))

View File

@@ -24,23 +24,36 @@
import FreeCAD
import FreeCADGui
from FreeCAD import Vector
from PySide import QtCore, QtGui
import Part
import PathIconViewProvider
from PySide import QtCore
# Qt tanslation handling
def translate(context, text, disambig=None):
return QtCore.QCoreApplication.translate(context, text, disambig)
class Stock:
class StockFromBase:
def __init__(self, obj):
def __init__(self, obj, base):
"Make stock"
obj.addProperty("App::PropertyFloat","Length_Allowance","Stock",QtCore.QT_TRANSLATE_NOOP("App::Property","extra allowance from part width")).Length_Allowance = 1.0
obj.addProperty("App::PropertyFloat","Width_Allowance","Stock",QtCore.QT_TRANSLATE_NOOP("App::Property","extra allowance from part width")).Width_Allowance = 1.0
obj.addProperty("App::PropertyFloat","Height_Allowance","Stock",QtCore.QT_TRANSLATE_NOOP("App::Property","extra allowance from part width")).Height_Allowance = 1.0
obj.addProperty("App::PropertyLink","Base","Base",QtCore.QT_TRANSLATE_NOOP("App::Property","The base object this represents"))
obj.addProperty("App::PropertyLink", "Base", "Base", QtCore.QT_TRANSLATE_NOOP("PathStock", "The base object this stock is derived from"))
obj.addProperty("App::PropertyLength", "ExtXneg", "Stock", QtCore.QT_TRANSLATE_NOOP("PathStock", "Extra allowance from part bound box in negative X direction"))
obj.addProperty("App::PropertyLength", "ExtXpos", "Stock", QtCore.QT_TRANSLATE_NOOP("PathStock", "Extra allowance from part bound box in positive X direction"))
obj.addProperty("App::PropertyLength", "ExtYneg", "Stock", QtCore.QT_TRANSLATE_NOOP("PathStock", "Extra allowance from part bound box in negative Y direction"))
obj.addProperty("App::PropertyLength", "ExtYpos", "Stock", QtCore.QT_TRANSLATE_NOOP("PathStock", "Extra allowance from part bound box in positive Y direction"))
obj.addProperty("App::PropertyLength", "ExtZneg", "Stock", QtCore.QT_TRANSLATE_NOOP("PathStock", "Extra allowance from part bound box in negative Z direction"))
obj.addProperty("App::PropertyLength", "ExtZpos", "Stock", QtCore.QT_TRANSLATE_NOOP("PathStock", "Extra allowance from part bound box in positive Z direction"))
obj.Base = base
obj.ExtXneg= 1.0
obj.ExtXpos= 1.0
obj.ExtYneg= 1.0
obj.ExtYpos= 1.0
obj.ExtZneg= 1.0
obj.ExtZpos= 1.0
obj.Proxy = self
def __getstate__(self):
@@ -50,23 +63,70 @@ class Stock:
return None
def execute(self, obj):
self.Xmin = obj.Base.Shape.BoundBox.XMin
self.Xmax = obj.Base.Shape.BoundBox.XMax
bb = obj.Base.Shape.BoundBox
self.Ymin = obj.Base.Shape.BoundBox.YMin
self.Ymax = obj.Base.Shape.BoundBox.YMax
origin = FreeCAD.Vector(bb.XMin, bb.YMin, bb.ZMin)
self.origin = origin - FreeCAD.Vector(obj.ExtXneg.Value, obj.ExtYneg.Value, obj.ExtZneg.Value)
self.Zmin = obj.Base.Shape.BoundBox.ZMin
self.Zmax = obj.Base.Shape.BoundBox.ZMax
self.length = bb.XLength + obj.ExtXneg.Value + obj.ExtXpos.Value
self.width = bb.YLength + obj.ExtYneg.Value + obj.ExtYpos.Value
self.height = bb.ZLength + obj.ExtZneg.Value + obj.ExtZpos.Value
self.length = self.Xmax - self.Xmin + obj.Length_Allowance * 2.0
self.width = self.Ymax - self.Ymin + obj.Width_Allowance * 2.0
self.height = self.Zmax - self.Zmin + obj.Height_Allowance * 2.0
self.pnt = Vector(self.Xmin - obj.Length_Allowance, self.Ymin -
obj.Width_Allowance, self.Zmin - obj.Height_Allowance)
obj.Shape = Part.makeBox(self.length, self.width, self.height, self.origin)
obj.Shape = Part.makeBox(
self.length, self.width, self.height, self.pnt)
def SetupStockObject(obj, addVPProxy):
if FreeCAD.GuiUp and obj.ViewObject:
if addVPProxy:
PathIconViewProvider.ViewProvider(obj.ViewObject, 'Stock')
obj.ViewObject.Transparency = 90
obj.ViewObject.DisplayMode = 'Wireframe'
def CreateFromBase(job):
obj = FreeCAD.ActiveDocument.addObject('Part::FeaturePython', 'Stock')
proxy = StockFromBase(obj, job.Base)
SetupStockObject(obj, True)
proxy.execute(obj)
obj.purgeTouched()
return obj
def CreateBox(job, extent=None, at=None):
obj = FreeCAD.ActiveDocument.addObject('Part::Box', 'Stock')
if extent:
obj.Length = extent.x
obj.Width = extent.y
obj.Height = extent.z
elif job.Base:
bb = job.Base.Shape.BoundBox
obj.Length = bb.XLength
obj.Width = bb.YLength
obj.Height = bb.ZLength
if at:
obj.Placement = FreeCAD.Placement(at, FreeCAD.Vector(), 0)
else:
bb = job.Base.Shape.BoundBox
origin = FreeCAD.Vector(bb.XMin, bb.YMin, bb.ZMin)
obj.Placement = FreeCAD.Placement(origin, FreeCAD.Vector(), 0)
SetupStockObject(obj, False)
return obj
def CreateCylinder(job, radius=None, height=None, at=None):
obj = FreeCAD.ActiveDocument.addObject('Part::Cylinder', 'Stock')
if radius:
obj.Radius = radius
if height:
obj.Height = height
elif job.Base:
bb = job.Base.Shape.BoundBox
obj.Radius = max(bb.XLength, bb.YLength) * 0.7072 # 1/sqrt(2)
obj.Height = bb.ZLength
if at:
obj.Placement = FreeCAD.Placement(at, FreeCAD.Vector(), 0)
else:
bb = job.Base.Shape.BoundBox
origin = FreeCAD.Vector((bb.XMin + bb.XMax)/2, (bb.YMin + bb.YMax)/2, bb.ZMin)
obj.Placement = FreeCAD.Placement(origin, FreeCAD.Vector(), 0)
SetupStockObject(obj, False)
return obj
class _ViewProviderStock:

View File

@@ -37,9 +37,9 @@ import PathScripts.PathLog as PathLog
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
NotValidBaseTypeIds = ['Sketcher::SketchObject']
def isValidBaseObject(obj):
'''isSolid(obj) ... returns true if an object represents a solid.'''
def isValidBaseObject(obj):
'''isValidBaseObject(obj) ... returns true if the object can be used as a base for a job.'''
if not hasattr(obj, 'Shape'):
return False
if obj.TypeId in NotValidBaseTypeIds:
@@ -48,9 +48,23 @@ def isValidBaseObject(obj):
return False
return True
def isSolid(obj):
'''isSolid(obj) ... return True if the object is a valid solid.'''
if hasattr(obj, 'Tip'):
return isSolid(obj.Tip)
if hasattr(obj, 'Shape'):
if obj.Shape.ShapeType == 'Solid' and obj.Shape.isClosed():
return True
if obj.Shape.ShapeType == 'Compound':
if hasattr(obj, 'Base') and hasattr(obj, 'Tool'):
return isSolid(obj.Base) and isSolid(obj.Tool)
return False
def toolControllerForOp(op):
if hasattr(op, 'ToolController'):
return op.ToolController
if hasattr(op, 'Base'):
return toolControllerForOp(op.Base)
return None