meerk40t 0.9.7010__py2.py3-none-any.whl → 0.9.7020__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/galvo_commands.py +1 -2
- meerk40t/core/elements/branches.py +18 -4
- meerk40t/core/elements/element_treeops.py +34 -0
- meerk40t/core/elements/elements.py +49 -63
- meerk40t/core/elements/offset_clpr.py +4 -3
- meerk40t/core/elements/shapes.py +1 -1
- meerk40t/core/elements/testcases.py +105 -0
- meerk40t/core/node/op_cut.py +9 -8
- meerk40t/core/node/op_dots.py +8 -8
- meerk40t/core/node/op_engrave.py +7 -7
- meerk40t/core/node/op_raster.py +8 -8
- meerk40t/extra/encode_detect.py +8 -2
- meerk40t/extra/hershey.py +2 -3
- meerk40t/extra/inkscape.py +3 -5
- meerk40t/extra/outerworld.py +2 -3
- meerk40t/extra/param_functions.py +1 -1
- meerk40t/grbl/device.py +4 -1
- meerk40t/grbl/gui/grblcontroller.py +2 -2
- meerk40t/gui/busy.py +75 -13
- meerk40t/gui/choicepropertypanel.py +364 -375
- meerk40t/gui/consolepanel.py +3 -3
- meerk40t/gui/hersheymanager.py +13 -3
- meerk40t/gui/laserpanel.py +12 -7
- meerk40t/gui/materialmanager.py +33 -6
- meerk40t/gui/plugin.py +9 -3
- meerk40t/gui/propertypanels/operationpropertymain.py +1 -1
- meerk40t/gui/ribbon.py +4 -1
- meerk40t/gui/scene/widget.py +1 -1
- meerk40t/gui/scenewidgets/rectselectwidget.py +19 -16
- meerk40t/gui/scenewidgets/selectionwidget.py +26 -20
- meerk40t/gui/simpleui.py +13 -8
- meerk40t/gui/simulation.py +22 -2
- meerk40t/gui/spoolerpanel.py +2 -2
- meerk40t/gui/tips.py +2 -3
- meerk40t/gui/toolwidgets/toolmeasure.py +4 -1
- meerk40t/gui/wxmeerk40t.py +6 -3
- meerk40t/gui/wxmmain.py +72 -6
- meerk40t/gui/wxmscene.py +2 -6
- meerk40t/gui/wxmtree.py +17 -11
- meerk40t/gui/wxutils.py +1 -1
- meerk40t/image/imagetools.py +20 -5
- meerk40t/kernel/kernel.py +21 -2
- meerk40t/main.py +1 -1
- meerk40t/network/console_server.py +52 -14
- meerk40t/network/web_server.py +15 -1
- meerk40t/ruida/device.py +5 -1
- meerk40t/tools/polybool.py +2 -1
- meerk40t/tools/shxparser.py +92 -34
- {meerk40t-0.9.7010.dist-info → meerk40t-0.9.7020.dist-info}/METADATA +1 -1
- {meerk40t-0.9.7010.dist-info → meerk40t-0.9.7020.dist-info}/RECORD +55 -54
- {meerk40t-0.9.7010.dist-info → meerk40t-0.9.7020.dist-info}/LICENSE +0 -0
- {meerk40t-0.9.7010.dist-info → meerk40t-0.9.7020.dist-info}/WHEEL +0 -0
- {meerk40t-0.9.7010.dist-info → meerk40t-0.9.7020.dist-info}/entry_points.txt +0 -0
- {meerk40t-0.9.7010.dist-info → meerk40t-0.9.7020.dist-info}/top_level.txt +0 -0
- {meerk40t-0.9.7010.dist-info → meerk40t-0.9.7020.dist-info}/zip-safe +0 -0
meerk40t/gui/consolepanel.py
CHANGED
@@ -6,7 +6,7 @@ from wx import aui
|
|
6
6
|
|
7
7
|
from meerk40t.gui.icons import STD_ICON_SIZE, icons8_console
|
8
8
|
from meerk40t.gui.mwindow import MWindow
|
9
|
-
from meerk40t.kernel import
|
9
|
+
from meerk40t.kernel import signal_listener
|
10
10
|
from meerk40t.gui.wxutils import TextCtrl
|
11
11
|
|
12
12
|
try:
|
@@ -78,7 +78,7 @@ def register_panel_console(window, context):
|
|
78
78
|
aui.AuiPaneInfo()
|
79
79
|
.Bottom()
|
80
80
|
.Layer(2)
|
81
|
-
.MinSize(
|
81
|
+
.MinSize(100, 100)
|
82
82
|
.FloatingSize(600, 230)
|
83
83
|
.Caption(_("Console"))
|
84
84
|
.Name("console")
|
@@ -600,7 +600,7 @@ class ConsolePanel(wx.ScrolledWindow):
|
|
600
600
|
event.Skip(False)
|
601
601
|
|
602
602
|
def history_filename(self):
|
603
|
-
safe_dir =
|
603
|
+
safe_dir = self.context.kernel.os_information["WORKDIR"]
|
604
604
|
fname = os.path.join(safe_dir, "cmdhistory.log")
|
605
605
|
is_there = os.path.exists(fname)
|
606
606
|
return fname, is_there
|
meerk40t/gui/hersheymanager.py
CHANGED
@@ -283,9 +283,19 @@ class FontGlyphPicker(wx.Dialog):
|
|
283
283
|
return
|
284
284
|
as_stroke = getattr(cfont, "STROKE_BASED", False)
|
285
285
|
for c in cfont.glyphs:
|
286
|
-
if
|
286
|
+
if isinstance(c, str):
|
287
|
+
if len(c) > 1:
|
288
|
+
# print (f"Strange: {c}, use {idx} instead")
|
289
|
+
continue
|
290
|
+
if ord(c) == 65535:
|
291
|
+
continue
|
292
|
+
cstr = str(c)
|
293
|
+
elif isinstance(c, int):
|
294
|
+
if c == 65535:
|
295
|
+
continue
|
296
|
+
cstr = chr(c)
|
297
|
+
else:
|
287
298
|
continue
|
288
|
-
cstr = str(c)
|
289
299
|
hexa = cstr.encode("utf-8")
|
290
300
|
item = self.list_glyphs.InsertItem(self.list_glyphs.ItemCount, hexa)
|
291
301
|
self.list_glyphs.SetItem(item, 1, str(ord(cstr)))
|
@@ -294,7 +304,7 @@ class FontGlyphPicker(wx.Dialog):
|
|
294
304
|
try:
|
295
305
|
cfont.render(
|
296
306
|
path,
|
297
|
-
|
307
|
+
cstr,
|
298
308
|
True,
|
299
309
|
12.0,
|
300
310
|
1.0,
|
meerk40t/gui/laserpanel.py
CHANGED
@@ -18,7 +18,7 @@ from meerk40t.gui.icons import (
|
|
18
18
|
icons8_pentagon,
|
19
19
|
icons8_save,
|
20
20
|
)
|
21
|
-
from meerk40t.gui.navigationpanels import Drag, Jog, MovePanel
|
21
|
+
from meerk40t.gui.navigationpanels import Drag, Jog, MovePanel, JogDistancePanel
|
22
22
|
from meerk40t.gui.wxutils import (
|
23
23
|
HoverButton,
|
24
24
|
ScrolledPanel,
|
@@ -47,10 +47,14 @@ def register_panel_laser(window, context):
|
|
47
47
|
jog_drag.SetupScrolling()
|
48
48
|
jog_panel = Jog(jog_drag, wx.ID_ANY, context=context)
|
49
49
|
drag_panel = Drag(jog_drag, wx.ID_ANY, context=context)
|
50
|
-
|
50
|
+
distance_panel = JogDistancePanel(jog_drag, wx.ID_ANY, context=context)
|
51
|
+
main_sizer = wx.BoxSizer(wx.VERTICAL)
|
52
|
+
sub_sizer = wx.BoxSizer(wx.HORIZONTAL)
|
51
53
|
# main_sizer.AddStretchSpacer()
|
52
|
-
|
53
|
-
|
54
|
+
sub_sizer.Add(jog_panel, 1, wx.ALIGN_CENTER_VERTICAL, 0)
|
55
|
+
sub_sizer.Add(drag_panel, 1, wx.ALIGN_CENTER_VERTICAL, 0)
|
56
|
+
main_sizer.Add(sub_sizer, 1, wx.EXPAND, 0)
|
57
|
+
main_sizer.Add(distance_panel, 0, wx.EXPAND, 0)
|
54
58
|
# main_sizer.AddStretchSpacer()
|
55
59
|
jog_drag.SetSizer(main_sizer)
|
56
60
|
jog_drag.Layout()
|
@@ -97,7 +101,7 @@ def register_panel_laser(window, context):
|
|
97
101
|
page = notebook.GetCurrentPage()
|
98
102
|
if page is None:
|
99
103
|
return
|
100
|
-
pages = [jog_panel, drag_panel] if page is jog_drag else [page]
|
104
|
+
pages = [jog_panel, drag_panel, distance_panel] if page is jog_drag else [page]
|
101
105
|
for p in pages:
|
102
106
|
if hasattr(p, "pane_show"):
|
103
107
|
p.pane_show()
|
@@ -127,8 +131,9 @@ def register_panel_laser(window, context):
|
|
127
131
|
else:
|
128
132
|
panel_size = (wb_size[0] / 2, wb_size[1])
|
129
133
|
|
130
|
-
jog_panel
|
131
|
-
|
134
|
+
for panel in (jog_panel, drag_panel, distance_panel):
|
135
|
+
if hasattr(panel, "set_icons"):
|
136
|
+
panel.set_icons(dimension=panel_size)
|
132
137
|
|
133
138
|
jog_drag.Bind(wx.EVT_SIZE, on_resize)
|
134
139
|
|
meerk40t/gui/materialmanager.py
CHANGED
@@ -36,7 +36,6 @@ from meerk40t.gui.wxutils import (
|
|
36
36
|
wxStaticText,
|
37
37
|
wxTreeCtrl,
|
38
38
|
)
|
39
|
-
from meerk40t.kernel.kernel import get_safe_path
|
40
39
|
from meerk40t.kernel.settings import Settings
|
41
40
|
from meerk40t.svgelements import Color
|
42
41
|
|
@@ -389,6 +388,9 @@ class MaterialPanel(ScrolledPanel):
|
|
389
388
|
self.list_preview.AppendColumn(
|
390
389
|
_("Frequency") + " [kHz]", format=wx.LIST_FORMAT_LEFT, width=50
|
391
390
|
)
|
391
|
+
self.list_preview.AppendColumn(
|
392
|
+
_("Passes"), format=wx.LIST_FORMAT_LEFT, width=50
|
393
|
+
)
|
392
394
|
self.list_preview.resize_columns()
|
393
395
|
self.list_preview.SetToolTip(_("Click to select / Right click for actions"))
|
394
396
|
self.opinfo = {
|
@@ -919,7 +921,7 @@ class MaterialPanel(ScrolledPanel):
|
|
919
921
|
if len(oplist) == 0:
|
920
922
|
return
|
921
923
|
opinfo["author"] = last_author
|
922
|
-
directory =
|
924
|
+
directory = self.context.kernel.os_information["WORKDIR"]
|
923
925
|
local_file = os.path.join(directory, "op_export.cfg")
|
924
926
|
if os.path.exists(local_file):
|
925
927
|
try:
|
@@ -1317,6 +1319,9 @@ class MaterialPanel(ScrolledPanel):
|
|
1317
1319
|
self.op_data.write_persistent(
|
1318
1320
|
section_name, "passes", numeric_value
|
1319
1321
|
)
|
1322
|
+
self.op_data.write_persistent(
|
1323
|
+
section_name, "passes_custom", True
|
1324
|
+
)
|
1320
1325
|
elif param == "speed":
|
1321
1326
|
if numeric_value != 0:
|
1322
1327
|
speedval = numeric_value
|
@@ -1592,6 +1597,9 @@ class MaterialPanel(ScrolledPanel):
|
|
1592
1597
|
self.op_data.write_persistent(
|
1593
1598
|
section_name, "passes", numeric_value
|
1594
1599
|
)
|
1600
|
+
self.op_data.write_persistent(
|
1601
|
+
section_name, "passes_custom", True
|
1602
|
+
)
|
1595
1603
|
elif param == "markspeed":
|
1596
1604
|
if numeric_value != 0:
|
1597
1605
|
speedval = numeric_value
|
@@ -2066,6 +2074,7 @@ class MaterialPanel(ScrolledPanel):
|
|
2066
2074
|
oplabel = self.op_data.read_persistent(str, subsection, "label", "")
|
2067
2075
|
speed = self.op_data.read_persistent(str, subsection, "speed", "")
|
2068
2076
|
power = self.op_data.read_persistent(str, subsection, "power", "")
|
2077
|
+
passes = self.op_data.read_persistent(str, subsection, "passes", "")
|
2069
2078
|
frequency = self.op_data.read_persistent(
|
2070
2079
|
str, subsection, "frequency", ""
|
2071
2080
|
)
|
@@ -2074,6 +2083,8 @@ class MaterialPanel(ScrolledPanel):
|
|
2074
2083
|
command = self.op_data.read_persistent(str, subsection, "command", "")
|
2075
2084
|
if power == "" and optype.startswith("op "):
|
2076
2085
|
power = "1000"
|
2086
|
+
if passes == "" and optype.startswith("op "):
|
2087
|
+
passes = "1"
|
2077
2088
|
list_id = self.list_preview.InsertItem(
|
2078
2089
|
self.list_preview.GetItemCount(), f"#{idx}"
|
2079
2090
|
)
|
@@ -2093,6 +2104,7 @@ class MaterialPanel(ScrolledPanel):
|
|
2093
2104
|
self.list_preview.SetItem(list_id, 4, power)
|
2094
2105
|
self.list_preview.SetItem(list_id, 5, speed)
|
2095
2106
|
self.list_preview.SetItem(list_id, 6, frequency)
|
2107
|
+
self.list_preview.SetItem(list_id, 7, passes)
|
2096
2108
|
key = get_key(optype, opc)
|
2097
2109
|
if key in icon_dict:
|
2098
2110
|
imgid = icon_dict[key]
|
@@ -2576,6 +2588,7 @@ class MaterialPanel(ScrolledPanel):
|
|
2576
2588
|
"power": "1000",
|
2577
2589
|
"label": "Raster ({percent}, {speed}mm/s)",
|
2578
2590
|
"color": "#000000",
|
2591
|
+
"passes": "1",
|
2579
2592
|
}
|
2580
2593
|
if self.is_balor:
|
2581
2594
|
op_dict["frequency"] = "35"
|
@@ -2675,15 +2688,16 @@ class MaterialPanel(ScrolledPanel):
|
|
2675
2688
|
# 4 "Power"
|
2676
2689
|
# 5 "Speed"
|
2677
2690
|
# 6 "Frequency"
|
2691
|
+
# 7 "Passes"
|
2678
2692
|
if self.is_balor:
|
2679
2693
|
p1 = 0.15
|
2680
2694
|
p2 = 0.35
|
2681
|
-
p3 = (1.0 - p1 - p2) /
|
2695
|
+
p3 = (1.0 - p1 - p2) / 5
|
2682
2696
|
p4 = p3
|
2683
2697
|
else:
|
2684
2698
|
p1 = 0.15
|
2685
2699
|
p2 = 0.40
|
2686
|
-
p3 = (1.0 - p1 - p2) /
|
2700
|
+
p3 = (1.0 - p1 - p2) / 4
|
2687
2701
|
p4 = 0
|
2688
2702
|
self.list_preview.SetColumnWidth(0, int(p3 * remaining))
|
2689
2703
|
self.list_preview.SetColumnWidth(1, int(p1 * remaining))
|
@@ -2692,6 +2706,7 @@ class MaterialPanel(ScrolledPanel):
|
|
2692
2706
|
self.list_preview.SetColumnWidth(4, int(p3 * remaining))
|
2693
2707
|
self.list_preview.SetColumnWidth(5, int(p3 * remaining))
|
2694
2708
|
self.list_preview.SetColumnWidth(6, int(p4 * remaining))
|
2709
|
+
self.list_preview.SetColumnWidth(7, int(p3 * remaining))
|
2695
2710
|
|
2696
2711
|
def before_operation_update(self, event):
|
2697
2712
|
list_id = event.GetIndex() # Get the current row
|
@@ -2708,7 +2723,7 @@ class MaterialPanel(ScrolledPanel):
|
|
2708
2723
|
ok = False
|
2709
2724
|
except (AttributeError, KeyError):
|
2710
2725
|
ok = False
|
2711
|
-
if col_id not in range(2, 7):
|
2726
|
+
if col_id not in range(2, 7 + 1):
|
2712
2727
|
ok = False
|
2713
2728
|
if col_id == 6 and not self.is_balor:
|
2714
2729
|
ok = False
|
@@ -2724,7 +2739,7 @@ class MaterialPanel(ScrolledPanel):
|
|
2724
2739
|
index = self.list_preview.GetItemData(list_id)
|
2725
2740
|
key = self.get_nth_operation(index)
|
2726
2741
|
|
2727
|
-
if list_id >= 0 and col_id in range(2, 7):
|
2742
|
+
if list_id >= 0 and col_id in range(2, 7 + 1):
|
2728
2743
|
if col_id == 2:
|
2729
2744
|
# id
|
2730
2745
|
self.op_data.write_persistent(key, "id", new_data)
|
@@ -2761,6 +2776,18 @@ class MaterialPanel(ScrolledPanel):
|
|
2761
2776
|
except ValueError:
|
2762
2777
|
event.Veto()
|
2763
2778
|
return
|
2779
|
+
elif col_id == 7:
|
2780
|
+
# Passes
|
2781
|
+
try:
|
2782
|
+
new_data = int(new_data)
|
2783
|
+
if new_data < 1:
|
2784
|
+
new_data = 1
|
2785
|
+
self.op_data.write_persistent(key, "passes_custom", bool(new_data != 1))
|
2786
|
+
self.op_data.write_persistent(key, "passes", new_data)
|
2787
|
+
new_data = f"{new_data}"
|
2788
|
+
except ValueError:
|
2789
|
+
event.Veto()
|
2790
|
+
return
|
2764
2791
|
# Set the new data in the listctrl
|
2765
2792
|
self.op_data.write_configuration()
|
2766
2793
|
self.list_preview.SetItem(list_id, col_id, new_data)
|
meerk40t/gui/plugin.py
CHANGED
@@ -327,13 +327,19 @@ and a wxpython version <= 4.1.1."""
|
|
327
327
|
|
328
328
|
kernel.yesno = yesno_popup
|
329
329
|
|
330
|
-
from meerk40t.gui.busy import BusyInfo
|
330
|
+
from meerk40t.gui.busy import SimpleBusyInfo, BusyInfo
|
331
331
|
|
332
|
-
kargs = {}
|
332
|
+
kargs = {"kernel": kernel,}
|
333
333
|
if kernel.themes.dark:
|
334
334
|
kargs["bgcolor"] = kernel.themes.get("win_bg")
|
335
335
|
kargs["fgcolor"] = kernel.themes.get("win_fg")
|
336
|
-
kernel.
|
336
|
+
if kernel.os_information["OS_NAME"] != "Linux":
|
337
|
+
# The Linux implementation of wxWidgets
|
338
|
+
# cannot properly update controls (n idea why,
|
339
|
+
# any hint to circumvent this would be welcome)
|
340
|
+
kernel.busyinfo = BusyInfo(**kargs)
|
341
|
+
else:
|
342
|
+
kernel.busyinfo = SimpleBusyInfo(**kargs)
|
337
343
|
|
338
344
|
@kernel.console_argument("message")
|
339
345
|
@kernel.console_command("notify", hidden=True)
|
meerk40t/gui/ribbon.py
CHANGED
@@ -563,7 +563,10 @@ class Button:
|
|
563
563
|
"""
|
564
564
|
|
565
565
|
def toggle_click(origin, *args):
|
566
|
-
|
566
|
+
# Whats the value to set?
|
567
|
+
set_value = args[0] if args else not self.toggle
|
568
|
+
# But if we have a toggle_attr then this has precedence
|
569
|
+
set_value = getattr(self.object, self.toggle_attr) if self.toggle_attr else set_value
|
567
570
|
self.set_button_toggle(set_value)
|
568
571
|
|
569
572
|
self.context.listen(signal, toggle_click)
|
meerk40t/gui/scene/widget.py
CHANGED
@@ -257,22 +257,25 @@ class RectSelectWidget(Widget):
|
|
257
257
|
"""
|
258
258
|
Calculates the shortest distance between two arrays of 2-dimensional points.
|
259
259
|
"""
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
260
|
+
try:
|
261
|
+
# Calculate the Euclidean distance between each point in p1 and p2
|
262
|
+
if tuplemode:
|
263
|
+
# For an array of tuples:
|
264
|
+
dist = np.sqrt(np.sum((p1[:, np.newaxis] - p2) ** 2, axis=2))
|
265
|
+
else:
|
266
|
+
# For an array of complex numbers
|
267
|
+
dist = np.abs(p1[:, np.newaxis] - p2[np.newaxis, :])
|
268
|
+
|
269
|
+
# Find the minimum distance and its corresponding indices
|
270
|
+
min_dist = np.min(dist)
|
271
|
+
if np.isnan(min_dist):
|
272
|
+
return None, 0, 0
|
273
|
+
min_indices = np.argwhere(dist == min_dist)
|
274
|
+
|
275
|
+
# Return the coordinates of the two points
|
276
|
+
return min_dist, p1[min_indices[0][0]], p2[min_indices[0][1]]
|
277
|
+
except Exception: # out of memory eg
|
278
|
+
return None, None, None
|
276
279
|
|
277
280
|
b = self.scene.context.elements._emphasized_bounds
|
278
281
|
if b is None:
|
@@ -31,6 +31,7 @@ from meerk40t.gui.scene.scene import (
|
|
31
31
|
from meerk40t.gui.scene.sceneconst import HITCHAIN_HIT_AND_DELEGATE
|
32
32
|
from meerk40t.gui.scene.widget import Widget
|
33
33
|
from meerk40t.gui.wxutils import (
|
34
|
+
dip_size,
|
34
35
|
StaticBoxSizer,
|
35
36
|
create_menu_for_node,
|
36
37
|
get_gc_full_scale,
|
@@ -268,7 +269,7 @@ class BorderWidget(Widget):
|
|
268
269
|
if self.show_rb:
|
269
270
|
gc.StrokeLine(sx * center_x, sy * self.bottom, sx * center_x, sy * bed_h)
|
270
271
|
gc.StrokeLine(sx * self.right, sy * center_y, sx * bed_w, sy * center_y)
|
271
|
-
|
272
|
+
|
272
273
|
mypen.SetStyle(wx.PENSTYLE_DOT)
|
273
274
|
gc.SetPen(mypen)
|
274
275
|
gc.StrokeLine(sx * self.left, sy * self.top, sx * self.right, sy * self.top)
|
@@ -335,7 +336,7 @@ class BorderWidget(Widget):
|
|
335
336
|
s_txt = str(Length(amount=rpos, digits=2, preferred_units=units))
|
336
337
|
(t_width, t_height) = gc.GetTextExtent(s_txt)
|
337
338
|
pos = self.right + rpos / 2.0 - t_width / 2
|
338
|
-
if pos -
|
339
|
+
if pos - distance <= self.right:
|
339
340
|
pos = self.right + distance
|
340
341
|
gc.DrawText(s_txt, pos, center_y)
|
341
342
|
|
@@ -1610,23 +1611,26 @@ class MoveWidget(Widget):
|
|
1610
1611
|
"""
|
1611
1612
|
Calculates the shortest distance between two arrays of 2-dimensional points.
|
1612
1613
|
"""
|
1613
|
-
|
1614
|
-
|
1615
|
-
|
1616
|
-
|
1617
|
-
|
1618
|
-
|
1619
|
-
|
1620
|
-
|
1621
|
-
|
1622
|
-
|
1623
|
-
|
1624
|
-
|
1625
|
-
|
1626
|
-
|
1627
|
-
|
1628
|
-
|
1629
|
-
|
1614
|
+
try:
|
1615
|
+
# Calculate the Euclidean distance between each point in p1 and p2
|
1616
|
+
if tuplemode:
|
1617
|
+
# For an array of tuples:
|
1618
|
+
dist = np.sqrt(np.sum((p1[:, np.newaxis] - p2) ** 2, axis=2))
|
1619
|
+
else:
|
1620
|
+
# For an array of complex numbers
|
1621
|
+
dist = np.abs(p1[:, np.newaxis] - p2[np.newaxis, :])
|
1622
|
+
# Find the minimum distance and its corresponding indices
|
1623
|
+
min_dist = np.min(dist)
|
1624
|
+
if np.isnan(min_dist):
|
1625
|
+
# print (f"Encountered the infamous bug: {p1} {p2}")
|
1626
|
+
# Still need an example when that happens
|
1627
|
+
return None, 0, 0
|
1628
|
+
min_indices = np.argwhere(dist == min_dist)
|
1629
|
+
|
1630
|
+
# Return the coordinates of the two points
|
1631
|
+
return min_dist, p1[min_indices[0][0]], p2[min_indices[0][1]]
|
1632
|
+
except Exception: # out of memory eg
|
1633
|
+
return None, None, None
|
1630
1634
|
|
1631
1635
|
b = elements._emphasized_bounds
|
1632
1636
|
if b is None:
|
@@ -2390,6 +2394,8 @@ class SelectionWidget(Widget):
|
|
2390
2394
|
self.handle_pen.SetStyle(wx.PENSTYLE_SOLID)
|
2391
2395
|
# want to have sharp edges
|
2392
2396
|
self.handle_pen.SetJoin(wx.JOIN_MITER)
|
2397
|
+
fact = dip_size(self.scene.pane, 100, 100)
|
2398
|
+
self.font_size_factor = (fact[0] + fact[1]) / 100 * 0.5
|
2393
2399
|
|
2394
2400
|
self.gc = None
|
2395
2401
|
self.reset_variables()
|
@@ -2797,7 +2803,7 @@ class SelectionWidget(Widget):
|
|
2797
2803
|
try:
|
2798
2804
|
factor = math.sqrt(abs(matrix.determinant))
|
2799
2805
|
self.line_width = 2.0 / factor
|
2800
|
-
self.font_size =
|
2806
|
+
self.font_size = 12.0 / factor * self.font_size_factor
|
2801
2807
|
except ZeroDivisionError:
|
2802
2808
|
matrix.reset()
|
2803
2809
|
return
|
meerk40t/gui/simpleui.py
CHANGED
@@ -13,7 +13,7 @@ from wx import aui
|
|
13
13
|
from ..core.exceptions import BadFileError
|
14
14
|
from .icons import get_default_icon_size, icons8_computer_support, icons8_opened_folder
|
15
15
|
from .mwindow import MWindow
|
16
|
-
from .navigationpanels import Drag, Jog
|
16
|
+
from .navigationpanels import Drag, Jog, JogDistancePanel
|
17
17
|
from .wxutils import StaticBoxSizer, TextCtrl, wxButton, wxStaticText
|
18
18
|
|
19
19
|
_ = wx.GetTranslation
|
@@ -26,19 +26,24 @@ class JogMovePanel(wx.Panel):
|
|
26
26
|
wx.Panel.__init__(self, *args, **kwds)
|
27
27
|
self.context = context
|
28
28
|
self.context.themes.set_window_colors(self)
|
29
|
-
|
29
|
+
distance_panel = JogDistancePanel(self, wx.ID_ANY, context=context)
|
30
30
|
jog_panel = Jog(self, wx.ID_ANY, context=context)
|
31
31
|
drag_panel = Drag(self, wx.ID_ANY, context=context)
|
32
|
-
self.panels = [jog_panel, drag_panel]
|
33
|
-
self.main_sizer = wx.BoxSizer(wx.
|
34
|
-
self.
|
35
|
-
self.
|
32
|
+
self.panels = [distance_panel, jog_panel, drag_panel]
|
33
|
+
self.main_sizer = wx.BoxSizer(wx.VERTICAL)
|
34
|
+
self.jog_sizer = wx.BoxSizer(wx.HORIZONTAL)
|
35
|
+
self.jog_sizer.Add(jog_panel, 1, wx.EXPAND, 0)
|
36
|
+
self.jog_sizer.Add(drag_panel, 1, wx.EXPAND, 0)
|
37
|
+
self.main_sizer.Add(distance_panel, 0, wx.EXPAND, 0)
|
38
|
+
self.main_sizer.Add(self.jog_sizer, 1, wx.EXPAND, 0)
|
36
39
|
self.SetSizer(self.main_sizer)
|
37
40
|
self.Layout()
|
38
41
|
self.Bind(wx.EVT_SIZE, self.on_resize)
|
42
|
+
# Force initial resizing
|
43
|
+
wx.CallAfter(self.on_resize)
|
39
44
|
|
40
|
-
def on_resize(self, event):
|
41
|
-
wb_size =
|
45
|
+
def on_resize(self, event=None):
|
46
|
+
wb_size = self.jog_sizer.GetSize()
|
42
47
|
panel_size = (wb_size[0] / 2, wb_size[1])
|
43
48
|
for p in self.panels:
|
44
49
|
if hasattr(p, "set_icons"):
|
meerk40t/gui/simulation.py
CHANGED
@@ -823,7 +823,7 @@ class SimulationPanel(wx.Panel, Job):
|
|
823
823
|
job_name="cache_updater",
|
824
824
|
interval=0.25,
|
825
825
|
times=1,
|
826
|
-
run_main=
|
826
|
+
run_main=True,
|
827
827
|
)
|
828
828
|
|
829
829
|
self.job_name = "simulate"
|
@@ -1573,6 +1573,8 @@ class SimulationPanel(wx.Panel, Job):
|
|
1573
1573
|
self._stop()
|
1574
1574
|
return
|
1575
1575
|
# Refresh cutcode
|
1576
|
+
self.SetCursor(wx.Cursor(wx.CURSOR_WAIT))
|
1577
|
+
|
1576
1578
|
if self.plan_name:
|
1577
1579
|
self.cutplan = self.context.planner.get_or_make_plan(self.plan_name)
|
1578
1580
|
else:
|
@@ -1621,6 +1623,8 @@ class SimulationPanel(wx.Panel, Job):
|
|
1621
1623
|
|
1622
1624
|
self._startup()
|
1623
1625
|
self.request_refresh()
|
1626
|
+
self.SetCursor(wx.Cursor(wx.CURSOR_ARROW))
|
1627
|
+
|
1624
1628
|
|
1625
1629
|
@signal_listener("device;modified")
|
1626
1630
|
@signal_listener("plan")
|
@@ -1685,7 +1689,11 @@ class SimulationPanel(wx.Panel, Job):
|
|
1685
1689
|
self.options_optimize.Enable(False)
|
1686
1690
|
|
1687
1691
|
def cache_updater(self):
|
1688
|
-
|
1692
|
+
try:
|
1693
|
+
self.button_spool.Enable(False)
|
1694
|
+
except RuntimeError:
|
1695
|
+
# Control no longer existant
|
1696
|
+
return
|
1689
1697
|
msg = self.button_spool.GetLabel()
|
1690
1698
|
self.button_spool.SetLabel(_("Calculating"))
|
1691
1699
|
for cut in self.cutcode:
|
@@ -1837,6 +1845,15 @@ class SimulationPanel(wx.Panel, Job):
|
|
1837
1845
|
event.Skip()
|
1838
1846
|
|
1839
1847
|
def on_redo_it(self, event):
|
1848
|
+
# Dont occupy gui event handling too long
|
1849
|
+
wx.CallAfter(self.redo_action)
|
1850
|
+
|
1851
|
+
def redo_action(self):
|
1852
|
+
self.SetCursor(wx.Cursor(wx.CURSOR_WAIT))
|
1853
|
+
self.btn_redo_it.SetLabel(_("Preparing simulation..."))
|
1854
|
+
self.btn_redo_it.Enable(False)
|
1855
|
+
self.btn_redo_it.Refresh()
|
1856
|
+
self.btn_redo_it.Update()
|
1840
1857
|
busy = self.context.kernel.busyinfo
|
1841
1858
|
busy.start(msg=_("Preparing simulation..."))
|
1842
1859
|
|
@@ -1853,6 +1870,9 @@ class SimulationPanel(wx.Panel, Job):
|
|
1853
1870
|
)
|
1854
1871
|
busy.end()
|
1855
1872
|
self._refresh_simulated_plan()
|
1873
|
+
self.btn_redo_it.Enable(True)
|
1874
|
+
self.btn_redo_it.SetLabel(_("Recalculate"))
|
1875
|
+
self.SetCursor(wx.Cursor(wx.CURSOR_ARROW))
|
1856
1876
|
|
1857
1877
|
def pane_show(self):
|
1858
1878
|
self.Layout()
|
meerk40t/gui/spoolerpanel.py
CHANGED
@@ -23,7 +23,7 @@ from meerk40t.gui.wxutils import (
|
|
23
23
|
wxListCtrl,
|
24
24
|
wxStaticText,
|
25
25
|
)
|
26
|
-
from meerk40t.kernel import Job,
|
26
|
+
from meerk40t.kernel import Job, signal_listener
|
27
27
|
|
28
28
|
_ = wx.GetTranslation
|
29
29
|
|
@@ -330,7 +330,7 @@ class SpoolerPanel(wx.Panel):
|
|
330
330
|
self.current_item = event.Index
|
331
331
|
|
332
332
|
def write_csv(self):
|
333
|
-
filename = Path(
|
333
|
+
filename = Path(self.context.kernel.os_information["WORKDIR"]).joinpath(
|
334
334
|
"history.csv"
|
335
335
|
)
|
336
336
|
if self.filter_device:
|
meerk40t/gui/tips.py
CHANGED
@@ -11,7 +11,6 @@ import webbrowser
|
|
11
11
|
|
12
12
|
import wx
|
13
13
|
|
14
|
-
from ..kernel import get_safe_path
|
15
14
|
from .icons import (
|
16
15
|
icon_outline,
|
17
16
|
icon_youtube,
|
@@ -43,7 +42,7 @@ class TipPanel(wx.Panel):
|
|
43
42
|
self.tip_image = ""
|
44
43
|
self.tips = []
|
45
44
|
|
46
|
-
safe_dir =
|
45
|
+
safe_dir = self.context.kernel.os_information["WORKDIR"]
|
47
46
|
self.local_file = os.path.join(safe_dir, "tips.txt")
|
48
47
|
|
49
48
|
self.setup_tips()
|
@@ -538,7 +537,7 @@ class TipPanel(wx.Panel):
|
|
538
537
|
Check for existence of a subdirectory to store images
|
539
538
|
and create it if not found
|
540
539
|
"""
|
541
|
-
safe_dir =
|
540
|
+
safe_dir = self.context.kernel.os_information["WORKDIR"]
|
542
541
|
cache_dir = os.path.join(safe_dir, "tip_images")
|
543
542
|
if not os.path.exists(cache_dir):
|
544
543
|
try:
|
@@ -3,7 +3,7 @@ from math import atan2, cos, sin, sqrt, tau
|
|
3
3
|
import wx
|
4
4
|
|
5
5
|
from meerk40t.core.units import Length
|
6
|
-
from meerk40t.gui.wxutils import get_matrix_scale, get_gc_scale
|
6
|
+
from meerk40t.gui.wxutils import get_matrix_scale, get_gc_scale, dip_size
|
7
7
|
|
8
8
|
from .toolpointlistbuilder import PointListTool
|
9
9
|
|
@@ -24,6 +24,8 @@ class MeasureTool(PointListTool):
|
|
24
24
|
self.line_pen.SetColour(self.scene.colors.color_measure_line)
|
25
25
|
self.line_pen.SetStyle(wx.PENSTYLE_DOT)
|
26
26
|
self.line_pen.SetWidth(1000)
|
27
|
+
fact = dip_size(self.scene.pane, 100, 100)
|
28
|
+
self.font_size_factor = (fact[0] + fact[1]) / 100 * 0.5
|
27
29
|
|
28
30
|
def create_node(self):
|
29
31
|
# No need to create anything
|
@@ -43,6 +45,7 @@ class MeasureTool(PointListTool):
|
|
43
45
|
font_size = 5000
|
44
46
|
if font_size > 1e8:
|
45
47
|
font_size = 5000
|
48
|
+
font_size *= self.font_size_factor
|
46
49
|
# print ("Fontsize=%.3f, " % self.font_size)
|
47
50
|
if font_size < 1.0:
|
48
51
|
font_size = 1.0 # Mac does not allow values lower than 1.
|
meerk40t/gui/wxmeerk40t.py
CHANGED
@@ -500,7 +500,8 @@ class wxMeerK40t(wx.App, Module):
|
|
500
500
|
|
501
501
|
def OnInit(self):
|
502
502
|
self.name = f"MeerK40t-{wx.GetUserId()}"
|
503
|
-
|
503
|
+
mkdir = self.context.kernel.os_information["OS_TEMPDIR"]
|
504
|
+
self.instance = wx.SingleInstanceChecker(self.name, path=mkdir)
|
504
505
|
self.context.setting(bool, "single_instance_only", True)
|
505
506
|
if self.context.kernel._was_restarted:
|
506
507
|
return True
|
@@ -560,15 +561,17 @@ class wxMeerK40t(wx.App, Module):
|
|
560
561
|
def MacOpenFile(self, filename):
|
561
562
|
try:
|
562
563
|
if self.context is not None:
|
563
|
-
self.context.
|
564
|
+
channel = self.context.kernel.channel("console")
|
565
|
+
self.context.elements.load(os.path.realpath(filename), svg_ppi=self.context.elements.svg_ppi, channel=channel)
|
564
566
|
except AttributeError:
|
565
567
|
pass
|
566
568
|
|
567
569
|
def MacOpenFiles(self, filenames):
|
568
570
|
try:
|
569
571
|
if self.context is not None:
|
572
|
+
channel = self.context.kernel.channel("console")
|
570
573
|
for filename in filenames:
|
571
|
-
self.context.elements.load(os.path.realpath(filename))
|
574
|
+
self.context.elements.load(os.path.realpath(filename), svg_ppi=self.context.elements.svg_ppi, channel=channel)
|
572
575
|
except AttributeError:
|
573
576
|
pass
|
574
577
|
|