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.
Files changed (372) hide show
  1. meltygui/__init__.py +107 -0
  2. meltygui/accounts/__init__.py +0 -0
  3. meltygui/accounts/internet_accounts.py +1355 -0
  4. meltygui/chat/__init__.py +91 -0
  5. meltygui/chat/activity.py +75 -0
  6. meltygui/chat/backends.py +36 -0
  7. meltygui/chat/chat_interface.py +732 -0
  8. meltygui/chat/chat_proxy.py +352 -0
  9. meltygui/chat/codex_proxy.py +592 -0
  10. meltygui/chat/codex_settings.py +100 -0
  11. meltygui/chat/codex_transport.py +60 -0
  12. meltygui/chat/command_parser.py +204 -0
  13. meltygui/chat/images.py +227 -0
  14. meltygui/chat/messages.py +417 -0
  15. meltygui/chat/metadata.py +139 -0
  16. meltygui/chat/writer_locks.py +64 -0
  17. meltygui/code/__init__.py +0 -0
  18. meltygui/code/basic_converters.py +533 -0
  19. meltygui/code/chain_converters.py +2111 -0
  20. meltygui/code/code_checks.py +2209 -0
  21. meltygui/code/core_syntax.py +1430 -0
  22. meltygui/code/file_converters.py +1933 -0
  23. meltygui/code/fileref.py +702 -0
  24. meltygui/code/hotswap_guard.py +144 -0
  25. meltygui/code/libcst_conversion.py +9724 -0
  26. meltygui/code/live_instrument.py +392 -0
  27. meltygui/code/live_view.py +2490 -0
  28. meltygui/code/melty_scan.py +2684 -0
  29. meltygui/code/new_codecs.py +1255 -0
  30. meltygui/code/new_converters.py +3017 -0
  31. meltygui/code/project_code.py +278 -0
  32. meltygui/code/source_context.py +63 -0
  33. meltygui/code/symbol_roster.py +1588 -0
  34. meltygui/code/syntax_check.py +34 -0
  35. meltygui/code/syntax_check_worker.py +114 -0
  36. meltygui/completion/__init__.py +0 -0
  37. meltygui/completion/fim.py +1232 -0
  38. meltygui/completion/fim_context.py +481 -0
  39. meltygui/completion/providers/__init__.py +0 -0
  40. meltygui/completion/providers/anthropic_oauth.py +446 -0
  41. meltygui/completion/providers/anthropic_requests.py +69 -0
  42. meltygui/completion/providers/claude.py +203 -0
  43. meltygui/completion/providers/claude_usage.py +499 -0
  44. meltygui/completion/providers/codex_accounts.py +180 -0
  45. meltygui/completion/providers/copilot.py +617 -0
  46. meltygui/completion/providers/oauth_popup.py +220 -0
  47. meltygui/completion/providers/ollama.py +320 -0
  48. meltygui/completion/providers/profiles.py +23 -0
  49. meltygui/core/README.md +88 -0
  50. meltygui/core/__init__.py +1 -0
  51. meltygui/core/automation/__init__.py +1 -0
  52. meltygui/core/automation/action_core.py +153 -0
  53. meltygui/core/automation/collection_action.py +45 -0
  54. meltygui/core/automation/mcp_eval.py +167 -0
  55. meltygui/core/automation/mcp_hotswap.py +107 -0
  56. meltygui/core/automation/mcp_query.py +552 -0
  57. meltygui/core/automation/mcp_server.py +657 -0
  58. meltygui/core/automation/orchestration_core.py +2636 -0
  59. meltygui/core/automation/query_core.py +124 -0
  60. meltygui/core/automation/search_core.py +26 -0
  61. meltygui/core/automation/selector_core.py +340 -0
  62. meltygui/core/automation/value_core.py +1752 -0
  63. meltygui/core/cache/__init__.py +1 -0
  64. meltygui/core/cache/cache_diagnostics.py +0 -0
  65. meltygui/core/cache/invalidation_decoration.py +153 -0
  66. meltygui/core/cache/invalidation_tracker.py +43 -0
  67. meltygui/core/cache/tile_cache.py +5968 -0
  68. meltygui/core/conversion/__init__.py +1 -0
  69. meltygui/core/conversion/bubbling.py +599 -0
  70. meltygui/core/conversion/cache_tree.py +188 -0
  71. meltygui/core/conversion/chain.py +113 -0
  72. meltygui/core/conversion/converter_register.py +145 -0
  73. meltygui/core/conversion/data_decoration.py +67 -0
  74. meltygui/core/conversion/dict_conversion.py +1815 -0
  75. meltygui/core/conversion/dict_conversion_util.py +177 -0
  76. meltygui/core/conversion/dynamic_obj.py +89 -0
  77. meltygui/core/conversion/graph_compare.py +183 -0
  78. meltygui/core/conversion/load_save_v2.py +1032 -0
  79. meltygui/core/conversion/missing_saved_class.py +39 -0
  80. meltygui/core/conversion/path_finder.py +606 -0
  81. meltygui/core/conversion/render_host.py +1083 -0
  82. meltygui/core/core_render.py +6537 -0
  83. meltygui/core/definition_hotswap.py +231 -0
  84. meltygui/core/diagnostics/__init__.py +1 -0
  85. meltygui/core/diagnostics/attribute_churn.py +38 -0
  86. meltygui/core/diagnostics/fps_counter.py +39 -0
  87. meltygui/core/diagnostics/gpu_frame_timer.py +103 -0
  88. meltygui/core/diagnostics/inspection_core.py +169 -0
  89. meltygui/core/diagnostics/monitor_core.py +105 -0
  90. meltygui/core/diagnostics/notifications.py +706 -0
  91. meltygui/core/diagnostics/perf_trace.py +281 -0
  92. meltygui/core/diagnostics/profile_decoration.py +88 -0
  93. meltygui/core/diagnostics/resize_trace.py +62 -0
  94. meltygui/core/diagnostics/screenshot_core.py +247 -0
  95. meltygui/core/diagnostics/session_status.py +98 -0
  96. meltygui/core/diagnostics/trace_core.py +445 -0
  97. meltygui/core/files/__init__.py +1 -0
  98. meltygui/core/files/file_core.py +208 -0
  99. meltygui/core/files/file_explorer_core.py +104 -0
  100. meltygui/core/files/file_tree_core.py +198 -0
  101. meltygui/core/files/file_watch_core.py +43 -0
  102. meltygui/core/files/import_graph_core.py +43 -0
  103. meltygui/core/files/metadata_core.py +51 -0
  104. meltygui/core/graphics/__init__.py +1 -0
  105. meltygui/core/graphics/cuda_context_core.py +166 -0
  106. meltygui/core/graphics/cuda_interop_core.py +136 -0
  107. meltygui/core/graphics/cuda_kernel_core.py +91 -0
  108. meltygui/core/graphics/framebuffer_recorder.py +337 -0
  109. meltygui/core/graphics/gl_state.py +658 -0
  110. meltygui/core/graphics/lut_core.py +52 -0
  111. meltygui/core/graphics/overlay_renderer.py +984 -0
  112. meltygui/core/graphics/scene_target.py +180 -0
  113. meltygui/core/graphics/screenshot.py +439 -0
  114. meltygui/core/graphics/shader_func.py +478 -0
  115. meltygui/core/graphics/tensor_core.py +45 -0
  116. meltygui/core/graphics/text_texture.py +329 -0
  117. meltygui/core/graphics/wayland_color.py +635 -0
  118. meltygui/core/input/__init__.py +1 -0
  119. meltygui/core/input/collision.py +165 -0
  120. meltygui/core/input/drag_drop_core.py +1525 -0
  121. meltygui/core/input/hypr_left_drag.py +323 -0
  122. meltygui/core/input/input_core.py +245 -0
  123. meltygui/core/input/input_handler.py +1101 -0
  124. meltygui/core/input/mouse_cursor.py +355 -0
  125. meltygui/core/input/pynput_backend.py +1054 -0
  126. meltygui/core/input/space_mouse.py +338 -0
  127. meltygui/core/input/touchpad_backend.py +393 -0
  128. meltygui/core/input/view_selection.py +177 -0
  129. meltygui/core/layout/__init__.py +1 -0
  130. meltygui/core/layout/column_core.py +2153 -0
  131. meltygui/core/layout/cursor_core.py +161 -0
  132. meltygui/core/layout/dropdown_core.py +278 -0
  133. meltygui/core/layout/edge_constraints.py +155 -0
  134. meltygui/core/layout/grid_core.py +117 -0
  135. meltygui/core/layout/header_core.py +23 -0
  136. meltygui/core/layout/header_runtime.py +67 -0
  137. meltygui/core/layout/layout_core.py +87 -0
  138. meltygui/core/layout/tile_manager_core.py +591 -0
  139. meltygui/core/melty.py +6726 -0
  140. meltygui/core/module_map.json +896 -0
  141. meltygui/core/module_names.py +19 -0
  142. meltygui/core/rendering/__init__.py +1 -0
  143. meltygui/core/rendering/core_decoration.py +431 -0
  144. meltygui/core/rendering/core_render_helpers.py +328 -0
  145. meltygui/core/rendering/func_metadata.py +398 -0
  146. meltygui/core/rendering/mode.py +818 -0
  147. meltygui/core/rendering/mode_defaults.py +41 -0
  148. meltygui/core/rendering/modes.py +136 -0
  149. meltygui/core/rendering/parameter_core.py +1665 -0
  150. meltygui/core/rendering/render_dispatch.py +1891 -0
  151. meltygui/core/rendering/render_funcs.py +273 -0
  152. meltygui/core/rendering/shaped.py +312 -0
  153. meltygui/core/rendering/window_decoration.py +25 -0
  154. meltygui/core/runtime/__init__.py +1 -0
  155. meltygui/core/runtime/app.py +735 -0
  156. meltygui/core/runtime/app_session.py +140 -0
  157. meltygui/core/runtime/background.py +564 -0
  158. meltygui/core/runtime/extensions.py +53 -0
  159. meltygui/core/runtime/gc_manager.py +1163 -0
  160. meltygui/core/runtime/lifecycle.py +21 -0
  161. meltygui/core/runtime/paths.py +27 -0
  162. meltygui/core/runtime/settings.py +14 -0
  163. meltygui/core/runtime/singleton.py +16 -0
  164. meltygui/core/runtime/thread_safe_bool.py +24 -0
  165. meltygui/core/runtime/thread_signal.py +30 -0
  166. meltygui/core/runtime/toggles.py +3115 -0
  167. meltygui/core/services/__init__.py +1 -0
  168. meltygui/core/services/account_core.py +10 -0
  169. meltygui/core/services/chat_core.py +19 -0
  170. meltygui/core/services/claude_terminal_core.py +346 -0
  171. meltygui/core/services/terminal_core.py +458 -0
  172. meltygui/core/services/terminal_runtime.py +78 -0
  173. meltygui/core/styling/__init__.py +1 -0
  174. meltygui/core/styling/color_core.py +46 -0
  175. meltygui/core/styling/fonts.py +639 -0
  176. meltygui/core/styling/global_style.py +338 -0
  177. meltygui/core/styling/style.py +198 -0
  178. meltygui/core/styling/style_core.py +522 -0
  179. meltygui/core/styling/warm_start.py +149 -0
  180. meltygui/core/windowing/__init__.py +1 -0
  181. meltygui/core/windowing/backends/PYIMGUI_LICENSE +28 -0
  182. meltygui/core/windowing/backends/__init__.py +1 -0
  183. meltygui/core/windowing/backends/imgui_renderer.py +138 -0
  184. meltygui/core/windowing/backends/native_wayland.py +850 -0
  185. meltygui/core/windowing/backends/protocols/xdg-decoration-unstable-v1.xml +156 -0
  186. meltygui/core/windowing/backends/protocols/xdg-shell.xml +1420 -0
  187. meltygui/core/windowing/backends/wayland_protocol.py +101 -0
  188. meltygui/core/windowing/dock_core.py +182 -0
  189. meltygui/core/windowing/frame_geometry.py +42 -0
  190. meltygui/core/windowing/geometry_feed.py +864 -0
  191. meltygui/core/windowing/glfw_utils.py +1343 -0
  192. meltygui/core/windowing/os_frame.py +1552 -0
  193. meltygui/core/windowing/surface.py +643 -0
  194. meltygui/core/windowing/titlebar.py +1560 -0
  195. meltygui/core/windowing/titlebar_buttons.py +281 -0
  196. meltygui/core/windowing/wayland_move.py +932 -0
  197. meltygui/core/windowing/window_api.py +62 -0
  198. meltygui/core/windowing/window_constants.py +339 -0
  199. meltygui/core/windowing/window_visibility.py +162 -0
  200. meltygui/debug/__init__.py +0 -0
  201. meltygui/debug/app_view_utils.py +9 -0
  202. meltygui/editor/__init__.py +0 -0
  203. meltygui/editor/bash_syntax.py +30 -0
  204. meltygui/editor/code_line_fast.py +152 -0
  205. meltygui/editor/diff.py +139 -0
  206. meltygui/editor/external_changes.py +159 -0
  207. meltygui/editor/file_header.py +41 -0
  208. meltygui/editor/live_usage.py +169 -0
  209. meltygui/editor/live_view_views.py +1803 -0
  210. meltygui/editor/pending_save.py +1351 -0
  211. meltygui/editor/roster_tints.py +547 -0
  212. meltygui/editor/source_preview.py +16 -0
  213. meltygui/editor/source_tools.py +10 -0
  214. meltygui/editor/source_ui.py +70 -0
  215. meltygui/editor/spell_check.py +77 -0
  216. meltygui/editor/text_editor.py +9076 -0
  217. meltygui/editor/usage_picker.py +538 -0
  218. meltygui/events/__init__.py +0 -0
  219. meltygui/events/example.py +118 -0
  220. meltygui/examples/__init__.py +0 -0
  221. meltygui/examples/columns_demo.py +33 -0
  222. meltygui/examples/columns_window_demo.py +60 -0
  223. meltygui/examples/context_menu_demo.py +24 -0
  224. meltygui/examples/context_menu_window_demo.py +49 -0
  225. meltygui/examples/gui_playground.py +127 -0
  226. meltygui/examples/live_view_playground.py +256 -0
  227. meltygui/examples/lora.py +43 -0
  228. meltygui/examples/lora_data.py +59 -0
  229. meltygui/examples/lora_policies.py +67 -0
  230. meltygui/examples/mode_demo.py +49 -0
  231. meltygui/examples/modifies_demo.py +119 -0
  232. meltygui/examples/scalar_policies.py +60 -0
  233. meltygui/examples/style_layouts.py +149 -0
  234. meltygui/examples/tile_manager_demo.py +74 -0
  235. meltygui/examples/tint_demo.py +160 -0
  236. meltygui/examples/tint_functions.py +56 -0
  237. meltygui/examples/trace_demo.py +88 -0
  238. meltygui/examples/two_windows.py +36 -0
  239. meltygui/files/__init__.py +0 -0
  240. meltygui/files/fast_file_explorer.py +439 -0
  241. meltygui/gnome_extension/lsd-window-geometry@latent-descent/extension.js +237 -0
  242. meltygui/gnome_extension/lsd-window-geometry@latent-descent/lsd-window-geometry@latent-descent.iml +9 -0
  243. meltygui/gnome_extension/lsd-window-geometry@latent-descent/metadata.json +7 -0
  244. meltygui/graphics/__init__.py +6 -0
  245. meltygui/graphics/base.py +85 -0
  246. meltygui/graphics/examples.py +507 -0
  247. meltygui/graphics/executor.py +520 -0
  248. meltygui/graphics/filter.py +667 -0
  249. meltygui/graphics/filter.pyi +856 -0
  250. meltygui/graphics/generate_stubs.py +22 -0
  251. meltygui/graphics/registry.py +203 -0
  252. meltygui/graphics/shader_compiler.py +155 -0
  253. meltygui/graphics/shaders.py +1302 -0
  254. meltygui/graphics/stub_generator.py +250 -0
  255. meltygui/graphics/texture_manager.py +170 -0
  256. meltygui/graphics/texture_min_max.py +295 -0
  257. meltygui/hdr_color.py +757 -0
  258. meltygui/image_load.py +308 -0
  259. meltygui/model/__init__.py +1 -0
  260. meltygui/model/account_model.py +142 -0
  261. meltygui/model/camera_model.py +159 -0
  262. meltygui/model/chat_model.py +86 -0
  263. meltygui/model/code_model.py +62 -0
  264. meltygui/model/code_proxy_model.py +876 -0
  265. meltygui/model/collection_model.py +41 -0
  266. meltygui/model/color_model.py +127 -0
  267. meltygui/model/cuda_tensor_model.py +36 -0
  268. meltygui/model/cuda_texture_model.py +149 -0
  269. meltygui/model/dropdown_model.py +137 -0
  270. meltygui/model/file_metadata_model.py +73 -0
  271. meltygui/model/file_model.py +289 -0
  272. meltygui/model/format_model.py +390 -0
  273. meltygui/model/graph_model.py +98 -0
  274. meltygui/model/icon_model.py +1024 -0
  275. meltygui/model/import_graph_model.py +468 -0
  276. meltygui/model/layout_model.py +15 -0
  277. meltygui/model/lut_model.py +266 -0
  278. meltygui/model/search_model.py +173 -0
  279. meltygui/model/tensor_model.py +402 -0
  280. meltygui/model/terminal_model.py +329 -0
  281. meltygui/model/texture_model.py +146 -0
  282. meltygui/model/tile_model.py +24 -0
  283. meltygui/model/trace_model.py +198 -0
  284. meltygui/model/trace_report_model.py +146 -0
  285. meltygui/models/__init__.py +0 -0
  286. meltygui/models/file_meta.py +613 -0
  287. meltygui/models/function_console.py +184 -0
  288. meltygui/models/orchestration.py +48 -0
  289. meltygui/pbr.py +1576 -0
  290. meltygui/png_unfilter.c +49 -0
  291. meltygui/resources/JetBrainsMono-Regular.ttf +0 -0
  292. meltygui/resources/THIRD_PARTY_NOTICES.md +21 -0
  293. meltygui/resources/dejavu/DejaVuSans-Bold.ttf +0 -0
  294. meltygui/resources/dejavu/DejaVuSans-ExtraLight.ttf +0 -0
  295. meltygui/resources/dejavu/DejaVuSans.ttf +0 -0
  296. meltygui/resources/dejavu/LICENSE.txt +78 -0
  297. meltygui/resources/fontawesome-LICENSE.txt +121 -0
  298. meltygui/resources/fontawesome-webfont.ttf +0 -0
  299. meltygui/resources/hdri/studio_small_09_1k.hdr +0 -0
  300. meltygui/resources/jetbrains-weights/JetBrainsMono-Bold.ttf +0 -0
  301. meltygui/resources/jetbrains-weights/JetBrainsMono-ExtraBold.ttf +0 -0
  302. meltygui/resources/jetbrains-weights/JetBrainsMono-ExtraLight.ttf +0 -0
  303. meltygui/resources/jetbrains-weights/JetBrainsMono-Light.ttf +0 -0
  304. meltygui/resources/jetbrains-weights/JetBrainsMono-Medium.ttf +0 -0
  305. meltygui/resources/jetbrains-weights/JetBrainsMono-SemiBold.ttf +0 -0
  306. meltygui/resources/jetbrains-weights/JetBrainsMono-Thin.ttf +0 -0
  307. meltygui/resources/jetbrains-weights/OFL.txt +93 -0
  308. meltygui/resources/jetbrains-weights/README.md +2 -0
  309. meltygui/state/__init__.py +0 -0
  310. meltygui/state/account_state.py +22 -0
  311. meltygui/state/animation_state.py +97 -0
  312. meltygui/state/annotation_state.py +22 -0
  313. meltygui/state/chat_state.py +36 -0
  314. meltygui/state/code_state.py +10 -0
  315. meltygui/state/core_enums.py +59 -0
  316. meltygui/state/core_markers.py +115 -0
  317. meltygui/state/core_undo.py +1075 -0
  318. meltygui/state/file_state.py +75 -0
  319. meltygui/state/graph_state.py +26 -0
  320. meltygui/state/inspection_state.py +47 -0
  321. meltygui/state/menu_state.py +10 -0
  322. meltygui/state/model_enums.py +11 -0
  323. meltygui/state/new_core_model.py +2394 -0
  324. meltygui/state/orchestration_state.py +14 -0
  325. meltygui/state/query_state.py +24 -0
  326. meltygui/state/tensor_state.py +10 -0
  327. meltygui/state/terminal_state.py +23 -0
  328. meltygui/state/trace_state.py +32 -0
  329. meltygui/state/voxel_state.py +12 -0
  330. meltygui/text_index.py +816 -0
  331. meltygui/utils/__init__.py +0 -0
  332. meltygui/utils/jump_to_code.py +344 -0
  333. meltygui/utils/pkl_inspect.py +90 -0
  334. meltygui/utils/render_utils.py +1419 -0
  335. meltygui/view/__init__.py +1 -0
  336. meltygui/view/account_view.py +524 -0
  337. meltygui/view/action_view.py +73 -0
  338. meltygui/view/chat_decoration_view.py +112 -0
  339. meltygui/view/chat_view.py +1703 -0
  340. meltygui/view/code_view.py +2677 -0
  341. meltygui/view/collection_view.py +1185 -0
  342. meltygui/view/color_view.py +824 -0
  343. meltygui/view/control_view.py +559 -0
  344. meltygui/view/decoration_view.py +439 -0
  345. meltygui/view/diagnostic_view.py +177 -0
  346. meltygui/view/dropdown_view.py +1082 -0
  347. meltygui/view/file_view.py +1599 -0
  348. meltygui/view/graph_cuda_view.py +105 -0
  349. meltygui/view/graph_view.py +882 -0
  350. meltygui/view/header_view.py +848 -0
  351. meltygui/view/input_view.py +238 -0
  352. meltygui/view/inspection_view.py +1783 -0
  353. meltygui/view/layout_view.py +596 -0
  354. meltygui/view/lut_view.py +45 -0
  355. meltygui/view/menu_view.py +212 -0
  356. meltygui/view/orchestration_view.py +658 -0
  357. meltygui/view/query_view.py +118 -0
  358. meltygui/view/search_view.py +342 -0
  359. meltygui/view/tab_view.py +258 -0
  360. meltygui/view/tensor_view.py +430 -0
  361. meltygui/view/terminal_view.py +355 -0
  362. meltygui/view/text_view.py +8031 -0
  363. meltygui/view/texture_view.py +480 -0
  364. meltygui/view/tile_view.py +38 -0
  365. meltygui/view/trace_view.py +923 -0
  366. meltygui/view/voxel_cuda_view.py +824 -0
  367. meltygui/view/voxel_view.py +1860 -0
  368. meltygui/view/window_view.py +111 -0
  369. meltygui-0.1.0.dist-info/METADATA +143 -0
  370. meltygui-0.1.0.dist-info/RECORD +372 -0
  371. meltygui-0.1.0.dist-info/WHEEL +4 -0
  372. 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