meltygui 0.1.0__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.
- meltygui/__init__.py +107 -0
- meltygui/accounts/__init__.py +0 -0
- meltygui/accounts/internet_accounts.py +1355 -0
- meltygui/chat/__init__.py +91 -0
- meltygui/chat/activity.py +75 -0
- meltygui/chat/backends.py +36 -0
- meltygui/chat/chat_interface.py +732 -0
- meltygui/chat/chat_proxy.py +352 -0
- meltygui/chat/codex_proxy.py +592 -0
- meltygui/chat/codex_settings.py +100 -0
- meltygui/chat/codex_transport.py +60 -0
- meltygui/chat/command_parser.py +204 -0
- meltygui/chat/images.py +227 -0
- meltygui/chat/messages.py +417 -0
- meltygui/chat/metadata.py +139 -0
- meltygui/chat/writer_locks.py +64 -0
- meltygui/code/__init__.py +0 -0
- meltygui/code/basic_converters.py +533 -0
- meltygui/code/chain_converters.py +2111 -0
- meltygui/code/code_checks.py +2209 -0
- meltygui/code/core_syntax.py +1430 -0
- meltygui/code/file_converters.py +1933 -0
- meltygui/code/fileref.py +702 -0
- meltygui/code/hotswap_guard.py +144 -0
- meltygui/code/libcst_conversion.py +9724 -0
- meltygui/code/live_instrument.py +392 -0
- meltygui/code/live_view.py +2490 -0
- meltygui/code/melty_scan.py +2684 -0
- meltygui/code/new_codecs.py +1255 -0
- meltygui/code/new_converters.py +3017 -0
- meltygui/code/project_code.py +278 -0
- meltygui/code/source_context.py +63 -0
- meltygui/code/symbol_roster.py +1588 -0
- meltygui/code/syntax_check.py +34 -0
- meltygui/code/syntax_check_worker.py +114 -0
- meltygui/completion/__init__.py +0 -0
- meltygui/completion/fim.py +1232 -0
- meltygui/completion/fim_context.py +481 -0
- meltygui/completion/providers/__init__.py +0 -0
- meltygui/completion/providers/anthropic_oauth.py +446 -0
- meltygui/completion/providers/anthropic_requests.py +69 -0
- meltygui/completion/providers/claude.py +203 -0
- meltygui/completion/providers/claude_usage.py +499 -0
- meltygui/completion/providers/codex_accounts.py +180 -0
- meltygui/completion/providers/copilot.py +617 -0
- meltygui/completion/providers/oauth_popup.py +220 -0
- meltygui/completion/providers/ollama.py +320 -0
- meltygui/completion/providers/profiles.py +23 -0
- meltygui/core/README.md +88 -0
- meltygui/core/__init__.py +1 -0
- meltygui/core/automation/__init__.py +1 -0
- meltygui/core/automation/action_core.py +153 -0
- meltygui/core/automation/collection_action.py +45 -0
- meltygui/core/automation/mcp_eval.py +167 -0
- meltygui/core/automation/mcp_hotswap.py +107 -0
- meltygui/core/automation/mcp_query.py +552 -0
- meltygui/core/automation/mcp_server.py +657 -0
- meltygui/core/automation/orchestration_core.py +2636 -0
- meltygui/core/automation/query_core.py +124 -0
- meltygui/core/automation/search_core.py +26 -0
- meltygui/core/automation/selector_core.py +340 -0
- meltygui/core/automation/value_core.py +1752 -0
- meltygui/core/cache/__init__.py +1 -0
- meltygui/core/cache/cache_diagnostics.py +0 -0
- meltygui/core/cache/invalidation_decoration.py +153 -0
- meltygui/core/cache/invalidation_tracker.py +43 -0
- meltygui/core/cache/tile_cache.py +5968 -0
- meltygui/core/conversion/__init__.py +1 -0
- meltygui/core/conversion/bubbling.py +599 -0
- meltygui/core/conversion/cache_tree.py +188 -0
- meltygui/core/conversion/chain.py +113 -0
- meltygui/core/conversion/converter_register.py +145 -0
- meltygui/core/conversion/data_decoration.py +67 -0
- meltygui/core/conversion/dict_conversion.py +1815 -0
- meltygui/core/conversion/dict_conversion_util.py +177 -0
- meltygui/core/conversion/dynamic_obj.py +89 -0
- meltygui/core/conversion/graph_compare.py +183 -0
- meltygui/core/conversion/load_save_v2.py +1032 -0
- meltygui/core/conversion/missing_saved_class.py +39 -0
- meltygui/core/conversion/path_finder.py +606 -0
- meltygui/core/conversion/render_host.py +1083 -0
- meltygui/core/core_render.py +6537 -0
- meltygui/core/definition_hotswap.py +231 -0
- meltygui/core/diagnostics/__init__.py +1 -0
- meltygui/core/diagnostics/attribute_churn.py +38 -0
- meltygui/core/diagnostics/fps_counter.py +39 -0
- meltygui/core/diagnostics/gpu_frame_timer.py +103 -0
- meltygui/core/diagnostics/inspection_core.py +169 -0
- meltygui/core/diagnostics/monitor_core.py +105 -0
- meltygui/core/diagnostics/notifications.py +706 -0
- meltygui/core/diagnostics/perf_trace.py +281 -0
- meltygui/core/diagnostics/profile_decoration.py +88 -0
- meltygui/core/diagnostics/resize_trace.py +62 -0
- meltygui/core/diagnostics/screenshot_core.py +247 -0
- meltygui/core/diagnostics/session_status.py +98 -0
- meltygui/core/diagnostics/trace_core.py +445 -0
- meltygui/core/files/__init__.py +1 -0
- meltygui/core/files/file_core.py +208 -0
- meltygui/core/files/file_explorer_core.py +104 -0
- meltygui/core/files/file_tree_core.py +198 -0
- meltygui/core/files/file_watch_core.py +43 -0
- meltygui/core/files/import_graph_core.py +43 -0
- meltygui/core/files/metadata_core.py +51 -0
- meltygui/core/graphics/__init__.py +1 -0
- meltygui/core/graphics/cuda_context_core.py +166 -0
- meltygui/core/graphics/cuda_interop_core.py +136 -0
- meltygui/core/graphics/cuda_kernel_core.py +91 -0
- meltygui/core/graphics/framebuffer_recorder.py +337 -0
- meltygui/core/graphics/gl_state.py +658 -0
- meltygui/core/graphics/lut_core.py +52 -0
- meltygui/core/graphics/overlay_renderer.py +984 -0
- meltygui/core/graphics/scene_target.py +180 -0
- meltygui/core/graphics/screenshot.py +439 -0
- meltygui/core/graphics/shader_func.py +478 -0
- meltygui/core/graphics/tensor_core.py +45 -0
- meltygui/core/graphics/text_texture.py +329 -0
- meltygui/core/graphics/wayland_color.py +635 -0
- meltygui/core/input/__init__.py +1 -0
- meltygui/core/input/collision.py +165 -0
- meltygui/core/input/drag_drop_core.py +1525 -0
- meltygui/core/input/hypr_left_drag.py +323 -0
- meltygui/core/input/input_core.py +245 -0
- meltygui/core/input/input_handler.py +1101 -0
- meltygui/core/input/mouse_cursor.py +355 -0
- meltygui/core/input/pynput_backend.py +1054 -0
- meltygui/core/input/space_mouse.py +338 -0
- meltygui/core/input/touchpad_backend.py +393 -0
- meltygui/core/input/view_selection.py +177 -0
- meltygui/core/layout/__init__.py +1 -0
- meltygui/core/layout/column_core.py +2153 -0
- meltygui/core/layout/cursor_core.py +161 -0
- meltygui/core/layout/dropdown_core.py +278 -0
- meltygui/core/layout/edge_constraints.py +155 -0
- meltygui/core/layout/grid_core.py +117 -0
- meltygui/core/layout/header_core.py +23 -0
- meltygui/core/layout/header_runtime.py +67 -0
- meltygui/core/layout/layout_core.py +87 -0
- meltygui/core/layout/tile_manager_core.py +591 -0
- meltygui/core/melty.py +6726 -0
- meltygui/core/module_map.json +896 -0
- meltygui/core/module_names.py +19 -0
- meltygui/core/rendering/__init__.py +1 -0
- meltygui/core/rendering/core_decoration.py +431 -0
- meltygui/core/rendering/core_render_helpers.py +328 -0
- meltygui/core/rendering/func_metadata.py +398 -0
- meltygui/core/rendering/mode.py +818 -0
- meltygui/core/rendering/mode_defaults.py +41 -0
- meltygui/core/rendering/modes.py +136 -0
- meltygui/core/rendering/parameter_core.py +1665 -0
- meltygui/core/rendering/render_dispatch.py +1891 -0
- meltygui/core/rendering/render_funcs.py +273 -0
- meltygui/core/rendering/shaped.py +312 -0
- meltygui/core/rendering/window_decoration.py +25 -0
- meltygui/core/runtime/__init__.py +1 -0
- meltygui/core/runtime/app.py +735 -0
- meltygui/core/runtime/app_session.py +140 -0
- meltygui/core/runtime/background.py +564 -0
- meltygui/core/runtime/extensions.py +53 -0
- meltygui/core/runtime/gc_manager.py +1163 -0
- meltygui/core/runtime/lifecycle.py +21 -0
- meltygui/core/runtime/paths.py +27 -0
- meltygui/core/runtime/settings.py +14 -0
- meltygui/core/runtime/singleton.py +16 -0
- meltygui/core/runtime/thread_safe_bool.py +24 -0
- meltygui/core/runtime/thread_signal.py +30 -0
- meltygui/core/runtime/toggles.py +3115 -0
- meltygui/core/services/__init__.py +1 -0
- meltygui/core/services/account_core.py +10 -0
- meltygui/core/services/chat_core.py +19 -0
- meltygui/core/services/claude_terminal_core.py +346 -0
- meltygui/core/services/terminal_core.py +458 -0
- meltygui/core/services/terminal_runtime.py +78 -0
- meltygui/core/styling/__init__.py +1 -0
- meltygui/core/styling/color_core.py +46 -0
- meltygui/core/styling/fonts.py +639 -0
- meltygui/core/styling/global_style.py +338 -0
- meltygui/core/styling/style.py +198 -0
- meltygui/core/styling/style_core.py +522 -0
- meltygui/core/styling/warm_start.py +149 -0
- meltygui/core/windowing/__init__.py +1 -0
- meltygui/core/windowing/backends/PYIMGUI_LICENSE +28 -0
- meltygui/core/windowing/backends/__init__.py +1 -0
- meltygui/core/windowing/backends/imgui_renderer.py +138 -0
- meltygui/core/windowing/backends/native_wayland.py +850 -0
- meltygui/core/windowing/backends/protocols/xdg-decoration-unstable-v1.xml +156 -0
- meltygui/core/windowing/backends/protocols/xdg-shell.xml +1420 -0
- meltygui/core/windowing/backends/wayland_protocol.py +101 -0
- meltygui/core/windowing/dock_core.py +182 -0
- meltygui/core/windowing/frame_geometry.py +42 -0
- meltygui/core/windowing/geometry_feed.py +864 -0
- meltygui/core/windowing/glfw_utils.py +1343 -0
- meltygui/core/windowing/os_frame.py +1552 -0
- meltygui/core/windowing/surface.py +643 -0
- meltygui/core/windowing/titlebar.py +1560 -0
- meltygui/core/windowing/titlebar_buttons.py +281 -0
- meltygui/core/windowing/wayland_move.py +932 -0
- meltygui/core/windowing/window_api.py +62 -0
- meltygui/core/windowing/window_constants.py +339 -0
- meltygui/core/windowing/window_visibility.py +162 -0
- meltygui/debug/__init__.py +0 -0
- meltygui/debug/app_view_utils.py +9 -0
- meltygui/editor/__init__.py +0 -0
- meltygui/editor/bash_syntax.py +30 -0
- meltygui/editor/code_line_fast.py +152 -0
- meltygui/editor/diff.py +139 -0
- meltygui/editor/external_changes.py +159 -0
- meltygui/editor/file_header.py +41 -0
- meltygui/editor/live_usage.py +169 -0
- meltygui/editor/live_view_views.py +1803 -0
- meltygui/editor/pending_save.py +1351 -0
- meltygui/editor/roster_tints.py +547 -0
- meltygui/editor/source_preview.py +16 -0
- meltygui/editor/source_tools.py +10 -0
- meltygui/editor/source_ui.py +70 -0
- meltygui/editor/spell_check.py +77 -0
- meltygui/editor/text_editor.py +9076 -0
- meltygui/editor/usage_picker.py +538 -0
- meltygui/events/__init__.py +0 -0
- meltygui/events/example.py +118 -0
- meltygui/examples/__init__.py +0 -0
- meltygui/examples/columns_demo.py +33 -0
- meltygui/examples/columns_window_demo.py +60 -0
- meltygui/examples/context_menu_demo.py +24 -0
- meltygui/examples/context_menu_window_demo.py +49 -0
- meltygui/examples/gui_playground.py +127 -0
- meltygui/examples/live_view_playground.py +256 -0
- meltygui/examples/lora.py +43 -0
- meltygui/examples/lora_data.py +59 -0
- meltygui/examples/lora_policies.py +67 -0
- meltygui/examples/mode_demo.py +49 -0
- meltygui/examples/modifies_demo.py +119 -0
- meltygui/examples/scalar_policies.py +60 -0
- meltygui/examples/style_layouts.py +149 -0
- meltygui/examples/tile_manager_demo.py +74 -0
- meltygui/examples/tint_demo.py +160 -0
- meltygui/examples/tint_functions.py +56 -0
- meltygui/examples/trace_demo.py +88 -0
- meltygui/examples/two_windows.py +36 -0
- meltygui/files/__init__.py +0 -0
- meltygui/files/fast_file_explorer.py +439 -0
- meltygui/gnome_extension/lsd-window-geometry@latent-descent/extension.js +237 -0
- meltygui/gnome_extension/lsd-window-geometry@latent-descent/lsd-window-geometry@latent-descent.iml +9 -0
- meltygui/gnome_extension/lsd-window-geometry@latent-descent/metadata.json +7 -0
- meltygui/graphics/__init__.py +6 -0
- meltygui/graphics/base.py +85 -0
- meltygui/graphics/examples.py +507 -0
- meltygui/graphics/executor.py +520 -0
- meltygui/graphics/filter.py +667 -0
- meltygui/graphics/filter.pyi +856 -0
- meltygui/graphics/generate_stubs.py +22 -0
- meltygui/graphics/registry.py +203 -0
- meltygui/graphics/shader_compiler.py +155 -0
- meltygui/graphics/shaders.py +1302 -0
- meltygui/graphics/stub_generator.py +250 -0
- meltygui/graphics/texture_manager.py +170 -0
- meltygui/graphics/texture_min_max.py +295 -0
- meltygui/hdr_color.py +757 -0
- meltygui/image_load.py +308 -0
- meltygui/model/__init__.py +1 -0
- meltygui/model/account_model.py +142 -0
- meltygui/model/camera_model.py +159 -0
- meltygui/model/chat_model.py +86 -0
- meltygui/model/code_model.py +62 -0
- meltygui/model/code_proxy_model.py +876 -0
- meltygui/model/collection_model.py +41 -0
- meltygui/model/color_model.py +127 -0
- meltygui/model/cuda_tensor_model.py +36 -0
- meltygui/model/cuda_texture_model.py +149 -0
- meltygui/model/dropdown_model.py +137 -0
- meltygui/model/file_metadata_model.py +73 -0
- meltygui/model/file_model.py +289 -0
- meltygui/model/format_model.py +390 -0
- meltygui/model/graph_model.py +98 -0
- meltygui/model/icon_model.py +1024 -0
- meltygui/model/import_graph_model.py +468 -0
- meltygui/model/layout_model.py +15 -0
- meltygui/model/lut_model.py +266 -0
- meltygui/model/search_model.py +173 -0
- meltygui/model/tensor_model.py +402 -0
- meltygui/model/terminal_model.py +329 -0
- meltygui/model/texture_model.py +146 -0
- meltygui/model/tile_model.py +24 -0
- meltygui/model/trace_model.py +198 -0
- meltygui/model/trace_report_model.py +146 -0
- meltygui/models/__init__.py +0 -0
- meltygui/models/file_meta.py +613 -0
- meltygui/models/function_console.py +184 -0
- meltygui/models/orchestration.py +48 -0
- meltygui/pbr.py +1576 -0
- meltygui/png_unfilter.c +49 -0
- meltygui/resources/JetBrainsMono-Regular.ttf +0 -0
- meltygui/resources/THIRD_PARTY_NOTICES.md +21 -0
- meltygui/resources/dejavu/DejaVuSans-Bold.ttf +0 -0
- meltygui/resources/dejavu/DejaVuSans-ExtraLight.ttf +0 -0
- meltygui/resources/dejavu/DejaVuSans.ttf +0 -0
- meltygui/resources/dejavu/LICENSE.txt +78 -0
- meltygui/resources/fontawesome-LICENSE.txt +121 -0
- meltygui/resources/fontawesome-webfont.ttf +0 -0
- meltygui/resources/hdri/studio_small_09_1k.hdr +0 -0
- meltygui/resources/jetbrains-weights/JetBrainsMono-Bold.ttf +0 -0
- meltygui/resources/jetbrains-weights/JetBrainsMono-ExtraBold.ttf +0 -0
- meltygui/resources/jetbrains-weights/JetBrainsMono-ExtraLight.ttf +0 -0
- meltygui/resources/jetbrains-weights/JetBrainsMono-Light.ttf +0 -0
- meltygui/resources/jetbrains-weights/JetBrainsMono-Medium.ttf +0 -0
- meltygui/resources/jetbrains-weights/JetBrainsMono-SemiBold.ttf +0 -0
- meltygui/resources/jetbrains-weights/JetBrainsMono-Thin.ttf +0 -0
- meltygui/resources/jetbrains-weights/OFL.txt +93 -0
- meltygui/resources/jetbrains-weights/README.md +2 -0
- meltygui/state/__init__.py +0 -0
- meltygui/state/account_state.py +22 -0
- meltygui/state/animation_state.py +97 -0
- meltygui/state/annotation_state.py +22 -0
- meltygui/state/chat_state.py +36 -0
- meltygui/state/code_state.py +10 -0
- meltygui/state/core_enums.py +59 -0
- meltygui/state/core_markers.py +115 -0
- meltygui/state/core_undo.py +1075 -0
- meltygui/state/file_state.py +75 -0
- meltygui/state/graph_state.py +26 -0
- meltygui/state/inspection_state.py +47 -0
- meltygui/state/menu_state.py +10 -0
- meltygui/state/model_enums.py +11 -0
- meltygui/state/new_core_model.py +2394 -0
- meltygui/state/orchestration_state.py +14 -0
- meltygui/state/query_state.py +24 -0
- meltygui/state/tensor_state.py +10 -0
- meltygui/state/terminal_state.py +23 -0
- meltygui/state/trace_state.py +32 -0
- meltygui/state/voxel_state.py +12 -0
- meltygui/text_index.py +816 -0
- meltygui/utils/__init__.py +0 -0
- meltygui/utils/jump_to_code.py +344 -0
- meltygui/utils/pkl_inspect.py +90 -0
- meltygui/utils/render_utils.py +1419 -0
- meltygui/view/__init__.py +1 -0
- meltygui/view/account_view.py +524 -0
- meltygui/view/action_view.py +73 -0
- meltygui/view/chat_decoration_view.py +112 -0
- meltygui/view/chat_view.py +1703 -0
- meltygui/view/code_view.py +2677 -0
- meltygui/view/collection_view.py +1185 -0
- meltygui/view/color_view.py +824 -0
- meltygui/view/control_view.py +559 -0
- meltygui/view/decoration_view.py +439 -0
- meltygui/view/diagnostic_view.py +177 -0
- meltygui/view/dropdown_view.py +1082 -0
- meltygui/view/file_view.py +1599 -0
- meltygui/view/graph_cuda_view.py +105 -0
- meltygui/view/graph_view.py +882 -0
- meltygui/view/header_view.py +848 -0
- meltygui/view/input_view.py +238 -0
- meltygui/view/inspection_view.py +1783 -0
- meltygui/view/layout_view.py +596 -0
- meltygui/view/lut_view.py +45 -0
- meltygui/view/menu_view.py +212 -0
- meltygui/view/orchestration_view.py +658 -0
- meltygui/view/query_view.py +118 -0
- meltygui/view/search_view.py +342 -0
- meltygui/view/tab_view.py +258 -0
- meltygui/view/tensor_view.py +430 -0
- meltygui/view/terminal_view.py +355 -0
- meltygui/view/text_view.py +8031 -0
- meltygui/view/texture_view.py +480 -0
- meltygui/view/tile_view.py +38 -0
- meltygui/view/trace_view.py +923 -0
- meltygui/view/voxel_cuda_view.py +824 -0
- meltygui/view/voxel_view.py +1860 -0
- meltygui/view/window_view.py +111 -0
- meltygui-0.1.0.dist-info/METADATA +143 -0
- meltygui-0.1.0.dist-info/RECORD +372 -0
- meltygui-0.1.0.dist-info/WHEEL +4 -0
- meltygui-0.1.0.dist-info/licenses/LICENSE +202 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"uuid": "lsd-window-geometry@latent-descent",
|
|
3
|
+
"name": "LSD Window Geometry",
|
|
4
|
+
"description": "Publishes window frame rectangles and monitor work areas over the session D-Bus (org.latentdescent.WindowGeometry). Wayland never tells a client where its window sits on the screen; LSD Studio needs that to treat the screen edges as collision walls for its own window edges. Installed and managed from the studio (gl_gui/installation_helper.py).",
|
|
5
|
+
"shell-version": ["45", "46", "47", "48"],
|
|
6
|
+
"version": 1
|
|
7
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Base classes for shader types and shaders.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from abc import ABC
|
|
6
|
+
from dataclasses import dataclass, field
|
|
7
|
+
from typing import Dict, Any, Optional, List
|
|
8
|
+
from enum import Enum
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class GLType(Enum):
|
|
12
|
+
"""OpenGL data types for shader attributes and uniforms."""
|
|
13
|
+
FLOAT = 'float'
|
|
14
|
+
VEC2 = 'vec2'
|
|
15
|
+
VEC3 = 'vec3'
|
|
16
|
+
VEC4 = 'vec4'
|
|
17
|
+
MAT2 = 'mat2'
|
|
18
|
+
MAT3 = 'mat3'
|
|
19
|
+
MAT4 = 'mat4'
|
|
20
|
+
INT = 'int'
|
|
21
|
+
IVEC2 = 'ivec2'
|
|
22
|
+
IVEC3 = 'ivec3'
|
|
23
|
+
IVEC4 = 'ivec4'
|
|
24
|
+
SAMPLER2D = 'sampler2D'
|
|
25
|
+
BOOL = 'bool'
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@dataclass
|
|
29
|
+
class ShaderType:
|
|
30
|
+
"""
|
|
31
|
+
Defines a shader type (vertex shader structure).
|
|
32
|
+
|
|
33
|
+
Attributes:
|
|
34
|
+
name: The type name (inferred from class name)
|
|
35
|
+
vertex_in: Input attributes {name: GLType}
|
|
36
|
+
vertex_out: Output varyings {name: GLType}
|
|
37
|
+
vertex_code: The vertex shader code template
|
|
38
|
+
"""
|
|
39
|
+
name: str
|
|
40
|
+
vertex_in: Dict[str, GLType] = field(default_factory=dict)
|
|
41
|
+
vertex_out: Dict[str, GLType] = field(default_factory=dict)
|
|
42
|
+
vertex_code: str = ""
|
|
43
|
+
|
|
44
|
+
def generate_vertex_declarations(self) -> str:
|
|
45
|
+
"""Generate GLSL declarations for vertex shader inputs/outputs."""
|
|
46
|
+
lines = []
|
|
47
|
+
for attr_name, attr_type in self.vertex_in.items():
|
|
48
|
+
lines.append(f"in {attr_type.value} {attr_name};")
|
|
49
|
+
for var_name, var_type in self.vertex_out.items():
|
|
50
|
+
lines.append(f"out {var_type.value} {var_name};")
|
|
51
|
+
return '\n'.join(lines)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
@dataclass
|
|
55
|
+
class Shader:
|
|
56
|
+
"""
|
|
57
|
+
Defines a complete shader (fragment shader with optional vertex override).
|
|
58
|
+
|
|
59
|
+
Attributes:
|
|
60
|
+
name: The shader name (inferred from class name, converted to snake_case)
|
|
61
|
+
shader_type: The ShaderType this shader uses
|
|
62
|
+
fragment_code: The fragment shader code
|
|
63
|
+
vertex_code: Optional vertex shader code override
|
|
64
|
+
uniforms: Uniform definitions {name: (GLType, default_value)}
|
|
65
|
+
"""
|
|
66
|
+
name: str
|
|
67
|
+
shader_type: Optional[str] = None # Name of shader type to use
|
|
68
|
+
fragment_code: str = ""
|
|
69
|
+
vertex_code: Optional[str] = None # Override vertex code if provided
|
|
70
|
+
uniforms: Dict[str, tuple] = field(default_factory=dict) # {name: (GLType, default)}
|
|
71
|
+
|
|
72
|
+
def get_uniform_declarations(self) -> str:
|
|
73
|
+
"""Generate GLSL uniform declarations."""
|
|
74
|
+
lines = []
|
|
75
|
+
for name, (gl_type, _) in self.uniforms.items():
|
|
76
|
+
lines.append(f"uniform {gl_type.value} {name};")
|
|
77
|
+
return '\n'.join(lines)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def camel_to_snake(name: str) -> str:
|
|
81
|
+
"""Convert CamelCase to snake_case."""
|
|
82
|
+
import re
|
|
83
|
+
# Insert underscore before uppercase letters and convert to lowercase
|
|
84
|
+
s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
|
|
85
|
+
return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()
|
|
@@ -0,0 +1,507 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Example usage of the Melty shader library.
|
|
3
|
+
|
|
4
|
+
This demonstrates:
|
|
5
|
+
1. Basic filter application
|
|
6
|
+
2. Creating custom shaders
|
|
7
|
+
3. Filter chaining
|
|
8
|
+
4. Custom shader types
|
|
9
|
+
"""
|
|
10
|
+
from meltygui.core.melty import Melty
|
|
11
|
+
from meltygui.graphics.base import GLType
|
|
12
|
+
from meltygui.graphics.filter import Filter
|
|
13
|
+
from meltygui.graphics.registry import register_shader
|
|
14
|
+
from meltygui.graphics.registry import register_shader_type
|
|
15
|
+
from meltygui.graphics.registry import get_registry
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
# =============================================================================
|
|
19
|
+
# CUSTOM SHADER EXAMPLE
|
|
20
|
+
# =============================================================================
|
|
21
|
+
|
|
22
|
+
@register_shader
|
|
23
|
+
class ColorTint:
|
|
24
|
+
"""Apply a color tint to the image."""
|
|
25
|
+
shader_type = 'standard'
|
|
26
|
+
uniforms = {
|
|
27
|
+
'tint_color': (GLType.VEC3, (1.0, 0.8, 0.6)),
|
|
28
|
+
'amount': (GLType.FLOAT, 0.3),
|
|
29
|
+
}
|
|
30
|
+
fragment_code = """
|
|
31
|
+
void main() {
|
|
32
|
+
vec4 color = texture(u_texture, v_texcoord);
|
|
33
|
+
color.rgb = mix(color.rgb, color.rgb * tint_color, amount);
|
|
34
|
+
fragColor = color;
|
|
35
|
+
}
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@register_shader
|
|
40
|
+
class FilmGrain:
|
|
41
|
+
"""Add film grain noise effect."""
|
|
42
|
+
shader_type = 'standard'
|
|
43
|
+
uniforms = {
|
|
44
|
+
'amount': (GLType.FLOAT, 0.1),
|
|
45
|
+
'time': (GLType.FLOAT, 0.0), # Animate with time for varying grain
|
|
46
|
+
}
|
|
47
|
+
fragment_code = """
|
|
48
|
+
// Simple hash function for noise
|
|
49
|
+
float hash(vec2 p) {
|
|
50
|
+
return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
void main() {
|
|
54
|
+
vec4 color = texture(u_texture, v_texcoord);
|
|
55
|
+
|
|
56
|
+
// Generate noise based on position and time
|
|
57
|
+
float noise = hash(v_texcoord * 1000.0 + time) * 2.0 - 1.0;
|
|
58
|
+
|
|
59
|
+
// Apply grain
|
|
60
|
+
color.rgb += noise * amount;
|
|
61
|
+
color.rgb = clamp(color.rgb, 0.0, 1.0);
|
|
62
|
+
|
|
63
|
+
fragColor = color;
|
|
64
|
+
}
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
@register_shader
|
|
69
|
+
class Sharpen:
|
|
70
|
+
"""Sharpening filter using unsharp mask."""
|
|
71
|
+
shader_type = 'standard'
|
|
72
|
+
uniforms = {
|
|
73
|
+
'amount': (GLType.FLOAT, 1.0),
|
|
74
|
+
'texture_size': (GLType.VEC2, (512.0, 512.0)),
|
|
75
|
+
}
|
|
76
|
+
fragment_code = """
|
|
77
|
+
void main() {
|
|
78
|
+
vec2 texel = 1.0 / texture_size;
|
|
79
|
+
|
|
80
|
+
// Sample center and neighbors
|
|
81
|
+
vec4 center = texture(u_texture, v_texcoord);
|
|
82
|
+
vec4 top = texture(u_texture, v_texcoord + vec2(0, -1) * texel);
|
|
83
|
+
vec4 bottom = texture(u_texture, v_texcoord + vec2(0, 1) * texel);
|
|
84
|
+
vec4 left = texture(u_texture, v_texcoord + vec2(-1, 0) * texel);
|
|
85
|
+
vec4 right = texture(u_texture, v_texcoord + vec2(1, 0) * texel);
|
|
86
|
+
|
|
87
|
+
// Sharpen kernel: -1, -1, -1 / -1, 9, -1 / -1, -1, -1 (simplified)
|
|
88
|
+
vec4 sharpened = center * (1.0 + 4.0 * amount) - (top + bottom + left + right) * amount;
|
|
89
|
+
|
|
90
|
+
fragColor = clamp(sharpened, 0.0, 1.0);
|
|
91
|
+
}
|
|
92
|
+
"""
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
# =============================================================================
|
|
96
|
+
# CUSTOM SHADER TYPE EXAMPLE
|
|
97
|
+
# =============================================================================
|
|
98
|
+
|
|
99
|
+
@register_shader_type
|
|
100
|
+
class MultiTexture:
|
|
101
|
+
"""
|
|
102
|
+
Shader type that supports multiple texture inputs.
|
|
103
|
+
Useful for blend modes, masks, etc.
|
|
104
|
+
"""
|
|
105
|
+
vertex_in = {
|
|
106
|
+
'position': GLType.VEC3,
|
|
107
|
+
'texcoord': GLType.VEC2,
|
|
108
|
+
}
|
|
109
|
+
vertex_out = {
|
|
110
|
+
'v_texcoord': GLType.VEC2,
|
|
111
|
+
}
|
|
112
|
+
vertex_code = """
|
|
113
|
+
void main() {
|
|
114
|
+
v_texcoord = texcoord;
|
|
115
|
+
gl_Position = vec4(position, 1.0);
|
|
116
|
+
}
|
|
117
|
+
"""
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
@register_shader(shader_type='multi_texture')
|
|
121
|
+
class BlendMultiply:
|
|
122
|
+
"""Multiply blend two textures."""
|
|
123
|
+
uniforms = {
|
|
124
|
+
'blend_texture': (GLType.SAMPLER2D, 0),
|
|
125
|
+
'opacity': (GLType.FLOAT, 1.0),
|
|
126
|
+
}
|
|
127
|
+
fragment_code = """
|
|
128
|
+
uniform sampler2D blend_texture;
|
|
129
|
+
|
|
130
|
+
void main() {
|
|
131
|
+
vec4 base = texture(u_texture, v_texcoord);
|
|
132
|
+
vec4 blend = texture(blend_texture, v_texcoord);
|
|
133
|
+
|
|
134
|
+
vec3 result = base.rgb * blend.rgb;
|
|
135
|
+
fragColor = vec4(mix(base.rgb, result, opacity), base.a);
|
|
136
|
+
}
|
|
137
|
+
"""
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
# =============================================================================
|
|
141
|
+
# INTEGRATION EXAMPLE - How your Melty class would use Filter
|
|
142
|
+
# =============================================================================
|
|
143
|
+
|
|
144
|
+
# class Melty:
|
|
145
|
+
# """Example of how your existing Melty class would integrate with Filter."""
|
|
146
|
+
#
|
|
147
|
+
# def __init__(self):
|
|
148
|
+
# self.filter = Filter()
|
|
149
|
+
#
|
|
150
|
+
# def cleanup(self):
|
|
151
|
+
# self.filter.cleanup()
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
# =============================================================================
|
|
155
|
+
# USAGE EXAMPLES
|
|
156
|
+
# =============================================================================
|
|
157
|
+
|
|
158
|
+
def basic_usage_example():
|
|
159
|
+
"""Demonstrate basic filter usage."""
|
|
160
|
+
|
|
161
|
+
# Your Melty class holds the Filter instance
|
|
162
|
+
|
|
163
|
+
# Assuming you have a texture_id defined somewhere
|
|
164
|
+
texture_id = 1 # Placeholder
|
|
165
|
+
|
|
166
|
+
# Apply a single filter
|
|
167
|
+
result = Melty.filter.brightness_contrast(
|
|
168
|
+
texture_id,
|
|
169
|
+
brightness=0.2,
|
|
170
|
+
contrast=1.3
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
# Apply in-place (modifies original texture)
|
|
174
|
+
Melty.filter.grayscale(texture_id, in_place=True)
|
|
175
|
+
|
|
176
|
+
# Apply multiple filters
|
|
177
|
+
result = Melty.filter.hue_saturation(result, saturation=1.5)
|
|
178
|
+
result = Melty.filter.vignette(result, radius=0.8, amount=0.3)
|
|
179
|
+
|
|
180
|
+
# Clean up
|
|
181
|
+
Melty.cleanup()
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def direct_to_screen_example():
|
|
185
|
+
"""Demonstrate rendering filters directly to the main framebuffer (screen)."""
|
|
186
|
+
|
|
187
|
+
texture_id = 1 # Placeholder
|
|
188
|
+
|
|
189
|
+
# Apply filter directly to main framebuffer (0) - no off-screen buffer!
|
|
190
|
+
# This is perfect for final post-processing effects
|
|
191
|
+
Melty.filter.vignette(
|
|
192
|
+
texture_id,
|
|
193
|
+
output_framebuffer=0, # Render to main screen
|
|
194
|
+
radius=0.8,
|
|
195
|
+
amount=0.4
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
# The filter is applied directly to the screen
|
|
199
|
+
# No texture is created - returns 0
|
|
200
|
+
|
|
201
|
+
# You can also render to a custom framebuffer
|
|
202
|
+
custom_fbo = 5 # Your framebuffer ID
|
|
203
|
+
Melty.filter.gaussian_blur(
|
|
204
|
+
texture_id,
|
|
205
|
+
output_framebuffer=custom_fbo,
|
|
206
|
+
radius=5.0
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
Melty.cleanup()
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
def framebuffer_input_example():
|
|
213
|
+
"""Demonstrate using framebuffers as input (e.g., apply filters to screen contents)."""
|
|
214
|
+
|
|
215
|
+
# Apply a filter to whatever is currently rendered on screen!
|
|
216
|
+
# Reads from framebuffer 0 (main screen) and outputs to a texture
|
|
217
|
+
result_texture = Melty.filter.vignette(
|
|
218
|
+
input_framebuffer=0, # Read from main screen
|
|
219
|
+
radius=0.8,
|
|
220
|
+
amount=0.5
|
|
221
|
+
)
|
|
222
|
+
# Returns a texture with the filtered screen contents
|
|
223
|
+
|
|
224
|
+
# You can also do screen-to-screen filtering (both input and output are framebuffers)
|
|
225
|
+
Melty.filter.gaussian_blur(
|
|
226
|
+
input_framebuffer=0, # Read from main screen
|
|
227
|
+
output_framebuffer=0, # Write back to main screen
|
|
228
|
+
radius=5.0
|
|
229
|
+
)
|
|
230
|
+
# This applies the blur directly to the screen in-place!
|
|
231
|
+
|
|
232
|
+
# Read from custom framebuffer and output to texture
|
|
233
|
+
custom_fbo = 5 # Your framebuffer ID
|
|
234
|
+
result = Melty.filter.brightness_contrast(
|
|
235
|
+
input_framebuffer=custom_fbo,
|
|
236
|
+
brightness=0.2,
|
|
237
|
+
contrast=1.3
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
# Read from custom framebuffer and write to another framebuffer
|
|
241
|
+
output_fbo = 6
|
|
242
|
+
Melty.filter.sepia(
|
|
243
|
+
input_framebuffer=custom_fbo,
|
|
244
|
+
output_framebuffer=output_fbo,
|
|
245
|
+
amount=0.8
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
Melty.cleanup()
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
def chaining_example():
|
|
252
|
+
"""Demonstrate filter chaining."""
|
|
253
|
+
|
|
254
|
+
texture_id = 1 # Placeholder
|
|
255
|
+
|
|
256
|
+
# Create a filter chain
|
|
257
|
+
# Note: texture_size is automatically detected - no need to pass it!
|
|
258
|
+
result = (Melty.filter.chain()
|
|
259
|
+
.brightness_contrast(brightness=0.1, contrast=1.2)
|
|
260
|
+
.hue_saturation(saturation=1.2)
|
|
261
|
+
.vignette(radius=0.7, softness=0.5, amount=0.4)
|
|
262
|
+
.sharpen(amount=0.5)
|
|
263
|
+
.apply(texture_id))
|
|
264
|
+
|
|
265
|
+
# Apply chain in-place
|
|
266
|
+
(Melty.filter.chain()
|
|
267
|
+
.sepia(amount=0.8)
|
|
268
|
+
.film_grain(amount=0.05)
|
|
269
|
+
.apply(texture_id, in_place=True))
|
|
270
|
+
|
|
271
|
+
Melty.cleanup()
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
def context_manager_example():
|
|
275
|
+
"""Using Filter as a context manager."""
|
|
276
|
+
|
|
277
|
+
texture_id = 1 # Placeholder
|
|
278
|
+
|
|
279
|
+
with Filter() as f:
|
|
280
|
+
result = f.posterize(texture_id, levels=4)
|
|
281
|
+
|
|
282
|
+
# Resources are automatically cleaned up
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
def listing_shaders_example():
|
|
286
|
+
"""List available shaders and their info."""
|
|
287
|
+
|
|
288
|
+
f = Filter()
|
|
289
|
+
|
|
290
|
+
# List all available shaders
|
|
291
|
+
print("Available shaders:")
|
|
292
|
+
for name in f.list_shaders():
|
|
293
|
+
info = f.get_shader_info(name)
|
|
294
|
+
print(f" {name}:")
|
|
295
|
+
print(f" type: {info['shader_type']}")
|
|
296
|
+
print(f" uniforms: {list(info['uniforms'].keys())}")
|
|
297
|
+
|
|
298
|
+
# List shader types
|
|
299
|
+
print("\nAvailable shader types:")
|
|
300
|
+
for name in f.list_shader_types():
|
|
301
|
+
print(f" {name}")
|
|
302
|
+
|
|
303
|
+
f.cleanup()
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
def texture_caching_example():
|
|
307
|
+
"""Demonstrate automatic texture caching for efficient multi-frame processing."""
|
|
308
|
+
|
|
309
|
+
texture_id = 1 # Placeholder for input texture
|
|
310
|
+
|
|
311
|
+
f = Filter()
|
|
312
|
+
|
|
313
|
+
# Process multiple frames efficiently
|
|
314
|
+
# Output textures are automatically cached per input texture ID
|
|
315
|
+
for frame in range(10):
|
|
316
|
+
# Apply filters - same output texture is cached each frame!
|
|
317
|
+
result1 = f.brightness_contrast(texture_id, brightness=0.1)
|
|
318
|
+
result2 = f.vignette(result1, amount=0.3)
|
|
319
|
+
|
|
320
|
+
# Use the final result...
|
|
321
|
+
# (In a real app, you'd render it or save it)
|
|
322
|
+
|
|
323
|
+
# No need to manually release - caching is automatic!
|
|
324
|
+
|
|
325
|
+
# Check cache statistics
|
|
326
|
+
stats = f.get_cache_stats()
|
|
327
|
+
print("Texture cache stats:", stats['textures'])
|
|
328
|
+
# Output: {1: (10, 512, 512), 10: (11, 512, 512)}
|
|
329
|
+
# Maps input_texture_id -> (output_texture_id, width, height)
|
|
330
|
+
|
|
331
|
+
# Clear cache when done to free GPU memory
|
|
332
|
+
f.clear_texture_cache()
|
|
333
|
+
|
|
334
|
+
f.cleanup()
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
def cache_benefits_example():
|
|
338
|
+
"""
|
|
339
|
+
Demonstrate the benefits of automatic texture caching.
|
|
340
|
+
|
|
341
|
+
With automatic caching:
|
|
342
|
+
- Each input texture ID gets its own persistent output texture
|
|
343
|
+
- Textures are automatically reused across frames
|
|
344
|
+
- Zero manual management required
|
|
345
|
+
- Optimal performance for multi-frame processing
|
|
346
|
+
"""
|
|
347
|
+
|
|
348
|
+
texture_id = 1 # Placeholder
|
|
349
|
+
width, height = 1920, 1080
|
|
350
|
+
|
|
351
|
+
f = Filter()
|
|
352
|
+
|
|
353
|
+
# Process 100 frames with filter chain
|
|
354
|
+
for frame in range(100):
|
|
355
|
+
# Apply multiple filters
|
|
356
|
+
# Each intermediate result automatically gets its own cached texture
|
|
357
|
+
temp1 = f.brightness_contrast(texture_id, brightness=0.1)
|
|
358
|
+
# Note: texture_size is automatically detected from the texture!
|
|
359
|
+
temp2 = f.gaussian_blur_h(temp1, radius=5.0)
|
|
360
|
+
final = f.gaussian_blur_v(temp2, radius=5.0)
|
|
361
|
+
|
|
362
|
+
# Use final result...
|
|
363
|
+
# No manual release needed!
|
|
364
|
+
|
|
365
|
+
# After 100 iterations, 3 textures exist (one per unique input texture ID)
|
|
366
|
+
stats = f.get_cache_stats()
|
|
367
|
+
print(f"Cached textures: {len(stats['textures'])}")
|
|
368
|
+
# Output: 3 (one for texture_id=1, one for temp1, one for temp2)
|
|
369
|
+
|
|
370
|
+
f.cleanup()
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
def multi_size_caching_example():
|
|
374
|
+
"""
|
|
375
|
+
Demonstrate automatic FBO and texture caching for multiple texture sizes.
|
|
376
|
+
|
|
377
|
+
This is the key use case: when processing textures of different sizes
|
|
378
|
+
in the same session, FBOs and output textures are cached automatically.
|
|
379
|
+
"""
|
|
380
|
+
|
|
381
|
+
f = Filter()
|
|
382
|
+
|
|
383
|
+
# Simulate rendering two different sized textures each frame
|
|
384
|
+
texture_a = 1 # 512x512 texture
|
|
385
|
+
texture_b = 2 # 1920x1080 texture
|
|
386
|
+
|
|
387
|
+
for frame in range(100):
|
|
388
|
+
# Process texture A (512x512)
|
|
389
|
+
# Frame 1: Creates FBO for 512x512 and output texture for texture_a
|
|
390
|
+
# Frame 2+: Reuses both!
|
|
391
|
+
result_a = f.brightness_contrast(texture_a, brightness=0.1)
|
|
392
|
+
# Use result_a...
|
|
393
|
+
|
|
394
|
+
# Process texture B (1920x1080)
|
|
395
|
+
# Frame 1: Creates FBO for 1920x1080 and output texture for texture_b
|
|
396
|
+
# Frame 2+: Reuses both!
|
|
397
|
+
result_b = f.vignette(texture_b, amount=0.3)
|
|
398
|
+
# Use result_b...
|
|
399
|
+
|
|
400
|
+
# No manual management needed!
|
|
401
|
+
|
|
402
|
+
# Check cache stats
|
|
403
|
+
stats = f.get_cache_stats()
|
|
404
|
+
print("Cache statistics:")
|
|
405
|
+
print(f" Output textures: {stats['textures']}")
|
|
406
|
+
# e.g., {1: (10, 512, 512), 2: (11, 1920, 1080)}
|
|
407
|
+
# Maps input_texture_id -> (output_texture_id, width, height)
|
|
408
|
+
print(f" FBOs cached: {list(stats['fbos'].keys())}")
|
|
409
|
+
# e.g., [(512, 512), (1920, 1080)]
|
|
410
|
+
print(f" Temp textures: {list(stats['temp_textures'].keys())}")
|
|
411
|
+
# e.g., [(512, 512), (1920, 1080)]
|
|
412
|
+
|
|
413
|
+
# Each size has its own FBO and temp texture - no extra overhead!
|
|
414
|
+
# Each input texture has its own output texture - automatic reuse!
|
|
415
|
+
|
|
416
|
+
f.cleanup()
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
def normalize_example():
|
|
420
|
+
"""
|
|
421
|
+
Demonstrate GPU-accelerated texture normalization.
|
|
422
|
+
|
|
423
|
+
The normalize filter efficiently calculates the min/max values
|
|
424
|
+
using parallel reduction on the GPU, then remaps all values to [0, 1].
|
|
425
|
+
"""
|
|
426
|
+
|
|
427
|
+
f = Filter()
|
|
428
|
+
|
|
429
|
+
texture_id = 1 # Placeholder input texture that may have non-normalized values
|
|
430
|
+
|
|
431
|
+
# Normalize the texture - automatically finds min/max and remaps to [0, 1]
|
|
432
|
+
# This uses GPU parallel reduction - much faster than reading all pixels!
|
|
433
|
+
result = f.normalize(texture_id)
|
|
434
|
+
|
|
435
|
+
# Can also normalize in-place (modifies original texture)
|
|
436
|
+
f.normalize(texture_id, in_place=True)
|
|
437
|
+
|
|
438
|
+
# How normalization works under the hood:
|
|
439
|
+
# 1. Progressively downsamples the texture using min/max reduction shader
|
|
440
|
+
# - 1024x1024 -> 512x512 -> 256x256 -> ... -> 1x1
|
|
441
|
+
# 2. Reads the final 1x1 pixel (only 4 float values!) to get min/max
|
|
442
|
+
# 3. Applies normalization remap shader with calculated min/max
|
|
443
|
+
#
|
|
444
|
+
# For a 1024x1024 texture, this reads ~10 reduction passes + 1 pixel
|
|
445
|
+
# instead of reading 1 million pixels on the CPU!
|
|
446
|
+
|
|
447
|
+
f.cleanup()
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
# =============================================================================
|
|
451
|
+
# PYGAME INTEGRATION EXAMPLE
|
|
452
|
+
# =============================================================================
|
|
453
|
+
|
|
454
|
+
# def pygame_integration_example():
|
|
455
|
+
# """Example integration with Pygame."""
|
|
456
|
+
# import pygame
|
|
457
|
+
# from pygame.locals import *
|
|
458
|
+
# from OpenGL.GL import *
|
|
459
|
+
#
|
|
460
|
+
# # Initialize Pygame and OpenGL
|
|
461
|
+
# pygame.init()
|
|
462
|
+
# pygame.display.set_mode((800, 600), DOUBLEBUF | OPENGL)
|
|
463
|
+
#
|
|
464
|
+
# # Initialize Melty class with Filter
|
|
465
|
+
# meltygui = Melty()
|
|
466
|
+
#
|
|
467
|
+
# # Load an image as texture (simplified)
|
|
468
|
+
# def load_texture(path):
|
|
469
|
+
# surface = pygame.image.load(path)
|
|
470
|
+
# data = pygame.image.tostring(surface, "RGBA", True)
|
|
471
|
+
# width, height = surface.get_size()
|
|
472
|
+
#
|
|
473
|
+
# texture = glGenTextures(1)
|
|
474
|
+
# glBindTexture(GL_TEXTURE_2D, texture)
|
|
475
|
+
# glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
|
|
476
|
+
# GL_RGBA, GL_UNSIGNED_BYTE, data)
|
|
477
|
+
# glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
|
|
478
|
+
# glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
|
|
479
|
+
#
|
|
480
|
+
# return texture, (width, height)
|
|
481
|
+
#
|
|
482
|
+
# # Example usage:
|
|
483
|
+
# # texture, size = load_texture("image.png")
|
|
484
|
+
# # texture = meltygui.filter.brightness_contrast(texture, brightness=0.2)
|
|
485
|
+
#
|
|
486
|
+
# meltygui.cleanup()
|
|
487
|
+
# pygame.quit()
|
|
488
|
+
|
|
489
|
+
|
|
490
|
+
if __name__ == '__main__':
|
|
491
|
+
# Just list available shaders (doesn't need OpenGL context)
|
|
492
|
+
|
|
493
|
+
registry = get_registry()
|
|
494
|
+
|
|
495
|
+
print("Melty Shader Library")
|
|
496
|
+
print("=" * 40)
|
|
497
|
+
|
|
498
|
+
print("\nRegistered Shader Types:")
|
|
499
|
+
for name, shader_type in registry.shader_types.items():
|
|
500
|
+
print(f" @{name}")
|
|
501
|
+
print(f" inputs: {list(shader_type.vertex_in.keys())}")
|
|
502
|
+
print(f" outputs: {list(shader_type.vertex_out.keys())}")
|
|
503
|
+
|
|
504
|
+
print("\nRegistered Shaders:")
|
|
505
|
+
for name, shader in registry.shaders.items():
|
|
506
|
+
uniforms = ', '.join(f"{k}={v[1]}" for k, v in shader.uniforms.items())
|
|
507
|
+
print(f" {name}({uniforms})")
|