* [CAM] extract tool controller ui elements into their own file * [CAM] make the changes in the tool controller UI only apply when ok is clicked * [CAM] Add tool controller edit panel to the Profile operation * [CAM] Add copy button to in-operation tool controller editor * [CAM] clean up changes * [CAM] Add tool controller edit UI to all operations Notes on changes that were not a simple copy/paste job from the changes I made for Profile: - Deburr: changed TC/coolant rows from 1 and 2 to 0 and 1 - Probe: didn't work at all initially due to bug in main where ShapeName changed to ShapeType. I added a utility for reading either a ShapeType or a ShapeName (check for both properties, convert ShapeType to lower case) and applied it to probe and camotics - Drilling: moved Keep Tool Down checkbox up from row 8 to row 2 (all intermediate rows were missing) and added the edit checkbox in row 3 below it - VBit, Probe (or anything else that requires a specific tool type): in Base.py setupToolController(), I added a check to see if the currently selected tool is an invalid type, and if so and there is a valid tool, then change to that one. This fixes two UI bugs. Plausibly pre-existing, if there is one valid tool and an invalid tool is selected, it's impossible to switch to the valid one because you can't generate a combo box change event for the new tool. Definitely new: if an invalid tool is selected and there are no valid tools, the combo box will be empty but the new tool controller edit utility will let you edit the current TC anyway. - Thread Milling: replaced the Tool Controller GroupBox with the standard QFrame layout, and added the checkbox. Note that this operation doesn't have a UI element for coolant -- likely a bug, but I didn't look into it - Surface: Changed from form layout to grid layout. Deleted an old SurfaceEdit.ui file -- it was replaced with PageOpSurfaceEdit.ui in 2017 but not deleted (commit 77af19e7489e1fc637a68cdad220e5dd430dc2b9) - Waterline: Changed from form layout to grid layout * [CAM] Bug fixes setupUi() wasn't called on the tool controller editor, preventing changes in its UI from being written back to the object immediately. This caused weird behavior where if you edited a field twice it would reset the second time it was focused Added a hook to automatically update the TC combo box when the TC name (or anything else about it, since that was easier) changes * Fix usage of QSignalBlockers * [CAM] Block scroll events on tool number and spindle direction when not focused Specifically, if you mouse over either of these UI elements and use the scroll wheel, it used to focus the element and change its value. This commit makes it do neither of those things, for these specific elements, as a measure against users accidentally changing these values. * disable tcNumber edit field in operations panel * Add "New tool controller" option to TC combo box When selected, it opens (toggles, technically) the tool bit dock and returns to the previous selection. Adding a new tool controller using the dock (already, before this commit) automatically switches the operation's tool controller to the new one * Add "Copy" option to tool controller combo box * Copy TC function only in combo box, no button * [CAM] update in-operation "new tool controller" function to use a dialog * [CAM] make the tool selector always a dialog and never a dock * remove spacer from ToolControllerEdit.ui to fix exces white space * [CAM] change tool dialog default sizing/spacing * [CAM] fix bug where copying tool controller doesn't copy all values
153 lines
5.9 KiB
Python
153 lines
5.9 KiB
Python
# -*- coding: utf-8 -*-
|
|
# ***************************************************************************
|
|
# * Copyright (c) 2018 sliptonic <shopinthewoods@gmail.com> *
|
|
# * *
|
|
# * This program is free software; you can redistribute it and/or modify *
|
|
# * it under the terms of the GNU Lesser General Public License (LGPL) *
|
|
# * as published by the Free Software Foundation; either version 2 of *
|
|
# * the License, or (at your option) any later version. *
|
|
# * for detail see the LICENCE text file. *
|
|
# * *
|
|
# * This program is distributed in the hope that it will be useful, *
|
|
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
# * GNU Library General Public License for more details. *
|
|
# * *
|
|
# * You should have received a copy of the GNU Library General Public *
|
|
# * License along with this program; if not, write to the Free Software *
|
|
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
|
# * USA *
|
|
# * *
|
|
# ***************************************************************************
|
|
|
|
|
|
import FreeCAD
|
|
import Path
|
|
import Path.Op.Base as PathOp
|
|
import PathScripts.PathUtils as PathUtils
|
|
from PySide.QtCore import QT_TRANSLATE_NOOP
|
|
|
|
|
|
__title__ = "CAM Probing Operation"
|
|
__author__ = "sliptonic (Brad Collette)"
|
|
__url__ = "https://www.freecad.org"
|
|
__doc__ = "CAM Probing operation."
|
|
|
|
if False:
|
|
Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule())
|
|
Path.Log.trackModule(Path.Log.thisModule())
|
|
else:
|
|
Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule())
|
|
|
|
|
|
class ObjectProbing(PathOp.ObjectOp):
|
|
"""Proxy object for Probing operation."""
|
|
|
|
def opFeatures(self, obj):
|
|
"""opFeatures(obj) ... Probing works on the stock object."""
|
|
return PathOp.FeatureDepths | PathOp.FeatureHeights | PathOp.FeatureTool
|
|
|
|
def initOperation(self, obj):
|
|
obj.addProperty(
|
|
"App::PropertyLength",
|
|
"Xoffset",
|
|
"Probe",
|
|
QT_TRANSLATE_NOOP("App::Property", "X offset between tool and probe"),
|
|
)
|
|
obj.addProperty(
|
|
"App::PropertyLength",
|
|
"Yoffset",
|
|
"Probe",
|
|
QT_TRANSLATE_NOOP("App::Property", "Y offset between tool and probe"),
|
|
)
|
|
obj.addProperty(
|
|
"App::PropertyInteger",
|
|
"PointCountX",
|
|
"Probe",
|
|
QT_TRANSLATE_NOOP("App::Property", "Number of points to probe in X-direction"),
|
|
)
|
|
obj.addProperty(
|
|
"App::PropertyInteger",
|
|
"PointCountY",
|
|
"Probe",
|
|
QT_TRANSLATE_NOOP("App::Property", "Number of points to probe in Y-direction"),
|
|
)
|
|
obj.addProperty(
|
|
"App::PropertyFile",
|
|
"OutputFileName",
|
|
"Path",
|
|
QT_TRANSLATE_NOOP(
|
|
"App::Property", "The output location for the probe data to be written"
|
|
),
|
|
)
|
|
|
|
def nextpoint(self, startpoint=0.0, endpoint=0.0, count=3):
|
|
curstep = 0
|
|
dist = (endpoint - startpoint) / (count - 1)
|
|
while curstep <= count - 1:
|
|
yield startpoint + (curstep * dist)
|
|
curstep += 1
|
|
|
|
def opExecute(self, obj):
|
|
"""opExecute(obj) ... generate probe locations."""
|
|
Path.Log.track()
|
|
if not self.isToolSupported(obj, self.tool):
|
|
Path.Log.warning("No suitable probe tool found")
|
|
return
|
|
|
|
self.commandlist.append(Path.Command("(Begin Probing)"))
|
|
|
|
stock = PathUtils.findParentJob(obj).Stock
|
|
bb = stock.Shape.BoundBox
|
|
|
|
openstring = "(PROBEOPEN {})".format(obj.OutputFileName)
|
|
self.commandlist.append(Path.Command(openstring))
|
|
self.commandlist.append(Path.Command("G0", {"Z": obj.ClearanceHeight.Value}))
|
|
|
|
for y in self.nextpoint(bb.YMin, bb.YMax, obj.PointCountY):
|
|
for x in self.nextpoint(bb.XMin, bb.XMax, obj.PointCountX):
|
|
self.commandlist.append(
|
|
Path.Command(
|
|
"G0",
|
|
{
|
|
"X": x + obj.Xoffset.Value,
|
|
"Y": y + obj.Yoffset.Value,
|
|
"Z": obj.SafeHeight.Value,
|
|
},
|
|
)
|
|
)
|
|
self.commandlist.append(
|
|
Path.Command(
|
|
"G38.2",
|
|
{
|
|
"Z": obj.FinalDepth.Value,
|
|
"F": obj.ToolController.VertFeed.Value,
|
|
},
|
|
)
|
|
)
|
|
self.commandlist.append(Path.Command("G0", {"Z": obj.SafeHeight.Value}))
|
|
|
|
self.commandlist.append(Path.Command("(PROBECLOSE)"))
|
|
|
|
def opSetDefaultValues(self, obj, job):
|
|
"""opSetDefaultValues(obj, job) ... set default value for RetractHeight"""
|
|
|
|
def isToolSupported(self, obj, tool):
|
|
"""Probe operation requires a probe tool"""
|
|
support = PathUtils.getToolShapeName(tool) == "probe"
|
|
Path.Log.track(tool.Label, support)
|
|
return support
|
|
|
|
|
|
def SetupProperties():
|
|
setup = ["Xoffset", "Yoffset", "PointCountX", "PointCountY", "OutputFileName"]
|
|
return setup
|
|
|
|
|
|
def Create(name, obj=None, parentJob=None):
|
|
"""Create(name) ... Creates and returns a Probing operation."""
|
|
if obj is None:
|
|
obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", name)
|
|
proxy = ObjectProbing(obj, name, parentJob)
|
|
return obj
|