meerk40t 0.9.7910__py2.py3-none-any.whl → 0.9.7940__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/controller.py +46 -13
- meerk40t/balormk/livelightjob.py +34 -7
- meerk40t/core/bindalias.py +12 -4
- meerk40t/core/cutcode/plotcut.py +2 -1
- meerk40t/core/elements/branches.py +35 -14
- meerk40t/core/elements/clipboard.py +10 -12
- meerk40t/core/elements/elements.py +23 -0
- meerk40t/core/elements/files.py +1 -1
- meerk40t/core/elements/geometry.py +48 -14
- meerk40t/core/elements/grid.py +56 -24
- meerk40t/core/elements/offset_clpr.py +2 -4
- meerk40t/core/elements/placements.py +17 -22
- meerk40t/core/elements/render.py +30 -11
- meerk40t/core/elements/shapes.py +206 -126
- meerk40t/core/node/effect_hatch.py +8 -7
- meerk40t/core/node/effect_warp.py +7 -2
- meerk40t/core/node/effect_wobble.py +8 -2
- meerk40t/core/node/op_image.py +79 -25
- meerk40t/core/spoolers.py +1 -1
- meerk40t/core/units.py +4 -0
- meerk40t/grbl/emulator.py +10 -8
- meerk40t/grbl/gcodejob.py +11 -3
- meerk40t/grbl/plugin.py +10 -1
- meerk40t/gui/help_assets/help_assets.py +402 -43
- meerk40t/gui/plugin.py +12 -0
- meerk40t/gui/tips.py +78 -41
- meerk40t/gui/wxmmain.py +99 -4
- meerk40t/lihuiyu/driver.py +46 -9
- meerk40t/main.py +1 -1
- meerk40t/ruida/emulator.py +13 -10
- meerk40t/ruida/plugin.py +5 -0
- meerk40t/ruida/rdjob.py +5 -5
- meerk40t/tools/geomstr.py +15 -0
- {meerk40t-0.9.7910.dist-info → meerk40t-0.9.7940.dist-info}/METADATA +1 -1
- {meerk40t-0.9.7910.dist-info → meerk40t-0.9.7940.dist-info}/RECORD +40 -40
- {meerk40t-0.9.7910.dist-info → meerk40t-0.9.7940.dist-info}/LICENSE +0 -0
- {meerk40t-0.9.7910.dist-info → meerk40t-0.9.7940.dist-info}/WHEEL +0 -0
- {meerk40t-0.9.7910.dist-info → meerk40t-0.9.7940.dist-info}/entry_points.txt +0 -0
- {meerk40t-0.9.7910.dist-info → meerk40t-0.9.7940.dist-info}/top_level.txt +0 -0
- {meerk40t-0.9.7910.dist-info → meerk40t-0.9.7940.dist-info}/zip-safe +0 -0
@@ -210,7 +210,6 @@ class WarpEffectNode(Node, FunctionalParameter):
|
|
210
210
|
self.d3 = complex(nn3.x - pp3.x, nn3.y - pp3.y)
|
211
211
|
self.d4 = complex(nn4.x - pp4.x, nn4.y - pp4.y)
|
212
212
|
|
213
|
-
|
214
213
|
def default_map(self, default_map=None):
|
215
214
|
default_map = super().default_map(default_map=default_map)
|
216
215
|
default_map["element_type"] = "Warp"
|
@@ -229,6 +228,8 @@ class WarpEffectNode(Node, FunctionalParameter):
|
|
229
228
|
subs = right_types(e)
|
230
229
|
res.extend(subs)
|
231
230
|
elif e.type.startswith("elem"):
|
231
|
+
if hasattr(e, "hidden") and e.hidden:
|
232
|
+
continue
|
232
233
|
res.append(e)
|
233
234
|
return res
|
234
235
|
|
@@ -297,7 +298,11 @@ class WarpEffectNode(Node, FunctionalParameter):
|
|
297
298
|
self.altered()
|
298
299
|
|
299
300
|
def can_drop(self, drag_node):
|
300
|
-
if
|
301
|
+
if (
|
302
|
+
hasattr(drag_node, "as_geometry")
|
303
|
+
or drag_node.type in ("effect", "file", "group", "reference")
|
304
|
+
or (drag_node.type.startswith("op ") and drag_node.type != "op dots")
|
305
|
+
):
|
301
306
|
return True
|
302
307
|
return False
|
303
308
|
|
@@ -2,8 +2,8 @@ import math
|
|
2
2
|
from copy import copy
|
3
3
|
from math import sqrt
|
4
4
|
|
5
|
-
from meerk40t.core.node.node import Node
|
6
5
|
from meerk40t.core.node.mixins import Suppressable
|
6
|
+
from meerk40t.core.node.node import Node
|
7
7
|
from meerk40t.core.units import Length
|
8
8
|
from meerk40t.svgelements import Color
|
9
9
|
from meerk40t.tools.geomstr import Geomstr # , Scanbeam
|
@@ -225,6 +225,8 @@ class WobbleEffectNode(Node, Suppressable):
|
|
225
225
|
subs = right_types(e)
|
226
226
|
res.extend(subs)
|
227
227
|
elif e.type.startswith("elem"):
|
228
|
+
if hasattr(e, "hidden") and e.hidden:
|
229
|
+
continue
|
228
230
|
res.append(e)
|
229
231
|
return res
|
230
232
|
|
@@ -384,7 +386,11 @@ class WobbleEffectNode(Node, Suppressable):
|
|
384
386
|
self.altered()
|
385
387
|
|
386
388
|
def can_drop(self, drag_node):
|
387
|
-
if
|
389
|
+
if (
|
390
|
+
hasattr(drag_node, "as_geometry")
|
391
|
+
or drag_node.type in ("effect", "file", "group", "reference")
|
392
|
+
or (drag_node.type.startswith("op ") and drag_node.type != "op dots")
|
393
|
+
):
|
388
394
|
return True
|
389
395
|
return False
|
390
396
|
|
meerk40t/core/node/op_image.py
CHANGED
@@ -21,16 +21,17 @@ Methods:
|
|
21
21
|
"""
|
22
22
|
from copy import copy
|
23
23
|
from math import isnan
|
24
|
+
|
24
25
|
from meerk40t.constants import (
|
25
|
-
RASTER_T2B,
|
26
26
|
RASTER_B2T,
|
27
|
-
|
28
|
-
RASTER_L2R,
|
29
|
-
RASTER_HATCH,
|
27
|
+
RASTER_CROSSOVER,
|
30
28
|
RASTER_GREEDY_H,
|
31
29
|
RASTER_GREEDY_V,
|
32
|
-
|
30
|
+
RASTER_HATCH,
|
31
|
+
RASTER_L2R,
|
32
|
+
RASTER_R2L,
|
33
33
|
RASTER_SPIRAL,
|
34
|
+
RASTER_T2B,
|
34
35
|
)
|
35
36
|
from meerk40t.core.cutcode.rastercut import RasterCut
|
36
37
|
from meerk40t.core.elements.element_types import *
|
@@ -67,7 +68,13 @@ class ImageOpNode(Node, Parameters):
|
|
67
68
|
super().__init__(type="op image", **kwargs)
|
68
69
|
self._formatter = "{enabled}{pass}{element_type}{direction}{speed}mm/s @{power}"
|
69
70
|
# They might come from a svg read, but shouldnt be in settings
|
70
|
-
for attrib in (
|
71
|
+
for attrib in (
|
72
|
+
"lock",
|
73
|
+
"dangerous",
|
74
|
+
"use_grayscale",
|
75
|
+
"consider_laserspot",
|
76
|
+
"overrule_dpi",
|
77
|
+
):
|
71
78
|
if attrib in self.settings:
|
72
79
|
del self.settings[attrib]
|
73
80
|
|
@@ -146,7 +153,9 @@ class ImageOpNode(Node, Parameters):
|
|
146
153
|
# Move operation to a different position.
|
147
154
|
return True
|
148
155
|
elif drag_node.type in ("file", "group"):
|
149
|
-
return not any(
|
156
|
+
return not any(
|
157
|
+
e.has_ancestor("branch reg") for e in drag_node.flat(elem_nodes)
|
158
|
+
)
|
150
159
|
return False
|
151
160
|
|
152
161
|
def drop(self, drag_node, modify=True, flag=False):
|
@@ -255,8 +264,12 @@ class ImageOpNode(Node, Parameters):
|
|
255
264
|
height_in_inches = (max_y - min_y) / UNITS_PER_INCH
|
256
265
|
speed_in_per_s = self.speed / MM_PER_INCH
|
257
266
|
if self.raster_direction in (
|
258
|
-
RASTER_T2B,
|
259
|
-
|
267
|
+
RASTER_T2B,
|
268
|
+
RASTER_B2T,
|
269
|
+
RASTER_HATCH,
|
270
|
+
RASTER_GREEDY_H,
|
271
|
+
RASTER_CROSSOVER,
|
272
|
+
RASTER_SPIRAL,
|
260
273
|
):
|
261
274
|
scanlines = height_in_inches * dpi
|
262
275
|
if not self.bidirectional:
|
@@ -268,7 +281,12 @@ class ImageOpNode(Node, Parameters):
|
|
268
281
|
this_len = scanlines * width_in_inches + height_in_inches
|
269
282
|
estimate += this_len / speed_in_per_s
|
270
283
|
# print (f"Horizontal scanlines: {scanlines}, Length: {this_len:.1f}")
|
271
|
-
if self.raster_direction in (
|
284
|
+
if self.raster_direction in (
|
285
|
+
RASTER_L2R,
|
286
|
+
RASTER_R2L,
|
287
|
+
RASTER_HATCH,
|
288
|
+
RASTER_GREEDY_V,
|
289
|
+
):
|
272
290
|
scanlines = width_in_inches * dpi
|
273
291
|
if not self.bidirectional:
|
274
292
|
scanlines *= 2
|
@@ -304,7 +322,14 @@ class ImageOpNode(Node, Parameters):
|
|
304
322
|
if self.consider_laserspot:
|
305
323
|
try:
|
306
324
|
laserspot = getattr(context.device, "laserspot", "0.3mm")
|
307
|
-
spot =
|
325
|
+
spot = (
|
326
|
+
2
|
327
|
+
* float(Length(laserspot))
|
328
|
+
/ (
|
329
|
+
context.device.view.native_scale_x
|
330
|
+
+ context.device.view.native_scale_y
|
331
|
+
)
|
332
|
+
)
|
308
333
|
# print (f"Laserpot in device units: {spot:.2f} [{laserspot.length_mm}], scale: {context.device.view.native_scale_x + context.device.view.native_scale_y:.2f}")
|
309
334
|
except (ValueError, AttributeError):
|
310
335
|
spot = 0
|
@@ -388,9 +413,12 @@ class ImageOpNode(Node, Parameters):
|
|
388
413
|
def call_me(method):
|
389
414
|
def handler():
|
390
415
|
method(self)
|
416
|
+
|
391
417
|
return handler
|
392
418
|
|
393
|
-
for key, description, method in context.kernel.lookup_all(
|
419
|
+
for key, description, method in context.kernel.lookup_all(
|
420
|
+
"raster_preprocessor/.*"
|
421
|
+
):
|
394
422
|
if key == self.raster_direction:
|
395
423
|
plan.commands.append(call_me(method))
|
396
424
|
# print (f"Found {description}")
|
@@ -433,7 +461,13 @@ class ImageOpNode(Node, Parameters):
|
|
433
461
|
start_on_top = self.raster_preference_top
|
434
462
|
if direction in (RASTER_GREEDY_V, RASTER_L2R, RASTER_R2L):
|
435
463
|
horizontal = False
|
436
|
-
if direction in (
|
464
|
+
if direction in (
|
465
|
+
RASTER_B2T,
|
466
|
+
RASTER_T2B,
|
467
|
+
RASTER_HATCH,
|
468
|
+
RASTER_CROSSOVER,
|
469
|
+
RASTER_GREEDY_H,
|
470
|
+
):
|
437
471
|
horizontal = True
|
438
472
|
if direction in (RASTER_T2B, RASTER_CROSSOVER):
|
439
473
|
start_on_top = True
|
@@ -494,7 +528,7 @@ class ImageOpNode(Node, Parameters):
|
|
494
528
|
gres = 0
|
495
529
|
if gres > 255:
|
496
530
|
gres = 255
|
497
|
-
stepsize = 255 /
|
531
|
+
stepsize = 255 / gres
|
498
532
|
|
499
533
|
# no need for the filter as we have already moved every
|
500
534
|
# pixel during preprocessing to either 255 or 0
|
@@ -607,27 +641,42 @@ class ImageOpNode(Node, Parameters):
|
|
607
641
|
else:
|
608
642
|
# Create Cut Object for regular image
|
609
643
|
image_filter = None
|
610
|
-
do_optimize = self.raster_direction in (
|
644
|
+
do_optimize = self.raster_direction in (
|
645
|
+
RASTER_GREEDY_H,
|
646
|
+
RASTER_GREEDY_V,
|
647
|
+
)
|
611
648
|
if do_optimize:
|
612
649
|
# get some image statistics
|
613
650
|
white_pixels = 0
|
614
651
|
used_colors = pil_image.getcolors()
|
615
652
|
for col_count, col in used_colors:
|
616
|
-
if col==255:
|
653
|
+
if col == 255:
|
617
654
|
white_pixels = col_count
|
618
655
|
break
|
619
|
-
white_pixel_ratio = white_pixels / (
|
656
|
+
white_pixel_ratio = white_pixels / (
|
657
|
+
pil_image.width * pil_image.height
|
658
|
+
)
|
620
659
|
# print (f"white pixels: {white_pixels}, ratio = {white_pixel_ratio:.3f}")
|
621
660
|
if white_pixel_ratio < 0.3:
|
622
|
-
self.raster_direction =
|
661
|
+
self.raster_direction = (
|
662
|
+
RASTER_T2B
|
663
|
+
if self.raster_direction == RASTER_GREEDY_H
|
664
|
+
else RASTER_L2R
|
665
|
+
)
|
623
666
|
|
624
|
-
if self.raster_direction in (
|
667
|
+
if self.raster_direction in (
|
668
|
+
RASTER_CROSSOVER,
|
669
|
+
RASTER_SPIRAL,
|
670
|
+
): # Crossover - need both
|
625
671
|
settings["raster_step_x"] = step_x
|
626
672
|
settings["raster_step_y"] = step_y
|
627
|
-
if
|
673
|
+
if (
|
674
|
+
self.raster_direction == RASTER_CROSSOVER
|
675
|
+
and "split_crossover" in self._instructions
|
676
|
+
):
|
628
677
|
self._instructions["mode_filter"] = "ROW"
|
629
|
-
horizontal=True
|
630
|
-
bidirectional=True
|
678
|
+
horizontal = True
|
679
|
+
bidirectional = True
|
631
680
|
start_on_top = True
|
632
681
|
start_on_left = True
|
633
682
|
if horizontal:
|
@@ -666,7 +715,7 @@ class ImageOpNode(Node, Parameters):
|
|
666
715
|
cutcodes.append(cut)
|
667
716
|
|
668
717
|
# Now set it for the next pass
|
669
|
-
horizontal=False
|
718
|
+
horizontal = False
|
670
719
|
if horizontal:
|
671
720
|
# Raster step is only along y for horizontal raster
|
672
721
|
settings["raster_step_x"] = 0
|
@@ -701,7 +750,7 @@ class ImageOpNode(Node, Parameters):
|
|
701
750
|
)
|
702
751
|
cut.path = path
|
703
752
|
cut.original_op = self.type
|
704
|
-
|
753
|
+
cutcodes.append(cut)
|
705
754
|
if self.raster_direction == RASTER_HATCH:
|
706
755
|
# Create optional crosshatch cut
|
707
756
|
direction = RASTER_L2R if start_on_left else RASTER_R2L
|
@@ -750,6 +799,11 @@ class ImageOpNode(Node, Parameters):
|
|
750
799
|
self._bounds = None
|
751
800
|
if self.output:
|
752
801
|
if self._children:
|
753
|
-
self._bounds = Node.union_bounds(
|
802
|
+
self._bounds = Node.union_bounds(
|
803
|
+
self._children,
|
804
|
+
bounds=self._bounds,
|
805
|
+
ignore_locked=False,
|
806
|
+
ignore_hidden=True,
|
807
|
+
)
|
754
808
|
self._bounds_dirty = False
|
755
809
|
return self._bounds
|
meerk40t/core/spoolers.py
CHANGED
meerk40t/core/units.py
CHANGED
@@ -106,7 +106,9 @@ class Length:
|
|
106
106
|
unitless=1.0,
|
107
107
|
preferred_units=None,
|
108
108
|
digits=None,
|
109
|
+
settings=None,
|
109
110
|
):
|
111
|
+
self.settings = settings if settings is not None else {}
|
110
112
|
self._digits = digits
|
111
113
|
self._amount = amount
|
112
114
|
if relative_length:
|
@@ -121,6 +123,8 @@ class Length:
|
|
121
123
|
else:
|
122
124
|
raise ValueError("Arguments not acceptable")
|
123
125
|
s = str(value)
|
126
|
+
if s in self.settings:
|
127
|
+
s = str(self.settings[s])
|
124
128
|
match = REGEX_LENGTH.match(s)
|
125
129
|
if not match:
|
126
130
|
raise ValueError(f"Length was not parsable: '{s}'.")
|
meerk40t/grbl/emulator.py
CHANGED
@@ -368,6 +368,15 @@ class GRBLEmulator:
|
|
368
368
|
else:
|
369
369
|
self._buffer.append(chr(c))
|
370
370
|
|
371
|
+
def _home_device(self):
|
372
|
+
if hasattr(self.device.driver, "physical_home"):
|
373
|
+
# If the driver has a physical home, we can use that.
|
374
|
+
self.device.driver.physical_home()
|
375
|
+
elif hasattr(self.device.driver, "home"):
|
376
|
+
self.device.driver.home()
|
377
|
+
else:
|
378
|
+
self.device.driver.move_abs(0, 0)
|
379
|
+
|
371
380
|
def _grbl_special(self, data):
|
372
381
|
"""
|
373
382
|
GRBL special commands are commands beginning with $ that do purely grbl specific things.
|
@@ -458,14 +467,7 @@ class GRBLEmulator:
|
|
458
467
|
elif data == "$H":
|
459
468
|
if not self.settings["homing_cycle_enable"]:
|
460
469
|
return 5 # Homing cycle not enabled by settings.
|
461
|
-
|
462
|
-
self.device.driver.physical_home()
|
463
|
-
except AttributeError:
|
464
|
-
pass
|
465
|
-
try:
|
466
|
-
self.device.driver.move_abs(0, 0)
|
467
|
-
except AttributeError:
|
468
|
-
pass
|
470
|
+
self._home_device()
|
469
471
|
return 0
|
470
472
|
elif data.startswith("$J="):
|
471
473
|
"""
|
meerk40t/grbl/gcodejob.py
CHANGED
@@ -574,8 +574,10 @@ class GcodeJob:
|
|
574
574
|
# Numeric value format is not valid or missing an expected value.
|
575
575
|
return ERROR_NUMERIC_VALUE_INVALID
|
576
576
|
if 0.0 < v <= 1.0:
|
577
|
-
v *= 1000 # numbers between 0-1 are taken to be in range 0-
|
577
|
+
v *= 1000 # numbers between 0-1 are taken to be in range 0-1000.
|
578
578
|
if self.power != v:
|
579
|
+
# print(f"Setting power to {v}")
|
580
|
+
self.plot_commit() # Power change means plot change
|
579
581
|
try:
|
580
582
|
self._driver.set("power", v)
|
581
583
|
except AttributeError:
|
@@ -707,12 +709,18 @@ class GcodeJob:
|
|
707
709
|
if power is None:
|
708
710
|
power = 1000
|
709
711
|
power = min(1000, power)
|
712
|
+
# print (f"Plotting location: ({x}, {y}) with power {power} (self.power={self.power})")
|
710
713
|
if self.plotcut is None:
|
711
714
|
ox, oy = matrix.transform_point([self.x, self.y])
|
712
|
-
|
715
|
+
p = power if power else self.power
|
716
|
+
if p is None:
|
717
|
+
p = 1000
|
718
|
+
settings = {"speed": self.speed, "power": p}
|
719
|
+
self.plotcut = PlotCut(settings=settings)
|
713
720
|
self.plotcut.plot_init(int(round(ox)), int(round(oy)))
|
714
721
|
tx, ty = matrix.transform_point([x, y])
|
715
|
-
self.
|
722
|
+
on = power / self.power if self.power else 0
|
723
|
+
self.plotcut.plot_append(int(round(tx)), int(round(ty)), on)
|
716
724
|
if not self.program_mode:
|
717
725
|
self.plot_commit()
|
718
726
|
self.x = x
|
meerk40t/grbl/plugin.py
CHANGED
@@ -175,7 +175,9 @@ def plugin(kernel, lifecycle=None):
|
|
175
175
|
{
|
176
176
|
"provider": "provider/device/grbl",
|
177
177
|
"friendly_name": _("Longer Ray5 (GRBL)"),
|
178
|
-
"extended_info": _(
|
178
|
+
"extended_info": _(
|
179
|
+
"Longer-branded 5w/10w/20w grbl diode laser.\nMake sure you verify your bed size! This machine has several upgrade kits."
|
180
|
+
),
|
179
181
|
"priority": 21,
|
180
182
|
"family": _("Longer Diode-Laser"),
|
181
183
|
"choices": [
|
@@ -229,9 +231,13 @@ def plugin(kernel, lifecycle=None):
|
|
229
231
|
hidden=True,
|
230
232
|
)
|
231
233
|
def grblserver(
|
234
|
+
command,
|
235
|
+
channel,
|
236
|
+
_,
|
232
237
|
port=23,
|
233
238
|
verbose=False,
|
234
239
|
quit=False,
|
240
|
+
remainder=None,
|
235
241
|
**kwargs,
|
236
242
|
):
|
237
243
|
"""
|
@@ -239,10 +245,13 @@ def plugin(kernel, lifecycle=None):
|
|
239
245
|
this emulates a grbl devices in order to be compatible with software that
|
240
246
|
controls that type of device.
|
241
247
|
"""
|
248
|
+
if remainder and remainder.lower() in ("stop", "quit"):
|
249
|
+
quit = True
|
242
250
|
root = kernel.root
|
243
251
|
grblcontrol = root.device.lookup("grblcontrol")
|
244
252
|
if grblcontrol is None:
|
245
253
|
if quit:
|
254
|
+
channel(_("No control instance to stop."))
|
246
255
|
return
|
247
256
|
grblcontrol = GRBLControl(root)
|
248
257
|
root.device.register("grblcontrol", grblcontrol)
|