PathBoundary editor filled with life.
This commit is contained in:
@@ -15,7 +15,7 @@
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="boundaryGroup">
|
||||
<widget class="QGroupBox" name="stockGroup">
|
||||
<property name="title">
|
||||
<string>Boundary Body</string>
|
||||
</property>
|
||||
@@ -27,7 +27,7 @@
|
||||
<widget class="QWidget" name="widget_2" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<item>
|
||||
<widget class="QComboBox" name="boundary">
|
||||
<widget class="QComboBox" name="stock">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
@@ -76,29 +76,29 @@
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="boundaryFromExisting">
|
||||
<widget class="QFrame" name="stockFromExisting">
|
||||
<layout class="QGridLayout" name="gridLayout_8">
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="boundaryExisting"/>
|
||||
<widget class="QComboBox" name="stockExisting"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="boundaryFromBase">
|
||||
<widget class="QFrame" name="stockFromBase">
|
||||
<layout class="QGridLayout" name="gridLayout_9">
|
||||
<item row="1" column="3">
|
||||
<widget class="Gui::InputField" name="boundaryExtYpos"/>
|
||||
<widget class="Gui::InputField" name="stockExtYpos"/>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="boundaryExtXLabel">
|
||||
<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="boundaryExtXpos">
|
||||
<widget class="Gui::InputField" name="stockExtXpos">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
@@ -108,52 +108,52 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="boundaryExtYLabel">
|
||||
<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="boundaryExtXneg"/>
|
||||
<widget class="Gui::InputField" name="stockExtXneg"/>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="boundaryExtZLabel">
|
||||
<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="boundaryExtZneg"/>
|
||||
<widget class="Gui::InputField" name="stockExtZneg"/>
|
||||
</item>
|
||||
<item row="2" column="3">
|
||||
<widget class="Gui::InputField" name="boundaryExtZpos"/>
|
||||
<widget class="Gui::InputField" name="stockExtZpos"/>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="Gui::InputField" name="boundaryExtYneg"/>
|
||||
<widget class="Gui::InputField" name="stockExtYneg"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="boundaryCreateCylinder">
|
||||
<widget class="QFrame" name="stockCreateCylinder">
|
||||
<layout class="QGridLayout" name="gridLayout_10">
|
||||
<item row="0" column="2">
|
||||
<widget class="Gui::InputField" name="boundaryCylinderRadius"/>
|
||||
<widget class="Gui::InputField" name="stockCylinderRadius"/>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="Gui::InputField" name="boundaryCylinderHeight"/>
|
||||
<widget class="Gui::InputField" name="stockCylinderHeight"/>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="boundaryCylinderRadiusLabel">
|
||||
<widget class="QLabel" name="stockCylinderRadiusLabel">
|
||||
<property name="text">
|
||||
<string>Radius</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="boundaryCylinderHeightLabel">
|
||||
<widget class="QLabel" name="stockCylinderHeightLabel">
|
||||
<property name="text">
|
||||
<string>Height</string>
|
||||
</property>
|
||||
@@ -163,33 +163,33 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="boundaryCreateBox">
|
||||
<widget class="QFrame" name="stockCreateBox">
|
||||
<layout class="QGridLayout" name="gridLayout_11">
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="boundaryBoxLengthLabel">
|
||||
<widget class="QLabel" name="stockBoxLengthLabel">
|
||||
<property name="text">
|
||||
<string>Length</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="boundaryBoxWidthLabel">
|
||||
<widget class="QLabel" name="stockBoxWidthLabel">
|
||||
<property name="text">
|
||||
<string>Width</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="Gui::InputField" name="boundaryBoxLength"/>
|
||||
<widget class="Gui::InputField" name="stockBoxLength"/>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="Gui::InputField" name="boundaryBoxHeight"/>
|
||||
<widget class="Gui::InputField" name="stockBoxHeight"/>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="Gui::InputField" name="boundaryBoxWidth"/>
|
||||
<widget class="Gui::InputField" name="stockBoxWidth"/>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="boundaryBoxHeightLabel">
|
||||
<widget class="QLabel" name="stockBoxHeightLabel">
|
||||
<property name="text">
|
||||
<string>Height</string>
|
||||
</property>
|
||||
@@ -202,7 +202,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="boundaryInside">
|
||||
<widget class="QCheckBox" name="stockInside">
|
||||
<property name="text">
|
||||
<string>Constrained to Inside</string>
|
||||
</property>
|
||||
|
||||
@@ -32,8 +32,8 @@ import PathScripts.PathUtils as PathUtils
|
||||
|
||||
from PySide import QtCore
|
||||
|
||||
PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule())
|
||||
PathLog.trackModule(PathLog.thisModule())
|
||||
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
|
||||
#PathLog.trackModule(PathLog.thisModule())
|
||||
|
||||
def _vstr(v):
|
||||
if v:
|
||||
@@ -45,8 +45,8 @@ class DressupPathBoundary(object):
|
||||
def __init__(self, obj, base, job):
|
||||
obj.addProperty("App::PropertyLink", "Base", "Base", QtCore.QT_TRANSLATE_NOOP("Path_DressupPathBoundary", "The base path to modify"))
|
||||
obj.Base = base
|
||||
obj.addProperty("App::PropertyLink", "Boundary", "Boundary", QtCore.QT_TRANSLATE_NOOP("Path_DressupPathBoundary", "Solid object to be used to limit the generated Path."))
|
||||
obj.Boundary = PathStock.CreateFromBase(job)
|
||||
obj.addProperty("App::PropertyLink", "Stock", "Boundary", QtCore.QT_TRANSLATE_NOOP("Path_DressupPathBoundary", "Solid object to be used to limit the generated Path."))
|
||||
obj.Stock = PathStock.CreateFromBase(job)
|
||||
obj.addProperty("App::PropertyBool", "Inside", "Boundary", QtCore.QT_TRANSLATE_NOOP("Path_DressupPathBoundary", "Determines if Boundary describes an inclusion or exclusion mask."))
|
||||
obj.Inside = True
|
||||
|
||||
@@ -63,9 +63,16 @@ class DressupPathBoundary(object):
|
||||
self.obj = obj
|
||||
|
||||
def onDelete(self, obj, args):
|
||||
if obj.Boundary:
|
||||
obj.Document.removeObject(obj.Boundary.Name)
|
||||
obj.Boundary = None
|
||||
if obj.Base:
|
||||
job = PathUtils.findParentJob(obj)
|
||||
job.Proxy.addOperation(obj.Base, obj)
|
||||
if obj.Base.ViewObject:
|
||||
ob.Base.ViewObject.Visibility = True
|
||||
obj.Base = None
|
||||
if obj.Stock:
|
||||
obj.Document.removeObject(obj.Stock.Name)
|
||||
obj.Stock = None
|
||||
return True
|
||||
|
||||
def boundaryCommands(self, obj, begin, end):
|
||||
PathLog.track(_vstr(begin), _vstr(end))
|
||||
@@ -92,7 +99,7 @@ class DressupPathBoundary(object):
|
||||
self.safeHeight = float(PathUtil.opProperty(obj.Base, 'SafeHeight'))
|
||||
self.clearanceHeight = float(PathUtil.opProperty(obj.Base, 'ClearanceHeight'))
|
||||
|
||||
boundary = obj.Boundary.Shape
|
||||
boundary = obj.Stock.Shape
|
||||
cmd = obj.Base.Path.Commands[0]
|
||||
pos = cmd.Placement.Base
|
||||
commands = [cmd]
|
||||
@@ -124,7 +131,7 @@ class DressupPathBoundary(object):
|
||||
pos = PathGeom.commandEndPoint(cmd, pos)
|
||||
else:
|
||||
PathLog.track(_vstr(pos), _vstr(lastExit), len(inside), len(outside), cmd)
|
||||
# cmd pierces Boundary
|
||||
# cmd pierces boundary
|
||||
while inside or outside:
|
||||
ie = [e for e in inside if PathGeom.edgeConnectsTo(e, pos)]
|
||||
PathLog.track(ie)
|
||||
@@ -188,5 +195,5 @@ def Create(base, name='DressupPathBoundary'):
|
||||
obj = FreeCAD.ActiveDocument.addObject('Path::FeaturePython', name)
|
||||
job = PathUtils.findParentJob(base)
|
||||
obj.Proxy = DressupPathBoundary(obj, base, job)
|
||||
job.Proxy.addOperation(obj, base)
|
||||
job.Proxy.addOperation(obj, base, True)
|
||||
return obj
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
import FreeCAD
|
||||
import FreeCADGui
|
||||
import PathScripts.PathDressupPathBoundary as PathDressupPathBoundary
|
||||
import PathScripts.PathJobGui as PathJobGui
|
||||
import PathScripts.PathLog as PathLog
|
||||
|
||||
from PySide import QtGui, QtCore
|
||||
@@ -42,12 +43,26 @@ class TaskPanel(object):
|
||||
self.obj = obj
|
||||
self.viewProvider = viewProvider
|
||||
self.form = FreeCADGui.PySideUic.loadUi(':/panels/DressupPathBoundary.ui')
|
||||
self.visibilityBase = obj.Base.ViewObject.Visibility if obj.Base else None
|
||||
self.visibilityBoundary = obj.Boundary.ViewObject.Visibility if obj.Boundary else None
|
||||
if obj.Stock:
|
||||
self.visibilityBoundary = obj.Stock.ViewObject.Visibility
|
||||
obj.Stock.ViewObject.Visibility = True
|
||||
else:
|
||||
self.visibilityBoundary = False
|
||||
|
||||
self.stockFromBase = None
|
||||
self.stockFromExisting = None
|
||||
self.stockCreateBox = None
|
||||
self.stockCreateCylinder = None
|
||||
self.stockEdit = None
|
||||
|
||||
def getStandardButtons(self):
|
||||
return int(QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Apply | QtGui.QDialogButtonBox.Cancel)
|
||||
|
||||
def clicked(self, button):
|
||||
# callback for standard buttons
|
||||
if button == QtGui.QDialogButtonBox.Apply:
|
||||
self.obj.Proxy.execute(self.obj)
|
||||
|
||||
def abort(self):
|
||||
FreeCAD.ActiveDocument.abortTransaction()
|
||||
self.cleanup(False)
|
||||
@@ -69,18 +84,74 @@ class TaskPanel(object):
|
||||
FreeCADGui.ActiveDocument.resetEdit()
|
||||
FreeCADGui.Control.closeDialog()
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
if self.obj.Base:
|
||||
self.obj.Base.ViewObject.Visibility = self.visibilityBase
|
||||
if self.obj.Boundary:
|
||||
self.obj.Boundary.ViewObject.Visibility = self.visibilityBoundary
|
||||
if self.obj.Stock:
|
||||
self.obj.Stock.ViewObject.Visibility = self.visibilityBoundary
|
||||
|
||||
def getFields(self):
|
||||
pass
|
||||
def setFields(self):
|
||||
pass
|
||||
|
||||
def updateStockEditor(self, index, force=False):
|
||||
import PathScripts.PathStock as PathStock
|
||||
|
||||
def setupFromBaseEdit():
|
||||
PathLog.track(index, force)
|
||||
if force or not self.stockFromBase:
|
||||
self.stockFromBase = PathJobGui.StockFromBaseBoundBoxEdit(self.obj, self.form, force)
|
||||
self.stockEdit = self.stockFromBase
|
||||
|
||||
def setupCreateBoxEdit():
|
||||
PathLog.track(index, force)
|
||||
if force or not self.stockCreateBox:
|
||||
self.stockCreateBox = PathJobGui.StockCreateBoxEdit(self.obj, self.form, force)
|
||||
self.stockEdit = self.stockCreateBox
|
||||
|
||||
def setupCreateCylinderEdit():
|
||||
PathLog.track(index, force)
|
||||
if force or not self.stockCreateCylinder:
|
||||
self.stockCreateCylinder = PathJobGui.StockCreateCylinderEdit(self.obj, self.form, force)
|
||||
self.stockEdit = self.stockCreateCylinder
|
||||
|
||||
def setupFromExisting():
|
||||
PathLog.track(index, force)
|
||||
if force or not self.stockFromExisting:
|
||||
self.stockFromExisting = PathJobGui.StockFromExistingEdit(self.obj, self.form, force)
|
||||
if self.stockFromExisting.candidates(self.obj):
|
||||
self.stockEdit = self.stockFromExisting
|
||||
return True
|
||||
return False
|
||||
|
||||
if index == -1:
|
||||
if self.obj.Stock is None or PathJobGui.StockFromBaseBoundBoxEdit.IsStock(self.obj):
|
||||
setupFromBaseEdit()
|
||||
elif PathJobGui.StockCreateBoxEdit.IsStock(self.obj):
|
||||
setupCreateBoxEdit()
|
||||
elif PathJobGui.StockCreateCylinderEdit.IsStock(self.obj):
|
||||
setupCreateCylinderEdit()
|
||||
elif PathJobGui.StockFromExistingEdit.IsStock(self.obj):
|
||||
setupFromExisting()
|
||||
else:
|
||||
PathLog.error(translate('PathJob', "Unsupported stock object %s") % self.obj.Stock.Label)
|
||||
else:
|
||||
if index == PathJobGui.StockFromBaseBoundBoxEdit.Index:
|
||||
setupFromBaseEdit()
|
||||
elif index == PathJobGui.StockCreateBoxEdit.Index:
|
||||
setupCreateBoxEdit()
|
||||
elif index == PathJobGui.StockCreateCylinderEdit.Index:
|
||||
setupCreateCylinderEdit()
|
||||
elif index == PathJobGui.StockFromExistingEdit.Index:
|
||||
if not setupFromExisting():
|
||||
setupFromBaseEdit()
|
||||
index = -1
|
||||
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):
|
||||
pass
|
||||
self.updateStockEditor(-1, False)
|
||||
|
||||
self.form.stock.currentIndexChanged.connect(self.updateStockEditor)
|
||||
|
||||
|
||||
class DressupPathBoundaryViewProvider(object):
|
||||
@@ -100,10 +171,11 @@ class DressupPathBoundaryViewProvider(object):
|
||||
self.panel = None
|
||||
|
||||
def claimChildren(self):
|
||||
return [self.obj.Base, self.obj.Boundary]
|
||||
return [self.obj.Base, self.obj.Stock]
|
||||
|
||||
def onDelete(self, vobj, args=None):
|
||||
vobj.Object.Proxy.onDelete(vobj.Object, args)
|
||||
return True
|
||||
|
||||
def setEdit(self, vobj, mode=0):
|
||||
panel = TaskPanel(vobj.Object, self)
|
||||
@@ -128,6 +200,8 @@ def Create(base, name='DressupPathBoundary'):
|
||||
FreeCAD.ActiveDocument.openTransaction(translate('Path_DressupPathBoundary', 'Create a Boundary dressup'))
|
||||
obj = PathDressupPathBoundary.Create(base, name)
|
||||
obj.ViewObject.Proxy = DressupPathBoundaryViewProvider(obj.ViewObject)
|
||||
obj.Base.ViewObject.Visibility = False
|
||||
obj.Stock.ViewObject.Visibility = False
|
||||
FreeCAD.ActiveDocument.commitTransaction()
|
||||
obj.ViewObject.Document.setEdit(obj.ViewObject, 0)
|
||||
return obj
|
||||
|
||||
@@ -344,12 +344,14 @@ class ObjectJob:
|
||||
def execute(self, obj):
|
||||
obj.Path = obj.Operations.Path
|
||||
|
||||
def addOperation(self, op, before = None):
|
||||
def addOperation(self, op, before = None, removeBefore = False):
|
||||
group = self.obj.Operations.Group
|
||||
if op not in group:
|
||||
if before:
|
||||
try:
|
||||
group.insert(group.index(before), op)
|
||||
if removeBefore:
|
||||
group.remove(before)
|
||||
except Exception as e: # pylint: disable=broad-except
|
||||
PathLog.error(e)
|
||||
group.append(op)
|
||||
|
||||
@@ -527,12 +527,16 @@ class StockFromExistingEdit(StockEdit):
|
||||
|
||||
def candidates(self, obj):
|
||||
solids = [o for o in obj.Document.Objects if PathUtil.isSolid(o)]
|
||||
for base in obj.Model.Group:
|
||||
if base in solids and PathJob.isResourceClone(obj, base, 'Model'):
|
||||
if hasattr(obj, 'Model'):
|
||||
job = obj
|
||||
else:
|
||||
job = PathUtils.findParentJob(obj)
|
||||
for base in job.Model.Group:
|
||||
if base in solids and PathJob.isResourceClone(job, base, 'Model'):
|
||||
solids.remove(base)
|
||||
if obj.Stock in solids:
|
||||
if job.Stock in solids:
|
||||
# regardless, what stock is/was, it's not a valid choice
|
||||
solids.remove(obj.Stock)
|
||||
solids.remove(job.Stock)
|
||||
return sorted(solids, key=lambda c: c.Label)
|
||||
|
||||
def setFields(self, obj):
|
||||
|
||||
@@ -233,9 +233,22 @@ def SetupStockObject(obj, stockType):
|
||||
obj.ViewObject.Transparency = 90
|
||||
obj.ViewObject.DisplayMode = 'Wireframe'
|
||||
|
||||
class FakeJob(object):
|
||||
def __init__(self, base):
|
||||
self.Group = [base]
|
||||
|
||||
def _getBase(job):
|
||||
if job and hasattr(job, 'Model'):
|
||||
return job.Model
|
||||
if job:
|
||||
import PathScripts.PathUtils as PathUtils
|
||||
job = PathUtils.findParentJob(job)
|
||||
return job.Model if job else None
|
||||
return None
|
||||
|
||||
def CreateFromBase(job, neg=None, pos=None, placement=None):
|
||||
PathLog.track(job.Label, neg, pos, placement)
|
||||
base = job.Model if job else None
|
||||
base = _getBase(job)
|
||||
obj = FreeCAD.ActiveDocument.addObject('Part::FeaturePython', 'Stock')
|
||||
obj.Proxy = StockFromBase(obj, base)
|
||||
|
||||
@@ -258,7 +271,7 @@ def CreateFromBase(job, neg=None, pos=None, placement=None):
|
||||
return obj
|
||||
|
||||
def CreateBox(job, extent=None, placement=None):
|
||||
base = job.Model if job else None
|
||||
base = _getBase(job)
|
||||
obj = FreeCAD.ActiveDocument.addObject('Part::FeaturePython', 'Stock')
|
||||
obj.Proxy = StockCreateBox(obj)
|
||||
|
||||
@@ -283,7 +296,7 @@ def CreateBox(job, extent=None, placement=None):
|
||||
return obj
|
||||
|
||||
def CreateCylinder(job, radius=None, height=None, placement=None):
|
||||
base = job.Model if job else None
|
||||
base = _getBase(job)
|
||||
obj = FreeCAD.ActiveDocument.addObject('Part::FeaturePython', 'Stock')
|
||||
obj.Proxy = StockCreateCylinder(obj)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user