meerk40t 0.9.2000__py2.py3-none-any.whl → 0.9.3001__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- meerk40t/balormk/balor_params.py +1 -43
- meerk40t/balormk/controller.py +1 -41
- meerk40t/balormk/device.py +16 -22
- meerk40t/balormk/driver.py +4 -4
- meerk40t/balormk/gui/balorconfig.py +2 -2
- meerk40t/balormk/gui/balorcontroller.py +13 -5
- meerk40t/balormk/gui/baloroperationproperties.py +0 -46
- meerk40t/balormk/gui/gui.py +17 -17
- meerk40t/camera/gui/camerapanel.py +18 -11
- meerk40t/core/cutcode/rastercut.py +3 -1
- meerk40t/core/cutplan.py +145 -14
- meerk40t/core/elements/clipboard.py +18 -9
- meerk40t/core/elements/element_treeops.py +320 -180
- meerk40t/core/elements/element_types.py +7 -2
- meerk40t/core/elements/elements.py +53 -27
- meerk40t/core/elements/geometry.py +8 -0
- meerk40t/core/elements/offset_clpr.py +129 -4
- meerk40t/core/elements/offset_mk.py +3 -1
- meerk40t/core/elements/shapes.py +28 -25
- meerk40t/core/laserjob.py +7 -0
- meerk40t/core/node/bootstrap.py +4 -0
- meerk40t/core/node/effect_hatch.py +85 -96
- meerk40t/core/node/effect_wobble.py +309 -0
- meerk40t/core/node/elem_image.py +49 -19
- meerk40t/core/node/elem_line.py +60 -0
- meerk40t/core/node/elem_rect.py +5 -3
- meerk40t/core/node/image_processed.py +766 -0
- meerk40t/core/node/image_raster.py +113 -0
- meerk40t/core/node/node.py +120 -1
- meerk40t/core/node/op_cut.py +2 -8
- meerk40t/core/node/op_dots.py +0 -8
- meerk40t/core/node/op_engrave.py +2 -18
- meerk40t/core/node/op_image.py +22 -35
- meerk40t/core/node/op_raster.py +0 -9
- meerk40t/core/planner.py +32 -2
- meerk40t/core/svg_io.py +699 -461
- meerk40t/core/treeop.py +191 -0
- meerk40t/core/undos.py +15 -1
- meerk40t/core/units.py +14 -4
- meerk40t/device/dummydevice.py +3 -2
- meerk40t/device/gui/defaultactions.py +43 -55
- meerk40t/device/gui/formatterpanel.py +58 -49
- meerk40t/device/gui/warningpanel.py +12 -12
- meerk40t/device/mixins.py +13 -0
- meerk40t/dxf/dxf_io.py +9 -5
- meerk40t/extra/ezd.py +28 -26
- meerk40t/extra/imageactions.py +300 -308
- meerk40t/extra/lbrn.py +19 -2
- meerk40t/fill/fills.py +6 -6
- meerk40t/fill/patternfill.py +1061 -1061
- meerk40t/fill/patterns.py +2 -6
- meerk40t/grbl/controller.py +168 -52
- meerk40t/grbl/device.py +23 -18
- meerk40t/grbl/driver.py +39 -0
- meerk40t/grbl/emulator.py +79 -19
- meerk40t/grbl/gcodejob.py +10 -0
- meerk40t/grbl/gui/grblconfiguration.py +2 -2
- meerk40t/grbl/gui/grblcontroller.py +24 -8
- meerk40t/grbl/gui/grblhardwareconfig.py +153 -0
- meerk40t/grbl/gui/gui.py +17 -14
- meerk40t/grbl/mock_connection.py +15 -34
- meerk40t/grbl/plugin.py +0 -4
- meerk40t/grbl/serial_connection.py +2 -1
- meerk40t/gui/about.py +8 -5
- meerk40t/gui/alignment.py +10 -6
- meerk40t/gui/basicops.py +27 -17
- meerk40t/gui/bufferview.py +2 -2
- meerk40t/gui/choicepropertypanel.py +101 -13
- meerk40t/gui/consolepanel.py +12 -9
- meerk40t/gui/devicepanel.py +38 -25
- meerk40t/gui/executejob.py +6 -4
- meerk40t/gui/help_assets/help_assets.py +13 -10
- meerk40t/gui/hersheymanager.py +8 -6
- meerk40t/gui/icons.py +1951 -3065
- meerk40t/gui/imagesplitter.py +14 -7
- meerk40t/gui/keymap.py +3 -3
- meerk40t/gui/laserpanel.py +151 -84
- meerk40t/gui/laserrender.py +61 -70
- meerk40t/gui/lasertoolpanel.py +8 -7
- meerk40t/gui/materialtest.py +3 -3
- meerk40t/gui/mkdebug.py +254 -1
- meerk40t/gui/navigationpanels.py +321 -180
- meerk40t/gui/notes.py +3 -3
- meerk40t/gui/opassignment.py +12 -12
- meerk40t/gui/operation_info.py +13 -13
- meerk40t/gui/plugin.py +5 -0
- meerk40t/gui/position.py +20 -18
- meerk40t/gui/preferences.py +21 -6
- meerk40t/gui/propertypanels/attributes.py +70 -22
- meerk40t/gui/propertypanels/blobproperty.py +2 -2
- meerk40t/gui/propertypanels/consoleproperty.py +2 -2
- meerk40t/gui/propertypanels/groupproperties.py +3 -3
- meerk40t/gui/propertypanels/hatchproperty.py +11 -18
- meerk40t/gui/propertypanels/imageproperty.py +4 -3
- meerk40t/gui/propertypanels/opbranchproperties.py +1 -1
- meerk40t/gui/propertypanels/pathproperty.py +2 -2
- meerk40t/gui/propertypanels/pointproperty.py +2 -2
- meerk40t/gui/propertypanels/propertywindow.py +4 -4
- meerk40t/gui/propertypanels/textproperty.py +3 -3
- meerk40t/gui/propertypanels/wobbleproperty.py +204 -0
- meerk40t/gui/ribbon.py +367 -259
- meerk40t/gui/scene/scene.py +31 -5
- meerk40t/gui/scenewidgets/elementswidget.py +12 -4
- meerk40t/gui/scenewidgets/gridwidget.py +2 -2
- meerk40t/gui/scenewidgets/laserpathwidget.py +7 -2
- meerk40t/gui/scenewidgets/machineoriginwidget.py +6 -2
- meerk40t/gui/scenewidgets/relocatewidget.py +1 -1
- meerk40t/gui/scenewidgets/reticlewidget.py +9 -0
- meerk40t/gui/scenewidgets/selectionwidget.py +12 -7
- meerk40t/gui/simpleui.py +95 -8
- meerk40t/gui/simulation.py +44 -36
- meerk40t/gui/spoolerpanel.py +124 -26
- meerk40t/gui/statusbarwidgets/defaultoperations.py +18 -6
- meerk40t/gui/statusbarwidgets/infowidget.py +2 -2
- meerk40t/gui/statusbarwidgets/opassignwidget.py +12 -12
- meerk40t/gui/statusbarwidgets/shapepropwidget.py +45 -18
- meerk40t/gui/statusbarwidgets/statusbar.py +11 -4
- meerk40t/gui/themes.py +78 -0
- meerk40t/gui/toolwidgets/toolcircle.py +2 -1
- meerk40t/gui/toolwidgets/toolellipse.py +2 -1
- meerk40t/gui/toolwidgets/toolimagecut.py +132 -0
- meerk40t/gui/toolwidgets/toolline.py +144 -0
- meerk40t/gui/toolwidgets/toolnodeedit.py +72 -145
- meerk40t/gui/toolwidgets/toolpoint.py +1 -1
- meerk40t/gui/toolwidgets/toolpolygon.py +8 -55
- meerk40t/gui/toolwidgets/toolrect.py +2 -1
- meerk40t/gui/usbconnect.py +2 -2
- meerk40t/gui/utilitywidgets/cyclocycloidwidget.py +2 -2
- meerk40t/gui/utilitywidgets/harmonograph.py +7 -7
- meerk40t/gui/utilitywidgets/scalewidget.py +1 -1
- meerk40t/gui/wordlisteditor.py +33 -18
- meerk40t/gui/wxmeerk40t.py +166 -66
- meerk40t/gui/wxmmain.py +236 -157
- meerk40t/gui/wxmribbon.py +49 -25
- meerk40t/gui/wxmscene.py +49 -38
- meerk40t/gui/wxmtree.py +216 -85
- meerk40t/gui/wxutils.py +62 -4
- meerk40t/image/imagetools.py +443 -15
- meerk40t/internal_plugins.py +2 -10
- meerk40t/kernel/kernel.py +12 -4
- meerk40t/lihuiyu/controller.py +7 -7
- meerk40t/lihuiyu/device.py +3 -1
- meerk40t/lihuiyu/driver.py +3 -0
- meerk40t/lihuiyu/gui/gui.py +8 -8
- meerk40t/lihuiyu/gui/lhyaccelgui.py +2 -2
- meerk40t/lihuiyu/gui/lhycontrollergui.py +73 -27
- meerk40t/lihuiyu/gui/lhydrivergui.py +2 -2
- meerk40t/lihuiyu/gui/tcpcontroller.py +22 -9
- meerk40t/main.py +6 -1
- meerk40t/moshi/controller.py +5 -5
- meerk40t/moshi/device.py +5 -2
- meerk40t/moshi/driver.py +4 -0
- meerk40t/moshi/gui/gui.py +8 -8
- meerk40t/moshi/gui/moshicontrollergui.py +24 -8
- meerk40t/moshi/gui/moshidrivergui.py +2 -2
- meerk40t/newly/controller.py +2 -0
- meerk40t/newly/device.py +9 -2
- meerk40t/newly/driver.py +4 -0
- meerk40t/newly/gui/gui.py +16 -17
- meerk40t/newly/gui/newlyconfig.py +2 -2
- meerk40t/newly/gui/newlycontroller.py +13 -5
- meerk40t/rotary/gui/gui.py +2 -2
- meerk40t/rotary/gui/rotarysettings.py +2 -2
- meerk40t/ruida/device.py +3 -0
- meerk40t/ruida/driver.py +4 -0
- meerk40t/ruida/gui/gui.py +6 -6
- meerk40t/ruida/gui/ruidaconfig.py +2 -2
- meerk40t/ruida/gui/ruidacontroller.py +13 -5
- meerk40t/svgelements.py +9 -9
- meerk40t/tools/geomstr.py +849 -153
- meerk40t/tools/kerftest.py +8 -4
- meerk40t/tools/livinghinges.py +15 -8
- {meerk40t-0.9.2000.dist-info → meerk40t-0.9.3001.dist-info}/METADATA +21 -16
- {meerk40t-0.9.2000.dist-info → meerk40t-0.9.3001.dist-info}/RECORD +185 -177
- {meerk40t-0.9.2000.dist-info → meerk40t-0.9.3001.dist-info}/entry_points.txt +0 -1
- test/test_core_elements.py +8 -24
- test/test_file_svg.py +88 -0
- test/test_fill.py +9 -9
- test/test_geomstr.py +258 -8
- test/test_kernel.py +4 -0
- test/test_tools_rasterplotter.py +29 -0
- meerk40t/extra/embroider.py +0 -56
- meerk40t/extra/pathoptimize.py +0 -249
- {meerk40t-0.9.2000.dist-info → meerk40t-0.9.3001.dist-info}/LICENSE +0 -0
- {meerk40t-0.9.2000.dist-info → meerk40t-0.9.3001.dist-info}/WHEEL +0 -0
- {meerk40t-0.9.2000.dist-info → meerk40t-0.9.3001.dist-info}/top_level.txt +0 -0
- {meerk40t-0.9.2000.dist-info → meerk40t-0.9.3001.dist-info}/zip-safe +0 -0
@@ -1,5 +1,5 @@
|
|
1
1
|
"""
|
2
|
-
This is a large number of flagged tree operations. The details of how these are registered is
|
2
|
+
This is a large number of flagged tree operations. The details of how these are registered is available in the treeop.py
|
3
3
|
file. These define the right-click node menu operations. That menu is dynamically created based on various context
|
4
4
|
cues.
|
5
5
|
"""
|
@@ -9,7 +9,6 @@ import math
|
|
9
9
|
import os.path
|
10
10
|
from copy import copy
|
11
11
|
|
12
|
-
from meerk40t.core.cutcode.cutcode import CutCode
|
13
12
|
from meerk40t.core.node.elem_image import ImageNode
|
14
13
|
from meerk40t.core.node.node import Node
|
15
14
|
from meerk40t.core.treeop import (
|
@@ -29,6 +28,7 @@ from meerk40t.core.treeop import (
|
|
29
28
|
from meerk40t.core.units import UNITS_PER_INCH, Length
|
30
29
|
from meerk40t.kernel import CommandSyntaxError
|
31
30
|
from meerk40t.svgelements import Matrix, Point, Polygon
|
31
|
+
from meerk40t.tools.geomstr import Geomstr
|
32
32
|
|
33
33
|
from .element_types import *
|
34
34
|
|
@@ -49,13 +49,7 @@ def init_tree(kernel):
|
|
49
49
|
# --------------------------- TREE OPERATIONS ---------------------------
|
50
50
|
|
51
51
|
def is_regmark(node):
|
52
|
-
|
53
|
-
try:
|
54
|
-
if node._parent.type == "branch reg":
|
55
|
-
result = True
|
56
|
-
except AttributeError:
|
57
|
-
pass
|
58
|
-
return result
|
52
|
+
return node.has_ancestor("branch reg")
|
59
53
|
|
60
54
|
def has_changes(node):
|
61
55
|
result = False
|
@@ -67,6 +61,10 @@ def init_tree(kernel):
|
|
67
61
|
pass
|
68
62
|
return result
|
69
63
|
|
64
|
+
def is_developer_mode():
|
65
|
+
flag = getattr(self.kernel.root, "developer_mode", False)
|
66
|
+
return flag
|
67
|
+
|
70
68
|
@tree_separator_after()
|
71
69
|
@tree_conditional(lambda node: len(list(self.ops(selected=True))) == 1)
|
72
70
|
@tree_operation(_("Operation properties"), node_type=op_nodes, help="")
|
@@ -121,6 +119,17 @@ def init_tree(kernel):
|
|
121
119
|
if activate is not None:
|
122
120
|
activate(node)
|
123
121
|
|
122
|
+
# @tree_operation(_("Debug group"), node_type=("group", "file"), help="")
|
123
|
+
# def debug_group(node, **kwargs):
|
124
|
+
# if node is None:
|
125
|
+
# return
|
126
|
+
# info = ""
|
127
|
+
# for idx, e in enumerate(list(node.children)):
|
128
|
+
# if info:
|
129
|
+
# info += "\n"
|
130
|
+
# info += f"{idx}#: {e.type}, identical to parent: {e is node}"
|
131
|
+
# print (info)
|
132
|
+
|
124
133
|
@tree_conditional(lambda node: not is_regmark(node))
|
125
134
|
@tree_operation(_("Ungroup elements"), node_type=("group", "file"), help="")
|
126
135
|
def ungroup_elements(node, **kwargs):
|
@@ -190,8 +199,31 @@ def init_tree(kernel):
|
|
190
199
|
@tree_conditional(lambda node: len(list(self.elems(emphasized=True))) > 1)
|
191
200
|
@tree_operation(_("Group elements"), node_type=elem_nodes, help="")
|
192
201
|
def group_elements(node, **kwargs):
|
193
|
-
|
194
|
-
|
202
|
+
def minimal_parent(data):
|
203
|
+
result = None
|
204
|
+
root = self.elem_branch
|
205
|
+
curr_level = None
|
206
|
+
for node in data:
|
207
|
+
plevel = 0
|
208
|
+
candidate = node.parent
|
209
|
+
while candidate is not None and candidate.parent is not root:
|
210
|
+
candidate = candidate.parent
|
211
|
+
plevel += 1
|
212
|
+
if curr_level is None or plevel < curr_level:
|
213
|
+
curr_level = plevel
|
214
|
+
result = node.parent
|
215
|
+
if plevel == 0:
|
216
|
+
# No need to continue
|
217
|
+
break
|
218
|
+
if result is None:
|
219
|
+
result = root
|
220
|
+
return result
|
221
|
+
|
222
|
+
raw_data = list(self.elems(emphasized=True))
|
223
|
+
data = self.condense_elements(raw_data, expand_at_end=False)
|
224
|
+
parent_node = minimal_parent(data)
|
225
|
+
group_node = parent_node.add(type="group", label="Group")
|
226
|
+
for e in data:
|
195
227
|
group_node.append_child(e)
|
196
228
|
|
197
229
|
@tree_conditional(
|
@@ -982,42 +1014,24 @@ def init_tree(kernel):
|
|
982
1014
|
# REMOVE SINGLE (Tree Selected - ELEMENT)
|
983
1015
|
# ==========
|
984
1016
|
|
985
|
-
@tree_conditional(lambda node:
|
986
|
-
@
|
987
|
-
|
988
|
-
|
989
|
-
|
990
|
-
|
991
|
-
|
992
|
-
|
993
|
-
|
994
|
-
|
995
|
-
|
996
|
-
|
997
|
-
|
998
|
-
|
999
|
-
|
1000
|
-
|
1001
|
-
|
1002
|
-
|
1003
|
-
@tree_conditional(lambda node: node.can_remove)
|
1004
|
-
@tree_conditional(
|
1005
|
-
lambda cond: len(
|
1006
|
-
list(self.flat(selected=True, cascade=False, types=elem_nodes))
|
1007
|
-
)
|
1008
|
-
== 1
|
1009
|
-
)
|
1010
|
-
@tree_operation(
|
1011
|
-
_("Delete element '{name}' fully"),
|
1012
|
-
node_type=elem_nodes,
|
1013
|
-
help="",
|
1014
|
-
)
|
1015
|
-
def remove_type_elem(node, **kwargs):
|
1016
|
-
if hasattr(node, "can_remove") and not node.can_remove:
|
1017
|
-
pass
|
1018
|
-
else:
|
1019
|
-
self.set_emphasis(None)
|
1020
|
-
node.remove_node()
|
1017
|
+
# @tree_conditional(lambda node: node.can_remove)
|
1018
|
+
# @tree_conditional(
|
1019
|
+
# lambda cond: len(
|
1020
|
+
# list(self.flat(selected=True, cascade=False, types=elem_nodes))
|
1021
|
+
# )
|
1022
|
+
# == 1
|
1023
|
+
# )
|
1024
|
+
# @tree_operation(
|
1025
|
+
# _("Delete element '{name}' fully"),
|
1026
|
+
# node_type=elem_nodes,
|
1027
|
+
# help="",
|
1028
|
+
# )
|
1029
|
+
# def remove_type_elem(node, **kwargs):
|
1030
|
+
# if hasattr(node, "can_remove") and not node.can_remove:
|
1031
|
+
# pass
|
1032
|
+
# else:
|
1033
|
+
# self.set_emphasis(None)
|
1034
|
+
# node.remove_node()
|
1021
1035
|
|
1022
1036
|
@tree_conditional(
|
1023
1037
|
lambda cond: len(list(self.flat(selected=True, cascade=False, types=op_nodes)))
|
@@ -1202,7 +1216,7 @@ def init_tree(kernel):
|
|
1202
1216
|
# REMOVE ELEMENTS
|
1203
1217
|
# ==========
|
1204
1218
|
# More than one, special case == 1 already dealt with
|
1205
|
-
@tree_conditional(lambda node: len(list(self.elems(emphasized=True)))
|
1219
|
+
@tree_conditional(lambda node: len(list(self.elems(emphasized=True))) >= 1)
|
1206
1220
|
@tree_calc("ecount", lambda i: len(list(self.elems(emphasized=True))))
|
1207
1221
|
@tree_operation(
|
1208
1222
|
_("Delete {ecount} elements, as selected in scene"),
|
@@ -1221,7 +1235,7 @@ def init_tree(kernel):
|
|
1221
1235
|
self.signal("make_reference", node)
|
1222
1236
|
|
1223
1237
|
@tree_conditional(
|
1224
|
-
lambda node:
|
1238
|
+
lambda node: node.closed and len(list(node.geometry.as_points())) >= 3
|
1225
1239
|
)
|
1226
1240
|
@tree_operation(
|
1227
1241
|
_("Make Polygon regular"),
|
@@ -1229,74 +1243,28 @@ def init_tree(kernel):
|
|
1229
1243
|
help="",
|
1230
1244
|
)
|
1231
1245
|
def make_polygon_regular(node, **kwargs):
|
1232
|
-
# from .units import Length
|
1233
|
-
# from ..svgelements import Color
|
1234
|
-
|
1235
|
-
# def mk_debug_point(x, y, col):
|
1236
|
-
# circ = Ellipse(cx=x, cy=y, r=float(Length("1mm")))
|
1237
|
-
# circ.transform = copy(node.shape.transform)
|
1238
|
-
# self.elem_branch.add(
|
1239
|
-
# shape=circ,
|
1240
|
-
# type="elem ellipse",
|
1241
|
-
# stroke=Color(col),
|
1242
|
-
# fill=Color(col),
|
1243
|
-
# matrix=copy(node.matrix),
|
1244
|
-
# )
|
1245
|
-
|
1246
1246
|
if node is None or node.type != "elem polyline":
|
1247
1247
|
return
|
1248
|
-
|
1249
|
-
|
1250
|
-
|
1251
|
-
|
1252
|
-
#
|
1253
|
-
#
|
1254
|
-
|
1255
|
-
return
|
1256
|
-
pts = node.shape.points
|
1257
|
-
dx = pts[1].x - pts[0].x
|
1258
|
-
dy = pts[1].y - pts[0].y
|
1259
|
-
baseline = math.sqrt(dx * dx + dy * dy)
|
1260
|
-
apothem = baseline / (2 * math.tan(math.tau / (2 * number_points)))
|
1261
|
-
circumradius = baseline / (2 * math.sin(math.tau / (2 * number_points)))
|
1262
|
-
midpoint = Point(pts[0].x + 0.5 * dx, pts[0].y + 0.5 * dy)
|
1263
|
-
# mk_debug_point(midpoint.x, midpoint.y, "black")
|
1264
|
-
ax = 0
|
1265
|
-
ay = 0
|
1266
|
-
for idx, pt in enumerate(pts):
|
1267
|
-
ax += pt.x
|
1268
|
-
ay += pt.y
|
1269
|
-
ax /= number_points
|
1270
|
-
ay /= number_points
|
1248
|
+
pts = list(node.geometry.as_points())
|
1249
|
+
vertex_count = len(pts) - 1
|
1250
|
+
baseline = abs(pts[1] - pts[0])
|
1251
|
+
circumradius = baseline / (2 * math.sin(math.tau / (2 * vertex_count)))
|
1252
|
+
# apothem = baseline / (2 * math.tan(math.tau / (2 * vertex_count)))
|
1253
|
+
# midpoint = (pts[0] - pts[1]) / 2
|
1254
|
+
|
1271
1255
|
# The arithmetic center (ax, ay) indicates to which
|
1272
1256
|
# 'side' of the baseline the polygon needs to be constructed
|
1273
|
-
arithmetic_center =
|
1274
|
-
|
1275
|
-
|
1276
|
-
|
1277
|
-
|
1278
|
-
|
1279
|
-
|
1280
|
-
|
1281
|
-
|
1282
|
-
|
1283
|
-
|
1284
|
-
d2 = arithmetic_center.distance_to(second_point)
|
1285
|
-
if d1 < d2:
|
1286
|
-
center_point = copy(first_point)
|
1287
|
-
else:
|
1288
|
-
center_point = copy(second_point)
|
1289
|
-
# mk_debug_point(center_point.x, center_point.y, "red")
|
1290
|
-
|
1291
|
-
if center_point.angle_to(pts[0]) > center_point.angle_to(pts[1]):
|
1292
|
-
deltaangle *= -1
|
1293
|
-
angle = center_point.angle_to(pts[0])
|
1294
|
-
for idx in range(number_points):
|
1295
|
-
# if idx > 1:
|
1296
|
-
pt = Point.polar(center_point, angle, circumradius)
|
1297
|
-
pts[idx].x = pt.x
|
1298
|
-
pts[idx].y = pt.y
|
1299
|
-
angle += deltaangle
|
1257
|
+
arithmetic_center = sum(pts[:-1]) / vertex_count
|
1258
|
+
|
1259
|
+
start_angle = Geomstr.angle(None, arithmetic_center, pts[0])
|
1260
|
+
|
1261
|
+
node.geometry = Geomstr.regular_polygon(
|
1262
|
+
vertex_count,
|
1263
|
+
arithmetic_center,
|
1264
|
+
radius=circumradius,
|
1265
|
+
radius_inner=circumradius,
|
1266
|
+
start_angle=start_angle,
|
1267
|
+
)
|
1300
1268
|
node.altered()
|
1301
1269
|
self.signal("refresh_scene", "Scene")
|
1302
1270
|
|
@@ -1422,48 +1390,89 @@ def init_tree(kernel):
|
|
1422
1390
|
node.reverse()
|
1423
1391
|
self.signal("refresh_tree", list(self.flat(types="reference")))
|
1424
1392
|
|
1425
|
-
@
|
1426
|
-
@tree_conditional(lambda node: self.classify_autogenerate)
|
1393
|
+
@tree_submenu(_("Classification"))
|
1427
1394
|
@tree_operation(
|
1428
|
-
_("
|
1429
|
-
node_type="branch ops",
|
1395
|
+
_("Generate operations if needed"),
|
1396
|
+
node_type=("branch ops", "branch elems"),
|
1397
|
+
help="",
|
1398
|
+
enable=False,
|
1399
|
+
)
|
1400
|
+
def do_classification_comment_1(node, **kwargs):
|
1401
|
+
return
|
1402
|
+
|
1403
|
+
@tree_submenu(_("Classification"))
|
1404
|
+
@tree_operation(
|
1405
|
+
_("Refresh classification for all"),
|
1406
|
+
node_type=("branch ops", "branch elems"),
|
1430
1407
|
help=_("Reclassify elements and create operations if necessary"),
|
1431
1408
|
)
|
1432
|
-
def
|
1409
|
+
def refresh_classification_for_all_std(node, **kwargs):
|
1410
|
+
previous = self.classify_autogenerate
|
1411
|
+
self.classify_autogenerate = True
|
1433
1412
|
self.remove_elements_from_operations(list(self.elems()))
|
1434
1413
|
self.classify(list(self.elems()))
|
1414
|
+
self.classify_autogenerate = previous
|
1435
1415
|
self.signal("refresh_tree", list(self.flat(types="reference")))
|
1436
1416
|
|
1437
|
-
@tree_conditional(lambda node:
|
1417
|
+
@tree_conditional(lambda node: self.have_unassigned_elements())
|
1418
|
+
@tree_submenu(_("Classification"))
|
1438
1419
|
@tree_operation(
|
1439
|
-
_("
|
1440
|
-
node_type="branch ops",
|
1441
|
-
help=_("
|
1420
|
+
_("Classification for unassigned"),
|
1421
|
+
node_type=("branch ops", "branch elems"),
|
1422
|
+
help=_("Classify unassigned elements and create operations if necessary"),
|
1442
1423
|
)
|
1443
|
-
def
|
1444
|
-
self.
|
1445
|
-
self.
|
1424
|
+
def do_classification_for_unassigned_std(node, **kwargs):
|
1425
|
+
previous = self.classify_autogenerate
|
1426
|
+
self.classify_autogenerate = True
|
1427
|
+
target_list = list(self.unassigned_elements())
|
1428
|
+
self.classify(target_list)
|
1429
|
+
self.classify_autogenerate = previous
|
1446
1430
|
self.signal("refresh_tree", list(self.flat(types="reference")))
|
1447
1431
|
|
1448
|
-
@
|
1449
|
-
@
|
1432
|
+
@tree_submenu(_("Classification"))
|
1433
|
+
@tree_separator_before()
|
1450
1434
|
@tree_operation(
|
1451
|
-
_("
|
1452
|
-
node_type="branch ops",
|
1453
|
-
help=
|
1435
|
+
_("Use only existing operations"),
|
1436
|
+
node_type=("branch ops", "branch elems"),
|
1437
|
+
help="",
|
1438
|
+
enable=False,
|
1454
1439
|
)
|
1455
|
-
def
|
1440
|
+
def do_classification_comment_2(node, **kwargs):
|
1441
|
+
return
|
1442
|
+
|
1443
|
+
@tree_submenu(_("Classification"))
|
1444
|
+
@tree_operation(
|
1445
|
+
_("Refresh classification for all"),
|
1446
|
+
node_type=("branch ops", "branch elems"),
|
1447
|
+
help=_("Reclassify all elements and use only existing operations"),
|
1448
|
+
)
|
1449
|
+
def refresh_classification_for_all_existing_only(node, **kwargs):
|
1456
1450
|
previous = self.classify_autogenerate
|
1457
|
-
self.classify_autogenerate =
|
1451
|
+
self.classify_autogenerate = False
|
1458
1452
|
self.remove_elements_from_operations(list(self.elems()))
|
1459
1453
|
self.classify(list(self.elems()))
|
1460
1454
|
self.classify_autogenerate = previous
|
1461
1455
|
self.signal("refresh_tree", list(self.flat(types="reference")))
|
1462
1456
|
|
1457
|
+
@tree_submenu(_("Classification"))
|
1458
|
+
@tree_conditional(lambda node: self.have_unassigned_elements())
|
1459
|
+
@tree_operation(
|
1460
|
+
_("Classification for unassigned"),
|
1461
|
+
node_type=("branch ops", "branch elems"),
|
1462
|
+
help=_("Classify unassigned elements and use only existing operations"),
|
1463
|
+
)
|
1464
|
+
def do_classification_for_unassigned_existing_only(node, **kwargs):
|
1465
|
+
previous = self.classify_autogenerate
|
1466
|
+
self.classify_autogenerate = False
|
1467
|
+
target_list = list(self.unassigned_elements())
|
1468
|
+
self.classify(target_list)
|
1469
|
+
self.classify_autogenerate = previous
|
1470
|
+
self.signal("refresh_tree", list(self.flat(types="reference")))
|
1471
|
+
|
1463
1472
|
@tree_conditional(lambda cond: self.have_unassigned_elements())
|
1464
1473
|
@tree_operation(
|
1465
1474
|
_("Select unassigned elements"),
|
1466
|
-
node_type="branch ops",
|
1475
|
+
node_type=("branch ops", "branch elems"),
|
1467
1476
|
help=_("Select all elements that won't be burned"),
|
1468
1477
|
)
|
1469
1478
|
def select_unassigned(node, **kwargs):
|
@@ -1505,6 +1514,7 @@ def init_tree(kernel):
|
|
1505
1514
|
difference = [m for m in materials if m not in secs]
|
1506
1515
|
return difference
|
1507
1516
|
|
1517
|
+
@tree_separator_before()
|
1508
1518
|
@tree_submenu(_("Load"))
|
1509
1519
|
@tree_values("opname", values=self.op_data.section_set)
|
1510
1520
|
@tree_operation("{opname}", node_type="branch ops", help="")
|
@@ -1699,13 +1709,6 @@ def init_tree(kernel):
|
|
1699
1709
|
)
|
1700
1710
|
self.signal("updateop_tree")
|
1701
1711
|
|
1702
|
-
@tree_operation(_("Reclassify operations"), node_type="branch elems", help="")
|
1703
|
-
def reclassify_operations(node, **kwargs):
|
1704
|
-
elems = list(self.elems())
|
1705
|
-
self.remove_elements_from_operations(elems)
|
1706
|
-
self.classify(list(self.elems()))
|
1707
|
-
self.signal("refresh_tree")
|
1708
|
-
|
1709
1712
|
@tree_operation(
|
1710
1713
|
_("Remove all assignments from operations"),
|
1711
1714
|
node_type="branch elems",
|
@@ -1718,62 +1721,153 @@ def init_tree(kernel):
|
|
1718
1721
|
ref.remove_node()
|
1719
1722
|
self.signal("refresh_tree")
|
1720
1723
|
|
1721
|
-
|
1722
|
-
|
1723
|
-
|
1724
|
-
|
1725
|
-
|
1726
|
-
|
1724
|
+
hatchable_elems = (
|
1725
|
+
"elem path",
|
1726
|
+
"elem rect",
|
1727
|
+
"elem circle",
|
1728
|
+
"elem ellipse",
|
1729
|
+
"elem polyline",
|
1730
|
+
)
|
1731
|
+
|
1732
|
+
@tree_submenu(_("Apply special effect"))
|
1733
|
+
@tree_operation(_("Append Line-fill 0.1mm"), node_type=hatchable_elems, help="")
|
1734
|
+
def append_element_effect_eulerian(node, pos=None, **kwargs):
|
1735
|
+
group_node = node.parent.add(
|
1727
1736
|
type="effect hatch",
|
1728
1737
|
hatch_type="scanline",
|
1729
1738
|
hatch_distance="0.1mm",
|
1730
1739
|
hatch_angle="0deg",
|
1731
1740
|
pos=pos,
|
1732
1741
|
)
|
1742
|
+
for e in list(self.elems(emphasized=True)):
|
1743
|
+
group_node.append_child(e)
|
1744
|
+
if self.classify_new:
|
1745
|
+
self.classify([group_node])
|
1746
|
+
|
1733
1747
|
self.signal("updateelem_tree")
|
1734
1748
|
|
1735
|
-
@tree_submenu(_("
|
1749
|
+
@tree_submenu(_("Apply special effect"))
|
1736
1750
|
@tree_operation(
|
1737
|
-
_("Append diagonal Line-fill 0.1mm"), node_type=
|
1751
|
+
_("Append diagonal Line-fill 0.1mm"), node_type=hatchable_elems, help=""
|
1738
1752
|
)
|
1739
|
-
def append_element_effect_eulerian_45(
|
1740
|
-
|
1741
|
-
):
|
1742
|
-
self.elem_branch.add(
|
1753
|
+
def append_element_effect_eulerian_45(node, pos=None, **kwargs):
|
1754
|
+
group_node = node.parent.add(
|
1743
1755
|
type="effect hatch",
|
1744
1756
|
hatch_type="scanline", # scanline / eulerian
|
1745
1757
|
hatch_distance="0.1mm",
|
1746
1758
|
hatch_angle="45deg",
|
1747
1759
|
pos=pos,
|
1748
1760
|
)
|
1761
|
+
for e in list(self.elems(emphasized=True)):
|
1762
|
+
group_node.append_child(e)
|
1763
|
+
if self.classify_new:
|
1764
|
+
self.classify([group_node])
|
1765
|
+
|
1749
1766
|
self.signal("updateelem_tree")
|
1750
1767
|
|
1751
|
-
@tree_submenu(_("
|
1752
|
-
@tree_operation(_("Append Line-Fill 1mm"), node_type=
|
1753
|
-
def append_element_effect_line(node,
|
1754
|
-
|
1768
|
+
@tree_submenu(_("Apply special effect"))
|
1769
|
+
@tree_operation(_("Append Line-Fill 1mm"), node_type=hatchable_elems, help="")
|
1770
|
+
def append_element_effect_line(node, pos=None, **kwargs):
|
1771
|
+
group_node = node.parent.add(
|
1755
1772
|
type="effect hatch",
|
1756
1773
|
hatch_type="scanline",
|
1757
1774
|
hatch_distance="1mm",
|
1758
1775
|
hatch_angle="0deg",
|
1759
1776
|
pos=pos,
|
1760
1777
|
)
|
1778
|
+
for e in list(self.elems(emphasized=True)):
|
1779
|
+
group_node.append_child(e)
|
1780
|
+
if self.classify_new:
|
1781
|
+
self.classify([group_node])
|
1782
|
+
|
1761
1783
|
self.signal("updateelem_tree")
|
1762
1784
|
|
1763
|
-
@tree_submenu(_("
|
1785
|
+
@tree_submenu(_("Apply special effect"))
|
1764
1786
|
@tree_operation(
|
1765
|
-
_("Append diagonal Line-Fill 1mm"), node_type=
|
1787
|
+
_("Append diagonal Line-Fill 1mm"), node_type=hatchable_elems, help=""
|
1766
1788
|
)
|
1767
|
-
def append_element_effect_line_45(
|
1768
|
-
|
1769
|
-
):
|
1770
|
-
self.elem_branch.add(
|
1789
|
+
def append_element_effect_line_45(node, pos=None, **kwargs):
|
1790
|
+
group_node = node.parent.add(
|
1771
1791
|
type="effect hatch",
|
1772
1792
|
hatch_type="scanline",
|
1773
1793
|
hatch_distance="1mm",
|
1774
1794
|
hatch_angle="45deg",
|
1775
1795
|
pos=pos,
|
1776
1796
|
)
|
1797
|
+
for e in list(self.elems(emphasized=True)):
|
1798
|
+
group_node.append_child(e)
|
1799
|
+
if self.classify_new:
|
1800
|
+
self.classify([group_node])
|
1801
|
+
|
1802
|
+
self.signal("updateelem_tree")
|
1803
|
+
|
1804
|
+
@tree_submenu(_("Apply special effect"))
|
1805
|
+
@tree_operation(
|
1806
|
+
_("Append wobble {type} {radius} @{interval}").format(
|
1807
|
+
type="Circle", radius="0.5mm", interval="0.05mm"
|
1808
|
+
),
|
1809
|
+
node_type=hatchable_elems,
|
1810
|
+
help="",
|
1811
|
+
)
|
1812
|
+
def append_element_effect_wobble_c05(node, pos=None, **kwargs):
|
1813
|
+
group_node = node.parent.add(
|
1814
|
+
type="effect wobble",
|
1815
|
+
wobble_type="circle",
|
1816
|
+
wobble_radius="0.5mm",
|
1817
|
+
wobble_interval="0.05mm",
|
1818
|
+
pos=pos,
|
1819
|
+
)
|
1820
|
+
for e in list(self.elems(emphasized=True)):
|
1821
|
+
group_node.append_child(e)
|
1822
|
+
if self.classify_new:
|
1823
|
+
self.classify([group_node])
|
1824
|
+
|
1825
|
+
self.signal("updateelem_tree")
|
1826
|
+
|
1827
|
+
@tree_submenu(_("Apply special effect"))
|
1828
|
+
@tree_operation(
|
1829
|
+
_("Append wobble {type} {radius} @{interval}").format(
|
1830
|
+
type="Circle", radius="1mm", interval="0.1mm"
|
1831
|
+
),
|
1832
|
+
node_type=hatchable_elems,
|
1833
|
+
help="",
|
1834
|
+
)
|
1835
|
+
def append_element_effect_wobble_c1(node, pos=None, **kwargs):
|
1836
|
+
group_node = node.parent.add(
|
1837
|
+
type="effect wobble",
|
1838
|
+
wobble_type="circle",
|
1839
|
+
wobble_radius="1mm",
|
1840
|
+
wobble_interval="0.1mm",
|
1841
|
+
pos=pos,
|
1842
|
+
)
|
1843
|
+
for e in list(self.elems(emphasized=True)):
|
1844
|
+
group_node.append_child(e)
|
1845
|
+
if self.classify_new:
|
1846
|
+
self.classify([group_node])
|
1847
|
+
|
1848
|
+
self.signal("updateelem_tree")
|
1849
|
+
|
1850
|
+
@tree_submenu(_("Apply special effect"))
|
1851
|
+
@tree_operation(
|
1852
|
+
_("Append wobble {type} {radius} @{interval}").format(
|
1853
|
+
type="Circle", radius="3mm", interval="0.1mm"
|
1854
|
+
),
|
1855
|
+
node_type=hatchable_elems,
|
1856
|
+
help="",
|
1857
|
+
)
|
1858
|
+
def append_element_effect_wobble_c3(node, pos=None, **kwargs):
|
1859
|
+
group_node = node.parent.add(
|
1860
|
+
type="effect wobble",
|
1861
|
+
wobble_type="circle_right",
|
1862
|
+
wobble_radius="3mm",
|
1863
|
+
wobble_interval="0.1mm",
|
1864
|
+
pos=pos,
|
1865
|
+
)
|
1866
|
+
for e in list(self.elems(emphasized=True)):
|
1867
|
+
group_node.append_child(e)
|
1868
|
+
if self.classify_new:
|
1869
|
+
self.classify([group_node])
|
1870
|
+
|
1777
1871
|
self.signal("updateelem_tree")
|
1778
1872
|
|
1779
1873
|
@tree_operation(
|
@@ -2176,19 +2270,26 @@ def init_tree(kernel):
|
|
2176
2270
|
had_optional = False
|
2177
2271
|
# Need to add stroke and fill, as copy will take the
|
2178
2272
|
# default values for these attributes
|
2179
|
-
|
2180
|
-
|
2273
|
+
options = ["fill", "stroke", "wxfont"]
|
2274
|
+
for optional in options:
|
2275
|
+
if hasattr(e, optional):
|
2181
2276
|
setattr(copy_node, optional, getattr(orgnode, optional))
|
2182
|
-
|
2183
|
-
|
2184
|
-
|
2277
|
+
hadoptional = False
|
2278
|
+
options = []
|
2279
|
+
for prop in dir(e):
|
2280
|
+
if prop.startswith("mk"):
|
2281
|
+
options.append(prop)
|
2282
|
+
for optional in options:
|
2283
|
+
if hasattr(e, optional):
|
2185
2284
|
setattr(copy_node, optional, getattr(orgnode, optional))
|
2285
|
+
hadoptional = True
|
2286
|
+
|
2186
2287
|
if self.copy_increases_wordlist_references and hasattr(orgnode, "text"):
|
2187
2288
|
copy_node.text = self.wordlist_delta(orgnode.text, delta_wordlist)
|
2188
2289
|
elif self.copy_increases_wordlist_references and hasattr(e, "mktext"):
|
2189
2290
|
copy_node.mktext = self.wordlist_delta(e.mktext, delta_wordlist)
|
2190
2291
|
orgparent.add_node(copy_node)
|
2191
|
-
if
|
2292
|
+
if hadoptional:
|
2192
2293
|
for property_op in self.kernel.lookup_all("path_updater/.*"):
|
2193
2294
|
property_op(self.kernel.root, copy_node)
|
2194
2295
|
|
@@ -2335,6 +2436,33 @@ def init_tree(kernel):
|
|
2335
2436
|
setattr(newnode, item[0], item[1])
|
2336
2437
|
newnode.altered()
|
2337
2438
|
|
2439
|
+
@tree_conditional(
|
2440
|
+
lambda node: hasattr(node, "as_geometry") and node.has_ancestor("branch elems")
|
2441
|
+
)
|
2442
|
+
@tree_operation(
|
2443
|
+
_("Convert to path"),
|
2444
|
+
node_type=effect_nodes,
|
2445
|
+
help="Convert effect to path",
|
2446
|
+
)
|
2447
|
+
def convert_to_path(singlenode, **kwargs):
|
2448
|
+
elements = self.elem_branch
|
2449
|
+
for node in list(elements.flat(types=effect_nodes, emphasized=True)):
|
2450
|
+
if not hasattr(node, "as_geometry"):
|
2451
|
+
continue
|
2452
|
+
node_attributes = []
|
2453
|
+
for attrib in ("stroke", "fill", "stroke_width", "stroke_scaled"):
|
2454
|
+
if hasattr(node, attrib):
|
2455
|
+
oldval = getattr(node, attrib, None)
|
2456
|
+
node_attributes.append([attrib, oldval])
|
2457
|
+
geometry = node.as_geometry()
|
2458
|
+
node.remove_all_children()
|
2459
|
+
if not len(geometry):
|
2460
|
+
return
|
2461
|
+
newnode = node.replace_node(geometry=geometry, type="elem path")
|
2462
|
+
for item in node_attributes:
|
2463
|
+
setattr(newnode, item[0], item[1])
|
2464
|
+
newnode.altered()
|
2465
|
+
|
2338
2466
|
@tree_submenu(_("Flip"))
|
2339
2467
|
@tree_separator_before()
|
2340
2468
|
@tree_conditional(lambda node: not is_regmark(node))
|
@@ -2527,8 +2655,6 @@ def init_tree(kernel):
|
|
2527
2655
|
@tree_separator_before()
|
2528
2656
|
@tree_operation(_("Create placement"), node_type=elem_nodes, help="")
|
2529
2657
|
def regmark_as_placement(node, **kwargs):
|
2530
|
-
if node is None:
|
2531
|
-
return
|
2532
2658
|
if hasattr(node, "path"):
|
2533
2659
|
bb = node.path.bbox(transformed=False)
|
2534
2660
|
elif hasattr(node, "shape"):
|
@@ -2556,8 +2682,6 @@ def init_tree(kernel):
|
|
2556
2682
|
@tree_submenu(_("Toggle Magnet-Lines"))
|
2557
2683
|
@tree_operation(_("Around border"), node_type=elem_group_nodes, help="")
|
2558
2684
|
def regmark_to_magnet_1(node, **kwargs):
|
2559
|
-
if node is None:
|
2560
|
-
return
|
2561
2685
|
if not hasattr(node, "bounds"):
|
2562
2686
|
return
|
2563
2687
|
self.signal("magnet_gen", ("outer", node))
|
@@ -2566,18 +2690,10 @@ def init_tree(kernel):
|
|
2566
2690
|
@tree_submenu(_("Toggle Magnet-Lines"))
|
2567
2691
|
@tree_operation(_("At center"), node_type=elem_group_nodes, help="")
|
2568
2692
|
def regmark_to_magnet_2(node, **kwargs):
|
2569
|
-
if node is None:
|
2570
|
-
return
|
2571
2693
|
if not hasattr(node, "bounds"):
|
2572
2694
|
return
|
2573
2695
|
self.signal("magnet_gen", ("center", node))
|
2574
2696
|
|
2575
|
-
# @tree_conditional(lambda node: not node.lock)
|
2576
|
-
# @tree_conditional_try(lambda node: not node.lock)
|
2577
|
-
# @tree_operation(_("Actualize pixels"), node_type="elem image", help="")
|
2578
|
-
# def image_actualize_pixels(node, **kwargs):
|
2579
|
-
# self("image resample\n")
|
2580
|
-
|
2581
2697
|
@tree_conditional(lambda node: not node.lock)
|
2582
2698
|
@tree_submenu(_("Z-depth divide"))
|
2583
2699
|
@tree_iterate("divide", 2, 10)
|
@@ -2639,7 +2755,21 @@ def init_tree(kernel):
|
|
2639
2755
|
def image_ccw(node, **kwargs):
|
2640
2756
|
self("image ccw\n")
|
2641
2757
|
|
2758
|
+
@tree_conditional(lambda node: not node.lock)
|
2759
|
+
@tree_separator_before()
|
2760
|
+
@tree_submenu(_("Image"))
|
2761
|
+
@tree_operation(_("Identify inner white areas"), node_type="elem image", help="")
|
2762
|
+
def image_white_area(node, **kwargs):
|
2763
|
+
self("image innerwhite -l -o -m 2\n")
|
2764
|
+
|
2765
|
+
@tree_conditional(lambda node: not node.lock)
|
2642
2766
|
@tree_submenu(_("Image"))
|
2767
|
+
@tree_operation(_("Split image along white areas"), node_type="elem image", help="")
|
2768
|
+
def image_white_area_split(node, **kwargs):
|
2769
|
+
self("image innerwhite -w -o -m 2\n")
|
2770
|
+
|
2771
|
+
@tree_submenu(_("Image"))
|
2772
|
+
@tree_separator_before()
|
2643
2773
|
@tree_operation(
|
2644
2774
|
_("Save original image to output.png"), node_type="elem image", help=""
|
2645
2775
|
)
|
@@ -2653,6 +2783,16 @@ def init_tree(kernel):
|
|
2653
2783
|
def image_save_processed(node, **kwargs):
|
2654
2784
|
self("image save output.png --processed\n")
|
2655
2785
|
|
2786
|
+
@tree_conditional(lambda node: not node.lock and is_developer_mode())
|
2787
|
+
@tree_submenu(_("Convert"))
|
2788
|
+
@tree_operation(_("Raw Image"), node_type="elem image", help="")
|
2789
|
+
def image_convert_raw(node, **kwargs):
|
2790
|
+
node.replace_node(
|
2791
|
+
image=node.image,
|
2792
|
+
matrix=node.matrix,
|
2793
|
+
type="image raster",
|
2794
|
+
)
|
2795
|
+
|
2656
2796
|
@tree_conditional(lambda node: len(node.children) > 0)
|
2657
2797
|
@tree_separator_before()
|
2658
2798
|
@tree_operation(
|