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,328 @@
1
+ import meltygui_imgui as imgui
2
+ from meltygui.hdr_color import pack_color
3
+
4
+ from meltygui.core.melty import Melty
5
+
6
+ # Cache to track used space - key is snapped y position, value is max x used
7
+ _floating_text_cache = {}
8
+ _floating_text_prev_frame_heights = {} # Store max label height per line from previous frame
9
+
10
+
11
+ def floating_text(text: str, x_offset: float = 0, line_height: float = None, tint: tuple = (1, 1, 1, 1),
12
+ max_width: float = 200):
13
+ cursor_pos = imgui.get_cursor_screen_pos()
14
+
15
+ inside_window = len(Melty.window_stack) > 0
16
+
17
+ # Get draw list - only use overlay
18
+ draw_list = imgui.get_overlay_draw_list()
19
+ window_pos = Melty.melty_window_stack[-1][0] if len(Melty.melty_window_stack) else imgui.get_window_position()
20
+
21
+ # Get current window ID to track labels per-window
22
+ window_id = Melty.window_stack[-1] if len(Melty.window_stack) > 0 else 0
23
+
24
+ # Account for scroll offset
25
+ scroll_x = imgui.get_scroll_x()
26
+ scroll_y = imgui.get_scroll_y()
27
+
28
+ # Check if the cursor position (in content space) is within the visible content area
29
+ content_min = imgui.get_window_content_region_min()
30
+ content_max = imgui.get_window_content_region_max()
31
+ content_height = content_max.y - content_min.y
32
+
33
+ # Don't render if outside the scrolled content bounds
34
+ if cursor_pos[1] < scroll_y or cursor_pos[1] > scroll_y + content_height:
35
+ return
36
+
37
+ # Starting position (cursor position in screen coordinates, adjusted for scroll)
38
+ start_x = cursor_pos[0] - scroll_x
39
+ start_y = cursor_pos[1] - scroll_y
40
+
41
+ padding = 4
42
+ spacing = 8
43
+
44
+ # Check if text needs wrapping
45
+ single_line_size = imgui.calc_text_size(text)
46
+ text_line_height = imgui.get_text_line_height()
47
+
48
+ # Split text into lines if needed
49
+ text_lines = []
50
+ if single_line_size.x > max_width:
51
+ # Text needs wrapping - manually split by words
52
+ words = text.split(' ')
53
+ current_line = ""
54
+
55
+ for word in words:
56
+ test_line = current_line + (" " if current_line else "") + word
57
+ test_size = imgui.calc_text_size(test_line)
58
+ if test_size.x <= max_width:
59
+ current_line = test_line
60
+ else:
61
+ if current_line:
62
+ text_lines.append(current_line)
63
+ current_line = word
64
+ else:
65
+ # Single word is too long, just add it anyway
66
+ text_lines.append(word)
67
+ current_line = ""
68
+ if current_line:
69
+ text_lines.append(current_line)
70
+ else:
71
+ text_lines = [text]
72
+
73
+ # Use imgui's calc_text_size with wrap_width to get proper wrapped size
74
+ wrapped_size = imgui.calc_text_size(text, wrap_width=max_width)
75
+ text_width = wrapped_size.x
76
+ total_text_height = wrapped_size.y
77
+
78
+ # Use text height for line snapping if not specified
79
+ if line_height is None:
80
+ line_height = text_line_height + padding * 2
81
+
82
+ # Calculate label height
83
+ label_height = total_text_height + padding * 2
84
+
85
+ # Snap to line index based on cursor position
86
+ relative_y = cursor_pos[1] - scroll_y
87
+ line_index = round(relative_y / line_height)
88
+
89
+ # Calculate actual y by summing previous lines' heights from previous frame
90
+ actual_y = 0
91
+ for i in range(line_index):
92
+ prev_key = (window_id, i)
93
+ if prev_key in _floating_text_prev_frame_heights:
94
+ actual_y += _floating_text_prev_frame_heights[prev_key]
95
+ else:
96
+ actual_y += line_height # default height if not set
97
+
98
+ snapped_y = actual_y
99
+
100
+ # Track max label height for this line in current frame
101
+ window_key = Melty.melty_window_stack[-1][2] if len(Melty.melty_window_stack) > 0 else 0
102
+ cache_key = (window_key, line_index)
103
+ if cache_key in _floating_text_cache:
104
+ cache_data = _floating_text_cache[cache_key]
105
+ cache_data['max_height'] = max(cache_data.get('max_height', 0), label_height)
106
+ left_x = cache_data.get('left_x', float('inf'))
107
+ else:
108
+ _floating_text_cache[cache_key] = {
109
+ 'max_height': label_height,
110
+ 'left_x': float('inf')
111
+ }
112
+ left_x = float('inf')
113
+
114
+ # Calculate x position relative to window (right edge of label)
115
+ current_x_right = window_pos[0] + x_offset
116
+
117
+ # Check for horizontal overlap at this y position
118
+ if current_x_right >= left_x:
119
+ current_x_right = left_x - spacing
120
+
121
+ # Calculate left edge of this label
122
+ label_left = current_x_right - text_width - padding * 2
123
+
124
+ # Update cache with this line's x position
125
+ _floating_text_cache[cache_key]['left_x'] = label_left
126
+
127
+ # Text position (left edge)
128
+ text_x = label_left + padding
129
+ text_y = snapped_y
130
+
131
+ # End position for the line (right edge of label box, middle height)
132
+ end_x = current_x_right - padding
133
+ end_y = text_y
134
+
135
+ # Check if mouse is hovering over the text box
136
+ mouse_pos = imgui.get_mouse_pos()
137
+ is_hovered = (mouse_pos.x >= text_x - padding and
138
+ mouse_pos.x <= text_x + text_width + padding and
139
+ mouse_pos.y >= text_y - padding and
140
+ mouse_pos.y <= text_y + label_height - padding)
141
+
142
+ # Calculate control points for S-curve
143
+ horizontal_distance = end_x - start_x
144
+ curve_offset = abs(horizontal_distance) * 0.5
145
+
146
+ cp1_x = start_x + curve_offset if horizontal_distance > 0 else start_x - curve_offset
147
+ cp1_y = start_y
148
+ cp2_x = end_x - curve_offset if horizontal_distance > 0 else end_x + curve_offset
149
+ cp2_y = end_y
150
+
151
+ # Use channels: 0 for lines (back), 1 for boxes (front)
152
+ if is_hovered:
153
+ line_channel = 0
154
+ line_color = pack_color(1, 1, 1, 1)
155
+ dot_color = pack_color(1, 1, 1, 1)
156
+ line_thickness = 2.5
157
+ else:
158
+ line_channel = 0
159
+ line_color = pack_color(tint[0], tint[1], tint[2], tint[3] * 0.5)
160
+ dot_color = pack_color(tint[0], tint[1], tint[2], tint[3])
161
+ line_thickness = 1.0
162
+
163
+ draw_list.add_bezier_cubic(
164
+ start_x, start_y,
165
+ cp1_x, cp1_y,
166
+ cp2_x, cp2_y,
167
+ end_x, end_y,
168
+ line_color,
169
+ line_thickness,
170
+ 0
171
+ )
172
+
173
+ # Draw the dot
174
+ draw_list.add_circle_filled(
175
+ start_x, start_y,
176
+ 3.0,
177
+ dot_color,
178
+ 12
179
+ )
180
+
181
+ # Draw background rectangle
182
+ draw_list.add_rect_filled(
183
+ text_x - padding,
184
+ text_y - padding,
185
+ text_x + text_width + padding,
186
+ text_y + label_height - padding,
187
+ pack_color(0.1, 0.1, 0.1, 1.0)
188
+ )
189
+
190
+ # Draw outline in tint color (or yellow if hovered)
191
+ if is_hovered:
192
+ outline_color = pack_color(1, 1, 1, 1)
193
+ outline_thickness = 2.0
194
+ else:
195
+ outline_color = pack_color(tint[0], tint[1], tint[2], tint[3])
196
+ outline_thickness = 1.0
197
+
198
+ draw_list.add_rect(
199
+ text_x - padding,
200
+ text_y - padding,
201
+ text_x + text_width + padding,
202
+ text_y + label_height - padding,
203
+ outline_color,
204
+ 0.0,
205
+ 0,
206
+ outline_thickness
207
+ )
208
+
209
+ # Draw text lines
210
+ text_color = pack_color(tint[0], tint[1], tint[2], tint[3])
211
+ line_y = text_y
212
+ for line in text_lines:
213
+ draw_list.add_text(
214
+ text_x,
215
+ line_y,
216
+ text_color,
217
+ line
218
+ )
219
+ line_y += text_line_height
220
+
221
+
222
+ def draw_vertical_scrollbar(content_height: float,
223
+ view_height: float,
224
+ view_width: float,
225
+ scroll_offset: float,
226
+ scrollbar_width: float,
227
+ left: float = 0.0,
228
+ top: float = 0.0,
229
+ *,
230
+ pad: float = 1.0,
231
+ rounding: float = 3.0,
232
+ tint=None,
233
+ bar_top_margin: float = 15.0,
234
+ min_grab_size: float | None = None):
235
+ # Style & colors
236
+ style = imgui.get_style()
237
+
238
+ if min_grab_size is None:
239
+ min_grab_size = float(style.grab_min_size)
240
+
241
+ if tint is not None:
242
+ col_grab = pack_color(*tint[:3], 1.0)
243
+ else:
244
+ col_grab = imgui.get_color_u32(imgui.COLOR_SCROLLBAR_GRAB)
245
+ col_border = imgui.get_color_u32(imgui.COLOR_BORDER)
246
+
247
+ # Early clamps & deriveds
248
+ view_height = max(0.0, float(view_height))
249
+ view_width = max(0.0, float(view_width))
250
+ content_height = max(0.0, float(content_height))
251
+ scrollbar_width = max(0.0, float(scrollbar_width))
252
+
253
+ max_scroll = max(0.0, content_height - view_height)
254
+ scroll_offset = float(max(0.0, min(scroll_offset, max_scroll)))
255
+
256
+ # Anchor the container at the current cursor position in screen space
257
+ origin_x, origin_y = (left, top)
258
+
259
+ bar_margin = 4.0
260
+ bar_margin_x = 1.0
261
+
262
+ # Compute geometry (stick it to the right side of the container)
263
+ track_w = min(scrollbar_width, view_width)
264
+ track_h = view_height - bar_top_margin
265
+ track_x1 = origin_x + (view_width - track_w) - bar_margin_x
266
+ track_y1 = origin_y + bar_margin
267
+ track_x2 = track_x1 + track_w - bar_margin_x
268
+ track_y2 = track_y1 + track_h - bar_margin * 2
269
+
270
+ # Compute grab size & position
271
+ if content_height <= 0.0 or track_h <= 0.0:
272
+ grab_h = 0.0
273
+ t = 0.0
274
+ else:
275
+ # Proportional size with a minimum; cap to track height.
276
+ ratio = view_height / content_height if content_height > 0.0 else 1.0
277
+ grab_h = max(min_grab_size, ratio * track_h)
278
+ grab_h = min(grab_h, track_h)
279
+
280
+ # Normalized scroll position -> grab position
281
+ travel = max(0.0, track_h - grab_h)
282
+ t = 0.0 if max_scroll == 0.0 else (scroll_offset / max_scroll)
283
+ t = max(0.0, min(1.0, t)) # clamp just in case
284
+
285
+ grab_y1 = track_y1 + (max(0.0, track_h - grab_h) * t)
286
+ grab_y2 = grab_y1 + grab_h
287
+
288
+ # Inner padding for nicer visuals
289
+ inner_x1 = track_x1 + pad
290
+ inner_x2 = track_x2 - pad
291
+ inner_y1 = track_y1 + pad
292
+ inner_y2 = track_y2 - pad
293
+ grab_x1 = inner_x1
294
+ grab_x2 = inner_x2
295
+ grab_y1 = max(inner_y1, min(grab_y1, inner_y2 - (grab_y2 - grab_y1))) + bar_top_margin
296
+ grab_y2 = grab_y1 + max(0.0, min(grab_h, inner_y2 - inner_y1))
297
+
298
+ # Draw
299
+ dl = imgui.get_window_draw_list()
300
+ # Track
301
+
302
+ # Melty.engine.mask_mark_rect(Melty.depth, track_x1, track_y1, track_w, track_h,
303
+ # key=str(Melty.unique_stack[-1]) + "scrollbar")
304
+
305
+ dl.add_rect(track_x1, track_y1, track_x2, track_y2, col_border, rounding)
306
+ # Grab
307
+ if grab_y2 > grab_y1 and grab_x2 > grab_x1:
308
+ dl.add_rect_filled(grab_x1, grab_y1, grab_x2, grab_y2, col_grab, rounding)
309
+ dl.add_rect(grab_x1, grab_y1, grab_x2, grab_y2, col_border, rounding)
310
+
311
+ return None
312
+
313
+
314
+ def clear_floating_text_cache():
315
+ """Call this at the start of each frame to reset label positioning"""
316
+
317
+ # Copy current frame's max heights to previous frame for next frame's use
318
+ _floating_text_prev_frame_heights = {
319
+ key: data['max_height']
320
+ for key, data in _floating_text_cache.items()
321
+ if 'max_height' in data
322
+ }
323
+
324
+ # Clear current cache for new frame
325
+ _floating_text_cache.clear()
326
+
327
+
328
+