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,480 @@
|
|
|
1
|
+
"""Texture view functions and supporting definitions."""
|
|
2
|
+
from meltygui.core.graphics.gl_state import GLState
|
|
3
|
+
from meltygui.core.graphics.shader_func import shader_func
|
|
4
|
+
from meltygui.graphics.texture_manager import PendingTexture
|
|
5
|
+
from meltygui.hdr_color import pack_color
|
|
6
|
+
from meltygui.core.core_render import render_func
|
|
7
|
+
from meltygui.core.rendering.core_decoration import Core
|
|
8
|
+
from meltygui.state.new_core_model import ZoomState
|
|
9
|
+
from meltygui.view.header_view import draw_header
|
|
10
|
+
from meltygui_imgui.core import _DrawList
|
|
11
|
+
import OpenGL.GL as gl
|
|
12
|
+
import math
|
|
13
|
+
import meltygui_imgui as imgui
|
|
14
|
+
import numpy
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@render_func(is_default_for=PendingTexture, use_cache=True, wrap=True, z_offset=0, selectable=False,
|
|
18
|
+
show_bg=False, auto_resize=True, with_header=draw_header)
|
|
19
|
+
def draw_pending_texture(input_value: PendingTexture, draw_state, **kwargs):
|
|
20
|
+
from meltygui.view.texture_view import draw_texture
|
|
21
|
+
|
|
22
|
+
if input_value.texture_id is None:
|
|
23
|
+
imgui.text(f"Uploading... {id(input_value)}")
|
|
24
|
+
return False, input_value
|
|
25
|
+
|
|
26
|
+
# Sized by the caller (an editor pane passes width+height): fill the box
|
|
27
|
+
# - draw_texture fits the image inside it with zoom/pan. Otherwise (a
|
|
28
|
+
# folder-tree leaf) a 300px thumbnail at the image's resolution.
|
|
29
|
+
fill_w, fill_h = kwargs.get("width"), kwargs.get("height")
|
|
30
|
+
if fill_w and fill_h:
|
|
31
|
+
size_kwargs = {"width": max(35, fill_w - 4), "height": max(35, fill_h - 4)}
|
|
32
|
+
else:
|
|
33
|
+
max_size = 300
|
|
34
|
+
if input_value.tex_width > input_value.tex_height:
|
|
35
|
+
width = max_size
|
|
36
|
+
height = int(max_size * input_value.tex_height / input_value.tex_width)
|
|
37
|
+
else:
|
|
38
|
+
height = max_size
|
|
39
|
+
width = int(max_size * input_value.tex_width / input_value.tex_height)
|
|
40
|
+
size_kwargs = {"initial": {"width": width, "height": height}}
|
|
41
|
+
|
|
42
|
+
return_val = draw_texture(input_value.texture_id, **size_kwargs,
|
|
43
|
+
name=f"{draw_state.id}_inner", auto_resize=False,
|
|
44
|
+
show_header=False, use_cache=True, wrap=False, tint=(0.11, 0.29, 0.52))
|
|
45
|
+
|
|
46
|
+
return return_val
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@render_func(is_default_for=numpy.uint32, show_bg=False, use_cache=False, show_add_delete=False, z_offset=0,
|
|
50
|
+
fill_height=True, selectable=False,
|
|
51
|
+
indent_size=0, min_width=35, min_height=35, wrap=False, disable_scroll=True,
|
|
52
|
+
zoom_speed=0.3, with_header=draw_header, manual_content_height=True)
|
|
53
|
+
def draw_texture(input_value: numpy.uint32, hovered, scroll_y_changed, middle_mouse_drag, double_right_mouse_drag,
|
|
54
|
+
zoom_state: ZoomState, zoom_speed, header_height=0, min_zoom=0.1,
|
|
55
|
+
max_zoom=50.0, style_manager=None, max_brightness=5.0, max_contrast=5.0,
|
|
56
|
+
draw_state=None, jet=False, nearest=False, dim_outside=None, dim_alpha=0.55, show_info=True, flip_y=False, **kwargs):
|
|
57
|
+
import meltygui.core.windowing.window_api as glfw
|
|
58
|
+
|
|
59
|
+
original_id = input_value
|
|
60
|
+
texture_id = input_value
|
|
61
|
+
imgui.dummy(draw_state.width, draw_state.height - 20)
|
|
62
|
+
|
|
63
|
+
# Ensure we have valid state if this is the first run
|
|
64
|
+
if not hasattr(zoom_state, 'zoom'):
|
|
65
|
+
zoom_state.zoom = 1.0
|
|
66
|
+
zoom_state.center_u = 0.5
|
|
67
|
+
zoom_state.center_v = 0.5
|
|
68
|
+
|
|
69
|
+
# Check if opengl texture ID is valid
|
|
70
|
+
if not gl.glIsTexture(texture_id):
|
|
71
|
+
imgui.text(f"Error: {texture_id} is not a valid texture")
|
|
72
|
+
return False, input_value
|
|
73
|
+
|
|
74
|
+
# 1. Query Texture Properties
|
|
75
|
+
original_texture = gl.glGetIntegerv(gl.GL_TEXTURE_BINDING_2D)
|
|
76
|
+
gl.glBindTexture(gl.GL_TEXTURE_2D, texture_id)
|
|
77
|
+
|
|
78
|
+
width = gl.glGetTexLevelParameteriv(gl.GL_TEXTURE_2D, 0, gl.GL_TEXTURE_WIDTH)
|
|
79
|
+
height = gl.glGetTexLevelParameteriv(gl.GL_TEXTURE_2D, 0, gl.GL_TEXTURE_HEIGHT)
|
|
80
|
+
gl.glBindTexture(gl.GL_TEXTURE_2D, 0)
|
|
81
|
+
|
|
82
|
+
if width > 16384 or height > 16384:
|
|
83
|
+
imgui.text(f"Error: Texture size {width}x{height} exceeds maximum supported size.")
|
|
84
|
+
return False, input_value
|
|
85
|
+
|
|
86
|
+
if width == 0 or height == 0:
|
|
87
|
+
return False, input_value
|
|
88
|
+
|
|
89
|
+
# 2. Canvas Setup (Fill all space)
|
|
90
|
+
view_width = max(1, draw_state.width)
|
|
91
|
+
view_height = max(1, draw_state.height)
|
|
92
|
+
|
|
93
|
+
# 3. Calculate Aspect Ratio Corrections
|
|
94
|
+
tex_aspect = width / height
|
|
95
|
+
view_aspect = view_width / view_height
|
|
96
|
+
|
|
97
|
+
# Calculate the visible UV width/height based on zoom and aspect ratio.
|
|
98
|
+
if view_aspect > tex_aspect:
|
|
99
|
+
# View is wider: Fit to Height
|
|
100
|
+
uv_height_size = 1.0 / zoom_state.zoom
|
|
101
|
+
uv_width_size = uv_height_size * (view_aspect / tex_aspect)
|
|
102
|
+
else:
|
|
103
|
+
# View is taller: Fit to Width
|
|
104
|
+
uv_width_size = 1.0 / zoom_state.zoom
|
|
105
|
+
uv_height_size = uv_width_size * (tex_aspect / view_aspect)
|
|
106
|
+
|
|
107
|
+
mixed_color = (1, 1, 1, 1)
|
|
108
|
+
highlight_color = (1, 1, 1, 1)
|
|
109
|
+
|
|
110
|
+
if style_manager is not None:
|
|
111
|
+
mixed_color = style_manager.make_color_rgb(*mixed_color[:3],
|
|
112
|
+
value=0.3,
|
|
113
|
+
factor=0.9,
|
|
114
|
+
saturation_scale=1.0,
|
|
115
|
+
alpha=1.0)
|
|
116
|
+
highlight_color = style_manager.make_color_rgb(*mixed_color[:3],
|
|
117
|
+
value=1.0,
|
|
118
|
+
factor=0.9,
|
|
119
|
+
saturation_scale=1.0,
|
|
120
|
+
alpha=1.0)
|
|
121
|
+
io = imgui.get_io()
|
|
122
|
+
overlay: _DrawList = imgui.get_overlay_draw_list()
|
|
123
|
+
|
|
124
|
+
if double_right_mouse_drag:
|
|
125
|
+
b_str = f"{zoom_state.brightness:.3f}"
|
|
126
|
+
overlay.add_text(double_right_mouse_drag.x, double_right_mouse_drag.y - 30,
|
|
127
|
+
col=pack_color(*highlight_color[:3], 1),
|
|
128
|
+
text=f"brightness:{zoom_state.brightness:.3}\ncontrast:{zoom_state.contrast:.3}")
|
|
129
|
+
|
|
130
|
+
if io.key_shift:
|
|
131
|
+
if io.key_ctrl:
|
|
132
|
+
zoom_state.hue += double_right_mouse_drag.dx * 0.001
|
|
133
|
+
zoom_state.saturation -= double_right_mouse_drag.dy * 0.001
|
|
134
|
+
else:
|
|
135
|
+
zoom_state.brightness += double_right_mouse_drag.dx * 0.001
|
|
136
|
+
zoom_state.contrast -= double_right_mouse_drag.dy * 0.001
|
|
137
|
+
else:
|
|
138
|
+
if io.key_ctrl:
|
|
139
|
+
zoom_state.hue += double_right_mouse_drag.dx * 0.005
|
|
140
|
+
zoom_state.saturation -= double_right_mouse_drag.dy * 0.005
|
|
141
|
+
else:
|
|
142
|
+
zoom_state.brightness += double_right_mouse_drag.dx * 0.005
|
|
143
|
+
zoom_state.contrast -= double_right_mouse_drag.dy * 0.005
|
|
144
|
+
|
|
145
|
+
# zoom_state.brightness = max(0.0, min(max_brightness, zoom_state.brightness))
|
|
146
|
+
# zoom_state.contrast = max(0.0, min(max_contrast, zoom_state.contrast))
|
|
147
|
+
|
|
148
|
+
if jet:
|
|
149
|
+
texture_id = Core.melty.filter.brightness_contrast(
|
|
150
|
+
input_value,
|
|
151
|
+
brightness=zoom_state.brightness,
|
|
152
|
+
contrast=zoom_state.contrast
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
# texture_id = Core.melty.filter.swirl(
|
|
156
|
+
# input_value,
|
|
157
|
+
# radius=zoom_state.brightness,
|
|
158
|
+
# angle=zoom_state.contrast
|
|
159
|
+
#
|
|
160
|
+
# )
|
|
161
|
+
texture_id = Core.melty.filter.jet(texture_id, offset=zoom_state.hue)
|
|
162
|
+
else:
|
|
163
|
+
texture_id = Core.melty.filter.brightness_contrast(
|
|
164
|
+
input_value,
|
|
165
|
+
brightness=zoom_state.brightness,
|
|
166
|
+
contrast=zoom_state.contrast
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
# texture_id = Core.melty.filter.swirl(
|
|
170
|
+
# input_value,
|
|
171
|
+
# radius=zoom_state.brightness,
|
|
172
|
+
# angle=zoom_state.contrast
|
|
173
|
+
#
|
|
174
|
+
# )
|
|
175
|
+
texture_id = Core.melty.filter.hue_saturation(
|
|
176
|
+
texture_id,
|
|
177
|
+
saturation=(zoom_state.saturation),
|
|
178
|
+
hue_shift=(zoom_state.hue),
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
# texture_id = Core.melty.filter.swirl(
|
|
182
|
+
# input_value,
|
|
183
|
+
# radius=1.0,
|
|
184
|
+
# angle=(zoom_state.brightness * 5),
|
|
185
|
+
# )
|
|
186
|
+
# texture_id = Core.melty.filter.swirl(
|
|
187
|
+
# texture_id,
|
|
188
|
+
# angle=zoom_state.brightness,
|
|
189
|
+
# radius=zoom_state.contrast
|
|
190
|
+
# )
|
|
191
|
+
|
|
192
|
+
# `dim_outside=(x0, y0, x1, y1)` (texels, row 0 = top): the image is drawn
|
|
193
|
+
# darkened by `dim_alpha` (the `multiply` filter) and the rectangle is
|
|
194
|
+
# drawn over it from the undimmed texture, then outlined -- the
|
|
195
|
+
# hdr-viewer's crop selection. Translucent fills on the image never
|
|
196
|
+
# showed here (09-14); the image path does.
|
|
197
|
+
bright_texture_id = texture_id
|
|
198
|
+
if dim_outside is not None:
|
|
199
|
+
texture_id = Core.melty.filter.multiply(texture_id, factor=1.0 - dim_alpha)
|
|
200
|
+
|
|
201
|
+
# Pixel mode: `nearest=True` shows the texels as hard squares when zoomed
|
|
202
|
+
# in (see hdr-viewer: "Pixel Mode Nearest" menu item), else bilinear.
|
|
203
|
+
# Stamped every frame on the filter chain's OUTPUT texture - that is what
|
|
204
|
+
# gets drawn, and the filter may hand back a different or reused texture
|
|
205
|
+
# from one frame to the next.
|
|
206
|
+
filter_mode = gl.GL_NEAREST if nearest else gl.GL_LINEAR
|
|
207
|
+
gl.glBindTexture(gl.GL_TEXTURE_2D, texture_id)
|
|
208
|
+
gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, filter_mode)
|
|
209
|
+
gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, filter_mode)
|
|
210
|
+
gl.glBindTexture(gl.GL_TEXTURE_2D, 0)
|
|
211
|
+
|
|
212
|
+
p_min = (draw_state.abs_left + 2, draw_state.abs_top + 2)
|
|
213
|
+
p_max = (draw_state.abs_left + draw_state.width, draw_state.abs_top + draw_state.height - 2)
|
|
214
|
+
p_min_x, p_min_y = p_min[0], p_min[1]
|
|
215
|
+
|
|
216
|
+
scroll_delta = 0
|
|
217
|
+
if scroll_y_changed is not None:
|
|
218
|
+
scroll_delta = scroll_y_changed.value
|
|
219
|
+
|
|
220
|
+
# --- Logic: Zoom and Pan ---
|
|
221
|
+
|
|
222
|
+
zoom_delta = 0.0
|
|
223
|
+
|
|
224
|
+
# 4a. Handle Zoom Triggers (Scroll & Keyboard)
|
|
225
|
+
|
|
226
|
+
# Keyboard Shortcuts (1, 2, 3, 4)
|
|
227
|
+
forced_zoom = -1.0
|
|
228
|
+
key_1 = 49
|
|
229
|
+
numpad_key_1 = 321
|
|
230
|
+
# Not while a text field has the keyboard (a meltygui draw_text editor or an
|
|
231
|
+
# imgui input): typing a path with a "4" in it over the image zoomed the
|
|
232
|
+
# hdr-viewer to 12.5 % (09-14).
|
|
233
|
+
typing = Core.melty.text_focused_ds is not None or io.want_text_input
|
|
234
|
+
if hovered and not typing:
|
|
235
|
+
if imgui.is_key_pressed(key_1) or imgui.is_key_pressed(numpad_key_1): # Key '1'
|
|
236
|
+
forced_zoom = 1.0
|
|
237
|
+
# Reset Pan to Center
|
|
238
|
+
zoom_state.center_u = 0.5
|
|
239
|
+
zoom_state.center_v = 0.5
|
|
240
|
+
zoom_state.brightness = 0.0
|
|
241
|
+
zoom_state.contrast = 1.0
|
|
242
|
+
zoom_state.hue = 0.0
|
|
243
|
+
zoom_state.saturation = 1.0
|
|
244
|
+
elif imgui.is_key_pressed(50): # Key '2'
|
|
245
|
+
forced_zoom = 0.5
|
|
246
|
+
zoom_state.brightness = 0.0
|
|
247
|
+
zoom_state.contrast = 1.0
|
|
248
|
+
zoom_state.hue = 0.0
|
|
249
|
+
zoom_state.saturation = 1.0
|
|
250
|
+
elif imgui.is_key_pressed(51): # Key '3'
|
|
251
|
+
forced_zoom = 0.25
|
|
252
|
+
zoom_state.brightness = 0.0
|
|
253
|
+
zoom_state.contrast = 1.0
|
|
254
|
+
zoom_state.hue = 0.0
|
|
255
|
+
zoom_state.saturation = 1.0
|
|
256
|
+
elif imgui.is_key_pressed(52): # Key '4'
|
|
257
|
+
forced_zoom = 0.125
|
|
258
|
+
zoom_state.brightness = 0.0
|
|
259
|
+
zoom_state.contrast = 1.0
|
|
260
|
+
zoom_state.hue = 0.0
|
|
261
|
+
zoom_state.saturation = 1.0
|
|
262
|
+
|
|
263
|
+
# Double-click toggles between the image centred at native size (one
|
|
264
|
+
# texel per pixel, which "100 %" scrolling rarely lands on exactly) and
|
|
265
|
+
# fit. Zoom 1.0 is fit, and native is the texture's size over the view's
|
|
266
|
+
# along the fitted axis; "at native" allows a hair of float slop.
|
|
267
|
+
# The toggle fires on the RELEASE of a double click that did not drag:
|
|
268
|
+
# a double-click-and-drag is the hdr-viewer's crop gesture (09-14), and
|
|
269
|
+
# toggling on the press would jump the view under the drag.
|
|
270
|
+
if hovered and imgui.is_mouse_double_clicked(0):
|
|
271
|
+
zoom_state.double_click_armed = True
|
|
272
|
+
double_click = False
|
|
273
|
+
if getattr(zoom_state, 'double_click_armed', False):
|
|
274
|
+
if imgui.is_mouse_dragging(0, 4.0):
|
|
275
|
+
zoom_state.double_click_armed = False
|
|
276
|
+
elif imgui.is_mouse_released(0):
|
|
277
|
+
zoom_state.double_click_armed = False
|
|
278
|
+
double_click = True
|
|
279
|
+
if double_click:
|
|
280
|
+
if view_aspect > tex_aspect:
|
|
281
|
+
native_zoom = height / max(1.0, view_height)
|
|
282
|
+
else:
|
|
283
|
+
native_zoom = width / max(1.0, view_width)
|
|
284
|
+
native_zoom = max(min_zoom, min(native_zoom, max_zoom))
|
|
285
|
+
at_native = abs(math.log2(zoom_state.zoom / native_zoom)) < 0.01
|
|
286
|
+
forced_zoom = 1.0 if at_native else native_zoom
|
|
287
|
+
zoom_state.center_u = 0.5
|
|
288
|
+
zoom_state.center_v = 0.5
|
|
289
|
+
|
|
290
|
+
if forced_zoom > 0:
|
|
291
|
+
zoom_state.zoom = forced_zoom
|
|
292
|
+
# Recalculate uv sizes immediately for consistent bounding this frame
|
|
293
|
+
if view_aspect > tex_aspect:
|
|
294
|
+
uv_height_size = 1.0 / zoom_state.zoom
|
|
295
|
+
uv_width_size = uv_height_size * (view_aspect / tex_aspect)
|
|
296
|
+
else:
|
|
297
|
+
uv_width_size = 1.0 / zoom_state.zoom
|
|
298
|
+
uv_height_size = uv_width_size * (tex_aspect / view_aspect)
|
|
299
|
+
|
|
300
|
+
# Scroll Logic: zoom_delta is in STOPS (log2): a notch multiplies the
|
|
301
|
+
# zoom by 2^(zoom_speed/2) (~11 % at the default 0.3), shift is 0.3x
|
|
302
|
+
# that. Exponential steps are symmetric, so zooming up and down cancel
|
|
303
|
+
# exactly instead of drifting (the old 1 + delta style gained ~9 % per
|
|
304
|
+
# round trip and the view could never find its way home to fit).
|
|
305
|
+
zoom_step = zoom_speed * 0.5
|
|
306
|
+
if scroll_delta != 0:
|
|
307
|
+
if io.key_shift:
|
|
308
|
+
zoom_delta = scroll_delta * zoom_step * 0.3
|
|
309
|
+
else:
|
|
310
|
+
zoom_delta = scroll_delta * zoom_step
|
|
311
|
+
elif middle_mouse_drag and middle_mouse_drag.modifiers == glfw.MOD_CONTROL:
|
|
312
|
+
zoom_delta = io.mouse_delta.y * -0.008
|
|
313
|
+
|
|
314
|
+
# 4b. Handle Pan (Middle Click Drag)
|
|
315
|
+
if middle_mouse_drag and middle_mouse_drag.modifiers != glfw.MOD_CONTROL:
|
|
316
|
+
u_scale = uv_width_size / view_width
|
|
317
|
+
v_scale = uv_height_size / view_height
|
|
318
|
+
if middle_mouse_drag.modifiers == glfw.MOD_SHIFT:
|
|
319
|
+
zoom_state.center_u -= middle_mouse_drag.dx * u_scale * 0.5
|
|
320
|
+
zoom_state.center_v += middle_mouse_drag.dy * v_scale * 0.5
|
|
321
|
+
else:
|
|
322
|
+
zoom_state.center_u -= middle_mouse_drag.dx * u_scale
|
|
323
|
+
zoom_state.center_v += middle_mouse_drag.dy * v_scale
|
|
324
|
+
|
|
325
|
+
# 4c. Apply Zoom Logic (Zoom to Cursor)
|
|
326
|
+
if zoom_delta != 0.0:
|
|
327
|
+
new_zoom = max(min_zoom, min(zoom_state.zoom * (2.0 ** zoom_delta), max_zoom))
|
|
328
|
+
|
|
329
|
+
if new_zoom != zoom_state.zoom:
|
|
330
|
+
mouse_pos = imgui.get_mouse_pos()
|
|
331
|
+
|
|
332
|
+
if io.key_ctrl:
|
|
333
|
+
mouse_u_ratio, mouse_v_ratio = (0.5, 0.5)
|
|
334
|
+
else:
|
|
335
|
+
mouse_u_ratio = (mouse_pos[0] - p_min_x) / view_width
|
|
336
|
+
mouse_v_ratio = (mouse_pos[1] - p_min_y) / view_height
|
|
337
|
+
|
|
338
|
+
curr_uv_w = uv_width_size
|
|
339
|
+
curr_uv_h = uv_height_size
|
|
340
|
+
|
|
341
|
+
# Recalculate new UV dimensions
|
|
342
|
+
if view_aspect > tex_aspect:
|
|
343
|
+
new_uv_h = 1.0 / new_zoom
|
|
344
|
+
new_uv_w = new_uv_h * (view_aspect / tex_aspect)
|
|
345
|
+
else:
|
|
346
|
+
new_uv_w = 1.0 / new_zoom
|
|
347
|
+
new_uv_h = new_uv_w * (tex_aspect / view_aspect)
|
|
348
|
+
|
|
349
|
+
diff_w = curr_uv_w - new_uv_w
|
|
350
|
+
diff_h = curr_uv_h - new_uv_h
|
|
351
|
+
|
|
352
|
+
# Every step anchors on the mouse, zooming out included: the
|
|
353
|
+
# image is not pulled back to centre on the way to fit (that
|
|
354
|
+
# homing was removed 09-14; the bounding step below still keeps
|
|
355
|
+
# it on screen).
|
|
356
|
+
zoom_state.center_u += diff_w * (mouse_u_ratio - 0.5)
|
|
357
|
+
zoom_state.center_v += diff_h * (0.5 - mouse_v_ratio)
|
|
358
|
+
|
|
359
|
+
zoom_state.zoom = new_zoom
|
|
360
|
+
|
|
361
|
+
# Update these for Step 5
|
|
362
|
+
uv_width_size = new_uv_w
|
|
363
|
+
uv_height_size = new_uv_h
|
|
364
|
+
|
|
365
|
+
# 5. Calculate Final UVs and Clamp to Bounds
|
|
366
|
+
half_uv_w = uv_width_size * 0.5
|
|
367
|
+
half_uv_h = uv_height_size * 0.5
|
|
368
|
+
|
|
369
|
+
# --- Bounding Logic Start ---
|
|
370
|
+
margin_px = 20.0
|
|
371
|
+
|
|
372
|
+
pixel_u = uv_width_size / view_width
|
|
373
|
+
pixel_v = uv_height_size / view_height
|
|
374
|
+
margin_u = margin_px * pixel_u
|
|
375
|
+
margin_v = margin_px * pixel_v
|
|
376
|
+
|
|
377
|
+
min_u = -half_uv_w + margin_u
|
|
378
|
+
max_u = 1.0 + half_uv_w - margin_u
|
|
379
|
+
|
|
380
|
+
if min_u > max_u:
|
|
381
|
+
zoom_state.center_u = 0.5
|
|
382
|
+
else:
|
|
383
|
+
zoom_state.center_u = max(min_u, min(zoom_state.center_u, max_u))
|
|
384
|
+
|
|
385
|
+
min_v = -half_uv_h + margin_v
|
|
386
|
+
max_v = 1.0 + half_uv_h - margin_v
|
|
387
|
+
|
|
388
|
+
if min_v > max_v:
|
|
389
|
+
zoom_state.center_v = 0.5
|
|
390
|
+
else:
|
|
391
|
+
zoom_state.center_v = max(min_v, min(zoom_state.center_v, max_v))
|
|
392
|
+
# --- Bounding Logic End ---
|
|
393
|
+
|
|
394
|
+
uv_x_min = zoom_state.center_u - half_uv_w
|
|
395
|
+
uv_x_max = zoom_state.center_u + half_uv_w
|
|
396
|
+
uv_y_min = zoom_state.center_v - half_uv_h
|
|
397
|
+
uv_y_max = zoom_state.center_v + half_uv_h
|
|
398
|
+
|
|
399
|
+
# Top-down uploads (for example chat images) keep the same pan/zoom
|
|
400
|
+
# geometry and reverse only the texture sampling coordinates.
|
|
401
|
+
uv_a = (uv_x_min, 1.0 - uv_y_max if flip_y else uv_y_max)
|
|
402
|
+
uv_b = (uv_x_max, 1.0 - uv_y_min if flip_y else uv_y_min)
|
|
403
|
+
|
|
404
|
+
# 6. Clip and Draw
|
|
405
|
+
scale_u_px = view_width / uv_width_size
|
|
406
|
+
scale_v_px = view_height / uv_height_size
|
|
407
|
+
|
|
408
|
+
# Project UV Edges
|
|
409
|
+
raw_img_left = p_min_x + (0.0 - uv_x_min) * scale_u_px
|
|
410
|
+
raw_img_right = p_min_x + (1.0 - uv_x_min) * scale_u_px
|
|
411
|
+
raw_img_top = p_min_y + (uv_y_max - 1.0) * scale_v_px
|
|
412
|
+
raw_img_bottom = p_min_y + (uv_y_max - 0.0) * scale_v_px
|
|
413
|
+
|
|
414
|
+
# Intersect with Viewport
|
|
415
|
+
clip_left = max(p_min_x, raw_img_left)
|
|
416
|
+
clip_right = min(p_max[0], raw_img_right)
|
|
417
|
+
clip_top = max(p_min_y, raw_img_top)
|
|
418
|
+
clip_bottom = min(p_max[1], raw_img_bottom)
|
|
419
|
+
draw_list: _DrawList = imgui.get_window_draw_list()
|
|
420
|
+
|
|
421
|
+
if imgui.is_mouse_hovering_rect(clip_left, clip_top, clip_right, clip_bottom):
|
|
422
|
+
draw_state.hover_reported = True
|
|
423
|
+
else:
|
|
424
|
+
draw_state.hover_reported = False
|
|
425
|
+
|
|
426
|
+
Core.melty.push_clip((clip_left, clip_top, clip_right - 3, clip_bottom))
|
|
427
|
+
draw_list.add_image_rounded(texture_id,
|
|
428
|
+
a=p_min,
|
|
429
|
+
b=p_max,
|
|
430
|
+
uv_a=uv_a,
|
|
431
|
+
uv_b=uv_b,
|
|
432
|
+
rounding=5.0)
|
|
433
|
+
draw_list.add_rect(raw_img_left, raw_img_top, raw_img_right + 1, raw_img_bottom + 1,
|
|
434
|
+
pack_color(*mixed_color[:3], 1.0),
|
|
435
|
+
0.0, 0, 1.0)
|
|
436
|
+
if dim_outside is not None:
|
|
437
|
+
x0, y0, x1, y1 = dim_outside
|
|
438
|
+
sx = (raw_img_right - raw_img_left) / max(1, width)
|
|
439
|
+
sy = (raw_img_bottom - raw_img_top) / max(1, height)
|
|
440
|
+
sl, st = raw_img_left + x0 * sx, raw_img_top + y0 * sy
|
|
441
|
+
sr, sb = raw_img_left + x1 * sx, raw_img_top + y1 * sy
|
|
442
|
+
sl, st = max(sl, clip_left), max(st, clip_top)
|
|
443
|
+
sr, sb = min(sr, clip_right - 3), min(sb, clip_bottom)
|
|
444
|
+
if sr > sl and sb > st:
|
|
445
|
+
def uv(x, y):
|
|
446
|
+
v = uv_y_max - (y - p_min_y) / scale_v_px
|
|
447
|
+
return uv_x_min + (x - p_min_x) / scale_u_px, 1.0 - v if flip_y else v
|
|
448
|
+
gl.glBindTexture(gl.GL_TEXTURE_2D, bright_texture_id)
|
|
449
|
+
gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, filter_mode)
|
|
450
|
+
gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, filter_mode)
|
|
451
|
+
gl.glBindTexture(gl.GL_TEXTURE_2D, 0)
|
|
452
|
+
draw_list.add_image(bright_texture_id, (sl, st), (sr, sb), uv(sl, st), uv(sr, sb))
|
|
453
|
+
draw_list.add_rect(sl, st, sr, sb, pack_color(1.0, 1.0, 1.0, 0.9), 0.0, 0, 1.0)
|
|
454
|
+
Core.melty.pop_clip()
|
|
455
|
+
|
|
456
|
+
if show_info:
|
|
457
|
+
line_height = imgui.get_text_line_height()
|
|
458
|
+
draw_list.add_text(max(p_min_x + 5, raw_img_left), clip_top - line_height - 5,
|
|
459
|
+
pack_color(*mixed_color[:3], 1.0),
|
|
460
|
+
text=f"{original_id} - {texture_id} - {width}x{height} - Zoom: {zoom_state.zoom:.2f}x")
|
|
461
|
+
|
|
462
|
+
gl.glBindTexture(gl.GL_TEXTURE_2D, original_texture)
|
|
463
|
+
|
|
464
|
+
return False, draw_state
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
IMAGE_BLIT_FRAG = """
|
|
468
|
+
#version 330 core
|
|
469
|
+
out vec4 FragColor;
|
|
470
|
+
uniform sampler2D image;
|
|
471
|
+
void main() { FragColor = texelFetch(image, ivec2(gl_FragCoord.xy), 0); }
|
|
472
|
+
"""
|
|
473
|
+
|
|
474
|
+
|
|
475
|
+
@shader_func(fragment=IMAGE_BLIT_FRAG)
|
|
476
|
+
def image_blit_pass(gl_state: GLState = None, image=None, program=None, **kwargs):
|
|
477
|
+
"""Fullscreen copy of `image` (a 2-D GLTexture the size of the target)
|
|
478
|
+
into the bound FBO — the voxel_pass stand-in for cuda_march frames."""
|
|
479
|
+
gl.glBindVertexArray(gl_state.vao("fs_triangle"))
|
|
480
|
+
gl.glDrawArrays(gl.GL_TRIANGLES, 0, 3)
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""A tile's editor picker and the selected render function's content."""
|
|
2
|
+
from meltygui import imgui
|
|
3
|
+
from meltygui.model.tile_model import Tile
|
|
4
|
+
from meltygui.view.dropdown_view import draw_dropdown
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def draw_tile_content(input_value: Tile, width, height, multi_instance_renderers=(),
|
|
8
|
+
layout_frame=None):
|
|
9
|
+
# Change the picker height here; the editor receives the remaining tile area.
|
|
10
|
+
picker_height = 28.0
|
|
11
|
+
tile = input_value
|
|
12
|
+
choices = {"Empty": None}
|
|
13
|
+
choices.update({renderer.__name__: renderer for renderer in multi_instance_renderers})
|
|
14
|
+
left, top = imgui.get_cursor_screen_pos()
|
|
15
|
+
selected, renderer = draw_dropdown(
|
|
16
|
+
tile.render_func, collection=choices, name="Editor type", key=tile.id,
|
|
17
|
+
show_name=False, width=width, height=picker_height,
|
|
18
|
+
show_header=False,
|
|
19
|
+
display_label="Empty" if tile.render_func is None else tile.render_func.__name__,
|
|
20
|
+
)
|
|
21
|
+
if selected:
|
|
22
|
+
tile.render_func = renderer
|
|
23
|
+
|
|
24
|
+
changed = selected
|
|
25
|
+
if tile.render_func is not None:
|
|
26
|
+
imgui.set_cursor_screen_pos((left, top + picker_height))
|
|
27
|
+
content_changed, value = tile.render_func(
|
|
28
|
+
tile.input_value,
|
|
29
|
+
unique_name=f"{tile.render_func.__module__}.{tile.render_func.__qualname__}",
|
|
30
|
+
width=width,
|
|
31
|
+
height=max(0.0, height - picker_height),
|
|
32
|
+
auto_resize=False, show_header=False,
|
|
33
|
+
key=tile.id, instance=tile.id, layout_frame=layout_frame,
|
|
34
|
+
)
|
|
35
|
+
if content_changed:
|
|
36
|
+
tile.input_value = value
|
|
37
|
+
changed |= content_changed
|
|
38
|
+
return changed, tile
|