meerk40t 0.9.7030__py2.py3-none-any.whl → 0.9.7050__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.
Files changed (85) hide show
  1. meerk40t/balormk/clone_loader.py +3 -2
  2. meerk40t/balormk/controller.py +38 -13
  3. meerk40t/balormk/cylindermod.py +1 -0
  4. meerk40t/balormk/device.py +13 -9
  5. meerk40t/balormk/driver.py +9 -2
  6. meerk40t/balormk/galvo_commands.py +3 -1
  7. meerk40t/balormk/gui/gui.py +6 -0
  8. meerk40t/balormk/livelightjob.py +338 -321
  9. meerk40t/balormk/mock_connection.py +4 -3
  10. meerk40t/balormk/usb_connection.py +11 -2
  11. meerk40t/camera/camera.py +19 -14
  12. meerk40t/camera/gui/camerapanel.py +6 -0
  13. meerk40t/core/cutplan.py +101 -78
  14. meerk40t/core/elements/element_treeops.py +435 -140
  15. meerk40t/core/elements/elements.py +100 -9
  16. meerk40t/core/elements/shapes.py +259 -72
  17. meerk40t/core/elements/tree_commands.py +10 -5
  18. meerk40t/core/node/blobnode.py +19 -4
  19. meerk40t/core/node/elem_ellipse.py +18 -8
  20. meerk40t/core/node/elem_image.py +51 -19
  21. meerk40t/core/node/elem_line.py +18 -8
  22. meerk40t/core/node/elem_path.py +18 -8
  23. meerk40t/core/node/elem_point.py +10 -4
  24. meerk40t/core/node/elem_polyline.py +19 -11
  25. meerk40t/core/node/elem_rect.py +18 -8
  26. meerk40t/core/node/elem_text.py +11 -5
  27. meerk40t/core/node/filenode.py +2 -8
  28. meerk40t/core/node/groupnode.py +11 -11
  29. meerk40t/core/node/image_processed.py +11 -5
  30. meerk40t/core/node/image_raster.py +11 -5
  31. meerk40t/core/node/node.py +64 -16
  32. meerk40t/core/node/refnode.py +2 -1
  33. meerk40t/core/planner.py +25 -11
  34. meerk40t/core/svg_io.py +91 -34
  35. meerk40t/device/dummydevice.py +7 -1
  36. meerk40t/extra/vtracer.py +222 -0
  37. meerk40t/grbl/device.py +96 -9
  38. meerk40t/grbl/driver.py +15 -5
  39. meerk40t/gui/about.py +20 -0
  40. meerk40t/gui/devicepanel.py +20 -16
  41. meerk40t/gui/gui_mixins.py +4 -0
  42. meerk40t/gui/icons.py +330 -253
  43. meerk40t/gui/laserpanel.py +27 -3
  44. meerk40t/gui/laserrender.py +41 -21
  45. meerk40t/gui/magnetoptions.py +158 -65
  46. meerk40t/gui/materialtest.py +569 -310
  47. meerk40t/gui/navigationpanels.py +229 -24
  48. meerk40t/gui/propertypanels/hatchproperty.py +2 -0
  49. meerk40t/gui/propertypanels/imageproperty.py +160 -106
  50. meerk40t/gui/propertypanels/wobbleproperty.py +6 -2
  51. meerk40t/gui/ribbon.py +6 -1
  52. meerk40t/gui/scenewidgets/gridwidget.py +29 -32
  53. meerk40t/gui/scenewidgets/rectselectwidget.py +190 -192
  54. meerk40t/gui/simulation.py +75 -77
  55. meerk40t/gui/spoolerpanel.py +27 -7
  56. meerk40t/gui/statusbarwidgets/defaultoperations.py +84 -48
  57. meerk40t/gui/statusbarwidgets/infowidget.py +2 -2
  58. meerk40t/gui/tips.py +15 -1
  59. meerk40t/gui/toolwidgets/toolpointmove.py +3 -1
  60. meerk40t/gui/wxmmain.py +242 -114
  61. meerk40t/gui/wxmscene.py +107 -24
  62. meerk40t/gui/wxmtree.py +4 -2
  63. meerk40t/gui/wxutils.py +286 -15
  64. meerk40t/image/imagetools.py +129 -65
  65. meerk40t/internal_plugins.py +4 -0
  66. meerk40t/kernel/kernel.py +67 -18
  67. meerk40t/kernel/settings.py +28 -9
  68. meerk40t/lihuiyu/device.py +24 -12
  69. meerk40t/main.py +14 -9
  70. meerk40t/moshi/device.py +20 -6
  71. meerk40t/network/console_server.py +22 -6
  72. meerk40t/newly/device.py +10 -3
  73. meerk40t/newly/gui/gui.py +10 -0
  74. meerk40t/ruida/device.py +22 -2
  75. meerk40t/ruida/loader.py +9 -4
  76. meerk40t/ruida/rdjob.py +48 -8
  77. meerk40t/tools/geomstr.py +240 -123
  78. meerk40t/tools/rasterplotter.py +185 -94
  79. {meerk40t-0.9.7030.dist-info → meerk40t-0.9.7050.dist-info}/METADATA +1 -1
  80. {meerk40t-0.9.7030.dist-info → meerk40t-0.9.7050.dist-info}/RECORD +85 -84
  81. {meerk40t-0.9.7030.dist-info → meerk40t-0.9.7050.dist-info}/LICENSE +0 -0
  82. {meerk40t-0.9.7030.dist-info → meerk40t-0.9.7050.dist-info}/WHEEL +0 -0
  83. {meerk40t-0.9.7030.dist-info → meerk40t-0.9.7050.dist-info}/entry_points.txt +0 -0
  84. {meerk40t-0.9.7030.dist-info → meerk40t-0.9.7050.dist-info}/top_level.txt +0 -0
  85. {meerk40t-0.9.7030.dist-info → meerk40t-0.9.7050.dist-info}/zip-safe +0 -0
@@ -17,6 +17,13 @@ from meerk40t.gui.icons import (
17
17
  icon_corner4,
18
18
  icon_fence_closed,
19
19
  icon_fence_open,
20
+ icon_z_down,
21
+ icon_z_down_double,
22
+ icon_z_down_triple,
23
+ icon_z_home,
24
+ icon_z_up,
25
+ icon_z_up_double,
26
+ icon_z_up_triple,
20
27
  icons8_caret_down,
21
28
  icons8_caret_left,
22
29
  icons8_caret_right,
@@ -50,8 +57,8 @@ from meerk40t.gui.wxutils import (
50
57
  StaticBoxSizer,
51
58
  TextCtrl,
52
59
  dip_size,
53
- wxStaticBitmap,
54
60
  wxBitmapButton,
61
+ wxStaticBitmap,
55
62
  wxStaticText,
56
63
  )
57
64
  from meerk40t.kernel import signal_listener
@@ -396,6 +403,169 @@ class TimerButtons:
396
403
  self.stop_timer(action=True)
397
404
 
398
405
 
406
+ class ZMovePanel(wx.Panel):
407
+ Z_SMALL = 1
408
+ Z_MEDIUM = 10
409
+ Z_LARGE = 100
410
+ # define your “steps” once
411
+ _BUTTON_SPECS = [
412
+ ("up", Z_SMALL, icon_z_up),
413
+ ("up", Z_MEDIUM, icon_z_up_double),
414
+ ("up", Z_LARGE, icon_z_up_triple),
415
+ ("home", None, icon_z_home),
416
+ ("down", Z_SMALL, icon_z_down),
417
+ ("down", Z_MEDIUM, icon_z_down_double),
418
+ ("down", Z_LARGE, icon_z_down_triple),
419
+ ]
420
+
421
+ def __init__(self, *args, context=None, **kwds):
422
+ # begin wxGlade: ZMovePanel.__init__
423
+ kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL
424
+ wx.Panel.__init__(self, *args, **kwds)
425
+ self.context = context
426
+ self.context.themes.set_window_colors(self)
427
+ self.SetHelpText("zmove")
428
+ self.icon_size = 15
429
+ self.resize_factor = 1
430
+ self.resolution = 1
431
+ self.buttons = {}
432
+ self.listening = False
433
+
434
+ for direction, step, icon in self._BUTTON_SPECS:
435
+ if direction == "home":
436
+ btnname = f"button_z_{direction}"
437
+ else:
438
+ btnname = f"button_z_{direction}_{step}"
439
+ btn = wx.StaticBitmap(self, wx.ID_ANY)
440
+ setattr(self, btnname, btn)
441
+ self.buttons[btnname] = (btn, direction, step, icon)
442
+
443
+ self.__set_properties()
444
+ self.__do_layout()
445
+ self.__do_logic()
446
+
447
+ def __do_logic(self):
448
+ self.timer = TimerButtons(self)
449
+ for btn, direction, step, icon in self.buttons.values():
450
+ if direction == "home":
451
+ btn.Bind(wx.EVT_LEFT_DOWN, self.z_home)
452
+ btn.Bind(wx.EVT_RIGHT_DOWN, self.z_focus)
453
+ else:
454
+ handler = (
455
+ self.z_move_up(step)
456
+ if direction == "up"
457
+ else self.z_move_down(step)
458
+ )
459
+ self.timer.add_button(btn, handler)
460
+ self.set_timer_options()
461
+
462
+ def __set_properties(self):
463
+ for btn, direction, step, icon in self.buttons.values():
464
+ if direction == "home":
465
+ tip = _("Move the laser to the defined Z-Home-Position")
466
+ else:
467
+ mm = step * 0.1
468
+ # _("Move the laserhead down by {mm} mm")
469
+ # _("Move the laserhead up by {mm} mm")
470
+ if direction == "up":
471
+ tip = _("Move the laser up by {mm}mm").format(mm=mm)
472
+ else:
473
+ tip = _("Move the laser down by {mm}mm").format(mm=mm)
474
+ btn.SetToolTip(tip)
475
+
476
+ def __do_layout(self):
477
+ # begin wxGlade: ZMovePanel.__do_layout
478
+ self.navigation_sizer = wx.BoxSizer(wx.VERTICAL)
479
+ for name in self.buttons:
480
+ self.navigation_sizer.Add(self.buttons[name][0], 0, 0)
481
+ self.SetSizer(self.navigation_sizer)
482
+ self.navigation_sizer.Fit(self)
483
+ self.set_icons(iconsize=10)
484
+ self.Layout()
485
+
486
+ def z_home(self, event=None):
487
+ self.context("z_home\n")
488
+
489
+ def z_focus(self, event=None):
490
+ if self.context.kernel.has_command("z_focus"):
491
+ self.context("z_focus\n")
492
+
493
+ def z_move_down(self, distance):
494
+ def handler():
495
+ self.context(f"z_move -{distance*0.1:.2f}mm")
496
+
497
+ return handler
498
+
499
+ def z_move_up(self, distance):
500
+ def handler():
501
+ self.context(f"z_move {distance*0.1:.2f}mm")
502
+
503
+ return handler
504
+
505
+ def set_icons(self, iconsize=None, dimension=None):
506
+ # orgsize = iconsize
507
+ if iconsize is None and dimension is not None:
508
+ dim_x = int(dimension[0] / 3) - 8
509
+ dim_y = int(dimension[1] / 4) - 8
510
+ iconsize = max(10, min(dim_x, dim_y))
511
+ # This is a bug within wxPython! It seems to appear only here at very high scale factors under windows
512
+ bmp = icon_z_home.GetBitmap(resize=self.icon_size, resolution=self.resolution)
513
+ s = bmp.Size
514
+ self.button_z_home.SetBitmap(bmp)
515
+ t = self.button_z_home.GetBitmap().Size
516
+ # print(f"Was asking for {best_size}x{best_size}, got {s[0]}x{s[1]}, button has {t[0]}x{t[1]}")
517
+ scale_x = s[0] / t[0]
518
+ scale_y = s[1] / t[1]
519
+ self.resize_factor = (self.icon_size * scale_x, self.icon_size * scale_y)
520
+
521
+ self.icon_size = iconsize
522
+ # print(f"Icon-Size set to {self.icon_size}, requested was {orgsize}")
523
+ for btn, direction, step, icon in self.buttons.values():
524
+ bmp = icon.GetBitmap(resize=self.resize_factor, resolution=self.resolution)
525
+ btn.SetBitmap(bmp)
526
+ self.navigation_sizer.Layout()
527
+ self.Layout()
528
+
529
+ def on_update(self, origin, *args):
530
+ has_home = self.context.kernel.has_command("z_home")
531
+ # print (f"Has_home for {self.context.device.name}: {has_home}")
532
+ self.button_z_home.Show(has_home)
533
+ tip = _("Move the laser to the defined Z-Home-Position")
534
+ if self.context.kernel.has_command("z_focus"):
535
+ tip += "\n" + _("Right click: autofocus the Z-Axis")
536
+
537
+ self.button_z_home.SetToolTip(tip)
538
+
539
+ self.navigation_sizer.Show(self.button_z_home, has_home)
540
+ self.navigation_sizer.Layout()
541
+
542
+ def pane_show(self, *args):
543
+ self.listening = True
544
+ self.context.listen("button-repeat", self.on_button_repeat)
545
+ self.context.listen("activate;device", self.on_update)
546
+ self.on_update(None)
547
+
548
+ def pane_hide(self, *args):
549
+ if self.listening:
550
+ self.context.unlisten("button-repeat", self.on_button_repeat)
551
+ self.context.unlisten("activate;device", self.on_update)
552
+ self.listening = False
553
+
554
+ def set_timer_options(self):
555
+ interval = self.context.button_repeat
556
+ if interval is None:
557
+ interval = 0.5
558
+ interval = max(0, interval)
559
+ accelerate = self.context.button_accelerate
560
+ if accelerate is None:
561
+ accelerate = True
562
+ self.timer.interval = interval
563
+ self.timer.accelerate = accelerate
564
+
565
+ def on_button_repeat(self, origin, *args):
566
+ self.set_timer_options()
567
+
568
+
399
569
  class Drag(wx.Panel):
400
570
  def __init__(self, *args, context=None, **kwds):
401
571
  # begin wxGlade: Drag.__init__
@@ -545,9 +715,7 @@ class Drag(wx.Panel):
545
715
  self.button_align_first_position.GetBestSize()
546
716
  )
547
717
  self.button_align_trace_hull.SetToolTip(
548
- _(
549
- "Perform a convex hull trace of the selection"
550
- )
718
+ _("Perform a convex hull trace of the selection")
551
719
  )
552
720
  self.button_align_trace_hull.SetSize(self.button_align_trace_hull.GetBestSize())
553
721
  self.button_align_trace_quick.SetToolTip(
@@ -920,7 +1088,7 @@ class Drag(wx.Panel):
920
1088
 
921
1089
 
922
1090
  class Jog(wx.Panel):
923
- def __init__(self, *args, context=None, **kwds):
1091
+ def __init__(self, *args, context=None, suppress_z_controls=False, **kwds):
924
1092
  # begin wxGlade: Jog.__init__
925
1093
  kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL
926
1094
 
@@ -935,6 +1103,7 @@ class Jog(wx.Panel):
935
1103
  self.icon_size = None
936
1104
  self.resize_factor = None
937
1105
  self.resolution = 5
1106
+ self.suppress_z_controls = suppress_z_controls
938
1107
  self.button_navigate_up_left = wxBitmapButton(self, wx.ID_ANY)
939
1108
  self.button_navigate_up = wxBitmapButton(self, wx.ID_ANY)
940
1109
  self.button_navigate_up_right = wxBitmapButton(self, wx.ID_ANY)
@@ -947,6 +1116,12 @@ class Jog(wx.Panel):
947
1116
  self.button_navigate_unlock = wxBitmapButton(self, wx.ID_ANY)
948
1117
  self.button_navigate_lock = wxBitmapButton(self, wx.ID_ANY)
949
1118
  self.button_confine = wxBitmapButton(self, wx.ID_ANY)
1119
+ self.z_axis = ZMovePanel(self, wx.ID_ANY, context=context)
1120
+ zshow = (
1121
+ getattr(self.context.device, "supports_z_axis", False)
1122
+ and not self.suppress_z_controls
1123
+ )
1124
+ self.z_axis.Show(zshow)
950
1125
  self.__set_properties()
951
1126
  self.__do_layout()
952
1127
  self.timer = TimerButtons(self)
@@ -965,7 +1140,9 @@ class Jog(wx.Panel):
965
1140
  self.Bind(
966
1141
  wx.EVT_BUTTON, self.on_button_navigate_home, self.button_navigate_home
967
1142
  )
968
- self.button_navigate_home.Bind(wx.EVT_MIDDLE_DOWN, self.on_button_navigate_jobstart)
1143
+ self.button_navigate_home.Bind(
1144
+ wx.EVT_MIDDLE_DOWN, self.on_button_navigate_jobstart
1145
+ )
969
1146
 
970
1147
  self.button_navigate_home.Bind(
971
1148
  wx.EVT_RIGHT_DOWN, self.on_button_navigate_physical_home
@@ -1026,6 +1203,7 @@ class Jog(wx.Panel):
1026
1203
 
1027
1204
  def __do_layout(self):
1028
1205
  # begin wxGlade: Jog.__do_layout
1206
+ self.main_sizer = wx.BoxSizer(wx.HORIZONTAL)
1029
1207
  self.navigation_sizer = wx.BoxSizer(wx.VERTICAL)
1030
1208
  button_sizer = wx.FlexGridSizer(4, 3, 0, 0)
1031
1209
  button_sizer.Add(self.button_navigate_up_left, 0, 0, 0)
@@ -1041,15 +1219,19 @@ class Jog(wx.Panel):
1041
1219
  button_sizer.Add(self.button_confine, 0, 0, 0)
1042
1220
  button_sizer.Add(self.button_navigate_lock, 0, 0, 0)
1043
1221
  self.navigation_sizer.Add(button_sizer, 1, wx.ALIGN_CENTER_HORIZONTAL, 0)
1044
- self.SetSizer(self.navigation_sizer)
1045
- self.navigation_sizer.Fit(self)
1222
+ self.main_sizer.Add(self.navigation_sizer, 0, wx.EXPAND)
1223
+ self.main_sizer.Add(self.z_axis, 0, wx.EXPAND)
1224
+ self.SetSizer(self.main_sizer)
1225
+ self.main_sizer.Fit(self)
1046
1226
  self.Layout()
1047
1227
 
1048
1228
  def set_icons(self, iconsize=None, dimension=None):
1229
+ cols = 4 if self.z_axis.IsShown() else 3
1049
1230
  if iconsize is None and dimension is not None:
1050
- dim_x = int(dimension[0] / 3) - 8
1231
+ dim_x = int(dimension[0] / cols) - 8
1051
1232
  dim_y = int(dimension[1] / 4) - 8
1052
1233
  iconsize = max(15, min(dim_x, dim_y))
1234
+ dimension = None
1053
1235
  self.icon_size = iconsize
1054
1236
  # This is a bug within wxPython! It seems to appear only here at very high scale factors under windows
1055
1237
  bmp = icons8_up_left.GetBitmap(
@@ -1116,6 +1298,11 @@ class Jog(wx.Panel):
1116
1298
  self.button_confine.SetBitmap(
1117
1299
  btn_icon.GetBitmap(resize=self.resize_factor, resolution=self.resolution)
1118
1300
  )
1301
+ if self.z_axis.IsShown():
1302
+ # Has 7 Buttons for our 4
1303
+ self.z_axis.set_icons(
1304
+ iconsize=int(round(4 / 7 * self.icon_size, 0)), dimension=dimension
1305
+ )
1119
1306
  self.navigation_sizer.Layout()
1120
1307
  self.Layout()
1121
1308
 
@@ -1215,7 +1402,7 @@ class Jog(wx.Panel):
1215
1402
  def move_rel(self, dx, dy):
1216
1403
  nx, ny = get_movement(self.context, dx, dy)
1217
1404
  self.context(f".move_relative {nx} {ny}\n")
1218
-
1405
+
1219
1406
  def on_button_navigate_jobstart(self, event):
1220
1407
  ops = self.context.elements.op_branch
1221
1408
  for op in ops.children:
@@ -1250,9 +1437,8 @@ class Jog(wx.Panel):
1250
1437
 
1251
1438
  def set_home_logic(self):
1252
1439
  tip = _("Send laser to home position")
1253
- if hasattr(self.context.device, "has_endstops"):
1254
- if self.context.device.has_endstops:
1255
- tip = _("Send laser to home position (right click: to physical home)")
1440
+ if getattr(self.context.device, "has_endstops", False):
1441
+ tip = _("Send laser to home position (right click: to physical home)")
1256
1442
  ops = self.context.elements.op_branch
1257
1443
  for op in ops.children:
1258
1444
  if op.type == "place point" and op.output:
@@ -1262,22 +1448,38 @@ class Jog(wx.Panel):
1262
1448
 
1263
1449
  def on_update(self, origin, *args):
1264
1450
  self.set_home_logic()
1451
+ self.set_z_support()
1452
+
1453
+ def set_z_support(self):
1454
+ show_z = (
1455
+ getattr(self.context.device, "supports_z_axis", False)
1456
+ and not self.suppress_z_controls
1457
+ )
1458
+ self.z_axis.Show(show_z)
1459
+ if show_z:
1460
+ self.z_axis.pane_show()
1461
+ else:
1462
+ self.z_axis.pane_hide()
1463
+ self.set_icons(iconsize=None, dimension=self.GetClientSize())
1464
+ self.main_sizer.Show(self.z_axis, show_z)
1465
+ self.main_sizer.Layout()
1265
1466
 
1266
1467
  def pane_show(self):
1267
1468
  self.context.listen("activate;device", self.on_update)
1268
1469
  self.context.listen("button-repeat", self.on_button_repeat)
1269
1470
  self.set_home_logic()
1471
+ self.set_z_support()
1270
1472
 
1271
1473
  def pane_hide(self):
1272
1474
  self.context.unlisten("activate;device", self.on_update)
1273
1475
  self.context.unlisten("button-repeat", self.on_button_repeat)
1476
+ self.z_axis.pane_hide()
1274
1477
 
1275
1478
  def set_timer_options(self):
1276
1479
  interval = self.context.button_repeat
1277
1480
  if interval is None:
1278
1481
  interval = 0.5
1279
- if interval < 0:
1280
- interval = 0
1482
+ interval = max(0, interval)
1281
1483
  accelerate = self.context.button_accelerate
1282
1484
  if accelerate is None:
1283
1485
  accelerate = True
@@ -1543,13 +1745,17 @@ class MovePanel(wx.Panel):
1543
1745
  # wrong device...
1544
1746
  return
1545
1747
  # New position...
1546
- p = self.context
1547
- units = p.units_name
1548
- xpos = Length(amount=pos[2], preferred_units=units)
1549
- ypos = Length(amount=pos[3], preferred_units=units)
1550
- self.label_pos.SetLabel(
1551
- f"{round(xpos.preferred, 6):.1f}{units}\n{round(ypos.preferred, 6):.1f}{units}"
1552
- )
1748
+ try:
1749
+ p = self.context
1750
+ units = p.units_name
1751
+ xpos = Length(amount=pos[2], preferred_units=units)
1752
+ ypos = Length(amount=pos[3], preferred_units=units)
1753
+ self.label_pos.SetLabel(
1754
+ f"{round(xpos.preferred, 6):.1f}{units}\n{round(ypos.preferred, 6):.1f}{units}"
1755
+ )
1756
+ except (ValueError, RuntimeError):
1757
+ # Already destroyed or invalid
1758
+ return
1553
1759
  self.label_pos.Refresh()
1554
1760
  # button_info_sizer.Layout()
1555
1761
  # self.GetSizer().Layout()
@@ -2192,8 +2398,7 @@ class Transform(wx.Panel):
2192
2398
  interval = self.context.button_repeat
2193
2399
  if interval is None:
2194
2400
  interval = 0.5
2195
- if interval < 0:
2196
- interval = 0
2401
+ interval = max(0, interval)
2197
2402
  accelerate = self.context.button_accelerate
2198
2403
  if accelerate is None:
2199
2404
  accelerate = True
@@ -11,6 +11,8 @@ _ = wx.GetTranslation
11
11
 
12
12
 
13
13
  class HatchPropertyPanel(ScrolledPanel):
14
+ name = _("Hatch")
15
+
14
16
  def __init__(self, *args, context=None, node=None, **kwds):
15
17
  # super().__init__(parent)
16
18
  kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL