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,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
|
+
|