IS-Matrix-Forge 1.0.0.dev8__tar.gz → 1.0.0.dev27__tar.gz
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.
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/PKG-INFO +38 -1
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/README.md +40 -7
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/Untitled.ipynb +109 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/__init__.py +1 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/assets/__init__.py +1 -1
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/assets/digit_map.py +82 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/assets/font_map/base.py +289 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/assets/font_map/builders.py +132 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/assets/font_map/helpers.py +35 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/assets/font_map/models/__init__.py +17 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/assets/font_map/models/glyph.py +4 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/common/helpers/__init__.py +9 -2
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/common/helpers/errors.py +23 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/common/logging/__init__.py +17 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/common/logging/log_exceptions.py +79 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/designer_gui/__init__.py +1 -1
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/designer_gui/main_window/__init__.py +56 -11
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/designer_gui/main_window/layout/menu_bar.py +43 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/dev_tools/__init__.py +1 -1
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/Scripts/__init__.py +4 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/Scripts/battery_monitor.py +4 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/Scripts/identify_matrices.py +102 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/Scripts/install_presets/main.py +68 -16
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/Scripts/led_matrix/__init__.py +210 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/Scripts/led_matrix/arguments/__init__.py +108 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/Scripts/led_matrix/arguments/commands/__init__.py +17 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/Scripts/led_matrix/arguments/commands/display_text.py +37 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/Scripts/led_matrix/arguments/commands/identify_matrices.py +42 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/Scripts/led_matrix/arguments/commands/scroll_text.py +35 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/Scripts/led_matrix/guards.py +115 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/__init__.py +96 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/commands/__init__.py +1 -1
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/commands/map.py +1 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/constants.py +4 -1
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/controller/__init__.py +4 -15
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/controller/base.py +90 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/controller/components/__init__.py +17 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/controller/components/animation.py +200 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/controller/components/breather.py +67 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/controller/components/brightness/__init__.py +370 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/controller/components/brightness/helpers/__init__.py +12 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/controller/components/brightness/helpers/breather_killer.py +25 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/controller/components/brightness/helpers/easing.py +15 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/controller/components/brightness/helpers/fade_planner.py +25 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/controller/components/brightness/helpers/fade_spec.py +10 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/controller/components/brightness/helpers/levels.py +13 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/controller/components/brightness/helpers/percent.py +25 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/controller/components/brightness/helpers/safe_ops.py +31 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/controller/components/brightness/manager.py +425 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/controller/components/drawing.py +98 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/controller/components/example_template.py +45 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/controller/components/identify.py +46 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/controller/components/keep_alive.py +81 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/controller/controller.py +76 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/controller/helpers/__init__.py +67 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/controller/helpers/threading.py +45 -0
- is_matrix_forge-1.0.0.dev8/is_matrix_forge/led_matrix/controller/controller.py → is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/controller/legacy.py +189 -54
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/display/__init__.py +1 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/display/animations/__init__.py +19 -1
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/display/animations/animation.py +93 -64
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/display/animations/audio_visualizer.py +3 -3
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/display/animations/effects/__init__.py +1 -1
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/display/animations/font/__init__.py +1 -1
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/display/animations/font/font.py +2 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/display/animations/frame/base.py +452 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/display/animations/frame/helpers.py +15 -1
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/display/animations/text/__init__.py +5 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/display/animations/text/glyph_normalizer.py +110 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/display/animations/text_scroller.py +222 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/display/animations.zip +0 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/display/assets/__init__.py +2 -0
- {is_matrix_forge-1.0.0.dev8/is_matrix_forge/led_matrix → is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/display/assets}/fonts.py +3 -1
- {is_matrix_forge-1.0.0.dev8/is_matrix_forge/led_matrix/helpers/core → is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/display/effects}/__init__.py +1 -1
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/display/effects/breather.py +36 -14
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/display/grid/__init__.py +1 -1
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/display/grid/base.py +414 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/display/grid/composite/__init__.py +13 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/display/grid/composite/background.py +11 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/display/grid/composite/composite.py +91 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/display/grid/composite/foreground.py +53 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/display/grid/helpers.py +4 -1
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/display/grid/presets/__init__.py +1 -1
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/display/helpers/__init__.py +16 -4
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/display/patterns/built_in/constants.py +3 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/display/patterns/built_in/stencils/__init__.py +11 -8
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/display/scene/__init__.py +17 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/display/scene/errors.py +12 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/display/scene/scene.py +93 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/display/text/__init__.py +3 -1
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/display/text/scroller.py +0 -2
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/display/text/text.py +303 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/errors/base.py +5 -1
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/errors/composite_grid.py +1 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/errors/matrix.py +5 -1
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/hardware.py +68 -7
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/helpers/__init__.py +18 -2
- is_matrix_forge-1.0.0.dev8/is_matrix_forge/led_matrix/helpers/device.py → is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/helpers/device/__init__.py +28 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/helpers/device/bootloader/__init__.py +47 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/helpers/device/bootloader/constants.py +3 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/helpers/device/bootloader/unix.py +33 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/helpers/device/bootloader/win.py +44 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/led_matrix/is_matrix_forge.led_matrix.display.zip +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/tools/__init__.py +1 -1
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/utils/__init__.py +1 -1
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/log_engine.py +44 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/monitor/gui/layout/__init__.py +1 -1
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/progress.py +449 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/scripts/__init__.py +0 -0
- is_matrix_forge-1.0.0.dev27/is_matrix_forge/scripts/preset_installer.py +18 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/pyproject.toml +12 -1
- is_matrix_forge-1.0.0.dev8/is_matrix_forge/__init__.py +0 -8
- is_matrix_forge-1.0.0.dev8/is_matrix_forge/assets/font_map.py +0 -119
- is_matrix_forge-1.0.0.dev8/is_matrix_forge/led_matrix/Scripts/__init__.py +0 -4
- is_matrix_forge-1.0.0.dev8/is_matrix_forge/led_matrix/Scripts/identify_matrices.py +0 -228
- is_matrix_forge-1.0.0.dev8/is_matrix_forge/led_matrix/__init__.py +0 -58
- is_matrix_forge-1.0.0.dev8/is_matrix_forge/led_matrix/controller/helpers/__init__.py +0 -7
- is_matrix_forge-1.0.0.dev8/is_matrix_forge/led_matrix/controller/helpers/threading.py +0 -41
- is_matrix_forge-1.0.0.dev8/is_matrix_forge/led_matrix/display/__init__.py +0 -13
- is_matrix_forge-1.0.0.dev8/is_matrix_forge/led_matrix/display/animations/font/font.py +0 -4
- is_matrix_forge-1.0.0.dev8/is_matrix_forge/led_matrix/display/animations/frame/base.py +0 -245
- is_matrix_forge-1.0.0.dev8/is_matrix_forge/led_matrix/display/animations/text_scroller.py +0 -104
- is_matrix_forge-1.0.0.dev8/is_matrix_forge/led_matrix/display/effects/__init__.py +0 -17
- is_matrix_forge-1.0.0.dev8/is_matrix_forge/led_matrix/display/grid/grid.py +0 -243
- is_matrix_forge-1.0.0.dev8/is_matrix_forge/led_matrix/helpers/core/lazy_mod_load.py +0 -84
- is_matrix_forge-1.0.0.dev8/is_matrix_forge/led_matrix/helpers/stream/__init__.py +0 -70
- is_matrix_forge-1.0.0.dev8/is_matrix_forge/led_matrix/helpers/stream/errors.py +0 -17
- is_matrix_forge-1.0.0.dev8/is_matrix_forge/led_matrix/led_matrix.py +0 -25
- is_matrix_forge-1.0.0.dev8/is_matrix_forge/log_engine.py +0 -25
- is_matrix_forge-1.0.0.dev8/is_matrix_forge/progress.py +0 -99
- is_matrix_forge-1.0.0.dev8/is_matrix_forge/scripts/preset_installer.py +0 -184
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/LICENSE.md +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/assets/audio/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/assets/audio/files/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/assets/audio/files/plugged.wav +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/assets/audio/files/unplugged.wav +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/assets/char_map.json +0 -0
- /is_matrix_forge-1.0.0.dev8/is_matrix_forge/led_matrix/display/patterns/built_in/constants.py → /is_matrix_forge-1.0.0.dev27/is_matrix_forge/assets/font_map/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/common/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/common/decorators/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/common/decorators/freeze_setter.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/common/dirs.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/common/helpers/github_api.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/designer_gui/main_window/layout/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/designer_gui/main_window/layout/button_grid/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/designer_gui/main_window/layout/button_grid/column.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/designer_gui/main_window/layout/button_grid/grid.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/designer_gui/main_window/streamlit_app.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/dev_tools/debug.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/dev_tools/presets.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/inputmodule/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/inputmodule/b1display.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/inputmodule/c1minimal.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/inputmodule/font.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/inputmodule/helpers/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/inputmodule/ledmatrix.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/Scripts/install_presets/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/Scripts/install_presets/arguments.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/Scripts/pixel_grid.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/controller/multiton.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/controller/threaded.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/display/animations/errors.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/display/animations/font/map_builder.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/display/animations/frame/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/display/animations/keep_awake.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/display/animations/plugged.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/display/effects/fade.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/display/effects/scroller/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/display/effects/scroller/base.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/display/effects/scroller/helpers.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/display/grid/presets/manifest.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/display/helpers/columns.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/display/media.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/display/patterns/built_in/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/display/patterns/built_in/commands.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/display/patterns/built_in/stencils/res.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/errors/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/errors/grid.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/errors/misc.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/helpers/status_handler.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/status.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/led_matrix/tools/identify.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/monitor/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/monitor/errors.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/monitor/events.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/monitor/gui/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/monitor/gui/errors.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/monitor/gui/event/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/monitor/gui/event/collection.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/monitor/gui/event/errors.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/monitor/gui/event/event.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/monitor/gui/layout/base.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/monitor/gui/metaclasses/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/monitor/gui/windows/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/monitor/gui/windows/base.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/monitor/gui/windows/main/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/monitor/gui/windows/main/layout.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/monitor/helpers.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/monitor/monitor.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/notify/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/notify/sounds/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/notify/sounds/base.py +0 -0
- /is_matrix_forge-1.0.0.dev8/is_matrix_forge/scripts/__init__.py → /is_matrix_forge-1.0.0.dev27/is_matrix_forge/scripts/led-matrix.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/serial_com/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/serial_com/base/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/serial_com/base/answer.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/serial_com/base/message.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/serial_com/base/request.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/serial_com/exchange.py +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/presets/blank.json +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/presets/manifest.json +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/presets/shock_face.json +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/presets/test1.json +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/presets/test2.json +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/presets/test3.json +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/presets/test4.json +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/presets/test5.json +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/presets/test6.json +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/presets/test7.json +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/presets/x_animation II.json +0 -0
- {is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/presets/x_animation.json +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: IS-Matrix-Forge
|
|
3
|
-
Version: 1.0.0.
|
|
3
|
+
Version: 1.0.0.dev27
|
|
4
4
|
Summary:
|
|
5
5
|
License: MIT
|
|
6
6
|
Keywords: led,matrix,framework,hardware
|
|
@@ -19,12 +19,16 @@ Requires-Dist: easy-exit-calls (>=1.0.0.dev1,<2.0.0)
|
|
|
19
19
|
Requires-Dist: imapclient (==3.0.1)
|
|
20
20
|
Requires-Dist: inspy-logger (>=3.2.3,<4.0.0)
|
|
21
21
|
Requires-Dist: inspyre-toolbox (>=1.6.0.dev23)
|
|
22
|
+
Requires-Dist: ipywidgets (==8.1.7)
|
|
23
|
+
Requires-Dist: notebook (>=7.4.4,<8.0.0)
|
|
22
24
|
Requires-Dist: opencv-python (>=4.11.0.86,<5.0.0.0)
|
|
23
25
|
Requires-Dist: pillow (>=11.2.1,<12.0.0)
|
|
26
|
+
Requires-Dist: psutil (==6.1.1)
|
|
24
27
|
Requires-Dist: pyserial (>=3.5,<4.0)
|
|
25
28
|
Requires-Dist: pysimplegui-4-foss (==4.60.4.1)
|
|
26
29
|
Requires-Dist: pysimpleguiweb (==0.39.0)
|
|
27
30
|
Requires-Dist: requests (>=2.32.4,<3.0.0)
|
|
31
|
+
Requires-Dist: wmi (>=1.5.1,<2.0.0) ; sys_platform == "win32"
|
|
28
32
|
Project-URL: Homepage, https://github.com/Inspyre-Softworks/IS-Matrix-Forge
|
|
29
33
|
Project-URL: Repository, https://github.com/Inspyre-Softworks/IS-Matrix-Forge
|
|
30
34
|
Description-Content-Type: text/markdown
|
|
@@ -132,6 +136,26 @@ ctrl = LEDMatrixController(DEVICES[0])
|
|
|
132
136
|
ctrl.scroll_text("Hello World!", loop=False)
|
|
133
137
|
```
|
|
134
138
|
|
|
139
|
+
## Controller Architecture
|
|
140
|
+
|
|
141
|
+
- Composition is implemented via multiple mixins that all use cooperative
|
|
142
|
+
initialization with `super()`.
|
|
143
|
+
- MRO ordering ensures safe access patterns during `__init__`:
|
|
144
|
+
- `DeviceBase` initializes early so mixins can use `self.device`.
|
|
145
|
+
- `BrightnessManager` precedes `BreatherManager` because the breather inspects
|
|
146
|
+
brightness at init time.
|
|
147
|
+
- `BreatherManager` precedes `IdentifyManager` because `IdentifyManager` may
|
|
148
|
+
call `@synchronized` methods in `__init__` that rely on a breather pause context.
|
|
149
|
+
- `Loggable` is placed last so the cooperative chain can pass `logger=` safely.
|
|
150
|
+
- Thread safety: pass `thread_safe=True` to enable an internal `RLock` used by
|
|
151
|
+
the `@synchronized` decorator for device operations.
|
|
152
|
+
- Logging: integrates with InspyLogger when available and falls back to a simple
|
|
153
|
+
logger; the controller passes `parent_log_device` through the cooperative chain
|
|
154
|
+
and the fallback stub supports it.
|
|
155
|
+
|
|
156
|
+
MRO diagram (left → right, init order)
|
|
157
|
+
`DeviceBase → KeepAliveManager → AnimationManager → DrawingManager → BrightnessManager → BreatherManager → IdentifyManager → Loggable`
|
|
158
|
+
|
|
135
159
|
### Progress Bars
|
|
136
160
|
|
|
137
161
|
```python
|
|
@@ -184,6 +208,19 @@ run_power_monitor(device)
|
|
|
184
208
|
Contributions are welcome! If you have ideas or improvements for Matrix Forge,
|
|
185
209
|
feel free to open an issue or submit a pull request.
|
|
186
210
|
|
|
211
|
+
- See docs/contributing-mixins.md for guidance on authoring new controller mixins
|
|
212
|
+
using cooperative initialization and the `@synchronized` decorator.
|
|
213
|
+
A minimal reference mixin is available at
|
|
214
|
+
`is_matrix_forge/led_matrix/controller/components/example_template.py`.
|
|
215
|
+
|
|
216
|
+
Quick checklist for a new controller mixin
|
|
217
|
+
- Create `is_matrix_forge/led_matrix/controller/components/<name>.py` with `ClassNameManager`.
|
|
218
|
+
- In `__init__(...)`, accept keyword-only args and call `super().__init__(**kwargs)`.
|
|
219
|
+
- Avoid IO-heavy work in `__init__`; use `@synchronized` for device methods.
|
|
220
|
+
- If calling synchronized methods in `__init__`, ensure MRO places you after `BreatherManager`.
|
|
221
|
+
- If adding to the main controller, place after `DeviceBase` and before `IdentifyManager`; consider dependencies.
|
|
222
|
+
- Provide docstrings, type hints, and a small usage example or test.
|
|
223
|
+
|
|
187
224
|
## License
|
|
188
225
|
|
|
189
226
|
This project is licensed under the MIT License - see the LICENSE.md file for details.
|
|
@@ -80,7 +80,7 @@ This project requires Python 3.12 or newer and the following dependencies:
|
|
|
80
80
|
pip install .
|
|
81
81
|
```
|
|
82
82
|
|
|
83
|
-
## Usage Examples
|
|
83
|
+
## Usage Examples
|
|
84
84
|
|
|
85
85
|
### Identify Connected Devices
|
|
86
86
|
|
|
@@ -98,8 +98,28 @@ from is_matrix_forge.led_matrix.controller.controller import LEDMatrixController
|
|
|
98
98
|
from is_matrix_forge.led_matrix.helpers.device import DEVICES
|
|
99
99
|
|
|
100
100
|
ctrl = LEDMatrixController(DEVICES[0])
|
|
101
|
-
ctrl.scroll_text("Hello World!", loop=False)
|
|
102
|
-
```
|
|
101
|
+
ctrl.scroll_text("Hello World!", loop=False)
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Controller Architecture
|
|
105
|
+
|
|
106
|
+
- Composition is implemented via multiple mixins that all use cooperative
|
|
107
|
+
initialization with `super()`.
|
|
108
|
+
- MRO ordering ensures safe access patterns during `__init__`:
|
|
109
|
+
- `DeviceBase` initializes early so mixins can use `self.device`.
|
|
110
|
+
- `BrightnessManager` precedes `BreatherManager` because the breather inspects
|
|
111
|
+
brightness at init time.
|
|
112
|
+
- `BreatherManager` precedes `IdentifyManager` because `IdentifyManager` may
|
|
113
|
+
call `@synchronized` methods in `__init__` that rely on a breather pause context.
|
|
114
|
+
- `Loggable` is placed last so the cooperative chain can pass `logger=` safely.
|
|
115
|
+
- Thread safety: pass `thread_safe=True` to enable an internal `RLock` used by
|
|
116
|
+
the `@synchronized` decorator for device operations.
|
|
117
|
+
- Logging: integrates with InspyLogger when available and falls back to a simple
|
|
118
|
+
logger; the controller passes `parent_log_device` through the cooperative chain
|
|
119
|
+
and the fallback stub supports it.
|
|
120
|
+
|
|
121
|
+
MRO diagram (left → right, init order)
|
|
122
|
+
`DeviceBase → KeepAliveManager → AnimationManager → DrawingManager → BrightnessManager → BreatherManager → IdentifyManager → Loggable`
|
|
103
123
|
|
|
104
124
|
### Progress Bars
|
|
105
125
|
|
|
@@ -148,10 +168,23 @@ run_power_monitor(device)
|
|
|
148
168
|
2. Check that the matrix dimensions match the expected 9x34 size.
|
|
149
169
|
3. Try clearing the matrix and restarting the application.
|
|
150
170
|
|
|
151
|
-
## Contributing
|
|
152
|
-
|
|
153
|
-
Contributions are welcome! If you have ideas or improvements for Matrix Forge,
|
|
154
|
-
feel free to open an issue or submit a pull request.
|
|
171
|
+
## Contributing
|
|
172
|
+
|
|
173
|
+
Contributions are welcome! If you have ideas or improvements for Matrix Forge,
|
|
174
|
+
feel free to open an issue or submit a pull request.
|
|
175
|
+
|
|
176
|
+
- See docs/contributing-mixins.md for guidance on authoring new controller mixins
|
|
177
|
+
using cooperative initialization and the `@synchronized` decorator.
|
|
178
|
+
A minimal reference mixin is available at
|
|
179
|
+
`is_matrix_forge/led_matrix/controller/components/example_template.py`.
|
|
180
|
+
|
|
181
|
+
Quick checklist for a new controller mixin
|
|
182
|
+
- Create `is_matrix_forge/led_matrix/controller/components/<name>.py` with `ClassNameManager`.
|
|
183
|
+
- In `__init__(...)`, accept keyword-only args and call `super().__init__(**kwargs)`.
|
|
184
|
+
- Avoid IO-heavy work in `__init__`; use `@synchronized` for device methods.
|
|
185
|
+
- If calling synchronized methods in `__init__`, ensure MRO places you after `BreatherManager`.
|
|
186
|
+
- If adding to the main controller, place after `DeviceBase` and before `IdentifyManager`; consider dependencies.
|
|
187
|
+
- Provide docstrings, type hints, and a small usage example or test.
|
|
155
188
|
|
|
156
189
|
## License
|
|
157
190
|
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cells": [
|
|
3
|
+
{
|
|
4
|
+
"cell_type": "code",
|
|
5
|
+
"execution_count": 5,
|
|
6
|
+
"id": "a6d553a0-fca1-411a-a7bd-cf15dce52e97",
|
|
7
|
+
"metadata": {},
|
|
8
|
+
"outputs": [
|
|
9
|
+
{
|
|
10
|
+
"data": {
|
|
11
|
+
"application/vnd.jupyter.widget-view+json": {
|
|
12
|
+
"model_id": "a9c234aa78a641018ba78e54e9a3755b",
|
|
13
|
+
"version_major": 2,
|
|
14
|
+
"version_minor": 0
|
|
15
|
+
},
|
|
16
|
+
"text/plain": [
|
|
17
|
+
"VBox(children=(Dropdown(description='Pick a pattern to render...', options=('All LEDs on', 'Gradient (0-13% Br…"
|
|
18
|
+
]
|
|
19
|
+
},
|
|
20
|
+
"metadata": {},
|
|
21
|
+
"output_type": "display_data"
|
|
22
|
+
}
|
|
23
|
+
],
|
|
24
|
+
"source": [
|
|
25
|
+
"from is_matrix_forge.led_matrix import get_controllers\n",
|
|
26
|
+
"import ipywidgets as widgets\n",
|
|
27
|
+
"CONTROLLERS = get_controllers(threaded = True)\n",
|
|
28
|
+
"PATTERNS = CONTROLLERS[0].built_in_pattern_names\n",
|
|
29
|
+
"\n",
|
|
30
|
+
"\n",
|
|
31
|
+
"class DropdownWithButton:\n",
|
|
32
|
+
" def __init__(self, options, description='Choose:', button_desc='Run', callback=None):\n",
|
|
33
|
+
" self.output = widgets.Output()\n",
|
|
34
|
+
" self.dropdown = widgets.Dropdown(\n",
|
|
35
|
+
" options=options, description=description, disabled=False\n",
|
|
36
|
+
" )\n",
|
|
37
|
+
" self.button = widgets.Button(\n",
|
|
38
|
+
" description=button_desc, disabled=True, button_style='primary'\n",
|
|
39
|
+
" )\n",
|
|
40
|
+
" self.callback = callback or self.default_callback\n",
|
|
41
|
+
"\n",
|
|
42
|
+
" # Set up observers\n",
|
|
43
|
+
" self.dropdown.observe(self._on_select, names='value')\n",
|
|
44
|
+
" self.button.on_click(self._on_click)\n",
|
|
45
|
+
"\n",
|
|
46
|
+
" # Layout\n",
|
|
47
|
+
" self.container = widgets.VBox([self.dropdown, self.button, self.output])\n",
|
|
48
|
+
" display(self.container)\n",
|
|
49
|
+
"\n",
|
|
50
|
+
" def _on_select(self, change):\n",
|
|
51
|
+
" self.button.disabled = False # Enable button once a selection is made\n",
|
|
52
|
+
"\n",
|
|
53
|
+
" def _on_click(self, b):\n",
|
|
54
|
+
" with self.output:\n",
|
|
55
|
+
" # Clear prior output\n",
|
|
56
|
+
" self.output.clear_output()\n",
|
|
57
|
+
" self.callback(self.dropdown.value)\n",
|
|
58
|
+
"\n",
|
|
59
|
+
" @staticmethod\n",
|
|
60
|
+
" def default_callback(value):\n",
|
|
61
|
+
" print(f\"You selected: {value}\")\n",
|
|
62
|
+
"\n",
|
|
63
|
+
"\n",
|
|
64
|
+
"\n",
|
|
65
|
+
"def render(selection):\n",
|
|
66
|
+
" CONTROLLERS[0].draw_pattern(selection)\n",
|
|
67
|
+
"\n",
|
|
68
|
+
"\n",
|
|
69
|
+
"\n",
|
|
70
|
+
"drp_bttn = DropdownWithButton(\n",
|
|
71
|
+
" options=PATTERNS,\n",
|
|
72
|
+
" description='Pick a pattern to render...',\n",
|
|
73
|
+
" button_desc='Render',\n",
|
|
74
|
+
" callback=render\n",
|
|
75
|
+
"\n",
|
|
76
|
+
")\n"
|
|
77
|
+
]
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"cell_type": "code",
|
|
81
|
+
"execution_count": null,
|
|
82
|
+
"id": "8533a241-ef3b-4a44-99cd-2e88cabb9fbb",
|
|
83
|
+
"metadata": {},
|
|
84
|
+
"outputs": [],
|
|
85
|
+
"source": []
|
|
86
|
+
}
|
|
87
|
+
],
|
|
88
|
+
"metadata": {
|
|
89
|
+
"kernelspec": {
|
|
90
|
+
"display_name": "Python 3 (ipykernel)",
|
|
91
|
+
"language": "python",
|
|
92
|
+
"name": "python3"
|
|
93
|
+
},
|
|
94
|
+
"language_info": {
|
|
95
|
+
"codemirror_mode": {
|
|
96
|
+
"name": "ipython",
|
|
97
|
+
"version": 3
|
|
98
|
+
},
|
|
99
|
+
"file_extension": ".py",
|
|
100
|
+
"mimetype": "text/x-python",
|
|
101
|
+
"name": "python",
|
|
102
|
+
"nbconvert_exporter": "python",
|
|
103
|
+
"pygments_lexer": "ipython3",
|
|
104
|
+
"version": "3.12.10"
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
"nbformat": 4,
|
|
108
|
+
"nbformat_minor": 5
|
|
109
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from is_matrix_forge.led_matrix.controller import get_controllers
|
{is_matrix_forge-1.0.0.dev8 → is_matrix_forge-1.0.0.dev27}/is_matrix_forge/assets/__init__.py
RENAMED
|
@@ -3,6 +3,6 @@ Author: Taylor B. tayjaybabee@gmail.com
|
|
|
3
3
|
Date: 2025-04-15 09:15:37
|
|
4
4
|
LastEditors: Taylor B. tayjaybabee@gmail.com
|
|
5
5
|
LastEditTime: 2025-04-15 09:24:40
|
|
6
|
-
FilePath: is_matrix_forge/assets/
|
|
6
|
+
FilePath: is_matrix_forge/assets/base.py
|
|
7
7
|
Description: 这是默认设置,可以在设置》工具》File Description中进行配置
|
|
8
8
|
"""
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Contains the pixel representation of the ld states within a 3x5 grid.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
DIGITS = {
|
|
7
|
+
"0": [
|
|
8
|
+
[1, 1, 1],
|
|
9
|
+
[1, 0, 1],
|
|
10
|
+
[1, 0, 1],
|
|
11
|
+
[1, 0, 1],
|
|
12
|
+
[1, 1, 1],
|
|
13
|
+
],
|
|
14
|
+
"1": [
|
|
15
|
+
[0, 1, 0],
|
|
16
|
+
[1, 1, 0],
|
|
17
|
+
[0, 1, 0],
|
|
18
|
+
[0, 1, 0],
|
|
19
|
+
[1, 1, 1],
|
|
20
|
+
],
|
|
21
|
+
"2": [
|
|
22
|
+
[1, 1, 1],
|
|
23
|
+
[0, 0, 1],
|
|
24
|
+
[1, 1, 1],
|
|
25
|
+
[1, 0, 0],
|
|
26
|
+
[1, 1, 1],
|
|
27
|
+
],
|
|
28
|
+
"3": [
|
|
29
|
+
[1, 1, 1],
|
|
30
|
+
[0, 0, 1],
|
|
31
|
+
[1, 1, 1],
|
|
32
|
+
[0, 0, 1],
|
|
33
|
+
[1, 1, 1],
|
|
34
|
+
],
|
|
35
|
+
"4": [
|
|
36
|
+
[1, 0, 1],
|
|
37
|
+
[1, 0, 1],
|
|
38
|
+
[1, 1, 1],
|
|
39
|
+
[0, 0, 1],
|
|
40
|
+
[0, 0, 1],
|
|
41
|
+
],
|
|
42
|
+
"5": [
|
|
43
|
+
[1, 1, 1],
|
|
44
|
+
[1, 0, 0],
|
|
45
|
+
[1, 1, 1],
|
|
46
|
+
[0, 0, 1],
|
|
47
|
+
[1, 1, 1],
|
|
48
|
+
],
|
|
49
|
+
"6": [
|
|
50
|
+
[1, 1, 1],
|
|
51
|
+
[1, 0, 0],
|
|
52
|
+
[1, 1, 1],
|
|
53
|
+
[1, 0, 1],
|
|
54
|
+
[1, 1, 1],
|
|
55
|
+
],
|
|
56
|
+
"7": [
|
|
57
|
+
[1, 1, 1],
|
|
58
|
+
[0, 0, 1],
|
|
59
|
+
[0, 0, 1],
|
|
60
|
+
[0, 0, 1],
|
|
61
|
+
[0, 0, 1],
|
|
62
|
+
],
|
|
63
|
+
"8": [
|
|
64
|
+
[1, 1, 1],
|
|
65
|
+
[1, 0, 1],
|
|
66
|
+
[1, 1, 1],
|
|
67
|
+
[1, 0, 1],
|
|
68
|
+
[1, 1, 1],
|
|
69
|
+
],
|
|
70
|
+
"9": [
|
|
71
|
+
[1, 1, 1],
|
|
72
|
+
[1, 0, 1],
|
|
73
|
+
[1, 1, 1],
|
|
74
|
+
[0, 0, 1],
|
|
75
|
+
[1, 1, 1],
|
|
76
|
+
],
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
__all__ = [
|
|
81
|
+
'DIGITS'
|
|
82
|
+
]
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Author:
|
|
3
|
+
Inspyre Softworks
|
|
4
|
+
|
|
5
|
+
Project:
|
|
6
|
+
IS-Matrix-Forge
|
|
7
|
+
|
|
8
|
+
File:
|
|
9
|
+
${DIR_PATH}/${FILE_NAME}
|
|
10
|
+
|
|
11
|
+
Description:
|
|
12
|
+
FontMap: a dict-like facade over character/symbol glyph data with optional
|
|
13
|
+
case-insensitive lookups and a configurable fallback character.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
from collections.abc import Mapping, Iterator
|
|
19
|
+
from dataclasses import dataclass
|
|
20
|
+
from typing import Any, Dict, Iterable, Optional, Tuple, Callable
|
|
21
|
+
|
|
22
|
+
from inspyre_toolbox.syntactic_sweets.classes import validate_type
|
|
23
|
+
from .models.glyph import Glyph
|
|
24
|
+
from .helpers import load_builtin_char_map, get_ignore_case, has_key_ignore_case
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass(init=False, slots=True)
|
|
28
|
+
class FontMap(Mapping[str, Glyph]):
|
|
29
|
+
"""
|
|
30
|
+
FontMap allows lookup of character and symbol patterns as a dict-like mapping.
|
|
31
|
+
|
|
32
|
+
Parameters:
|
|
33
|
+
font_map:
|
|
34
|
+
Either:
|
|
35
|
+
- a *combined* map: { 'A': Glyph, '?': Glyph, ... }, or
|
|
36
|
+
- a *raw* map with top-level keys for characters/symbols:
|
|
37
|
+
{ 'characters': {...}, 'symbols': {...} }.
|
|
38
|
+
If None, falls back to `load_builtin_char_map()`.
|
|
39
|
+
characters_key:
|
|
40
|
+
Key name used for character definitions when a *raw* map is supplied.
|
|
41
|
+
symbols_key:
|
|
42
|
+
Key name used for symbol definitions when a *raw* map is supplied.
|
|
43
|
+
case_sensitive:
|
|
44
|
+
When False (default), keys are normalized to uppercase.
|
|
45
|
+
fallback_char:
|
|
46
|
+
Glyph to use when a key is missing. Defaults to '?'. If the glyph for '?' is
|
|
47
|
+
unavailable the implementation falls back to ' ' when present, otherwise a
|
|
48
|
+
:class:`ValueError` is raised requesting an explicit fallback.
|
|
49
|
+
|
|
50
|
+
Properties:
|
|
51
|
+
is_case_sensitive (bool): Current case-sensitivity flag.
|
|
52
|
+
fallback_char (str): Current fallback character.
|
|
53
|
+
characters (list[str]): Keys in the character sub-map (if available).
|
|
54
|
+
symbols (list[str]): Keys in the symbol sub-map (if available).
|
|
55
|
+
character_map (dict[str, Glyph]): Raw character map (best-effort).
|
|
56
|
+
symbol_map (dict[str, Glyph]): Raw symbol map (best-effort).
|
|
57
|
+
|
|
58
|
+
Methods:
|
|
59
|
+
lookup(key: str, kind: Optional[str] = None) -> Glyph
|
|
60
|
+
Look up a glyph, optionally forcing 'character' or 'symbol'.
|
|
61
|
+
reload(font_map: dict) -> None
|
|
62
|
+
Replace the underlying map and rebuild indexes.
|
|
63
|
+
|
|
64
|
+
Raises:
|
|
65
|
+
ValueError:
|
|
66
|
+
- If `fallback_char` is not a single character.
|
|
67
|
+
Example Usage:
|
|
68
|
+
fm = FontMap() # load built-ins
|
|
69
|
+
g_q = fm.get('?') # dict-like get
|
|
70
|
+
g_a = fm['A'] # Mapping access (uses fallback if missing)
|
|
71
|
+
fm.is_case_sensitive = True # switch mode and reindex
|
|
72
|
+
fm.fallback_char = ' ' # change fallback
|
|
73
|
+
g = fm.lookup('→', kind='symbol') # force symbol map
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
_glyphs: Dict[str, Glyph]
|
|
77
|
+
_raw_map: Optional[Dict[str, Dict[str, Glyph]]]
|
|
78
|
+
_characters_key: str
|
|
79
|
+
_symbols_key: str
|
|
80
|
+
_case_sensitive: bool
|
|
81
|
+
_fallback_char: str
|
|
82
|
+
|
|
83
|
+
DEFAULT_FALLBACK_CHAR: str = '?'
|
|
84
|
+
|
|
85
|
+
def __init__(
|
|
86
|
+
self,
|
|
87
|
+
font_map: Optional[Dict[str, Any]] = None,
|
|
88
|
+
*,
|
|
89
|
+
characters_key: str = 'characters',
|
|
90
|
+
symbols_key: str = 'symbols',
|
|
91
|
+
case_sensitive: bool = False,
|
|
92
|
+
fallback_char: Optional[str] = None
|
|
93
|
+
) -> None:
|
|
94
|
+
self._characters_key = characters_key
|
|
95
|
+
self._symbols_key = symbols_key
|
|
96
|
+
self._case_sensitive = case_sensitive
|
|
97
|
+
self._fallback_char = fallback_char or '?'
|
|
98
|
+
self._raw_map = None
|
|
99
|
+
self._glyphs = {}
|
|
100
|
+
|
|
101
|
+
# Load data
|
|
102
|
+
if font_map is None:
|
|
103
|
+
# Prefer helper: expected to return a combined {str: Glyph} mapping.
|
|
104
|
+
data = load_builtin_char_map()
|
|
105
|
+
self._ingest_unknown_map(data)
|
|
106
|
+
else:
|
|
107
|
+
self._ingest_unknown_map(font_map)
|
|
108
|
+
|
|
109
|
+
self._validate_fallback()
|
|
110
|
+
|
|
111
|
+
# ---------- ingestion / normalization ----------
|
|
112
|
+
|
|
113
|
+
def _looks_like_raw_map(self, data: Dict[str, Any]) -> bool:
|
|
114
|
+
return (
|
|
115
|
+
isinstance(data, dict)
|
|
116
|
+
and (has_key_ignore_case(data, self._characters_key) or has_key_ignore_case(data, self._symbols_key))
|
|
117
|
+
and isinstance(get_ignore_case(data, self._characters_key, {}), dict)
|
|
118
|
+
and isinstance(get_ignore_case(data, self._symbols_key, {}), dict)
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
def _ingest_unknown_map(self, data: Dict[str, Any]) -> None:
|
|
122
|
+
if self._looks_like_raw_map(data):
|
|
123
|
+
chars = dict(get_ignore_case(data, self._characters_key, {}) or {})
|
|
124
|
+
syms = dict(get_ignore_case(data, self._symbols_key, {}) or {})
|
|
125
|
+
self._raw_map = {'characters': chars, 'symbols': syms}
|
|
126
|
+
self._glyphs = {}
|
|
127
|
+
self._merge_into_glyphs(chars)
|
|
128
|
+
self._merge_into_glyphs(syms)
|
|
129
|
+
else:
|
|
130
|
+
self._raw_map = None
|
|
131
|
+
self._ingest_combined_map(data) # treat as already-flat mapping
|
|
132
|
+
|
|
133
|
+
def _ingest_combined_map(self, combined: Dict[str, Glyph]) -> None:
|
|
134
|
+
self._raw_map = None
|
|
135
|
+
self._glyphs = {}
|
|
136
|
+
self._merge_into_glyphs(combined)
|
|
137
|
+
|
|
138
|
+
def _merge_into_glyphs(self, mapping: Dict[str, Glyph]) -> None:
|
|
139
|
+
if not mapping:
|
|
140
|
+
return
|
|
141
|
+
normalise: Callable[[str], str] = str if self._case_sensitive else lambda key: str(key).upper()
|
|
142
|
+
for k, v in mapping.items():
|
|
143
|
+
self._glyphs[normalise(k)] = v
|
|
144
|
+
|
|
145
|
+
def _normalize_key(self, key: str) -> str:
|
|
146
|
+
return key if self._case_sensitive else key.upper()
|
|
147
|
+
|
|
148
|
+
def _validate_fallback(self) -> None:
|
|
149
|
+
# Ensure fallback exists; prefer '?' then space, otherwise require an explicit fallback.
|
|
150
|
+
normalized = self._normalize_key(self._fallback_char)
|
|
151
|
+
if normalized in self._glyphs:
|
|
152
|
+
return
|
|
153
|
+
|
|
154
|
+
space_key = self._normalize_key(' ')
|
|
155
|
+
if space_key in self._glyphs:
|
|
156
|
+
self._fallback_char = ' '
|
|
157
|
+
return
|
|
158
|
+
|
|
159
|
+
if not self._glyphs:
|
|
160
|
+
raise ValueError('font_map must contain at least one glyph definition')
|
|
161
|
+
|
|
162
|
+
raise ValueError(
|
|
163
|
+
"Fallback character is missing from the font_map and no space fallback is available. "
|
|
164
|
+
"Provide a valid fallback_char or include an appropriate glyph."
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
# ---------- Mapping protocol ----------
|
|
168
|
+
|
|
169
|
+
def __getitem__(self, key: str) -> Glyph:
|
|
170
|
+
try:
|
|
171
|
+
return self._glyphs[self._normalize_key(key)]
|
|
172
|
+
except KeyError:
|
|
173
|
+
return self._glyphs[self._normalize_key(self._fallback_char)]
|
|
174
|
+
|
|
175
|
+
def __iter__(self) -> Iterator[str]:
|
|
176
|
+
return iter(self._glyphs)
|
|
177
|
+
|
|
178
|
+
def __len__(self) -> int:
|
|
179
|
+
return len(self._glyphs)
|
|
180
|
+
|
|
181
|
+
# dict-like conveniences
|
|
182
|
+
def get(self, key: str, default: Optional[Glyph] = None) -> Optional[Glyph]: # type: ignore[override]
|
|
183
|
+
return self._glyphs.get(self._normalize_key(key), default)
|
|
184
|
+
|
|
185
|
+
def keys(self) -> Iterable[str]: # type: ignore[override]
|
|
186
|
+
return self._glyphs.keys()
|
|
187
|
+
|
|
188
|
+
def values(self) -> Iterable[Glyph]: # type: ignore[override]
|
|
189
|
+
return self._glyphs.values()
|
|
190
|
+
|
|
191
|
+
def items(self) -> Iterable[tuple[str, Glyph]]: # type: ignore[override]
|
|
192
|
+
return self._glyphs.items()
|
|
193
|
+
|
|
194
|
+
def __contains__(self, key: object) -> bool:
|
|
195
|
+
return isinstance(key, str) and self._normalize_key(key) in self._glyphs
|
|
196
|
+
|
|
197
|
+
# ---------- Higher-level API ----------
|
|
198
|
+
|
|
199
|
+
def lookup(self, key: str, kind: Optional[str] = None) -> Glyph:
|
|
200
|
+
"""
|
|
201
|
+
Lookup a character or symbol by key. If `kind` is provided, force that sub-map.
|
|
202
|
+
|
|
203
|
+
Parameters:
|
|
204
|
+
key:
|
|
205
|
+
The character/symbol to look up.
|
|
206
|
+
kind:
|
|
207
|
+
'character'/'char' or 'symbol' to force the specific sub-map. If not provided
|
|
208
|
+
or the raw segmentation is unavailable, falls back to the combined map.
|
|
209
|
+
|
|
210
|
+
Returns:
|
|
211
|
+
Glyph for `key`, or the configured fallback glyph if not present.
|
|
212
|
+
"""
|
|
213
|
+
if kind is None or self._raw_map is None:
|
|
214
|
+
return self[key]
|
|
215
|
+
|
|
216
|
+
k = self._normalize_key(key)
|
|
217
|
+
if kind.lower().startswith('sym'):
|
|
218
|
+
return self._lookup_in(self._raw_map['symbols'], k)
|
|
219
|
+
if kind.lower().startswith('char'):
|
|
220
|
+
return self._lookup_in(self._raw_map['characters'], k)
|
|
221
|
+
return self[key]
|
|
222
|
+
|
|
223
|
+
def _lookup_in(self, mapping: Dict[str, Glyph], key: str) -> Glyph:
|
|
224
|
+
if not self._case_sensitive:
|
|
225
|
+
mapping = {str(k).upper(): v for k, v in mapping.items()}
|
|
226
|
+
return mapping.get(key, self._glyphs[self._normalize_key(self._fallback_char)])
|
|
227
|
+
|
|
228
|
+
def reload(self, font_map: Dict[str, Any]) -> None:
|
|
229
|
+
"""
|
|
230
|
+
Reload the font map (raw or combined) and rebuild indexes.
|
|
231
|
+
"""
|
|
232
|
+
self._ingest_unknown_map(font_map)
|
|
233
|
+
self._validate_fallback()
|
|
234
|
+
|
|
235
|
+
# ---------- Properties ----------
|
|
236
|
+
|
|
237
|
+
@property
|
|
238
|
+
def character_map(self) -> Dict[str, Glyph]:
|
|
239
|
+
if self._raw_map is None:
|
|
240
|
+
return dict(self._glyphs) # best-effort: treat all as characters
|
|
241
|
+
return dict(self._raw_map['characters'])
|
|
242
|
+
|
|
243
|
+
@property
|
|
244
|
+
def symbol_map(self) -> Dict[str, Glyph]:
|
|
245
|
+
return {} if self._raw_map is None else dict(self._raw_map['symbols'])
|
|
246
|
+
|
|
247
|
+
@property
|
|
248
|
+
def characters(self) -> list[str]:
|
|
249
|
+
return list(self.character_map.keys())
|
|
250
|
+
|
|
251
|
+
@property
|
|
252
|
+
def symbols(self) -> list[str]:
|
|
253
|
+
return list(self.symbol_map.keys())
|
|
254
|
+
|
|
255
|
+
@property
|
|
256
|
+
def fallback_char(self) -> str:
|
|
257
|
+
return self._fallback_char
|
|
258
|
+
|
|
259
|
+
@fallback_char.setter
|
|
260
|
+
def fallback_char(self, new: str) -> None:
|
|
261
|
+
if not isinstance(new, str) or len(new) != 1:
|
|
262
|
+
raise ValueError('fallback_char must be a single character string')
|
|
263
|
+
self._fallback_char = new
|
|
264
|
+
self._validate_fallback()
|
|
265
|
+
|
|
266
|
+
@property
|
|
267
|
+
def is_case_sensitive(self) -> bool:
|
|
268
|
+
return self._case_sensitive
|
|
269
|
+
|
|
270
|
+
@validate_type(bool)
|
|
271
|
+
@is_case_sensitive.setter
|
|
272
|
+
def is_case_sensitive(self, new: bool) -> None:
|
|
273
|
+
if new is self._case_sensitive:
|
|
274
|
+
return
|
|
275
|
+
# Rebuild normalized key index under the new rule.
|
|
276
|
+
self._case_sensitive = new
|
|
277
|
+
existing = dict(self._glyphs)
|
|
278
|
+
self._glyphs.clear()
|
|
279
|
+
self._merge_into_glyphs(existing)
|
|
280
|
+
self._validate_fallback()
|
|
281
|
+
|
|
282
|
+
def __repr__(self) -> str:
|
|
283
|
+
return (
|
|
284
|
+
f'{self.__class__.__name__}('
|
|
285
|
+
f'case_sensitive={self._case_sensitive}, '
|
|
286
|
+
f'fallback_char={self._fallback_char!r}, '
|
|
287
|
+
f'count={len(self)}'
|
|
288
|
+
f')'
|
|
289
|
+
)
|