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
meerk40t/gui/wxmscene.py
CHANGED
@@ -1,1453 +1,1635 @@
|
|
1
|
-
import
|
2
|
-
import
|
3
|
-
import
|
4
|
-
|
5
|
-
|
6
|
-
import
|
7
|
-
from wx import aui
|
8
|
-
|
9
|
-
from meerk40t.core.elements.element_types import elem_nodes
|
10
|
-
from meerk40t.core.
|
11
|
-
from meerk40t.
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
from meerk40t.gui.
|
19
|
-
from meerk40t.gui.
|
20
|
-
from meerk40t.gui.
|
21
|
-
from meerk40t.gui.scenewidgets.
|
22
|
-
from meerk40t.gui.scenewidgets.
|
23
|
-
from meerk40t.gui.scenewidgets.
|
24
|
-
from meerk40t.gui.scenewidgets.
|
25
|
-
from meerk40t.gui.scenewidgets.
|
26
|
-
|
27
|
-
from meerk40t.gui.scenewidgets.
|
28
|
-
from meerk40t.gui.scenewidgets.
|
29
|
-
from meerk40t.gui.scenewidgets.
|
30
|
-
|
31
|
-
from meerk40t.gui.scenewidgets.
|
32
|
-
from meerk40t.gui.
|
33
|
-
from meerk40t.gui.toolwidgets.
|
34
|
-
from meerk40t.gui.toolwidgets.
|
35
|
-
from meerk40t.gui.toolwidgets.
|
36
|
-
from meerk40t.gui.toolwidgets.
|
37
|
-
from meerk40t.gui.toolwidgets.
|
38
|
-
from meerk40t.gui.toolwidgets.
|
39
|
-
from meerk40t.gui.toolwidgets.
|
40
|
-
from meerk40t.gui.toolwidgets.
|
41
|
-
from meerk40t.gui.toolwidgets.
|
42
|
-
from meerk40t.gui.toolwidgets.
|
43
|
-
from meerk40t.gui.toolwidgets.
|
44
|
-
from meerk40t.gui.toolwidgets.
|
45
|
-
from meerk40t.gui.toolwidgets.
|
46
|
-
from meerk40t.gui.toolwidgets.toolpolygon import PolygonTool
|
47
|
-
from meerk40t.gui.toolwidgets.toolpolyline import PolylineTool
|
48
|
-
from meerk40t.gui.toolwidgets.toolrect import RectTool
|
49
|
-
from meerk40t.gui.toolwidgets.toolrelocate import RelocateTool
|
50
|
-
from meerk40t.gui.toolwidgets.toolribbon import RibbonTool
|
51
|
-
from meerk40t.gui.toolwidgets.
|
52
|
-
from meerk40t.gui.toolwidgets.
|
53
|
-
from meerk40t.gui.
|
54
|
-
from meerk40t.gui.utilitywidgets.
|
55
|
-
from meerk40t.gui.utilitywidgets.
|
56
|
-
from meerk40t.gui.utilitywidgets.
|
57
|
-
from meerk40t.gui.utilitywidgets.
|
58
|
-
from meerk40t.gui.wxutils import get_key_name, is_navigation_key
|
59
|
-
from meerk40t.kernel import CommandSyntaxError, signal_listener
|
60
|
-
from meerk40t.svgelements import
|
61
|
-
|
62
|
-
_ = wx.GetTranslation
|
63
|
-
|
64
|
-
|
65
|
-
def register_panel_scene(window, context):
|
66
|
-
# control = wx.aui.AuiNotebook(window, -1, size=(200, 150))
|
67
|
-
# panel1 = MeerK40tScenePanel(window, wx.ID_ANY, context=context, index=1)
|
68
|
-
# control.AddPage(panel1, "scene1")
|
69
|
-
# panel2 = MeerK40tScenePanel(window, wx.ID_ANY, context=context, index=2)
|
70
|
-
# control.AddPage(panel2, "scene2")
|
71
|
-
|
72
|
-
control = MeerK40tScenePanel(window, wx.ID_ANY, context=context)
|
73
|
-
pane = aui.AuiPaneInfo().CenterPane().MinSize(200, 200).Name("scene")
|
74
|
-
pane.dock_proportion = 600
|
75
|
-
pane.control = control
|
76
|
-
pane.hide_menu = True
|
77
|
-
|
78
|
-
# def on_note_page_change(event=None):
|
79
|
-
# if control.GetPageText(control.GetSelection()) == "scene1":
|
80
|
-
# context.kernel.activate_service_path('elements', 'elements')
|
81
|
-
# else:
|
82
|
-
# context.kernel.activate_service_path('elements', "elements1")
|
83
|
-
# context("refresh\n")
|
84
|
-
# control.Bind(aui.EVT_AUINOTEBOOK_PAGE_CHANGED, on_note_page_change, control)
|
85
|
-
|
86
|
-
window.on_pane_create(pane)
|
87
|
-
context.register("pane/scene", pane)
|
88
|
-
|
89
|
-
|
90
|
-
class
|
91
|
-
def __init__(self,
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
self.context = context
|
96
|
-
self.
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
self.
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
self.
|
113
|
-
self.
|
114
|
-
|
115
|
-
self.
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
self.
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
)
|
129
|
-
|
130
|
-
|
131
|
-
context.
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
self.
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
self.
|
143
|
-
|
144
|
-
|
145
|
-
self.
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
self.
|
150
|
-
|
151
|
-
#
|
152
|
-
self.
|
153
|
-
self.
|
154
|
-
|
155
|
-
|
156
|
-
self.
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
#
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
self.
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
self.widget_scene.
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
self.
|
202
|
-
self.
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
self.
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
context.
|
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
|
-
context.
|
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
|
-
0,
|
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
|
-
|
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
|
-
channel(str(matrix))
|
599
|
-
return "scene", data
|
600
|
-
|
601
|
-
@self.context.
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
"
|
616
|
-
|
617
|
-
|
618
|
-
help="
|
619
|
-
)
|
620
|
-
@self.context.console_command("
|
621
|
-
def
|
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
|
-
|
652
|
-
|
653
|
-
|
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
|
-
self.scene.signal("
|
794
|
-
self.
|
795
|
-
self.request_refresh()
|
796
|
-
elif target[0] == "
|
797
|
-
self.grid.
|
798
|
-
if self.grid.
|
799
|
-
if ox is None:
|
800
|
-
self.grid.
|
801
|
-
self.grid.
|
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
|
-
|
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
|
-
|
887
|
-
|
888
|
-
|
889
|
-
|
890
|
-
|
891
|
-
|
892
|
-
|
893
|
-
|
894
|
-
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
|
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
|
-
if
|
1003
|
-
|
1004
|
-
|
1005
|
-
|
1006
|
-
|
1007
|
-
|
1008
|
-
|
1009
|
-
|
1010
|
-
|
1011
|
-
|
1012
|
-
if
|
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
|
-
self.
|
1112
|
-
|
1113
|
-
|
1114
|
-
|
1115
|
-
|
1116
|
-
|
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
|
-
|
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
|
-
self.
|
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
|
-
self.
|
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
|
-
self.
|
1322
|
-
|
1323
|
-
|
1324
|
-
|
1325
|
-
|
1326
|
-
|
1327
|
-
|
1328
|
-
|
1329
|
-
|
1330
|
-
|
1331
|
-
|
1332
|
-
|
1333
|
-
|
1334
|
-
|
1335
|
-
|
1336
|
-
|
1337
|
-
|
1338
|
-
|
1339
|
-
|
1340
|
-
|
1341
|
-
self.
|
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
|
-
@signal_listener("
|
1384
|
-
def
|
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
|
-
def
|
1420
|
-
|
1421
|
-
|
1422
|
-
|
1423
|
-
|
1424
|
-
|
1425
|
-
|
1426
|
-
|
1427
|
-
|
1428
|
-
|
1429
|
-
|
1430
|
-
|
1431
|
-
|
1432
|
-
|
1433
|
-
|
1434
|
-
|
1435
|
-
|
1436
|
-
|
1437
|
-
|
1438
|
-
|
1439
|
-
def
|
1440
|
-
|
1441
|
-
self.
|
1442
|
-
|
1443
|
-
|
1444
|
-
|
1445
|
-
|
1446
|
-
|
1447
|
-
|
1448
|
-
|
1449
|
-
|
1450
|
-
|
1451
|
-
|
1452
|
-
|
1453
|
-
|
1
|
+
import platform
|
2
|
+
import random
|
3
|
+
import time
|
4
|
+
|
5
|
+
import wx
|
6
|
+
from PIL import Image
|
7
|
+
from wx import aui
|
8
|
+
|
9
|
+
from meerk40t.core.elements.element_types import elem_nodes
|
10
|
+
from meerk40t.core.node.elem_image import ImageNode
|
11
|
+
from meerk40t.core.units import UNITS_PER_PIXEL, Angle, Length
|
12
|
+
from meerk40t.gui.icons import STD_ICON_SIZE, icon_meerk40t, icons8_r_white, icons8_text
|
13
|
+
from meerk40t.gui.laserrender import DRAW_MODE_BACKGROUND, DRAW_MODE_GUIDES, LaserRender
|
14
|
+
from meerk40t.gui.mwindow import MWindow
|
15
|
+
from meerk40t.gui.propertypanels.imageproperty import ContourPanel
|
16
|
+
from meerk40t.gui.scene.scenepanel import ScenePanel
|
17
|
+
|
18
|
+
# from meerk40t.gui.scenewidgets.affinemover import AffineMover
|
19
|
+
from meerk40t.gui.scenewidgets.attractionwidget import AttractionWidget
|
20
|
+
from meerk40t.gui.scenewidgets.bedwidget import BedWidget
|
21
|
+
from meerk40t.gui.scenewidgets.elementswidget import ElementsWidget
|
22
|
+
from meerk40t.gui.scenewidgets.gridwidget import GridWidget
|
23
|
+
from meerk40t.gui.scenewidgets.guidewidget import GuideWidget
|
24
|
+
from meerk40t.gui.scenewidgets.laserpathwidget import LaserPathWidget
|
25
|
+
from meerk40t.gui.scenewidgets.machineoriginwidget import MachineOriginWidget
|
26
|
+
|
27
|
+
# from meerk40t.gui.scenewidgets.nodeselector import NodeSelector
|
28
|
+
from meerk40t.gui.scenewidgets.rectselectwidget import RectSelectWidget
|
29
|
+
from meerk40t.gui.scenewidgets.reticlewidget import ReticleWidget
|
30
|
+
|
31
|
+
# from meerk40t.gui.scenewidgets.selectionwidget import SelectionWidget
|
32
|
+
from meerk40t.gui.toolwidgets.toolcircle import CircleTool
|
33
|
+
from meerk40t.gui.toolwidgets.toolcontainer import ToolContainer
|
34
|
+
from meerk40t.gui.toolwidgets.tooldraw import DrawTool
|
35
|
+
from meerk40t.gui.toolwidgets.toolellipse import EllipseTool
|
36
|
+
from meerk40t.gui.toolwidgets.toolimagecut import ImageCutTool
|
37
|
+
from meerk40t.gui.toolwidgets.toolline import LineTool
|
38
|
+
from meerk40t.gui.toolwidgets.toollinetext import LineTextTool
|
39
|
+
from meerk40t.gui.toolwidgets.toolmeasure import MeasureTool
|
40
|
+
from meerk40t.gui.toolwidgets.toolnodeedit import EditTool
|
41
|
+
from meerk40t.gui.toolwidgets.toolnodemove import NodeMoveTool
|
42
|
+
from meerk40t.gui.toolwidgets.toolparameter import ParameterTool
|
43
|
+
from meerk40t.gui.toolwidgets.toolplacement import PlacementTool
|
44
|
+
from meerk40t.gui.toolwidgets.toolpoint import PointTool
|
45
|
+
from meerk40t.gui.toolwidgets.toolpointmove import PointMoveTool
|
46
|
+
from meerk40t.gui.toolwidgets.toolpolygon import PolygonTool
|
47
|
+
from meerk40t.gui.toolwidgets.toolpolyline import PolylineTool
|
48
|
+
from meerk40t.gui.toolwidgets.toolrect import RectTool
|
49
|
+
from meerk40t.gui.toolwidgets.toolrelocate import RelocateTool
|
50
|
+
from meerk40t.gui.toolwidgets.toolribbon import RibbonTool
|
51
|
+
from meerk40t.gui.toolwidgets.tooltabedit import TabEditTool
|
52
|
+
from meerk40t.gui.toolwidgets.tooltext import TextTool
|
53
|
+
from meerk40t.gui.toolwidgets.toolvector import VectorTool
|
54
|
+
from meerk40t.gui.utilitywidgets.checkboxwidget import CheckboxWidget
|
55
|
+
from meerk40t.gui.utilitywidgets.cyclocycloidwidget import CyclocycloidWidget
|
56
|
+
from meerk40t.gui.utilitywidgets.harmonograph import HarmonographWidget
|
57
|
+
from meerk40t.gui.utilitywidgets.seekbarwidget import SeekbarWidget
|
58
|
+
from meerk40t.gui.wxutils import get_key_name, is_navigation_key
|
59
|
+
from meerk40t.kernel import CommandSyntaxError, signal_listener
|
60
|
+
from meerk40t.svgelements import Color, Matrix
|
61
|
+
|
62
|
+
_ = wx.GetTranslation
|
63
|
+
|
64
|
+
|
65
|
+
def register_panel_scene(window, context):
|
66
|
+
# control = wx.aui.AuiNotebook(window, -1, size=(200, 150))
|
67
|
+
# panel1 = MeerK40tScenePanel(window, wx.ID_ANY, context=context, index=1)
|
68
|
+
# control.AddPage(panel1, "scene1")
|
69
|
+
# panel2 = MeerK40tScenePanel(window, wx.ID_ANY, context=context, index=2)
|
70
|
+
# control.AddPage(panel2, "scene2")
|
71
|
+
|
72
|
+
control = MeerK40tScenePanel(window, wx.ID_ANY, context=context)
|
73
|
+
pane = aui.AuiPaneInfo().CenterPane().MinSize(200, 200).Name("scene")
|
74
|
+
pane.dock_proportion = 600
|
75
|
+
pane.control = control
|
76
|
+
pane.hide_menu = True
|
77
|
+
|
78
|
+
# def on_note_page_change(event=None):
|
79
|
+
# if control.GetPageText(control.GetSelection()) == "scene1":
|
80
|
+
# context.kernel.activate_service_path('elements', 'elements')
|
81
|
+
# else:
|
82
|
+
# context.kernel.activate_service_path('elements', "elements1")
|
83
|
+
# context("refresh\n")
|
84
|
+
# control.Bind(aui.EVT_AUINOTEBOOK_PAGE_CHANGED, on_note_page_change, control)
|
85
|
+
|
86
|
+
window.on_pane_create(pane)
|
87
|
+
context.register("pane/scene", pane)
|
88
|
+
|
89
|
+
|
90
|
+
class ContourDetectionDialog(wx.Dialog):
|
91
|
+
def __init__(self, parent, context, node):
|
92
|
+
super().__init__(
|
93
|
+
parent, wx.ID_ANY, style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER
|
94
|
+
)
|
95
|
+
self.context = context
|
96
|
+
self._init_ui(node)
|
97
|
+
self._start_dialog()
|
98
|
+
|
99
|
+
def _init_ui(self, node):
|
100
|
+
main_sizer = wx.BoxSizer(wx.VERTICAL)
|
101
|
+
panel = ContourPanel(
|
102
|
+
self, wx.ID_ANY, context=self.context, node=node, simplified=True, direct_mode=True,
|
103
|
+
)
|
104
|
+
main_sizer.Add(panel, 1, wx.EXPAND, 0)
|
105
|
+
buttons = self.CreateStdDialogButtonSizer(wx.OK)
|
106
|
+
main_sizer.Add(buttons, 0, wx.EXPAND, 0)
|
107
|
+
panel.pane_active()
|
108
|
+
self.SetSizer(main_sizer)
|
109
|
+
self.Layout()
|
110
|
+
|
111
|
+
def _start_dialog(self):
|
112
|
+
win_wd = self.context.setting(int, "win_bgcontour_width", 700)
|
113
|
+
win_ht = self.context.setting(int, "win_bgcontour_height", 500)
|
114
|
+
self.SetSize(win_wd, win_ht)
|
115
|
+
self.CenterOnParent()
|
116
|
+
|
117
|
+
def end_dialog(self):
|
118
|
+
# Save window size for next time
|
119
|
+
win_wd, win_ht = self.GetSize()
|
120
|
+
self.context.win_bgcontour_width = win_wd
|
121
|
+
self.context.win_bgcontour_height = win_ht
|
122
|
+
self.context.signal("refresh_scene", "Scene")
|
123
|
+
|
124
|
+
|
125
|
+
class MeerK40tScenePanel(wx.Panel):
|
126
|
+
def __init__(self, *args, context=None, index=None, **kwargs):
|
127
|
+
# begin wxGlade: ConsolePanel.__init__
|
128
|
+
kwargs["style"] = kwargs.get("style", 0) | wx.TAB_TRAVERSAL
|
129
|
+
wx.Panel.__init__(self, *args, **kwargs)
|
130
|
+
self.context = context
|
131
|
+
self.context.themes.set_window_colors(self)
|
132
|
+
self.scene = ScenePanel(
|
133
|
+
self.context,
|
134
|
+
self,
|
135
|
+
scene_name="Scene" if index is None else f"Scene{index}",
|
136
|
+
style=wx.EXPAND | wx.WANTS_CHARS,
|
137
|
+
)
|
138
|
+
self.scene.start_scene()
|
139
|
+
self.widget_scene = self.scene.scene
|
140
|
+
|
141
|
+
self.tool_active = False
|
142
|
+
self.modif_active = False
|
143
|
+
self.ignore_snap = False
|
144
|
+
self.suppress_selection = False
|
145
|
+
self._reference = None # Reference Object
|
146
|
+
|
147
|
+
# Stuff for magnet-lines
|
148
|
+
self.magnet_x = []
|
149
|
+
self.magnet_y = []
|
150
|
+
self._magnet_attraction = 2
|
151
|
+
# 0 off, `1..x` increasing strength (quadratic behaviour)
|
152
|
+
self.magnet_attract_x = True # Shall the X-Axis be affected
|
153
|
+
self.magnet_attract_y = True # Shall the Y-Axis be affected
|
154
|
+
self.magnet_attract_c = True # Shall the center be affected
|
155
|
+
|
156
|
+
self.context.setting(bool, "clear_magnets", True)
|
157
|
+
|
158
|
+
# Save / Load the content of magnets
|
159
|
+
from os.path import join, realpath
|
160
|
+
|
161
|
+
from meerk40t.kernel.functions import get_safe_path
|
162
|
+
|
163
|
+
self._magnet_file = join(
|
164
|
+
realpath(get_safe_path(self.context.kernel.name)), "magnets.cfg"
|
165
|
+
)
|
166
|
+
self.load_magnets()
|
167
|
+
# Add a plugin routine to be called at the time of a full new start
|
168
|
+
context.kernel.register(
|
169
|
+
"reset_routines/magnets", self.clear_magnets_conditionally
|
170
|
+
)
|
171
|
+
|
172
|
+
self.active_tool = "none"
|
173
|
+
|
174
|
+
self._last_snap_position = None
|
175
|
+
self._last_snap_ts = 0
|
176
|
+
|
177
|
+
context = self.context
|
178
|
+
# Add in snap-to-grid functionality.
|
179
|
+
self.widget_scene.add_scenewidget(AttractionWidget(self.widget_scene))
|
180
|
+
|
181
|
+
# Tool container - Widget to hold tools.
|
182
|
+
self.tool_container = ToolContainer(self.widget_scene)
|
183
|
+
self.widget_scene.add_scenewidget(self.tool_container)
|
184
|
+
|
185
|
+
# Rectangular selection.
|
186
|
+
self.widget_scene.add_scenewidget(RectSelectWidget(self.widget_scene))
|
187
|
+
|
188
|
+
# Laser-Path blue-line drawer.
|
189
|
+
self.laserpath_widget = LaserPathWidget(self.widget_scene)
|
190
|
+
self.widget_scene.add_scenewidget(self.laserpath_widget)
|
191
|
+
|
192
|
+
# Draw elements in scene.
|
193
|
+
self.widget_scene.add_scenewidget(
|
194
|
+
ElementsWidget(self.widget_scene, LaserRender(context))
|
195
|
+
)
|
196
|
+
|
197
|
+
# Draw Machine Origin widget.
|
198
|
+
self.widget_scene.add_scenewidget(MachineOriginWidget(self.widget_scene))
|
199
|
+
|
200
|
+
# Draw Grid.
|
201
|
+
self.grid = GridWidget(self.widget_scene)
|
202
|
+
self.widget_scene.add_scenewidget(self.grid)
|
203
|
+
|
204
|
+
# Draw Bed
|
205
|
+
self.widget_scene.add_scenewidget(BedWidget(self.widget_scene))
|
206
|
+
|
207
|
+
# Draw Interface Guide.
|
208
|
+
self.widget_scene.add_interfacewidget(GuideWidget(self.widget_scene))
|
209
|
+
|
210
|
+
# Draw Interface Laser-Position
|
211
|
+
self.widget_scene.add_interfacewidget(ReticleWidget(self.widget_scene))
|
212
|
+
|
213
|
+
sizer_2 = wx.BoxSizer(wx.VERTICAL)
|
214
|
+
sizer_2.Add(self.scene, 20, wx.EXPAND, 0)
|
215
|
+
self.SetSizer(sizer_2)
|
216
|
+
sizer_2.Fit(self)
|
217
|
+
self.Layout()
|
218
|
+
|
219
|
+
# Allow Scene update from now on (are suppressed by default during startup phase)
|
220
|
+
self.widget_scene.suppress_changes = False
|
221
|
+
self._keybind_channel = self.context.channel("keybinds")
|
222
|
+
|
223
|
+
if platform.system() == "Windows":
|
224
|
+
|
225
|
+
def charhook(event):
|
226
|
+
keyvalue = get_key_name(event)
|
227
|
+
if is_navigation_key(keyvalue):
|
228
|
+
if self._keybind_channel:
|
229
|
+
self._keybind_channel(
|
230
|
+
f"Scene, char_hook used for key_down: {keyvalue}"
|
231
|
+
)
|
232
|
+
self.on_key_down(event)
|
233
|
+
event.Skip()
|
234
|
+
else:
|
235
|
+
event.DoAllowNextEvent()
|
236
|
+
|
237
|
+
self.scene.Bind(wx.EVT_CHAR_HOOK, charhook)
|
238
|
+
self.scene.Bind(wx.EVT_KEY_UP, self.on_key_up)
|
239
|
+
self.scene.Bind(wx.EVT_KEY_DOWN, self.on_key_down)
|
240
|
+
|
241
|
+
self.Bind(wx.EVT_SIZE, self.on_size)
|
242
|
+
|
243
|
+
self._tool_widget = None
|
244
|
+
|
245
|
+
context.register("tool/draw", DrawTool)
|
246
|
+
context.register("tool/rect", RectTool)
|
247
|
+
context.register("tool/line", LineTool)
|
248
|
+
context.register("tool/polyline", PolylineTool)
|
249
|
+
context.register("tool/polygon", PolygonTool)
|
250
|
+
context.register("tool/point", PointTool)
|
251
|
+
context.register("tool/circle", CircleTool)
|
252
|
+
context.register("tool/ellipse", EllipseTool)
|
253
|
+
context.register("tool/relocate", RelocateTool)
|
254
|
+
context.register("tool/text", TextTool)
|
255
|
+
context.register("tool/vector", VectorTool)
|
256
|
+
context.register("tool/measure", MeasureTool)
|
257
|
+
context.register("tool/ribbon", RibbonTool)
|
258
|
+
context.register("tool/linetext", LineTextTool)
|
259
|
+
context.register("tool/edit", EditTool)
|
260
|
+
context.register("tool/placement", PlacementTool)
|
261
|
+
context.register("tool/nodemove", NodeMoveTool)
|
262
|
+
context.register("tool/pointmove", PointMoveTool)
|
263
|
+
context.register("tool/parameter", ParameterTool)
|
264
|
+
context.register("tool/imagecut", ImageCutTool)
|
265
|
+
context.register("tool/tabedit", TabEditTool)
|
266
|
+
|
267
|
+
bsize_normal = STD_ICON_SIZE
|
268
|
+
|
269
|
+
def proxy_linetext():
|
270
|
+
if context.fonts.have_hershey_fonts():
|
271
|
+
context.kernel.elements("tool linetext\n")
|
272
|
+
else:
|
273
|
+
context.kernel.elements("window open HersheyFontManager\n")
|
274
|
+
|
275
|
+
context.kernel.register(
|
276
|
+
"button/tools/Linetext",
|
277
|
+
{
|
278
|
+
"label": _("Vector Text"),
|
279
|
+
"icon": icons8_text,
|
280
|
+
"tip": _("Add a vector text element"),
|
281
|
+
"action": lambda v: proxy_linetext(),
|
282
|
+
"group": "tool",
|
283
|
+
"size": bsize_normal,
|
284
|
+
"identifier": "linetext",
|
285
|
+
},
|
286
|
+
)
|
287
|
+
|
288
|
+
context.kernel.register(
|
289
|
+
"button/align/refob",
|
290
|
+
{
|
291
|
+
"label": _("Ref. Obj."),
|
292
|
+
"icon": icons8_r_white,
|
293
|
+
"tip": _("Toggle Reference Object Status"),
|
294
|
+
"action": lambda v: self.toggle_ref_obj(),
|
295
|
+
"size": bsize_normal,
|
296
|
+
"identifier": "refobj",
|
297
|
+
"rule_enabled": lambda cond: len(
|
298
|
+
list(context.kernel.elements.elems(emphasized=True))
|
299
|
+
)
|
300
|
+
== 1,
|
301
|
+
},
|
302
|
+
)
|
303
|
+
|
304
|
+
# Provide a reference to current scene in root context
|
305
|
+
setattr(self.context.root, "mainscene", self.widget_scene)
|
306
|
+
|
307
|
+
@context.console_command("dialog_fps", hidden=True)
|
308
|
+
def dialog_fps(**kwgs):
|
309
|
+
dlg = wx.TextEntryDialog(
|
310
|
+
None, _("Enter FPS Limit"), _("FPS Limit Entry"), ""
|
311
|
+
)
|
312
|
+
dlg.SetValue("")
|
313
|
+
|
314
|
+
if dlg.ShowModal() == wx.ID_OK:
|
315
|
+
fps = dlg.GetValue()
|
316
|
+
try:
|
317
|
+
self.widget_scene.set_fps(int(fps))
|
318
|
+
except ValueError:
|
319
|
+
pass
|
320
|
+
dlg.Destroy()
|
321
|
+
|
322
|
+
# @context.console_command("tool_menu", hidden=True)
|
323
|
+
# def tool_menu(channel, _, **kwgs):
|
324
|
+
# orgx = 5
|
325
|
+
# orgy = 5
|
326
|
+
# # Are guides drawn?
|
327
|
+
# if self.context.draw_mode & DRAW_MODE_GUIDES == 0:
|
328
|
+
# orgx += 25
|
329
|
+
# orgy += 25
|
330
|
+
# if self._tool_widget is not None:
|
331
|
+
# visible = self._tool_widget.visible
|
332
|
+
# self._tool_widget.show(not visible)
|
333
|
+
# self.widget_scene.request_refresh()
|
334
|
+
|
335
|
+
# if self._tool_widget is None:
|
336
|
+
# self._tool_widget = ToggleWidget(
|
337
|
+
# self.widget_scene,
|
338
|
+
# orgx,
|
339
|
+
# orgy,
|
340
|
+
# orgx + 25,
|
341
|
+
# orgy + 25,
|
342
|
+
# icons8_menu.GetBitmap(use_theme=False),
|
343
|
+
# "button/tool",
|
344
|
+
# )
|
345
|
+
# self.widget_scene.widget_root.interface_widget.add_widget(
|
346
|
+
# -1,
|
347
|
+
# self._tool_widget,
|
348
|
+
# )
|
349
|
+
# channel(_("Added tool widget to interface"))
|
350
|
+
|
351
|
+
@context.console_command("seek_bar", hidden=True)
|
352
|
+
def seek_bar(channel, _, **kwgs):
|
353
|
+
def changed(values, seeker):
|
354
|
+
print(values)
|
355
|
+
|
356
|
+
widget = SeekbarWidget(
|
357
|
+
self.widget_scene, 25, 25, 200, 25, 0, 1000.0, changed
|
358
|
+
)
|
359
|
+
|
360
|
+
def clicked(values, seeker):
|
361
|
+
self.widget_scene.widget_root.interface_widget.remove_widget(widget)
|
362
|
+
self.widget_scene.request_refresh()
|
363
|
+
|
364
|
+
widget.add_value(500.0)
|
365
|
+
widget.add_value(250.0)
|
366
|
+
widget.clicked = clicked
|
367
|
+
self.widget_scene.widget_root.interface_widget.add_widget(-1, widget)
|
368
|
+
|
369
|
+
channel(_("Added example_seekbar to interface"))
|
370
|
+
self.widget_scene.request_refresh()
|
371
|
+
|
372
|
+
@context.console_command("checkbox", hidden=True)
|
373
|
+
def checkbox(channel, _, **kwgs):
|
374
|
+
def checked(value):
|
375
|
+
print(value)
|
376
|
+
|
377
|
+
widget = CheckboxWidget(
|
378
|
+
self.widget_scene,
|
379
|
+
25,
|
380
|
+
25,
|
381
|
+
text="Example",
|
382
|
+
tool_tip="Example's tool tip",
|
383
|
+
checked=checked,
|
384
|
+
)
|
385
|
+
self.widget_scene.widget_root.interface_widget.add_widget(-1, widget)
|
386
|
+
channel(_("Added example_checkbox to interface"))
|
387
|
+
self.widget_scene.request_refresh()
|
388
|
+
|
389
|
+
@context.console_command("cyclocycloid", hidden=True)
|
390
|
+
def cyclocycloid(channel, _, **kwgs):
|
391
|
+
self.widget_scene.widget_root.scene_widget.add_widget(
|
392
|
+
0, CyclocycloidWidget(self.widget_scene)
|
393
|
+
)
|
394
|
+
channel(_("Added cyclocycloid widget to scene."))
|
395
|
+
|
396
|
+
@context.console_command("harmonograph", hidden=True)
|
397
|
+
def harmonograph(channel, _, **kwgs):
|
398
|
+
self.widget_scene.widget_root.scene_widget.add_widget(
|
399
|
+
0, HarmonographWidget(self.widget_scene)
|
400
|
+
)
|
401
|
+
self.widget_scene.request_refresh()
|
402
|
+
channel(_("Added harmonograph widget to scene."))
|
403
|
+
|
404
|
+
@context.console_command("toast", hidden=True)
|
405
|
+
def toast_scene(remainder, **kwgs):
|
406
|
+
self.widget_scene.toast(remainder)
|
407
|
+
|
408
|
+
@context.console_argument("tool", help=_("tool to use."))
|
409
|
+
@context.console_command("tool", help=_("sets a particular tool for the scene"))
|
410
|
+
def tool_base(command, channel, _, tool=None, remainder=None, **kwgs):
|
411
|
+
if tool is None:
|
412
|
+
channel(_("Tools:"))
|
413
|
+
channel("none")
|
414
|
+
for t in context.match("tool/", suffix=True):
|
415
|
+
channel(t)
|
416
|
+
channel(_("-------"))
|
417
|
+
return
|
418
|
+
toolbar = context.lookup("ribbonbar/tools")
|
419
|
+
# Reset the edit toolbar
|
420
|
+
if toolbar is not None:
|
421
|
+
toolbar.remove_page("toolcontainer")
|
422
|
+
for pages in toolbar.pages:
|
423
|
+
pages.visible = True
|
424
|
+
toolbar.validate_current_page()
|
425
|
+
toolbar.apply_enable_rules()
|
426
|
+
toolbar.modified()
|
427
|
+
try:
|
428
|
+
if tool == "none":
|
429
|
+
success, response = self.tool_container.set_tool(None, remainder)
|
430
|
+
channel(response)
|
431
|
+
if not success:
|
432
|
+
return
|
433
|
+
else:
|
434
|
+
success, response = self.tool_container.set_tool(
|
435
|
+
tool.lower(), remainder
|
436
|
+
)
|
437
|
+
channel(response)
|
438
|
+
if not success:
|
439
|
+
return
|
440
|
+
# Reset the edit toolbar
|
441
|
+
if toolbar is not None:
|
442
|
+
toolbar.remove_page("toolcontainer")
|
443
|
+
tool_values = list(
|
444
|
+
context.find(f"button/secondarytool_{tool}/.*")
|
445
|
+
)
|
446
|
+
# print(f"button/secondarytool_{tool}/.*\n{tool_values}")
|
447
|
+
if tool_values is not None and len(tool_values) > 0:
|
448
|
+
for pages in toolbar.pages:
|
449
|
+
pages.visible = False
|
450
|
+
newpage = toolbar.add_page(
|
451
|
+
"toolcontainer",
|
452
|
+
"toolcontainer",
|
453
|
+
"Select",
|
454
|
+
None,
|
455
|
+
)
|
456
|
+
|
457
|
+
select_panel = toolbar.add_panel(
|
458
|
+
"toolback",
|
459
|
+
newpage,
|
460
|
+
"toolback",
|
461
|
+
"Select",
|
462
|
+
None,
|
463
|
+
)
|
464
|
+
select_values = (
|
465
|
+
(
|
466
|
+
context.lookup("button/select/Scene"),
|
467
|
+
"button/select/Scene",
|
468
|
+
"Select",
|
469
|
+
),
|
470
|
+
)
|
471
|
+
select_panel.set_buttons(select_values)
|
472
|
+
|
473
|
+
tool_panel = toolbar.add_panel(
|
474
|
+
"toolutil",
|
475
|
+
newpage,
|
476
|
+
"toolutil",
|
477
|
+
"Tools",
|
478
|
+
None,
|
479
|
+
)
|
480
|
+
tool_panel.set_buttons(tool_values)
|
481
|
+
newpage.visible = True
|
482
|
+
toolbar.validate_current_page()
|
483
|
+
toolbar.apply_enable_rules()
|
484
|
+
|
485
|
+
toolbar.modified()
|
486
|
+
|
487
|
+
except (KeyError, AttributeError):
|
488
|
+
raise CommandSyntaxError
|
489
|
+
|
490
|
+
@context.console_argument("page", help=_("page to use."))
|
491
|
+
@context.console_command(
|
492
|
+
"page", help=_("Switches to a particular page in the ribbonbar")
|
493
|
+
)
|
494
|
+
def page_base(command, channel, _, page=None, **kwgs):
|
495
|
+
# No need to store it beyond
|
496
|
+
context = self.context.root
|
497
|
+
context.setting(str, "_active_page", "")
|
498
|
+
if page is None:
|
499
|
+
channel(_("Active Page: {page}").format(page=context._active_page))
|
500
|
+
return
|
501
|
+
else:
|
502
|
+
page = page.lower()
|
503
|
+
if page == "none":
|
504
|
+
page = "home"
|
505
|
+
context._active_page = page
|
506
|
+
self.context.signal("page", page)
|
507
|
+
|
508
|
+
@context.console_command("laserpath_clear", hidden=True)
|
509
|
+
def clear_laser_path(**kwgs):
|
510
|
+
self.laserpath_widget.clear_laserpath()
|
511
|
+
self.request_refresh()
|
512
|
+
|
513
|
+
@self.context.console_command("scene", output_type="scene")
|
514
|
+
def scene(command, _, channel, **kwgs):
|
515
|
+
channel(f"scene: {str(self.widget_scene)}")
|
516
|
+
return "scene", self.widget_scene
|
517
|
+
|
518
|
+
@self.context.console_argument(
|
519
|
+
"aspect", type=str, help="aspect of the scene to color"
|
520
|
+
)
|
521
|
+
@self.context.console_argument(
|
522
|
+
"color", type=str, help="color to apply to scene"
|
523
|
+
)
|
524
|
+
@self.context.console_command("color", input_type="scene")
|
525
|
+
def scene_color(command, _, channel, data, aspect=None, color=None, **kwgs):
|
526
|
+
"""
|
527
|
+
Sets the scene colors. This is usually done with `scene color <aspect> <color>` which
|
528
|
+
sets the aspect to the color specified. `scene color unset` unsets all colors and returns
|
529
|
+
them to the default settings. `scene color random` changes all colors to random.
|
530
|
+
"""
|
531
|
+
if aspect is None:
|
532
|
+
for key in dir(self.context):
|
533
|
+
if key.startswith("color_"):
|
534
|
+
channel(key[6:])
|
535
|
+
else:
|
536
|
+
color_key = f"color_{aspect}"
|
537
|
+
if aspect == "unset": # reset all
|
538
|
+
self.widget_scene.colors.set_default_colors()
|
539
|
+
self.context.signal("theme", True)
|
540
|
+
return "scene", data
|
541
|
+
if aspect == "unsetbright": # reset all
|
542
|
+
self.widget_scene.colors.set_default_colors(brighter=True)
|
543
|
+
self.context.signal("theme", True)
|
544
|
+
return "scene", data
|
545
|
+
if aspect == "random": # reset all
|
546
|
+
self.widget_scene.colors.set_random_colors()
|
547
|
+
self.context.signal("theme", True)
|
548
|
+
return "scene", data
|
549
|
+
if color == "unset": # reset one
|
550
|
+
setattr(self.context, color_key, "default")
|
551
|
+
self.context.signal("theme", True)
|
552
|
+
return "scene", data
|
553
|
+
if color == "random": # randomize one
|
554
|
+
random_color = (
|
555
|
+
f"#"
|
556
|
+
f"{random.randint(0, 255):02X}"
|
557
|
+
f"{random.randint(0, 255):02X}"
|
558
|
+
f"{random.randint(0, 255):02X}"
|
559
|
+
)
|
560
|
+
setattr(self.context, color_key, random_color)
|
561
|
+
self.context.signal("theme", True)
|
562
|
+
return "scene", data
|
563
|
+
|
564
|
+
if color is None:
|
565
|
+
channel(
|
566
|
+
_(
|
567
|
+
"No color given! Please provide one like 'green', '#RRBBGGAA' (i.e. #FF000080 for semitransparent red)"
|
568
|
+
)
|
569
|
+
)
|
570
|
+
return "scene", data
|
571
|
+
color = Color(color)
|
572
|
+
if hasattr(self.context, color_key):
|
573
|
+
setattr(self.context, color_key, color.hexa)
|
574
|
+
channel(_("Scene aspect color is set."))
|
575
|
+
self.context.signal("theme", False)
|
576
|
+
else:
|
577
|
+
channel(
|
578
|
+
_("{name} is not a known scene color command").format(
|
579
|
+
name=aspect
|
580
|
+
)
|
581
|
+
)
|
582
|
+
|
583
|
+
return "scene", data
|
584
|
+
|
585
|
+
@self.context.console_argument(
|
586
|
+
"zoom_x", type=float, help="zoom amount from current"
|
587
|
+
)
|
588
|
+
@self.context.console_argument(
|
589
|
+
"zoom_y", type=float, help="zoom amount from current"
|
590
|
+
)
|
591
|
+
@self.context.console_command("aspect", input_type="scene")
|
592
|
+
def scene_aspect(command, _, channel, data, zoom_x=1.0, zoom_y=1.0, **kwgs):
|
593
|
+
if zoom_x is None or zoom_y is None:
|
594
|
+
raise CommandSyntaxError
|
595
|
+
matrix = data.widget_root.scene_widget.matrix
|
596
|
+
matrix.post_scale(zoom_x, zoom_y)
|
597
|
+
data.request_refresh()
|
598
|
+
channel(str(matrix))
|
599
|
+
return "scene", data
|
600
|
+
|
601
|
+
@self.context.console_argument(
|
602
|
+
"zoomfactor", type=float, help="zoom amount from current"
|
603
|
+
)
|
604
|
+
@self.context.console_command("zoom", input_type="scene")
|
605
|
+
def scene_zoomfactor(command, _, channel, data, zoomfactor=1.0, **kwgs):
|
606
|
+
matrix = data.widget_root.scene_widget.matrix
|
607
|
+
if zoomfactor is None:
|
608
|
+
zoomfactor = 1.0
|
609
|
+
matrix.post_scale(zoomfactor)
|
610
|
+
data.request_refresh()
|
611
|
+
channel(str(matrix))
|
612
|
+
return "scene", data
|
613
|
+
|
614
|
+
@self.context.console_argument(
|
615
|
+
"pan_x", type=float, default=0, help="pan from current position x"
|
616
|
+
)
|
617
|
+
@self.context.console_argument(
|
618
|
+
"pan_y", type=float, default=0, help="pan from current position y"
|
619
|
+
)
|
620
|
+
@self.context.console_command("pan", input_type="scene")
|
621
|
+
def scene_pan(command, _, channel, data, pan_x, pan_y, **kwgs):
|
622
|
+
matrix = data.widget_root.scene_widget.matrix
|
623
|
+
if pan_x is None or pan_y is None:
|
624
|
+
return
|
625
|
+
matrix.post_translate(pan_x, pan_y)
|
626
|
+
data.request_refresh()
|
627
|
+
channel(str(matrix))
|
628
|
+
return "scene", data
|
629
|
+
|
630
|
+
@self.context.console_argument(
|
631
|
+
"angle", type=Angle, default=0, help="Rotate scene"
|
632
|
+
)
|
633
|
+
@self.context.console_command("rotate", input_type="scene")
|
634
|
+
def scene_rotate(command, _, channel, data, angle, **kwgs):
|
635
|
+
matrix = data.widget_root.scene_widget.matrix
|
636
|
+
if angle is not None:
|
637
|
+
matrix.post_rotate(angle)
|
638
|
+
data.request_refresh()
|
639
|
+
channel(str(matrix))
|
640
|
+
return "scene", data
|
641
|
+
|
642
|
+
@self.context.console_command("reset", input_type="scene")
|
643
|
+
def scene_reset(command, _, channel, data, **kwgs):
|
644
|
+
matrix = data.widget_root.scene_widget.matrix
|
645
|
+
matrix.reset()
|
646
|
+
data.request_refresh()
|
647
|
+
channel(str(matrix))
|
648
|
+
return "scene", data
|
649
|
+
|
650
|
+
@self.context.console_argument("x", type=str, help="x position")
|
651
|
+
@self.context.console_argument("y", type=str, help="y position")
|
652
|
+
@self.context.console_argument("width", type=str, help="width of view")
|
653
|
+
@self.context.console_argument("height", type=str, help="height of view")
|
654
|
+
@self.context.console_option(
|
655
|
+
"animate",
|
656
|
+
"a",
|
657
|
+
type=bool,
|
658
|
+
action="store_true",
|
659
|
+
help="perform focus with animation",
|
660
|
+
)
|
661
|
+
@self.context.console_command("focus", input_type="scene")
|
662
|
+
def scene_focus(
|
663
|
+
command, _, channel, data, x, y, width, height, animate=False, **kwgs
|
664
|
+
):
|
665
|
+
if animate:
|
666
|
+
overrule = self.context.setting(bool, "suppress_focus_animation", False)
|
667
|
+
if overrule:
|
668
|
+
animate = False
|
669
|
+
|
670
|
+
if height is None:
|
671
|
+
raise CommandSyntaxError("x, y, width, height not specified")
|
672
|
+
try:
|
673
|
+
x = Length(
|
674
|
+
x,
|
675
|
+
relative_length=self.context.device.view.width,
|
676
|
+
unitless=UNITS_PER_PIXEL,
|
677
|
+
)
|
678
|
+
y = Length(
|
679
|
+
y,
|
680
|
+
relative_length=self.context.device.view.height,
|
681
|
+
unitless=UNITS_PER_PIXEL,
|
682
|
+
)
|
683
|
+
width = Length(
|
684
|
+
width,
|
685
|
+
relative_length=self.context.device.view.width,
|
686
|
+
unitless=UNITS_PER_PIXEL,
|
687
|
+
)
|
688
|
+
height = Length(
|
689
|
+
height,
|
690
|
+
relative_length=self.context.device.view.height,
|
691
|
+
unitless=UNITS_PER_PIXEL,
|
692
|
+
)
|
693
|
+
except ValueError:
|
694
|
+
raise CommandSyntaxError("Not a valid length.")
|
695
|
+
bbox = (x, y, width, height)
|
696
|
+
matrix = data.widget_root.scene_widget.matrix
|
697
|
+
data.widget_root.focus_viewport_scene(bbox, self.Size, animate=animate)
|
698
|
+
data.request_refresh()
|
699
|
+
channel(str(matrix))
|
700
|
+
return "scene", data
|
701
|
+
|
702
|
+
@context.console_command("feature_request")
|
703
|
+
def send_developer_feature(remainder="", **kwgs):
|
704
|
+
from .wxmeerk40t import send_data_to_developers
|
705
|
+
|
706
|
+
send_data_to_developers("feature_request.txt", remainder)
|
707
|
+
|
708
|
+
@context.console_command("bug")
|
709
|
+
def send_developer_bug(remainder="", **kwgs):
|
710
|
+
from .wxmeerk40t import send_data_to_developers
|
711
|
+
|
712
|
+
send_data_to_developers("bug.txt", remainder)
|
713
|
+
|
714
|
+
@context.console_command("reference")
|
715
|
+
def make_reference(**kwgs):
|
716
|
+
# Take first emphasized element
|
717
|
+
for e in self.context.elements.flat(types=elem_nodes, emphasized=True):
|
718
|
+
self.reference_object = e
|
719
|
+
break
|
720
|
+
self.context.signal("reference")
|
721
|
+
|
722
|
+
# Establishes commands
|
723
|
+
@context.console_argument(
|
724
|
+
"target", type=str, help=_("Target (one of primary, secondary, circular")
|
725
|
+
)
|
726
|
+
@context.console_argument("ox", type=str, help=_("X-Position of origin"))
|
727
|
+
@context.console_argument("oy", type=str, help=_("Y-Position of origin"))
|
728
|
+
@context.console_argument(
|
729
|
+
"scalex", type=str, help=_("Scaling of X-Axis for secondary")
|
730
|
+
)
|
731
|
+
@context.console_argument(
|
732
|
+
"scaley", type=str, help=_("Scaling of Y-Axis for secondary")
|
733
|
+
)
|
734
|
+
@context.console_command(
|
735
|
+
"grid",
|
736
|
+
help=_("grid <target> <rows> <x_distance> <y_distance> <origin>"),
|
737
|
+
input_type="scene",
|
738
|
+
)
|
739
|
+
def show_grid(
|
740
|
+
command,
|
741
|
+
channel,
|
742
|
+
_,
|
743
|
+
target=None,
|
744
|
+
ox=None,
|
745
|
+
oy=None,
|
746
|
+
scalex=None,
|
747
|
+
scaley=None,
|
748
|
+
**kwgs,
|
749
|
+
):
|
750
|
+
if target is None:
|
751
|
+
channel(_("Grid-Parameters:"))
|
752
|
+
p_state = _("On") if self.grid.draw_grid_primary else _("Off")
|
753
|
+
channel(f"Primary: {p_state}")
|
754
|
+
if self.grid.draw_grid_secondary:
|
755
|
+
channel(f"Secondary: {_('On')}")
|
756
|
+
if self.grid.grid_secondary_cx is not None:
|
757
|
+
channel(
|
758
|
+
f" cx: {Length(amount=self.grid.grid_secondary_cx).length_mm}"
|
759
|
+
)
|
760
|
+
if self.grid.grid_secondary_cy is not None:
|
761
|
+
channel(
|
762
|
+
f" cy: {Length(amount=self.grid.grid_secondary_cy).length_mm}"
|
763
|
+
)
|
764
|
+
if self.grid.grid_secondary_scale_x is not None:
|
765
|
+
channel(f" scale-x: {self.grid.grid_secondary_scale_x:.2f}")
|
766
|
+
if self.grid.grid_secondary_scale_y is not None:
|
767
|
+
channel(f" scale-y: {self.grid.grid_secondary_scale_y:.2f}")
|
768
|
+
else:
|
769
|
+
channel(f"Secondary: {_('Off')}")
|
770
|
+
if self.grid.draw_grid_circular:
|
771
|
+
channel(f"Circular: {_('On')}")
|
772
|
+
if self.grid.grid_circular_cx is not None:
|
773
|
+
channel(
|
774
|
+
f" cx: {Length(amount=self.grid.grid_circular_cx).length_mm}"
|
775
|
+
)
|
776
|
+
if self.grid.grid_circular_cy is not None:
|
777
|
+
channel(
|
778
|
+
f" cy: {Length(amount=self.grid.grid_circular_cy).length_mm}"
|
779
|
+
)
|
780
|
+
else:
|
781
|
+
channel(f"Circular: {_('Off')}")
|
782
|
+
return
|
783
|
+
else:
|
784
|
+
target = target.lower()
|
785
|
+
if target[0] == "p":
|
786
|
+
self.grid.draw_grid_primary = not self.grid.draw_grid_primary
|
787
|
+
channel(
|
788
|
+
_("Turned primary grid on")
|
789
|
+
if self.grid.draw_grid_primary
|
790
|
+
else _("Turned primary grid off")
|
791
|
+
)
|
792
|
+
self.scene.signal("guide")
|
793
|
+
self.scene.signal("grid")
|
794
|
+
self.widget_scene.reset_snap_attraction()
|
795
|
+
self.request_refresh()
|
796
|
+
elif target[0] == "s":
|
797
|
+
self.grid.draw_grid_secondary = not self.grid.draw_grid_secondary
|
798
|
+
if self.grid.draw_grid_secondary:
|
799
|
+
if ox is None:
|
800
|
+
self.grid.grid_secondary_cx = None
|
801
|
+
self.grid.grid_secondary_cy = None
|
802
|
+
scalex = None
|
803
|
+
scaley = None
|
804
|
+
else:
|
805
|
+
if oy is None:
|
806
|
+
oy = ox
|
807
|
+
self.grid.grid_secondary_cx = float(
|
808
|
+
Length(
|
809
|
+
ox, relative_length=self.context.device.view.width
|
810
|
+
)
|
811
|
+
)
|
812
|
+
self.grid.grid_secondary_cy = float(
|
813
|
+
Length(
|
814
|
+
oy, relative_length=self.context.device.view.height
|
815
|
+
)
|
816
|
+
)
|
817
|
+
if scalex is None:
|
818
|
+
rot = self.scene.context.device.rotary
|
819
|
+
if rot.active:
|
820
|
+
scalex = rot.scale_x
|
821
|
+
scaley = rot.scale_y
|
822
|
+
else:
|
823
|
+
scalex = 1.0
|
824
|
+
scaley = 1.0
|
825
|
+
else:
|
826
|
+
scalex = float(scalex)
|
827
|
+
if scaley is None:
|
828
|
+
scaley = scalex
|
829
|
+
else:
|
830
|
+
scaley = float(scaley)
|
831
|
+
self.grid.grid_secondary_scale_x = scalex
|
832
|
+
self.grid.grid_secondary_scale_y = scaley
|
833
|
+
channel(
|
834
|
+
_(
|
835
|
+
"Turned secondary grid on"
|
836
|
+
if self.grid.draw_grid_secondary
|
837
|
+
else "Turned secondary grid off"
|
838
|
+
)
|
839
|
+
)
|
840
|
+
self.scene.signal("guide")
|
841
|
+
self.scene.signal("grid")
|
842
|
+
self.request_refresh()
|
843
|
+
elif target[0] == "c":
|
844
|
+
self.grid.draw_grid_circular = not self.grid.draw_grid_circular
|
845
|
+
if self.grid.draw_grid_circular:
|
846
|
+
if ox is None:
|
847
|
+
self.grid.grid_circular_cx = None
|
848
|
+
self.grid.grid_circular_cy = None
|
849
|
+
else:
|
850
|
+
if oy is None:
|
851
|
+
oy = ox
|
852
|
+
self.grid.grid_circular_cx = float(
|
853
|
+
Length(
|
854
|
+
ox, relative_length=self.context.device.view.width
|
855
|
+
)
|
856
|
+
)
|
857
|
+
self.grid.grid_circular_cy = float(
|
858
|
+
Length(
|
859
|
+
oy, relative_length=self.context.device.view.height
|
860
|
+
)
|
861
|
+
)
|
862
|
+
channel(
|
863
|
+
_(
|
864
|
+
"Turned circular grid on"
|
865
|
+
if self.grid.draw_grid_circular
|
866
|
+
else "Turned circular grid off"
|
867
|
+
)
|
868
|
+
)
|
869
|
+
self.scene.signal("guide")
|
870
|
+
self.scene.signal("grid")
|
871
|
+
self.request_refresh()
|
872
|
+
else:
|
873
|
+
channel(_("Target needs to be one of primary, secondary, circular"))
|
874
|
+
|
875
|
+
def toggle_ref_obj(self):
|
876
|
+
for e in self.scene.context.elements.flat(types=elem_nodes, emphasized=True):
|
877
|
+
if self.reference_object == e:
|
878
|
+
self.reference_object = None
|
879
|
+
else:
|
880
|
+
self.reference_object = e
|
881
|
+
break
|
882
|
+
self.context.signal("reference")
|
883
|
+
self.request_refresh()
|
884
|
+
|
885
|
+
def validate_reference(self):
|
886
|
+
"""
|
887
|
+
Check whether the reference is still valid
|
888
|
+
"""
|
889
|
+
found = False
|
890
|
+
if self._reference:
|
891
|
+
for e in self.context.elements.flat(types=elem_nodes):
|
892
|
+
# Here we ignore the lock-status of an element
|
893
|
+
if e is self._reference:
|
894
|
+
found = True
|
895
|
+
break
|
896
|
+
if not found:
|
897
|
+
self._reference = None
|
898
|
+
|
899
|
+
@property
|
900
|
+
def reference_object(self):
|
901
|
+
return self._reference
|
902
|
+
|
903
|
+
@reference_object.setter
|
904
|
+
def reference_object(self, ref_object):
|
905
|
+
prev = self._reference
|
906
|
+
self._reference = ref_object
|
907
|
+
self.scene.reference_object = self._reference
|
908
|
+
dlist = []
|
909
|
+
if prev is not None:
|
910
|
+
dlist.append(prev)
|
911
|
+
if self._reference is not None:
|
912
|
+
dlist.append(self._reference)
|
913
|
+
if len(dlist) > 0:
|
914
|
+
self.context.signal("element_property_update", dlist)
|
915
|
+
|
916
|
+
##########
|
917
|
+
# MAGNETS
|
918
|
+
##########
|
919
|
+
|
920
|
+
@property
|
921
|
+
def magnet_attraction(self):
|
922
|
+
return self._magnet_attraction
|
923
|
+
|
924
|
+
@magnet_attraction.setter
|
925
|
+
def magnet_attraction(self, value):
|
926
|
+
if 0 <= value <= 5:
|
927
|
+
self._magnet_attraction = value
|
928
|
+
self.save_magnets()
|
929
|
+
|
930
|
+
def save_magnets(self):
|
931
|
+
try:
|
932
|
+
with open(self._magnet_file, "w") as f:
|
933
|
+
f.write(f"a={self.magnet_attraction}\n")
|
934
|
+
for x in self.magnet_x:
|
935
|
+
f.write(f"x={Length(x, preferred_units='mm').preferred_length}\n")
|
936
|
+
for y in self.magnet_y:
|
937
|
+
f.write(f"y={Length(y, preferred_units='mm').preferred_length}\n")
|
938
|
+
except (ValueError, PermissionError, OSError, FileNotFoundError):
|
939
|
+
return
|
940
|
+
|
941
|
+
def load_magnets(self):
|
942
|
+
self.magnet_x = []
|
943
|
+
self.magnet_y = []
|
944
|
+
try:
|
945
|
+
with open(self._magnet_file, "r") as f:
|
946
|
+
for line in f:
|
947
|
+
cline = line.strip()
|
948
|
+
if cline != "":
|
949
|
+
subs = cline.split("=")
|
950
|
+
if len(subs) > 1:
|
951
|
+
try:
|
952
|
+
if subs[0] in ("a", "A"):
|
953
|
+
# Attraction strength
|
954
|
+
value = int(subs[1])
|
955
|
+
if value < 0:
|
956
|
+
value = 0
|
957
|
+
if value > 5:
|
958
|
+
value = 5
|
959
|
+
self._magnet_attraction = value
|
960
|
+
elif subs[0] in ("x", "X"):
|
961
|
+
dimens = Length(subs[1])
|
962
|
+
value = float(dimens)
|
963
|
+
if value not in self.magnet_x:
|
964
|
+
self.magnet_x.append(value)
|
965
|
+
elif subs[0] in ("y", "Y"):
|
966
|
+
dimens = Length(subs[1])
|
967
|
+
value = float(dimens)
|
968
|
+
if value not in self.magnet_y:
|
969
|
+
self.magnet_y.append(value)
|
970
|
+
except ValueError:
|
971
|
+
pass
|
972
|
+
except (PermissionError, OSError, FileNotFoundError):
|
973
|
+
return
|
974
|
+
|
975
|
+
def clear_magnets(self):
|
976
|
+
self.magnet_x = []
|
977
|
+
self.magnet_y = []
|
978
|
+
self.save_magnets()
|
979
|
+
|
980
|
+
def clear_magnets_conditionally(self):
|
981
|
+
# Depending on setting
|
982
|
+
if self.context.clear_magnets:
|
983
|
+
self.clear_magnets()
|
984
|
+
|
985
|
+
def toggle_x_magnet(self, x_value):
|
986
|
+
if x_value in self.magnet_x:
|
987
|
+
self.magnet_x.remove(x_value)
|
988
|
+
else:
|
989
|
+
self.magnet_x += [x_value]
|
990
|
+
|
991
|
+
def toggle_y_magnet(self, y_value):
|
992
|
+
if y_value in self.magnet_y:
|
993
|
+
self.magnet_y.remove(y_value)
|
994
|
+
else:
|
995
|
+
self.magnet_y += [y_value]
|
996
|
+
|
997
|
+
def magnet_attracted_x(self, x_value, useit):
|
998
|
+
delta = float("inf")
|
999
|
+
x_val = None
|
1000
|
+
if useit:
|
1001
|
+
for mag_x in self.magnet_x:
|
1002
|
+
if abs(x_value - mag_x) < delta:
|
1003
|
+
delta = abs(x_value - mag_x)
|
1004
|
+
x_val = mag_x
|
1005
|
+
return delta, x_val
|
1006
|
+
|
1007
|
+
def magnet_attracted_y(self, y_value, useit):
|
1008
|
+
delta = float("inf")
|
1009
|
+
y_val = None
|
1010
|
+
if useit:
|
1011
|
+
for mag_y in self.magnet_y:
|
1012
|
+
if abs(y_value - mag_y) < delta:
|
1013
|
+
delta = abs(y_value - mag_y)
|
1014
|
+
y_val = mag_y
|
1015
|
+
return delta, y_val
|
1016
|
+
|
1017
|
+
def revised_magnet_bound(self, bounds=None):
|
1018
|
+
dx = 0
|
1019
|
+
dy = 0
|
1020
|
+
if self.has_magnets() and self._magnet_attraction > 0:
|
1021
|
+
if self.grid.tick_distance > 0:
|
1022
|
+
s = f"{self.grid.tick_distance}{self.context.units_name}"
|
1023
|
+
len_tick = float(Length(s))
|
1024
|
+
# Attraction length is 1/3, 4/3, 9/3 of a grid-unit
|
1025
|
+
# fmt: off
|
1026
|
+
attraction_len = 1 / 3 * self._magnet_attraction * self._magnet_attraction * len_tick
|
1027
|
+
|
1028
|
+
# print("Attraction len=%s, attract=%d, alen=%.1f, tlen=%.1f, factor=%.1f" % (s, self._magnet_attraction, attraction_len, len_tick, attraction_len / len_tick ))
|
1029
|
+
# fmt: on
|
1030
|
+
else:
|
1031
|
+
attraction_len = float(Length("1mm"))
|
1032
|
+
|
1033
|
+
delta_x1, x1 = self.magnet_attracted_x(bounds[0], self.magnet_attract_x)
|
1034
|
+
delta_x2, x2 = self.magnet_attracted_x(bounds[2], self.magnet_attract_x)
|
1035
|
+
delta_x3, x3 = self.magnet_attracted_x(
|
1036
|
+
(bounds[0] + bounds[2]) / 2, self.magnet_attract_c
|
1037
|
+
)
|
1038
|
+
delta_y1, y1 = self.magnet_attracted_y(bounds[1], self.magnet_attract_y)
|
1039
|
+
delta_y2, y2 = self.magnet_attracted_y(bounds[3], self.magnet_attract_y)
|
1040
|
+
delta_y3, y3 = self.magnet_attracted_y(
|
1041
|
+
(bounds[1] + bounds[3]) / 2, self.magnet_attract_c
|
1042
|
+
)
|
1043
|
+
if delta_x3 < delta_x1 and delta_x3 < delta_x2:
|
1044
|
+
if delta_x3 < attraction_len:
|
1045
|
+
if x3 is not None:
|
1046
|
+
dx = x3 - (bounds[0] + bounds[2]) / 2
|
1047
|
+
# print("X Take center , x=%.1f, dx=%.1f" % ((bounds[0] + bounds[2]) / 2, dx)
|
1048
|
+
elif delta_x1 < delta_x2 and delta_x1 < delta_x3:
|
1049
|
+
if delta_x1 < attraction_len:
|
1050
|
+
if x1 is not None:
|
1051
|
+
dx = x1 - bounds[0]
|
1052
|
+
# print("X Take left side, x=%.1f, dx=%.1f" % (bounds[0], dx))
|
1053
|
+
elif delta_x2 < delta_x1 and delta_x2 < delta_x3:
|
1054
|
+
if delta_x2 < attraction_len:
|
1055
|
+
if x2 is not None:
|
1056
|
+
dx = x2 - bounds[2]
|
1057
|
+
# print("X Take right side, x=%.1f, dx=%.1f" % (bounds[2], dx))
|
1058
|
+
if delta_y3 < delta_y1 and delta_y3 < delta_y2:
|
1059
|
+
if delta_y3 < attraction_len:
|
1060
|
+
if y3 is not None:
|
1061
|
+
dy = y3 - (bounds[1] + bounds[3]) / 2
|
1062
|
+
# print("Y Take center , x=%.1f, dx=%.1f" % ((bounds[1] + bounds[3]) / 2, dy))
|
1063
|
+
elif delta_y1 < delta_y2 and delta_y1 < delta_y3:
|
1064
|
+
if delta_y1 < attraction_len:
|
1065
|
+
if y1 is not None:
|
1066
|
+
dy = y1 - bounds[1]
|
1067
|
+
# print("Y Take top side, y=%.1f, dy=%.1f" % (bounds[1], dy))
|
1068
|
+
elif delta_y2 < delta_y1 and delta_y2 < delta_y3:
|
1069
|
+
if delta_y2 < attraction_len:
|
1070
|
+
if y2 is not None:
|
1071
|
+
dy = y2 - bounds[3]
|
1072
|
+
# print("Y Take bottom side, y=%.1f, dy=%.1f" % (bounds[3], dy))
|
1073
|
+
|
1074
|
+
return dx, dy
|
1075
|
+
|
1076
|
+
def has_magnets(self):
|
1077
|
+
return len(self.magnet_x) + len(self.magnet_y) > 0
|
1078
|
+
|
1079
|
+
##############
|
1080
|
+
# SNAPS
|
1081
|
+
##############
|
1082
|
+
|
1083
|
+
@property
|
1084
|
+
def last_snap(self):
|
1085
|
+
result = self._last_snap_position
|
1086
|
+
# Too old? Discard
|
1087
|
+
if (time.time() - self._last_snap_ts) > 0.5:
|
1088
|
+
result = None
|
1089
|
+
return result
|
1090
|
+
|
1091
|
+
@last_snap.setter
|
1092
|
+
def last_snap(self, value):
|
1093
|
+
self._last_snap_position = value
|
1094
|
+
if value is None:
|
1095
|
+
self._last_snap_ts = 0
|
1096
|
+
else:
|
1097
|
+
self._last_snap_ts = time.time()
|
1098
|
+
|
1099
|
+
@signal_listener("make_reference")
|
1100
|
+
def listen_make_ref(self, origin, *args):
|
1101
|
+
node = args[0]
|
1102
|
+
self.reference_object = node
|
1103
|
+
self.context.signal("reference")
|
1104
|
+
|
1105
|
+
@signal_listener("create_magnets")
|
1106
|
+
def listen_magnet_creation(self, origin, creation_list, *args):
|
1107
|
+
for (info, value) in creation_list:
|
1108
|
+
if info == "x":
|
1109
|
+
self.toggle_x_magnet(value)
|
1110
|
+
else:
|
1111
|
+
self.toggle_y_magnet(value)
|
1112
|
+
self.save_magnets()
|
1113
|
+
self.request_refresh()
|
1114
|
+
|
1115
|
+
@signal_listener("draw_mode")
|
1116
|
+
def on_draw_mode(self, origin, *args):
|
1117
|
+
if self._tool_widget is not None:
|
1118
|
+
orgx = 5
|
1119
|
+
orgy = 5
|
1120
|
+
# Are guides drawn?
|
1121
|
+
if self.context.draw_mode & DRAW_MODE_GUIDES == 0:
|
1122
|
+
orgx += 25
|
1123
|
+
orgy += 25
|
1124
|
+
self._tool_widget.set_position(orgx, orgy)
|
1125
|
+
|
1126
|
+
@signal_listener("scene_right_click")
|
1127
|
+
def on_scene_right(self, origin, *args):
|
1128
|
+
def zoom_in(event=None):
|
1129
|
+
self.context(f"scene zoom {1.5 / 1.0}\n")
|
1130
|
+
|
1131
|
+
def zoom_out(event=None):
|
1132
|
+
self.context(f"scene zoom {1.0 / 1.5}\n")
|
1133
|
+
|
1134
|
+
def zoom_to_bed(event=None):
|
1135
|
+
zoom = self.context.zoom_margin
|
1136
|
+
self.context(f"scene focus -a {-zoom}% {-zoom}% {zoom+100}% {zoom+100}%\n")
|
1137
|
+
|
1138
|
+
def zoom_to_selected(event=None):
|
1139
|
+
bbox = self.context.elements.selected_area()
|
1140
|
+
if bbox is None:
|
1141
|
+
zoom_to_bed(event=event)
|
1142
|
+
else:
|
1143
|
+
zfact = self.context.zoom_margin / 100.0
|
1144
|
+
|
1145
|
+
x_delta = (bbox[2] - bbox[0]) * zfact
|
1146
|
+
y_delta = (bbox[3] - bbox[1]) * zfact
|
1147
|
+
x0 = Length(
|
1148
|
+
amount=bbox[0] - x_delta,
|
1149
|
+
relative_length=self.context.device.view.width,
|
1150
|
+
).length_mm
|
1151
|
+
y0 = Length(
|
1152
|
+
amount=bbox[1] - y_delta,
|
1153
|
+
relative_length=self.context.device.view.height,
|
1154
|
+
).length_mm
|
1155
|
+
x1 = Length(
|
1156
|
+
amount=bbox[2] + x_delta,
|
1157
|
+
relative_length=self.context.device.view.width,
|
1158
|
+
).length_mm
|
1159
|
+
y1 = Length(
|
1160
|
+
amount=bbox[3] + y_delta,
|
1161
|
+
relative_length=self.context.device.view.height,
|
1162
|
+
).length_mm
|
1163
|
+
self.context(f"scene focus -a {x0} {y0} {x1} {y1}\n")
|
1164
|
+
|
1165
|
+
def toggle_background(event=None):
|
1166
|
+
"""
|
1167
|
+
Toggle the draw mode for the background
|
1168
|
+
"""
|
1169
|
+
self.widget_scene.context.draw_mode ^= DRAW_MODE_BACKGROUND
|
1170
|
+
self.widget_scene.request_refresh()
|
1171
|
+
|
1172
|
+
def toggle_grid(gridtype):
|
1173
|
+
if gridtype == "primary":
|
1174
|
+
self.grid.draw_grid_primary = not self.grid.draw_grid_primary
|
1175
|
+
elif gridtype == "secondary":
|
1176
|
+
self.grid.draw_grid_secondary = not self.grid.draw_grid_secondary
|
1177
|
+
elif gridtype == "circular":
|
1178
|
+
self.grid.draw_grid_circular = not self.grid.draw_grid_circular
|
1179
|
+
elif gridtype == "offset":
|
1180
|
+
self.grid.draw_offset_lines = not self.grid.draw_offset_lines
|
1181
|
+
self.scene.signal("guide")
|
1182
|
+
self.scene.signal("grid")
|
1183
|
+
self.widget_scene.reset_snap_attraction()
|
1184
|
+
self.request_refresh()
|
1185
|
+
|
1186
|
+
def toggle_grid_p(event=None):
|
1187
|
+
toggle_grid("primary")
|
1188
|
+
|
1189
|
+
def toggle_grid_s(event=None):
|
1190
|
+
toggle_grid("secondary")
|
1191
|
+
|
1192
|
+
def toggle_grid_c(event=None):
|
1193
|
+
toggle_grid("circular")
|
1194
|
+
|
1195
|
+
def toggle_grid_o(event=None):
|
1196
|
+
toggle_grid("offset")
|
1197
|
+
|
1198
|
+
def remove_background(event=None):
|
1199
|
+
self.widget_scene._signal_widget(
|
1200
|
+
self.widget_scene.widget_root, "background", None
|
1201
|
+
)
|
1202
|
+
self.widget_scene.request_refresh()
|
1203
|
+
|
1204
|
+
def recognize_background_contours(event=None):
|
1205
|
+
def image_from_bitmap(myBitmap):
|
1206
|
+
wx_image = myBitmap.ConvertToImage()
|
1207
|
+
myPilImage = Image.new(
|
1208
|
+
"RGB", (wx_image.GetWidth(), wx_image.GetHeight())
|
1209
|
+
)
|
1210
|
+
myPilImage.frombytes(wx_image.GetData())
|
1211
|
+
return myPilImage
|
1212
|
+
|
1213
|
+
if not self.widget_scene.has_background:
|
1214
|
+
return
|
1215
|
+
# We build a dummy imageNode, so we fetch the background,
|
1216
|
+
# calculate the required transformation matrix and pass
|
1217
|
+
# it on to one of the standard image node property dialogs
|
1218
|
+
|
1219
|
+
background = self.widget_scene.active_background
|
1220
|
+
if background is None:
|
1221
|
+
return
|
1222
|
+
background_image = image_from_bitmap(background)
|
1223
|
+
|
1224
|
+
# Calculate scaling matrix
|
1225
|
+
sx = float(Length(self.context.device.view.width)) / background_image.width
|
1226
|
+
sy = (
|
1227
|
+
float(Length(self.context.device.view.height)) / background_image.height
|
1228
|
+
)
|
1229
|
+
matrix = Matrix(f"scale({sx},{sy})")
|
1230
|
+
# print (f"Image dimension: {background_image.width} x {background_image.height} pixel")
|
1231
|
+
# print (f"View-Size: {float(Length(self.context.device.view.width))} x {float(Length(self.context.device.view.height))}")
|
1232
|
+
# print (f"Matrix: {matrix}")
|
1233
|
+
|
1234
|
+
node = ImageNode(
|
1235
|
+
image=background_image,
|
1236
|
+
matrix=matrix,
|
1237
|
+
dither=False,
|
1238
|
+
prevent_crop=True,
|
1239
|
+
dpi=500,
|
1240
|
+
)
|
1241
|
+
# print (f"Node-Dimensions: {node.bbox()}")
|
1242
|
+
dlg = ContourDetectionDialog(self, self.context, node)
|
1243
|
+
dlg.ShowModal()
|
1244
|
+
dlg.end_dialog()
|
1245
|
+
dlg.Destroy()
|
1246
|
+
|
1247
|
+
def stop_auto_update(event=None):
|
1248
|
+
devlabel = self.context.device.label
|
1249
|
+
to_stop = []
|
1250
|
+
for job, content in self.context.kernel.jobs.items():
|
1251
|
+
if job is not None and job.startswith("timer.updatebg"):
|
1252
|
+
cmd = str(content).strip()
|
1253
|
+
if cmd.endswith("background") or cmd.endswith(devlabel):
|
1254
|
+
to_stop.append(job)
|
1255
|
+
for job in to_stop:
|
1256
|
+
self.context(f"{job} --off\n")
|
1257
|
+
|
1258
|
+
gui = self
|
1259
|
+
menu = wx.Menu()
|
1260
|
+
id1 = menu.Append(
|
1261
|
+
wx.ID_ANY,
|
1262
|
+
_("Show Background"),
|
1263
|
+
_("Display the background picture in the scene"),
|
1264
|
+
wx.ITEM_CHECK,
|
1265
|
+
)
|
1266
|
+
self.Bind(wx.EVT_MENU, toggle_background, id=id1.GetId())
|
1267
|
+
menu.Check(
|
1268
|
+
id1.GetId(),
|
1269
|
+
(self.widget_scene.context.draw_mode & DRAW_MODE_BACKGROUND == 0),
|
1270
|
+
)
|
1271
|
+
id2 = menu.Append(
|
1272
|
+
wx.ID_ANY,
|
1273
|
+
_("Show Primary Grid"),
|
1274
|
+
_("Display the primary grid in the scene"),
|
1275
|
+
wx.ITEM_CHECK,
|
1276
|
+
)
|
1277
|
+
self.Bind(wx.EVT_MENU, toggle_grid_p, id=id2.GetId())
|
1278
|
+
menu.Check(id2.GetId(), self.grid.draw_grid_primary)
|
1279
|
+
id3 = menu.Append(
|
1280
|
+
wx.ID_ANY,
|
1281
|
+
_("Show Secondary Grid"),
|
1282
|
+
_("Display the secondary grid in the scene"),
|
1283
|
+
wx.ITEM_CHECK,
|
1284
|
+
)
|
1285
|
+
self.Bind(wx.EVT_MENU, toggle_grid_s, id=id3.GetId())
|
1286
|
+
menu.Check(id3.GetId(), self.grid.draw_grid_secondary)
|
1287
|
+
id4 = menu.Append(
|
1288
|
+
wx.ID_ANY,
|
1289
|
+
_("Show Circular Grid"),
|
1290
|
+
_("Display the circular grid in the scene"),
|
1291
|
+
wx.ITEM_CHECK,
|
1292
|
+
)
|
1293
|
+
self.Bind(wx.EVT_MENU, toggle_grid_c, id=id4.GetId())
|
1294
|
+
menu.Check(id4.GetId(), self.grid.draw_grid_circular)
|
1295
|
+
try:
|
1296
|
+
mx = float(Length(self.context.device.view.margin_x))
|
1297
|
+
my = float(Length(self.context.device.view.margin_y))
|
1298
|
+
except ValueError:
|
1299
|
+
mx = 0
|
1300
|
+
my = 0
|
1301
|
+
# print(self.context.device.view.margin_x, self.context.device.view.margin_y)
|
1302
|
+
if mx != 0.0 or my != 0.0:
|
1303
|
+
menu.AppendSeparator()
|
1304
|
+
id4b = menu.Append(
|
1305
|
+
wx.ID_ANY,
|
1306
|
+
_("Show physical dimensions"),
|
1307
|
+
_("Display the physical dimensions"),
|
1308
|
+
wx.ITEM_CHECK,
|
1309
|
+
)
|
1310
|
+
self.Bind(wx.EVT_MENU, toggle_grid_o, id=id4b.GetId())
|
1311
|
+
menu.Check(id4b.GetId(), self.grid.draw_offset_lines)
|
1312
|
+
|
1313
|
+
if self.widget_scene.has_background:
|
1314
|
+
menu.AppendSeparator()
|
1315
|
+
id5 = menu.Append(wx.ID_ANY, _("Remove Background"), "")
|
1316
|
+
self.Bind(wx.EVT_MENU, remove_background, id=id5.GetId())
|
1317
|
+
|
1318
|
+
id6 = menu.Append(wx.ID_ANY, _("Detect contours on background"), "")
|
1319
|
+
self.Bind(wx.EVT_MENU, recognize_background_contours, id=id6.GetId())
|
1320
|
+
# Do we have a timer called .updatebg?
|
1321
|
+
devlabel = self.context.device.label
|
1322
|
+
we_have_a_job = False
|
1323
|
+
for job, content in self.context.kernel.jobs.items():
|
1324
|
+
if job is not None and job.startswith("timer.updatebg"):
|
1325
|
+
cmd = str(content).strip()
|
1326
|
+
if cmd.endswith("background") or cmd.endswith(devlabel):
|
1327
|
+
we_have_a_job = True
|
1328
|
+
break
|
1329
|
+
|
1330
|
+
if we_have_a_job:
|
1331
|
+
self.Bind(
|
1332
|
+
wx.EVT_MENU,
|
1333
|
+
lambda e: stop_auto_update(),
|
1334
|
+
menu.Append(
|
1335
|
+
wx.ID_ANY,
|
1336
|
+
_("Stop autoupdate"),
|
1337
|
+
_("Stop automatic refresh of background image"),
|
1338
|
+
),
|
1339
|
+
)
|
1340
|
+
menu.AppendSeparator()
|
1341
|
+
self.Bind(
|
1342
|
+
wx.EVT_MENU,
|
1343
|
+
lambda e: zoom_out(),
|
1344
|
+
menu.Append(
|
1345
|
+
wx.ID_ANY,
|
1346
|
+
_("Zoom Out"),
|
1347
|
+
_("Make the scene smaller"),
|
1348
|
+
),
|
1349
|
+
)
|
1350
|
+
self.Bind(
|
1351
|
+
wx.EVT_MENU,
|
1352
|
+
lambda e: zoom_in(),
|
1353
|
+
menu.Append(
|
1354
|
+
wx.ID_ANY,
|
1355
|
+
_("Zoom In"),
|
1356
|
+
_("Make the scene larger"),
|
1357
|
+
),
|
1358
|
+
)
|
1359
|
+
self.Bind(
|
1360
|
+
wx.EVT_MENU,
|
1361
|
+
lambda e: zoom_to_bed(),
|
1362
|
+
menu.Append(
|
1363
|
+
wx.ID_ANY,
|
1364
|
+
_("&Zoom to Bed"),
|
1365
|
+
_("View the whole laser bed"),
|
1366
|
+
),
|
1367
|
+
)
|
1368
|
+
if self.context.elements.has_emphasis():
|
1369
|
+
self.Bind(
|
1370
|
+
wx.EVT_MENU,
|
1371
|
+
lambda e: zoom_to_selected(),
|
1372
|
+
menu.Append(
|
1373
|
+
wx.ID_ANY,
|
1374
|
+
_("Zoom to &Selected"),
|
1375
|
+
_("Fill the scene area with the selected elements"),
|
1376
|
+
),
|
1377
|
+
)
|
1378
|
+
|
1379
|
+
if menu.MenuItemCount != 0:
|
1380
|
+
gui.PopupMenu(menu)
|
1381
|
+
menu.Destroy()
|
1382
|
+
|
1383
|
+
@signal_listener("refresh_scene")
|
1384
|
+
def on_refresh_scene(self, origin, scene_name=None, *args):
|
1385
|
+
"""
|
1386
|
+
Called by 'refresh_scene' change. To refresh tree.
|
1387
|
+
|
1388
|
+
@param origin: the path of the originating signal
|
1389
|
+
@param scene_name: Scene to refresh on if matching
|
1390
|
+
@param args:
|
1391
|
+
@return:
|
1392
|
+
"""
|
1393
|
+
if scene_name == "Scene":
|
1394
|
+
self.request_refresh()
|
1395
|
+
|
1396
|
+
@signal_listener("coolant_changed")
|
1397
|
+
def on_coolant_changed(self, origin, *args):
|
1398
|
+
if hasattr(self.context.device, "coolant"):
|
1399
|
+
coolid = self.context.device.device_coolant
|
1400
|
+
if coolid == "":
|
1401
|
+
coolid = None
|
1402
|
+
cool = self.context.kernel.root.coolant
|
1403
|
+
cool.claim_coolant(self.context.device, coolid)
|
1404
|
+
|
1405
|
+
@signal_listener("view;realized")
|
1406
|
+
def on_bedsize_simple(self, origin=None, nocmd=None, *args):
|
1407
|
+
self.scene.signal("guide")
|
1408
|
+
self.scene.signal("grid")
|
1409
|
+
self.request_refresh(origin)
|
1410
|
+
|
1411
|
+
@signal_listener("magnet-attraction")
|
1412
|
+
def on_magnet_attract(self, origin, strength, *args):
|
1413
|
+
strength = int(strength)
|
1414
|
+
if strength < 0:
|
1415
|
+
strength = 0
|
1416
|
+
self.magnet_attraction = strength
|
1417
|
+
|
1418
|
+
@signal_listener("magnet_gen")
|
1419
|
+
def on_magnet_generate(self, origin, *args):
|
1420
|
+
candidate = args[0]
|
1421
|
+
if candidate is None:
|
1422
|
+
return
|
1423
|
+
if not isinstance(candidate, (tuple, list)) or len(candidate) < 2:
|
1424
|
+
return
|
1425
|
+
method = candidate[0]
|
1426
|
+
node = candidate[1]
|
1427
|
+
bb = node.bounds
|
1428
|
+
if method == "outer":
|
1429
|
+
self.toggle_x_magnet(bb[0])
|
1430
|
+
self.toggle_x_magnet(bb[2])
|
1431
|
+
self.toggle_y_magnet(bb[1])
|
1432
|
+
self.toggle_y_magnet(bb[3])
|
1433
|
+
elif method == "center":
|
1434
|
+
self.toggle_x_magnet((bb[0] + bb[2]) / 2)
|
1435
|
+
self.toggle_y_magnet((bb[1] + bb[3]) / 2)
|
1436
|
+
self.save_magnets()
|
1437
|
+
self.request_refresh()
|
1438
|
+
|
1439
|
+
def pane_show(self, *args):
|
1440
|
+
zl = self.context.zoom_margin
|
1441
|
+
self.context(f"scene focus -{zl}% -{zl}% {100 + zl}% {100 + zl}%\n")
|
1442
|
+
|
1443
|
+
def pane_hide(self, *args):
|
1444
|
+
pass
|
1445
|
+
|
1446
|
+
@signal_listener("activate;device")
|
1447
|
+
def on_activate_device(self, origin, device):
|
1448
|
+
self.scene.signal("grid")
|
1449
|
+
self.request_refresh()
|
1450
|
+
|
1451
|
+
def on_size(self, event):
|
1452
|
+
if self.context is None:
|
1453
|
+
return
|
1454
|
+
self.Layout()
|
1455
|
+
# Refresh not needed as scenepanel already does it...
|
1456
|
+
# self.scene.signal("guide")
|
1457
|
+
# self.request_refresh()
|
1458
|
+
|
1459
|
+
def on_close(self, event):
|
1460
|
+
self.save_magnets()
|
1461
|
+
|
1462
|
+
@signal_listener("pause")
|
1463
|
+
@signal_listener("pipe;running")
|
1464
|
+
def on_driver_mode(self, origin, *args):
|
1465
|
+
# pipe running has (state) as args
|
1466
|
+
new_color = None
|
1467
|
+
try:
|
1468
|
+
if self.context.device.driver.paused:
|
1469
|
+
new_color = self.context.themes.get("pause_bg")
|
1470
|
+
elif self.context.device.laser_status == "active":
|
1471
|
+
new_color = self.context.themes.get("stop_bg")
|
1472
|
+
except AttributeError:
|
1473
|
+
pass
|
1474
|
+
self.widget_scene.overrule_background = new_color
|
1475
|
+
self.widget_scene.request_refresh_for_animation()
|
1476
|
+
|
1477
|
+
@signal_listener("background")
|
1478
|
+
def on_background_signal(self, origin, background):
|
1479
|
+
background = wx.Bitmap.FromBuffer(*background)
|
1480
|
+
self.scene.signal("background", background)
|
1481
|
+
self.request_refresh()
|
1482
|
+
|
1483
|
+
@signal_listener("units")
|
1484
|
+
def space_changed(self, origin, *args):
|
1485
|
+
self.scene.signal("guide")
|
1486
|
+
self.scene.signal("grid")
|
1487
|
+
self.request_refresh(origin)
|
1488
|
+
|
1489
|
+
@signal_listener("bed_size")
|
1490
|
+
def bed_changed(self, origin, *args):
|
1491
|
+
self.scene.signal("grid")
|
1492
|
+
# self.scene.signal('guide')
|
1493
|
+
self.request_refresh(origin)
|
1494
|
+
|
1495
|
+
@signal_listener("modified_by_tool")
|
1496
|
+
def on_modification_by_tool(self, origin, *args):
|
1497
|
+
self.context.elements.process_keyhole_updates(self.context)
|
1498
|
+
self.scene.signal("modified_by_tool")
|
1499
|
+
|
1500
|
+
@signal_listener("tabs_updated")
|
1501
|
+
def on_tabs_update(self, origin, *args):
|
1502
|
+
# Pass on to scene widgets
|
1503
|
+
self.scene.signal("tabs_updated")
|
1504
|
+
|
1505
|
+
@signal_listener("emphasized")
|
1506
|
+
def on_emphasized_elements_changed(self, origin, *args):
|
1507
|
+
self.scene.context.elements.set_start_time("Emphasis wxmscene")
|
1508
|
+
self.scene.signal("emphasized")
|
1509
|
+
self.laserpath_widget.clear_laserpath()
|
1510
|
+
self.request_refresh(origin)
|
1511
|
+
self.scene.context.elements.set_end_time("Emphasis wxmscene")
|
1512
|
+
|
1513
|
+
def request_refresh(self, *args):
|
1514
|
+
self.widget_scene.request_refresh(*args)
|
1515
|
+
|
1516
|
+
@signal_listener("altered")
|
1517
|
+
@signal_listener("modified")
|
1518
|
+
def on_element_modified(self, *args):
|
1519
|
+
self.scene.signal("modified")
|
1520
|
+
self.widget_scene.request_refresh(*args)
|
1521
|
+
|
1522
|
+
@signal_listener("linetext")
|
1523
|
+
def on_signal_linetext(self, origin, *args):
|
1524
|
+
if len(args) == 1:
|
1525
|
+
self.scene.signal("linetext", args[0])
|
1526
|
+
elif len(args) > 1:
|
1527
|
+
self.scene.signal("linetext", args[0], args[1])
|
1528
|
+
|
1529
|
+
@signal_listener("nodeedit")
|
1530
|
+
def on_signal_nodeedit(self, origin, *args):
|
1531
|
+
if len(args) == 1:
|
1532
|
+
self.scene.signal("nodeedit", args[0])
|
1533
|
+
elif len(args) > 1:
|
1534
|
+
self.scene.signal("nodeedit", args[0], args[1])
|
1535
|
+
|
1536
|
+
@signal_listener("element_added")
|
1537
|
+
@signal_listener("tree_changed")
|
1538
|
+
def on_elements_added(self, origin, nodes=None, *args):
|
1539
|
+
self.scene.signal("element_added", nodes)
|
1540
|
+
# There may be a smarter way to eliminate unnecessary rebuilds, but it's doing the job...
|
1541
|
+
# self.context.signal("rebuild_tree")
|
1542
|
+
self.context.signal("refresh_tree", nodes)
|
1543
|
+
self.widget_scene.request_refresh()
|
1544
|
+
|
1545
|
+
@signal_listener("rebuild_tree")
|
1546
|
+
def on_rebuild_tree(self, origin, *args):
|
1547
|
+
self.widget_scene._signal_widget(
|
1548
|
+
self.widget_scene.widget_root, "rebuild_tree", None
|
1549
|
+
)
|
1550
|
+
|
1551
|
+
@signal_listener("theme")
|
1552
|
+
def on_theme_change(self, origin, theme=None):
|
1553
|
+
self.scene.signal("theme", theme)
|
1554
|
+
self.request_refresh(origin)
|
1555
|
+
|
1556
|
+
@signal_listener("selstroke")
|
1557
|
+
def on_selstroke(self, origin, rgb, *args):
|
1558
|
+
# print (origin, rgb, args)
|
1559
|
+
if rgb[0] == 255 and rgb[1] == 255 and rgb[2] == 255:
|
1560
|
+
color = None
|
1561
|
+
else:
|
1562
|
+
color = Color(rgb[0], rgb[1], rgb[2])
|
1563
|
+
self.widget_scene.context.elements.default_stroke = color
|
1564
|
+
|
1565
|
+
@signal_listener("selfill")
|
1566
|
+
def on_selfill(self, origin, rgb, *args):
|
1567
|
+
# print (origin, rgb, args)
|
1568
|
+
if rgb[0] == 255 and rgb[1] == 255 and rgb[2] == 255:
|
1569
|
+
color = None
|
1570
|
+
else:
|
1571
|
+
color = Color(rgb[0], rgb[1], rgb[2])
|
1572
|
+
self.widget_scene.context.elements.default_fill = color
|
1573
|
+
|
1574
|
+
@signal_listener("scene_deactivated")
|
1575
|
+
def on_scene_deactived(self, origin, *args):
|
1576
|
+
if not self.context.setting(bool, "auto_tool_reset", True):
|
1577
|
+
return
|
1578
|
+
if self.active_tool != "none":
|
1579
|
+
self.context(".tool none\n")
|
1580
|
+
|
1581
|
+
def on_key_down(self, event):
|
1582
|
+
keyvalue = get_key_name(event)
|
1583
|
+
ignore = self.tool_active
|
1584
|
+
if self._keybind_channel:
|
1585
|
+
self._keybind_channel(f"Scene key_down: {keyvalue}.")
|
1586
|
+
if not ignore and self.context.bind.trigger(keyvalue):
|
1587
|
+
if self._keybind_channel:
|
1588
|
+
self._keybind_channel(f"Scene key_down: {keyvalue} executed.")
|
1589
|
+
else:
|
1590
|
+
if self._keybind_channel:
|
1591
|
+
if ignore:
|
1592
|
+
self._keybind_channel(
|
1593
|
+
f"Scene key_down: {keyvalue} was ignored as tool active."
|
1594
|
+
)
|
1595
|
+
else:
|
1596
|
+
self._keybind_channel(f"Scene key_down: {keyvalue} unfound.")
|
1597
|
+
event.Skip()
|
1598
|
+
|
1599
|
+
def on_key_up(self, event, log=True):
|
1600
|
+
keyvalue = get_key_name(event)
|
1601
|
+
ignore = self.tool_active
|
1602
|
+
if self._keybind_channel:
|
1603
|
+
self._keybind_channel(f"Scene key_up: {keyvalue}.")
|
1604
|
+
if not ignore and self.context.bind.untrigger(keyvalue):
|
1605
|
+
if self._keybind_channel:
|
1606
|
+
self._keybind_channel(f"Scene key_up: {keyvalue} executed.")
|
1607
|
+
else:
|
1608
|
+
if self._keybind_channel:
|
1609
|
+
if ignore:
|
1610
|
+
self._keybind_channel(
|
1611
|
+
f"Scene key_up: {keyvalue} was ignored as tool active."
|
1612
|
+
)
|
1613
|
+
else:
|
1614
|
+
self._keybind_channel(f"Scene key_up: {keyvalue} unfound.")
|
1615
|
+
event.Skip()
|
1616
|
+
|
1617
|
+
|
1618
|
+
class SceneWindow(MWindow):
|
1619
|
+
def __init__(self, *args, **kwds):
|
1620
|
+
super().__init__(1280, 800, *args, **kwds)
|
1621
|
+
self.panel = MeerK40tScenePanel(self, wx.ID_ANY, context=self.context)
|
1622
|
+
self.sizer.Add(self.panel, 1, wx.EXPAND, 0)
|
1623
|
+
self.add_module_delegate(self.panel)
|
1624
|
+
_icon = wx.NullIcon
|
1625
|
+
_icon.CopyFromBitmap(icon_meerk40t.GetBitmap())
|
1626
|
+
self.SetIcon(_icon)
|
1627
|
+
self.SetTitle(_("Scene"))
|
1628
|
+
self.Layout()
|
1629
|
+
self.restore_aspect()
|
1630
|
+
|
1631
|
+
def window_open(self):
|
1632
|
+
self.panel.pane_show()
|
1633
|
+
|
1634
|
+
def window_close(self):
|
1635
|
+
self.panel.pane_hide()
|