luvatrix 0.2.1__tar.gz → 0.2.2__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.
- {luvatrix-0.2.1/luvatrix.egg-info → luvatrix-0.2.2}/PKG-INFO +1 -1
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix/app.py +7 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2/luvatrix.egg-info}/PKG-INFO +1 -1
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix.egg-info/SOURCES.txt +1 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/__init__.py +1 -1
- luvatrix-0.2.2/luvatrix_core/core/interaction_work.py +162 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/android/runner.py +32 -4
- {luvatrix-0.2.1 → luvatrix-0.2.2}/pyproject.toml +1 -1
- {luvatrix-0.2.1 → luvatrix-0.2.2}/LICENSE +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/MANIFEST.in +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/README.md +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix/__init__.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix/auth/__init__.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix/auth/calendar.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix/auth/google.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix/auth/sign_in.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix/auth/ui.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix.egg-info/dependency_links.txt +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix.egg-info/entry_points.txt +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix.egg-info/requires.txt +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix.egg-info/top_level.txt +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/accel.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/core/__init__.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/core/app_runtime.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/core/audit.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/core/coordinates.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/core/debug_capture.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/core/debug_menu.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/core/display_runtime.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/core/energy_safety.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/core/engine.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/core/events.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/core/frame_rate_controller.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/core/hdi_thread.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/core/process_runtime.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/core/process_sdk.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/core/protocol_governance.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/core/scene_display_runtime.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/core/scene_graph.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/core/scene_rasterizer.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/core/sensor_manager.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/core/ui_frame_renderer.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/core/unified_runtime.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/core/window_matrix.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/perf/copy_telemetry.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/__init__.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/android/__init__.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/android/camera_processing_contract.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/android/camera_style.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/android/hdi_source.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/android/scene_target.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/android/sensors.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/android/vulkan_target.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/frame_pipeline.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/ios/__init__.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/ios/hdi_source.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/ios/lifecycle.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/ios/metal_backend.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/ios/runner.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/ios/scene_target.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/ios/window_system.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/macos/__init__.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/macos/hdi_source.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/macos/iohid_source.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/macos/metal_backend.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/macos/metal_presenter.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/macos/metal_scene_target.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/macos/sensors.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/macos/vulkan_backend.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/macos/vulkan_presenter.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/macos/window_system.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/package_sync.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/vulkan_compat.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/vulkan_scaling.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/vulkan_setup.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/web/__init__.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/web/build.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/web/command_buffer.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/web/python_shim/luvatrix/__init__.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/web/python_shim/luvatrix/app.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/web/runtime_assets/index.html +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/web/runtime_assets/runtime/command-buffer.js +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/web/runtime_assets/runtime/input.js +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/web/runtime_assets/runtime/luvatrix-web.js +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/web/runtime_assets/runtime/package.json +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/web/runtime_assets/runtime/renderers.js +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/web/runtime_assets/runtime/spotify-bridge.js +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/web/server.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/web/websocket_target.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/render/__init__.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/render/framebuffer.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/render/svg.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/scaffold.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/targets/__init__.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/targets/base.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/targets/cpu_scene_target.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/targets/metal_target.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/targets/scene_target.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/targets/vulkan_target.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/targets/web_target.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/android/.gitignore +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/android/app/build.gradle.kts +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/android/app/src/main/AndroidManifest.xml +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/android/app/src/main/assets/luvatrix_bitmap_font.txt +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/android/app/src/main/assets/luvatrix_launch_config.json +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/android/app/src/main/assets/luvatrix_matrix_font_alpha.txt +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/android/app/src/main/cpp/CMakeLists.txt +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/android/app/src/main/cpp/luvatrix_camera_preview.frag +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/android/app/src/main/cpp/luvatrix_camera_preview_shaders.h +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/android/app/src/main/cpp/luvatrix_vulkan_renderer.cpp +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/android/app/src/main/java/com/luvatrix/app/CameraBridge.kt +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/android/app/src/main/java/com/luvatrix/app/LuvatrixVulkanView.kt +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/android/app/src/main/java/com/luvatrix/app/MainActivity.kt +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/android/app/src/main/java/com/luvatrix/app/NativeVulkan.kt +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/android/app/src/main/python/.gitignore +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/android/app/src/main/python/luvatrix_android_boot.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/android/app/src/main/python/luvatrix_launch_config.json +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/android/app/src/main/res/values/styles.xml +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/android/build.gradle.kts +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/android/gradle.properties +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/android/gradlew +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/android/scripts/emulator_acceptance.sh +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/android/scripts/sync_python_assets.sh +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/android/settings.gradle.kts +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/ios/Luvatrix/AppDelegate.swift +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/ios/Luvatrix/Assets.xcassets/AppIcon.appiconset/Contents.json +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/ios/Luvatrix/Assets.xcassets/AppIcon.appiconset/icon.png +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/ios/Luvatrix/Assets.xcassets/Contents.json +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/ios/Luvatrix/Info.plist +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/ios/Luvatrix/Luvatrix-Bridging-Header.h +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/ios/Luvatrix/Luvatrix.entitlements +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/ios/Luvatrix/PythonBridge.h +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/ios/Luvatrix/PythonBridge.m +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/ios/Luvatrix/main.swift +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/ios/project.yml +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/ios/scripts/setup_ios.sh +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/ui/__init__.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/ui/element.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/ui/page_loader.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_plot/__init__.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_plot/adapters/__init__.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_plot/adapters/normalize.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_plot/api.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_plot/compile/__init__.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_plot/compile/app_protocol.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_plot/display.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_plot/dynamic_axis.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_plot/errors.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_plot/figure.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_plot/live.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_plot/raster/__init__.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_plot/raster/canvas.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_plot/raster/draw_lines.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_plot/raster/draw_markers.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_plot/raster/draw_text.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_plot/raster/layers.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_plot/scales.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_plot/series.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_ui/__init__.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_ui/component_schema.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_ui/controls/__init__.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_ui/controls/button.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_ui/controls/interaction.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_ui/controls/stained_glass_button.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_ui/controls/svg_component.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_ui/controls/svg_renderer.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_ui/planes_protocol.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_ui/planes_runtime.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_ui/planes_v2_validator.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_ui/planning/__init__.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_ui/planning/agile_renderer.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_ui/planning/exporters.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_ui/planning/gantt_renderer.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_ui/planning/interaction.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_ui/planning/schema.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_ui/planning/validation.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_ui/style/__init__.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_ui/style/theme.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_ui/table/__init__.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_ui/table/component.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_ui/text/__init__.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_ui/text/component.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_ui/text/renderer.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_ui/text/wrapping.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_ui/ui_ir.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/main.py +0 -0
- {luvatrix-0.2.1 → luvatrix-0.2.2}/setup.cfg +0 -0
|
@@ -22,6 +22,7 @@ from luvatrix_core.core.app_runtime import (
|
|
|
22
22
|
ResolvedAppVariant,
|
|
23
23
|
)
|
|
24
24
|
from luvatrix_core.core.hdi_thread import HDIEvent, HDIThread
|
|
25
|
+
from luvatrix_core.core.interaction_work import InteractionAwareWorkScheduler
|
|
25
26
|
from luvatrix_core.core.sensor_manager import SensorManagerThread, SensorSample
|
|
26
27
|
from luvatrix_core.core.window_matrix import FullRewrite, WriteBatch, WindowMatrix
|
|
27
28
|
from luvatrix_core import accel
|
|
@@ -299,6 +300,11 @@ class SwipeMomentumController:
|
|
|
299
300
|
def dragging(self) -> bool:
|
|
300
301
|
return self._dragging
|
|
301
302
|
|
|
303
|
+
@property
|
|
304
|
+
def active(self) -> bool:
|
|
305
|
+
"""Whether a drag or post-release momentum is active."""
|
|
306
|
+
return self._dragging or self._velocity != 0.0
|
|
307
|
+
|
|
302
308
|
def reset(self) -> None:
|
|
303
309
|
self._touch_id = None
|
|
304
310
|
self._last_position = None
|
|
@@ -1856,6 +1862,7 @@ __all__ = [
|
|
|
1856
1862
|
"Display",
|
|
1857
1863
|
"InputManager",
|
|
1858
1864
|
"InputState",
|
|
1865
|
+
"InteractionAwareWorkScheduler",
|
|
1859
1866
|
"MatrixFrame",
|
|
1860
1867
|
"MissingOptionalDependencyError",
|
|
1861
1868
|
"ResolvedAppVariant",
|
|
@@ -31,6 +31,7 @@ luvatrix_core/core/engine.py
|
|
|
31
31
|
luvatrix_core/core/events.py
|
|
32
32
|
luvatrix_core/core/frame_rate_controller.py
|
|
33
33
|
luvatrix_core/core/hdi_thread.py
|
|
34
|
+
luvatrix_core/core/interaction_work.py
|
|
34
35
|
luvatrix_core/core/process_runtime.py
|
|
35
36
|
luvatrix_core/core/process_sdk.py
|
|
36
37
|
luvatrix_core/core/protocol_governance.py
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections import deque
|
|
4
|
+
from collections.abc import Callable, Hashable
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
import threading
|
|
7
|
+
import time
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass(frozen=True)
|
|
12
|
+
class _WorkItem:
|
|
13
|
+
key: Hashable
|
|
14
|
+
prepare: Callable[[], Any]
|
|
15
|
+
on_complete: Callable[[Any], None] | None
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class InteractionAwareWorkScheduler:
|
|
19
|
+
"""Run keyed preparation work only while user interaction is idle.
|
|
20
|
+
|
|
21
|
+
Work and callbacks execute sequentially on one daemon thread. Running work
|
|
22
|
+
is not preempted when interaction begins; the idle gate prevents queued
|
|
23
|
+
work from starting until ``interaction_active`` returns false.
|
|
24
|
+
|
|
25
|
+
Pair with ``SwipeMomentumController`` using
|
|
26
|
+
``interaction_active=lambda: swipe.active`` and call
|
|
27
|
+
:meth:`notify_interaction_state_changed` after controller updates to wake
|
|
28
|
+
queued work immediately when momentum stops.
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
def __init__(
|
|
32
|
+
self,
|
|
33
|
+
*,
|
|
34
|
+
interaction_active: Callable[[], bool],
|
|
35
|
+
request_render: Callable[[], None] | None = None,
|
|
36
|
+
on_error: Callable[[Hashable, Exception], None] | None = None,
|
|
37
|
+
idle_poll_interval: float = 1.0 / 120.0,
|
|
38
|
+
thread_name: str = "luvatrix-interaction-work",
|
|
39
|
+
) -> None:
|
|
40
|
+
self.interaction_active = interaction_active
|
|
41
|
+
self.request_render = request_render
|
|
42
|
+
self.on_error = on_error
|
|
43
|
+
self.idle_poll_interval = max(0.001, float(idle_poll_interval))
|
|
44
|
+
self.thread_name = str(thread_name)
|
|
45
|
+
self._condition = threading.Condition()
|
|
46
|
+
self._pending: deque[_WorkItem] = deque()
|
|
47
|
+
self._keys: set[Hashable] = set()
|
|
48
|
+
self._thread: threading.Thread | None = None
|
|
49
|
+
self._closed = False
|
|
50
|
+
|
|
51
|
+
@property
|
|
52
|
+
def pending_count(self) -> int:
|
|
53
|
+
with self._condition:
|
|
54
|
+
return len(self._keys)
|
|
55
|
+
|
|
56
|
+
def submit(
|
|
57
|
+
self,
|
|
58
|
+
key: Hashable,
|
|
59
|
+
prepare: Callable[[], Any],
|
|
60
|
+
*,
|
|
61
|
+
on_complete: Callable[[Any], None] | None = None,
|
|
62
|
+
) -> bool:
|
|
63
|
+
"""Queue work unless the key is already queued or running."""
|
|
64
|
+
with self._condition:
|
|
65
|
+
if self._closed:
|
|
66
|
+
raise RuntimeError("interaction-aware work scheduler is closed")
|
|
67
|
+
if key in self._keys:
|
|
68
|
+
return False
|
|
69
|
+
self._keys.add(key)
|
|
70
|
+
self._pending.append(_WorkItem(key, prepare, on_complete))
|
|
71
|
+
if self._thread is None:
|
|
72
|
+
self._thread = threading.Thread(
|
|
73
|
+
target=self._run,
|
|
74
|
+
name=self.thread_name,
|
|
75
|
+
daemon=True,
|
|
76
|
+
)
|
|
77
|
+
self._thread.start()
|
|
78
|
+
self._condition.notify_all()
|
|
79
|
+
return True
|
|
80
|
+
|
|
81
|
+
def notify_interaction_state_changed(self) -> None:
|
|
82
|
+
"""Wake idle-gated work after a controller state update."""
|
|
83
|
+
with self._condition:
|
|
84
|
+
self._condition.notify_all()
|
|
85
|
+
|
|
86
|
+
def wait_idle(self, timeout: float | None = None) -> bool:
|
|
87
|
+
"""Wait until queued/running work and its callbacks have completed."""
|
|
88
|
+
deadline = None if timeout is None else time.monotonic() + max(0.0, float(timeout))
|
|
89
|
+
with self._condition:
|
|
90
|
+
while self._keys:
|
|
91
|
+
if deadline is None:
|
|
92
|
+
self._condition.wait()
|
|
93
|
+
continue
|
|
94
|
+
remaining = deadline - time.monotonic()
|
|
95
|
+
if remaining <= 0.0:
|
|
96
|
+
return False
|
|
97
|
+
self._condition.wait(remaining)
|
|
98
|
+
return True
|
|
99
|
+
|
|
100
|
+
def close(self, *, wait: bool = False) -> None:
|
|
101
|
+
"""Cancel queued work and optionally wait for running work to finish."""
|
|
102
|
+
with self._condition:
|
|
103
|
+
self._closed = True
|
|
104
|
+
while self._pending:
|
|
105
|
+
self._keys.discard(self._pending.popleft().key)
|
|
106
|
+
thread = self._thread
|
|
107
|
+
self._condition.notify_all()
|
|
108
|
+
if wait and thread is not None and thread is not threading.current_thread():
|
|
109
|
+
thread.join()
|
|
110
|
+
|
|
111
|
+
def _run(self) -> None:
|
|
112
|
+
while True:
|
|
113
|
+
with self._condition:
|
|
114
|
+
while not self._closed and not self._pending:
|
|
115
|
+
self._condition.wait()
|
|
116
|
+
if self._closed:
|
|
117
|
+
return
|
|
118
|
+
pending_key = self._pending[0].key
|
|
119
|
+
|
|
120
|
+
try:
|
|
121
|
+
interaction_active = bool(self.interaction_active())
|
|
122
|
+
except Exception as exc:
|
|
123
|
+
self._report_error(pending_key, exc)
|
|
124
|
+
interaction_active = False
|
|
125
|
+
|
|
126
|
+
with self._condition:
|
|
127
|
+
if self._closed:
|
|
128
|
+
return
|
|
129
|
+
if not self._pending:
|
|
130
|
+
continue
|
|
131
|
+
if interaction_active:
|
|
132
|
+
self._condition.wait(self.idle_poll_interval)
|
|
133
|
+
continue
|
|
134
|
+
item = self._pending.popleft()
|
|
135
|
+
|
|
136
|
+
try:
|
|
137
|
+
value = item.prepare()
|
|
138
|
+
except Exception as exc:
|
|
139
|
+
self._report_error(item.key, exc)
|
|
140
|
+
else:
|
|
141
|
+
if item.on_complete is not None:
|
|
142
|
+
try:
|
|
143
|
+
item.on_complete(value)
|
|
144
|
+
except Exception as exc:
|
|
145
|
+
self._report_error(item.key, exc)
|
|
146
|
+
try:
|
|
147
|
+
if self.request_render is not None:
|
|
148
|
+
self.request_render()
|
|
149
|
+
except Exception as exc:
|
|
150
|
+
self._report_error(item.key, exc)
|
|
151
|
+
finally:
|
|
152
|
+
with self._condition:
|
|
153
|
+
self._keys.discard(item.key)
|
|
154
|
+
self._condition.notify_all()
|
|
155
|
+
|
|
156
|
+
def _report_error(self, key: Hashable, error: Exception) -> None:
|
|
157
|
+
if self.on_error is None:
|
|
158
|
+
return
|
|
159
|
+
try:
|
|
160
|
+
self.on_error(key, error)
|
|
161
|
+
except Exception:
|
|
162
|
+
return
|
|
@@ -332,14 +332,17 @@ def sync_android_python_assets(app_dir: Path, *, project_dir: Path) -> None:
|
|
|
332
332
|
|
|
333
333
|
def _android_python_packages_for_app(app_dir: Path, *, exclude_dirs: Iterable[Path] = ()) -> tuple[str, ...]:
|
|
334
334
|
packages = ["luvatrix", "luvatrix_core"]
|
|
335
|
-
|
|
335
|
+
imported_modules = _imported_modules_for_app(app_dir, exclude_dirs=exclude_dirs)
|
|
336
|
+
imports = {module.split(".", 1)[0] for module in imported_modules}
|
|
337
|
+
for module in imported_modules:
|
|
338
|
+
imports.update(_first_party_module_import_roots(module))
|
|
336
339
|
for optional_pkg in ("luvatrix_ui", "luvatrix_plot"):
|
|
337
340
|
if optional_pkg in imports:
|
|
338
341
|
packages.append(optional_pkg)
|
|
339
342
|
return tuple(packages)
|
|
340
343
|
|
|
341
344
|
|
|
342
|
-
def
|
|
345
|
+
def _imported_modules_for_app(app_dir: Path, *, exclude_dirs: Iterable[Path] = ()) -> set[str]:
|
|
343
346
|
imports: set[str] = set()
|
|
344
347
|
excluded = tuple(path.resolve() for path in exclude_dirs)
|
|
345
348
|
for path in app_dir.rglob("*.py"):
|
|
@@ -355,12 +358,37 @@ def _top_level_imports_for_app(app_dir: Path, *, exclude_dirs: Iterable[Path] =
|
|
|
355
358
|
for node in ast.walk(tree):
|
|
356
359
|
if isinstance(node, ast.Import):
|
|
357
360
|
for alias in node.names:
|
|
358
|
-
imports.add(alias.name
|
|
361
|
+
imports.add(alias.name)
|
|
359
362
|
elif isinstance(node, ast.ImportFrom) and node.module:
|
|
360
|
-
imports.add(node.module
|
|
363
|
+
imports.add(node.module)
|
|
361
364
|
return imports
|
|
362
365
|
|
|
363
366
|
|
|
367
|
+
def _first_party_module_import_roots(module_name: str) -> set[str]:
|
|
368
|
+
package_name, _, relative_module = module_name.partition(".")
|
|
369
|
+
if package_name not in {"luvatrix", "luvatrix_core"}:
|
|
370
|
+
return set()
|
|
371
|
+
package_dir = _python_package_dir(package_name)
|
|
372
|
+
if relative_module:
|
|
373
|
+
module_path = package_dir.joinpath(*relative_module.split("."))
|
|
374
|
+
source_path = module_path.with_suffix(".py")
|
|
375
|
+
if not source_path.is_file():
|
|
376
|
+
source_path = module_path / "__init__.py"
|
|
377
|
+
else:
|
|
378
|
+
source_path = package_dir / "__init__.py"
|
|
379
|
+
try:
|
|
380
|
+
tree = ast.parse(source_path.read_text(encoding="utf-8"), filename=str(source_path))
|
|
381
|
+
except (OSError, SyntaxError):
|
|
382
|
+
return set()
|
|
383
|
+
roots: set[str] = set()
|
|
384
|
+
for node in ast.walk(tree):
|
|
385
|
+
if isinstance(node, ast.Import):
|
|
386
|
+
roots.update(alias.name.split(".", 1)[0] for alias in node.names)
|
|
387
|
+
elif isinstance(node, ast.ImportFrom) and node.module:
|
|
388
|
+
roots.add(node.module.split(".", 1)[0])
|
|
389
|
+
return roots
|
|
390
|
+
|
|
391
|
+
|
|
364
392
|
def _make_android_app_ignore(project_dir: Path):
|
|
365
393
|
pattern_ignore = shutil.ignore_patterns("__pycache__", "*.pyc", ".pytest_cache", ".luvatrix")
|
|
366
394
|
project = project_dir.resolve()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/android/camera_processing_contract.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/web/python_shim/luvatrix/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/web/runtime_assets/runtime/input.js
RENAMED
|
File without changes
|
{luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/web/runtime_assets/runtime/luvatrix-web.js
RENAMED
|
File without changes
|
{luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/web/runtime_assets/runtime/package.json
RENAMED
|
File without changes
|
{luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/platform/web/runtime_assets/runtime/renderers.js
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/android/app/build.gradle.kts
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/android/settings.gradle.kts
RENAMED
|
File without changes
|
{luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/ios/Luvatrix/AppDelegate.swift
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/ios/Luvatrix/Luvatrix.entitlements
RENAMED
|
File without changes
|
{luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/ios/Luvatrix/PythonBridge.h
RENAMED
|
File without changes
|
{luvatrix-0.2.1 → luvatrix-0.2.2}/luvatrix_core/templates/native/ios/Luvatrix/PythonBridge.m
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|