meerk40t 0.9.3001__py2.py3-none-any.whl → 0.9.7010__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/__init__.py +1 -1
- meerk40t/balormk/balor_params.py +167 -167
- meerk40t/balormk/clone_loader.py +457 -457
- meerk40t/balormk/controller.py +1566 -1512
- meerk40t/balormk/cylindermod.py +64 -0
- meerk40t/balormk/device.py +966 -1959
- meerk40t/balormk/driver.py +778 -591
- meerk40t/balormk/galvo_commands.py +1195 -0
- meerk40t/balormk/gui/balorconfig.py +237 -111
- meerk40t/balormk/gui/balorcontroller.py +191 -184
- meerk40t/balormk/gui/baloroperationproperties.py +116 -115
- meerk40t/balormk/gui/corscene.py +845 -0
- meerk40t/balormk/gui/gui.py +179 -147
- meerk40t/balormk/livelightjob.py +466 -382
- meerk40t/balormk/mock_connection.py +131 -109
- meerk40t/balormk/plugin.py +133 -135
- meerk40t/balormk/usb_connection.py +306 -301
- meerk40t/camera/__init__.py +1 -1
- meerk40t/camera/camera.py +514 -397
- meerk40t/camera/gui/camerapanel.py +1241 -1095
- meerk40t/camera/gui/gui.py +58 -58
- meerk40t/camera/plugin.py +441 -399
- meerk40t/ch341/__init__.py +27 -27
- meerk40t/ch341/ch341device.py +628 -628
- meerk40t/ch341/libusb.py +595 -589
- meerk40t/ch341/mock.py +171 -171
- meerk40t/ch341/windriver.py +157 -157
- meerk40t/constants.py +13 -0
- meerk40t/core/__init__.py +1 -1
- meerk40t/core/bindalias.py +550 -539
- meerk40t/core/core.py +47 -47
- meerk40t/core/cutcode/cubiccut.py +73 -73
- meerk40t/core/cutcode/cutcode.py +315 -312
- meerk40t/core/cutcode/cutgroup.py +141 -137
- meerk40t/core/cutcode/cutobject.py +192 -185
- meerk40t/core/cutcode/dwellcut.py +37 -37
- meerk40t/core/cutcode/gotocut.py +29 -29
- meerk40t/core/cutcode/homecut.py +29 -29
- meerk40t/core/cutcode/inputcut.py +34 -34
- meerk40t/core/cutcode/linecut.py +33 -33
- meerk40t/core/cutcode/outputcut.py +34 -34
- meerk40t/core/cutcode/plotcut.py +335 -335
- meerk40t/core/cutcode/quadcut.py +61 -61
- meerk40t/core/cutcode/rastercut.py +168 -148
- meerk40t/core/cutcode/waitcut.py +34 -34
- meerk40t/core/cutplan.py +1843 -1316
- meerk40t/core/drivers.py +330 -329
- meerk40t/core/elements/align.py +801 -669
- meerk40t/core/elements/branches.py +1844 -1507
- meerk40t/core/elements/clipboard.py +229 -219
- meerk40t/core/elements/element_treeops.py +4561 -2837
- meerk40t/core/elements/element_types.py +125 -105
- meerk40t/core/elements/elements.py +4329 -3617
- meerk40t/core/elements/files.py +117 -64
- meerk40t/core/elements/geometry.py +473 -224
- meerk40t/core/elements/grid.py +467 -316
- meerk40t/core/elements/materials.py +158 -94
- meerk40t/core/elements/notes.py +50 -38
- meerk40t/core/elements/offset_clpr.py +933 -912
- meerk40t/core/elements/offset_mk.py +963 -955
- meerk40t/core/elements/penbox.py +339 -267
- meerk40t/core/elements/placements.py +300 -83
- meerk40t/core/elements/render.py +785 -687
- meerk40t/core/elements/shapes.py +2618 -2092
- meerk40t/core/elements/trace.py +651 -563
- meerk40t/core/elements/tree_commands.py +415 -409
- meerk40t/core/elements/undo_redo.py +116 -58
- meerk40t/core/elements/wordlist.py +319 -200
- meerk40t/core/exceptions.py +9 -9
- meerk40t/core/laserjob.py +220 -220
- meerk40t/core/logging.py +63 -63
- meerk40t/core/node/blobnode.py +83 -86
- meerk40t/core/node/bootstrap.py +105 -103
- meerk40t/core/node/branch_elems.py +40 -31
- meerk40t/core/node/branch_ops.py +45 -38
- meerk40t/core/node/branch_regmark.py +48 -41
- meerk40t/core/node/cutnode.py +29 -32
- meerk40t/core/node/effect_hatch.py +375 -257
- meerk40t/core/node/effect_warp.py +398 -0
- meerk40t/core/node/effect_wobble.py +441 -309
- meerk40t/core/node/elem_ellipse.py +404 -309
- meerk40t/core/node/elem_image.py +1082 -801
- meerk40t/core/node/elem_line.py +358 -292
- meerk40t/core/node/elem_path.py +259 -201
- meerk40t/core/node/elem_point.py +129 -102
- meerk40t/core/node/elem_polyline.py +310 -246
- meerk40t/core/node/elem_rect.py +376 -286
- meerk40t/core/node/elem_text.py +445 -418
- meerk40t/core/node/filenode.py +59 -40
- meerk40t/core/node/groupnode.py +138 -74
- meerk40t/core/node/image_processed.py +777 -766
- meerk40t/core/node/image_raster.py +156 -113
- meerk40t/core/node/layernode.py +31 -31
- meerk40t/core/node/mixins.py +135 -107
- meerk40t/core/node/node.py +1427 -1304
- meerk40t/core/node/nutils.py +117 -114
- meerk40t/core/node/op_cut.py +462 -335
- meerk40t/core/node/op_dots.py +296 -251
- meerk40t/core/node/op_engrave.py +414 -311
- meerk40t/core/node/op_image.py +755 -369
- meerk40t/core/node/op_raster.py +787 -522
- meerk40t/core/node/place_current.py +37 -40
- meerk40t/core/node/place_point.py +329 -126
- meerk40t/core/node/refnode.py +58 -47
- meerk40t/core/node/rootnode.py +225 -219
- meerk40t/core/node/util_console.py +48 -48
- meerk40t/core/node/util_goto.py +84 -65
- meerk40t/core/node/util_home.py +61 -61
- meerk40t/core/node/util_input.py +102 -102
- meerk40t/core/node/util_output.py +102 -102
- meerk40t/core/node/util_wait.py +65 -65
- meerk40t/core/parameters.py +709 -707
- meerk40t/core/planner.py +875 -785
- meerk40t/core/plotplanner.py +656 -652
- meerk40t/core/space.py +120 -113
- meerk40t/core/spoolers.py +706 -705
- meerk40t/core/svg_io.py +1836 -1549
- meerk40t/core/treeop.py +534 -445
- meerk40t/core/undos.py +278 -124
- meerk40t/core/units.py +784 -680
- meerk40t/core/view.py +393 -322
- meerk40t/core/webhelp.py +62 -62
- meerk40t/core/wordlist.py +513 -504
- meerk40t/cylinder/cylinder.py +247 -0
- meerk40t/cylinder/gui/cylindersettings.py +41 -0
- meerk40t/cylinder/gui/gui.py +24 -0
- meerk40t/device/__init__.py +1 -1
- meerk40t/device/basedevice.py +322 -123
- meerk40t/device/devicechoices.py +50 -0
- meerk40t/device/dummydevice.py +163 -128
- meerk40t/device/gui/defaultactions.py +618 -602
- meerk40t/device/gui/effectspanel.py +114 -0
- meerk40t/device/gui/formatterpanel.py +253 -290
- meerk40t/device/gui/warningpanel.py +337 -260
- meerk40t/device/mixins.py +13 -13
- meerk40t/dxf/__init__.py +1 -1
- meerk40t/dxf/dxf_io.py +766 -554
- meerk40t/dxf/plugin.py +47 -35
- meerk40t/external_plugins.py +79 -79
- meerk40t/external_plugins_build.py +28 -28
- meerk40t/extra/cag.py +112 -116
- meerk40t/extra/coolant.py +403 -0
- meerk40t/extra/encode_detect.py +198 -0
- meerk40t/extra/ezd.py +1165 -1165
- meerk40t/extra/hershey.py +835 -340
- meerk40t/extra/imageactions.py +322 -316
- meerk40t/extra/inkscape.py +630 -622
- meerk40t/extra/lbrn.py +424 -424
- meerk40t/extra/outerworld.py +284 -0
- meerk40t/extra/param_functions.py +1542 -1556
- meerk40t/extra/potrace.py +257 -253
- meerk40t/extra/serial_exchange.py +118 -0
- meerk40t/extra/updater.py +602 -453
- meerk40t/extra/vectrace.py +147 -146
- meerk40t/extra/winsleep.py +83 -83
- meerk40t/extra/xcs_reader.py +597 -0
- meerk40t/fill/fills.py +781 -335
- meerk40t/fill/patternfill.py +1061 -1061
- meerk40t/fill/patterns.py +614 -567
- meerk40t/grbl/control.py +87 -87
- meerk40t/grbl/controller.py +990 -903
- meerk40t/grbl/device.py +1081 -768
- meerk40t/grbl/driver.py +989 -771
- meerk40t/grbl/emulator.py +532 -497
- meerk40t/grbl/gcodejob.py +783 -767
- meerk40t/grbl/gui/grblconfiguration.py +373 -298
- meerk40t/grbl/gui/grblcontroller.py +485 -271
- meerk40t/grbl/gui/grblhardwareconfig.py +269 -153
- meerk40t/grbl/gui/grbloperationconfig.py +105 -0
- meerk40t/grbl/gui/gui.py +147 -116
- meerk40t/grbl/interpreter.py +44 -44
- meerk40t/grbl/loader.py +22 -22
- meerk40t/grbl/mock_connection.py +56 -56
- meerk40t/grbl/plugin.py +294 -264
- meerk40t/grbl/serial_connection.py +93 -88
- meerk40t/grbl/tcp_connection.py +81 -79
- meerk40t/grbl/ws_connection.py +112 -0
- meerk40t/gui/__init__.py +1 -1
- meerk40t/gui/about.py +2042 -296
- meerk40t/gui/alignment.py +1644 -1608
- meerk40t/gui/autoexec.py +199 -0
- meerk40t/gui/basicops.py +791 -670
- meerk40t/gui/bufferview.py +77 -71
- meerk40t/gui/busy.py +170 -133
- meerk40t/gui/choicepropertypanel.py +1673 -1469
- meerk40t/gui/consolepanel.py +706 -542
- meerk40t/gui/devicepanel.py +687 -581
- meerk40t/gui/dialogoptions.py +110 -107
- meerk40t/gui/executejob.py +316 -306
- meerk40t/gui/fonts.py +90 -90
- meerk40t/gui/functionwrapper.py +252 -0
- meerk40t/gui/gui_mixins.py +729 -0
- meerk40t/gui/guicolors.py +205 -182
- meerk40t/gui/help_assets/help_assets.py +218 -201
- meerk40t/gui/helper.py +154 -0
- meerk40t/gui/hersheymanager.py +1430 -846
- meerk40t/gui/icons.py +3422 -2747
- meerk40t/gui/imagesplitter.py +555 -508
- meerk40t/gui/keymap.py +354 -344
- meerk40t/gui/laserpanel.py +892 -806
- meerk40t/gui/laserrender.py +1470 -1232
- meerk40t/gui/lasertoolpanel.py +805 -793
- meerk40t/gui/magnetoptions.py +436 -0
- meerk40t/gui/materialmanager.py +2917 -0
- meerk40t/gui/materialtest.py +1722 -1694
- meerk40t/gui/mkdebug.py +646 -359
- meerk40t/gui/mwindow.py +163 -140
- meerk40t/gui/navigationpanels.py +2605 -2467
- meerk40t/gui/notes.py +143 -142
- meerk40t/gui/opassignment.py +414 -410
- meerk40t/gui/operation_info.py +310 -299
- meerk40t/gui/plugin.py +494 -328
- meerk40t/gui/position.py +714 -669
- meerk40t/gui/preferences.py +901 -650
- meerk40t/gui/propertypanels/attributes.py +1461 -1131
- meerk40t/gui/propertypanels/blobproperty.py +117 -114
- meerk40t/gui/propertypanels/consoleproperty.py +83 -80
- meerk40t/gui/propertypanels/gotoproperty.py +77 -0
- meerk40t/gui/propertypanels/groupproperties.py +223 -217
- meerk40t/gui/propertypanels/hatchproperty.py +489 -469
- meerk40t/gui/propertypanels/imageproperty.py +2244 -1384
- meerk40t/gui/propertypanels/inputproperty.py +59 -58
- meerk40t/gui/propertypanels/opbranchproperties.py +82 -80
- meerk40t/gui/propertypanels/operationpropertymain.py +1890 -1638
- meerk40t/gui/propertypanels/outputproperty.py +59 -58
- meerk40t/gui/propertypanels/pathproperty.py +389 -380
- meerk40t/gui/propertypanels/placementproperty.py +1214 -383
- meerk40t/gui/propertypanels/pointproperty.py +140 -136
- meerk40t/gui/propertypanels/propertywindow.py +313 -181
- meerk40t/gui/propertypanels/rasterwizardpanels.py +996 -912
- meerk40t/gui/propertypanels/regbranchproperties.py +76 -0
- meerk40t/gui/propertypanels/textproperty.py +770 -755
- meerk40t/gui/propertypanels/waitproperty.py +56 -55
- meerk40t/gui/propertypanels/warpproperty.py +121 -0
- meerk40t/gui/propertypanels/wobbleproperty.py +255 -204
- meerk40t/gui/ribbon.py +2468 -2210
- meerk40t/gui/scene/scene.py +1100 -1051
- meerk40t/gui/scene/sceneconst.py +22 -22
- meerk40t/gui/scene/scenepanel.py +439 -349
- meerk40t/gui/scene/scenespacewidget.py +365 -365
- meerk40t/gui/scene/widget.py +518 -505
- meerk40t/gui/scenewidgets/affinemover.py +215 -215
- meerk40t/gui/scenewidgets/attractionwidget.py +315 -309
- meerk40t/gui/scenewidgets/bedwidget.py +120 -97
- meerk40t/gui/scenewidgets/elementswidget.py +137 -107
- meerk40t/gui/scenewidgets/gridwidget.py +785 -745
- meerk40t/gui/scenewidgets/guidewidget.py +765 -765
- meerk40t/gui/scenewidgets/laserpathwidget.py +66 -66
- meerk40t/gui/scenewidgets/machineoriginwidget.py +86 -86
- meerk40t/gui/scenewidgets/nodeselector.py +28 -28
- meerk40t/gui/scenewidgets/rectselectwidget.py +589 -346
- meerk40t/gui/scenewidgets/relocatewidget.py +33 -33
- meerk40t/gui/scenewidgets/reticlewidget.py +83 -83
- meerk40t/gui/scenewidgets/selectionwidget.py +2952 -2756
- meerk40t/gui/simpleui.py +357 -333
- meerk40t/gui/simulation.py +2431 -2094
- meerk40t/gui/snapoptions.py +208 -203
- meerk40t/gui/spoolerpanel.py +1227 -1180
- meerk40t/gui/statusbarwidgets/defaultoperations.py +480 -353
- meerk40t/gui/statusbarwidgets/infowidget.py +520 -483
- meerk40t/gui/statusbarwidgets/opassignwidget.py +356 -355
- meerk40t/gui/statusbarwidgets/selectionwidget.py +172 -171
- meerk40t/gui/statusbarwidgets/shapepropwidget.py +754 -236
- meerk40t/gui/statusbarwidgets/statusbar.py +272 -260
- meerk40t/gui/statusbarwidgets/statusbarwidget.py +268 -270
- meerk40t/gui/statusbarwidgets/strokewidget.py +267 -251
- meerk40t/gui/themes.py +200 -78
- meerk40t/gui/tips.py +591 -0
- meerk40t/gui/toolwidgets/circlebrush.py +35 -35
- meerk40t/gui/toolwidgets/toolcircle.py +248 -242
- meerk40t/gui/toolwidgets/toolcontainer.py +82 -77
- meerk40t/gui/toolwidgets/tooldraw.py +97 -90
- meerk40t/gui/toolwidgets/toolellipse.py +219 -212
- meerk40t/gui/toolwidgets/toolimagecut.py +25 -132
- meerk40t/gui/toolwidgets/toolline.py +39 -144
- meerk40t/gui/toolwidgets/toollinetext.py +79 -236
- meerk40t/gui/toolwidgets/toollinetext_inline.py +296 -0
- meerk40t/gui/toolwidgets/toolmeasure.py +160 -216
- meerk40t/gui/toolwidgets/toolnodeedit.py +2088 -2074
- meerk40t/gui/toolwidgets/toolnodemove.py +92 -94
- meerk40t/gui/toolwidgets/toolparameter.py +754 -668
- meerk40t/gui/toolwidgets/toolplacement.py +108 -108
- meerk40t/gui/toolwidgets/toolpoint.py +68 -59
- meerk40t/gui/toolwidgets/toolpointlistbuilder.py +294 -0
- meerk40t/gui/toolwidgets/toolpointmove.py +183 -0
- meerk40t/gui/toolwidgets/toolpolygon.py +288 -403
- meerk40t/gui/toolwidgets/toolpolyline.py +38 -196
- meerk40t/gui/toolwidgets/toolrect.py +211 -207
- meerk40t/gui/toolwidgets/toolrelocate.py +72 -72
- meerk40t/gui/toolwidgets/toolribbon.py +598 -113
- meerk40t/gui/toolwidgets/tooltabedit.py +546 -0
- meerk40t/gui/toolwidgets/tooltext.py +98 -89
- meerk40t/gui/toolwidgets/toolvector.py +213 -204
- meerk40t/gui/toolwidgets/toolwidget.py +39 -39
- meerk40t/gui/usbconnect.py +98 -91
- meerk40t/gui/utilitywidgets/buttonwidget.py +18 -18
- meerk40t/gui/utilitywidgets/checkboxwidget.py +90 -90
- meerk40t/gui/utilitywidgets/controlwidget.py +14 -14
- meerk40t/gui/utilitywidgets/cyclocycloidwidget.py +343 -340
- meerk40t/gui/utilitywidgets/debugwidgets.py +148 -0
- meerk40t/gui/utilitywidgets/handlewidget.py +27 -27
- meerk40t/gui/utilitywidgets/harmonograph.py +450 -447
- meerk40t/gui/utilitywidgets/openclosewidget.py +40 -40
- meerk40t/gui/utilitywidgets/rotationwidget.py +54 -54
- meerk40t/gui/utilitywidgets/scalewidget.py +75 -75
- meerk40t/gui/utilitywidgets/seekbarwidget.py +183 -183
- meerk40t/gui/utilitywidgets/togglewidget.py +142 -142
- meerk40t/gui/utilitywidgets/toolbarwidget.py +8 -8
- meerk40t/gui/wordlisteditor.py +985 -931
- meerk40t/gui/wxmeerk40t.py +1444 -1169
- meerk40t/gui/wxmmain.py +5578 -4112
- meerk40t/gui/wxmribbon.py +1591 -1076
- meerk40t/gui/wxmscene.py +1635 -1453
- meerk40t/gui/wxmtree.py +2410 -2089
- meerk40t/gui/wxutils.py +1769 -1099
- meerk40t/gui/zmatrix.py +102 -102
- meerk40t/image/__init__.py +1 -1
- meerk40t/image/dither.py +429 -0
- meerk40t/image/imagetools.py +2778 -2269
- meerk40t/internal_plugins.py +150 -130
- meerk40t/kernel/__init__.py +63 -12
- meerk40t/kernel/channel.py +259 -212
- meerk40t/kernel/context.py +538 -538
- meerk40t/kernel/exceptions.py +41 -41
- meerk40t/kernel/functions.py +463 -414
- meerk40t/kernel/jobs.py +100 -100
- meerk40t/kernel/kernel.py +3809 -3571
- meerk40t/kernel/lifecycles.py +71 -71
- meerk40t/kernel/module.py +49 -49
- meerk40t/kernel/service.py +147 -147
- meerk40t/kernel/settings.py +383 -343
- meerk40t/lihuiyu/controller.py +883 -876
- meerk40t/lihuiyu/device.py +1181 -1069
- meerk40t/lihuiyu/driver.py +1466 -1372
- meerk40t/lihuiyu/gui/gui.py +127 -106
- meerk40t/lihuiyu/gui/lhyaccelgui.py +377 -363
- meerk40t/lihuiyu/gui/lhycontrollergui.py +741 -651
- meerk40t/lihuiyu/gui/lhydrivergui.py +470 -446
- meerk40t/lihuiyu/gui/lhyoperationproperties.py +238 -237
- meerk40t/lihuiyu/gui/tcpcontroller.py +226 -190
- meerk40t/lihuiyu/interpreter.py +53 -53
- meerk40t/lihuiyu/laserspeed.py +450 -450
- meerk40t/lihuiyu/loader.py +90 -90
- meerk40t/lihuiyu/parser.py +404 -404
- meerk40t/lihuiyu/plugin.py +101 -102
- meerk40t/lihuiyu/tcp_connection.py +111 -109
- meerk40t/main.py +231 -165
- meerk40t/moshi/builder.py +788 -781
- meerk40t/moshi/controller.py +505 -499
- meerk40t/moshi/device.py +495 -442
- meerk40t/moshi/driver.py +862 -696
- meerk40t/moshi/gui/gui.py +78 -76
- meerk40t/moshi/gui/moshicontrollergui.py +538 -522
- meerk40t/moshi/gui/moshidrivergui.py +87 -75
- meerk40t/moshi/plugin.py +43 -43
- meerk40t/network/console_server.py +102 -57
- meerk40t/network/kernelserver.py +10 -9
- meerk40t/network/tcp_server.py +142 -140
- meerk40t/network/udp_server.py +103 -77
- meerk40t/network/web_server.py +390 -0
- meerk40t/newly/controller.py +1158 -1144
- meerk40t/newly/device.py +874 -732
- meerk40t/newly/driver.py +540 -412
- meerk40t/newly/gui/gui.py +219 -188
- meerk40t/newly/gui/newlyconfig.py +116 -101
- meerk40t/newly/gui/newlycontroller.py +193 -186
- meerk40t/newly/gui/operationproperties.py +51 -51
- meerk40t/newly/mock_connection.py +82 -82
- meerk40t/newly/newly_params.py +56 -56
- meerk40t/newly/plugin.py +1214 -1246
- meerk40t/newly/usb_connection.py +322 -322
- meerk40t/rotary/gui/gui.py +52 -46
- meerk40t/rotary/gui/rotarysettings.py +240 -232
- meerk40t/rotary/rotary.py +202 -98
- meerk40t/ruida/control.py +291 -91
- meerk40t/ruida/controller.py +138 -1088
- meerk40t/ruida/device.py +672 -231
- meerk40t/ruida/driver.py +534 -472
- meerk40t/ruida/emulator.py +1494 -1491
- meerk40t/ruida/exceptions.py +4 -4
- meerk40t/ruida/gui/gui.py +71 -76
- meerk40t/ruida/gui/ruidaconfig.py +239 -72
- meerk40t/ruida/gui/ruidacontroller.py +187 -184
- meerk40t/ruida/gui/ruidaoperationproperties.py +48 -47
- meerk40t/ruida/loader.py +54 -52
- meerk40t/ruida/mock_connection.py +57 -109
- meerk40t/ruida/plugin.py +124 -87
- meerk40t/ruida/rdjob.py +2084 -945
- meerk40t/ruida/serial_connection.py +116 -0
- meerk40t/ruida/tcp_connection.py +146 -0
- meerk40t/ruida/udp_connection.py +73 -0
- meerk40t/svgelements.py +9671 -9669
- meerk40t/tools/driver_to_path.py +584 -579
- meerk40t/tools/geomstr.py +5583 -4680
- meerk40t/tools/jhfparser.py +357 -292
- meerk40t/tools/kerftest.py +904 -890
- meerk40t/tools/livinghinges.py +1168 -1033
- meerk40t/tools/pathtools.py +987 -949
- meerk40t/tools/pmatrix.py +234 -0
- meerk40t/tools/pointfinder.py +942 -942
- meerk40t/tools/polybool.py +940 -940
- meerk40t/tools/rasterplotter.py +1660 -547
- meerk40t/tools/shxparser.py +989 -901
- meerk40t/tools/ttfparser.py +726 -446
- meerk40t/tools/zinglplotter.py +595 -593
- {meerk40t-0.9.3001.dist-info → meerk40t-0.9.7010.dist-info}/LICENSE +21 -21
- {meerk40t-0.9.3001.dist-info → meerk40t-0.9.7010.dist-info}/METADATA +150 -139
- meerk40t-0.9.7010.dist-info/RECORD +445 -0
- {meerk40t-0.9.3001.dist-info → meerk40t-0.9.7010.dist-info}/WHEEL +1 -1
- {meerk40t-0.9.3001.dist-info → meerk40t-0.9.7010.dist-info}/top_level.txt +0 -1
- {meerk40t-0.9.3001.dist-info → meerk40t-0.9.7010.dist-info}/zip-safe +1 -1
- meerk40t/balormk/elementlightjob.py +0 -159
- meerk40t-0.9.3001.dist-info/RECORD +0 -437
- test/bootstrap.py +0 -63
- test/test_cli.py +0 -12
- test/test_core_cutcode.py +0 -418
- test/test_core_elements.py +0 -144
- test/test_core_plotplanner.py +0 -397
- test/test_core_viewports.py +0 -312
- test/test_drivers_grbl.py +0 -108
- test/test_drivers_lihuiyu.py +0 -443
- test/test_drivers_newly.py +0 -113
- test/test_element_degenerate_points.py +0 -43
- test/test_elements_classify.py +0 -97
- test/test_elements_penbox.py +0 -22
- test/test_file_svg.py +0 -176
- test/test_fill.py +0 -155
- test/test_geomstr.py +0 -1523
- test/test_geomstr_nodes.py +0 -18
- test/test_imagetools_actualize.py +0 -306
- test/test_imagetools_wizard.py +0 -258
- test/test_kernel.py +0 -200
- test/test_laser_speeds.py +0 -3303
- test/test_length.py +0 -57
- test/test_lifecycle.py +0 -66
- test/test_operations.py +0 -251
- test/test_operations_hatch.py +0 -57
- test/test_ruida.py +0 -19
- test/test_spooler.py +0 -22
- test/test_tools_rasterplotter.py +0 -29
- test/test_wobble.py +0 -133
- test/test_zingl.py +0 -124
- {test → meerk40t/cylinder}/__init__.py +0 -0
- /meerk40t/{core/element_commands.py → cylinder/gui/__init__.py} +0 -0
- {meerk40t-0.9.3001.dist-info → meerk40t-0.9.7010.dist-info}/entry_points.txt +0 -0
@@ -1,1507 +1,1844 @@
|
|
1
|
-
"""
|
2
|
-
This
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
from
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
@self.console_argument("
|
172
|
-
@self.
|
173
|
-
|
174
|
-
"
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
)
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
]
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
)
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
)
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
),
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
if
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
if
|
615
|
-
|
616
|
-
|
617
|
-
if
|
618
|
-
for
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
)
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
)
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
"
|
651
|
-
type=
|
652
|
-
|
653
|
-
help=_(
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
@self.
|
797
|
-
"
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
|
825
|
-
|
826
|
-
|
827
|
-
|
828
|
-
|
829
|
-
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
|
838
|
-
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
|
843
|
-
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
853
|
-
|
854
|
-
type=
|
855
|
-
|
856
|
-
|
857
|
-
|
858
|
-
|
859
|
-
"
|
860
|
-
|
861
|
-
|
862
|
-
|
863
|
-
|
864
|
-
|
865
|
-
|
866
|
-
|
867
|
-
|
868
|
-
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
885
|
-
)
|
886
|
-
return
|
887
|
-
|
888
|
-
|
889
|
-
|
890
|
-
|
891
|
-
|
892
|
-
|
893
|
-
|
894
|
-
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
@self.
|
909
|
-
|
910
|
-
|
911
|
-
|
912
|
-
|
913
|
-
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
|
920
|
-
|
921
|
-
|
922
|
-
|
923
|
-
|
924
|
-
|
925
|
-
|
926
|
-
|
927
|
-
|
928
|
-
|
929
|
-
|
930
|
-
|
931
|
-
|
932
|
-
|
933
|
-
|
934
|
-
|
935
|
-
|
936
|
-
|
937
|
-
|
938
|
-
|
939
|
-
|
940
|
-
|
941
|
-
|
942
|
-
|
943
|
-
|
944
|
-
|
945
|
-
|
946
|
-
|
947
|
-
|
948
|
-
|
949
|
-
|
950
|
-
|
951
|
-
|
952
|
-
|
953
|
-
|
954
|
-
|
955
|
-
|
956
|
-
|
957
|
-
|
958
|
-
|
959
|
-
|
960
|
-
|
961
|
-
|
962
|
-
|
963
|
-
|
964
|
-
|
965
|
-
|
966
|
-
|
967
|
-
|
968
|
-
|
969
|
-
|
970
|
-
|
971
|
-
|
972
|
-
|
973
|
-
|
974
|
-
|
975
|
-
|
976
|
-
|
977
|
-
|
978
|
-
|
979
|
-
|
980
|
-
|
981
|
-
|
982
|
-
|
983
|
-
|
984
|
-
|
985
|
-
|
986
|
-
|
987
|
-
|
988
|
-
|
989
|
-
|
990
|
-
|
991
|
-
|
992
|
-
|
993
|
-
|
994
|
-
|
995
|
-
|
996
|
-
|
997
|
-
|
998
|
-
|
999
|
-
|
1000
|
-
|
1001
|
-
|
1002
|
-
|
1003
|
-
|
1004
|
-
|
1005
|
-
|
1006
|
-
|
1007
|
-
|
1008
|
-
|
1009
|
-
|
1010
|
-
|
1011
|
-
|
1012
|
-
|
1013
|
-
|
1014
|
-
|
1015
|
-
|
1016
|
-
|
1017
|
-
|
1018
|
-
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1025
|
-
|
1026
|
-
|
1027
|
-
|
1028
|
-
|
1029
|
-
|
1030
|
-
)
|
1031
|
-
|
1032
|
-
|
1033
|
-
|
1034
|
-
|
1035
|
-
|
1036
|
-
|
1037
|
-
|
1038
|
-
|
1039
|
-
|
1040
|
-
|
1041
|
-
|
1042
|
-
|
1043
|
-
|
1044
|
-
|
1045
|
-
|
1046
|
-
|
1047
|
-
|
1048
|
-
|
1049
|
-
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1053
|
-
|
1054
|
-
|
1055
|
-
|
1056
|
-
|
1057
|
-
|
1058
|
-
|
1059
|
-
|
1060
|
-
|
1061
|
-
|
1062
|
-
|
1063
|
-
|
1064
|
-
|
1065
|
-
|
1066
|
-
|
1067
|
-
|
1068
|
-
|
1069
|
-
|
1070
|
-
|
1071
|
-
|
1072
|
-
|
1073
|
-
|
1074
|
-
|
1075
|
-
|
1076
|
-
|
1077
|
-
|
1078
|
-
|
1079
|
-
|
1080
|
-
|
1081
|
-
|
1082
|
-
|
1083
|
-
|
1084
|
-
|
1085
|
-
|
1086
|
-
|
1087
|
-
|
1088
|
-
|
1089
|
-
|
1090
|
-
|
1091
|
-
|
1092
|
-
|
1093
|
-
|
1094
|
-
|
1095
|
-
|
1096
|
-
|
1097
|
-
|
1098
|
-
|
1099
|
-
|
1100
|
-
|
1101
|
-
|
1102
|
-
|
1103
|
-
|
1104
|
-
|
1105
|
-
|
1106
|
-
|
1107
|
-
|
1108
|
-
|
1109
|
-
|
1110
|
-
|
1111
|
-
|
1112
|
-
|
1113
|
-
|
1114
|
-
|
1115
|
-
|
1116
|
-
help=_("
|
1117
|
-
|
1118
|
-
|
1119
|
-
|
1120
|
-
|
1121
|
-
|
1122
|
-
|
1123
|
-
|
1124
|
-
|
1125
|
-
|
1126
|
-
|
1127
|
-
|
1128
|
-
|
1129
|
-
|
1130
|
-
"
|
1131
|
-
|
1132
|
-
|
1133
|
-
|
1134
|
-
|
1135
|
-
|
1136
|
-
|
1137
|
-
|
1138
|
-
|
1139
|
-
|
1140
|
-
|
1141
|
-
|
1142
|
-
|
1143
|
-
|
1144
|
-
|
1145
|
-
|
1146
|
-
|
1147
|
-
)
|
1148
|
-
|
1149
|
-
|
1150
|
-
|
1151
|
-
|
1152
|
-
|
1153
|
-
|
1154
|
-
|
1155
|
-
|
1156
|
-
|
1157
|
-
|
1158
|
-
|
1159
|
-
|
1160
|
-
if
|
1161
|
-
|
1162
|
-
|
1163
|
-
|
1164
|
-
|
1165
|
-
|
1166
|
-
|
1167
|
-
|
1168
|
-
|
1169
|
-
|
1170
|
-
|
1171
|
-
|
1172
|
-
|
1173
|
-
|
1174
|
-
|
1175
|
-
|
1176
|
-
|
1177
|
-
|
1178
|
-
|
1179
|
-
|
1180
|
-
|
1181
|
-
|
1182
|
-
|
1183
|
-
|
1184
|
-
|
1185
|
-
|
1186
|
-
|
1187
|
-
|
1188
|
-
|
1189
|
-
|
1190
|
-
|
1191
|
-
|
1192
|
-
|
1193
|
-
|
1194
|
-
|
1195
|
-
|
1196
|
-
|
1197
|
-
|
1198
|
-
|
1199
|
-
|
1200
|
-
|
1201
|
-
|
1202
|
-
|
1203
|
-
|
1204
|
-
|
1205
|
-
|
1206
|
-
|
1207
|
-
|
1208
|
-
|
1209
|
-
|
1210
|
-
|
1211
|
-
|
1212
|
-
|
1213
|
-
|
1214
|
-
|
1215
|
-
|
1216
|
-
|
1217
|
-
|
1218
|
-
|
1219
|
-
|
1220
|
-
|
1221
|
-
|
1222
|
-
|
1223
|
-
|
1224
|
-
|
1225
|
-
|
1226
|
-
|
1227
|
-
|
1228
|
-
|
1229
|
-
|
1230
|
-
|
1231
|
-
|
1232
|
-
|
1233
|
-
|
1234
|
-
|
1235
|
-
|
1236
|
-
|
1237
|
-
|
1238
|
-
|
1239
|
-
|
1240
|
-
|
1241
|
-
|
1242
|
-
|
1243
|
-
|
1244
|
-
|
1245
|
-
|
1246
|
-
|
1247
|
-
|
1248
|
-
|
1249
|
-
|
1250
|
-
|
1251
|
-
|
1252
|
-
|
1253
|
-
|
1254
|
-
|
1255
|
-
|
1256
|
-
|
1257
|
-
|
1258
|
-
|
1259
|
-
|
1260
|
-
|
1261
|
-
|
1262
|
-
|
1263
|
-
|
1264
|
-
|
1265
|
-
|
1266
|
-
|
1267
|
-
|
1268
|
-
|
1269
|
-
|
1270
|
-
|
1271
|
-
|
1272
|
-
|
1273
|
-
|
1274
|
-
|
1275
|
-
|
1276
|
-
"
|
1277
|
-
|
1278
|
-
|
1279
|
-
|
1280
|
-
|
1281
|
-
|
1282
|
-
|
1283
|
-
|
1284
|
-
|
1285
|
-
|
1286
|
-
|
1287
|
-
|
1288
|
-
|
1289
|
-
|
1290
|
-
|
1291
|
-
|
1292
|
-
|
1293
|
-
|
1294
|
-
|
1295
|
-
|
1296
|
-
|
1297
|
-
|
1298
|
-
|
1299
|
-
|
1300
|
-
|
1301
|
-
|
1302
|
-
|
1303
|
-
|
1304
|
-
|
1305
|
-
|
1306
|
-
|
1307
|
-
|
1308
|
-
|
1309
|
-
|
1310
|
-
|
1311
|
-
|
1312
|
-
|
1313
|
-
|
1314
|
-
|
1315
|
-
|
1316
|
-
|
1317
|
-
|
1318
|
-
|
1319
|
-
|
1320
|
-
|
1321
|
-
|
1322
|
-
|
1323
|
-
|
1324
|
-
|
1325
|
-
|
1326
|
-
|
1327
|
-
|
1328
|
-
|
1329
|
-
|
1330
|
-
|
1331
|
-
|
1332
|
-
|
1333
|
-
|
1334
|
-
|
1335
|
-
|
1336
|
-
|
1337
|
-
|
1338
|
-
|
1339
|
-
|
1340
|
-
|
1341
|
-
|
1342
|
-
|
1343
|
-
|
1344
|
-
|
1345
|
-
|
1346
|
-
|
1347
|
-
|
1348
|
-
|
1349
|
-
|
1350
|
-
|
1351
|
-
|
1352
|
-
|
1353
|
-
|
1354
|
-
|
1355
|
-
|
1356
|
-
|
1357
|
-
|
1358
|
-
|
1359
|
-
|
1360
|
-
|
1361
|
-
|
1362
|
-
|
1363
|
-
|
1364
|
-
|
1365
|
-
|
1366
|
-
|
1367
|
-
|
1368
|
-
|
1369
|
-
|
1370
|
-
|
1371
|
-
|
1372
|
-
|
1373
|
-
|
1374
|
-
|
1375
|
-
|
1376
|
-
|
1377
|
-
|
1378
|
-
|
1379
|
-
|
1380
|
-
|
1381
|
-
|
1382
|
-
|
1383
|
-
|
1384
|
-
|
1385
|
-
|
1386
|
-
|
1387
|
-
|
1388
|
-
|
1389
|
-
|
1390
|
-
|
1391
|
-
|
1392
|
-
|
1393
|
-
|
1394
|
-
|
1395
|
-
|
1396
|
-
|
1397
|
-
|
1398
|
-
|
1399
|
-
|
1400
|
-
|
1401
|
-
|
1402
|
-
|
1403
|
-
|
1404
|
-
|
1405
|
-
|
1406
|
-
|
1407
|
-
|
1408
|
-
|
1409
|
-
|
1410
|
-
|
1411
|
-
|
1412
|
-
|
1413
|
-
|
1414
|
-
|
1415
|
-
|
1416
|
-
|
1417
|
-
|
1418
|
-
|
1419
|
-
|
1420
|
-
|
1421
|
-
|
1422
|
-
|
1423
|
-
|
1424
|
-
|
1425
|
-
|
1426
|
-
|
1427
|
-
|
1428
|
-
|
1429
|
-
|
1430
|
-
|
1431
|
-
|
1432
|
-
|
1433
|
-
|
1434
|
-
|
1435
|
-
|
1436
|
-
|
1437
|
-
|
1438
|
-
|
1439
|
-
|
1440
|
-
|
1441
|
-
|
1442
|
-
|
1443
|
-
|
1444
|
-
|
1445
|
-
|
1446
|
-
|
1447
|
-
|
1448
|
-
|
1449
|
-
|
1450
|
-
|
1451
|
-
|
1452
|
-
|
1453
|
-
|
1454
|
-
|
1455
|
-
|
1456
|
-
|
1457
|
-
|
1458
|
-
|
1459
|
-
|
1460
|
-
except
|
1461
|
-
|
1462
|
-
|
1463
|
-
|
1464
|
-
|
1465
|
-
|
1466
|
-
|
1467
|
-
|
1468
|
-
|
1469
|
-
|
1470
|
-
|
1471
|
-
|
1472
|
-
|
1473
|
-
|
1474
|
-
|
1475
|
-
|
1476
|
-
|
1477
|
-
|
1478
|
-
|
1479
|
-
""
|
1480
|
-
|
1481
|
-
|
1482
|
-
|
1483
|
-
|
1484
|
-
|
1485
|
-
|
1486
|
-
|
1487
|
-
|
1488
|
-
|
1489
|
-
|
1490
|
-
|
1491
|
-
|
1492
|
-
|
1493
|
-
|
1494
|
-
|
1495
|
-
|
1496
|
-
|
1497
|
-
|
1498
|
-
|
1499
|
-
|
1500
|
-
|
1501
|
-
|
1502
|
-
|
1503
|
-
|
1504
|
-
|
1505
|
-
|
1506
|
-
|
1507
|
-
|
1
|
+
"""
|
2
|
+
This module provides a set of console commands for managing branches and operations within the application.
|
3
|
+
These commands allow users to load files, manage operations, and manipulate elements in various ways.
|
4
|
+
|
5
|
+
Functions:
|
6
|
+
- plugin(kernel, lifecycle=None): Initializes the plugin and sets up branch commands.
|
7
|
+
- init_commands(kernel): Initializes the branch commands and defines the associated operations.
|
8
|
+
- load(channel, _, filename=None, **kwargs): Loads a file from the working directory and adds its contents to the application.
|
9
|
+
Args:
|
10
|
+
channel: The communication channel for messages.
|
11
|
+
filename: The name of the file to load.
|
12
|
+
Returns:
|
13
|
+
A tuple containing the type of the file and its path.
|
14
|
+
- element(command, **kwargs): Displays information about operations in the system.
|
15
|
+
Args:
|
16
|
+
command: The command context.
|
17
|
+
Returns:
|
18
|
+
None
|
19
|
+
- operation_select(**kwargs): Selects the currently emphasized operations.
|
20
|
+
Args:
|
21
|
+
command: The command context.
|
22
|
+
Returns:
|
23
|
+
A tuple containing the type of operations and the selected operations.
|
24
|
+
- operation_all(**kwargs): Selects all operations in the system.
|
25
|
+
Args:
|
26
|
+
command: The command context.
|
27
|
+
Returns:
|
28
|
+
A tuple containing the type of operations and all operations.
|
29
|
+
- operation_invert(**kwargs): Selects all non-emphasized operations.
|
30
|
+
Args:
|
31
|
+
command: The command context.
|
32
|
+
Returns:
|
33
|
+
A tuple containing the type of operations and the non-selected operations.
|
34
|
+
- operation_base(**kwargs): Selects the currently emphasized operations.
|
35
|
+
Args:
|
36
|
+
command: The command context.
|
37
|
+
Returns:
|
38
|
+
A tuple containing the type of operations and the emphasized operations.
|
39
|
+
- operation_re(command, channel, _, **kwargs): Selects operations based on specified indices.
|
40
|
+
Args:
|
41
|
+
command: The command context.
|
42
|
+
channel: The communication channel for messages.
|
43
|
+
Returns:
|
44
|
+
A tuple containing the type of operations and the selected operations.
|
45
|
+
- operation_select_emphasis(data=None, **kwargs): Sets the specified operations as the current selection.
|
46
|
+
Args:
|
47
|
+
data: The operations to select.
|
48
|
+
Returns:
|
49
|
+
A tuple containing the type of operations and the selected operations.
|
50
|
+
- operation_select_plus(data=None, **kwargs): Adds the specified operations to the current selection.
|
51
|
+
Args:
|
52
|
+
data: The operations to add.
|
53
|
+
Returns:
|
54
|
+
A tuple containing the type of operations and the updated selection.
|
55
|
+
- operation_select_minus(data=None, **kwargs): Removes the specified operations from the current selection.
|
56
|
+
Args:
|
57
|
+
data: The operations to remove.
|
58
|
+
Returns:
|
59
|
+
A tuple containing the type of operations and the updated selection.
|
60
|
+
- operation_select_xor(data=None, **kwargs): Toggles the specified operations in the current selection.
|
61
|
+
Args:
|
62
|
+
data: The operations to toggle.
|
63
|
+
Returns:
|
64
|
+
A tuple containing the type of operations and the updated selection.
|
65
|
+
- opelem_select_range(data=None, data_type=None, start=None, end=None, step=1, **kwargs): Subsets the current selection based on specified start, end, and step indices.
|
66
|
+
Args:
|
67
|
+
data: The elements to subset.
|
68
|
+
data_type: The type of data being processed.
|
69
|
+
start: The starting index for the subset.
|
70
|
+
end: The ending index for the subset.
|
71
|
+
step: The step size for the subset.
|
72
|
+
Returns:
|
73
|
+
A tuple containing the type of data and the subsetted elements.
|
74
|
+
- opelem_filter(channel=None, data=None, data_type=None, filter=None, **kwargs): Filters the current selection based on the provided filter string.
|
75
|
+
Args:
|
76
|
+
channel: The communication channel for messages.
|
77
|
+
data: The elements to filter.
|
78
|
+
data_type: The type of data being processed.
|
79
|
+
filter: The filter string to apply.
|
80
|
+
Returns:
|
81
|
+
A tuple containing the type of data and the filtered elements.
|
82
|
+
- opelem_id(command, channel, _, id=None, data=None, data_type=None, **kwargs): Sets or retrieves the ID of the specified elements.
|
83
|
+
Args:
|
84
|
+
command: The command context.
|
85
|
+
channel: The communication channel for messages.
|
86
|
+
id: The new ID to set.
|
87
|
+
data: The elements to modify.
|
88
|
+
data_type: The type of data being processed.
|
89
|
+
Returns:
|
90
|
+
A tuple containing the type of data and the modified elements.
|
91
|
+
- opelem_label(command, channel, _, label=None, data=None, data_type=None, **kwargs): Sets or retrieves the label of the specified elements.
|
92
|
+
Args:
|
93
|
+
command: The command context.
|
94
|
+
channel: The communication channel for messages.
|
95
|
+
label: The new label to set.
|
96
|
+
data: The elements to modify.
|
97
|
+
data_type: The type of data being processed.
|
98
|
+
Returns:
|
99
|
+
A tuple containing the type of data and the modified elements.
|
100
|
+
- operation_empty(channel, _, data=None, data_type=None, **kwargs): Removes all elements from the specified operations.
|
101
|
+
Args:
|
102
|
+
channel: The communication channel for messages.
|
103
|
+
data: The operations to clear.
|
104
|
+
data_type: The type of data being processed.
|
105
|
+
Returns:
|
106
|
+
A tuple containing the type of data and the cleared operations.
|
107
|
+
- operation_list(command, channel, _, data=None, **kwargs): Lists information about the specified operations.
|
108
|
+
Args:
|
109
|
+
command: The command context.
|
110
|
+
channel: The communication channel for messages.
|
111
|
+
data: The operations to list.
|
112
|
+
Returns:
|
113
|
+
A tuple containing the type of data and the listed operations.
|
114
|
+
- element_lock(data=None, **kwargs): Locks the specified elements to prevent manipulation.
|
115
|
+
Args:
|
116
|
+
data: The elements to lock.
|
117
|
+
Returns:
|
118
|
+
A tuple containing the type of data and the locked elements.
|
119
|
+
- element_unlock(data=None, **kwargs): Unlocks the specified elements to allow manipulation.
|
120
|
+
Args:
|
121
|
+
data: The elements to unlock.
|
122
|
+
Returns:
|
123
|
+
A tuple containing the type of data and the unlocked elements.
|
124
|
+
- e_copy(data=None, data_type=None, post=None, dx=None, dy=None, copies=None, **kwargs): Duplicates the specified elements a given number of times with optional offsets.
|
125
|
+
Args:
|
126
|
+
data: The elements to copy.
|
127
|
+
data_type: The type of data being processed.
|
128
|
+
post: Additional processing information.
|
129
|
+
dx: The x-offset for the copies.
|
130
|
+
dy: The y-offset for the copies.
|
131
|
+
copies: The number of copies to create.
|
132
|
+
Returns:
|
133
|
+
A tuple containing the type of data and the copied elements.
|
134
|
+
- e_delete(command, channel, _, data=None, data_type=None, **kwargs): Deletes the specified elements or operations.
|
135
|
+
Args:
|
136
|
+
command: The command context.
|
137
|
+
channel: The communication channel for messages.
|
138
|
+
data: The elements or operations to delete.
|
139
|
+
data_type: The type of data being processed.
|
140
|
+
Returns:
|
141
|
+
A tuple containing the type of data and the deleted elements.
|
142
|
+
"""
|
143
|
+
|
144
|
+
import re
|
145
|
+
from copy import copy
|
146
|
+
|
147
|
+
from meerk40t.core.node.effect_hatch import HatchEffectNode
|
148
|
+
from meerk40t.core.node.op_cut import CutOpNode
|
149
|
+
from meerk40t.core.node.op_dots import DotsOpNode
|
150
|
+
from meerk40t.core.node.op_engrave import EngraveOpNode
|
151
|
+
from meerk40t.core.node.op_image import ImageOpNode
|
152
|
+
from meerk40t.core.node.op_raster import RasterOpNode
|
153
|
+
from meerk40t.core.units import Angle, Length
|
154
|
+
from meerk40t.kernel import CommandSyntaxError
|
155
|
+
from meerk40t.svgelements import Color, Matrix
|
156
|
+
from meerk40t.core.elements.element_types import op_nodes
|
157
|
+
from meerk40t.tools.geomstr import NON_GEOMETRY_TYPES
|
158
|
+
def plugin(kernel, lifecycle=None):
|
159
|
+
_ = kernel.translation
|
160
|
+
if lifecycle == "postboot":
|
161
|
+
init_commands(kernel)
|
162
|
+
|
163
|
+
|
164
|
+
def init_commands(kernel):
|
165
|
+
self = kernel.elements
|
166
|
+
|
167
|
+
_ = kernel.translation
|
168
|
+
|
169
|
+
classify_new = self.post_classify
|
170
|
+
|
171
|
+
@self.console_argument("filename")
|
172
|
+
@self.console_command(
|
173
|
+
"load",
|
174
|
+
help=_("loads file from working directory"),
|
175
|
+
input_type=None,
|
176
|
+
output_type="file",
|
177
|
+
)
|
178
|
+
def load(channel, _, filename=None, **kwargs):
|
179
|
+
import os
|
180
|
+
|
181
|
+
if filename is None:
|
182
|
+
channel(_("No file specified."))
|
183
|
+
return
|
184
|
+
new_file = os.path.join(self.kernel.current_directory, filename)
|
185
|
+
if not os.path.exists(new_file):
|
186
|
+
channel(_("No such file."))
|
187
|
+
return
|
188
|
+
try:
|
189
|
+
channel(_("loading..."))
|
190
|
+
result = self.load(new_file)
|
191
|
+
if result:
|
192
|
+
channel(_("Done."))
|
193
|
+
except AttributeError:
|
194
|
+
raise CommandSyntaxError(_("Loading files was not defined"))
|
195
|
+
return "file", new_file
|
196
|
+
|
197
|
+
# ==========
|
198
|
+
# OPERATION BASE
|
199
|
+
# ==========
|
200
|
+
|
201
|
+
@self.console_command("operations", help=_("Show information about operations"))
|
202
|
+
def element(**kwargs):
|
203
|
+
self(".operation* list\n")
|
204
|
+
|
205
|
+
@self.console_command(
|
206
|
+
"operation.*", help=_("operation.*: selected operations"), output_type="ops"
|
207
|
+
)
|
208
|
+
def operation_select(**kwargs):
|
209
|
+
return "ops", list(self.ops(emphasized=True))
|
210
|
+
|
211
|
+
@self.console_command(
|
212
|
+
"operation*", help=_("operation*: all operations"), output_type="ops"
|
213
|
+
)
|
214
|
+
def operation_all(**kwargs):
|
215
|
+
return "ops", list(self.ops())
|
216
|
+
|
217
|
+
@self.console_command(
|
218
|
+
"operation~",
|
219
|
+
help=_("operation~: non selected operations."),
|
220
|
+
output_type="ops",
|
221
|
+
)
|
222
|
+
def operation_invert(**kwargs):
|
223
|
+
return "ops", list(self.ops(emphasized=False))
|
224
|
+
|
225
|
+
@self.console_command(
|
226
|
+
"operation", help=_("operation: selected operations."), output_type="ops"
|
227
|
+
)
|
228
|
+
def operation_base(**kwargs):
|
229
|
+
return "ops", list(self.ops(emphasized=True))
|
230
|
+
|
231
|
+
@self.console_command(
|
232
|
+
r"operation([0-9]+,?)+",
|
233
|
+
help=_("operation0,2: operation #0 and #2"),
|
234
|
+
regex=True,
|
235
|
+
output_type="ops",
|
236
|
+
)
|
237
|
+
def operation_re(command, channel, _, **kwargs):
|
238
|
+
arg = command[9:]
|
239
|
+
op_values = []
|
240
|
+
for value in arg.split(","):
|
241
|
+
try:
|
242
|
+
value = int(value)
|
243
|
+
except ValueError:
|
244
|
+
continue
|
245
|
+
try:
|
246
|
+
op = self.get_op(value)
|
247
|
+
op_values.append(op)
|
248
|
+
except IndexError:
|
249
|
+
channel(_("index {index} out of range").format(index=value))
|
250
|
+
return "ops", op_values
|
251
|
+
|
252
|
+
@self.console_command(
|
253
|
+
"select",
|
254
|
+
help=_("Set these values as the selection."),
|
255
|
+
input_type="ops",
|
256
|
+
output_type="ops",
|
257
|
+
)
|
258
|
+
def operation_select_emphasis(data=None, **kwargs):
|
259
|
+
self.set_emphasis(data)
|
260
|
+
return "ops", data
|
261
|
+
|
262
|
+
@self.console_command(
|
263
|
+
"select+",
|
264
|
+
help=_("Add the input to the selection"),
|
265
|
+
input_type="ops",
|
266
|
+
output_type="ops",
|
267
|
+
)
|
268
|
+
def operation_select_plus(data=None, **kwargs):
|
269
|
+
ops = list(self.ops(emphasized=True))
|
270
|
+
ops.extend(data)
|
271
|
+
self.set_emphasis(ops)
|
272
|
+
return "ops", ops
|
273
|
+
|
274
|
+
@self.console_command(
|
275
|
+
"select-",
|
276
|
+
help=_("Remove the input data from the selection"),
|
277
|
+
input_type="ops",
|
278
|
+
output_type="ops",
|
279
|
+
)
|
280
|
+
def operation_select_minus(data=None, **kwargs):
|
281
|
+
ops = list(self.ops(emphasized=True))
|
282
|
+
for e in data:
|
283
|
+
try:
|
284
|
+
ops.remove(e)
|
285
|
+
except ValueError:
|
286
|
+
pass
|
287
|
+
self.set_emphasis(ops)
|
288
|
+
return "ops", ops
|
289
|
+
|
290
|
+
@self.console_command(
|
291
|
+
"select^",
|
292
|
+
help=_("Toggle the input data in the selection"),
|
293
|
+
input_type="ops",
|
294
|
+
output_type="ops",
|
295
|
+
)
|
296
|
+
def operation_select_xor(data=None, **kwargs):
|
297
|
+
ops = list(self.ops(emphasized=True))
|
298
|
+
for e in data:
|
299
|
+
try:
|
300
|
+
ops.remove(e)
|
301
|
+
except ValueError:
|
302
|
+
ops.append(e)
|
303
|
+
self.set_emphasis(ops)
|
304
|
+
return "ops", ops
|
305
|
+
|
306
|
+
@self.console_argument("start", type=int, help=_("start"))
|
307
|
+
@self.console_argument("end", type=int, help=_("end"))
|
308
|
+
@self.console_option("step", "s", type=int, default=1, help=_("step"))
|
309
|
+
@self.console_command(
|
310
|
+
"range",
|
311
|
+
help=_("Subset existing selection by begin and end indices and step"),
|
312
|
+
input_type=("ops", "elements"),
|
313
|
+
output_type=("ops", "elements"),
|
314
|
+
)
|
315
|
+
def opelem_select_range(
|
316
|
+
data=None, data_type=None, start=None, end=None, step=1, **kwargs
|
317
|
+
):
|
318
|
+
sublist = list()
|
319
|
+
for e in range(start, end, step):
|
320
|
+
try:
|
321
|
+
sublist.append(data[e])
|
322
|
+
except IndexError:
|
323
|
+
pass
|
324
|
+
self.set_emphasis(sublist)
|
325
|
+
return data_type, sublist
|
326
|
+
|
327
|
+
@self.console_argument("filter", type=str, help=_("Filter to apply"))
|
328
|
+
@self.console_command(
|
329
|
+
"filter",
|
330
|
+
help=_("Filter data by given value"),
|
331
|
+
input_type=("ops", "elements"),
|
332
|
+
output_type=("ops", "elements"),
|
333
|
+
)
|
334
|
+
def opelem_filter(channel=None, data=None, data_type=None, filter=None, **kwargs):
|
335
|
+
"""
|
336
|
+
Apply a filter string to a filter particular operations from the current data.
|
337
|
+
Operations or elements are evaluated in an infix prioritized stack format without spaces.
|
338
|
+
Qualified values for all node types are: id, label, len, type
|
339
|
+
Qualified element values are stroke, fill, dpi, elem
|
340
|
+
Qualified operation values are speed, power, frequency, dpi, acceleration, op, passes, color, overscan
|
341
|
+
Valid operators are >, >=, <, <=, =, ==, +, -, *, /, &, &&, |, and ||
|
342
|
+
Valid string operators are startswith, endswith, contains.
|
343
|
+
String values require single-quotes ', because the console interface requires double-quotes.
|
344
|
+
e.g. filter speed>=10, filter speed=5+5, filter speed>power/10, filter speed==2*4+2
|
345
|
+
e.g. filter engrave=op&speed=35|cut=op&speed=10
|
346
|
+
e.g. filter len=0
|
347
|
+
e.g. operation* filter "type='op image'" list
|
348
|
+
e.g. element* filter "id startswith 'p'" list
|
349
|
+
"""
|
350
|
+
sublist = list()
|
351
|
+
_filter_parse = [
|
352
|
+
("STR", r"'([^']*)'"),
|
353
|
+
("SKIP", r"[ ,\t\n\x09\x0A\x0C\x0D]+"),
|
354
|
+
("OP20", r"(\*|/)"),
|
355
|
+
("OP15", r"(\+|-)"),
|
356
|
+
("OP11", r"(<=|>=|==|!=|startswith|endswith|contains)"),
|
357
|
+
("OP10", r"(<|>|=)"),
|
358
|
+
("OP5", r"(&&)"),
|
359
|
+
("OP4", r"(&)"),
|
360
|
+
("OP3", r"(\|\|)"),
|
361
|
+
("OP2", r"(\|)"),
|
362
|
+
("NUM", r"([-+]?[0-9]*\.?[0-9]+(?:[eE][-+]?[0-9]+)?)"),
|
363
|
+
(
|
364
|
+
"COLOR",
|
365
|
+
r"(#[0123456789abcdefABCDEF]{6}|#[0123456789abcdefABCDEF]{3})",
|
366
|
+
),
|
367
|
+
(
|
368
|
+
"TYPE",
|
369
|
+
r"(raster|image|cut|engrave|dots|blob|rect|path|ellipse|point|image|line|polyline)",
|
370
|
+
),
|
371
|
+
(
|
372
|
+
"VAL",
|
373
|
+
r"(type|op|speed|power|frequency|dpi|passes|color|overscan|len|elem|stroke|fill|id|label)",
|
374
|
+
),
|
375
|
+
]
|
376
|
+
filter_re = re.compile("|".join("(?P<%s>%s)" % pair for pair in _filter_parse))
|
377
|
+
operator = list()
|
378
|
+
operand = list()
|
379
|
+
|
380
|
+
def filter_parser(text: str):
|
381
|
+
p = 0
|
382
|
+
limit = len(text)
|
383
|
+
while p < limit:
|
384
|
+
match = filter_re.match(text, p)
|
385
|
+
if match is None:
|
386
|
+
break # No more matches.
|
387
|
+
_kind = match.lastgroup
|
388
|
+
_start = p
|
389
|
+
p = match.end()
|
390
|
+
if _kind == "SKIP":
|
391
|
+
continue
|
392
|
+
_value = match.group()
|
393
|
+
yield _kind, _value, _start, p
|
394
|
+
|
395
|
+
def solve_to(order: int):
|
396
|
+
try:
|
397
|
+
while len(operator) and operator[0][0] >= order:
|
398
|
+
_p, op = operator.pop()
|
399
|
+
v2 = operand.pop()
|
400
|
+
v1 = operand.pop()
|
401
|
+
try:
|
402
|
+
if op == "==" or op == "=":
|
403
|
+
operand.append(v1 == v2)
|
404
|
+
elif op == "!=":
|
405
|
+
operand.append(v1 != v2)
|
406
|
+
elif op == ">":
|
407
|
+
operand.append(v1 > v2)
|
408
|
+
elif op == "<":
|
409
|
+
operand.append(v1 < v2)
|
410
|
+
elif op == "<=":
|
411
|
+
operand.append(v1 <= v2)
|
412
|
+
elif op == ">=":
|
413
|
+
operand.append(v1 >= v2)
|
414
|
+
elif op == "&&" or op == "&":
|
415
|
+
operand.append(v1 and v2)
|
416
|
+
elif op == "||" or op == "|":
|
417
|
+
operand.append(v1 or v2)
|
418
|
+
elif op == "*":
|
419
|
+
operand.append(v1 * v2)
|
420
|
+
elif op == "/":
|
421
|
+
operand.append(v1 / v2)
|
422
|
+
elif op == "+":
|
423
|
+
operand.append(v1 + v2)
|
424
|
+
elif op == "-":
|
425
|
+
operand.append(v1 - v2)
|
426
|
+
elif op == "startswith":
|
427
|
+
operand.append(str(v1).startswith(str(v2)))
|
428
|
+
elif op == "endswith":
|
429
|
+
operand.append(str(v1).endswith(str(v2)))
|
430
|
+
elif op == "contains":
|
431
|
+
operand.append(str(v2) in (str(v1)))
|
432
|
+
except TypeError:
|
433
|
+
raise CommandSyntaxError("Cannot evaluate expression")
|
434
|
+
except ZeroDivisionError:
|
435
|
+
operand.append(float("inf"))
|
436
|
+
except IndexError:
|
437
|
+
pass
|
438
|
+
|
439
|
+
for e in data:
|
440
|
+
for kind, value, start, pos in filter_parser(filter):
|
441
|
+
if kind == "COLOR":
|
442
|
+
operand.append(Color(value))
|
443
|
+
elif kind == "VAL":
|
444
|
+
try:
|
445
|
+
if value == "type":
|
446
|
+
operand.append(e.type)
|
447
|
+
elif value == "op":
|
448
|
+
if e.type.startswith("op"):
|
449
|
+
operand.append(e.type.replace("op", "").strip())
|
450
|
+
else:
|
451
|
+
operand.append(None)
|
452
|
+
elif value == "speed":
|
453
|
+
operand.append(e.speed)
|
454
|
+
elif value == "power":
|
455
|
+
operand.append(e.power)
|
456
|
+
elif value == "frequency":
|
457
|
+
operand.append(e.frequency)
|
458
|
+
elif value == "dpi":
|
459
|
+
operand.append(e.dpi)
|
460
|
+
elif value == "passes":
|
461
|
+
operand.append(e.passes)
|
462
|
+
elif value == "color":
|
463
|
+
operand.append(e.color)
|
464
|
+
elif value == "len":
|
465
|
+
try:
|
466
|
+
operand.append(len(e.children))
|
467
|
+
except AttributeError:
|
468
|
+
operand.append(0)
|
469
|
+
elif value == "elem":
|
470
|
+
if e.type.startswith("elem"):
|
471
|
+
operand.append(e.type.replace("elem", "").strip())
|
472
|
+
else:
|
473
|
+
operand.append(None)
|
474
|
+
elif value == "stroke":
|
475
|
+
operand.append(e.stroke)
|
476
|
+
elif value == "fill":
|
477
|
+
operand.append(e.fill)
|
478
|
+
elif value == "stroke_width":
|
479
|
+
operand.append(e.stroke_width)
|
480
|
+
elif value == "id":
|
481
|
+
operand.append(e.id)
|
482
|
+
elif value == "label":
|
483
|
+
operand.append(e.label)
|
484
|
+
else:
|
485
|
+
operand.append(e.settings.get(value))
|
486
|
+
except AttributeError:
|
487
|
+
operand.append(None)
|
488
|
+
elif kind == "NUM":
|
489
|
+
operand.append(float(value))
|
490
|
+
elif kind == "TYPE":
|
491
|
+
operand.append(value)
|
492
|
+
elif kind == "STR":
|
493
|
+
operand.append(value[1:-1])
|
494
|
+
elif kind.startswith("OP"):
|
495
|
+
precedence = int(kind[2:])
|
496
|
+
solve_to(precedence)
|
497
|
+
operator.append((precedence, value))
|
498
|
+
solve_to(0)
|
499
|
+
if len(operand) == 1:
|
500
|
+
if operand.pop():
|
501
|
+
sublist.append(e)
|
502
|
+
else:
|
503
|
+
raise CommandSyntaxError(_("Filter parse failed"))
|
504
|
+
|
505
|
+
self.set_emphasis(sublist)
|
506
|
+
return data_type, sublist
|
507
|
+
|
508
|
+
@self.console_argument(
|
509
|
+
"id",
|
510
|
+
type=str,
|
511
|
+
help=_("new id to set values to"),
|
512
|
+
)
|
513
|
+
@self.console_command(
|
514
|
+
"id",
|
515
|
+
help=_("id <id>"),
|
516
|
+
input_type=("ops", "elements"),
|
517
|
+
output_type=("elements", "ops"),
|
518
|
+
)
|
519
|
+
def opelem_id(command, channel, _, id=None, data=None, data_type=None, **kwargs):
|
520
|
+
if id is None:
|
521
|
+
# Display data about id.
|
522
|
+
channel("----------")
|
523
|
+
channel(_("ID Values:"))
|
524
|
+
for i, e in enumerate(data):
|
525
|
+
name = str(e)
|
526
|
+
channel(
|
527
|
+
_("{index}: {name} - id = {id}").format(index=i, name=name, id=e.id)
|
528
|
+
)
|
529
|
+
channel("----------")
|
530
|
+
return
|
531
|
+
|
532
|
+
if len(data) == 0:
|
533
|
+
channel(_("No selected nodes"))
|
534
|
+
return
|
535
|
+
for e in data:
|
536
|
+
e.id = id
|
537
|
+
self.validate_ids()
|
538
|
+
self.signal("element_property_update", data)
|
539
|
+
self.signal("refresh_scene", "Scene")
|
540
|
+
return data_type, data
|
541
|
+
|
542
|
+
@self.console_argument(
|
543
|
+
"label",
|
544
|
+
type=str,
|
545
|
+
help=_("new label to set values to"),
|
546
|
+
)
|
547
|
+
@self.console_command(
|
548
|
+
"label",
|
549
|
+
help=_("label <label>"),
|
550
|
+
input_type=("ops", "elements"),
|
551
|
+
output_type=("elements", "ops"),
|
552
|
+
)
|
553
|
+
def opelem_label(
|
554
|
+
command, channel, _, label=None, data=None, data_type=None, **kwargs
|
555
|
+
):
|
556
|
+
if label is None:
|
557
|
+
# Display data about id.
|
558
|
+
channel("----------")
|
559
|
+
channel(_("Label Values:"))
|
560
|
+
for i, e in enumerate(data):
|
561
|
+
name = str(e)
|
562
|
+
channel(
|
563
|
+
_("{index}: {name} - label = {label}").format(
|
564
|
+
index=i, name=name, label=e.label
|
565
|
+
)
|
566
|
+
)
|
567
|
+
channel("----------")
|
568
|
+
return
|
569
|
+
|
570
|
+
if len(data) == 0:
|
571
|
+
channel(_("No selected nodes"))
|
572
|
+
return
|
573
|
+
for e in data:
|
574
|
+
e.label = label
|
575
|
+
self.signal("element_property_update", data)
|
576
|
+
self.signal("refresh_scene", "Scene")
|
577
|
+
return data_type, data
|
578
|
+
|
579
|
+
|
580
|
+
@self.console_command(
|
581
|
+
"empty",
|
582
|
+
help=_("Remove all elements from provided operations"),
|
583
|
+
input_type="ops",
|
584
|
+
output_type="ops",
|
585
|
+
)
|
586
|
+
def operation_empty(channel, _, data=None, **kwargs):
|
587
|
+
if data is None:
|
588
|
+
data = list()
|
589
|
+
for item in list(self.flat(selected=True, cascade=False, types=op_nodes)):
|
590
|
+
data.append(item)
|
591
|
+
# _("Clear operations")
|
592
|
+
with self.undoscope("Clear operations"):
|
593
|
+
index_ops = list(self.ops())
|
594
|
+
for item in data:
|
595
|
+
i = index_ops.index(item)
|
596
|
+
select_piece = "*" if item.emphasized else " "
|
597
|
+
name = f"{select_piece} {i}: {str(item)}"
|
598
|
+
channel(f"{name}: {len(item.children)}")
|
599
|
+
item.remove_all_children()
|
600
|
+
self.signal("rebuild_tree", "operations")
|
601
|
+
|
602
|
+
@self.console_command(
|
603
|
+
"list",
|
604
|
+
help=_("Show information about the chained data"),
|
605
|
+
input_type="ops",
|
606
|
+
output_type="ops",
|
607
|
+
)
|
608
|
+
def operation_list(channel, _, data=None, **kwargs):
|
609
|
+
channel("----------")
|
610
|
+
channel(_("Operations:"))
|
611
|
+
index_ops = list(self.ops())
|
612
|
+
for op_obj in data:
|
613
|
+
i = index_ops.index(op_obj)
|
614
|
+
select_piece = "*" if op_obj.emphasized else " "
|
615
|
+
name = f"{select_piece} {i}: {str(op_obj)}"
|
616
|
+
channel(name)
|
617
|
+
if isinstance(op_obj, list):
|
618
|
+
for q, oe in enumerate(op_obj):
|
619
|
+
stroke_piece = (
|
620
|
+
"None"
|
621
|
+
if (not hasattr(oe, "stroke") or oe.stroke) is None
|
622
|
+
else oe.stroke.hex
|
623
|
+
)
|
624
|
+
fill_piece = (
|
625
|
+
"None"
|
626
|
+
if (not hasattr(oe, "stroke") or oe.fill) is None
|
627
|
+
else oe.fill.hex
|
628
|
+
)
|
629
|
+
ident_piece = str(oe.id)
|
630
|
+
name = f"{''.ljust(5)}{q}: {str(type(oe).__name__)}-{ident_piece} s:{stroke_piece} f:{fill_piece}"
|
631
|
+
channel(name)
|
632
|
+
channel("----------")
|
633
|
+
|
634
|
+
@self.console_option("color", "c", type=Color)
|
635
|
+
@self.console_option("default", "D", type=bool)
|
636
|
+
@self.console_option("speed", "s", type=float)
|
637
|
+
@self.console_option("power", "p", type=float)
|
638
|
+
@self.console_option("dpi", "d", type=int)
|
639
|
+
@self.console_option("overscan", "o", type=self.length)
|
640
|
+
@self.console_option("passes", "x", type=int)
|
641
|
+
@self.console_option(
|
642
|
+
"parallel",
|
643
|
+
"P",
|
644
|
+
type=bool,
|
645
|
+
help=_("Creates a new operation for each element given"),
|
646
|
+
action="store_true",
|
647
|
+
)
|
648
|
+
@self.console_option(
|
649
|
+
"stroke",
|
650
|
+
"K",
|
651
|
+
type=bool,
|
652
|
+
action="store_true",
|
653
|
+
help=_(
|
654
|
+
"Set the operation color based on the stroke if the first stroked item added to this operation"
|
655
|
+
),
|
656
|
+
)
|
657
|
+
@self.console_option(
|
658
|
+
"fill",
|
659
|
+
"F",
|
660
|
+
type=bool,
|
661
|
+
action="store_true",
|
662
|
+
help=_(
|
663
|
+
"Set the operation color based on the fill if the first filled item added to this operation"
|
664
|
+
),
|
665
|
+
)
|
666
|
+
@self.console_command(
|
667
|
+
("cut", "engrave", "raster", "imageop", "dots", "hatch"),
|
668
|
+
help=_(
|
669
|
+
"<cut/engrave/raster/imageop/dots/hatch> - group the elements into this operation"
|
670
|
+
),
|
671
|
+
input_type=(None, "elements"),
|
672
|
+
output_type="ops",
|
673
|
+
)
|
674
|
+
def makeop(
|
675
|
+
command,
|
676
|
+
data=None,
|
677
|
+
color=None,
|
678
|
+
default=None,
|
679
|
+
speed=None,
|
680
|
+
power=None,
|
681
|
+
dpi=None,
|
682
|
+
overscan=None,
|
683
|
+
passes=None,
|
684
|
+
parallel=False,
|
685
|
+
stroke=False,
|
686
|
+
fill=False,
|
687
|
+
**kwargs,
|
688
|
+
):
|
689
|
+
op_list = []
|
690
|
+
|
691
|
+
def make_op():
|
692
|
+
if command == "cut":
|
693
|
+
return CutOpNode()
|
694
|
+
elif command == "engrave":
|
695
|
+
return EngraveOpNode()
|
696
|
+
elif command == "raster":
|
697
|
+
return RasterOpNode()
|
698
|
+
elif command == "imageop":
|
699
|
+
return ImageOpNode()
|
700
|
+
elif command == "dots":
|
701
|
+
return DotsOpNode()
|
702
|
+
elif command == "hatch":
|
703
|
+
parent_node = EngraveOpNode()
|
704
|
+
parent_node.add_node(HatchEffectNode())
|
705
|
+
return parent_node
|
706
|
+
else:
|
707
|
+
raise ValueError
|
708
|
+
|
709
|
+
if parallel:
|
710
|
+
if data is None:
|
711
|
+
return "op", []
|
712
|
+
for item in data:
|
713
|
+
op = make_op()
|
714
|
+
if color is not None:
|
715
|
+
op.color = color
|
716
|
+
elif fill:
|
717
|
+
try:
|
718
|
+
op.color = item.fill
|
719
|
+
except AttributeError:
|
720
|
+
continue
|
721
|
+
elif stroke:
|
722
|
+
try:
|
723
|
+
op.color = item.stroke
|
724
|
+
except AttributeError:
|
725
|
+
continue
|
726
|
+
if default is not None:
|
727
|
+
op.default = default
|
728
|
+
if speed is not None:
|
729
|
+
op.speed = speed
|
730
|
+
if power is not None:
|
731
|
+
op.power = power
|
732
|
+
if passes is not None:
|
733
|
+
op.passes_custom = True
|
734
|
+
op.passes = passes
|
735
|
+
if dpi is not None:
|
736
|
+
op.dpi = dpi
|
737
|
+
if overscan is not None:
|
738
|
+
op.overscan = overscan
|
739
|
+
self.add_op(op)
|
740
|
+
op.add_reference(item)
|
741
|
+
op_list.append(op)
|
742
|
+
else:
|
743
|
+
op = make_op()
|
744
|
+
if color is not None:
|
745
|
+
op.color = color
|
746
|
+
elif fill:
|
747
|
+
try:
|
748
|
+
op.color = data[0].fill
|
749
|
+
except (AttributeError, IndexError):
|
750
|
+
pass
|
751
|
+
elif stroke:
|
752
|
+
try:
|
753
|
+
op.color = data[0].stroke
|
754
|
+
except (AttributeError, IndexError):
|
755
|
+
pass
|
756
|
+
if default is not None:
|
757
|
+
op.default = default
|
758
|
+
if speed is not None:
|
759
|
+
op.speed = speed
|
760
|
+
if power is not None:
|
761
|
+
op.power = power
|
762
|
+
if passes is not None:
|
763
|
+
op.passes_custom = True
|
764
|
+
op.passes = passes
|
765
|
+
if dpi is not None:
|
766
|
+
op.dpi = dpi
|
767
|
+
if overscan is not None:
|
768
|
+
op.overscan = overscan
|
769
|
+
self.add_op(op)
|
770
|
+
if data is not None:
|
771
|
+
for item in data:
|
772
|
+
op.add_reference(item)
|
773
|
+
op_list.append(op)
|
774
|
+
return "ops", op_list
|
775
|
+
|
776
|
+
@self.console_argument(
|
777
|
+
"time",
|
778
|
+
type=float,
|
779
|
+
default=5,
|
780
|
+
help=_("Time for the given wait operation."),
|
781
|
+
)
|
782
|
+
@self.console_command(
|
783
|
+
"waitop",
|
784
|
+
help=_("<waitop> - Create new utility operation"),
|
785
|
+
input_type=None,
|
786
|
+
output_type="ops",
|
787
|
+
)
|
788
|
+
def waitop(
|
789
|
+
command,
|
790
|
+
time=None,
|
791
|
+
**kwargs,
|
792
|
+
):
|
793
|
+
op = self.op_branch.add(type="util wait", wait=time)
|
794
|
+
return "ops", [op]
|
795
|
+
|
796
|
+
@self.console_argument(
|
797
|
+
"mask",
|
798
|
+
type=int,
|
799
|
+
default=0,
|
800
|
+
help=_("binary input/output mask"),
|
801
|
+
)
|
802
|
+
@self.console_argument(
|
803
|
+
"value",
|
804
|
+
type=int,
|
805
|
+
default=0,
|
806
|
+
help=_("binary input/output value"),
|
807
|
+
)
|
808
|
+
@self.console_command(
|
809
|
+
("outputop", "inputop"),
|
810
|
+
help=_("<outputop, inputop> - Create new utility operation"),
|
811
|
+
input_type=None,
|
812
|
+
output_type="ops",
|
813
|
+
)
|
814
|
+
def io_op(
|
815
|
+
command,
|
816
|
+
mask=None,
|
817
|
+
value=None,
|
818
|
+
**kwargs,
|
819
|
+
):
|
820
|
+
if command == "inputop":
|
821
|
+
op = self.op_branch.add(
|
822
|
+
type="util input", input_mask=mask, input_value=value
|
823
|
+
)
|
824
|
+
else:
|
825
|
+
op = self.op_branch.add(
|
826
|
+
type="util output", output_mask=mask, output_value=value
|
827
|
+
)
|
828
|
+
return "ops", [op]
|
829
|
+
|
830
|
+
@self.console_argument(
|
831
|
+
"x",
|
832
|
+
type=Length,
|
833
|
+
default=0,
|
834
|
+
help=_("X-Coordinate of Goto?"),
|
835
|
+
)
|
836
|
+
@self.console_argument(
|
837
|
+
"y",
|
838
|
+
type=Length,
|
839
|
+
default=0,
|
840
|
+
help=_("Y-Coordinate of Goto?"),
|
841
|
+
)
|
842
|
+
@self.console_command(
|
843
|
+
"gotoop",
|
844
|
+
help=_("<gotoop> <x> <y> - Create new utility operation"),
|
845
|
+
input_type=None,
|
846
|
+
output_type="ops",
|
847
|
+
)
|
848
|
+
def gotoop(
|
849
|
+
command,
|
850
|
+
x=0,
|
851
|
+
y=0,
|
852
|
+
**kwargs,
|
853
|
+
):
|
854
|
+
op = self.op_branch.add(type="util goto", x=str(x), y=str(y))
|
855
|
+
return "ops", [op]
|
856
|
+
|
857
|
+
@self.console_command(
|
858
|
+
"consoleop",
|
859
|
+
help=_("<consoleop> - Create new utility operation"),
|
860
|
+
)
|
861
|
+
def consoleop(
|
862
|
+
command,
|
863
|
+
remainder=None,
|
864
|
+
**kwargs,
|
865
|
+
):
|
866
|
+
if remainder is not None:
|
867
|
+
op = self.op_branch.add(type="util console", command=remainder)
|
868
|
+
return "ops", [op]
|
869
|
+
|
870
|
+
@self.console_argument("dpi", type=int, help=_("raster dpi"))
|
871
|
+
@self.console_command("dpi", help=_("dpi <raster-dpi>"), input_type="ops")
|
872
|
+
def op_dpi(command, channel, _, data, dpi=None, **kwrgs):
|
873
|
+
if dpi is None:
|
874
|
+
found = False
|
875
|
+
for op in data:
|
876
|
+
if op.type in ("op raster", "op image"):
|
877
|
+
dpi = op.dpi
|
878
|
+
channel(
|
879
|
+
_("Step for {name} is currently: {dpi}").format(
|
880
|
+
name=str(op), dpi=dpi
|
881
|
+
)
|
882
|
+
)
|
883
|
+
found = True
|
884
|
+
if not found:
|
885
|
+
channel(_("No raster operations selected."))
|
886
|
+
return
|
887
|
+
for op in data:
|
888
|
+
if op.type in ("op raster", "op image"):
|
889
|
+
op.dpi = dpi
|
890
|
+
op.updated()
|
891
|
+
return "ops", data
|
892
|
+
|
893
|
+
@self.console_option(
|
894
|
+
"difference",
|
895
|
+
"d",
|
896
|
+
type=bool,
|
897
|
+
action="store_true",
|
898
|
+
help=_("Change speed by this amount."),
|
899
|
+
)
|
900
|
+
@self.console_option(
|
901
|
+
"progress",
|
902
|
+
"p",
|
903
|
+
type=bool,
|
904
|
+
action="store_true",
|
905
|
+
help=_("Change speed for each item in order"),
|
906
|
+
)
|
907
|
+
@self.console_argument("speed", type=str, help=_("operation speed in mm/s"))
|
908
|
+
@self.console_command(
|
909
|
+
"speed", help=_("speed <speed>"), input_type="ops", output_type="ops"
|
910
|
+
)
|
911
|
+
def op_speed(
|
912
|
+
command,
|
913
|
+
channel,
|
914
|
+
_,
|
915
|
+
speed=None,
|
916
|
+
difference=False,
|
917
|
+
progress=False,
|
918
|
+
data=None,
|
919
|
+
**kwrgs,
|
920
|
+
):
|
921
|
+
if speed is None:
|
922
|
+
for op in data:
|
923
|
+
old = op.speed
|
924
|
+
channel(
|
925
|
+
_("Speed for '{name}' is currently: {speed}").format(
|
926
|
+
name=str(op), speed=old
|
927
|
+
)
|
928
|
+
)
|
929
|
+
return
|
930
|
+
if speed.endswith("%"):
|
931
|
+
speed = speed[:-1]
|
932
|
+
percent = True
|
933
|
+
else:
|
934
|
+
percent = False
|
935
|
+
|
936
|
+
try:
|
937
|
+
new_speed = float(speed)
|
938
|
+
except ValueError:
|
939
|
+
channel(_("Not a valid speed or percent."))
|
940
|
+
return
|
941
|
+
delta = 0
|
942
|
+
for op in data:
|
943
|
+
old = op.speed
|
944
|
+
if percent and difference:
|
945
|
+
s = old + old * (new_speed / 100.0)
|
946
|
+
elif difference:
|
947
|
+
s = old + new_speed
|
948
|
+
elif percent:
|
949
|
+
s = old * (new_speed / 100.0)
|
950
|
+
elif progress:
|
951
|
+
s = old + delta
|
952
|
+
delta += new_speed
|
953
|
+
else:
|
954
|
+
s = new_speed
|
955
|
+
if s < 0:
|
956
|
+
s = 0
|
957
|
+
op.speed = s
|
958
|
+
channel(
|
959
|
+
_("Speed for '{name}' updated {old_speed} -> {speed}").format(
|
960
|
+
name=str(op), old_speed=old, speed=s
|
961
|
+
)
|
962
|
+
)
|
963
|
+
op.updated()
|
964
|
+
return "ops", data
|
965
|
+
|
966
|
+
@self.console_argument(
|
967
|
+
"power", type=int, help=_("power in pulses per inch (ppi, 1000=max)")
|
968
|
+
)
|
969
|
+
@self.console_option(
|
970
|
+
"difference",
|
971
|
+
"d",
|
972
|
+
type=bool,
|
973
|
+
action="store_true",
|
974
|
+
help=_("Change power by this amount."),
|
975
|
+
)
|
976
|
+
@self.console_option(
|
977
|
+
"progress",
|
978
|
+
"p",
|
979
|
+
type=bool,
|
980
|
+
action="store_true",
|
981
|
+
help=_("Change power for each item in order"),
|
982
|
+
)
|
983
|
+
@self.console_command(
|
984
|
+
"power", help=_("power <ppi>"), input_type="ops", output_type="ops"
|
985
|
+
)
|
986
|
+
def op_power(
|
987
|
+
command,
|
988
|
+
channel,
|
989
|
+
_,
|
990
|
+
power=None,
|
991
|
+
difference=False,
|
992
|
+
progress=False,
|
993
|
+
data=None,
|
994
|
+
**kwrgs,
|
995
|
+
):
|
996
|
+
if power is None:
|
997
|
+
for op in data:
|
998
|
+
old = op.power
|
999
|
+
channel(
|
1000
|
+
_("Power for '{name}' is currently: {power}").format(
|
1001
|
+
name=str(op), power=old
|
1002
|
+
)
|
1003
|
+
)
|
1004
|
+
return
|
1005
|
+
delta = 0
|
1006
|
+
for op in data:
|
1007
|
+
old = op.power
|
1008
|
+
if progress:
|
1009
|
+
s = old + delta
|
1010
|
+
delta += power
|
1011
|
+
elif difference:
|
1012
|
+
s = old + power
|
1013
|
+
else:
|
1014
|
+
s = power
|
1015
|
+
if s > 1000:
|
1016
|
+
s = 1000
|
1017
|
+
if s < 0:
|
1018
|
+
s = 0
|
1019
|
+
op.power = s
|
1020
|
+
channel(
|
1021
|
+
_("Power for '{name}' updated {old_power} -> {power}").format(
|
1022
|
+
name=str(op), old_power=old, power=s
|
1023
|
+
)
|
1024
|
+
)
|
1025
|
+
op.updated()
|
1026
|
+
return "ops", data
|
1027
|
+
|
1028
|
+
@self.console_argument(
|
1029
|
+
"frequency", type=float, help=_("frequency set for operation")
|
1030
|
+
)
|
1031
|
+
@self.console_option(
|
1032
|
+
"difference",
|
1033
|
+
"d",
|
1034
|
+
type=bool,
|
1035
|
+
action="store_true",
|
1036
|
+
help=_("Change speed by this amount."),
|
1037
|
+
)
|
1038
|
+
@self.console_option(
|
1039
|
+
"progress",
|
1040
|
+
"p",
|
1041
|
+
type=bool,
|
1042
|
+
action="store_true",
|
1043
|
+
help=_("Change speed for each item in order"),
|
1044
|
+
)
|
1045
|
+
@self.console_command(
|
1046
|
+
"frequency", help=_("frequency <kHz>"), input_type="ops", output_type="ops"
|
1047
|
+
)
|
1048
|
+
def op_frequency(
|
1049
|
+
command,
|
1050
|
+
channel,
|
1051
|
+
_,
|
1052
|
+
frequency=None,
|
1053
|
+
difference=False,
|
1054
|
+
progress=False,
|
1055
|
+
data=None,
|
1056
|
+
**kwrgs,
|
1057
|
+
):
|
1058
|
+
if frequency is None:
|
1059
|
+
for op in data:
|
1060
|
+
old = op.frequency
|
1061
|
+
channel(
|
1062
|
+
_("Frequency for '{name}' is currently: {frequency}").format(
|
1063
|
+
name=str(op), frequency=old
|
1064
|
+
)
|
1065
|
+
)
|
1066
|
+
return
|
1067
|
+
delta = 0
|
1068
|
+
for op in data:
|
1069
|
+
old = op.frequency
|
1070
|
+
if progress:
|
1071
|
+
s = old + delta
|
1072
|
+
delta += frequency
|
1073
|
+
elif difference:
|
1074
|
+
s = old + frequency
|
1075
|
+
else:
|
1076
|
+
s = frequency
|
1077
|
+
if s < 0:
|
1078
|
+
s = 0
|
1079
|
+
op.frequency = s
|
1080
|
+
channel(
|
1081
|
+
_(
|
1082
|
+
"Frequency for '{name}' updated {old_frequency} -> {frequency}"
|
1083
|
+
).format(name=str(op), old_frequency=old, frequency=s)
|
1084
|
+
)
|
1085
|
+
op.updated()
|
1086
|
+
return "ops", data
|
1087
|
+
|
1088
|
+
@self.console_argument("passes", type=int, help=_("Set operation passes"))
|
1089
|
+
@self.console_command(
|
1090
|
+
"passes", help=_("passes <passes>"), input_type="ops", output_type="ops"
|
1091
|
+
)
|
1092
|
+
def op_passes(command, channel, _, passes=None, data=None, **kwrgs):
|
1093
|
+
if passes is None:
|
1094
|
+
for op in data:
|
1095
|
+
old_passes = op.passes
|
1096
|
+
channel(
|
1097
|
+
_("Passes for '{name}' is currently: {passes}").format(
|
1098
|
+
name=str(op), passes=old_passes
|
1099
|
+
)
|
1100
|
+
)
|
1101
|
+
return
|
1102
|
+
for op in data:
|
1103
|
+
old_passes = op.passes
|
1104
|
+
op.passes = passes
|
1105
|
+
if passes >= 1:
|
1106
|
+
op.passes_custom = True
|
1107
|
+
channel(
|
1108
|
+
_("Passes for '{name}' updated {old_passes} -> {passes}").format(
|
1109
|
+
name=str(op), old_passes=old_passes, passes=passes
|
1110
|
+
)
|
1111
|
+
)
|
1112
|
+
op.updated()
|
1113
|
+
return "ops", data
|
1114
|
+
|
1115
|
+
@self.console_argument(
|
1116
|
+
"distance", type=Length, help=_("Set hatch-distance of operations")
|
1117
|
+
)
|
1118
|
+
@self.console_option(
|
1119
|
+
"difference",
|
1120
|
+
"d",
|
1121
|
+
type=bool,
|
1122
|
+
action="store_true",
|
1123
|
+
help=_("Change hatch-distance by this amount."),
|
1124
|
+
)
|
1125
|
+
@self.console_option(
|
1126
|
+
"progress",
|
1127
|
+
"p",
|
1128
|
+
type=bool,
|
1129
|
+
action="store_true",
|
1130
|
+
help=_("Change hatch-distance for each item in order"),
|
1131
|
+
)
|
1132
|
+
@self.console_command(
|
1133
|
+
"hatch-distance",
|
1134
|
+
help=_("hatch-distance <distance>"),
|
1135
|
+
input_type="ops",
|
1136
|
+
output_type="ops",
|
1137
|
+
)
|
1138
|
+
def op_hatch_distance(
|
1139
|
+
command,
|
1140
|
+
channel,
|
1141
|
+
_,
|
1142
|
+
distance=None,
|
1143
|
+
difference=False,
|
1144
|
+
progress=False,
|
1145
|
+
data=None,
|
1146
|
+
**kwrgs,
|
1147
|
+
):
|
1148
|
+
if distance is None:
|
1149
|
+
for op in data:
|
1150
|
+
old = op.hatch_distance
|
1151
|
+
channel(
|
1152
|
+
_("Hatch Distance for '{name}' is currently: {distance}").format(
|
1153
|
+
name=str(op), distance=old
|
1154
|
+
)
|
1155
|
+
)
|
1156
|
+
return
|
1157
|
+
delta = 0
|
1158
|
+
for op in data:
|
1159
|
+
old = Length(op.hatch_distance)
|
1160
|
+
if progress:
|
1161
|
+
s = float(old) + delta
|
1162
|
+
delta += float(distance)
|
1163
|
+
elif difference:
|
1164
|
+
s = float(old) + float(distance)
|
1165
|
+
else:
|
1166
|
+
s = float(distance)
|
1167
|
+
if s < 0:
|
1168
|
+
s = 0
|
1169
|
+
op.hatch_distance = Length(amount=s).length_mm
|
1170
|
+
channel(
|
1171
|
+
_(
|
1172
|
+
"Hatch Distance for '{name}' updated {old_distance} -> {distance}"
|
1173
|
+
).format(name=str(op), old_distance=old, distance=op.hatch_distance)
|
1174
|
+
)
|
1175
|
+
op.updated()
|
1176
|
+
return "ops", data
|
1177
|
+
|
1178
|
+
@self.console_argument("angle", type=Angle, help=_("Set hatch-angle of operations"))
|
1179
|
+
@self.console_option(
|
1180
|
+
"difference",
|
1181
|
+
"d",
|
1182
|
+
type=bool,
|
1183
|
+
action="store_true",
|
1184
|
+
help=_("Change hatch-angle by this amount."),
|
1185
|
+
)
|
1186
|
+
@self.console_option(
|
1187
|
+
"progress",
|
1188
|
+
"p",
|
1189
|
+
type=bool,
|
1190
|
+
action="store_true",
|
1191
|
+
help=_("Change hatch-angle for each item in order"),
|
1192
|
+
)
|
1193
|
+
@self.console_command(
|
1194
|
+
"hatch-angle",
|
1195
|
+
help=_("hatch-angle <angle>"),
|
1196
|
+
input_type="ops",
|
1197
|
+
output_type="ops",
|
1198
|
+
)
|
1199
|
+
def op_hatch_angle(
|
1200
|
+
command,
|
1201
|
+
channel,
|
1202
|
+
_,
|
1203
|
+
angle=None,
|
1204
|
+
difference=False,
|
1205
|
+
progress=False,
|
1206
|
+
data=None,
|
1207
|
+
**kwrgs,
|
1208
|
+
):
|
1209
|
+
if angle is None:
|
1210
|
+
for op in data:
|
1211
|
+
old = Angle(op.hatch_angle, digits=4).angle_turns
|
1212
|
+
old_hatch_angle_deg = Angle(op.hatch_angle, digits=4).angle_degrees
|
1213
|
+
channel(
|
1214
|
+
_(
|
1215
|
+
"Hatch Angle for '{name}' is currently: {angle} ({angle_degree})"
|
1216
|
+
).format(name=str(op), angle=old, angle_degree=old_hatch_angle_deg)
|
1217
|
+
)
|
1218
|
+
return
|
1219
|
+
delta = 0
|
1220
|
+
for op in data:
|
1221
|
+
try:
|
1222
|
+
old = Angle(op.hatch_angle)
|
1223
|
+
except AttributeError:
|
1224
|
+
# Console-Op or other non-angled op.
|
1225
|
+
continue
|
1226
|
+
if progress:
|
1227
|
+
s = old + delta
|
1228
|
+
delta += angle
|
1229
|
+
elif difference:
|
1230
|
+
s = old + angle
|
1231
|
+
else:
|
1232
|
+
s = angle
|
1233
|
+
s = Angle.from_radians(float(s))
|
1234
|
+
op.hatch_angle = s.angle_turns
|
1235
|
+
new_hatch_angle_turn = s.angle_turns
|
1236
|
+
new_hatch_angle_deg = s.angle_degrees
|
1237
|
+
|
1238
|
+
channel(
|
1239
|
+
_(
|
1240
|
+
"Hatch Angle for '{name}' updated {old_angle} -> {angle} ({angle_degree})"
|
1241
|
+
).format(
|
1242
|
+
name=str(op),
|
1243
|
+
old_angle=old.angle_turns,
|
1244
|
+
angle=new_hatch_angle_turn,
|
1245
|
+
angle_degree=new_hatch_angle_deg,
|
1246
|
+
)
|
1247
|
+
)
|
1248
|
+
op.updated()
|
1249
|
+
return "ops", data
|
1250
|
+
|
1251
|
+
@self.console_command(
|
1252
|
+
"disable",
|
1253
|
+
help=_("Disable the given operations"),
|
1254
|
+
input_type="ops",
|
1255
|
+
output_type="ops",
|
1256
|
+
)
|
1257
|
+
def op_disable(command, channel, _, data=None, **kwrgs):
|
1258
|
+
for op in data:
|
1259
|
+
no_op = True
|
1260
|
+
if hasattr(op, "output"):
|
1261
|
+
try:
|
1262
|
+
op.output = False
|
1263
|
+
channel(_("Operation '{name}' disabled.").format(name=str(op)))
|
1264
|
+
op.updated()
|
1265
|
+
no_op = False
|
1266
|
+
except AttributeError:
|
1267
|
+
pass
|
1268
|
+
if no_op:
|
1269
|
+
channel(_("Operation '{name}' can't be disabled.").format(name=str(op)))
|
1270
|
+
return "ops", data
|
1271
|
+
|
1272
|
+
@self.console_command(
|
1273
|
+
"enable",
|
1274
|
+
help=_("Enable the given operations"),
|
1275
|
+
input_type="ops",
|
1276
|
+
output_type="ops",
|
1277
|
+
)
|
1278
|
+
def op_enable(command, channel, _, data=None, **kwrgs):
|
1279
|
+
for op in data:
|
1280
|
+
no_op = True
|
1281
|
+
if hasattr(op, "output"):
|
1282
|
+
try:
|
1283
|
+
op.output = True
|
1284
|
+
channel(_("Operation '{name}' enabled.").format(name=str(op)))
|
1285
|
+
op.updated()
|
1286
|
+
no_op = False
|
1287
|
+
except AttributeError:
|
1288
|
+
pass
|
1289
|
+
if no_op:
|
1290
|
+
channel(_("Operation '{name}' can't be enabled.").format(name=str(op)))
|
1291
|
+
return "ops", data
|
1292
|
+
|
1293
|
+
# ==========
|
1294
|
+
# ELEMENT/OPERATION SUBCOMMANDS
|
1295
|
+
# ==========
|
1296
|
+
@self.console_command(
|
1297
|
+
"lock",
|
1298
|
+
help=_("Lock element (protect from manipulation)"),
|
1299
|
+
input_type="elements",
|
1300
|
+
output_type="elements",
|
1301
|
+
)
|
1302
|
+
def e_lock(data=None, **kwargs):
|
1303
|
+
if data is None:
|
1304
|
+
data = list(self.elems(emphasized=True))
|
1305
|
+
for e in data:
|
1306
|
+
e.lock = True
|
1307
|
+
self.signal("element_property_update", data)
|
1308
|
+
self.signal("refresh_scene", "Scene")
|
1309
|
+
return "elements", data
|
1310
|
+
|
1311
|
+
@self.console_command(
|
1312
|
+
"unlock",
|
1313
|
+
help=_("Unlock element (allow manipulation)"),
|
1314
|
+
input_type="elements",
|
1315
|
+
output_type="elements",
|
1316
|
+
)
|
1317
|
+
def e_unlock(data=None, **kwargs):
|
1318
|
+
if data is None:
|
1319
|
+
data = list(self.elems(emphasized=True))
|
1320
|
+
for e in data:
|
1321
|
+
if hasattr(e, "lock"):
|
1322
|
+
e.lock = False
|
1323
|
+
self.signal("element_property_update", data)
|
1324
|
+
self.signal("refresh_scene", "Scene")
|
1325
|
+
return "elements", data
|
1326
|
+
|
1327
|
+
@self.console_option(
|
1328
|
+
"dx", "x", help=_("copy offset x (for elems)"), type=Length, default=0
|
1329
|
+
)
|
1330
|
+
@self.console_option(
|
1331
|
+
"dy", "y", help=_("copy offset y (for elems)"), type=Length, default=0
|
1332
|
+
)
|
1333
|
+
@self.console_option(
|
1334
|
+
"copies", "c", help=_("amount of copies to be created"), type=int, default=1
|
1335
|
+
)
|
1336
|
+
@self.console_command(
|
1337
|
+
"copy",
|
1338
|
+
help=_("Duplicate elements"),
|
1339
|
+
input_type=("elements", "ops"),
|
1340
|
+
output_type=("elements", "ops"),
|
1341
|
+
)
|
1342
|
+
def e_copy(data=None, data_type=None, post=None, dx=None, dy=None, copies=None, **kwargs):
|
1343
|
+
if data is None:
|
1344
|
+
# Take tree selection for ops, scene selection for elements
|
1345
|
+
if data_type == "ops":
|
1346
|
+
data = list(self.ops(selected=True))
|
1347
|
+
else:
|
1348
|
+
data = list(self.elems(emphasized=True))
|
1349
|
+
if copies is None:
|
1350
|
+
copies = 1
|
1351
|
+
if copies < 1:
|
1352
|
+
copies = 1
|
1353
|
+
|
1354
|
+
if data_type == "ops":
|
1355
|
+
add_ops = list()
|
1356
|
+
for idx in range(copies):
|
1357
|
+
add_ops.extend(list(map(copy, data)))
|
1358
|
+
# print (f"Add ops contains now: {len(add_ops)} operations")
|
1359
|
+
self.add_ops(add_ops)
|
1360
|
+
return "ops", add_ops
|
1361
|
+
else:
|
1362
|
+
if dx is None:
|
1363
|
+
x_pos = 0
|
1364
|
+
else:
|
1365
|
+
x_pos = float(dx)
|
1366
|
+
if dy is None:
|
1367
|
+
y_pos = 0
|
1368
|
+
else:
|
1369
|
+
y_pos = float(dy)
|
1370
|
+
add_elem = list()
|
1371
|
+
shift = list()
|
1372
|
+
tx = 0
|
1373
|
+
ty = 0
|
1374
|
+
for idx in range(copies):
|
1375
|
+
tx += x_pos
|
1376
|
+
ty += y_pos
|
1377
|
+
this_shift = [(tx, ty)] * len(data)
|
1378
|
+
add_elem.extend(list(map(copy, data)))
|
1379
|
+
shift.extend(this_shift)
|
1380
|
+
# print (f"Add elem contains now: {len(add_elem)} elements")
|
1381
|
+
delta_wordlist = 1
|
1382
|
+
for e, delta in zip(add_elem, shift):
|
1383
|
+
tx, ty = delta
|
1384
|
+
if tx != 0 or ty != 0:
|
1385
|
+
matrix = Matrix.translate(tx, ty)
|
1386
|
+
e.matrix *= matrix
|
1387
|
+
newnode = self.elem_branch.add_node(e)
|
1388
|
+
if self.copy_increases_wordlist_references and hasattr(newnode, "text"):
|
1389
|
+
newnode.text = self.wordlist_delta(newnode.text, delta_wordlist)
|
1390
|
+
elif self.copy_increases_wordlist_references and hasattr(
|
1391
|
+
newnode, "mktext"
|
1392
|
+
):
|
1393
|
+
newnode.mktext = self.wordlist_delta(newnode.mktext, delta_wordlist)
|
1394
|
+
for property_op in self.kernel.lookup_all("path_updater/.*"):
|
1395
|
+
property_op(self.kernel.root, newnode)
|
1396
|
+
# Newly created! Classification needed?
|
1397
|
+
post.append(classify_new(add_elem))
|
1398
|
+
self.signal("refresh_scene", "Scene")
|
1399
|
+
return "elements", add_elem
|
1400
|
+
|
1401
|
+
@self.console_command(
|
1402
|
+
"delete", help=_("Delete elements"), input_type=("elements", "ops")
|
1403
|
+
)
|
1404
|
+
def e_delete(command, channel, _, data=None, data_type=None, **kwargs):
|
1405
|
+
channel(_("Deleting…"))
|
1406
|
+
with self.undoscope("Deleting"):
|
1407
|
+
if data_type == "elements":
|
1408
|
+
self.remove_elements(data)
|
1409
|
+
else:
|
1410
|
+
self.remove_operations(data)
|
1411
|
+
self.signal("update_group_labels")
|
1412
|
+
|
1413
|
+
# ==========
|
1414
|
+
# ELEMENT BASE
|
1415
|
+
# ==========
|
1416
|
+
|
1417
|
+
@self.console_command(
|
1418
|
+
"elements",
|
1419
|
+
help=_("Show information about elements"),
|
1420
|
+
)
|
1421
|
+
def elements(**kwargs):
|
1422
|
+
self(".element* list\n")
|
1423
|
+
|
1424
|
+
@self.console_command(
|
1425
|
+
"element*",
|
1426
|
+
help=_("element*, all elements"),
|
1427
|
+
output_type="elements",
|
1428
|
+
)
|
1429
|
+
def element_star(**kwargs):
|
1430
|
+
return "elements", list(self.elems())
|
1431
|
+
|
1432
|
+
@self.console_command(
|
1433
|
+
"element~",
|
1434
|
+
help=_("element~, all non-selected elements"),
|
1435
|
+
output_type="elements",
|
1436
|
+
)
|
1437
|
+
def element_not(**kwargs):
|
1438
|
+
return "elements", list(self.elems(emphasized=False))
|
1439
|
+
|
1440
|
+
@self.console_command(
|
1441
|
+
"element",
|
1442
|
+
help=_("element, selected elements"),
|
1443
|
+
output_type="elements",
|
1444
|
+
)
|
1445
|
+
def element_base(**kwargs):
|
1446
|
+
return "elements", list(self.elems(emphasized=True))
|
1447
|
+
|
1448
|
+
@self.console_command(
|
1449
|
+
r"element([0-9]+,?)+",
|
1450
|
+
help=_("element0,3,4,5: chain a list of specific elements"),
|
1451
|
+
regex=True,
|
1452
|
+
output_type="elements",
|
1453
|
+
)
|
1454
|
+
def element_chain(command, channel, _, **kwargs):
|
1455
|
+
arg = command[7:]
|
1456
|
+
elements_list = []
|
1457
|
+
for value in arg.split(","):
|
1458
|
+
try:
|
1459
|
+
value = int(value)
|
1460
|
+
except ValueError:
|
1461
|
+
continue
|
1462
|
+
try:
|
1463
|
+
e = self.get_elem(value)
|
1464
|
+
elements_list.append(e)
|
1465
|
+
except IndexError:
|
1466
|
+
channel(_("index {index} out of range").format(index=value))
|
1467
|
+
return "elements", elements_list
|
1468
|
+
|
1469
|
+
# ==========
|
1470
|
+
# REGMARK COMMANDS
|
1471
|
+
# ==========
|
1472
|
+
def move_nodes_to(target, nodes):
|
1473
|
+
for elem in nodes:
|
1474
|
+
target.drop(elem)
|
1475
|
+
|
1476
|
+
@self.console_argument("cmd", type=str, help=_("free, clear, add"))
|
1477
|
+
@self.console_command(
|
1478
|
+
"regmark",
|
1479
|
+
help=_("regmark cmd"),
|
1480
|
+
input_type=(None, "elements"),
|
1481
|
+
output_type="elements",
|
1482
|
+
all_arguments_required=True,
|
1483
|
+
)
|
1484
|
+
def regmark(command, channel, _, data, cmd=None, **kwargs):
|
1485
|
+
# Move regmarks into the regular element tree and vice versa
|
1486
|
+
# _("Regmarks -> Elements") + _("Elements -> Regmarks")
|
1487
|
+
if cmd == "free":
|
1488
|
+
target = self.elem_branch
|
1489
|
+
scope = "Regmarks -> Elements"
|
1490
|
+
else:
|
1491
|
+
target = self.reg_branch
|
1492
|
+
scope = "Elements -> Regmarks"
|
1493
|
+
|
1494
|
+
with self.undoscope(scope):
|
1495
|
+
if data is None:
|
1496
|
+
data = list()
|
1497
|
+
if cmd == "free":
|
1498
|
+
for item in list(self.regmarks()):
|
1499
|
+
data.append(item)
|
1500
|
+
else:
|
1501
|
+
for item in list(self.elems(emphasized=True)):
|
1502
|
+
data.append(item)
|
1503
|
+
if cmd in ("free", "add"):
|
1504
|
+
if len(data) == 0:
|
1505
|
+
channel(_("No elements to transfer"))
|
1506
|
+
else:
|
1507
|
+
move_nodes_to(target, data)
|
1508
|
+
if cmd == "free" and self.classify_new:
|
1509
|
+
self.classify(data)
|
1510
|
+
elif cmd == "clear":
|
1511
|
+
self.clear_regmarks()
|
1512
|
+
data = None
|
1513
|
+
else:
|
1514
|
+
# Unknown command
|
1515
|
+
channel(_("Invalid command, use one of add, free, clear"))
|
1516
|
+
data = None
|
1517
|
+
return "elements", data
|
1518
|
+
|
1519
|
+
# ==========
|
1520
|
+
# ELEMENT SUBCOMMANDS
|
1521
|
+
# ==========
|
1522
|
+
|
1523
|
+
# @self.console_argument("step_size", type=int, help=_("element step size"))
|
1524
|
+
# @self.console_command(
|
1525
|
+
# "step",
|
1526
|
+
# help=_("step <element step-size>"),
|
1527
|
+
# input_type="elements",
|
1528
|
+
# output_type="elements",
|
1529
|
+
# )
|
1530
|
+
# def step_command(command, channel, _, data, step_size=None, **kwrgs):
|
1531
|
+
# if step_size is None:
|
1532
|
+
# found = False
|
1533
|
+
# for element in data:
|
1534
|
+
# if isinstance(element, SVGImage):
|
1535
|
+
# try:
|
1536
|
+
# step = element.values["raster_step"]
|
1537
|
+
# except KeyError:
|
1538
|
+
# step = 1
|
1539
|
+
# channel(
|
1540
|
+
# _("Image step for %s is currently: %s")
|
1541
|
+
# % (str(element), step)
|
1542
|
+
# )
|
1543
|
+
# found = True
|
1544
|
+
# if not found:
|
1545
|
+
# channel(_("No image element selected."))
|
1546
|
+
# return
|
1547
|
+
# for element in data:
|
1548
|
+
# element.values["raster_step"] = str(step_size)
|
1549
|
+
# m = element.transform
|
1550
|
+
# tx = m.e
|
1551
|
+
# ty = m.f
|
1552
|
+
# element.transform = Matrix.scale(float(step_size), float(step_size))
|
1553
|
+
# element.transform.post_translate(tx, ty)
|
1554
|
+
# if hasattr(element, "node"):
|
1555
|
+
# element.node.modified()
|
1556
|
+
# self.signal("element_property_reload", element)
|
1557
|
+
# return ("elements",)
|
1558
|
+
|
1559
|
+
@self.console_command(
|
1560
|
+
"select",
|
1561
|
+
help=_("Set these values as the selection."),
|
1562
|
+
input_type="elements",
|
1563
|
+
output_type="elements",
|
1564
|
+
)
|
1565
|
+
def element_select_base(data=None, **kwargs):
|
1566
|
+
self.set_emphasis(data)
|
1567
|
+
return "elements", data
|
1568
|
+
|
1569
|
+
@self.console_command(
|
1570
|
+
"select+",
|
1571
|
+
help=_("Add the input to the selection"),
|
1572
|
+
input_type="elements",
|
1573
|
+
output_type="elements",
|
1574
|
+
)
|
1575
|
+
def element_select_plus(data=None, **kwargs):
|
1576
|
+
elems = list(self.elems(emphasized=True))
|
1577
|
+
elems.extend(data)
|
1578
|
+
self.set_emphasis(elems)
|
1579
|
+
return "elements", elems
|
1580
|
+
|
1581
|
+
@self.console_command(
|
1582
|
+
"select-",
|
1583
|
+
help=_("Remove the input data from the selection"),
|
1584
|
+
input_type="elements",
|
1585
|
+
output_type="elements",
|
1586
|
+
)
|
1587
|
+
def element_select_minus(data=None, **kwargs):
|
1588
|
+
elems = list(self.elems(emphasized=True))
|
1589
|
+
for e in data:
|
1590
|
+
try:
|
1591
|
+
elems.remove(e)
|
1592
|
+
except ValueError:
|
1593
|
+
pass
|
1594
|
+
self.set_emphasis(elems)
|
1595
|
+
return "elements", elems
|
1596
|
+
|
1597
|
+
@self.console_command(
|
1598
|
+
"select^",
|
1599
|
+
help=_("Toggle the input data in the selection"),
|
1600
|
+
input_type="elements",
|
1601
|
+
output_type="elements",
|
1602
|
+
)
|
1603
|
+
def element_select_xor(data=None, **kwargs):
|
1604
|
+
elems = list(self.elems(emphasized=True))
|
1605
|
+
for e in data:
|
1606
|
+
try:
|
1607
|
+
elems.remove(e)
|
1608
|
+
except ValueError:
|
1609
|
+
elems.append(e)
|
1610
|
+
self.set_emphasis(elems)
|
1611
|
+
return "elements", elems
|
1612
|
+
|
1613
|
+
@self.console_command(
|
1614
|
+
"list",
|
1615
|
+
help=_("Show information about the chained data"),
|
1616
|
+
input_type="elements",
|
1617
|
+
output_type="elements",
|
1618
|
+
)
|
1619
|
+
def element_list(command, channel, _, data=None, **kwargs):
|
1620
|
+
channel("----------")
|
1621
|
+
channel(_("Graphical Elements:"))
|
1622
|
+
index_list = list(self.elems())
|
1623
|
+
for e in data:
|
1624
|
+
i = index_list.index(e)
|
1625
|
+
name = str(e)
|
1626
|
+
if len(name) > 50:
|
1627
|
+
name = name[:50] + "…"
|
1628
|
+
if e.emphasized:
|
1629
|
+
channel(f"{i}: * {name}")
|
1630
|
+
else:
|
1631
|
+
channel(f"{i}: {name}")
|
1632
|
+
channel("----------")
|
1633
|
+
return "elements", data
|
1634
|
+
|
1635
|
+
@kernel.console_option("stitchtolerance", "s", type=Length, help=_("By default elements will be stitched together if they have common end/start points, this option allows to set a tolerance"))
|
1636
|
+
@kernel.console_option("nostitch", "n", type=bool, action="store_true", help=_("By default elements will be stitched together if they have a common end/start point, this option prevents that and real subpaths will be created"))
|
1637
|
+
@self.console_command(
|
1638
|
+
"merge",
|
1639
|
+
help=_("merge elements"),
|
1640
|
+
input_type="elements",
|
1641
|
+
output_type="elements",
|
1642
|
+
)
|
1643
|
+
def element_merge(command, channel, _, data=None, post=None, nostitch=None, stitchtolerance=None, **kwargs):
|
1644
|
+
"""
|
1645
|
+
Merge combines the geometries of the inputs. This matters in some cases where fills are used. Such that two
|
1646
|
+
nested circles forms a toroid rather two independent circles.
|
1647
|
+
"""
|
1648
|
+
def set_nonset_attributes(node, e):
|
1649
|
+
try:
|
1650
|
+
if node.stroke is None:
|
1651
|
+
node.stroke = e.stroke
|
1652
|
+
except AttributeError:
|
1653
|
+
pass
|
1654
|
+
try:
|
1655
|
+
if node.fill is None:
|
1656
|
+
node.fill = e.fill
|
1657
|
+
except AttributeError:
|
1658
|
+
pass
|
1659
|
+
try:
|
1660
|
+
if node.stroke_width is None:
|
1661
|
+
node.stroke_width = e.stroke_width
|
1662
|
+
except AttributeError:
|
1663
|
+
pass
|
1664
|
+
|
1665
|
+
def merge_paths(other, path, nocase, tolerance):
|
1666
|
+
def segments_can_stitch(aseg, bseg, starta, startb):
|
1667
|
+
def segtype(info):
|
1668
|
+
return int(info[2].real) & 0xFF
|
1669
|
+
|
1670
|
+
if segtype(aseg) not in NON_GEOMETRY_TYPES and segtype(bseg) not in NON_GEOMETRY_TYPES:
|
1671
|
+
s1, _dummy2, _dummy3, _dummy4, e1 = aseg
|
1672
|
+
s2, _dummy2, _dummy3, _dummy4, e2 = bseg
|
1673
|
+
c1 = s1 if starta else e1
|
1674
|
+
c2 = s2 if startb else e2
|
1675
|
+
if abs(c1 - c2) <= tolerance + 1E-6:
|
1676
|
+
return True
|
1677
|
+
return False
|
1678
|
+
|
1679
|
+
|
1680
|
+
seg1_start = other.segments[0]
|
1681
|
+
seg1_end = other.segments[other.index - 1]
|
1682
|
+
seg2_start = path.segments[0]
|
1683
|
+
seg2_end = path.segments[path.index - 1]
|
1684
|
+
# We have six cases: forbidden, s1.end=s2.start, s1.start=s2.end, s1.start=s2.start, s2.end=s1.end, anything else
|
1685
|
+
|
1686
|
+
if nocase:
|
1687
|
+
# ignore, path after other, proper orientation, disjoint
|
1688
|
+
separate = True
|
1689
|
+
orientation = True
|
1690
|
+
path_before = False
|
1691
|
+
to_set_seg, to_set_idx, from_seg, from_idx = None, None, None, None
|
1692
|
+
elif segments_can_stitch(seg1_end, seg2_start, False, True):
|
1693
|
+
# s1.end = s2.start, path after other, proper orientation
|
1694
|
+
orientation = True
|
1695
|
+
path_before = False
|
1696
|
+
separate = False
|
1697
|
+
to_set_seg, to_set_idx, from_seg, from_idx = 0, 0, other.index - 1, 4
|
1698
|
+
elif segments_can_stitch(seg1_start, seg2_end, True, False):
|
1699
|
+
# s1.start = s2.end, path before other, proper orientation, joint
|
1700
|
+
orientation = True
|
1701
|
+
path_before = True
|
1702
|
+
separate = False
|
1703
|
+
to_set_seg, to_set_idx, from_seg, from_idx = path.index - 1, 4, 0, 0
|
1704
|
+
elif segments_can_stitch(seg1_start, seg2_start, True, True):
|
1705
|
+
# s1.start = s2.start, path before other, wrong orientation, joint
|
1706
|
+
orientation = False
|
1707
|
+
path_before = True
|
1708
|
+
separate = False
|
1709
|
+
to_set_seg, to_set_idx, from_seg, from_idx = 0, 0, 0, 0
|
1710
|
+
elif segments_can_stitch(seg1_end, seg2_end, False, False):
|
1711
|
+
# s1.end = s2. end, path after other, wrong orientation, joint
|
1712
|
+
orientation = False
|
1713
|
+
path_before = False
|
1714
|
+
separate = False
|
1715
|
+
to_set_seg, to_set_idx, from_seg, from_idx = path.index - 1, 4, other.index - 1, 4
|
1716
|
+
else:
|
1717
|
+
# ignore, path after other, proper orientation, disjoint
|
1718
|
+
separate = True
|
1719
|
+
orientation = True
|
1720
|
+
path_before = False
|
1721
|
+
to_set_seg, to_set_idx, from_seg, from_idx = None, None, None, None
|
1722
|
+
|
1723
|
+
return separate, orientation, path_before, to_set_seg, to_set_idx, from_seg, from_idx
|
1724
|
+
|
1725
|
+
|
1726
|
+
if nostitch is None:
|
1727
|
+
nostitch = False
|
1728
|
+
tolerance = 0
|
1729
|
+
if stitchtolerance is not None:
|
1730
|
+
try:
|
1731
|
+
tolerance = float(Length(stitchtolerance))
|
1732
|
+
except ValueError:
|
1733
|
+
channel(_("Invalid tolerance distance provided"))
|
1734
|
+
return
|
1735
|
+
if data is None:
|
1736
|
+
data = list(self.elems(emphasized=True))
|
1737
|
+
if len(data) == 0:
|
1738
|
+
channel(_("No item selected."))
|
1739
|
+
return
|
1740
|
+
node_label = None
|
1741
|
+
for e in data:
|
1742
|
+
if e.label is not None:
|
1743
|
+
el = e.label
|
1744
|
+
idx = el.rfind("-")
|
1745
|
+
if idx > 0:
|
1746
|
+
el = el[:idx]
|
1747
|
+
node_label = el
|
1748
|
+
break
|
1749
|
+
node = self.elem_branch.add(type="elem path", label=node_label)
|
1750
|
+
first = True
|
1751
|
+
for e in data:
|
1752
|
+
try:
|
1753
|
+
if hasattr(e, "final_geometry"):
|
1754
|
+
path = e.final_geometry()
|
1755
|
+
else:
|
1756
|
+
path = e.as_geometry()
|
1757
|
+
except AttributeError:
|
1758
|
+
continue
|
1759
|
+
|
1760
|
+
set_nonset_attributes(node, e)
|
1761
|
+
|
1762
|
+
if first:
|
1763
|
+
node.geometry = path
|
1764
|
+
first = False
|
1765
|
+
else:
|
1766
|
+
other = node.geometry
|
1767
|
+
|
1768
|
+
separate, orientation, path_before, to_set_seg, to_set_idx, from_seg, from_idx = merge_paths(other, path, nostitch, tolerance)
|
1769
|
+
if to_set_seg is not None:
|
1770
|
+
path.segments[to_set_seg, to_set_idx] = other.segments[from_seg, from_idx]
|
1771
|
+
actionstr = 'Insert' if path_before else 'Append'
|
1772
|
+
typestr = 'regular' if orientation else 'reversed'
|
1773
|
+
channel(f"{actionstr} a {typestr} path - separate: {separate}")
|
1774
|
+
if not orientation:
|
1775
|
+
path.reverse()
|
1776
|
+
if path_before:
|
1777
|
+
node.geometry.insert(0, path.segments[:path.index])
|
1778
|
+
else:
|
1779
|
+
node.geometry.append(path, end=separate)
|
1780
|
+
|
1781
|
+
self.remove_elements(data)
|
1782
|
+
self.set_node_emphasis(node, True)
|
1783
|
+
# Newly created! Classification needed?
|
1784
|
+
data = [node]
|
1785
|
+
post.append(classify_new(data))
|
1786
|
+
return "elements", data
|
1787
|
+
|
1788
|
+
@self.console_command(
|
1789
|
+
"subpath",
|
1790
|
+
help=_("break elements"),
|
1791
|
+
input_type="elements",
|
1792
|
+
output_type="elements",
|
1793
|
+
)
|
1794
|
+
def element_subpath(data=None, post=None, **kwargs):
|
1795
|
+
"""
|
1796
|
+
Subpath is the opposite of merge. It divides non-attached paths into different node objects.
|
1797
|
+
"""
|
1798
|
+
if not isinstance(data, list):
|
1799
|
+
data = list(data)
|
1800
|
+
if not data:
|
1801
|
+
return
|
1802
|
+
elements_nodes = []
|
1803
|
+
elems = []
|
1804
|
+
groups= []
|
1805
|
+
# _("Break elements")
|
1806
|
+
with self.undoscope("Break elements"):
|
1807
|
+
for node in data:
|
1808
|
+
node_label = node.label
|
1809
|
+
node_attributes = {}
|
1810
|
+
for attrib in ("stroke", "fill", "stroke_width", "stroke_scaled"):
|
1811
|
+
if hasattr(node, attrib):
|
1812
|
+
oldval = getattr(node, attrib, None)
|
1813
|
+
node_attributes[attrib] = oldval
|
1814
|
+
group_node = node.replace_node(type="group", label=node_label, expanded=True)
|
1815
|
+
groups.append(group_node)
|
1816
|
+
try:
|
1817
|
+
if hasattr(node, "final_geometry"):
|
1818
|
+
geometry = node.final_geometry()
|
1819
|
+
else:
|
1820
|
+
geometry = node.as_geometry()
|
1821
|
+
geometry.ensure_proper_subpaths()
|
1822
|
+
except AttributeError:
|
1823
|
+
continue
|
1824
|
+
idx = 0
|
1825
|
+
for subpath in geometry.as_subpaths():
|
1826
|
+
subpath.ensure_proper_subpaths()
|
1827
|
+
idx += 1
|
1828
|
+
subnode = group_node.add(
|
1829
|
+
geometry=subpath,
|
1830
|
+
type="elem path",
|
1831
|
+
label=f"{node_label}-{idx}",
|
1832
|
+
stroke=node_attributes.get("stroke", None),
|
1833
|
+
fill=node_attributes.get("fill", None),
|
1834
|
+
)
|
1835
|
+
for key, value in node_attributes.items():
|
1836
|
+
setattr(subnode, key, value)
|
1837
|
+
|
1838
|
+
elems.append(subnode)
|
1839
|
+
elements_nodes.append(group_node)
|
1840
|
+
post.append(classify_new(elems))
|
1841
|
+
self.signal("element_property_reload", groups)
|
1842
|
+
return "elements", elements_nodes
|
1843
|
+
|
1844
|
+
# --------------------------- END COMMANDS ------------------------------
|