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,329 @@
|
|
|
1
|
+
"""Text → GLTexture via imgui's own font atlas — no freetype dependency.
|
|
2
|
+
|
|
3
|
+
A private imgui context SHARING the main context's font atlas does the text
|
|
4
|
+
layout: `add_text` on its foreground draw list, `imgui.render()`, and the
|
|
5
|
+
resulting draw data renders into a small FBO with the same mechanics the
|
|
6
|
+
screen pass uses (SplitOverlayRenderer._render_command_lists): identical
|
|
7
|
+
vertex layout (pos/uv/col at imgui.VERTEX_SIZE strides), an imgui-style
|
|
8
|
+
ortho shader, glDrawElements straight off vtx_buffer_data/idx_buffer_data.
|
|
9
|
+
Glyphs come from the already-rasterized shared atlas texture, so any font
|
|
10
|
+
the FontManager loaded works via `font=`.
|
|
11
|
+
|
|
12
|
+
GL-thread only — callers sit inside a @render_func body on the render
|
|
13
|
+
thread, with the MAIN imgui context current (it is restored even on error).
|
|
14
|
+
The caller supplies its GLState: private layout contexts and GPU resources
|
|
15
|
+
are reused locally, survive source edits and are released with their GL context.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
import ctypes
|
|
19
|
+
|
|
20
|
+
import meltygui_imgui as imgui
|
|
21
|
+
from meltygui.hdr_color import pack_color
|
|
22
|
+
import OpenGL.GL as gl
|
|
23
|
+
|
|
24
|
+
from meltygui.core.graphics.gl_state import GLState, GLTexture
|
|
25
|
+
from meltygui.hdr_color import GLSL_DECODE as _GLSL_DECODE
|
|
26
|
+
from meltygui.hdr_color import GLSL_UNPREMULTIPLY as _GLSL_UNPREMULTIPLY
|
|
27
|
+
from meltygui.hdr_color import GLSL_TEXT_CLAMP as _GLSL_TEXT_CLAMP
|
|
28
|
+
from meltygui.hdr_color import set_decode_uniforms
|
|
29
|
+
|
|
30
|
+
_VS = """
|
|
31
|
+
#version 330 core
|
|
32
|
+
layout(location = 0) in vec2 Position;
|
|
33
|
+
layout(location = 1) in vec2 UV;
|
|
34
|
+
layout(location = 2) in vec4 Color;
|
|
35
|
+
uniform vec2 uSize;
|
|
36
|
+
out vec2 fUV;
|
|
37
|
+
out vec4 fColor;
|
|
38
|
+
""" + _GLSL_DECODE + """
|
|
39
|
+
void main() {
|
|
40
|
+
fUV = UV;
|
|
41
|
+
fColor = melty_decode_premultiplied(Color); // linear scRGB, premultiplied, like the screen pass
|
|
42
|
+
// imgui-style ortho: display y=0 (text top) -> ndc +1, so the baked
|
|
43
|
+
// texture's v=1 row is the TOP of the text.
|
|
44
|
+
gl_Position = vec4(Position.x * 2.0 / uSize.x - 1.0,
|
|
45
|
+
1.0 - Position.y * 2.0 / uSize.y, 0.0, 1.0);
|
|
46
|
+
}
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
_FS = """
|
|
50
|
+
#version 330 core
|
|
51
|
+
uniform sampler2D Texture;
|
|
52
|
+
in vec2 fUV;
|
|
53
|
+
in vec4 fColor; // premultiplied (see _VS)
|
|
54
|
+
out vec4 OutColor;
|
|
55
|
+
""" + _GLSL_UNPREMULTIPLY + _GLSL_TEXT_CLAMP + """
|
|
56
|
+
void main() {
|
|
57
|
+
vec4 color = melty_unpremultiply(fColor);
|
|
58
|
+
color.rgb = melty_clamp_text(color.rgb); // the bake is all text: Toggles.HDR.text_max_stops
|
|
59
|
+
OutColor = color * texture(Texture, fUV);
|
|
60
|
+
}
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
def _compile(shader_type, src):
|
|
64
|
+
s = gl.glCreateShader(shader_type)
|
|
65
|
+
gl.glShaderSource(s, src)
|
|
66
|
+
gl.glCompileShader(s)
|
|
67
|
+
if gl.glGetShaderiv(s, gl.GL_COMPILE_STATUS) != gl.GL_TRUE:
|
|
68
|
+
raise RuntimeError(gl.glGetShaderInfoLog(s).decode(errors="replace"))
|
|
69
|
+
return s
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def _ensure_gl(gl_state):
|
|
73
|
+
def create():
|
|
74
|
+
vs, fs = _compile(gl.GL_VERTEX_SHADER, _VS), _compile(gl.GL_FRAGMENT_SHADER, _FS)
|
|
75
|
+
prog = gl.glCreateProgram()
|
|
76
|
+
gl.glAttachShader(prog, vs)
|
|
77
|
+
gl.glAttachShader(prog, fs)
|
|
78
|
+
gl.glLinkProgram(prog)
|
|
79
|
+
if gl.glGetProgramiv(prog, gl.GL_LINK_STATUS) != gl.GL_TRUE:
|
|
80
|
+
raise RuntimeError(gl.glGetProgramInfoLog(prog).decode(errors="replace"))
|
|
81
|
+
gl.glDeleteShader(vs)
|
|
82
|
+
gl.glDeleteShader(fs)
|
|
83
|
+
|
|
84
|
+
vao = gl.glGenVertexArrays(1)
|
|
85
|
+
vbo = gl.glGenBuffers(1)
|
|
86
|
+
ebo = gl.glGenBuffers(1)
|
|
87
|
+
gl.glBindVertexArray(vao)
|
|
88
|
+
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vbo)
|
|
89
|
+
gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, ebo)
|
|
90
|
+
gl.glEnableVertexAttribArray(0)
|
|
91
|
+
gl.glEnableVertexAttribArray(1)
|
|
92
|
+
gl.glEnableVertexAttribArray(2)
|
|
93
|
+
gl.glVertexAttribPointer(0, 2, gl.GL_FLOAT, gl.GL_FALSE, imgui.VERTEX_SIZE,
|
|
94
|
+
ctypes.c_void_p(imgui.VERTEX_BUFFER_POS_OFFSET))
|
|
95
|
+
gl.glVertexAttribPointer(1, 2, gl.GL_FLOAT, gl.GL_FALSE, imgui.VERTEX_SIZE,
|
|
96
|
+
ctypes.c_void_p(imgui.VERTEX_BUFFER_UV_OFFSET))
|
|
97
|
+
gl.glVertexAttribPointer(2, 4, gl.GL_UNSIGNED_BYTE, gl.GL_TRUE, imgui.VERTEX_SIZE,
|
|
98
|
+
ctypes.c_void_p(imgui.VERTEX_BUFFER_COL_OFFSET))
|
|
99
|
+
gl.glBindVertexArray(0)
|
|
100
|
+
|
|
101
|
+
return dict(prog=prog, u_size=gl.glGetUniformLocation(prog, "uSize"),
|
|
102
|
+
vao=vao, vbo=vbo, ebo=ebo)
|
|
103
|
+
|
|
104
|
+
def delete(resources):
|
|
105
|
+
gl.glDeleteVertexArrays(1, [int(resources["vao"])])
|
|
106
|
+
gl.glDeleteBuffers(2, [int(resources["vbo"]), int(resources["ebo"])])
|
|
107
|
+
gl.glDeleteProgram(resources["prog"])
|
|
108
|
+
|
|
109
|
+
return gl_state.get("text_pipeline", create, delete, deps=(_VS, _FS))
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def _ensure_context(gl_state):
|
|
113
|
+
"""A private layout context sharing this view's current font atlas."""
|
|
114
|
+
main = imgui.get_current_context()
|
|
115
|
+
if main is None:
|
|
116
|
+
raise RuntimeError("text_texture: no main imgui context")
|
|
117
|
+
|
|
118
|
+
def create():
|
|
119
|
+
context = imgui.create_context(shared_font_atlas=imgui.get_io().fonts)
|
|
120
|
+
try:
|
|
121
|
+
imgui.set_current_context(context)
|
|
122
|
+
io = imgui.get_io()
|
|
123
|
+
io.ini_file_name = None
|
|
124
|
+
io.display_size = (4096.0, 512.0)
|
|
125
|
+
io.delta_time = 1.0 / 60.0
|
|
126
|
+
finally:
|
|
127
|
+
imgui.set_current_context(main)
|
|
128
|
+
return context
|
|
129
|
+
|
|
130
|
+
def delete(context):
|
|
131
|
+
current = imgui.get_current_context()
|
|
132
|
+
imgui.destroy_context(context)
|
|
133
|
+
imgui.set_current_context(current)
|
|
134
|
+
|
|
135
|
+
return gl_state.get("text_layout", create, delete, deps=main)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
class _SavedGL:
|
|
139
|
+
"""Targeted save/restore of everything the bake pass touches."""
|
|
140
|
+
|
|
141
|
+
def __init__(self):
|
|
142
|
+
self.fbo = gl.glGetIntegerv(gl.GL_DRAW_FRAMEBUFFER_BINDING)
|
|
143
|
+
self.read_fbo = gl.glGetIntegerv(gl.GL_READ_FRAMEBUFFER_BINDING)
|
|
144
|
+
self.viewport = tuple(gl.glGetIntegerv(gl.GL_VIEWPORT))
|
|
145
|
+
self.program = gl.glGetIntegerv(gl.GL_CURRENT_PROGRAM)
|
|
146
|
+
self.vao = gl.glGetIntegerv(gl.GL_VERTEX_ARRAY_BINDING)
|
|
147
|
+
self.array_buffer = gl.glGetIntegerv(gl.GL_ARRAY_BUFFER_BINDING)
|
|
148
|
+
self.active_texture = gl.glGetIntegerv(gl.GL_ACTIVE_TEXTURE)
|
|
149
|
+
self.texture_2d = gl.glGetIntegerv(gl.GL_TEXTURE_BINDING_2D)
|
|
150
|
+
self.blend = bool(gl.glIsEnabled(gl.GL_BLEND))
|
|
151
|
+
self.scissor = bool(gl.glIsEnabled(gl.GL_SCISSOR_TEST))
|
|
152
|
+
self.depth = bool(gl.glIsEnabled(gl.GL_DEPTH_TEST))
|
|
153
|
+
self.cull = bool(gl.glIsEnabled(gl.GL_CULL_FACE))
|
|
154
|
+
|
|
155
|
+
def restore(self):
|
|
156
|
+
gl.glBindFramebuffer(gl.GL_DRAW_FRAMEBUFFER, self.fbo)
|
|
157
|
+
gl.glBindFramebuffer(gl.GL_READ_FRAMEBUFFER, self.read_fbo)
|
|
158
|
+
gl.glViewport(*self.viewport)
|
|
159
|
+
gl.glUseProgram(self.program)
|
|
160
|
+
gl.glBindVertexArray(self.vao)
|
|
161
|
+
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.array_buffer)
|
|
162
|
+
gl.glActiveTexture(self.active_texture)
|
|
163
|
+
gl.glBindTexture(gl.GL_TEXTURE_2D, self.texture_2d)
|
|
164
|
+
(gl.glEnable if self.blend else gl.glDisable)(gl.GL_BLEND)
|
|
165
|
+
(gl.glEnable if self.scissor else gl.glDisable)(gl.GL_SCISSOR_TEST)
|
|
166
|
+
(gl.glEnable if self.depth else gl.glDisable)(gl.GL_DEPTH_TEST)
|
|
167
|
+
(gl.glEnable if self.cull else gl.glDisable)(gl.GL_CULL_FACE)
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def _render_draw_data(dd, w, h, gl_state):
|
|
171
|
+
"""Render finalized draw data into a fresh RGBA8 (w, h) texture, exactly
|
|
172
|
+
like the screen pass: stream the vtx/idx pointers, draw per command. No
|
|
173
|
+
scissoring — the bake surface IS the clip."""
|
|
174
|
+
saved = _SavedGL()
|
|
175
|
+
fbo = gl.glGenFramebuffers(1)
|
|
176
|
+
tex = gl.glGenTextures(1)
|
|
177
|
+
try:
|
|
178
|
+
resources = _ensure_gl(gl_state)
|
|
179
|
+
gl.glBindTexture(gl.GL_TEXTURE_2D, tex)
|
|
180
|
+
gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGBA16F, w, h, 0,
|
|
181
|
+
gl.GL_RGBA, gl.GL_HALF_FLOAT, None)
|
|
182
|
+
gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER,
|
|
183
|
+
gl.GL_LINEAR_MIPMAP_LINEAR)
|
|
184
|
+
gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR)
|
|
185
|
+
gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S, gl.GL_CLAMP_TO_EDGE)
|
|
186
|
+
gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T, gl.GL_CLAMP_TO_EDGE)
|
|
187
|
+
gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, fbo)
|
|
188
|
+
gl.glFramebufferTexture2D(gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT0,
|
|
189
|
+
gl.GL_TEXTURE_2D, tex, 0)
|
|
190
|
+
if gl.glCheckFramebufferStatus(gl.GL_FRAMEBUFFER) != gl.GL_FRAMEBUFFER_COMPLETE:
|
|
191
|
+
raise RuntimeError("text_texture: bake FBO incomplete")
|
|
192
|
+
|
|
193
|
+
gl.glViewport(0, 0, w, h)
|
|
194
|
+
gl.glDisable(gl.GL_SCISSOR_TEST)
|
|
195
|
+
gl.glDisable(gl.GL_DEPTH_TEST)
|
|
196
|
+
gl.glDisable(gl.GL_CULL_FACE)
|
|
197
|
+
# WHITE-transparent, not black-transparent: mip levels average the
|
|
198
|
+
# RGB of empty texels into the glyph shape, and black gives scaled
|
|
199
|
+
# down/angled text a dark halo. White RGB everywhere keeps every mip
|
|
200
|
+
# level pure white with only coverage in alpha.
|
|
201
|
+
gl.glClearColor(1.0, 1.0, 1.0, 0.0)
|
|
202
|
+
gl.glClear(gl.GL_COLOR_BUFFER_BIT)
|
|
203
|
+
gl.glEnable(gl.GL_BLEND)
|
|
204
|
+
gl.glBlendEquation(gl.GL_FUNC_ADD)
|
|
205
|
+
# ONE/ONE_MINUS_SRC_ALPHA on the alpha channel so coverage accumulates
|
|
206
|
+
# into a transparent target instead of multiplying away.
|
|
207
|
+
gl.glBlendFuncSeparate(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA,
|
|
208
|
+
gl.GL_ONE, gl.GL_ONE_MINUS_SRC_ALPHA)
|
|
209
|
+
|
|
210
|
+
gl.glUseProgram(resources["prog"])
|
|
211
|
+
gl.glUniform2f(resources["u_size"], float(w), float(h))
|
|
212
|
+
set_decode_uniforms(resources["prog"])
|
|
213
|
+
gl.glActiveTexture(gl.GL_TEXTURE0)
|
|
214
|
+
gl.glBindVertexArray(resources["vao"])
|
|
215
|
+
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, resources["vbo"])
|
|
216
|
+
gltype = gl.GL_UNSIGNED_SHORT if imgui.INDEX_SIZE == 2 else gl.GL_UNSIGNED_INT
|
|
217
|
+
for commands in dd.commands_lists:
|
|
218
|
+
gl.glBufferData(gl.GL_ARRAY_BUFFER,
|
|
219
|
+
commands.vtx_buffer_size * imgui.VERTEX_SIZE,
|
|
220
|
+
ctypes.c_void_p(commands.vtx_buffer_data), gl.GL_STREAM_DRAW)
|
|
221
|
+
gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, resources["ebo"])
|
|
222
|
+
gl.glBufferData(gl.GL_ELEMENT_ARRAY_BUFFER,
|
|
223
|
+
commands.idx_buffer_size * imgui.INDEX_SIZE,
|
|
224
|
+
ctypes.c_void_p(commands.idx_buffer_data), gl.GL_STREAM_DRAW)
|
|
225
|
+
offset = 0
|
|
226
|
+
for cmd in commands.commands:
|
|
227
|
+
gl.glBindTexture(gl.GL_TEXTURE_2D, cmd.texture_id)
|
|
228
|
+
gl.glDrawElements(gl.GL_TRIANGLES, cmd.elem_count, gltype,
|
|
229
|
+
ctypes.c_void_p(offset))
|
|
230
|
+
offset += cmd.elem_count * imgui.INDEX_SIZE
|
|
231
|
+
gl.glBindVertexArray(0)
|
|
232
|
+
|
|
233
|
+
# Trilinear mips + anisotropy keep scaled/angled billboard sampling
|
|
234
|
+
# sharp instead of shimmering. Anisotropic filtering is technically an
|
|
235
|
+
# extension (universally supported) - soft-fail if the driver lacks it.
|
|
236
|
+
gl.glBindTexture(gl.GL_TEXTURE_2D, tex)
|
|
237
|
+
gl.glGenerateMipmap(gl.GL_TEXTURE_2D)
|
|
238
|
+
try:
|
|
239
|
+
GL_TEXTURE_MAX_ANISOTROPY = 0x84FE
|
|
240
|
+
GL_MAX_TEXTURE_MAX_ANISOTROPY = 0x84FF
|
|
241
|
+
max_aniso = gl.glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY)
|
|
242
|
+
gl.glTexParameterf(gl.GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY,
|
|
243
|
+
min(8.0, float(max_aniso)))
|
|
244
|
+
except Exception:
|
|
245
|
+
pass
|
|
246
|
+
except Exception:
|
|
247
|
+
gl.glDeleteTextures([tex])
|
|
248
|
+
raise
|
|
249
|
+
finally:
|
|
250
|
+
gl.glDeleteFramebuffers(1, [fbo])
|
|
251
|
+
saved.restore()
|
|
252
|
+
return GLTexture(tex, gl.GL_TEXTURE_2D, (h, w), gl.GL_RGBA16F)
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def bake_text(text, gl_state: GLState, font=None, pad=2):
|
|
256
|
+
"""Rasterize one line of `text` into a fresh RGBA8 GLTexture — white
|
|
257
|
+
glyphs on transparent, `pad` transparent pixels on every side, texture
|
|
258
|
+
v=1 at the TOP of the text. `font` is any shared-atlas handle (e.g.
|
|
259
|
+
Melty.font_mgr.get(Font.JETBRAINS_MONO_30)); None = the atlas default.
|
|
260
|
+
The caller owns deletion (glDeleteTextures)."""
|
|
261
|
+
main = imgui.get_current_context()
|
|
262
|
+
ctx = _ensure_context(gl_state)
|
|
263
|
+
imgui.set_current_context(ctx)
|
|
264
|
+
try:
|
|
265
|
+
io = imgui.get_io()
|
|
266
|
+
io.delta_time = 1.0 / 60.0
|
|
267
|
+
imgui.new_frame()
|
|
268
|
+
if font is not None:
|
|
269
|
+
imgui.push_font(font)
|
|
270
|
+
try:
|
|
271
|
+
ts = imgui.calc_text_size(text)
|
|
272
|
+
w = max(1, int(ts.x + 0.5)) + pad * 2
|
|
273
|
+
h = max(1, int(ts.y + 0.5)) + pad * 2
|
|
274
|
+
imgui.get_overlay_draw_list().add_text(
|
|
275
|
+
float(pad), float(pad), pack_color(1, 1, 1, 1), text)
|
|
276
|
+
finally:
|
|
277
|
+
if font is not None:
|
|
278
|
+
imgui.pop_font()
|
|
279
|
+
imgui.render()
|
|
280
|
+
return _render_draw_data(imgui.get_draw_data(), w, h, gl_state)
|
|
281
|
+
finally:
|
|
282
|
+
imgui.set_current_context(main)
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
def bake_texts(texts, gl_state: GLState, font=None, pad=2, gap=8):
|
|
286
|
+
"""Rasterize MANY strings into ONE texture (a vertical-strip atlas), so a
|
|
287
|
+
whole label set renders as a single instanced draw. Returns
|
|
288
|
+
(GLTexture, {text: (u0, v0, u1, v1, px_w, px_h)}) with v1 at the TOP of
|
|
289
|
+
each string. `gap` transparent rows between entries keep mip levels from
|
|
290
|
+
bleeding neighbours into each other (labels draw near 1:1, so only the
|
|
291
|
+
first mips matter)."""
|
|
292
|
+
texts = list(dict.fromkeys(texts)) # de-dupe, preserving order
|
|
293
|
+
main = imgui.get_current_context()
|
|
294
|
+
ctx = _ensure_context(gl_state)
|
|
295
|
+
imgui.set_current_context(ctx)
|
|
296
|
+
try:
|
|
297
|
+
io = imgui.get_io()
|
|
298
|
+
io.display_size = (4096.0, 16384.0) # layout surface; never rendered
|
|
299
|
+
io.delta_time = 1.0 / 60.0
|
|
300
|
+
imgui.new_frame()
|
|
301
|
+
if font is not None:
|
|
302
|
+
imgui.push_font(font)
|
|
303
|
+
try:
|
|
304
|
+
dl = imgui.get_overlay_draw_list()
|
|
305
|
+
col = pack_color(1, 1, 1, 1)
|
|
306
|
+
rows, y, w_max = {}, 0, 1
|
|
307
|
+
for t in texts:
|
|
308
|
+
ts = imgui.calc_text_size(t)
|
|
309
|
+
w = max(1, int(ts.x + 0.5)) + pad * 2
|
|
310
|
+
h = max(1, int(ts.y + 0.5)) + pad * 2
|
|
311
|
+
dl.add_text(float(pad), float(y + pad), col, t)
|
|
312
|
+
rows[t] = (y, w, h)
|
|
313
|
+
w_max = max(w_max, w)
|
|
314
|
+
y += h + gap
|
|
315
|
+
height = max(1, y - gap)
|
|
316
|
+
finally:
|
|
317
|
+
if font is not None:
|
|
318
|
+
imgui.pop_font()
|
|
319
|
+
imgui.render()
|
|
320
|
+
tex = _render_draw_data(imgui.get_draw_data(), w_max, height, gl_state)
|
|
321
|
+
finally:
|
|
322
|
+
imgui.set_current_context(main)
|
|
323
|
+
rects = {}
|
|
324
|
+
for t, (y0, w, h) in rows.items():
|
|
325
|
+
rects[t] = (0.0, 1.0 - (y0 + h) / height, # u0, v0 (bottom)
|
|
326
|
+
w / w_max, 1.0 - y0 / height, # u1, v1 (top)
|
|
327
|
+
w, h)
|
|
328
|
+
# consistency with bake_text: display y=0 maps to v=1
|
|
329
|
+
return tex, rects
|